1616# 详细的授权流程,请联系 public@ricequant.com 获取。
1717import datetime
1818from collections import defaultdict
19- from copy import copy
19+ import math
2020from rqalpha .const import MATCHING_TYPE , ORDER_TYPE , POSITION_EFFECT , SIDE
2121from rqalpha .environment import Environment
2222from rqalpha .core .events import EVENT , Event
2525from rqalpha .model .tick import TickObject
2626from rqalpha .portfolio .account import Account
2727from rqalpha .utils import is_valid_price
28+ from rqalpha .interface import AbstractPriceBoard
2829from typing import Dict
2930from rqalpha .utils .i18n import gettext as _
3031from .slippage import SlippageDecider
3132
3233
34+ LIMIT_PRICE_VALID_THRESHOLD = 1e-7
35+
36+
37+ def _price_reaches_limit (order_book_id : str , side : SIDE , deal_price : float , price_board : AbstractPriceBoard ):
38+ if side == SIDE .BUY :
39+ limit_price = price_board .get_limit_up (order_book_id )
40+ return deal_price >= limit_price or math .isclose (deal_price , limit_price , abs_tol = LIMIT_PRICE_VALID_THRESHOLD )
41+ elif side == SIDE .SELL :
42+ limit_price = price_board .get_limit_down (order_book_id )
43+ return deal_price <= limit_price or math .isclose (deal_price , limit_price , abs_tol = LIMIT_PRICE_VALID_THRESHOLD )
44+ else :
45+ raise ValueError (f"Unsupport side: { side } " )
46+
47+
3348class AbstractMatcher :
3449 def match (self , account , order , open_auction ):
3550 # type: (Account, Order, bool) -> None
@@ -127,8 +142,6 @@ def match(self, account, order, open_auction):
127142 else :
128143 # 撮合的时候无行情数据也不需要撤单,等到有行情再撮合
129144 reason = None
130- # reason = _(u"Order Cancelled: current bar [{order_book_id}] miss market data.").format(
131- # order_book_id=order.order_book_id)
132145 if reason :
133146 order .mark_rejected (reason )
134147 return
@@ -141,22 +154,14 @@ def match(self, account, order, open_auction):
141154 return
142155 # 是否限制涨跌停不成交
143156 if self ._price_limit :
144- if order .side == SIDE .BUY and deal_price >= price_board .get_limit_up (order_book_id ):
145- return
146- if order .side == SIDE .SELL and deal_price <= price_board .get_limit_down (order_book_id ):
157+ if _price_reaches_limit (order_book_id , order .side , deal_price , price_board ):
147158 return
148159 else :
149160 if self ._price_limit :
150- if order .side == SIDE .BUY and deal_price >= price_board .get_limit_up (order_book_id ):
151- reason = _ (
152- "Order Cancelled: current bar [{order_book_id}] reach the limit_up price."
153- ).format (order_book_id = order .order_book_id )
154- order .mark_rejected (reason )
155- return
156- if order .side == SIDE .SELL and deal_price <= price_board .get_limit_down (order_book_id ):
161+ if _price_reaches_limit (order_book_id , order .side , deal_price , price_board ):
157162 reason = _ (
158- "Order Cancelled: current bar [{order_book_id}] reach the limit_down price."
159- ).format (order_book_id = order .order_book_id )
163+ "Order Cancelled: current bar [{order_book_id}] reach the {limit_up_or_down} price."
164+ ).format (order_book_id = order .order_book_id , limit_up_or_down = "limit_up" if order . side == SIDE . BUY else "limit_down" )
160165 order .mark_rejected (reason )
161166 return
162167
@@ -372,9 +377,7 @@ def match(self, account, order, open_auction): # type: (Account, Order, bool) -
372377 return
373378 # 是否限制涨跌停不成交
374379 if self ._price_limit :
375- if order .side == SIDE .BUY and deal_price >= price_board .get_limit_up (order_book_id ):
376- return
377- if order .side == SIDE .SELL and deal_price <= price_board .get_limit_down (order_book_id ):
380+ if _price_reaches_limit (order_book_id , order .side , deal_price , price_board ):
378381 return
379382 if self ._liquidity_limit :
380383 if order .side == SIDE .BUY and price_board .get_a1 (order_book_id ) == 0 :
@@ -383,16 +386,10 @@ def match(self, account, order, open_auction): # type: (Account, Order, bool) -
383386 return
384387 else :
385388 if self ._price_limit :
386- if order .side == SIDE .BUY and deal_price >= price_board .get_limit_up (order_book_id ):
387- reason = _ (
388- "Order Cancelled: current tick [{order_book_id}] reach the limit_up price."
389- ).format (order_book_id = order .order_book_id )
390- order .mark_rejected (reason )
391- return
392- if order .side == SIDE .SELL and deal_price <= price_board .get_limit_down (order_book_id ):
389+ if _price_reaches_limit (order_book_id , order .side , deal_price , price_board ):
393390 reason = _ (
394- "Order Cancelled: current tick [{order_book_id}] reach the limit_down price."
395- ).format (order_book_id = order .order_book_id )
391+ "Order Cancelled: current tick [{order_book_id}] reach the {limit_up_or_down} price."
392+ ).format (order_book_id = order .order_book_id , limit_up_or_down = "limit_up" if order . side == SIDE . BUY else "limit_down" )
396393 order .mark_rejected (reason )
397394 return
398395 if self ._liquidity_limit :
0 commit comments