diff --git a/sanguo_trader/matcher.py b/sanguo_trader/matcher.py index 3f19e8f..7640776 100644 --- a/sanguo_trader/matcher.py +++ b/sanguo_trader/matcher.py @@ -72,6 +72,10 @@ def cross_order( fill_price = float(match_bar["open"]) elif order.match_session == MatchSession.CURRENT_CLOSE: fill_price = float(match_bar["close"]) + elif order.match_session == MatchSession.CALL_AUCTION: + # 集合竞价开盘价(最大成交量原则 → open)。当前同 NEXT_OPEN 定价; + # 未来区分开盘/尾盘集合竞价需扩枚举(CALL_AUCTION_OPEN/CLOSE)。 + fill_price = float(match_bar["open"]) else: return PaperReject( order.strategy_id, symbol, "unsupported_match_session", bar_date diff --git a/tests/trader/test_matcher.py b/tests/trader/test_matcher.py index cd6d019..4a115c7 100644 --- a/tests/trader/test_matcher.py +++ b/tests/trader/test_matcher.py @@ -110,11 +110,12 @@ def test_st_5pct_limit_up(): assert isinstance(r, PaperReject) and r.reason == "limit_up_locked" -def test_call_auction_session_rejected(): - """CALL_AUCTION 首版预留,不支持。""" +def test_call_auction_fills_at_open(): + """集合竞价撮合用开盘价(最大成交量原则 → open,分期项)。""" o = buy(market=True, session=MatchSession.CALL_AUCTION) - r = cross_order(o, mkbar(10.5, 11, 10.2, 10.8), PREV, CFG) - assert isinstance(r, PaperReject) and r.reason == "unsupported_match_session" + t = cross_order(o, mkbar(10.5, 11, 10.2, 10.8), PREV, CFG) + assert isinstance(t, PaperTrade) + assert t.price == 10.5 # 集合竞价开盘价 = open # ---- 限价单触价 ----