From 38997a49fa2e928192a6e98608fb701ccd6d7382 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Sat, 19 Sep 2026 17:08:50 +0800 Subject: [PATCH] fix(crypto): align lifecycle baselines with natural-day metrics Co-Authored-By: Codex --- .github/workflows/drift-check.yml | 6 +++--- pyproject.toml | 2 +- qsl.toml | 2 +- scripts/run_walk_forward_backtest.py | 11 ++++++++++- src/crypto_strategies/backtest/orchestrator_runner.py | 4 ++++ tests/test_drift_workflow_config.py | 6 +++--- tests/test_qsl_compat_metadata.py | 2 +- uv.lock | 4 ++-- 8 files changed, 25 insertions(+), 12 deletions(-) diff --git a/.github/workflows/drift-check.yml b/.github/workflows/drift-check.yml index 2018bf1..c29e908 100644 --- a/.github/workflows/drift-check.yml +++ b/.github/workflows/drift-check.yml @@ -32,7 +32,7 @@ jobs: uses: actions/checkout@v6 with: repository: QuantStrategyLab/QuantPlatformKit - ref: c812ed70f83d61bdf1816fa5ca112b0f6976c6b6 + ref: 04721b1cce003b2f070e707493ff32c6cdb1b82b path: external/QuantPlatformKit - name: Set up Python @@ -207,7 +207,7 @@ jobs: contents: read issues: write id-token: write - uses: QuantStrategyLab/QuantPlatformKit/.github/workflows/reusable-drift-check.yml@c812ed70f83d61bdf1816fa5ca112b0f6976c6b6 + uses: QuantStrategyLab/QuantPlatformKit/.github/workflows/reusable-drift-check.yml@04721b1cce003b2f070e707493ff32c6cdb1b82b with: strategy_domain: crypto caller_event_name: ${{ github.event_name }} @@ -216,7 +216,7 @@ jobs: snapshot_checkout_path: external/CryptoLivePoolPipelines snapshot_repository_ref: ${{ needs.preflight_backtests.outputs.snapshot_repository_ref }} ai_gateway_service_url: ${{ vars.AI_GATEWAY_SERVICE_URL }} - quant_platform_kit_ref: c812ed70f83d61bdf1816fa5ca112b0f6976c6b6 + quant_platform_kit_ref: 04721b1cce003b2f070e707493ff32c6cdb1b82b lifecycle_preflight_artifact: lifecycle-preflight-${{ github.run_id }}-${{ github.run_attempt }} secrets: codex_audit_service_url: ${{ secrets.CODEX_AUDIT_SERVICE_URL }} diff --git a/pyproject.toml b/pyproject.toml index 1a85c55..1804bf9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ description = "Shared crypto strategy catalog and implementations" readme = "README.md" requires-python = ">=3.11" dependencies = [ - "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@c812ed70f83d61bdf1816fa5ca112b0f6976c6b6", + "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@04721b1cce003b2f070e707493ff32c6cdb1b82b", ] [project.optional-dependencies] diff --git a/qsl.toml b/qsl.toml index d7d8442..5a4483e 100644 --- a/qsl.toml +++ b/qsl.toml @@ -4,5 +4,5 @@ upgrade_ring = "ring_b" [compat] bundle = "2026.09.1" requires = [ - "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@c812ed70f83d61bdf1816fa5ca112b0f6976c6b6", + "quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@04721b1cce003b2f070e707493ff32c6cdb1b82b", ] diff --git a/scripts/run_walk_forward_backtest.py b/scripts/run_walk_forward_backtest.py index ff69b60..ed8eddf 100644 --- a/scripts/run_walk_forward_backtest.py +++ b/scripts/run_walk_forward_backtest.py @@ -31,6 +31,8 @@ ) DEFAULT_STORE_ROOT = Path("/tmp/crypto_wf_store") DRIFT_BASELINE_HORIZON_DAYS = 126 +CRYPTO_PERIODS_PER_YEAR = 365.25 +CRYPTO_CALENDAR_ID = "CRYPTO_NATURAL_DAY" PROFILE_DEFAULTS: dict[str, dict[str, Any]] = { PROFILE_NAME: {"min_history_days": DEFAULT_MIN_HISTORY_DAYS, "top_n": 2, "rebalance_every": 7}, @@ -191,7 +193,12 @@ def _write_return_matrix( def _baseline_from_return_tail(full_result: Any, returns: pd.Series) -> Any: tail = returns.tail(DRIFT_BASELINE_HORIZON_DAYS) - metrics = compute_window_metrics(tail, window_days=DRIFT_BASELINE_HORIZON_DAYS) + metrics = compute_window_metrics( + tail, + window_days=DRIFT_BASELINE_HORIZON_DAYS, + periods_per_year=CRYPTO_PERIODS_PER_YEAR, + calendar_id=CRYPTO_CALENDAR_ID, + ) max_drawdown = float(metrics.max_drawdown) cagr = float(metrics.cagr) return replace( @@ -206,6 +213,8 @@ def _baseline_from_return_tail(full_result: Any, returns: pd.Series) -> Any: start_date=metrics.start_date, end_date=metrics.end_date, observation_count=metrics.observation_count, + periods_per_year=metrics.periods_per_year, + calendar_id=metrics.calendar_id, ) diff --git a/src/crypto_strategies/backtest/orchestrator_runner.py b/src/crypto_strategies/backtest/orchestrator_runner.py index dffe697..4db08c3 100644 --- a/src/crypto_strategies/backtest/orchestrator_runner.py +++ b/src/crypto_strategies/backtest/orchestrator_runner.py @@ -24,6 +24,8 @@ COMBO_DEFAULT_MIN_HISTORY_DAYS = 260 SUPPORTED_PROFILES = frozenset({PROFILE_NAME, CRYPTO_EQUITY_COMBO_PROFILE}) SYNTHETIC_PANEL_GENERATOR_VERSION = "crypto_live_pool_panel.v2" +CRYPTO_PERIODS_PER_YEAR = 365.25 +CRYPTO_CALENDAR_ID = "CRYPTO_NATURAL_DAY" def _synthetic_digest_int(*parts: str) -> int: @@ -144,6 +146,8 @@ def _metrics_to_result( source_script="crypto_strategies.backtest.orchestrator_runner", computed_at=datetime.now(timezone.utc).isoformat(), run_duration_seconds=run_duration_seconds, + periods_per_year=CRYPTO_PERIODS_PER_YEAR, + calendar_id=CRYPTO_CALENDAR_ID, ) diff --git a/tests/test_drift_workflow_config.py b/tests/test_drift_workflow_config.py index 31ccad7..24057e4 100644 --- a/tests/test_drift_workflow_config.py +++ b/tests/test_drift_workflow_config.py @@ -25,10 +25,10 @@ def test_drift_workflow_wires_real_pipeline_inputs_and_preflight_bundle() -> Non assert "repository: QuantStrategyLab/QuantPlatformKit" in workflow assert ( "repository: QuantStrategyLab/QuantPlatformKit\n" - " ref: c812ed70f83d61bdf1816fa5ca112b0f6976c6b6\n" + " ref: 04721b1cce003b2f070e707493ff32c6cdb1b82b\n" " path: external/QuantPlatformKit" ) in workflow - assert "quant_platform_kit_ref: c812ed70f83d61bdf1816fa5ca112b0f6976c6b6" in workflow + assert "quant_platform_kit_ref: 04721b1cce003b2f070e707493ff32c6cdb1b82b" in workflow assert "python -m pip install --no-deps -e external/QuantPlatformKit" in workflow assert "scripts/run_walk_forward_backtest.py" in workflow assert '"--list-profiles"' in workflow @@ -38,7 +38,7 @@ def test_drift_workflow_wires_real_pipeline_inputs_and_preflight_bundle() -> Non assert "Upload lifecycle preflight artifact" in workflow assert "lifecycle-preflight-${{ github.run_id }}-${{ github.run_attempt }}" in workflow assert workflow.count("github.ref == format('refs/heads/{0}', github.event.repository.default_branch)") == 2 - assert "uses: QuantStrategyLab/QuantPlatformKit/.github/workflows/reusable-drift-check.yml@c812ed70f83d61bdf1816fa5ca112b0f6976c6b6" in workflow + assert "uses: QuantStrategyLab/QuantPlatformKit/.github/workflows/reusable-drift-check.yml@04721b1cce003b2f070e707493ff32c6cdb1b82b" in workflow assert "strategy_domain: crypto" in workflow assert "snapshot_repository: QuantStrategyLab/CryptoLivePoolPipelines" in workflow assert "snapshot_checkout_path: external/CryptoLivePoolPipelines" in workflow diff --git a/tests/test_qsl_compat_metadata.py b/tests/test_qsl_compat_metadata.py index 6258394..2b4e6f8 100644 --- a/tests/test_qsl_compat_metadata.py +++ b/tests/test_qsl_compat_metadata.py @@ -3,7 +3,7 @@ ROOT = Path(__file__).resolve().parents[1] -QPK_REVISION = "c812ed70f83d61bdf1816fa5ca112b0f6976c6b6" +QPK_REVISION = "04721b1cce003b2f070e707493ff32c6cdb1b82b" QPK_URL = ( "quant-platform-kit @ git+https://github.com/QuantStrategyLab/" f"QuantPlatformKit.git@{QPK_REVISION}" diff --git a/uv.lock b/uv.lock index 169aa89..07b6603 100644 --- a/uv.lock +++ b/uv.lock @@ -28,7 +28,7 @@ research = [ requires-dist = [ { name = "numpy", marker = "extra == 'research'", specifier = ">=1.26" }, { name = "pandas", marker = "extra == 'research'", specifier = ">=2.0" }, - { name = "quant-platform-kit", git = "https://github.com/QuantStrategyLab/QuantPlatformKit.git?rev=c812ed70f83d61bdf1816fa5ca112b0f6976c6b6" }, + { name = "quant-platform-kit", git = "https://github.com/QuantStrategyLab/QuantPlatformKit.git?rev=04721b1cce003b2f070e707493ff32c6cdb1b82b" }, ] provides-extras = ["research"] @@ -182,7 +182,7 @@ wheels = [ [[package]] name = "quant-platform-kit" version = "0.10.0" -source = { git = "https://github.com/QuantStrategyLab/QuantPlatformKit.git?rev=c812ed70f83d61bdf1816fa5ca112b0f6976c6b6#c812ed70f83d61bdf1816fa5ca112b0f6976c6b6" } +source = { git = "https://github.com/QuantStrategyLab/QuantPlatformKit.git?rev=04721b1cce003b2f070e707493ff32c6cdb1b82b#04721b1cce003b2f070e707493ff32c6cdb1b82b" } [[package]] name = "six"