feat: operationalize local Tushare Qlib research

This commit is contained in:
2026-07-31 01:26:49 +08:00
parent f81c116bfe
commit 6275370afc
21 changed files with 4438 additions and 401 deletions
+82 -7
View File
@@ -76,6 +76,8 @@ class PublicStatusTests(unittest.TestCase):
self.assertFalse(payload["marketScope"]["bseTradingEnabled"])
self.assertIn("北交所", payload["marketScope"]["statement"])
self.assertIn("fail closed", payload["marketScope"]["statement"])
self.assertEqual(payload["summary"]["testsRecorded"], 325)
self.assertEqual(payload["summary"]["optionalSkipsRecorded"], 1)
def test_public_payload_is_deliberately_non_secret_and_non_local(self):
payload = _read_payload()
@@ -99,6 +101,25 @@ class PublicStatusTests(unittest.TestCase):
self.assertFalse(Path(evidence["path"]).is_absolute())
self.assertNotIn("..", Path(evidence["path"]).parts)
def test_public_tushare_claims_cannot_regress_to_early_mirror(self):
payload = _read_payload()
encoded = json.dumps(payload, ensure_ascii=False, sort_keys=True)
scorecard = (PROJECT / "gate_scorecard.json").read_text(
encoding="utf-8"
)
stale_claims = (
"93 个",
"8.2%",
"1993-10-29",
"CSI500-2018-2025/de9657cd",
"de5b96253ff765fa4e4be9736ddc2fad528f72c7721964313956d44b02969173",
"3c550c0ba986f7eb736b421ac318fdc2a58eacaa65cfbdeaf6b3f920b5288304",
"aed22a7b83e4defd45c4874e568d6aeafdabe43987cea301e0c1d09543dccb7c",
)
for stale_claim in stale_claims:
self.assertNotIn(stale_claim, encoded)
self.assertNotIn(stale_claim, scorecard)
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)
@@ -272,6 +293,10 @@ class PublicStatusTests(unittest.TestCase):
evidence["joinquant-target-package-evidence"]["path"],
"docs/JOINQUANT_TARGET_PACKAGE_EVIDENCE_2026-07-26.md",
)
self.assertEqual(
evidence["tushare-csi500-research-run"]["path"],
"evidence/tushare/CSI500-2018-2025/5bf19d2d/run.json",
)
gaps = payload["deliveryGaps"]
self.assertGreaterEqual(len(gaps["internal"]), 3)
@@ -374,7 +399,7 @@ class PublicStatusTests(unittest.TestCase):
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-30")
self.assertEqual(freshness["project-audit"]["value"], "2026-07-31")
self.assertEqual(
freshness["joinquant-hosted-market-window"]["marketDataThrough"],
"2024-12-31",
@@ -394,17 +419,67 @@ class PublicStatusTests(unittest.TestCase):
self.assertIn("G9", target_package["semantics"])
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.assertEqual(tushare["status"], "research_only")
self.assertEqual(tushare["completedPartitions"], 96)
self.assertEqual(tushare["plannedPartitions"], 96)
self.assertEqual(tushare["completionRatio"], 1.0)
self.assertEqual(tushare["completedRows"], 8_813_885)
self.assertEqual(tushare["marketDataFrom"], "2018-01-02")
self.assertEqual(tushare["marketDataThrough"], "2025-12-31")
self.assertEqual(
(tushare["verifiedSnapshotJobs"], tushare["snapshotJobs"]),
(221, 221),
)
self.assertEqual(tushare["providerFiles"], 10_011)
self.assertEqual(tushare["providerBytes"], 71_707_194)
self.assertEqual(tushare["calendarSessions"], 1_942)
self.assertEqual(tushare["instrumentCount"], 1_111)
self.assertEqual(tushare["selectedDailyRows"], 1_975_455)
self.assertEqual(tushare["observedMembershipSnapshots"], 97)
self.assertEqual(tushare["effectiveMembershipSnapshots"], 96)
self.assertFalse(tushare["sameSessionMembershipUse"])
self.assertTrue(tushare["sourceStable"])
self.assertTrue(tushare["stateDbChangedDuringVerification"])
self.assertTrue(tushare["converterSourceMatchesCurrent"])
self.assertEqual(
tushare["providerDataVersion"],
"5bf19d2da064357ad1802bca4bfa0c0505ed63fe2b24785ec6c56ecff1724963",
)
self.assertEqual(
tushare["providerManifestSha256"],
"27fb6fedb6a4b114eae2aba44505fb6c4d32c7a9ae81e58c724dfadb8dd10ed0",
)
self.assertEqual(tushare["sourceJobCount"], 221)
self.assertEqual(
tushare["lineageMatchedFields"],
[
"id",
"path",
"row_count",
"byte_count",
"sha256",
"request_sha256",
],
)
self.assertEqual(tushare["lineageMismatchCount"], 0)
self.assertEqual(
tushare["runSha256"],
"803035a95ee9cf6f90af20cdf7e7024149b97e0113b585209a80f80048be87d3",
)
self.assertEqual(tushare["signalRows"], 176_615)
self.assertEqual(tushare["portfolioDays"], 1_698)
self.assertFalse(tushare["productionReady"])
self.assertFalse(tushare["investmentValueClaim"])
self.assertEqual(tushare["gateCredit"], [])
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.assertIn("221/221", tushare["semantics"])
self.assertIn(
"tushare-csi500-research-run",
tushare["evidenceLinks"],
)
self.assertEqual(freshness["jqdata-real-snapshot"]["value"], "N/A")
self.assertEqual(freshness["jqdata-real-snapshot"]["status"], "blocked")