feat: add Quant OS public status console

This commit is contained in:
2026-07-26 14:32:52 +08:00
parent e5911ca454
commit 00efeb7ec2
12 changed files with 4443 additions and 9 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ Quant OS 是项目名;`quant60` 是第一版 A 股 Baseline 内核、CLI names
回测/影子验证,并且所有 G1—G10 都由版本绑定的真实证据支持。 回测/影子验证,并且所有 G1—G10 都由版本绑定的真实证据支持。
当前结论仍为 `NOT_BASELINE_60`。最近一次标准库全量测试记录为 当前结论仍为 `NOT_BASELINE_60`。最近一次标准库全量测试记录为
`Ran 216 tests``OK (skipped=6)`;六个 skip 是可选依赖/运行时路径。 `Ran 224 tests``OK (skipped=6)`;六个 skip 是可选依赖/运行时路径。
该结果证明代码合同,不证明真实平台、券商或合规 Gate。 该结果证明代码合同,不证明真实平台、券商或合规 Gate。
## Stage 1: 独立仓库与确定性执行 ## Stage 1: 独立仓库与确定性执行
+8 -2
View File
@@ -4,7 +4,7 @@ SMOKE_DIR := artifacts/local-smoke
RESEARCH_DIR := artifacts/research-smoke RESEARCH_DIR := artifacts/research-smoke
PARITY_REPORT := artifacts/mock-parity/report.json PARITY_REPORT := artifacts/mock-parity/report.json
.PHONY: test bundle smoke verify research research-verify parity parity-verify doctor notebook-check notebook-smoke local .PHONY: test bundle smoke verify research research-verify parity parity-verify doctor status status-check notebook-check notebook-smoke local
test: test:
PYTHONPATH=$(PROJECT_PYTHONPATH) $(PYTHON) -m unittest discover -s tests -p '*.py' -q PYTHONPATH=$(PROJECT_PYTHONPATH) $(PYTHON) -m unittest discover -s tests -p '*.py' -q
@@ -33,10 +33,16 @@ parity-verify:
doctor: doctor:
PYTHONPATH=$(PROJECT_PYTHONPATH) $(PYTHON) tools/capability_probe.py PYTHONPATH=$(PROJECT_PYTHONPATH) $(PYTHON) tools/capability_probe.py
status:
$(PYTHON) tools/build_public_status.py
status-check:
$(PYTHON) tools/build_public_status.py --check
notebook-check: notebook-check:
$(PYTHON) tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb $(PYTHON) tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb
notebook-smoke: notebook-smoke:
$(PYTHON) tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb --execute $(PYTHON) tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb --execute
local: test bundle smoke verify research research-verify parity parity-verify doctor notebook-check notebook-smoke local: test bundle smoke verify research research-verify parity parity-verify doctor status-check notebook-check notebook-smoke
+20
View File
@@ -15,6 +15,26 @@ Quant OS 是项目名;`quant60` 是第一版 A 股 Baseline 的 Python
> [`docs/AUDIT_2026-07-25.md`](docs/AUDIT_2026-07-25.md) 与 > [`docs/AUDIT_2026-07-25.md`](docs/AUDIT_2026-07-25.md) 与
> [`gate_scorecard.json`](gate_scorecard.json)。 > [`gate_scorecard.json`](gate_scorecard.json)。
## 在线公开验收面板
公开只读入口:
[`https://gomars.fun/quants-strategies/quant-os/status/index.html`](https://gomars.fun/quants-strategies/quant-os/status/index.html)
页面从 `gate_scorecard.json`、平台矩阵、bundle manifest 和证据文档生成
脱敏的构建时快照,逐层展示数据、模型、回测平台、券商影子盘与 G1—G10
缺口。它不是实时服务健康页,不发布本地行情、账户状态或运行 artifacts。
更新权威记录后必须重新生成并检查页面数据:
```bash
python3 tools/build_public_status.py
python3 tools/build_public_status.py --check
```
网页源码位于 [`status/`](status/),生成器位于
[`tools/build_public_status.py`](tools/build_public_status.py)。
## 当前交付边界 ## 当前交付边界
| 路径 | 当前能做什么 | 已有证据 | 仍缺什么 | | 路径 | 当前能做什么 | 已有证据 | 仍缺什么 |
+1 -1
View File
@@ -228,7 +228,7 @@ saved/current source aggregate、saved/current schema aggregate 和 payload
schema。`verify-snapshot-decision` 与 data snapshot semantic verifier 承担 schema。`verify-snapshot-decision` 与 data snapshot semantic verifier 承担
各自边界的同类职责。 各自边界的同类职责。
这些合同已有自动测试;最近一次标准库套件为 216 tests、OK、6 个可选路径 这些合同已有自动测试;最近一次标准库套件为 224 tests、OK、6 个可选路径
skip。测试结果不能替代 schema 迁移演练、真实平台导出或券商回调认证。 skip。测试结果不能替代 schema 迁移演练、真实平台导出或券商回调认证。
## Clocks and reconciliation ## Clocks and reconciliation
+2 -2
View File
@@ -25,7 +25,7 @@ A 股 Baseline 内核。它的新增得分必须在授权数据、真实平台
截至 2026-07-26 的实现事实快照: 截至 2026-07-26 的实现事实快照:
- 截至 2026-07-26 的最新标准库全量测试为 `Ran 216 tests``OK (skipped=6)` - 截至 2026-07-26 的最新标准库全量测试为 `Ran 224 tests``OK (skipped=6)`
- JQData raw/factor/pre-close/limits/paused + 每日 PIT `is_st`/指数成员 - JQData raw/factor/pre-close/limits/paused + 每日 PIT `is_st`/指数成员
已连接到 semantic snapshot verifier、`snapshot-backtest` 已连接到 semantic snapshot verifier、`snapshot-backtest`
`snapshot-decision`,并拒绝把抓取当日未到 24:00 的日线标成完整收盘, `snapshot-decision`,并拒绝把抓取当日未到 24:00 的日线标成完整收盘,
@@ -152,7 +152,7 @@ A 股 Baseline 内核。它的新增得分必须在授权数据、真实平台
T 日 Signal 与 T+1 broker fact 绑定、完整 artifact verifier T 日 Signal 与 T+1 broker fact 绑定、完整 artifact verifier
- Colab 默认无账号流程,以及显式可选的 JQData/Qlib cell。 - Colab 默认无账号流程,以及显式可选的 JQData/Qlib cell。
最近一次 216-test suite、两条 Qlib fixture smoke 和 Tushare 最近一次 224-test suite、两条 Qlib fixture smoke 和 Tushare
managed-provider 技术 smoke 证明上述代码路径能执行, managed-provider 技术 smoke 证明上述代码路径能执行,
但仍明确不证明: 但仍明确不证明:
+1 -1
View File
@@ -5,7 +5,7 @@
| Path | Intended use | Runtime / prerequisite | Current verified fact | Missing release evidence | | Path | Intended use | Runtime / prerequisite | Current verified fact | Missing release evidence |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| Local synthetic execution | 确定性事件回测、ledger/replay | Python ≥3.10,无账号 | 标准库套件最近记录为 216 tests、OK、6 skipsmoke + exact manifest verifier 可运行 | synthetic 不代表真实市场/收益 | | Local synthetic execution | 确定性事件回测、ledger/replay | Python ≥3.10,无账号 | 标准库套件最近记录为 224 tests、OK、6 skipsmoke + exact manifest verifier 可运行 | synthetic 不代表真实市场/收益 |
| Local synthetic research | PIT/features/walk-forward/Ridge/risk/cost/target | Python ≥3.10,无账号 | research smoke + manifest verifier 可运行 | Ridge 未冻结部署,未做授权长样本 OOS | | Local synthetic research | PIT/features/walk-forward/Ridge/risk/cost/target | Python ≥3.10,无账号 | research smoke + manifest verifier 可运行 | Ridge 未冻结部署,未做授权长样本 OOS |
| JQData ingestion | 授权数据到 canonical immutable snapshot | `jqdatasdk==1.9.8` + 授权账号 | fake-provider 测试覆盖 raw/factor/pre-close/limits/paused/PIT `is_st`/membership、24:00 完整收盘约束和语义 verifier | 尚未登录真实账号保存快照、许可与 lineage | | JQData ingestion | 授权数据到 canonical immutable snapshot | `jqdatasdk==1.9.8` + 授权账号 | fake-provider 测试覆盖 raw/factor/pre-close/limits/paused/PIT `is_st`/membership、24:00 完整收盘约束和语义 verifier | 尚未登录真实账号保存快照、许可与 lineage |
| Snapshot local backtest | PIT membership 的 provider-data 本地回测 | semantic verifier 通过的 snapshot | `snapshot-backtest` 复用 production decision path,输出普通 run manifest | 尚无授权真实 snapshot;仍是本地 fill model | | Snapshot local backtest | PIT membership 的 provider-data 本地回测 | semantic verifier 通过的 snapshot | `snapshot-backtest` 复用 production decision path,输出普通 run manifest | 尚无授权真实 snapshot;仍是本地 fill model |
+2 -2
View File
@@ -33,9 +33,9 @@
"current_delivery": { "current_delivery": {
"score": null, "score": null,
"status": "not_scored", "status": "not_scored",
"reason": "Quant OS now has executable local pipelines, real Qlib fixture smokes, a checksummed incomplete Tushare-to-Qlib technical smoke and one completed real JoinQuant hosted smoke, but it has not produced complete adjusted PIT data, the same-input JoinQuant comparison, real QMT, broker-shadow, continuous reconciliation or compliance evidence required to score Baseline 60.", "reason": "Quant OS 已有可执行本地流水线、真实 Qlib fixture smoke、带校验但不完整的 TushareQlib 技术 smoke,以及一次完成的真实聚宽 hosted smoke;但仍缺完整复权 PIT 数据、同输入聚宽比较、真实 QMT、券商影子盘、连续对账与合规证据,因此不能计入 Baseline 60",
"verified_supporting_facts": [ "verified_supporting_facts": [
"The latest standard-library suite completed 216 tests with OK and 6 optional-runtime skips; the CPython 3.12 pyqlib environment completed the same 216 tests with the native Qlib smoke enabled and no skips.", "The latest standard-library suite completed 224 tests with OK and 6 optional-runtime skips; the CPython 3.12 pyqlib environment completed the same 224 tests with the native Qlib smoke enabled and no skips.",
"The JQData adapter maps raw bars, adjustment factor, previous close, daily limits, pause state, PIT is_st and daily PIT index membership into a semantically revalidated snapshot; it rejects an end date that has not reached the provider's complete daily-bar boundary, and only fake-provider tests have been run so far.", "The JQData adapter maps raw bars, adjustment factor, previous close, daily limits, pause state, PIT is_st and daily PIT index membership into a semantically revalidated snapshot; it rejects an end date that has not reached the provider's complete daily-bar boundary, and only fake-provider tests have been run so far.",
"The local snapshot can drive snapshot-backtest and snapshot-decision with manifest verification; it freezes a cross-checked provider trading calendar, and a T-close signal can bind only to a broker observation in the unique next session's Asia/Shanghai [09:00,09:30) window without collapsing the two clocks.", "The local snapshot can drive snapshot-backtest and snapshot-decision with manifest verification; it freezes a cross-checked provider trading calendar, and a T-close signal can bind only to a broker observation in the unique next session's Asia/Shanghai [09:00,09:30) window without collapsing the two clocks.",
"CPython 3.12 with pyqlib 0.9.7 completed a native momentum fixture smoke with 24 signals and saved audited portfolio-table hashes, bounds and recomputed metrics.", "CPython 3.12 with pyqlib 0.9.7 completed a native momentum fixture smoke with 24 signals and saved audited portfolio-table hashes, bounds and recomputed metrics.",
+1
View File
@@ -26,6 +26,7 @@ PYTHONPATH=src:. "${python_bin}" tools/export_mock_parity.py \
verify \ verify \
artifacts/mock-parity/report.json artifacts/mock-parity/report.json
PYTHONPATH=src:. "${python_bin}" tools/capability_probe.py PYTHONPATH=src:. "${python_bin}" tools/capability_probe.py
"${python_bin}" tools/build_public_status.py --check
"${python_bin}" tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb "${python_bin}" tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb
"${python_bin}" tools/run_colab_notebook.py \ "${python_bin}" tools/run_colab_notebook.py \
notebooks/quant_os_colab.ipynb \ notebooks/quant_os_colab.ipynb \
+2117
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+217
View File
@@ -0,0 +1,217 @@
import importlib.util
import json
import os
import re
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
PROJECT = Path(__file__).resolve().parents[1]
BUILDER_PATH = PROJECT / "tools" / "build_public_status.py"
OUTPUT_PATH = PROJECT / "status" / "status-data.js"
INDEX_PATH = PROJECT / "status" / "index.html"
PREFIX = "window.QUANT_OS_PUBLIC_STATUS = "
def _load_builder():
spec = importlib.util.spec_from_file_location("build_public_status", BUILDER_PATH)
if spec is None or spec.loader is None:
raise RuntimeError("cannot import public status builder")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def _read_payload(path=OUTPUT_PATH):
content = path.read_text(encoding="utf-8")
lines = content.splitlines()
if not lines or not lines[0].startswith("// Generated by"):
raise AssertionError("generated header is missing")
assignment = "\n".join(lines[1:])
if not assignment.startswith(PREFIX) or not assignment.endswith(";"):
raise AssertionError("unexpected JavaScript wrapper")
return json.loads(assignment[len(PREFIX) : -1])
class PublicStatusTests(unittest.TestCase):
def test_committed_status_data_has_no_drift(self):
result = subprocess.run(
[sys.executable, str(BUILDER_PATH), "--check"],
cwd=PROJECT,
check=False,
capture_output=True,
text=True,
)
self.assertEqual(result.returncode, 0, result.stderr)
payload = _read_payload()
self.assertEqual(payload["claim"]["status"], "NOT_BASELINE_60")
self.assertFalse(payload["claim"]["releaseVerified"])
self.assertFalse(payload["claim"]["liveReady"])
self.assertEqual(payload["claim"]["gatesPassed"], 0)
self.assertEqual(payload["claim"]["gatesTotal"], 10)
self.assertTrue(all(gate["status"] == "not_passed" for gate in payload["gates"]))
def test_public_payload_is_deliberately_non_secret_and_non_local(self):
payload = _read_payload()
encoded = json.dumps(payload, ensure_ascii=False, sort_keys=True)
self.assertNotRegex(
encoded,
re.compile(r"/(?:Users|home|root|private|var|tmp)/|[A-Za-z]:[\\/]"),
)
self.assertNotIn("RELEASE_VERIFIED", encoded)
self.assertNotIn("LIVE_READY", encoded)
lowered = encoded.lower()
for marker in (
"password",
"passwd",
"api_key",
"private_key",
"userdata_path",
):
self.assertNotIn(marker, lowered)
for evidence in payload["evidence"]:
self.assertFalse(Path(evidence["path"]).is_absolute())
self.assertNotIn("..", Path(evidence["path"]).parts)
def test_static_page_has_fail_closed_fallback_and_no_local_paths(self):
page = INDEX_PATH.read_text(encoding="utf-8")
self.assertIn('src="./status-data.js"', page)
self.assertGreaterEqual(page.count("STATUS DATA UNAVAILABLE"), 2)
self.assertIn("NOT_BASELINE_60", page)
self.assertIn("0 / 10", page)
self.assertIn("validatePublicData", page)
self.assertIn("platform.limitations", page)
self.assertNotIn("platform.missingReleaseEvidence", page)
self.assertNotRegex(
page,
re.compile(
r"(?:(?<=^)|(?<=[\s\"'=:(]))"
r"(?:/(?:Users|home|root|private|var|tmp)/|[A-Za-z]:[\\/])"
),
)
self.assertNotIn("quant-os/artifacts", page)
self.assertNotIn("quant-os/data", page)
for tag in re.findall(r"<a\\b[^>]*target=\"_blank\"[^>]*>", page):
self.assertIn('rel="noopener noreferrer"', tag)
def test_models_and_platforms_preserve_evidence_boundaries(self):
payload = _read_payload()
models = {model["id"]: model for model in payload["models"]}
self.assertEqual(
set(models),
{"portable-momentum-v1", "ridge-challenger", "alpha158-lightgbm"},
)
self.assertFalse(models["portable-momentum-v1"]["releaseVerified"])
self.assertFalse(models["ridge-challenger"]["investmentValueClaim"])
self.assertFalse(models["alpha158-lightgbm"]["investmentValueClaim"])
self.assertIn("synthetic", models["ridge-challenger"]["role"])
self.assertIn("synthetic", models["alpha158-lightgbm"]["limitations"][0])
platforms = {platform["name"]: platform for platform in payload["platforms"]}
self.assertEqual(platforms["JoinQuant hosted bundle"]["status"], "real_runtime")
self.assertEqual(platforms["QMT built-in bundle"]["status"], "implemented")
self.assertFalse(platforms["XtTrader read-only shadow"]["liveReady"])
self.assertIn("fake", platforms["XtTrader read-only shadow"]["claim"].lower())
def test_freshness_uses_daily_bars_not_the_later_trade_calendar(self):
payload = _read_payload()
freshness = {item["id"]: item for item in payload["freshness"]}
self.assertEqual(freshness["project-audit"]["value"], "2026-07-26")
self.assertEqual(
freshness["joinquant-hosted-market-window"]["marketDataThrough"],
"2024-12-31",
)
tushare = freshness["tushare-daily-market-data"]
self.assertEqual(tushare["completedPartitions"], 35)
self.assertEqual(tushare["plannedPartitions"], 428)
self.assertAlmostEqual(tushare["completionRatio"], 35 / 428, places=6)
self.assertEqual(tushare["marketDataThrough"], "1993-10-29")
self.assertFalse(tushare["productionReady"])
source = (PROJECT / "docs" / "TUSHARE_LOCAL_DATA.md").read_text(
encoding="utf-8"
)
self.assertRegex(source, r"`trade_cal`.*2026")
self.assertNotIn("2026", tushare["marketDataThrough"])
self.assertIn("daily", tushare["semantics"])
self.assertEqual(freshness["jqdata-real-snapshot"]["value"], "N/A")
self.assertEqual(freshness["jqdata-real-snapshot"]["status"], "blocked")
self.assertIsNone(
freshness["qmt-broker-real-runtime"]["lastRealRuntimeAt"]
)
self.assertEqual(
freshness["qmt-broker-real-runtime"]["status"], "blocked"
)
def test_explicit_timestamp_build_is_deterministic(self):
with tempfile.TemporaryDirectory() as temp_dir:
first = Path(temp_dir) / "first.js"
second = Path(temp_dir) / "second.js"
command = [
sys.executable,
str(BUILDER_PATH),
"--generated-at",
"2026-07-26T08:09:10+08:00",
]
subprocess.run(
[*command, "--output", str(first)],
cwd=PROJECT,
check=True,
capture_output=True,
text=True,
)
subprocess.run(
[*command, "--output", str(second)],
cwd=PROJECT,
check=True,
capture_output=True,
text=True,
)
self.assertEqual(first.read_bytes(), second.read_bytes())
payload = _read_payload(first)
self.assertEqual(payload["generatedAt"], "2026-07-26T00:09:10Z")
self.assertEqual(payload["generatedAtSource"], "argument")
def test_source_date_epoch_controls_timestamp(self):
with tempfile.TemporaryDirectory() as temp_dir:
output = Path(temp_dir) / "epoch.js"
environment = dict(os.environ)
environment["SOURCE_DATE_EPOCH"] = "0"
result = subprocess.run(
[
sys.executable,
str(BUILDER_PATH),
"--output",
str(output),
],
cwd=PROJECT,
env=environment,
check=False,
capture_output=True,
text=True,
)
self.assertEqual(result.returncode, 0, result.stderr)
payload = _read_payload(output)
self.assertEqual(payload["generatedAt"], "1970-01-01T00:00:00Z")
self.assertEqual(payload["generatedAtSource"], "source_date_epoch")
def test_builder_rejects_unearned_positive_claim(self):
module = _load_builder()
scorecard = {
"claim_policy": {
"baseline_threshold": 60,
"current_claim": "BASELINE_60",
},
"current_delivery": {"score": 59},
"gates": [{"id": "G1", "status": "not_passed"}],
}
with self.assertRaises(module.PublicStatusError):
module._validate_claim(scorecard)
if __name__ == "__main__":
unittest.main()
File diff suppressed because it is too large Load Diff