feat: preserve Quant OS target-package vertical slice
This commit is contained in:
+507
-47
@@ -18,10 +18,27 @@ PROJECT = Path(__file__).resolve().parents[1]
|
||||
DEFAULT_OUTPUT = PROJECT / "status" / "status-data.js"
|
||||
GLOBAL_NAME = "QUANT_OS_PUBLIC_STATUS"
|
||||
SCHEMA_VERSION = 1
|
||||
REACHABILITY_PATH = (
|
||||
"releases/quant60-research-candidate-v1/reachability.json"
|
||||
)
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_PATH = (
|
||||
"evidence/joinquant/TP-20240311-795dcfba/"
|
||||
"2457a7c39a276e09e0fabf99e28978e1/run.json"
|
||||
)
|
||||
JOINQUANT_TARGET_PACKAGE_DOC_PATH = (
|
||||
"docs/JOINQUANT_TARGET_PACKAGE_EVIDENCE_2026-07-26.md"
|
||||
)
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_ID = "2457a7c39a276e09e0fabf99e28978e1"
|
||||
JOINQUANT_TARGET_PACKAGE_OBSERVED_AT = "2026-07-26T08:50:15Z"
|
||||
JOINQUANT_TARGET_PACKAGE_BUNDLE_SHA256 = (
|
||||
"0586930ddc483f4489f09b562f4d4232b458b703e6a1194af809b707211be8c4"
|
||||
)
|
||||
|
||||
SOURCE_PATHS: Tuple[str, ...] = (
|
||||
"gate_scorecard.json",
|
||||
"dist/bundle_manifest.json",
|
||||
REACHABILITY_PATH,
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_PATH,
|
||||
"configs/baseline.json",
|
||||
"README.md",
|
||||
"docs/ARCHITECTURE.md",
|
||||
@@ -29,8 +46,10 @@ SOURCE_PATHS: Tuple[str, ...] = (
|
||||
"docs/PLATFORM_MATRIX.md",
|
||||
"docs/CROSS_ENGINE_CONSISTENCY.md",
|
||||
"docs/JOINQUANT_HOSTED_EVIDENCE_2026-07-26.md",
|
||||
JOINQUANT_TARGET_PACKAGE_DOC_PATH,
|
||||
"docs/TUSHARE_LOCAL_DATA.md",
|
||||
"runbooks/PLATFORM_DEPLOYMENT.md",
|
||||
"tools/build_release_reachability.py",
|
||||
"tools/build_public_status.py",
|
||||
)
|
||||
|
||||
@@ -245,6 +264,287 @@ def _validate_bundle_manifest(
|
||||
return public_artifacts
|
||||
|
||||
|
||||
def _validate_reachability_manifest(
|
||||
project: Path, manifest: Mapping[str, Any]
|
||||
) -> Dict[str, Any]:
|
||||
source_root = project / "src"
|
||||
inserted = str(source_root) not in sys.path
|
||||
if inserted:
|
||||
sys.path.insert(0, str(source_root))
|
||||
try:
|
||||
from quant60.release_reachability import ( # pylint: disable=import-outside-toplevel
|
||||
ReleaseReachabilityError,
|
||||
validate_release_reachability,
|
||||
)
|
||||
|
||||
try:
|
||||
manifest = validate_release_reachability(
|
||||
manifest,
|
||||
repository_root=project,
|
||||
expected_release_id="quant60-research-candidate-v1",
|
||||
)
|
||||
except ReleaseReachabilityError as exc:
|
||||
raise PublicStatusError(
|
||||
f"release reachability manifest failed canonical verification: {exc}"
|
||||
) from exc
|
||||
finally:
|
||||
if inserted:
|
||||
sys.path.remove(str(source_root))
|
||||
|
||||
expected_layers = {"universe", "alpha", "portfolio", "risk", "execution"}
|
||||
expected_capabilities = {
|
||||
"implemented",
|
||||
"unit_tested",
|
||||
"local_entrypoint_reachable",
|
||||
"jq_entrypoint_reachable",
|
||||
"qmt_entrypoint_reachable",
|
||||
"real_platform_observed",
|
||||
}
|
||||
declared_sha = str(manifest.get("manifest_sha256", ""))
|
||||
body = {
|
||||
key: value
|
||||
for key, value in manifest.items()
|
||||
if key != "manifest_sha256"
|
||||
}
|
||||
body_bytes = json.dumps(
|
||||
body,
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
separators=(",", ":"),
|
||||
).encode("utf-8")
|
||||
actual_sha = _sha256_bytes(body_bytes)
|
||||
if not re.fullmatch(r"[0-9a-f]{64}", declared_sha) or declared_sha != actual_sha:
|
||||
raise PublicStatusError("release reachability manifest self-hash is invalid")
|
||||
|
||||
layers = manifest.get("layers")
|
||||
if not isinstance(layers, dict) or set(layers) != expected_layers:
|
||||
raise PublicStatusError(
|
||||
"release reachability manifest must contain the canonical five layers"
|
||||
)
|
||||
calculated_summary: Dict[str, bool] = {}
|
||||
real_platforms: set[str] = set()
|
||||
real_platform_observed_layers: set[str] = set()
|
||||
for capability in sorted(expected_capabilities):
|
||||
statuses: List[bool] = []
|
||||
for layer in sorted(expected_layers):
|
||||
claims = layers[layer]
|
||||
if not isinstance(claims, dict) or set(claims) != expected_capabilities:
|
||||
raise PublicStatusError(
|
||||
f"release reachability claims are incomplete for {layer}"
|
||||
)
|
||||
claim = claims[capability]
|
||||
if not isinstance(claim, dict) or not isinstance(
|
||||
claim.get("status"), bool
|
||||
):
|
||||
raise PublicStatusError(
|
||||
f"release reachability status is invalid for {layer}.{capability}"
|
||||
)
|
||||
artifacts = claim.get("artifacts")
|
||||
if not isinstance(artifacts, list):
|
||||
raise PublicStatusError(
|
||||
f"release reachability artifacts are invalid for {layer}.{capability}"
|
||||
)
|
||||
status = claim["status"]
|
||||
if status != bool(artifacts):
|
||||
raise PublicStatusError(
|
||||
f"release reachability evidence/status mismatch for "
|
||||
f"{layer}.{capability}"
|
||||
)
|
||||
for index, artifact in enumerate(artifacts):
|
||||
if not isinstance(artifact, dict):
|
||||
raise PublicStatusError(
|
||||
f"release reachability artifact is invalid for "
|
||||
f"{layer}.{capability}[{index}]"
|
||||
)
|
||||
path = _safe_repo_path(
|
||||
artifact.get("path"),
|
||||
label=f"{layer}.{capability}[{index}].path",
|
||||
)
|
||||
_verify_file_hash(project, path, str(artifact.get("sha256", "")))
|
||||
if capability == "real_platform_observed":
|
||||
real_platforms.add(str(artifact.get("platform", "")))
|
||||
real_platform_observed_layers.add(layer)
|
||||
statuses.append(status)
|
||||
calculated_summary[f"all_layers_{capability}"] = all(statuses)
|
||||
|
||||
summary = manifest.get("summary")
|
||||
if not isinstance(summary, dict) or summary != calculated_summary:
|
||||
raise PublicStatusError(
|
||||
"release reachability summary does not match per-layer claims"
|
||||
)
|
||||
if (
|
||||
real_platforms != {"joinquant"}
|
||||
or real_platform_observed_layers != {"execution"}
|
||||
or calculated_summary["all_layers_real_platform_observed"]
|
||||
):
|
||||
raise PublicStatusError(
|
||||
"current release may claim only JoinQuant execution observation"
|
||||
)
|
||||
release_id = str(manifest.get("release_id", ""))
|
||||
if release_id != "quant60-research-candidate-v1":
|
||||
raise PublicStatusError("unexpected release reachability release_id")
|
||||
return {
|
||||
"releaseId": release_id,
|
||||
"manifest": REACHABILITY_PATH,
|
||||
"manifestSha256": declared_sha,
|
||||
"summary": calculated_summary,
|
||||
"realPlatformsObserved": sorted(
|
||||
platform for platform in real_platforms if platform
|
||||
),
|
||||
"realPlatformObservedLayers": sorted(real_platform_observed_layers),
|
||||
}
|
||||
|
||||
|
||||
def _validate_joinquant_target_package_run(
|
||||
project: Path,
|
||||
run: Mapping[str, Any],
|
||||
) -> Dict[str, Any]:
|
||||
"""Validate the narrow, redacted hosted execution observation."""
|
||||
|
||||
if run.get("record_type") != "joinquant_target_package_execution_smoke":
|
||||
raise PublicStatusError("unexpected JoinQuant TargetPackage run type")
|
||||
if run.get("platform") != "joinquant" or run.get("status") != "completed":
|
||||
raise PublicStatusError("JoinQuant TargetPackage run is not completed")
|
||||
if (
|
||||
run.get("platform_evidence_class") != "real_platform_runtime"
|
||||
or run.get("input_evidence_class") != "synthetic-research"
|
||||
or run.get("performance_claim") is not False
|
||||
):
|
||||
raise PublicStatusError(
|
||||
"JoinQuant TargetPackage evidence classes are unsafe"
|
||||
)
|
||||
if run.get("run_id") != JOINQUANT_TARGET_PACKAGE_RUN_ID:
|
||||
raise PublicStatusError("unexpected JoinQuant TargetPackage run identity")
|
||||
if run.get("observed_at") != JOINQUANT_TARGET_PACKAGE_OBSERVED_AT:
|
||||
raise PublicStatusError("unexpected JoinQuant TargetPackage observation time")
|
||||
|
||||
backtest = run.get("backtest")
|
||||
if not isinstance(backtest, dict):
|
||||
raise PublicStatusError("JoinQuant TargetPackage backtest must be an object")
|
||||
expected_url = (
|
||||
"https://www.joinquant.com/algorithm/backtest/detail?backtestId="
|
||||
+ JOINQUANT_TARGET_PACKAGE_RUN_ID
|
||||
)
|
||||
expected_backtest = {
|
||||
"id": JOINQUANT_TARGET_PACKAGE_RUN_ID,
|
||||
"url": expected_url,
|
||||
"start_date": "2024-03-11",
|
||||
"end_date": "2024-03-13",
|
||||
"initial_capital_cny": 1_000_000,
|
||||
"frequency": "day",
|
||||
"python": "Python3",
|
||||
"benchmark": "000905.XSHG",
|
||||
"timezone": "Asia/Shanghai",
|
||||
}
|
||||
if backtest != expected_backtest:
|
||||
raise PublicStatusError("JoinQuant TargetPackage settings drifted")
|
||||
|
||||
identity = run.get("artifact_identity")
|
||||
if not isinstance(identity, dict):
|
||||
raise PublicStatusError("JoinQuant TargetPackage identity must be an object")
|
||||
expected_identity = {
|
||||
"bundle_sha256": JOINQUANT_TARGET_PACKAGE_BUNDLE_SHA256,
|
||||
"browser_snapshot_sha256": JOINQUANT_TARGET_PACKAGE_BUNDLE_SHA256,
|
||||
"exact_browser_match": True,
|
||||
"bundle_manifest_sha256": (
|
||||
"91f4b4dc0bdd0d9f99b3466c830600e2678be78dd991d4499a4154bffec8597a"
|
||||
),
|
||||
"portable_core_sha256": (
|
||||
"f9de9f18e4008bb0fc80edb0b21cae6ea06a61828d89e9b7c11057f98225fc19"
|
||||
),
|
||||
"wrapper_sha256": (
|
||||
"0c672b64665b7c1d4409ba288b00d1608e976800af3a4f9a6467767ce4def592"
|
||||
),
|
||||
}
|
||||
if identity != expected_identity:
|
||||
raise PublicStatusError("JoinQuant TargetPackage artifact identity drifted")
|
||||
|
||||
target_package = run.get("target_package")
|
||||
if not isinstance(target_package, dict):
|
||||
raise PublicStatusError("JoinQuant TargetPackage identity is missing")
|
||||
if (
|
||||
target_package.get("package_id") != "TP-20240311-795dcfba"
|
||||
or target_package.get("evidence_class") != "synthetic-research"
|
||||
or target_package.get("package_sha256")
|
||||
!= "baa15c8156aa6cb54d3775d0cd562613a9d0a4f15b0c39f2a60e0f8b8c6f1f3a"
|
||||
or target_package.get("tape_sha256")
|
||||
!= "5383c376951637b8d4b1ca42fc6db80347abda74c0181c0f70d6c411fb97ea64"
|
||||
):
|
||||
raise PublicStatusError("JoinQuant TargetPackage lineage drifted")
|
||||
|
||||
sessions = run.get("session_observations")
|
||||
if not isinstance(sessions, list) or [
|
||||
(item.get("date"), item.get("event"), item.get("orders"), item.get("fills"))
|
||||
for item in sessions
|
||||
if isinstance(item, dict)
|
||||
] != [
|
||||
("2024-03-11", "TARGET_PACKAGE_NOOP", 0, 0),
|
||||
("2024-03-12", "TARGET_PACKAGE_HIT", 3, 3),
|
||||
("2024-03-13", "TARGET_PACKAGE_NOOP", 0, 0),
|
||||
]:
|
||||
raise PublicStatusError("JoinQuant TargetPackage session evidence drifted")
|
||||
if run.get("counts") != {
|
||||
"orders": 3,
|
||||
"fills": 3,
|
||||
"skipped_orders": 0,
|
||||
}:
|
||||
raise PublicStatusError("JoinQuant TargetPackage order/fill counts drifted")
|
||||
|
||||
boundary = run.get("claim_boundary")
|
||||
if not isinstance(boundary, dict):
|
||||
raise PublicStatusError("JoinQuant TargetPackage claim boundary is missing")
|
||||
required_false = (
|
||||
"upstream_layers_real_platform_observed",
|
||||
"authorized_real_data_oos_observed",
|
||||
"qmt_peer_observed",
|
||||
"same_input_cross_engine_parity_observed",
|
||||
"all_five_layers_real_platform_observed",
|
||||
"g9_passed",
|
||||
"baseline_60_passed",
|
||||
"release_verified",
|
||||
"investment_value_claim",
|
||||
)
|
||||
if boundary.get("real_platform_observed_layers") != ["execution"] or any(
|
||||
boundary.get(field) is not False for field in required_false
|
||||
):
|
||||
raise PublicStatusError(
|
||||
"JoinQuant TargetPackage run overclaims its evidence boundary"
|
||||
)
|
||||
performance = run.get("performance")
|
||||
if (
|
||||
not isinstance(performance, dict)
|
||||
or performance.get("investment_value_claim") is not False
|
||||
or performance.get("scope") != "three-session execution wiring smoke only"
|
||||
):
|
||||
raise PublicStatusError(
|
||||
"JoinQuant TargetPackage performance boundary is unsafe"
|
||||
)
|
||||
|
||||
path = _safe_repo_path(
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_PATH,
|
||||
label="JoinQuant TargetPackage run",
|
||||
)
|
||||
if not (project / path).is_file():
|
||||
raise PublicStatusError("tracked JoinQuant TargetPackage run is missing")
|
||||
return {
|
||||
"runId": JOINQUANT_TARGET_PACKAGE_RUN_ID,
|
||||
"observedAt": JOINQUANT_TARGET_PACKAGE_OBSERVED_AT,
|
||||
"marketDataFrom": backtest["start_date"],
|
||||
"marketDataThrough": backtest["end_date"],
|
||||
"bundleSha256": identity["bundle_sha256"],
|
||||
"packageId": target_package["package_id"],
|
||||
"evidenceClass": target_package["evidence_class"],
|
||||
"orders": 3,
|
||||
"fills": 3,
|
||||
"observedLayers": ["execution"],
|
||||
"allFiveLayersObserved": False,
|
||||
"qmtPeerObserved": False,
|
||||
"g9Passed": False,
|
||||
"baseline60Passed": False,
|
||||
"investmentValueClaim": False,
|
||||
}
|
||||
|
||||
|
||||
def _extract_test_summary(facts: Sequence[Any]) -> Tuple[int | None, int | None]:
|
||||
for fact in facts:
|
||||
text = str(fact)
|
||||
@@ -288,7 +588,13 @@ def _platform_status(name: str) -> str:
|
||||
def _platform_evidence_links(name: str) -> List[str]:
|
||||
links = ["platform-matrix"]
|
||||
if "JoinQuant" in name:
|
||||
links.append("joinquant-hosted-evidence")
|
||||
links.extend(
|
||||
(
|
||||
"joinquant-hosted-evidence",
|
||||
"joinquant-target-package-evidence",
|
||||
"joinquant-target-package-run",
|
||||
)
|
||||
)
|
||||
if "Qlib" in name or "Tushare" in name:
|
||||
links.append("tushare-data")
|
||||
if "QMT" in name or "XtTrader" in name:
|
||||
@@ -337,6 +643,12 @@ def _build_evidence(project: Path) -> List[Dict[str, Any]]:
|
||||
"dist/bundle_manifest.json",
|
||||
"machine_record",
|
||||
),
|
||||
(
|
||||
"release-reachability",
|
||||
"Five-layer release reachability manifest",
|
||||
REACHABILITY_PATH,
|
||||
"machine_record",
|
||||
),
|
||||
("readme", "Quant OS verification guide", "README.md", "documentation"),
|
||||
(
|
||||
"architecture",
|
||||
@@ -364,10 +676,22 @@ def _build_evidence(project: Path) -> List[Dict[str, Any]]:
|
||||
),
|
||||
(
|
||||
"joinquant-hosted-evidence",
|
||||
"JoinQuant hosted smoke boundary",
|
||||
"JoinQuant hosted momentum smoke boundary",
|
||||
"docs/JOINQUANT_HOSTED_EVIDENCE_2026-07-26.md",
|
||||
"runtime_evidence",
|
||||
),
|
||||
(
|
||||
"joinquant-target-package-evidence",
|
||||
"JoinQuant TargetPackage execution evidence boundary",
|
||||
JOINQUANT_TARGET_PACKAGE_DOC_PATH,
|
||||
"runtime_evidence",
|
||||
),
|
||||
(
|
||||
"joinquant-target-package-run",
|
||||
"Redacted JoinQuant TargetPackage hosted run",
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_PATH,
|
||||
"machine_record",
|
||||
),
|
||||
(
|
||||
"tushare-data",
|
||||
"Tushare inventory and Qlib bridge record",
|
||||
@@ -403,14 +727,14 @@ def _build_layers() -> List[Dict[str, Any]]:
|
||||
"id": "data",
|
||||
"name": "数据与时点",
|
||||
"status": "tested",
|
||||
"claim": "不可变快照、PIT 字段合同和 Tushare→Qlib 技术链路已实现并有本地合同/运行证据。",
|
||||
"claim": "不可变快照、PIT 字段合同和 Tushare→Qlib 技术链路已有本地合同/运行证据;这些 provider-data 路径尚未接成当前 Ridge 五层候选。",
|
||||
"capabilities": [
|
||||
"JQData raw/factor/limits/paused/PIT membership/ST snapshot",
|
||||
"Tushare completed-Parquet inventory and immutable Qlib provider",
|
||||
"semantic manifest and data-version verification",
|
||||
],
|
||||
"limitations": [
|
||||
"尚无授权 JQData 真实快照与许可 lineage;Tushare 镜像仅部分完成且缺生产关键字段。"
|
||||
"尚无授权 JQData 真实快照与许可 lineage;Tushare 镜像仅部分完成且缺生产关键字段;当前五层候选仍使用 synthetic 数据。"
|
||||
],
|
||||
"evidenceLinks": ["architecture", "tushare-data", "scorecard"],
|
||||
"releaseVerified": False,
|
||||
@@ -419,52 +743,65 @@ def _build_layers() -> List[Dict[str, Any]]:
|
||||
"id": "research",
|
||||
"name": "研究与模型",
|
||||
"status": "real_runtime",
|
||||
"claim": "synthetic research pipeline 已通过测试;Qlib 0.9.7 的 momentum 与 Alpha158/LightGBM fixture 已在真实本地运行时完成。",
|
||||
"claim": "synthetic 五层研究入口能冻结 train-only Ridge ModelBundle、逐层 trace 与 TargetPackageV1;Qlib momentum 和 Alpha158/LightGBM fixture 是另外的受限研究 smoke。",
|
||||
"capabilities": [
|
||||
"PIT features, purged walk-forward and deterministic Ridge",
|
||||
"train-only preprocessing, purged walk-forward and deterministic Ridge",
|
||||
"replayable frozen ModelBundle and synthetic TargetPackageV1",
|
||||
"Qlib native momentum",
|
||||
"Qlib Alpha158, LightGBM and Recorder workflow",
|
||||
],
|
||||
"limitations": [
|
||||
"fixture 仅两只 synthetic 股票;没有授权长样本 OOS、冻结模型包或投资价值证据。"
|
||||
"候选和 Qlib fixture 均是 synthetic;尚无授权长样本 OOS、真实数据校准、平台候选观察或投资价值证据。"
|
||||
],
|
||||
"evidenceLinks": [
|
||||
"architecture",
|
||||
"platform-matrix",
|
||||
"release-reachability",
|
||||
"scorecard",
|
||||
],
|
||||
"evidenceLinks": ["architecture", "platform-matrix", "scorecard"],
|
||||
"releaseVerified": False,
|
||||
},
|
||||
{
|
||||
"id": "signal-portfolio",
|
||||
"name": "信号、组合与事前风险",
|
||||
"status": "tested",
|
||||
"claim": "Signal→Target→Order Delta 合同、成本、风险与约束目标在本地测试路径可重放。",
|
||||
"claim": "当前 synthetic 主链把 Ridge Alpha、显式成本、60 日对角 realized variance、deterministic optimizer 和 post-risk gate 接成可重放 TargetPackage。",
|
||||
"capabilities": [
|
||||
"portable momentum scoring and capped target weights",
|
||||
"lot-rounded target quantities and T+1 sellable deltas",
|
||||
"factor risk, dated cost and constrained target research",
|
||||
"explicit fee/spread/square-root-impact cost forecast",
|
||||
"diagonal realized-variance risk input and deterministic constrained target",
|
||||
"single-name, industry, gross, capacity and turnover constraints",
|
||||
"post-risk weights with hash-linked lineage",
|
||||
],
|
||||
"limitations": [
|
||||
"风险、冲击和容量尚未用授权真实数据校准;G4/G5 均未通过。"
|
||||
"factor_risk.py 与 optional CVXPY solver 未被当前主链选择;风险、冲击和容量尚未用授权真实数据校准,G4/G5 均未通过。"
|
||||
],
|
||||
"evidenceLinks": [
|
||||
"architecture",
|
||||
"release-reachability",
|
||||
"scorecard",
|
||||
],
|
||||
"evidenceLinks": ["architecture", "scorecard"],
|
||||
"releaseVerified": False,
|
||||
},
|
||||
{
|
||||
"id": "backtest",
|
||||
"name": "回测与跨引擎",
|
||||
"status": "real_runtime",
|
||||
"claim": "本地 synthetic、Qlib fixture 与一次真实 JoinQuant hosted smoke 已运行;QMT 仍只有 bundle/harness。",
|
||||
"claim": "本地 synthetic 五层候选、平台 harness 和一次真实 JoinQuant TargetPackage execution smoke 已运行;QMT 尚无真实 peer run。",
|
||||
"capabilities": [
|
||||
"local event and snapshot backtests",
|
||||
"JoinQuant hosted single-file bundle",
|
||||
"QMT built-in/qmttools backtest-only bundle",
|
||||
"fail-closed JoinQuant TargetPackage single-file consumer",
|
||||
"fail-closed QMT built-in TargetPackage backtest consumer",
|
||||
"Qlib research runners",
|
||||
],
|
||||
"limitations": [
|
||||
"没有冻结同输入的本地/聚宽/QMT 逐层对比;真实 QMT 尚未运行,G9 未通过。"
|
||||
"聚宽只观察到一个 synthetic-research TargetPackage 的消费、账户/开盘价绑定和三笔成交;无真实长样本 OOS、QMT peer 或逐层真实数据 parity,G9 未通过。"
|
||||
],
|
||||
"evidenceLinks": [
|
||||
"platform-matrix",
|
||||
"joinquant-hosted-evidence",
|
||||
"joinquant-target-package-evidence",
|
||||
"joinquant-target-package-run",
|
||||
"cross-engine",
|
||||
"release-reachability",
|
||||
"scorecard",
|
||||
],
|
||||
"releaseVerified": False,
|
||||
@@ -473,17 +810,23 @@ def _build_layers() -> List[Dict[str, Any]]:
|
||||
"id": "platforms",
|
||||
"name": "平台适配",
|
||||
"status": "real_runtime",
|
||||
"claim": "Local、Colab、JoinQuant、Qlib 有可执行入口;JoinQuant/Qlib 有受限真实运行时 smoke。",
|
||||
"claim": "Local、Colab、JoinQuant、QMT、Qlib 有入口;JoinQuant 已真实观察 synthetic-research TargetPackage 的 execution consumer,QMT 候选仍未实跑。",
|
||||
"capabilities": [
|
||||
"local and Colab zero-account smoke",
|
||||
"JQData snapshot entrypoint",
|
||||
"JoinQuant upload bundle",
|
||||
"QMT built-in and qmttools entrypoints",
|
||||
"JoinQuant momentum or explicit TargetPackage upload bundle",
|
||||
"QMT built-in TargetPackage and qmttools entrypoints",
|
||||
],
|
||||
"limitations": [
|
||||
"JQData 真实账号、QMT 客户端/数据权限及平台完整导出仍是外部前置条件。"
|
||||
"JoinQuant 没有重跑上游四层;JQData 授权真实候选、QMT 客户端/数据权限、QMT peer 导出与逐层真实数据 parity 仍是外部前置条件。"
|
||||
],
|
||||
"evidenceLinks": [
|
||||
"platform-matrix",
|
||||
"joinquant-target-package-evidence",
|
||||
"joinquant-target-package-run",
|
||||
"platform-deployment",
|
||||
"release-reachability",
|
||||
],
|
||||
"evidenceLinks": ["platform-matrix", "platform-deployment"],
|
||||
"releaseVerified": False,
|
||||
},
|
||||
{
|
||||
@@ -526,11 +869,11 @@ def _build_models() -> List[Dict[str, Any]]:
|
||||
{
|
||||
"id": "portable-momentum-v1",
|
||||
"name": "portable-momentum-v1",
|
||||
"role": "跨引擎冻结计算基线",
|
||||
"role": "平台连通性 smoke 策略",
|
||||
"status": "real_runtime",
|
||||
"claim": "共享 symbol normalization、momentum、target weight/quantity 与 order-delta 计算;已进入 JoinQuant hosted smoke 和本地 Qlib momentum 路径。",
|
||||
"claim": "共享 symbol normalization、momentum、target weight/quantity 与 order-delta 计算;2024 JoinQuant hosted run 只证明这一 smoke 路径。",
|
||||
"limitations": [
|
||||
"尚无同输入 L1–L4 真实跨引擎通过证据,不是已验证的生产 champion。"
|
||||
"不是 Ridge/TargetPackage Baseline 候选;旧 hosted run 不得用于候选或 G9 计分。"
|
||||
],
|
||||
"evidenceLinks": [
|
||||
"architecture",
|
||||
@@ -543,13 +886,18 @@ def _build_models() -> List[Dict[str, Any]]:
|
||||
{
|
||||
"id": "ridge-challenger",
|
||||
"name": "Deterministic Ridge",
|
||||
"role": "synthetic 研究候选",
|
||||
"role": "synthetic 五层 Baseline 研究候选",
|
||||
"status": "tested",
|
||||
"claim": "purged walk-forward research pipeline 中可确定性训练和评估。",
|
||||
"claim": "train-only 预处理、系数、截距、训练截止和 lineage 可冻结为可重放 ModelBundle;其 synthetic TargetPackageV1 已被真实 JoinQuant execution consumer 消费并成交。",
|
||||
"limitations": [
|
||||
"只在 synthetic 研究路径验证;无真实 OOS、versioned model bundle 或跨平台推理验证。"
|
||||
"JoinQuant 只观察执行边界,未重跑上游四层;无授权真实 OOS、真实校准、QMT peer 或投资价值证据。"
|
||||
],
|
||||
"evidenceLinks": [
|
||||
"architecture",
|
||||
"platform-matrix",
|
||||
"joinquant-target-package-evidence",
|
||||
"joinquant-target-package-run",
|
||||
],
|
||||
"evidenceLinks": ["architecture", "platform-matrix"],
|
||||
"investmentValueClaim": False,
|
||||
"releaseVerified": False,
|
||||
},
|
||||
@@ -570,9 +918,15 @@ def _build_models() -> List[Dict[str, Any]]:
|
||||
|
||||
|
||||
def _build_next_actions(scorecard: Mapping[str, Any]) -> List[Dict[str, Any]]:
|
||||
missing = scorecard.get("current_delivery", {}).get(
|
||||
"external_evidence_missing", []
|
||||
)
|
||||
delivery = scorecard.get("current_delivery", {})
|
||||
if not isinstance(delivery, dict):
|
||||
raise PublicStatusError("scorecard current_delivery must be an object")
|
||||
internal = delivery.get("internal_delivery_gaps", [])
|
||||
missing = delivery.get("external_evidence_missing", [])
|
||||
if not isinstance(internal, list) or len(internal) < 3:
|
||||
raise PublicStatusError(
|
||||
"scorecard must list the internal delivery gaps blocking Baseline"
|
||||
)
|
||||
if not isinstance(missing, list) or len(missing) < 5:
|
||||
raise PublicStatusError(
|
||||
"scorecard must list the external evidence blocking release"
|
||||
@@ -580,30 +934,36 @@ def _build_next_actions(scorecard: Mapping[str, Any]) -> List[Dict[str, Any]]:
|
||||
return [
|
||||
{
|
||||
"priority": 1,
|
||||
"title": "生成授权 JQData 不可变真实快照",
|
||||
"why": str(missing[0]),
|
||||
"gateIds": ["G1", "G3", "G7"],
|
||||
"title": "接通真实数据五层候选",
|
||||
"why": f"{internal[0]} External prerequisite: {missing[0]}",
|
||||
"gateIds": ["G1", "G2", "G3", "G5", "G7"],
|
||||
},
|
||||
{
|
||||
"priority": 2,
|
||||
"title": "冻结聚宽同输入并完成逐层本地比较",
|
||||
"why": str(missing[1]),
|
||||
"gateIds": ["G3", "G9"],
|
||||
"title": "冻结主链风险、优化与执行选择",
|
||||
"why": str(internal[1]),
|
||||
"gateIds": ["G3", "G5", "G7", "G9"],
|
||||
},
|
||||
{
|
||||
"priority": 3,
|
||||
"title": "取得真实 QMT built-in 与 qmttools 导出",
|
||||
"why": str(missing[2]),
|
||||
"gateIds": ["G3", "G6", "G9"],
|
||||
"title": "扩展 JoinQuant 多期对账与逐层 parity",
|
||||
"why": f"{internal[2]} Required evidence: {missing[1]}",
|
||||
"gateIds": ["G3", "G7", "G9"],
|
||||
},
|
||||
{
|
||||
"priority": 4,
|
||||
"title": "运行真实 QMT TargetPackage 候选",
|
||||
"why": str(missing[2]),
|
||||
"gateIds": ["G6", "G8", "G9"],
|
||||
},
|
||||
{
|
||||
"priority": 5,
|
||||
"title": "完成 QMT 券商合同探针与至少 20 日影子盘",
|
||||
"why": str(missing[3]),
|
||||
"gateIds": ["G6", "G8", "G9"],
|
||||
},
|
||||
{
|
||||
"priority": 5,
|
||||
"priority": 6,
|
||||
"title": "完成连续对账、恢复演练与券商合规确认",
|
||||
"why": str(missing[4]),
|
||||
"gateIds": ["G8", "G10"],
|
||||
@@ -615,6 +975,7 @@ def _build_freshness(
|
||||
*,
|
||||
scorecard: Mapping[str, Any],
|
||||
joinquant_markdown: str,
|
||||
joinquant_target_package_run: Mapping[str, Any],
|
||||
tushare_markdown: str,
|
||||
) -> List[Dict[str, Any]]:
|
||||
period_match = re.search(
|
||||
@@ -686,15 +1047,44 @@ def _build_freshness(
|
||||
},
|
||||
{
|
||||
"id": "joinquant-hosted-market-window",
|
||||
"label": "JoinQuant hosted smoke 行情区间",
|
||||
"label": "JoinQuant hosted momentum smoke 行情区间",
|
||||
"status": "runtime_smoke",
|
||||
"marketDataFrom": joinquant_start,
|
||||
"marketDataThrough": joinquant_end,
|
||||
"value": f"{joinquant_start} — {joinquant_end}",
|
||||
"productionReady": False,
|
||||
"semantics": "单次真实 hosted runtime smoke 的回测区间;不代表同输入跨引擎通过。",
|
||||
"semantics": "旧 momentum hosted runtime smoke 的回测区间;不是 TargetPackage 候选或同输入跨引擎证据。",
|
||||
"evidenceLinks": ["joinquant-hosted-evidence", "scorecard"],
|
||||
},
|
||||
{
|
||||
"id": "joinquant-target-package-execution-smoke",
|
||||
"label": "JoinQuant TargetPackage execution smoke",
|
||||
"status": "runtime_smoke",
|
||||
"observedAt": str(joinquant_target_package_run["observedAt"]),
|
||||
"marketDataFrom": str(
|
||||
joinquant_target_package_run["marketDataFrom"]
|
||||
),
|
||||
"marketDataThrough": str(
|
||||
joinquant_target_package_run["marketDataThrough"]
|
||||
),
|
||||
"value": (
|
||||
f"{joinquant_target_package_run['marketDataFrom']} — "
|
||||
f"{joinquant_target_package_run['marketDataThrough']}; "
|
||||
"3 orders / 3 fills"
|
||||
),
|
||||
"productionReady": False,
|
||||
"investmentValueClaim": False,
|
||||
"semantics": (
|
||||
"真实平台只观察 synthetic-research TargetPackage 的 execution "
|
||||
"consumer;不代表上游四层真实平台执行、长样本 OOS 或 G9。"
|
||||
),
|
||||
"evidenceLinks": [
|
||||
"joinquant-target-package-evidence",
|
||||
"joinquant-target-package-run",
|
||||
"release-reachability",
|
||||
"scorecard",
|
||||
],
|
||||
},
|
||||
{
|
||||
"id": "tushare-daily-market-data",
|
||||
"label": "Tushare daily 行情覆盖",
|
||||
@@ -806,6 +1196,10 @@ def build_public_status(
|
||||
project = project.resolve()
|
||||
scorecard = _load_json(project / "gate_scorecard.json")
|
||||
manifest = _load_json(project / "dist" / "bundle_manifest.json")
|
||||
reachability_manifest = _load_json(project / REACHABILITY_PATH)
|
||||
joinquant_target_package_run_raw = _load_json(
|
||||
project / JOINQUANT_TARGET_PACKAGE_RUN_PATH
|
||||
)
|
||||
baseline = _load_json(project / "configs" / "baseline.json")
|
||||
platform_markdown = (project / "docs" / "PLATFORM_MATRIX.md").read_text(
|
||||
encoding="utf-8"
|
||||
@@ -870,6 +1264,13 @@ def build_public_status(
|
||||
test_count, optional_skips = _extract_test_summary(facts)
|
||||
|
||||
artifacts = _validate_bundle_manifest(project, manifest)
|
||||
reachability = _validate_reachability_manifest(
|
||||
project, reachability_manifest
|
||||
)
|
||||
joinquant_target_package_run = _validate_joinquant_target_package_run(
|
||||
project,
|
||||
joinquant_target_package_run_raw,
|
||||
)
|
||||
source_records: List[Dict[str, str]] = []
|
||||
for relative in SOURCE_PATHS:
|
||||
safe_path = _safe_repo_path(relative, label="provenance source")
|
||||
@@ -883,6 +1284,19 @@ def build_public_status(
|
||||
|
||||
claim_policy = scorecard["claim_policy"]
|
||||
delivery = scorecard["current_delivery"]
|
||||
internal_delivery_gaps = delivery.get("internal_delivery_gaps", [])
|
||||
external_evidence_missing = delivery.get("external_evidence_missing", [])
|
||||
if not isinstance(internal_delivery_gaps, list) or len(internal_delivery_gaps) < 3:
|
||||
raise PublicStatusError(
|
||||
"scorecard must list the internal delivery gaps blocking Baseline"
|
||||
)
|
||||
if (
|
||||
not isinstance(external_evidence_missing, list)
|
||||
or len(external_evidence_missing) < 5
|
||||
):
|
||||
raise PublicStatusError(
|
||||
"scorecard must list the external evidence blocking release"
|
||||
)
|
||||
payload: Dict[str, Any] = {
|
||||
"schemaVersion": SCHEMA_VERSION,
|
||||
"generatedAt": generated_at_value,
|
||||
@@ -905,8 +1319,20 @@ def build_public_status(
|
||||
"testsRecorded": test_count,
|
||||
"optionalSkipsRecorded": optional_skips,
|
||||
"testEvidenceQualifier": "Scorecard-recorded run; tests do not prove real-platform or broker gates.",
|
||||
"candidateRealPlatformObserved": bool(
|
||||
reachability["realPlatformsObserved"]
|
||||
),
|
||||
"candidateRealPlatformObservationScope": (
|
||||
"target_package_execution_consumer_only"
|
||||
),
|
||||
"allFiveLayersRealPlatformObserved": bool(
|
||||
reachability["summary"][
|
||||
"all_layers_real_platform_observed"
|
||||
]
|
||||
),
|
||||
"realRuntimeSmokes": [
|
||||
"JoinQuant hosted daily backtest (runtime/path only)",
|
||||
"JoinQuant TargetPackage execution consumer: one synthetic-research package, 3 orders / 3 fills (not Baseline/G9 evidence)",
|
||||
"JoinQuant portable_momentum_smoke hosted daily backtest (not Baseline/TargetPackage evidence)",
|
||||
"Qlib native momentum fixture",
|
||||
"Qlib Alpha158 + LightGBM fixture",
|
||||
"Tushare completed-partition Qlib momentum smoke",
|
||||
@@ -915,12 +1341,45 @@ def build_public_status(
|
||||
"productionReady": False,
|
||||
"investmentValueClaim": False,
|
||||
},
|
||||
"candidateBoundary": {
|
||||
"decisionMode": "target_package",
|
||||
"localEvidenceClass": "synthetic_research",
|
||||
"connectedRiskModel": "60-session diagonal realized variance",
|
||||
"connectedOptimizer": "deterministic constrained optimizer",
|
||||
"connectedExecution": "reference one-shot quantity/order-delta planner",
|
||||
"realJoinQuantObserved": (
|
||||
"joinquant" in reachability["realPlatformsObserved"]
|
||||
),
|
||||
"realQmtObserved": (
|
||||
"qmt" in reachability["realPlatformsObserved"]
|
||||
),
|
||||
"realPlatformObservedLayers": reachability[
|
||||
"realPlatformObservedLayers"
|
||||
],
|
||||
"allFiveLayersRealPlatformObserved": bool(
|
||||
reachability["summary"][
|
||||
"all_layers_real_platform_observed"
|
||||
]
|
||||
),
|
||||
"joinQuantTargetPackageRun": joinquant_target_package_run,
|
||||
"joinQuantTargetPackageCountsAsBaseline": False,
|
||||
"joinQuantTargetPackageCountsAsG9": False,
|
||||
"historicalJoinQuantMode": "portable_momentum_smoke",
|
||||
"historicalJoinQuantCountsAsBaseline": False,
|
||||
"reachability": reachability,
|
||||
"releaseVerified": False,
|
||||
},
|
||||
"deliveryGaps": {
|
||||
"internal": [str(item) for item in internal_delivery_gaps],
|
||||
"externalEvidence": [str(item) for item in external_evidence_missing],
|
||||
},
|
||||
"layers": _build_layers(),
|
||||
"models": _build_models(),
|
||||
"platforms": _build_platforms(platform_markdown),
|
||||
"freshness": _build_freshness(
|
||||
scorecard=scorecard,
|
||||
joinquant_markdown=joinquant_markdown,
|
||||
joinquant_target_package_run=joinquant_target_package_run,
|
||||
tushare_markdown=tushare_markdown,
|
||||
),
|
||||
"gates": gates,
|
||||
@@ -954,6 +1413,7 @@ def build_public_status(
|
||||
"provenance": {
|
||||
"scorecard": "gate_scorecard.json",
|
||||
"bundleManifest": "dist/bundle_manifest.json",
|
||||
"releaseReachability": REACHABILITY_PATH,
|
||||
"platformMatrix": "docs/PLATFORM_MATRIX.md",
|
||||
"baselineConfig": "configs/baseline.json",
|
||||
"sourceSetSha256": source_set_sha,
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
"""Build the conservative Quant60 research-candidate reachability manifest.
|
||||
|
||||
The hosted-platform claims in this manifest have deliberately narrow
|
||||
semantics. For Universe, Alpha, Portfolio, and Risk, ``*_entrypoint_reachable``
|
||||
means that the locally computed output and its lineage reach the hosted
|
||||
consumer through a verified ``TargetPackageV1``. It does *not* mean that
|
||||
JoinQuant or QMT execute those upstream Python implementations. Execution is
|
||||
the only layer implemented inside the hosted wrappers.
|
||||
|
||||
One real JoinQuant TargetPackage smoke observes the execution consumer,
|
||||
account/price binding, orders, and fills. It therefore supports only
|
||||
``execution.real_platform_observed``. The other four layer observations and
|
||||
the derived all-layer observation remain false.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
|
||||
PROJECT = Path(__file__).resolve().parents[1]
|
||||
SOURCE_ROOT = PROJECT / "src"
|
||||
if str(SOURCE_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(SOURCE_ROOT))
|
||||
|
||||
from quant60.ledger import canonical_json # noqa: E402
|
||||
from quant60.release_reachability import ( # noqa: E402
|
||||
LAYERS,
|
||||
build_evidence_artifact,
|
||||
build_release_reachability,
|
||||
load_verified_release_reachability,
|
||||
write_release_reachability,
|
||||
)
|
||||
|
||||
|
||||
RELEASE_ID = "quant60-research-candidate-v1"
|
||||
RELEASE_DECLARED_AT = "2026-07-26T12:00:00Z"
|
||||
DEFAULT_OUTPUT = (
|
||||
PROJECT / "releases" / RELEASE_ID / "reachability.json"
|
||||
)
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_PATH = (
|
||||
"evidence/joinquant/TP-20240311-795dcfba/"
|
||||
"2457a7c39a276e09e0fabf99e28978e1/run.json"
|
||||
)
|
||||
JOINQUANT_TARGET_PACKAGE_RUN_ID = "2457a7c39a276e09e0fabf99e28978e1"
|
||||
JOINQUANT_TARGET_PACKAGE_OBSERVED_AT = "2026-07-26T08:50:15Z"
|
||||
PLATFORM_CLAIM_NOTE = (
|
||||
"Upstream layer status means its locally computed output/lineage is "
|
||||
"carried through TargetPackageV1 to the hosted consumer; it does not "
|
||||
"claim JoinQuant/QMT executes the upstream Python. Execution alone runs "
|
||||
"inside the hosted wrapper. One JoinQuant smoke observes only that "
|
||||
"execution boundary; it does not observe all five layers."
|
||||
)
|
||||
|
||||
|
||||
# Each path names code used by the connected local five-layer decision path.
|
||||
# A shared composition module appears in several claims by design; artifact IDs
|
||||
# remain unique, as required by the reachability contract.
|
||||
IMPLEMENTED_EVIDENCE: dict[str, tuple[tuple[str, str], ...]] = {
|
||||
"universe": (
|
||||
("baseline-pipeline", "src/quant60/baseline_pipeline.py"),
|
||||
),
|
||||
"alpha": (
|
||||
("frozen-model-bundle", "src/quant60/model_bundle.py"),
|
||||
("baseline-pipeline", "src/quant60/baseline_pipeline.py"),
|
||||
),
|
||||
"portfolio": (
|
||||
("optimizer", "src/quant60/optimizer.py"),
|
||||
("baseline-pipeline", "src/quant60/baseline_pipeline.py"),
|
||||
),
|
||||
"risk": (
|
||||
("risk-gate", "src/quant60/risk.py"),
|
||||
("baseline-pipeline", "src/quant60/baseline_pipeline.py"),
|
||||
),
|
||||
"execution": (
|
||||
("portable-execution-core", "src/quant60/portable_core.py"),
|
||||
("baseline-pipeline", "src/quant60/baseline_pipeline.py"),
|
||||
),
|
||||
}
|
||||
|
||||
UNIT_TEST_EVIDENCE: dict[str, tuple[tuple[str, str], ...]] = {
|
||||
"universe": (
|
||||
("five-layer-causality", "tests/test_baseline_pipeline.py"),
|
||||
),
|
||||
"alpha": (
|
||||
("five-layer-causality", "tests/test_baseline_pipeline.py"),
|
||||
("frozen-model-replay", "tests/test_model_bundle.py"),
|
||||
),
|
||||
"portfolio": (
|
||||
("five-layer-causality", "tests/test_baseline_pipeline.py"),
|
||||
),
|
||||
"risk": (
|
||||
("five-layer-causality", "tests/test_baseline_pipeline.py"),
|
||||
),
|
||||
"execution": (
|
||||
("five-layer-causality", "tests/test_baseline_pipeline.py"),
|
||||
("portable-order-plan", "tests/test_portable_core.py"),
|
||||
),
|
||||
}
|
||||
|
||||
LOCAL_ENTRYPOINT_EVIDENCE: tuple[tuple[str, str], ...] = (
|
||||
("research-smoke-cli", "src/quant60/cli.py"),
|
||||
("research-experiment", "src/quant60/experiment.py"),
|
||||
)
|
||||
|
||||
PLATFORM_ENTRYPOINTS = {
|
||||
"jq": {
|
||||
"capability": "jq_entrypoint_reachable",
|
||||
"platform": "joinquant",
|
||||
"path": "platforms/joinquant_strategy.py",
|
||||
},
|
||||
"qmt": {
|
||||
"capability": "qmt_entrypoint_reachable",
|
||||
"platform": "qmt",
|
||||
"path": "platforms/qmt_builtin_strategy.py",
|
||||
},
|
||||
}
|
||||
|
||||
# These labels are part of the signed artifact IDs. They keep the narrow
|
||||
# meaning visible even though the v1 schema intentionally has no free-text
|
||||
# claim field.
|
||||
PLATFORM_OUTPUT_LABELS = {
|
||||
"universe": "universe-state-via-targetpackagev1-consumer",
|
||||
"alpha": "alpha-lineage-derived-target-via-targetpackagev1-consumer",
|
||||
"portfolio": "portfolio-weight-via-targetpackagev1-consumer",
|
||||
"risk": "post-risk-weight-constraints-via-targetpackagev1-consumer",
|
||||
"execution": "targetpackagev1-hosted-execution-entrypoint",
|
||||
}
|
||||
|
||||
|
||||
def _false_claim() -> dict[str, Any]:
|
||||
return {"status": False, "artifacts": []}
|
||||
|
||||
|
||||
def _evidence(
|
||||
*,
|
||||
repository_root: Path,
|
||||
artifact_id: str,
|
||||
kind: str,
|
||||
path: str,
|
||||
platform: str,
|
||||
observed_at: str | None = None,
|
||||
run_id: str | None = None,
|
||||
) -> dict[str, Any]:
|
||||
return build_evidence_artifact(
|
||||
artifact_id=artifact_id,
|
||||
kind=kind,
|
||||
path=path,
|
||||
platform=platform,
|
||||
repository_root=repository_root,
|
||||
observed_at=observed_at,
|
||||
run_id=run_id,
|
||||
)
|
||||
|
||||
|
||||
def build_manifest(
|
||||
*,
|
||||
repository_root: str | Path = PROJECT,
|
||||
generated_at: str = RELEASE_DECLARED_AT,
|
||||
) -> dict[str, Any]:
|
||||
"""Build a fully content-addressed manifest from the current repository."""
|
||||
|
||||
root = Path(repository_root)
|
||||
layers: dict[str, dict[str, Any]] = {}
|
||||
for layer in LAYERS:
|
||||
implemented = [
|
||||
_evidence(
|
||||
repository_root=root,
|
||||
artifact_id=f"{layer}-implemented-{label}",
|
||||
kind="source",
|
||||
path=path,
|
||||
platform="repository",
|
||||
)
|
||||
for label, path in IMPLEMENTED_EVIDENCE[layer]
|
||||
]
|
||||
unit_tested = [
|
||||
_evidence(
|
||||
repository_root=root,
|
||||
artifact_id=f"{layer}-unit-tested-{label}",
|
||||
kind="test",
|
||||
path=path,
|
||||
platform="repository",
|
||||
)
|
||||
for label, path in UNIT_TEST_EVIDENCE[layer]
|
||||
]
|
||||
local_entrypoint = [
|
||||
_evidence(
|
||||
repository_root=root,
|
||||
artifact_id=f"{layer}-local-{label}",
|
||||
kind="entrypoint",
|
||||
path=path,
|
||||
platform="local",
|
||||
)
|
||||
for label, path in LOCAL_ENTRYPOINT_EVIDENCE
|
||||
]
|
||||
claims: dict[str, Any] = {
|
||||
"implemented": {"status": True, "artifacts": implemented},
|
||||
"unit_tested": {"status": True, "artifacts": unit_tested},
|
||||
"local_entrypoint_reachable": {
|
||||
"status": True,
|
||||
"artifacts": local_entrypoint,
|
||||
},
|
||||
"real_platform_observed": _false_claim(),
|
||||
}
|
||||
if layer == "execution":
|
||||
claims["real_platform_observed"] = {
|
||||
"status": True,
|
||||
"artifacts": [
|
||||
_evidence(
|
||||
repository_root=root,
|
||||
artifact_id=(
|
||||
"execution-real-platform-targetpackagev1-smoke-jq"
|
||||
),
|
||||
kind="platform_run",
|
||||
path=JOINQUANT_TARGET_PACKAGE_RUN_PATH,
|
||||
platform="joinquant",
|
||||
observed_at=JOINQUANT_TARGET_PACKAGE_OBSERVED_AT,
|
||||
run_id=JOINQUANT_TARGET_PACKAGE_RUN_ID,
|
||||
)
|
||||
],
|
||||
}
|
||||
for name, declaration in PLATFORM_ENTRYPOINTS.items():
|
||||
capability = declaration["capability"]
|
||||
claims[capability] = {
|
||||
"status": True,
|
||||
"artifacts": [
|
||||
_evidence(
|
||||
repository_root=root,
|
||||
artifact_id=(
|
||||
f"{layer}-{PLATFORM_OUTPUT_LABELS[layer]}-{name}"
|
||||
),
|
||||
kind="entrypoint",
|
||||
path=declaration["path"],
|
||||
platform=declaration["platform"],
|
||||
)
|
||||
],
|
||||
}
|
||||
layers[layer] = claims
|
||||
|
||||
return build_release_reachability(
|
||||
release_id=RELEASE_ID,
|
||||
generated_at=generated_at,
|
||||
layers=layers,
|
||||
repository_root=root,
|
||||
)
|
||||
|
||||
|
||||
def _build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
type=Path,
|
||||
default=DEFAULT_OUTPUT,
|
||||
help="manifest path (default: releases/<release>/reachability.json)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--generated-at",
|
||||
default=RELEASE_DECLARED_AT,
|
||||
help="canonical UTC release declaration time",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--check",
|
||||
action="store_true",
|
||||
help="verify that the existing manifest exactly matches regeneration",
|
||||
)
|
||||
return parser
|
||||
|
||||
|
||||
def main(argv: list[str] | None = None) -> int:
|
||||
args = _build_parser().parse_args(argv)
|
||||
expected = build_manifest(generated_at=args.generated_at)
|
||||
output = args.output.expanduser().resolve()
|
||||
if args.check:
|
||||
observed = load_verified_release_reachability(
|
||||
output,
|
||||
repository_root=PROJECT,
|
||||
expected_release_id=RELEASE_ID,
|
||||
expected_manifest_sha256=expected["manifest_sha256"],
|
||||
)
|
||||
expected_bytes = (canonical_json(expected) + "\n").encode("utf-8")
|
||||
if observed != expected or output.read_bytes() != expected_bytes:
|
||||
raise ValueError(
|
||||
"reachability manifest does not exactly match regeneration"
|
||||
)
|
||||
else:
|
||||
write_release_reachability(
|
||||
expected,
|
||||
output,
|
||||
repository_root=PROJECT,
|
||||
)
|
||||
summary = {
|
||||
"ok": True,
|
||||
"checked": bool(args.check),
|
||||
"output": str(output),
|
||||
"release_id": RELEASE_ID,
|
||||
"manifest_sha256": expected["manifest_sha256"],
|
||||
"platform_claim_semantics": PLATFORM_CLAIM_NOTE,
|
||||
}
|
||||
print(json.dumps(summary, ensure_ascii=False, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
+198
-16
@@ -7,14 +7,33 @@ import ast
|
||||
import hashlib
|
||||
import json
|
||||
import pprint
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
|
||||
START = "# __PORTABLE_CORE_BUNDLE_START__"
|
||||
END = "# __PORTABLE_CORE_BUNDLE_END__"
|
||||
CONFIG_START = "# __BASELINE_CONFIG_START__"
|
||||
CONFIG_END = "# __BASELINE_CONFIG_END__"
|
||||
TARGET_START = "# __TARGET_PACKAGE_TAPE_START__"
|
||||
TARGET_END = "# __TARGET_PACKAGE_TAPE_END__"
|
||||
MOMENTUM_SMOKE_MODE = "portable_momentum_smoke"
|
||||
TARGET_PACKAGE_MODE = "target_package"
|
||||
JOINQUANT_EVIDENCE_PREFIX = "QUANT60_JOINQUANT_EVIDENCE_V1 "
|
||||
JOINQUANT_EVIDENCE_CHUNK_CHARACTERS = 1800
|
||||
JOINQUANT_TARGET_PRICE_SOURCE = "CURRENT_DATA_DAY_OPEN"
|
||||
JOINQUANT_EVIDENCE_EVENTS = [
|
||||
"INIT",
|
||||
"TARGET_PACKAGE_NOOP",
|
||||
"TARGET_PACKAGE_HIT",
|
||||
"PLATFORM_BINDING_INPUT",
|
||||
"TARGET_PACKAGE_PLAN",
|
||||
"SKIPPED_ORDER",
|
||||
"ORDER_REQUEST",
|
||||
"ORDER_RETURN",
|
||||
"EOD_STATUS",
|
||||
]
|
||||
|
||||
|
||||
def sha256_bytes(value: bytes) -> str:
|
||||
@@ -56,6 +75,73 @@ def inline_core(wrapper_source: str, core_source: str) -> str:
|
||||
return wrapper_source[:start] + replacement + wrapper_source[end:]
|
||||
|
||||
|
||||
def _canonical_target_tape_bytes(
|
||||
target_packages: List[Dict[str, Any]],
|
||||
) -> bytes:
|
||||
return json.dumps(
|
||||
target_packages,
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
separators=(",", ":"),
|
||||
allow_nan=False,
|
||||
).encode("utf-8")
|
||||
|
||||
|
||||
def inline_target_packages(
|
||||
wrapper_source: str,
|
||||
target_packages: List[Dict[str, Any]],
|
||||
) -> str:
|
||||
"""Inline a pre-validated, quantity-free decision tape."""
|
||||
|
||||
if (
|
||||
wrapper_source.count(TARGET_START) != 1
|
||||
or wrapper_source.count(TARGET_END) != 1
|
||||
):
|
||||
raise ValueError(
|
||||
"wrapper must contain exactly one target-package marker pair"
|
||||
)
|
||||
start = wrapper_source.index(TARGET_START)
|
||||
end = wrapper_source.index(TARGET_END, start) + len(TARGET_END)
|
||||
body = pprint.pformat(
|
||||
target_packages,
|
||||
width=88,
|
||||
sort_dicts=False,
|
||||
)
|
||||
body = body.encode("ascii", "backslashreplace").decode("ascii")
|
||||
replacement = (
|
||||
TARGET_START
|
||||
+ "\n# Generated by tools/bundle_platforms.py; do not edit this region.\n"
|
||||
+ "TARGET_PACKAGES = "
|
||||
+ body
|
||||
+ "\n"
|
||||
+ TARGET_END
|
||||
)
|
||||
return wrapper_source[:start] + replacement + wrapper_source[end:]
|
||||
|
||||
|
||||
def load_verified_target_packages(
|
||||
project_root: Path,
|
||||
path: Path,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""Load one package or a multi-decision tape through the canonical verifier."""
|
||||
|
||||
root = project_root.expanduser().resolve()
|
||||
source = path.expanduser().resolve()
|
||||
src_path = str(root / "src")
|
||||
inserted = src_path not in sys.path
|
||||
if inserted:
|
||||
sys.path.insert(0, src_path)
|
||||
try:
|
||||
from quant60.target_package import ( # pylint: disable=import-outside-toplevel
|
||||
load_target_package_tape,
|
||||
)
|
||||
|
||||
return list(load_target_package_tape(source))
|
||||
finally:
|
||||
if inserted:
|
||||
sys.path.remove(src_path)
|
||||
|
||||
|
||||
def _qmt_symbol(symbol: str) -> str:
|
||||
suffixes = {
|
||||
".XSHG": ".SH",
|
||||
@@ -71,20 +157,52 @@ def _qmt_symbol(symbol: str) -> str:
|
||||
def effective_platform_config(
|
||||
baseline: Dict[str, Any],
|
||||
platform: str,
|
||||
*,
|
||||
decision_mode: str = MOMENTUM_SMOKE_MODE,
|
||||
target_packages: Optional[List[Dict[str, Any]]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
packages = list(target_packages or [])
|
||||
if decision_mode not in {MOMENTUM_SMOKE_MODE, TARGET_PACKAGE_MODE}:
|
||||
raise ValueError(f"unsupported decision_mode: {decision_mode}")
|
||||
if decision_mode == TARGET_PACKAGE_MODE and not packages:
|
||||
raise ValueError("target_package mode requires a non-empty package tape")
|
||||
if decision_mode == MOMENTUM_SMOKE_MODE and packages:
|
||||
raise ValueError("momentum smoke mode cannot embed target packages")
|
||||
strategy = baseline["strategy"]
|
||||
execution = baseline["execution"]
|
||||
fees = baseline["fees"]
|
||||
universe_config = baseline["universe"]
|
||||
symbols = [str(symbol) for symbol in baseline["symbols"]]
|
||||
symbols = (
|
||||
sorted(
|
||||
{
|
||||
str(symbol)
|
||||
for package in packages
|
||||
for symbol in package["universe"]
|
||||
}
|
||||
)
|
||||
if packages
|
||||
else [str(symbol) for symbol in baseline["symbols"]]
|
||||
)
|
||||
if platform == "qmt_builtin":
|
||||
universe = [_qmt_symbol(symbol) for symbol in symbols]
|
||||
elif platform == "joinquant":
|
||||
universe = symbols
|
||||
else:
|
||||
raise ValueError(f"unsupported platform config: {platform}")
|
||||
tape_sha256 = (
|
||||
sha256_bytes(_canonical_target_tape_bytes(packages))
|
||||
if packages
|
||||
else None
|
||||
)
|
||||
common: Dict[str, Any] = {
|
||||
"universe_mode": str(universe_config["mode"]),
|
||||
"decision_mode": decision_mode,
|
||||
"target_package_count": len(packages),
|
||||
"target_package_tape_sha256": tape_sha256,
|
||||
"universe_mode": (
|
||||
"fixed"
|
||||
if decision_mode == TARGET_PACKAGE_MODE
|
||||
else str(universe_config["mode"])
|
||||
),
|
||||
"index_symbol": str(universe_config["index_symbol"]),
|
||||
"qmt_sector_name": str(universe_config["qmt_sector_name"]),
|
||||
"dedicated_account_required": bool(
|
||||
@@ -145,15 +263,19 @@ def bundle_one(
|
||||
wrapper_path: Path,
|
||||
output_path: Path,
|
||||
effective_config: Dict[str, Any],
|
||||
target_packages: Optional[List[Dict[str, Any]]] = None,
|
||||
require_ascii: bool = False,
|
||||
) -> Dict[str, str]:
|
||||
core_bytes = core_path.read_bytes()
|
||||
wrapper_bytes = wrapper_path.read_bytes()
|
||||
core_source = core_bytes.decode("utf-8")
|
||||
wrapper_source = wrapper_bytes.decode("utf-8")
|
||||
bundled = inline_config(
|
||||
inline_core(wrapper_source, core_source),
|
||||
effective_config,
|
||||
bundled = inline_target_packages(
|
||||
inline_config(
|
||||
inline_core(wrapper_source, core_source),
|
||||
effective_config,
|
||||
),
|
||||
list(target_packages or []),
|
||||
)
|
||||
output_bytes = bundled.encode("utf-8")
|
||||
if require_ascii:
|
||||
@@ -194,6 +316,7 @@ def bundle_one(
|
||||
def bundle_all(
|
||||
project_root: Path,
|
||||
output_dir: Optional[Path] = None,
|
||||
target_package_path: Optional[Path] = None,
|
||||
) -> Dict[str, object]:
|
||||
root = project_root.expanduser().resolve()
|
||||
output = (
|
||||
@@ -209,43 +332,90 @@ def bundle_all(
|
||||
baseline = json.loads(baseline_bytes.decode("utf-8"))
|
||||
if not isinstance(baseline, dict):
|
||||
raise ValueError("configs/baseline.json must contain an object")
|
||||
target_packages = (
|
||||
load_verified_target_packages(root, target_package_path)
|
||||
if target_package_path is not None
|
||||
else []
|
||||
)
|
||||
decision_mode = (
|
||||
TARGET_PACKAGE_MODE if target_packages else MOMENTUM_SMOKE_MODE
|
||||
)
|
||||
entries = {
|
||||
"joinquant": bundle_one(
|
||||
core_path=core,
|
||||
wrapper_path=root / "platforms" / "joinquant_strategy.py",
|
||||
output_path=output / "joinquant_strategy.py",
|
||||
effective_config=effective_platform_config(baseline, "joinquant"),
|
||||
effective_config=effective_platform_config(
|
||||
baseline,
|
||||
"joinquant",
|
||||
decision_mode=decision_mode,
|
||||
target_packages=target_packages,
|
||||
),
|
||||
target_packages=target_packages,
|
||||
),
|
||||
"qmt_builtin": bundle_one(
|
||||
core_path=core,
|
||||
wrapper_path=root / "platforms" / "qmt_builtin_strategy.py",
|
||||
output_path=output / "qmt_builtin_strategy.py",
|
||||
effective_config=effective_platform_config(baseline, "qmt_builtin"),
|
||||
effective_config=effective_platform_config(
|
||||
baseline,
|
||||
"qmt_builtin",
|
||||
decision_mode=decision_mode,
|
||||
target_packages=target_packages,
|
||||
),
|
||||
target_packages=target_packages,
|
||||
require_ascii=True,
|
||||
),
|
||||
}
|
||||
# Paths in a committed manifest must be portable and must not expose the
|
||||
# local account/home directory. Hashes remain byte-for-byte identities.
|
||||
logical_outputs = {
|
||||
# Paths in a manifest must be portable and must not expose the local
|
||||
# account/home directory. Preserve a real project-relative location for
|
||||
# outputs under the project (for example dist/target-package/...). A
|
||||
# clean-room output outside the project keeps the committed logical names
|
||||
# so its manifest remains byte-for-byte comparable with committed dist.
|
||||
default_logical_outputs = {
|
||||
"joinquant": "dist/joinquant_strategy.py",
|
||||
"qmt_builtin": "dist/qmt_builtin_strategy.py",
|
||||
}
|
||||
for platform_name, entry in entries.items():
|
||||
physical_output = Path(entry["output"])
|
||||
entry["core"] = "src/quant60/portable_core.py"
|
||||
entry["wrapper"] = (
|
||||
"platforms/joinquant_strategy.py"
|
||||
if "joinquant" in entry["wrapper"]
|
||||
else "platforms/qmt_builtin_strategy.py"
|
||||
)
|
||||
# The manifest describes the committed logical artifact, not the
|
||||
# caller's temporary build directory. This keeps clean-room builds
|
||||
# byte-for-byte comparable with committed ``dist``.
|
||||
entry["output"] = logical_outputs[platform_name]
|
||||
try:
|
||||
entry["output"] = physical_output.relative_to(root).as_posix()
|
||||
except ValueError:
|
||||
entry["output"] = default_logical_outputs[platform_name]
|
||||
manifest = {
|
||||
"schema_version": 1,
|
||||
"baseline_config": "configs/baseline.json",
|
||||
"baseline_config_sha256": sha256_bytes(baseline_bytes),
|
||||
"portable_core_sha256": entries["joinquant"]["core_sha256"],
|
||||
"decision_mode": decision_mode,
|
||||
"target_package_count": len(target_packages),
|
||||
"target_package_tape_sha256": (
|
||||
sha256_bytes(_canonical_target_tape_bytes(target_packages))
|
||||
if target_packages
|
||||
else None
|
||||
),
|
||||
"target_package_ids": [
|
||||
package["package_id"] for package in target_packages
|
||||
],
|
||||
"target_package_sha256": [
|
||||
package["package_sha256"] for package in target_packages
|
||||
],
|
||||
"joinquant_observation": {
|
||||
"eod_chunk_characters": JOINQUANT_EVIDENCE_CHUNK_CHARACTERS,
|
||||
"eod_chunk_encoding": "base64-canonical-json",
|
||||
"eod_api_policy": "best_effort_get_orders_get_trades",
|
||||
"events": JOINQUANT_EVIDENCE_EVENTS,
|
||||
"fail_soft": True,
|
||||
"prefix": JOINQUANT_EVIDENCE_PREFIX,
|
||||
"schema_version": "1.0",
|
||||
"target_price_source": JOINQUANT_TARGET_PRICE_SOURCE,
|
||||
},
|
||||
"artifacts": entries,
|
||||
}
|
||||
manifest_path = output / "bundle_manifest.json"
|
||||
@@ -266,8 +436,20 @@ def _main(argv: Optional[list[str]] = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--project-root", type=Path, default=default_root)
|
||||
parser.add_argument("--output-dir", type=Path)
|
||||
parser.add_argument(
|
||||
"--target-package",
|
||||
type=Path,
|
||||
help=(
|
||||
"verified TargetPackageV1 JSON/JSONL tape; switches both hosted "
|
||||
"artifacts from momentum smoke to target-package execution"
|
||||
),
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
manifest = bundle_all(args.project_root, args.output_dir)
|
||||
manifest = bundle_all(
|
||||
args.project_root,
|
||||
args.output_dir,
|
||||
args.target_package,
|
||||
)
|
||||
print(json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user