Skip to content

Commit 53cbf4b

Browse files
revise limit price valid logic (#931)
* revise limit price valid logic * update version * pr update * update --------- Co-authored-by: Don <lin.dongzhao@ricequant.com>
1 parent be9282d commit 53cbf4b

3 files changed

Lines changed: 25 additions & 28 deletions

File tree

rqalpha/mod/rqalpha_mod_sys_simulation/matcher.py

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# 详细的授权流程,请联系 public@ricequant.com 获取。
1717
import datetime
1818
from collections import defaultdict
19-
from copy import copy
19+
import math
2020
from rqalpha.const import MATCHING_TYPE, ORDER_TYPE, POSITION_EFFECT, SIDE
2121
from rqalpha.environment import Environment
2222
from rqalpha.core.events import EVENT, Event
@@ -25,11 +25,26 @@
2525
from rqalpha.model.tick import TickObject
2626
from rqalpha.portfolio.account import Account
2727
from rqalpha.utils import is_valid_price
28+
from rqalpha.interface import AbstractPriceBoard
2829
from typing import Dict
2930
from rqalpha.utils.i18n import gettext as _
3031
from .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+
3348
class 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:

tests/api_tests/test_position_queue.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ def test_future_position_queue_close_today():
272272
"start_date": "2016-03-07",
273273
"end_date": "2016-03-08",
274274
"accounts": {
275-
"future": 1000000
275+
"future": 10000000
276276
}
277277
}
278278
}
81 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)