test(performance): enforce semantic artifact authority boundary (#19)
CI / lite (push) Successful in 9s

This commit was merged in pull request #19.
This commit is contained in:
2026-09-01 23:12:10 +08:00
parent a724e1e57a
commit 68dd68392a
7 changed files with 3025 additions and 4 deletions
+871
View File
@@ -0,0 +1,871 @@
{
"cases": {
"absent": {
"artifact_available_at": "2026-01-08T02:05:00Z",
"authority": "quant_engine",
"backtest_evidence_manifest_document_sha256": "sha256:b7e9139e021de3122bee9376a8c8387fca3db75fe2a698adccf33471caf971d2",
"backtest_evidence_manifest_evidence_digest": "sha256:fae26a93d754e98f437bf9e4b635fc1cdc4f85d004a4bde396823b52e2115de5",
"backtest_evidence_manifest_id": "rhbacktestevidencev1:sha256:3f67fcad23c75684ffeb325d8405b2f81139a732e237d30fbb30d23f91e32726",
"backtest_evidence_qualification": "contract_qualified",
"backtest_run_ref_document_sha256": "sha256:6a798adb3e0568aca84ed3e3a285b92d181ec569462fc003952a8c0d8382ae3a",
"backtest_run_ref_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"benchmark_alignment_policy": "none",
"benchmark_id": "",
"benchmark_series_digest": null,
"calendar": "CN-A",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"configuration_digest": "sha256:d28b49ea1bebc78d0023667f4fb9990b1fb45807176c2193b458525def056f4d",
"cost_model_digest": "sha256:8888888888888888888888888888888888888888888888888888888888888888",
"cost_model_version": "1.0.0",
"dataset_content_digest": "sha256:44ea11ba64dc2e6fd55c6d8e038c5edc84ee38d6fd46e38b15a1d5409662a020",
"dataset_manifest_digest": "sha256:d991bb2f8f6b80525f93c51e0b371213a3ed4649dffb073ed4605bfbd32349bd",
"dataset_snapshot_id": "rhdsv1:sha256:f63a29b4795c63fb7d6b2d3b5544cee9274b633db77c75c63d50a340c0827d57",
"document_sha256": "sha256:729852af307fd4a94ac566ae45df2e57b3d45c4fbdf45820351b5ef19cdf0ad3",
"end_date": "2026-01-08",
"environment_lock_digest": "sha256:9999999999999999999999999999999999999999999999999999999999999999",
"execution_model_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777",
"execution_model_version": "1.0.0",
"factor_output_content_digest": "sha256:d78751460dc27fc796163c462d946924ce2bcb45dcfceb5e4b77f76093befc9e",
"factor_set_digest": "sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"factor_set_id": "rhfactorsetv1:sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"foundation_digest": "sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"foundation_id": "rhdfv1:sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"frequency": "1d",
"methodology": {
"alpha": "daily_ols_intercept_geometric_annualization",
"annual_risk_free": 0.0,
"annualized_return": "geometric_compound",
"annualized_volatility": "sample_std_sqrt_periods",
"benchmark_alignment": "none",
"benchmark_risk_free_daily": 0.0,
"beta": "sample_covariance_over_sample_variance",
"calmar_ratio": "unadjusted_annualized_return_over_absolute_maximum_drawdown",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"implementation_module": "quant_engine.metrics",
"implementation_version": "researchhub.quant-performance-methodology.v1",
"information_ratio": "mean_active_over_sample_std_active_sqrt_periods",
"maximum_drawdown": "non_positive_peak_to_trough_ratio_with_initial_nav_one",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"periods_per_year": 252,
"return_type": "simple",
"sharpe_ratio": "annualized_return_minus_annual_risk_free_over_annualized_volatility",
"sortino_ratio": "annualized_return_minus_annual_risk_free_over_root_mean_square_negative_returns_sqrt_periods",
"source_frequency": "1d",
"total_return": "final_nav_minus_one",
"tracking_error": "sample_std_active_return_sqrt_periods",
"win_rate": "positive_daily_return_count_over_observation_count"
},
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"metrics": [
{
"availability": "available",
"key": "total_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "total_ret",
"unit": "ratio",
"value": 0.575
},
{
"availability": "available",
"key": "annualized_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_ret",
"unit": "ratio_per_year",
"value": 2683336646708.1
},
{
"availability": "available",
"key": "annualized_volatility",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_volatility",
"unit": "ratio_per_year",
"value": 1.38901943830891
},
{
"availability": "available",
"key": "sharpe_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sharpe",
"unit": "ratio",
"value": 1931820803008.3313
},
{
"availability": "available",
"key": "sortino_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sortino",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "maximum_drawdown",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "max_dd",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "calmar_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "calmar",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "win_rate",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "win_rate",
"unit": "ratio",
"value": 0.75
},
{
"availability": "benchmark_absent",
"key": "tracking_error",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "tracking_error",
"unit": "ratio_per_year",
"value": null
},
{
"availability": "benchmark_absent",
"key": "information_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "ir",
"unit": "ratio",
"value": null
},
{
"availability": "benchmark_absent",
"key": "alpha",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "alpha",
"unit": "ratio_per_year",
"value": null
},
{
"availability": "benchmark_absent",
"key": "beta",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "beta",
"unit": "ratio",
"value": null
},
{
"availability": "available",
"key": "trade_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_trades",
"unit": "count",
"value": 3
},
{
"availability": "available",
"key": "day_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_days",
"unit": "count",
"value": 4
}
],
"performance_evidence_id": "rhperformanceevidencev1:sha256:d735abe76c28db429e107cb5ba6a1929c2c0f2084a6c4ac41b38ffbc02b2d2bd",
"performance_row_digest": "sha256:4e6329b0db4731513fe793491a163dd358e3a6f7baa84d3c94a4d4d2355c7a7d",
"performance_table_content_digest": "sha256:074b8511ff9a2154235e4dde8bac300658cb69f900e49f332d61560b82be9af5",
"performance_table_logical_name": "performance",
"performance_table_row_count": 1,
"performance_table_schema_digest": "sha256:16cef93a679761103ae405e622b7929abbfe07115bf276be4f164da5a16128d0",
"research_artifact_content_digest": "sha256:ad85ee1317bd8ce5fbef8fddc268b91be8678701ba5b8fbf6d61bf670f918bf9",
"research_artifact_schema_version": "1.1.0",
"run_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"schema_version": "researchhub.performance-evidence.v1",
"scope": "offline_research_only",
"start_date": "2026-01-05",
"strategy_digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666",
"strategy_id": "alpha-top1",
"strategy_version": "1.0.0",
"timezone": "Asia/Shanghai"
},
"estimable": {
"artifact_available_at": "2026-01-08T02:05:00Z",
"authority": "quant_engine",
"backtest_evidence_manifest_document_sha256": "sha256:e2e0e63fb4c733d2dba9a290511b6c8b0132bfe877dfe89ee7e614b74b87bc51",
"backtest_evidence_manifest_evidence_digest": "sha256:f3913894d032c389c64eef59058b3cbc694cb9cc14ce9cee2699f0068200b650",
"backtest_evidence_manifest_id": "rhbacktestevidencev1:sha256:f94733e849433f62f3da1e1ec8999891b93d49c7d657832d64e64bef9e211117",
"backtest_evidence_qualification": "contract_qualified",
"backtest_run_ref_document_sha256": "sha256:6a798adb3e0568aca84ed3e3a285b92d181ec569462fc003952a8c0d8382ae3a",
"backtest_run_ref_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"benchmark_alignment_policy": "exact_session_index",
"benchmark_id": "000300.SH",
"benchmark_series_digest": "sha256:1c564e4d12af0d59b1fd707d7816da2895238969d9207470984db63cfeac423a",
"calendar": "CN-A",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"configuration_digest": "sha256:d28b49ea1bebc78d0023667f4fb9990b1fb45807176c2193b458525def056f4d",
"cost_model_digest": "sha256:8888888888888888888888888888888888888888888888888888888888888888",
"cost_model_version": "1.0.0",
"dataset_content_digest": "sha256:44ea11ba64dc2e6fd55c6d8e038c5edc84ee38d6fd46e38b15a1d5409662a020",
"dataset_manifest_digest": "sha256:d991bb2f8f6b80525f93c51e0b371213a3ed4649dffb073ed4605bfbd32349bd",
"dataset_snapshot_id": "rhdsv1:sha256:f63a29b4795c63fb7d6b2d3b5544cee9274b633db77c75c63d50a340c0827d57",
"document_sha256": "sha256:a6a1a3313f511505c0cf57fddeebdf20a3b0f83a2958f31332d5597d172165e7",
"end_date": "2026-01-08",
"environment_lock_digest": "sha256:9999999999999999999999999999999999999999999999999999999999999999",
"execution_model_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777",
"execution_model_version": "1.0.0",
"factor_output_content_digest": "sha256:d78751460dc27fc796163c462d946924ce2bcb45dcfceb5e4b77f76093befc9e",
"factor_set_digest": "sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"factor_set_id": "rhfactorsetv1:sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"foundation_digest": "sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"foundation_id": "rhdfv1:sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"frequency": "1d",
"methodology": {
"alpha": "daily_ols_intercept_geometric_annualization",
"annual_risk_free": 0.0,
"annualized_return": "geometric_compound",
"annualized_volatility": "sample_std_sqrt_periods",
"benchmark_alignment": "exact_session_index",
"benchmark_risk_free_daily": 0.0,
"beta": "sample_covariance_over_sample_variance",
"calmar_ratio": "unadjusted_annualized_return_over_absolute_maximum_drawdown",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"implementation_module": "quant_engine.metrics",
"implementation_version": "researchhub.quant-performance-methodology.v1",
"information_ratio": "mean_active_over_sample_std_active_sqrt_periods",
"maximum_drawdown": "non_positive_peak_to_trough_ratio_with_initial_nav_one",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"periods_per_year": 252,
"return_type": "simple",
"sharpe_ratio": "annualized_return_minus_annual_risk_free_over_annualized_volatility",
"sortino_ratio": "annualized_return_minus_annual_risk_free_over_root_mean_square_negative_returns_sqrt_periods",
"source_frequency": "1d",
"total_return": "final_nav_minus_one",
"tracking_error": "sample_std_active_return_sqrt_periods",
"win_rate": "positive_daily_return_count_over_observation_count"
},
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"metrics": [
{
"availability": "available",
"key": "total_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "total_ret",
"unit": "ratio",
"value": 0.575
},
{
"availability": "available",
"key": "annualized_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_ret",
"unit": "ratio_per_year",
"value": 2683336646708.1
},
{
"availability": "available",
"key": "annualized_volatility",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_volatility",
"unit": "ratio_per_year",
"value": 1.38901943830891
},
{
"availability": "available",
"key": "sharpe_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sharpe",
"unit": "ratio",
"value": 1931820803008.3313
},
{
"availability": "available",
"key": "sortino_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sortino",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "maximum_drawdown",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "max_dd",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "calmar_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "calmar",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "win_rate",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "win_rate",
"unit": "ratio",
"value": 0.75
},
{
"availability": "available",
"key": "tracking_error",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "tracking_error",
"unit": "ratio_per_year",
"value": 1.3032171729991897
},
{
"availability": "available",
"key": "information_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "ir",
"unit": "ratio",
"value": 22.801264912443322
},
{
"availability": "available",
"key": "alpha",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "alpha",
"unit": "ratio_per_year",
"value": 123663320625.66454
},
{
"availability": "available",
"key": "beta",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "beta",
"unit": "ratio",
"value": 3.2500000000000013
},
{
"availability": "available",
"key": "trade_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_trades",
"unit": "count",
"value": 3
},
{
"availability": "available",
"key": "day_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_days",
"unit": "count",
"value": 4
}
],
"performance_evidence_id": "rhperformanceevidencev1:sha256:f1f72c34d7427bd0d2e273a66b9677d112aa51c2417ea1cda8245e51e334e4f6",
"performance_row_digest": "sha256:bad2b506679a6ca13d80ab00859a442ba692f3872d42b0b45bbc3b1d6ffe72a4",
"performance_table_content_digest": "sha256:0856439ea7ec84e38887ccfa0067324f2e9cd293543e4ef683b9c2beb9eb34cf",
"performance_table_logical_name": "performance",
"performance_table_row_count": 1,
"performance_table_schema_digest": "sha256:16cef93a679761103ae405e622b7929abbfe07115bf276be4f164da5a16128d0",
"research_artifact_content_digest": "sha256:6ec566d73da3966d3d5f946313e2b0181993374c9f4ceb4b56e165cc6793d382",
"research_artifact_schema_version": "1.1.0",
"run_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"schema_version": "researchhub.performance-evidence.v1",
"scope": "offline_research_only",
"start_date": "2026-01-05",
"strategy_digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666",
"strategy_id": "alpha-top1",
"strategy_version": "1.0.0",
"timezone": "Asia/Shanghai"
},
"zero_active_variance": {
"artifact_available_at": "2026-01-08T02:05:00Z",
"authority": "quant_engine",
"backtest_evidence_manifest_document_sha256": "sha256:8a13212575154d97f85011ed54ed3bb588f73a691926b3ca03b360d563e9fc29",
"backtest_evidence_manifest_evidence_digest": "sha256:8c0c2052ab93aa920254bc7f4d89435d839b7150ecaaaa798703e89ddf876ec1",
"backtest_evidence_manifest_id": "rhbacktestevidencev1:sha256:699ad35ee30a294082c607c40617097aa90d5d58343e7d8c8185d8a53f52596c",
"backtest_evidence_qualification": "contract_qualified",
"backtest_run_ref_document_sha256": "sha256:6a798adb3e0568aca84ed3e3a285b92d181ec569462fc003952a8c0d8382ae3a",
"backtest_run_ref_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"benchmark_alignment_policy": "exact_session_index",
"benchmark_id": "000300.SH",
"benchmark_series_digest": "sha256:7668b77ac689cd542005fae42cb2abd48fdf772d2f982086dca409606653e6ac",
"calendar": "CN-A",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"configuration_digest": "sha256:d28b49ea1bebc78d0023667f4fb9990b1fb45807176c2193b458525def056f4d",
"cost_model_digest": "sha256:8888888888888888888888888888888888888888888888888888888888888888",
"cost_model_version": "1.0.0",
"dataset_content_digest": "sha256:44ea11ba64dc2e6fd55c6d8e038c5edc84ee38d6fd46e38b15a1d5409662a020",
"dataset_manifest_digest": "sha256:d991bb2f8f6b80525f93c51e0b371213a3ed4649dffb073ed4605bfbd32349bd",
"dataset_snapshot_id": "rhdsv1:sha256:f63a29b4795c63fb7d6b2d3b5544cee9274b633db77c75c63d50a340c0827d57",
"document_sha256": "sha256:44a04be0105f29e1cbf8d2430b6b0eb084853d428bc2ccd5834dfdbcf9482bd7",
"end_date": "2026-01-08",
"environment_lock_digest": "sha256:9999999999999999999999999999999999999999999999999999999999999999",
"execution_model_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777",
"execution_model_version": "1.0.0",
"factor_output_content_digest": "sha256:d78751460dc27fc796163c462d946924ce2bcb45dcfceb5e4b77f76093befc9e",
"factor_set_digest": "sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"factor_set_id": "rhfactorsetv1:sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"foundation_digest": "sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"foundation_id": "rhdfv1:sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"frequency": "1d",
"methodology": {
"alpha": "daily_ols_intercept_geometric_annualization",
"annual_risk_free": 0.0,
"annualized_return": "geometric_compound",
"annualized_volatility": "sample_std_sqrt_periods",
"benchmark_alignment": "exact_session_index",
"benchmark_risk_free_daily": 0.0,
"beta": "sample_covariance_over_sample_variance",
"calmar_ratio": "unadjusted_annualized_return_over_absolute_maximum_drawdown",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"implementation_module": "quant_engine.metrics",
"implementation_version": "researchhub.quant-performance-methodology.v1",
"information_ratio": "mean_active_over_sample_std_active_sqrt_periods",
"maximum_drawdown": "non_positive_peak_to_trough_ratio_with_initial_nav_one",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"periods_per_year": 252,
"return_type": "simple",
"sharpe_ratio": "annualized_return_minus_annual_risk_free_over_annualized_volatility",
"sortino_ratio": "annualized_return_minus_annual_risk_free_over_root_mean_square_negative_returns_sqrt_periods",
"source_frequency": "1d",
"total_return": "final_nav_minus_one",
"tracking_error": "sample_std_active_return_sqrt_periods",
"win_rate": "positive_daily_return_count_over_observation_count"
},
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"metrics": [
{
"availability": "available",
"key": "total_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "total_ret",
"unit": "ratio",
"value": 0.575
},
{
"availability": "available",
"key": "annualized_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_ret",
"unit": "ratio_per_year",
"value": 2683336646708.1
},
{
"availability": "available",
"key": "annualized_volatility",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_volatility",
"unit": "ratio_per_year",
"value": 1.38901943830891
},
{
"availability": "available",
"key": "sharpe_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sharpe",
"unit": "ratio",
"value": 1931820803008.3313
},
{
"availability": "available",
"key": "sortino_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sortino",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "maximum_drawdown",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "max_dd",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "calmar_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "calmar",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "win_rate",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "win_rate",
"unit": "ratio",
"value": 0.75
},
{
"availability": "available",
"key": "tracking_error",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "tracking_error",
"unit": "ratio_per_year",
"value": 0.0
},
{
"availability": "not_estimable_active_variance",
"key": "information_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "ir",
"unit": "ratio",
"value": null
},
{
"availability": "available",
"key": "alpha",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "alpha",
"unit": "ratio_per_year",
"value": 0.0
},
{
"availability": "available",
"key": "beta",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "beta",
"unit": "ratio",
"value": 1.0000000000000002
},
{
"availability": "available",
"key": "trade_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_trades",
"unit": "count",
"value": 3
},
{
"availability": "available",
"key": "day_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_days",
"unit": "count",
"value": 4
}
],
"performance_evidence_id": "rhperformanceevidencev1:sha256:e6730d25d90c85a6370adb72bc45c1bf505235f77b72521dd8197898ca369fe5",
"performance_row_digest": "sha256:6528c47fa9416e350aa5010477dbd8c83a35cecf87aa5bc413cec95a9765114d",
"performance_table_content_digest": "sha256:7d57a966431c68093a9f6193ae62f79a63d33832f11dd68524ed9bcd2cb6257c",
"performance_table_logical_name": "performance",
"performance_table_row_count": 1,
"performance_table_schema_digest": "sha256:16cef93a679761103ae405e622b7929abbfe07115bf276be4f164da5a16128d0",
"research_artifact_content_digest": "sha256:b17ab9e158a7ceeb5107f6fe8a61f332009c314186f3436d4750aa44d6ca3856",
"research_artifact_schema_version": "1.1.0",
"run_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"schema_version": "researchhub.performance-evidence.v1",
"scope": "offline_research_only",
"start_date": "2026-01-05",
"strategy_digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666",
"strategy_id": "alpha-top1",
"strategy_version": "1.0.0",
"timezone": "Asia/Shanghai"
},
"zero_benchmark_variance": {
"artifact_available_at": "2026-01-08T02:05:00Z",
"authority": "quant_engine",
"backtest_evidence_manifest_document_sha256": "sha256:2389b804f5d8d20a37b31f596b52892484777c5da799dd68865a082ee90e6e5b",
"backtest_evidence_manifest_evidence_digest": "sha256:54bb315bc1940ef6df79999cf03ebb8d10defaf526bf7802d63da33f612520ec",
"backtest_evidence_manifest_id": "rhbacktestevidencev1:sha256:ad9559e1f8feca28bb310765216a975935f05f51057139c2d02fd2fe7dfe501e",
"backtest_evidence_qualification": "contract_qualified",
"backtest_run_ref_document_sha256": "sha256:6a798adb3e0568aca84ed3e3a285b92d181ec569462fc003952a8c0d8382ae3a",
"backtest_run_ref_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"benchmark_alignment_policy": "exact_session_index",
"benchmark_id": "000300.SH",
"benchmark_series_digest": "sha256:d0f1e954d796e95254bcccc893d6e3a8f9d541c3028b88b2c0b24c1658bb2408",
"calendar": "CN-A",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"configuration_digest": "sha256:d28b49ea1bebc78d0023667f4fb9990b1fb45807176c2193b458525def056f4d",
"cost_model_digest": "sha256:8888888888888888888888888888888888888888888888888888888888888888",
"cost_model_version": "1.0.0",
"dataset_content_digest": "sha256:44ea11ba64dc2e6fd55c6d8e038c5edc84ee38d6fd46e38b15a1d5409662a020",
"dataset_manifest_digest": "sha256:d991bb2f8f6b80525f93c51e0b371213a3ed4649dffb073ed4605bfbd32349bd",
"dataset_snapshot_id": "rhdsv1:sha256:f63a29b4795c63fb7d6b2d3b5544cee9274b633db77c75c63d50a340c0827d57",
"document_sha256": "sha256:077f3ec84802aff2f046365a3a5f61f475b1ad63ec05e96742844bc531bcb551",
"end_date": "2026-01-08",
"environment_lock_digest": "sha256:9999999999999999999999999999999999999999999999999999999999999999",
"execution_model_digest": "sha256:7777777777777777777777777777777777777777777777777777777777777777",
"execution_model_version": "1.0.0",
"factor_output_content_digest": "sha256:d78751460dc27fc796163c462d946924ce2bcb45dcfceb5e4b77f76093befc9e",
"factor_set_digest": "sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"factor_set_id": "rhfactorsetv1:sha256:e9339581cf569e92459f672e8081337712e7bf98e58ad42d60d7ed13f9b5a021",
"foundation_digest": "sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"foundation_id": "rhdfv1:sha256:d848237ab753ee9432ae78ec1f93b6ac45c8072d6694023b7f288203daf9d838",
"frequency": "1d",
"methodology": {
"alpha": "daily_ols_intercept_geometric_annualization",
"annual_risk_free": 0.0,
"annualized_return": "geometric_compound",
"annualized_volatility": "sample_std_sqrt_periods",
"benchmark_alignment": "exact_session_index",
"benchmark_risk_free_daily": 0.0,
"beta": "sample_covariance_over_sample_variance",
"calmar_ratio": "unadjusted_annualized_return_over_absolute_maximum_drawdown",
"code_revision": "dddddddddddddddddddddddddddddddddddddddd",
"implementation_module": "quant_engine.metrics",
"implementation_version": "researchhub.quant-performance-methodology.v1",
"information_ratio": "mean_active_over_sample_std_active_sqrt_periods",
"maximum_drawdown": "non_positive_peak_to_trough_ratio_with_initial_nav_one",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"periods_per_year": 252,
"return_type": "simple",
"sharpe_ratio": "annualized_return_minus_annual_risk_free_over_annualized_volatility",
"sortino_ratio": "annualized_return_minus_annual_risk_free_over_root_mean_square_negative_returns_sqrt_periods",
"source_frequency": "1d",
"total_return": "final_nav_minus_one",
"tracking_error": "sample_std_active_return_sqrt_periods",
"win_rate": "positive_daily_return_count_over_observation_count"
},
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"metrics": [
{
"availability": "available",
"key": "total_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "total_ret",
"unit": "ratio",
"value": 0.575
},
{
"availability": "available",
"key": "annualized_return",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_ret",
"unit": "ratio_per_year",
"value": 2683336646708.1
},
{
"availability": "available",
"key": "annualized_volatility",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "ann_volatility",
"unit": "ratio_per_year",
"value": 1.38901943830891
},
{
"availability": "available",
"key": "sharpe_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sharpe",
"unit": "ratio",
"value": 1931820803008.3313
},
{
"availability": "available",
"key": "sortino_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "sortino",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "maximum_drawdown",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "max_dd",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "calmar_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "calmar",
"unit": "ratio",
"value": 0.0
},
{
"availability": "available",
"key": "win_rate",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "win_rate",
"unit": "ratio",
"value": 0.75
},
{
"availability": "available",
"key": "tracking_error",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "tracking_error",
"unit": "ratio_per_year",
"value": 1.38901943830891
},
{
"availability": "available",
"key": "information_ratio",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "ir",
"unit": "ratio",
"value": 22.299903907544408
},
{
"availability": "not_estimable_benchmark_variance",
"key": "alpha",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "alpha",
"unit": "ratio_per_year",
"value": null
},
{
"availability": "not_estimable_benchmark_variance",
"key": "beta",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": true,
"source_column": "beta",
"unit": "ratio",
"value": null
},
{
"availability": "available",
"key": "trade_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_trades",
"unit": "count",
"value": 3
},
{
"availability": "available",
"key": "day_count",
"methodology_id": "researchhub.quant-performance-methodology.v1",
"metric_schema_id": "researchhub.quant-performance-metrics.v1",
"nullable": false,
"source_column": "n_days",
"unit": "count",
"value": 4
}
],
"performance_evidence_id": "rhperformanceevidencev1:sha256:86133a6b3c3091477cdc4618ebc294e671c9ba0a3ef5015a068f92bb575729b9",
"performance_row_digest": "sha256:90c9aa2f4168c15ff9ac5d4da2a35c3e915bb4e04736e5a440ea80c787a99553",
"performance_table_content_digest": "sha256:1570b64d83ad2a849607e6f5203f5ec2f0291a8d6cbb00b8edfe0ae030b7967d",
"performance_table_logical_name": "performance",
"performance_table_row_count": 1,
"performance_table_schema_digest": "sha256:16cef93a679761103ae405e622b7929abbfe07115bf276be4f164da5a16128d0",
"research_artifact_content_digest": "sha256:fed7a28888a6e98ccce78e7d84f22d4e3636e928485861af7a97f90eddc91f94",
"research_artifact_schema_version": "1.1.0",
"run_id": "rhbacktestrunv1:sha256:5036c771c44a2adade9ea590eee0d8cf824ff8f519fadd8ba424e5d914856386",
"schema_version": "researchhub.performance-evidence.v1",
"scope": "offline_research_only",
"start_date": "2026-01-05",
"strategy_digest": "sha256:6666666666666666666666666666666666666666666666666666666666666666",
"strategy_id": "alpha-top1",
"strategy_version": "1.0.0",
"timezone": "Asia/Shanghai"
}
},
"schema_version": 1,
"source_commit": "a724e1e57a99d1304a932d01ee836bac56c5c15c",
"source_tree": "4774e88442d25bf79a54eab3d7106ff4d0ba9603"
}
+8 -1
View File
@@ -16,7 +16,7 @@ def test_module_spec_declares_pure_research_engine_boundary() -> None:
prohibited = " ".join(spec["bounded_context"]["prohibited_responsibilities"]).lower()
for term in ("investment advice", "live order", "credentials", "source facts"):
assert term in prohibited
assert spec["authority"]["revision"] == 4
assert spec["authority"]["revision"] == 5
assert {
(item["contract_id"], item["version"])
for item in spec["contracts"]["provides"]
@@ -25,6 +25,7 @@ def test_module_spec_declares_pure_research_engine_boundary() -> None:
("researchhub.factor-set-ref", "1.0.0"),
("researchhub.backtest-run-ref", "1.0.0"),
("researchhub.backtest-evidence-manifest", "1.0.0"),
("researchhub.performance-evidence", "1.0.0"),
("researchhub.portfolio-decision", "1.0.0"),
("researchhub.risk-assessment", "1.0.0"),
}
@@ -33,6 +34,7 @@ def test_module_spec_declares_pure_research_engine_boundary() -> None:
"researchhub.factor-set-ref": "src/quant_engine/factor_contracts.py",
"researchhub.backtest-run-ref": "src/quant_engine/governed_pipeline.py",
"researchhub.backtest-evidence-manifest": "src/quant_engine/artifact.py",
"researchhub.performance-evidence": "src/quant_engine/artifact.py",
"researchhub.portfolio-decision": "src/quant_engine/portfolio_risk_contracts.py",
"researchhub.risk-assessment": "src/quant_engine/portfolio_risk_contracts.py",
}
@@ -53,6 +55,11 @@ def test_module_spec_declares_pure_research_engine_boundary() -> None:
)
assert spec["dependencies"] == []
capabilities = {item["id"]: item for item in spec["capabilities"]}
evidence_contract = capabilities["backtest-evidence-contracts"]
assert evidence_contract["status"] == "operational"
evidence_summary = evidence_contract["summary"].lower()
for term in ("performance-methodology", "without recomputation", "decision authority"):
assert term in evidence_summary
portfolio_contract = capabilities["portfolio-risk-computation-contracts"]
assert portfolio_contract["status"] == "operational"
summary = portfolio_contract["summary"].lower()
+727
View File
@@ -0,0 +1,727 @@
"""Closed performance-evidence contract conformance tests."""
from __future__ import annotations
import copy
import hashlib
import json
from dataclasses import replace
from pathlib import Path
from typing import Any
import numpy as np
import pandas as pd
import pytest
from quant_engine.artifact import (
PERFORMANCE_EVIDENCE_SCHEMA_VERSION,
PERFORMANCE_METRIC_SCHEMA_ID,
PERFORMANCE_METHODOLOGY_ID,
BacktestEvidenceManifest,
EvidenceQualification,
PerformanceEvidenceError,
PerformanceEvidenceErrorCode,
PerformanceEvidenceV1,
PerformanceMetricAvailability,
ResearchRunArtifact,
build_backtest_evidence_manifest,
build_performance_evidence,
build_research_run_artifact,
)
from quant_engine.execution import ExecutionConfig
from quant_engine.factor_contracts import (
ActorIdentity,
AvailabilityMode,
Causation,
DataFoundationEnvelope,
DatasetSnapshotEnvelope,
FactorInput,
FactorSetRef,
InputBinding,
OutputArtifactRef,
OutputCoverage,
OutputQuality,
OutputQualityCheck,
ProducerIdentity,
ViewAvailability,
canonical_json_bytes,
factor_definition_from_alpha158,
factor_input_schema_digest,
)
from quant_engine.governed_pipeline import BacktestRunRef
from quant_engine.metrics import TRADING_DAYS_PER_YEAR, benchmark_summary, summary
from quant_engine.research_pipeline import FactorBacktestResult, run_factor_backtest_research
ROOT = Path(__file__).resolve().parents[1]
FACTOR_FIXTURE = ROOT / "tests" / "fixtures" / "factor-contracts-v1.golden.json"
PERFORMANCE_FIXTURE = (
ROOT / "tests" / "fixtures" / "performance-evidence-v1.golden.json"
)
VIEW_REF_ID = "rhviewrefv1:sha256:bf776bcd26d940fafde1d650776a5505fb3fe8b5b068c351622bf2c42385629c"
VIEW_SCHEMA_DIGEST = "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
CALENDAR_REVISION_ID = "rhcalv1:sha256:1f4ca22557063389badd669cf774bb35234066e847646682dccfe411e252a078"
ACTION_REVISION_ID = "rhcav1:sha256:0f947df29f152bfa2c6ab0da7a0d464670c7ad2526cd10f2a7939b42fee5c275"
PARAMETERS = {"lag_sessions": 1, "top_k": 1}
def _sha256(value: bytes) -> str:
return f"sha256:{hashlib.sha256(value).hexdigest()}"
def _accepted_authorities() -> tuple[
DatasetSnapshotEnvelope,
DataFoundationEnvelope,
FactorSetRef,
]:
fixture = json.loads(FACTOR_FIXTURE.read_text(encoding="utf-8"))
snapshot = DatasetSnapshotEnvelope.from_dict(fixture["dataset_snapshot"])
foundation = DataFoundationEnvelope.from_dict(fixture["data_foundation"])
factor_input = FactorInput("market", VIEW_SCHEMA_DIGEST, ("close", "volume"))
definition = factor_definition_from_alpha158(
"alpha_005",
version="1.0.0",
parameters={},
inputs=(factor_input,),
implementation_digest="sha256:" + "1" * 64,
input_schema_digest=factor_input_schema_digest((factor_input,)),
valid_from="2026-01-01T00:00:00.000000Z",
valid_until="2027-01-01T00:00:00Z",
warmup_sessions=10,
lag_sessions=1,
producer=ProducerIdentity("quant_engine", "1.0.0"),
code_revision="c" * 40,
)
output_schema_bytes = canonical_json_bytes(fixture["output_schema"])
output_content_bytes = canonical_json_bytes(fixture["output_content"])
artifact_ref = OutputArtifactRef.create(
schema_digest=_sha256(output_schema_bytes),
content_digest=_sha256(output_content_bytes),
)
factor_set = FactorSetRef.create(
definitions=(definition,),
dataset_snapshot=snapshot,
foundation=foundation,
selected_view_ref_ids=(VIEW_REF_ID,),
input_bindings=(
InputBinding(
definition.definition_id,
"market",
VIEW_REF_ID,
VIEW_SCHEMA_DIGEST,
),
),
view_availability=(
ViewAvailability(VIEW_REF_ID, "2026-01-02T23:50:00Z", "sha256:" + "2" * 64),
),
output_quality=OutputQuality(
"passed",
(OutputQualityCheck("finite_values", "passed", "sha256:" + "3" * 64),),
),
output_coverage=OutputCoverage(
"complete",
1,
1,
"row",
"alpha_005.cn_a",
"sha256:" + "4" * 64,
),
output_schema_bytes=output_schema_bytes,
output_content_bytes=output_content_bytes,
output_artifact_ref=artifact_ref,
availability_mode=AvailabilityMode.AS_AVAILABLE,
evaluation_at="2026-01-03T11:00:00Z",
computed_at="2026-01-03T10:15:00Z",
artifact_available_at="2026-01-03T10:20:00Z",
producer=ProducerIdentity("quant_engine", "1.0.0"),
code_revision="c" * 40,
actor=ActorIdentity("service", "factor_worker_v1"),
correlation_id="research_run_001",
causation=Causation("foundation", foundation.foundation_id),
evidence_scope="synthetic_fixture",
decision_eligible=False,
)
return snapshot, foundation, factor_set
def _configuration_digest() -> str:
return _sha256(
json.dumps(
PARAMETERS,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
).encode("utf-8")
)
def _run_ref(**overrides: Any) -> BacktestRunRef:
snapshot, foundation, factor_set = _accepted_authorities()
arguments: dict[str, Any] = {
"dataset_snapshot": snapshot,
"foundation": foundation,
"factor_set": factor_set,
"universe_digest": "sha256:" + "5" * 64,
"trading_calendar_revision_ids": (CALENDAR_REVISION_ID,),
"corporate_action_revision_ids": (ACTION_REVISION_ID,),
"strategy_id": "alpha-top1",
"strategy_version": "1.0.0",
"strategy_digest": "sha256:" + "6" * 64,
"execution_model_version": "1.0.0",
"execution_model_digest": "sha256:" + "7" * 64,
"cost_model_version": "1.0.0",
"cost_model_digest": "sha256:" + "8" * 64,
"random_seed": 7,
"code_revision": "d" * 40,
"environment_lock_digest": "sha256:" + "9" * 64,
"configuration_digest": _configuration_digest(),
"evaluation_at": "2026-01-08T01:00:00Z",
"computed_at": "2026-01-08T02:00:00Z",
}
arguments.update(overrides)
return BacktestRunRef.create(**arguments)
def _backtest_result() -> FactorBacktestResult:
dates = pd.date_range("2026-01-05", periods=4, freq="B")
scores = pd.DataFrame({"A": [2.0, 0.0], "B": [1.0, 3.0]}, index=dates[:2])
opens = pd.DataFrame(
{"A": [10.0, 10.0, 15.0, 15.0], "B": [20.0, 20.0, 20.0, 21.0]},
index=dates,
)
closes = pd.DataFrame(
{"A": [10.0, 12.0, 15.0, 15.0], "B": [20.0, 20.0, 18.0, 21.0]},
index=dates,
)
return run_factor_backtest_research(
scores,
opens,
closes,
top_k=1,
execution_price_field="open",
valuation_price_field="close",
initial_cash=1_000.0,
config=ExecutionConfig(
commission_bps=0,
stamp_tax_bps=0,
slippage_bps=0,
min_trade_amount=0,
),
)
def _artifact(
run_ref: BacktestRunRef,
benchmark_kind: str,
) -> tuple[ResearchRunArtifact, FactorBacktestResult]:
result = _backtest_result()
benchmark_id: str | None
benchmark_returns: pd.Series | None
if benchmark_kind == "absent":
benchmark_id = None
benchmark_returns = None
elif benchmark_kind == "estimable":
benchmark_id = "000300.SH"
benchmark_returns = pd.Series(
[0.0, 0.01, -0.01, 0.02],
index=result.returns.index,
name="benchmark_return",
)
elif benchmark_kind == "zero_active_variance":
benchmark_id = "000300.SH"
benchmark_returns = result.returns.rename("benchmark_return")
elif benchmark_kind == "zero_benchmark_variance":
benchmark_id = "000300.SH"
benchmark_returns = pd.Series(
np.zeros(len(result.returns)),
index=result.returns.index,
name="benchmark_return",
)
else:
raise AssertionError(f"unknown benchmark_kind: {benchmark_kind}")
artifact = build_research_run_artifact(
result,
run_id=run_ref.run_id,
strategy_id=run_ref.strategy_id,
strategy_name="Alpha Top 1",
strategy_version=run_ref.strategy_version,
engine_version="1.2.0",
code_revision=run_ref.code_revision,
data_snapshot_id=run_ref.dataset_snapshot_id,
calendar="CN-A",
timezone="Asia/Shanghai",
started_at="2026-01-08T10:00:00+08:00",
finished_at="2026-01-08T10:01:00+08:00",
parameters=PARAMETERS,
benchmark_id=benchmark_id,
benchmark_returns=benchmark_returns,
)
return artifact, result
def _case(
benchmark_kind: str,
) -> tuple[PerformanceEvidenceV1, ResearchRunArtifact, BacktestRunRef, BacktestEvidenceManifest]:
run_ref = _run_ref()
artifact, _ = _artifact(run_ref, benchmark_kind)
manifest = build_backtest_evidence_manifest(
run_ref,
artifact,
artifact_available_at="2026-01-08T02:05:00Z",
qualification=EvidenceQualification.CONTRACT_QUALIFIED,
)
return (
build_performance_evidence(artifact, run_ref, manifest),
artifact,
run_ref,
manifest,
)
def _metric_map(evidence: PerformanceEvidenceV1) -> dict[str, Any]:
return {metric.key: metric for metric in evidence.metrics}
def _mutate_frozen(value: Any, field: str, replacement: object) -> Any:
changed = copy.copy(value)
object.__setattr__(changed, field, replacement)
return changed
def _assert_error(
error: pytest.ExceptionInfo[PerformanceEvidenceError],
code: PerformanceEvidenceErrorCode,
path: str,
) -> None:
assert error.value.code is code
assert error.value.path == path
def test_present_evidence_is_deterministic_content_addressed_and_three_party_closed() -> None:
first, artifact, run_ref, manifest = _case("estimable")
second = build_performance_evidence(artifact, run_ref, manifest)
assert first == second
assert first.schema_version == PERFORMANCE_EVIDENCE_SCHEMA_VERSION
assert first.performance_evidence_id.startswith("rhperformanceevidencev1:sha256:")
assert first.document_sha256.startswith("sha256:")
assert first.authority == "quant_engine"
assert first.scope == "offline_research_only"
assert first.run_id == first.backtest_run_ref_id == run_ref.run_id == manifest.run_id
assert first.backtest_evidence_manifest_id == manifest.manifest_id
assert first.backtest_evidence_manifest_evidence_digest == manifest.evidence_digest
assert first.backtest_evidence_qualification == "contract_qualified"
assert first.research_artifact_content_digest == f"sha256:{artifact.content_sha256}"
assert first.performance_table_logical_name == "performance"
assert first.performance_table_row_count == 1
assert first.performance_row_digest.startswith("sha256:")
assert first.benchmark_series_digest is not None
assert first.canonical_bytes() == first.to_json().encode("utf-8")
assert not first.canonical_bytes().endswith(b"\n")
document_payload = first.to_dict()
document_payload.pop("document_sha256")
expected_document = json.dumps(
document_payload,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
).encode("utf-8")
assert _sha256(expected_document) == first.document_sha256
assert PerformanceEvidenceV1.from_dict(
first.to_dict(),
artifact=artifact,
run_ref=run_ref,
evidence_manifest=manifest,
) == first
def test_methodology_and_metrics_bind_the_actual_artifact_builder_path() -> None:
evidence, artifact, _, _ = _case("estimable")
result = _backtest_result()
expected_absolute = summary(result.returns, rf=0.0)
benchmark = artifact.nav.set_index("trade_date")["benchmark_return"]
benchmark.index = result.returns.index
expected_relative = benchmark_summary(
result.returns,
benchmark,
risk_free_daily=0.0,
annualization=TRADING_DAYS_PER_YEAR,
)
metrics = _metric_map(evidence)
assert evidence.methodology.methodology_id == PERFORMANCE_METHODOLOGY_ID
assert evidence.metric_schema_id == PERFORMANCE_METRIC_SCHEMA_ID
assert evidence.methodology.return_type == "simple"
assert evidence.methodology.source_frequency == "1d"
assert evidence.methodology.periods_per_year == TRADING_DAYS_PER_YEAR == 252
assert evidence.methodology.annual_risk_free == 0.0
assert evidence.methodology.benchmark_risk_free_daily == 0.0
assert evidence.methodology.benchmark_alignment == "exact_session_index"
assert metrics["annualized_return"].value == pytest.approx(
expected_absolute["ann_return"]
)
assert metrics["sharpe_ratio"].value == pytest.approx(expected_absolute["sharpe"])
assert metrics["tracking_error"].value == pytest.approx(
expected_relative["tracking_error"]
)
assert metrics["alpha"].value == pytest.approx(expected_relative["alpha"])
assert all(metric.methodology_id == PERFORMANCE_METHODOLOGY_ID for metric in metrics.values())
assert all(metric.metric_schema_id == PERFORMANCE_METRIC_SCHEMA_ID for metric in metrics.values())
def test_relative_metric_availability_is_closed_for_present_absent_and_unestimable() -> None:
present, *_ = _case("estimable")
absent, *_ = _case("absent")
zero_active, *_ = _case("zero_active_variance")
zero_benchmark, *_ = _case("zero_benchmark_variance")
present_metrics = _metric_map(present)
assert all(
present_metrics[key].availability is PerformanceMetricAvailability.AVAILABLE
for key in ("tracking_error", "information_ratio", "alpha", "beta")
)
absent_metrics = _metric_map(absent)
assert absent.benchmark_series_digest is None
assert absent.benchmark_id == ""
assert absent.benchmark_alignment_policy == "none"
assert all(
absent_metrics[key].value is None
and absent_metrics[key].availability
is PerformanceMetricAvailability.BENCHMARK_ABSENT
for key in ("tracking_error", "information_ratio", "alpha", "beta")
)
zero_active_metrics = _metric_map(zero_active)
assert zero_active_metrics["tracking_error"].value == pytest.approx(0.0)
assert (
zero_active_metrics["information_ratio"].availability
is PerformanceMetricAvailability.NOT_ESTIMABLE_ACTIVE_VARIANCE
)
assert zero_active_metrics["information_ratio"].value is None
zero_benchmark_metrics = _metric_map(zero_benchmark)
assert np.isfinite(zero_benchmark_metrics["tracking_error"].value)
for key in ("alpha", "beta"):
assert zero_benchmark_metrics[key].value is None
assert (
zero_benchmark_metrics[key].availability
is PerformanceMetricAvailability.NOT_ESTIMABLE_BENCHMARK_VARIANCE
)
def test_golden_covers_present_absent_and_both_unestimable_states() -> None:
expected = {
"schema_version": 1,
"source_commit": "a724e1e57a99d1304a932d01ee836bac56c5c15c",
"source_tree": "4774e88442d25bf79a54eab3d7106ff4d0ba9603",
"cases": {
name: _case(name)[0].to_dict()
for name in (
"estimable",
"zero_active_variance",
"zero_benchmark_variance",
"absent",
)
},
}
assert json.loads(PERFORMANCE_FIXTURE.read_text(encoding="utf-8")) == expected
@pytest.mark.parametrize(
("owner", "field", "replacement", "code", "path"),
[
(
"run_ref",
"run_id",
"rhbacktestrunv1:sha256:" + "0" * 64,
PerformanceEvidenceErrorCode.IDENTITY_MISMATCH,
"$.backtest_run_ref.run_id",
),
(
"manifest",
"manifest_id",
"rhbacktestevidencev1:sha256:" + "0" * 64,
PerformanceEvidenceErrorCode.EVIDENCE_MISMATCH,
"$.backtest_evidence_manifest.manifest_id",
),
(
"manifest",
"qualification",
EvidenceQualification.EXPLORATORY,
PerformanceEvidenceErrorCode.AUTHORITY_REJECTED,
"$.backtest_evidence_manifest.qualification",
),
],
)
def test_owner_identity_and_authority_mismatches_fail_closed(
owner: str,
field: str,
replacement: object,
code: PerformanceEvidenceErrorCode,
path: str,
) -> None:
_, artifact, run_ref, manifest = _case("estimable")
changed_run_ref = _mutate_frozen(run_ref, field, replacement) if owner == "run_ref" else run_ref
changed_manifest = (
_mutate_frozen(manifest, field, replacement) if owner == "manifest" else manifest
)
with pytest.raises(PerformanceEvidenceError) as rejected:
build_performance_evidence(artifact, changed_run_ref, changed_manifest)
_assert_error(rejected, code, path)
def test_performance_table_row_and_benchmark_digest_mismatches_fail_closed() -> None:
evidence, artifact, run_ref, manifest = _case("estimable")
performance = artifact.performance
performance.loc[0, "n_days"] += 1
changed_artifact = replace(artifact, _performance=performance)
with pytest.raises(PerformanceEvidenceError) as table_mismatch:
build_performance_evidence(changed_artifact, run_ref, manifest)
_assert_error(
table_mismatch,
PerformanceEvidenceErrorCode.EVIDENCE_MISMATCH,
"$.artifact.tables.performance.content_digest",
)
payload = evidence.to_dict()
payload["benchmark_series_digest"] = "sha256:" + "0" * 64
with pytest.raises(PerformanceEvidenceError) as benchmark_mismatch:
PerformanceEvidenceV1.from_dict(
payload,
artifact=artifact,
run_ref=run_ref,
evidence_manifest=manifest,
)
_assert_error(
benchmark_mismatch,
PerformanceEvidenceErrorCode.BENCHMARK_INVALID,
"$.benchmark_series_digest",
)
def test_manifest_closure_covers_non_performance_artifact_tables() -> None:
_, artifact, run_ref, manifest = _case("estimable")
nav = artifact.nav
nav.loc[0, "nav"] += 0.01
changed_artifact = replace(artifact, _nav=nav)
with pytest.raises(PerformanceEvidenceError) as rejected:
build_performance_evidence(changed_artifact, run_ref, manifest)
_assert_error(
rejected,
PerformanceEvidenceErrorCode.EVIDENCE_MISMATCH,
"$.artifact.tables.nav.content_digest",
)
def test_row_and_benchmark_mutations_change_their_digests_and_document_identity() -> None:
original, artifact, run_ref, _ = _case("estimable")
performance = artifact.performance
performance.loc[0, "sharpe"] += 0.01
changed_performance_artifact = replace(artifact, _performance=performance)
changed_performance_manifest = build_backtest_evidence_manifest(
run_ref,
changed_performance_artifact,
artifact_available_at="2026-01-08T02:05:00Z",
)
changed_performance = build_performance_evidence(
changed_performance_artifact,
run_ref,
changed_performance_manifest,
)
assert changed_performance.performance_row_digest != original.performance_row_digest
assert changed_performance.performance_evidence_id != original.performance_evidence_id
nav = artifact.nav
nav.loc[0, "benchmark_nav"] += 0.01
changed_benchmark_artifact = replace(artifact, _nav=nav)
changed_benchmark_manifest = build_backtest_evidence_manifest(
run_ref,
changed_benchmark_artifact,
artifact_available_at="2026-01-08T02:05:00Z",
)
changed_benchmark = build_performance_evidence(
changed_benchmark_artifact,
run_ref,
changed_benchmark_manifest,
)
assert changed_benchmark.benchmark_series_digest != original.benchmark_series_digest
assert changed_benchmark.performance_row_digest == original.performance_row_digest
assert changed_benchmark.performance_evidence_id != original.performance_evidence_id
def test_relative_metric_null_reasons_cannot_be_invented() -> None:
_, artifact, run_ref, _ = _case("estimable")
performance = artifact.performance
performance.loc[0, "alpha"] = float("nan")
changed_artifact = replace(artifact, _performance=performance)
changed_manifest = build_backtest_evidence_manifest(
run_ref,
changed_artifact,
artifact_available_at="2026-01-08T02:05:00Z",
)
with pytest.raises(PerformanceEvidenceError) as false_alpha_domain:
build_performance_evidence(changed_artifact, run_ref, changed_manifest)
_assert_error(
false_alpha_domain,
PerformanceEvidenceErrorCode.METRIC_INVALID,
"$.metrics.alpha.value",
)
_, absent_artifact, absent_run_ref, _ = _case("absent")
absent_performance = absent_artifact.performance
absent_performance.loc[0, "tracking_error"] = 0.0
changed_absent = replace(absent_artifact, _performance=absent_performance)
changed_absent_manifest = build_backtest_evidence_manifest(
absent_run_ref,
changed_absent,
artifact_available_at="2026-01-08T02:05:00Z",
)
with pytest.raises(PerformanceEvidenceError) as false_absence:
build_performance_evidence(
changed_absent,
absent_run_ref,
changed_absent_manifest,
)
_assert_error(
false_absence,
PerformanceEvidenceErrorCode.BENCHMARK_INVALID,
"$.metrics.tracking_error.availability",
)
def test_artifact_builder_enforces_strict_benchmark_session_alignment() -> None:
run_ref = _run_ref()
result = _backtest_result()
misaligned = pd.Series(
[0.0, 0.01, -0.01, 0.02],
index=result.returns.index.shift(1, freq="B"),
)
with pytest.raises(ValueError, match="matching indexes"):
build_research_run_artifact(
result,
run_id=run_ref.run_id,
strategy_id=run_ref.strategy_id,
strategy_name="Alpha Top 1",
strategy_version=run_ref.strategy_version,
engine_version="1.2.0",
code_revision=run_ref.code_revision,
data_snapshot_id=run_ref.dataset_snapshot_id,
calendar="CN-A",
timezone="Asia/Shanghai",
started_at="2026-01-08T10:00:00+08:00",
finished_at="2026-01-08T10:01:00+08:00",
parameters=PARAMETERS,
benchmark_id="000300.SH",
benchmark_returns=misaligned,
)
@pytest.mark.parametrize(
("column", "value", "path"),
[
("total_ret", -1.01, "$.metrics.total_return.value"),
("ann_ret", -1.01, "$.metrics.annualized_return.value"),
("ann_volatility", -0.01, "$.metrics.annualized_volatility.value"),
("max_dd", 0.01, "$.metrics.maximum_drawdown.value"),
("win_rate", 1.01, "$.metrics.win_rate.value"),
("tracking_error", -0.01, "$.metrics.tracking_error.value"),
("n_trades", True, "$.metrics.trade_count.value"),
],
)
def test_metric_domains_reject_invalid_source_values(
column: str,
value: object,
path: str,
) -> None:
_, artifact, run_ref, _ = _case("estimable")
performance = artifact.performance.astype(object)
performance.at[0, column] = value
changed_artifact = replace(artifact, _performance=performance)
changed_manifest = build_backtest_evidence_manifest(
run_ref,
changed_artifact,
artifact_available_at="2026-01-08T02:05:00Z",
)
with pytest.raises(PerformanceEvidenceError) as rejected:
build_performance_evidence(changed_artifact, run_ref, changed_manifest)
_assert_error(rejected, PerformanceEvidenceErrorCode.METRIC_INVALID, path)
def test_closed_parser_rejects_unknown_non_ascii_non_finite_bool_and_unsafe_integer() -> None:
evidence, artifact, run_ref, manifest = _case("estimable")
mutations: list[tuple[dict[str, Any], PerformanceEvidenceErrorCode, str]] = []
unknown = evidence.to_dict()
unknown["unexpected"] = "value"
mutations.append((unknown, PerformanceEvidenceErrorCode.TYPE_ERROR, "$.unexpected"))
non_ascii = evidence.to_dict()
non_ascii["métric"] = "value"
mutations.append((non_ascii, PerformanceEvidenceErrorCode.TYPE_ERROR, "$.métric"))
non_finite = evidence.to_dict()
non_finite["metrics"][0]["value"] = float("inf")
mutations.append(
(non_finite, PerformanceEvidenceErrorCode.METRIC_INVALID, "$.metrics[0].value")
)
bool_number = evidence.to_dict()
bool_number["methodology"]["periods_per_year"] = True
mutations.append(
(
bool_number,
PerformanceEvidenceErrorCode.METHODOLOGY_MISMATCH,
"$.methodology.periods_per_year",
)
)
unsafe = evidence.to_dict()
unsafe["performance_table_row_count"] = 2**53
mutations.append(
(
unsafe,
PerformanceEvidenceErrorCode.EVIDENCE_MISMATCH,
"$.performance_table_row_count",
)
)
for payload, code, path in mutations:
with pytest.raises(PerformanceEvidenceError) as rejected:
PerformanceEvidenceV1.from_dict(
payload,
artifact=artifact,
run_ref=run_ref,
evidence_manifest=manifest,
)
_assert_error(rejected, code, path)
def test_public_mapping_has_no_raw_inputs_storage_or_runtime_authority() -> None:
evidence, *_ = _case("estimable")
payload = evidence.to_dict()
serialized = evidence.to_json().lower()
forbidden_keys = {
"parameters",
"params_json",
"returns",
"nav",
"benchmark_series",
"table_bytes",
"locator",
"uri",
"credential",
"decision_eligible",
"publication_eligible",
"paper_trading",
"live_trading",
"investment_advice",
}
def keys(value: object) -> set[str]:
if isinstance(value, dict):
return set(value) | {key for item in value.values() for key in keys(item)}
if isinstance(value, list):
return {key for item in value for key in keys(item)}
return set()
assert not (keys(payload) & forbidden_keys)
for token in ("postgres://", "mysql://", "s3://", "credential", "broker"):
assert token not in serialized
+31 -1
View File
@@ -952,6 +952,37 @@ def test_architecture_dependency_no_copy_and_authority_boundaries() -> None:
assert not any(name.startswith(("research_results", "research_platform")) for name in imports)
for candidate in ("riskfolio", "pyp", "skfolio", "cvxportfolio"):
assert candidate not in source.lower()
artifact_source = (ROOT / "src" / "quant_engine" / "artifact.py").read_text(
encoding="utf-8"
)
artifact_tree = ast.parse(artifact_source)
forbidden_artifact_authority_symbols = {
"PortfolioDecision",
"RiskAssessment",
"build_portfolio_decision",
"assess_portfolio_risk",
}
artifact_imports = {
alias.name
for node in ast.walk(artifact_tree)
if isinstance(node, ast.Import)
for alias in node.names
} | {
node.module or ""
for node in ast.walk(artifact_tree)
if isinstance(node, ast.ImportFrom)
}
artifact_names = {
node.id for node in ast.walk(artifact_tree) if isinstance(node, ast.Name)
} | {
node.attr for node in ast.walk(artifact_tree) if isinstance(node, ast.Attribute)
}
assert "quant_engine.portfolio_risk_contracts" not in artifact_imports
assert not forbidden_artifact_authority_symbols & artifact_names
assert all(
token not in artifact_source
for token in {"portfolio_risk_contracts", *forbidden_artifact_authority_symbols}
)
for owner_path in (
ROOT / "src" / "quant_engine" / "governed_pipeline.py",
ROOT / "src" / "quant_engine" / "artifact.py",
@@ -989,7 +1020,6 @@ def test_architecture_dependency_no_copy_and_authority_boundaries() -> None:
def test_read_only_owner_dependency_lock_and_ci_hashes_match_baseline() -> None:
expected = {
"src/quant_engine/governed_pipeline.py": "3b334f340898db78ed869375ab532f156e8c1fee595a8318f544bebdd391049d",
"src/quant_engine/artifact.py": "e15feec412d3bfff10d8f21ca20813fc65cabc0703940371ed661896147bc379",
"src/quant_engine/portfolio_construction.py": "e93d71da8d61b2047c19d4b99dace934a8cbc96d8d2b150ad62a9ceebd9163d4",
"src/quant_engine/portfolio_decomp.py": "1a4f9f9aac2c46bf6ed2826d1b0d1723f06e3ce7c4b3f6479e098cbbd135bea6",
"src/quant_engine/risk.py": "4a66c312d517d40f6f67bb71f438523e135645624ae78d49fa9c0fda2c02074e",