feat(trader): 软限额max_allocation(分期项)—每策略资金额度消除顺序依赖

spec §195: 多策略并发下单"先到后到"不可复现 → 每策略独立max_allocation
- StrategyRunner: max_allocation字段(默认inf) + used_allocation(持仓市值)
- engine._match: BUY cash_enough后查 used+成交额>max_allocation → 拒单max_allocation_exceeded
- live_orchestrator: runner传max_allocation(默认initial_capital)
- routes_paper: StrategyCfg加max_allocation(API→DB→live_step数据流)
- test_soft_limit: 3测试(累计超限拒单/默认不限/SELL不受限)

116 passed(113旧+3新), 无回归.
This commit is contained in:
2026-07-09 22:05:35 +08:00
parent 0810259911
commit 193064c953
5 changed files with 165 additions and 4 deletions
+5 -2
View File
@@ -34,6 +34,7 @@ class StrategyCfg(BaseModel):
match_session: str = "next_open"
symbol: str
listing_days: int = 0
max_allocation: float | None = None # 软限额(spec §195),None=用 initial_capital
class PaperCreateRequest(BaseModel):
@@ -168,8 +169,10 @@ def _run_replay(db, aid, req: PaperCreateRequest):
except Exception:
pass
cta.set_strategy(strat)
runners.append(StrategyRunner(s.name, strategy=strat, paper_cta_engine=cta,
symbol=s.symbol))
runners.append(StrategyRunner(
s.name, strategy=strat, paper_cta_engine=cta, symbol=s.symbol,
max_allocation=(s.max_allocation if s.max_allocation is not None
else req.initial_capital)))
pe = PaperEngine(account, runners, _DataSourceWrapper(data_cfg), acc_cfg,
db, aid, req.symbols, req.start, req.end, req.interval)
pe.run()