feat: operationalize local Tushare Qlib research
This commit is contained in:
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user