fix(HEL-494): 数据中枢独占调度,主网站不再回退旧接口

主网站只向中枢要业务数据;来源选择、切源、补数全部在中枢内部完成,失败不再走东财/腾讯/Tushare 保底。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
总工
2026-09-08 21:43:31 +08:00
co-authored by Cursor multica-agent
parent ef13d6feb5
commit 0b8419abca
23 changed files with 1159 additions and 368 deletions
+111
View File
@@ -0,0 +1,111 @@
from __future__ import annotations
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch
from datahub.adapters.tushare import TushareAdapter
from datahub.crypto import SecretVault
from datahub.hub import Hub
from datahub.settings import Settings
from tests.fixtures import TRADE_DATE, fake_transport
class StewardQueryTests(unittest.TestCase):
def setUp(self) -> None:
self.tmp = tempfile.TemporaryDirectory()
settings = Settings(
host="127.0.0.1",
port=0,
encryption_key=SecretVault.generate_key(),
api_token="k" * 32,
admin_password="StartPass1",
tushare_token="tushare-secret-token-xyz",
db_path=Path(self.tmp.name) / "hub.db",
backup_dir=Path(self.tmp.name) / "backups",
scheduler_enabled=False,
quality={"daily_row_ratio": 0.5, "null_rate_max": 0.5, "list_limit_default": 5000, "list_limit_max": 5000},
)
adapter = TushareAdapter("tushare-secret-token-xyz", transport=fake_transport)
self.hub = Hub(settings, adapter=adapter)
self.hub.pipeline.ingest_reference(TRADE_DATE)
for dataset in ("daily", "valuation", "moneyflow", "auction", "index_daily"):
self.hub.pipeline.run_dataset(dataset, TRADE_DATE)
def tearDown(self) -> None:
self.hub.stop()
self.tmp.cleanup()
def test_published_daily_is_tushare_native(self) -> None:
payload = self.hub.api.query_api(
{"api_name": "daily", "params": {"trade_date": TRADE_DATE}, "fields": "ts_code,close,vol,amount"}
)
rows = payload["data"]
by_code = {row["ts_code"]: row for row in rows}
self.assertEqual(by_code["600000.SH"]["vol"], 1000.0)
self.assertEqual(by_code["600000.SH"]["amount"], 2000.0)
self.assertEqual(payload["meta"]["row_shape"], "tushare")
def test_live_stk_limit_uses_internal_tushare(self) -> None:
payload = self.hub.api.query_api(
{"api_name": "stk_limit", "params": {"trade_date": TRADE_DATE}, "fields": "ts_code,up_limit,down_limit"}
)
self.assertEqual(payload["meta"]["source"], "tushare")
self.assertEqual(payload["data"][0]["ts_code"], "600000.SH")
def test_rt_sw_k_is_blocked(self) -> None:
from datahub.serving import ApiError
with self.assertRaises(ApiError):
self.hub.api.query_api({"api_name": "rt_sw_k", "params": {"ts_code": "801074.SI"}})
def test_rt_k_uses_free_quotes_not_tushare(self) -> None:
quotes = [
{
"ts_code": "600000.SH",
"name": "浦发银行",
"close": 10.2,
"pre_close": 10.0,
"open": 10.1,
"high": 10.3,
"low": 9.9,
"vol": 1000,
"amount": 2000000,
}
]
with patch("datahub.steward.fetch_quotes", return_value={"data": quotes, "meta": {"source": "eastmoney:ulist", "stale": False}}):
payload = self.hub.api.query_api({"api_name": "rt_k", "params": {"ts_code": "600000.SH"}})
self.assertEqual(payload["data"][0]["close"], 10.2)
self.assertEqual(payload["meta"]["source"], "eastmoney:ulist")
def test_shenwan_quote_uses_eastmoney_90_prefix(self) -> None:
from datahub.adapters.eastmoney import EastmoneyAdapter
with patch.object(EastmoneyAdapter, "_get_json") as get_json:
get_json.return_value = {
"data": {
"diff": [
{
"f12": "801074",
"f14": "工业金属",
"f2": 1234.5,
"f3": 2.88,
"f18": 1200,
"f17": 1205,
"f15": 1240,
"f16": 1198,
"f6": 1,
"f124": 1757319000,
}
]
}
}
quote = EastmoneyAdapter().fetch_shenwan_quote("801074.SI")
self.assertEqual(quote["source"], "eastmoney_sw")
self.assertAlmostEqual(quote["change"], 2.88)
self.assertEqual(get_json.call_args.args[1]["secids"], "90.801074")
if __name__ == "__main__":
unittest.main()