perf(portfolio): #12 03 momentum_timing层2向量化—当日预取宽表+内存切片:handle_data牛市日1-2次批量SQL(熊市1次,原每日~13次:1 buy_sign+10行业rps+1-2 select,726天×13≈9000+次IO无跨日缓存,全周期>3h被_TIMEOUT kill);三处_cal_rps/_select_stocks/_cal_buy_sign切片优先+回退直查(预取失败/缺列/空切片→None回退,行为等价旧版);_panel_slice dropna(how=all)精确复刻provider直查行集语义(超集切片组外日期全NaN行会改iloc[0]/tail(N)口径,测试单stock场景抓出);_stock_pool当日缓存(预取+_find_stock_pool共享get_index_stocks+filters);+1回归测试断言牛市日get_closes_panel≤2次+每行业get_index_stocks 1次,22绿 [vps]
This commit is contained in:
@@ -395,6 +395,49 @@ class TestHandleData:
|
||||
assert len(buy_calls) >= 1
|
||||
assert any(c.args[0] == "CAND.XSHG" for c in buy_calls)
|
||||
|
||||
def test_bull_day_single_prefetch_queries(self):
|
||||
"""#12 层2向量化:牛市全流程 provider.get_closes_panel ≤2 次
|
||||
(指数预取 + 股票池预取;原每日 ~13 次),get_index_stocks 每行业仅 1 次
|
||||
(_stock_pool 当日缓存,_find_stock_pool 复用)。
|
||||
"""
|
||||
cfg = MomentumTimingConfig(
|
||||
index_list=["IDX1.XSHG", "IDX2.XSHG"], top_k=6,
|
||||
ma_short=5, ma_long=15,
|
||||
)
|
||||
s = make_strategy(
|
||||
index_stocks_map={
|
||||
"IDX1.XSHG": ["A.XSHG"], "IDX2.XSHG": ["B.XSHG"],
|
||||
},
|
||||
config=cfg,
|
||||
)
|
||||
panel_calls: List[Any] = []
|
||||
|
||||
def _gcp(symbols, start=None, end=None, interval="d", fq="raw"):
|
||||
panel_calls.append(list(symbols) if isinstance(symbols, list) else symbols)
|
||||
syms = list(symbols)
|
||||
if all(s.startswith("IDX") for s in syms):
|
||||
return _make_close_wide(syms, [[20.0 + i for i in range(30)]] * len(syms), days=30)
|
||||
return _make_close_wide(syms, [[10.0 + i for i in range(15)]] * len(syms), days=15)
|
||||
|
||||
s.provider.get_closes_panel.side_effect = _gcp
|
||||
ctx = FakeContext(
|
||||
current_dt=datetime(2024, 10, 8, 9, 30),
|
||||
previous_date="2024-09-30", positions={}, cash=1_000_000,
|
||||
)
|
||||
s.handle_data(ctx)
|
||||
# 预取收敛:牛市日 ≤2 次批量 SQL(原 1 buy_sign + 10 rps + 1-2 select ≈13)
|
||||
assert len(panel_calls) <= 2, panel_calls
|
||||
# _stock_pool 缓存:每行业 get_index_stocks 只查 1 次(handle_data 预取
|
||||
# + _find_stock_pool 复用)
|
||||
idx_calls = [
|
||||
c for c in s.provider.get_index_stocks.call_args_list
|
||||
if c.args and str(c.args[0]).startswith("IDX")
|
||||
]
|
||||
assert len(idx_calls) == 2, idx_calls
|
||||
# 全流程仍有买入(链路活)
|
||||
buys = [c for c in s.broker.order_target_value.call_args_list if c.args[1] != 0]
|
||||
assert buys
|
||||
|
||||
def test_handle_data_uses_current_dt_not_today(self):
|
||||
"""⚠️ 修复原始 bug 验证:handle_data 必须用 context.current_dt 计算 cur_date,
|
||||
不能用 datetime.date.today()(后者取真实今天)。
|
||||
|
||||
Reference in New Issue
Block a user