Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## Unreleased

- Added PIT release rules (`alphaforge.pit.release_rules`): `NthBusinessDay`, `NthWeekday`, `CalendarDay`, `FixedLagMonths`, `QuarterlyRelease`, `WeeklyRelease`, and `CustomRule` with a tagged-union registry for YAML round-trips.
- Added vintage resolvers (`alphaforge.pit.resolvers`): `RealtimeResolver`, `LatestResolver`, and `FrozenResolver` implementing the `VintageResolver` protocol for point-in-time backtesting views.
- Added `VintageView` value object (`alphaforge.pit.views`) to declare realtime / latest / frozen vintage strategies without coupling to resolution logic.
- Added PIT panel builder utilities (`alphaforge.pit.panel`): `build_pit_panel` and `long_to_wide` for assembling aligned panels from PIT snapshots.
- Added missingness taxonomy (`alphaforge.pit.missingness`) for classifying NaN cells in nowcasting panels by cause.
- Added vintage selection and lookahead validation utilities (`alphaforge.pit.vintage`): `select_vintage_for_asof` and `validate_no_lookahead`.
- Fixed CI linting errors: removed unused imports and sorted import blocks across new modules and test files.
- Fixed mypy type errors: tightened `_register` signature in `pit/release_rules.py`, added `name: str` to `Parametric` protocol in `pipeline/protocols.py`, and corrected `Mapping[Any, str]` annotation in `data/short_rates.py`.

- Added `alphaforge.evaluation` package with pluggable metric infrastructure:
- `MetricFn` protocol (runtime-checkable) for composable forecast accuracy metrics.
- Built-in implementations: `RMSE`, `MAE`, `DirectionalAccuracy`, `MAPE`, `MeanError`.
Expand Down
16 changes: 8 additions & 8 deletions alphaforge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
from .data.fred_source import FREDDataSource
from .data.panel import PanelFrame
from .data.pit_source import PITDataSource
from .data.short_rates import (
ShortRateDataset,
build_duan_weekly_dataset,
build_kim_orphanides_dataset,
build_macro_finance_dataset,
build_policy_rule_dataset,
)
from .data.public_web import (
ANPFuelPricesDataSource,
B3HistoricalQuotesDataSource,
Expand All @@ -35,6 +28,13 @@
)
from .data.query import Query
from .data.schema import TableSchema
from .data.short_rates import (
ShortRateDataset,
build_duan_weekly_dataset,
build_kim_orphanides_dataset,
build_macro_finance_dataset,
build_policy_rule_dataset,
)
from .data.universe import EntityMetadata, Universe
from .features.frame import Artifact, FeatureFrame
from .features.ops import join_feature_frames, materialize
Expand Down Expand Up @@ -74,7 +74,6 @@
coerce_pipeline_spec,
)
from .pit.ref_entity import make_ref_entity_id, parse_ref_entity_id
from .registry import EntityEntry, EntityRegistry
from .pit.tasks import (
build_snapshot_tape,
first_vintage_snapshot,
Expand All @@ -93,6 +92,7 @@
)
from .pit.transforms import PITTransformResult, PITTransformSpec
from .pit.validation import PITValidationReport, validate_pit_observations
from .registry import EntityEntry, EntityRegistry
from .store.cache import MaterializationPolicy
from .store.duckdb_parquet import DuckDBParquetStore
from .time.align import AlignedPanel, AlignSpec, AvailabilityState, align_panel
Expand Down
4 changes: 2 additions & 2 deletions alphaforge/data/short_rates.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Mapping
from typing import Any, Mapping

import pandas as pd

