Files
big-qmt/py-client/tests/test_orderbook.py
2026-09-15 20:02:05 +08:00

87 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""委托簿:在途状态、方向锁、以及撤单范围。"""
import unittest
from datetime import datetime, timedelta
from unittest.mock import Mock
from libs.order import BUSY_STATUSES, OrderBook, TRACKED_STATUSES
from sdk import OrderItem
def order(index, remark, status=50, side=23, age_minutes=30):
stamp = datetime.now() - timedelta(minutes=age_minutes)
return OrderItem(stock_code=f'60000{index}.SH', order_sys_id=f'sys{index}',
remark=remark, order_status=status, offset_flag=side,
insert_date=stamp.strftime('%Y%m%d'),
insert_time=stamp.strftime('%H%M%S'))
def cancelled(client):
return [call.args[0] for call in client.cancel_by_id.call_args_list]
class CancelScopeTests(unittest.TestCase):
"""撤单必须限本策略前缀;防重则继续看全账户在途。"""
def test_zt_prefix_cancels_only_its_own_orders(self):
orders = [order(0, 'zt-base-own'), order(1, 'zt-SELL-own'),
order(2, 'zt-entry-own'), order(3, 'IPO-new'),
order(4, ''), order(5, 'TREN-BUY-other')]
client = Mock()
book = OrderBook()
book.refresh(client, orders, cancel_prefix='zt-')
self.assertEqual(cancelled(client), ['sys0', 'sys1', 'sys2'])
self.assertEqual(book.data, orders) # 撤单后仍保留在途锁
self.assertTrue(all(book.busy(o.stock_code, 'BUY') for o in orders))
def test_default_prefix_still_cancels_every_non_ipo_order(self):
orders = [order(0, 'zt-base-own'), order(1, 'TREN-BUY-other'),
order(2, 'IPO-new'), order(3, '')]
client = Mock()
OrderBook().refresh(client, orders)
self.assertEqual(cancelled(client), ['sys0', 'sys1', 'sys3'])
def test_fresh_and_unreportable_orders_are_never_cancelled(self):
# 48未报在跟踪集合内但不可撤刚提交的委托也不撤。
orders = [order(0, 'zt-entry-fresh', age_minutes=0),
order(1, 'zt-entry-filled', status=56),
order(2, 'zt-entry-unreported', status=48)]
client = Mock()
book = OrderBook()
book.refresh(client, orders, cancel_prefix='zt-')
client.cancel_by_id.assert_not_called()
self.assertEqual(book.data, orders)
class BusyLockTests(unittest.TestCase):
def test_only_busy_statuses_lock_a_direction(self):
book = OrderBook()
client = Mock()
book.refresh(client, [order(0, 'zt-entry-a', status=50)], cancel_prefix='zt-')
self.assertTrue(book.busy('600000.SH', 'BUY'))
book.refresh(client, [order(1, 'zt-entry-b', status=56)], cancel_prefix='zt-')
self.assertFalse(book.busy('600001.SH', 'BUY'))
def test_busy_and_tracked_status_sets_are_disjoint_as_designed(self):
self.assertNotIn('56', BUSY_STATUSES)
self.assertTrue(BUSY_STATUSES <= TRACKED_STATUSES)
self.assertIn('56', TRACKED_STATUSES)
def test_place_marks_the_direction_busy_before_submitting(self):
book = OrderBook()
book.busy_cache.set('BUY-600000.SH', True, timeout=180)
self.assertTrue(book.busy('600000.SH', 'BUY'))
self.assertFalse(book.busy('600000.SH', 'SELL'))
def test_unknown_offset_flag_never_places_an_order(self):
from libs.order import PlaceOrderRequest
book = OrderBook()
client = Mock()
self.assertFalse(book.place(client, PlaceOrderRequest(99, '600000.SH', 100,
'zt-x', 'zt')))
client.passorder.assert_not_called()
if __name__ == '__main__':
unittest.main()