rebuild(runtime): govern market operations and job truth
This commit is contained in:
@@ -130,6 +130,59 @@ class TushareProvider:
|
||||
)
|
||||
return datasets
|
||||
|
||||
def realtime_market_inputs(
|
||||
self,
|
||||
trade_date: str,
|
||||
previous_trade_date: str,
|
||||
identifiers: tuple[str, ...],
|
||||
) -> dict[str, ProviderResult | dict[str, Any]]:
|
||||
current = _compact(trade_date)
|
||||
previous = _compact(previous_trade_date)
|
||||
quotes = self._query(
|
||||
"rt_k",
|
||||
{"ts_code": ",".join(identifiers)},
|
||||
"",
|
||||
unit="mixed",
|
||||
)
|
||||
normalized = tuple(
|
||||
{
|
||||
**row,
|
||||
"trade_date": current,
|
||||
"pct_chg": _change(row.get("close"), row.get("pre_close")),
|
||||
"amount_unit": "yuan",
|
||||
}
|
||||
for row in quotes.rows
|
||||
if _number(row.get("close")) > 0 and _number(row.get("pre_close")) > 0
|
||||
)
|
||||
daily = ProviderResult(
|
||||
normalized,
|
||||
replace(
|
||||
quotes.metadata,
|
||||
coverage=min(len(normalized) / max(len(identifiers), 1), 1),
|
||||
state=SnapshotState.REALTIME,
|
||||
),
|
||||
)
|
||||
return {
|
||||
"daily": daily,
|
||||
"price_limits": self._query(
|
||||
"stk_limit",
|
||||
{"trade_date": current},
|
||||
"ts_code,trade_date,up_limit,down_limit",
|
||||
unit="yuan/share",
|
||||
),
|
||||
"previous_limit_up": self._query(
|
||||
"limit_list_d",
|
||||
{"trade_date": previous, "limit_type": "U"},
|
||||
(
|
||||
"trade_date,ts_code,industry,name,close,pct_chg,amount,limit_amount,"
|
||||
"float_mv,total_mv,turnover_ratio,fd_amount,first_time,last_time,"
|
||||
"open_times,up_stat,limit_times"
|
||||
),
|
||||
unit="mixed",
|
||||
empty_is_complete=True,
|
||||
),
|
||||
}
|
||||
|
||||
def sector_members(self, representative: str, trade_date: str) -> ProviderResult:
|
||||
target = _compact(trade_date)
|
||||
industry, members = self._sector_memberships(representative, target)
|
||||
@@ -354,6 +407,9 @@ class TushareProvider:
|
||||
) -> ProviderResult:
|
||||
raise ProviderError("Tushare不提供动态竞价快照")
|
||||
|
||||
def event_reasons(self, trade_date: str) -> ProviderResult:
|
||||
raise ProviderError("Tushare涨跌停榜单不提供可用的事件原因字段")
|
||||
|
||||
def screener_inputs(self, trade_dates: tuple[str, ...]) -> dict[str, ProviderResult | None]:
|
||||
if len(trade_dates) < 21:
|
||||
raise ProviderError("选股因子至少需要21个交易日")
|
||||
@@ -628,6 +684,12 @@ def _display(value: str) -> str:
|
||||
return f"{compact[:4]}-{compact[4:6]}-{compact[6:]}"
|
||||
|
||||
|
||||
def _change(close: Any, previous: Any) -> float:
|
||||
current = _number(close)
|
||||
prior = _number(previous)
|
||||
return round((current / prior - 1) * 100, 4) if current > 0 and prior > 0 else 0.0
|
||||
|
||||
|
||||
def _quarter_periods(through: str, count: int) -> tuple[str, ...]:
|
||||
year = int(through[:4])
|
||||
quarter = (int(through[4:6]) - 1) // 3
|
||||
|
||||
Reference in New Issue
Block a user