Expand Down Expand Up @@ -105,7 +105,7 @@ def _fetch_fred_panel(
ctx: DataContext,
*,
source: str,
series_map: Mapping[object, str],
series_map: Mapping[Any, str],
start: pd.Timestamp,
end: pd.Timestamp,
sort_labels: bool = True,
Expand Down
6 changes: 3 additions & 3 deletions alphaforge/evaluation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
from .metrics import (
BENCHMARK_METRICS,
DEFAULT_METRICS,
MAPE,
MAE,
MeanError,
MetricFn,
MAPE,
RMSE,
DirectionalAccuracy,
MeanError,
MetricFn,
)

__all__ = [
Expand Down
1 change: 0 additions & 1 deletion alphaforge/evaluation/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ def __call__(self, y_pred, y_true):

import numpy as np


# ---------------------------------------------------------------------------
# Protocol
# ---------------------------------------------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions alphaforge/pipeline/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class Parametric(Protocol):
Transformers and Signals may implement this. Filters do NOT.
"""

name: str

def get_params(self) -> dict[str, float]: ...
def set_params(self, params: dict[str, float]) -> None: ...

Expand Down
3 changes: 1 addition & 2 deletions alphaforge/pipeline/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pandas as pd

from alphaforge.pit.accessor import PITAccessor, to_utc_aware
from alphaforge.pit.accessor import PITAccessor

from .health import SourceHealthPolicy, SourceHealthStatus, assess_source_health

Expand All @@ -28,7 +28,6 @@ def _prefix(self, source_name: str) -> str:
return source_name.replace("_", ".")

def _latest_obs_date(self, source_name: str) -> pd.Timestamp | None:
prefix = self._prefix(source_name)
try:
result = self.pit.conn.execute(
"SELECT MAX(obs_date) FROM pit_observations WHERE source = ?",
Expand Down
14 changes: 7 additions & 7 deletions alphaforge/pit/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
from .accessor import PITAccessor, ensure_pit_table
from .contract import PIT_CONTRACT_VERSION, PITContractVersion, get_pit_contract_version
from .resolvers import (
FrozenResolver,
LatestResolver,
RealtimeResolver,
VintageResolver,
)
from .views import VintageView
from .exceptions import (
PITCausalityError,
PITContractError,
Expand Down Expand Up @@ -49,6 +42,12 @@
coerce_pipeline_spec,
)
from .ref_entity import make_ref_entity_id, parse_ref_entity_id
from .resolvers import (
FrozenResolver,
LatestResolver,
RealtimeResolver,
VintageResolver,
)
from .tasks import (
build_snapshot_tape,
first_vintage_snapshot,
Expand All @@ -67,6 +66,7 @@
)
from .transforms import PITTransformResult, PITTransformSpec
from .validation import PITValidationReport, validate_pit_observations
from .views import VintageView

__all__ = [
"PITAccessor",
Expand Down
12 changes: 6 additions & 6 deletions alphaforge/pit/release_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@
RULE_REGISTRY: dict[str, type] = {}


def _register(cls: type) -> type:
"""Decorator that adds a ReleaseRule subclass to the registry."""
RULE_REGISTRY[cls.rule_type] = cls
return cls


# ---------------------------------------------------------------------------
# Base
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -85,6 +79,12 @@ def from_dict(d: dict[str, Any]) -> ReleaseRule:
return cls(**kwargs)


def _register(cls: type[ReleaseRule]) -> type[ReleaseRule]:
"""Decorator that adds a ReleaseRule subclass to the registry."""
RULE_REGISTRY[cls.rule_type] = cls
return cls


# ---------------------------------------------------------------------------
# Concrete rule classes
# ---------------------------------------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion alphaforge/pit/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

from alphaforge.pit.views import VintageView


# ---------------------------------------------------------------------------
# Protocol
# ---------------------------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions docs/api/pit-missingness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PIT Missingness

::: alphaforge.pit.missingness
3 changes: 3 additions & 0 deletions docs/api/pit-panel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PIT Panel Builder

::: alphaforge.pit.panel
3 changes: 3 additions & 0 deletions docs/api/pit-release-rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PIT Release Rules

::: alphaforge.pit.release_rules
3 changes: 3 additions & 0 deletions docs/api/pit-resolvers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PIT Vintage Resolvers

::: alphaforge.pit.resolvers
3 changes: 3 additions & 0 deletions docs/api/pit-views.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PIT Vintage Views

::: alphaforge.pit.views
3 changes: 3 additions & 0 deletions docs/api/pit-vintage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# PIT Vintage Utilities

::: alphaforge.pit.vintage
2 changes: 1 addition & 1 deletion examples/short_rate_kim_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from alphaforge import (
DataContext,
DuckDBParquetStore,
FREDDataSource,
FRBTermStructureBenchmarkSource,
FREDDataSource,
PhiladelphiaSPFMeanLevelSource,
TradingCalendar,
build_kim_orphanides_dataset,
Expand Down
6 changes: 6 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ nav:
- Dataset Builder: api/dataset-builder.md
- Dataset Spec: api/dataset-spec.md
- PIT Accessor: api/pit-accessor.md
- PIT Release Rules: api/pit-release-rules.md
- PIT Vintage Views: api/pit-views.md
- PIT Vintage Resolvers: api/pit-resolvers.md
- PIT Panel Builder: api/pit-panel.md
- PIT Missingness: api/pit-missingness.md
- PIT Vintage Utilities: api/pit-vintage.md
- PIT Transforms: api/pit-transforms.md
- PIT Pipelines: api/pit-pipelines.md
- PIT Models: api/pit-models.md
Expand Down
3 changes: 0 additions & 3 deletions tests/test_logging.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
"""Tests for alphaforge.logging module."""
from __future__ import annotations

import json
import logging
import tempfile
from pathlib import Path

import structlog
from structlog.testing import capture_logs

from alphaforge.logging import configure_logging, get_logger
Expand Down
2 changes: 0 additions & 2 deletions tests/test_pipeline_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@
from alphaforge.pipeline.protocols import (
Filter,
Parametric,
Pipeline,
PipelineVariant,
Signal,
SimplePipeline,
Transformer,
)


# --- Stub implementations ---


Expand Down
1 change: 0 additions & 1 deletion tests/test_pit_panel_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from datetime import date

import pandas as pd
import pytest

from alphaforge.pit.vintage import select_vintage_for_asof, validate_no_lookahead

Expand Down
3 changes: 0 additions & 3 deletions tests/test_release_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@

from alphaforge.pit.release_rules import (
RULE_REGISTRY,
CalendarDay,
CustomRule,
FixedLagMonths,
NthBusinessDay,
NthWeekday,
QuarterlyRelease,
ReleaseRule,
WeeklyRelease,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_torch_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
torch = pytest.importorskip("torch")
nn = torch.nn

from alphaforge.pipeline.torch_protocols import (
from alphaforge.pipeline.torch_protocols import ( # noqa: E402
DifferentiableSignalModule,
NumpyDifferentiableWrapper,
TorchParametric,
Expand Down
1 change: 0 additions & 1 deletion tests/test_vintage_resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
)
from alphaforge.pit.views import VintageView


# ---------------------------------------------------------------------------
# VintageView value object
# ---------------------------------------------------------------------------
Expand Down
Loading