1 OrderItem介绍
OrderItem是ChartWidget的一个主图绘制部件,它的功能:
1)在委托发生K线绘制委托单图形
2)当鼠标移动到委托单所在K线,在信息提示区提示成交的最新委托信息,注意:是最新的!
2 OrderItem的实现
OrderItem也是一个伪装成CandleItem的ScatterPlotItem。
class OrderItem(ScatterPlotItem,CandleItem):
"""
委托单绘图部件
"""
def __init__(self, manager: BarManager):
""""""
ScatterPlotItem.__init__(self)
super(CandleItem,self).__init__(manager)
self.orders : Dict[int,Dict[str,Order]] = {} # {ix:{orderid:order}}
def add_orders(self,orders:List[OrderData]):
""" 增加委托单列表到OrderItem """
for order in orders:
if order.datetime:
self.add_order(order)
self.set_scatter_data()
self.update()
def add_order(self,order:OrderData,draw:bool=False):
""" 增加一个委托单到OrderItem """
# 这里使用reverse=True,是考虑到实盘成交往往发生在最新的bar里,可以加快搜索速度
od = OrderedDict(sorted(self._manager._datetime_index_map.items(),key = lambda t:t[0],reverse=True))
idx = self._manager.get_count() - 1
for dt,ix in od.items():
# print(f"dt={dt}\ntrade.datetime {trade.datetime}")
dt1 = CHINA_TZ.localize(datetime.combine(dt.date(),dt.time()))
if dt1 <= order.datetime:
print(f"【dt={dt},dt1={dt1},dt2={order.datetime} ix={ix}】")
idx = ix
break
# 注意:一个bar期间可能发生多个委托单
if idx in self.orders:
self.orders[idx][order.orderid] = order
else:
self.orders[idx] = {order.orderid:order}
if draw:
self.set_scatter_data()
self.update()
def set_scatter_data(self):
""" 把委托单列表绘制到ScatterPlotItem上 """
scatter_datas = []
for ix in self.orders:
lowest,highest=self.get_y_range()
# print(f"range={lowest,highest}")
for order in self.orders[ix].values():
# 处理委托报价超出显示范围的问题
if order.price>highest:
show_price = highest - 7
elif order.price<lowest:
show_price = lowest + 7
else:
show_price = order.price
scatter = {
"pos" : (ix, show_price),
"data": 1,
"size": 14,
"pen": pg.mkPen((255, 255, 255)),
}
if order.direction == Direction.LONG:
scatter_symbol = "t1" # Up arrow
else:
scatter_symbol = "t" # Down arrow
if order.offset == Offset.OPEN:
scatter_brush = pg.mkBrush((0, 128, 128)) # Yellow
else:
scatter_brush = pg.mkBrush((128, 128, 0)) # Blue
scatter["symbol"] = scatter_symbol
scatter["brush"] = scatter_brush
scatter_datas.append(scatter)
self.setData(scatter_datas)
def get_info_text(self, ix: int) -> str:
""""""
text = ""
if ix in self.orders:
for orderid,order in self.orders[ix].items():
# OrderData
text += f"委托:\n{order.price}{order.direction.value}{order.offset.value}{order.volume}手\n"
return text
3 测试效果
3.1 关于委托单绘制的一点说明:
- 委托单中的时间为None的没有绘制,它发生在send_order()函数执行,交易服务器刚接受委托申请之时,此时还没有任何成交,也没有进入等待队列,只是一种委托请求的确认。因此无法找到其发生的K线位置,所以无法绘制。
- 委托单绘制的位置不总代表委托的价格,为了照顾到状态的显示,将超出显示区域最高和最低的委托价的委托单,放在显示区的顶部和底部来显示,信息提示板中的委托单的文字描述包含准确的委托价格。
- 当然,市价委托单通常都是在其实际委托价格处显示的。
请看看下面的委托单记录可以明白了:
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_1', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3.0, traded=0, status=Status.SUBMITTING, datetime=None, reference='TTS-ag2012'),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_1', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 0, 1)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_1', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 0, 1)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_1', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=3, status=Status.ALLTRADED, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 0, 1)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_2', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3.0, traded=0, status=Status.SUBMITTING, datetime=None, reference='TTS-ag2012'),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_2', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 14, 46)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_2', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 14, 46)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_2', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=3, status=Status.ALLTRADED, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 14, 46)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_3', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3.0, traded=0, status=Status.SUBMITTING, datetime=None, reference='TTS-ag2012'),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_3', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 21, 59)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_3', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 21, 59)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_3', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=3, status=Status.ALLTRADED, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 21, 59)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_4', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3.0, traded=0, status=Status.SUBMITTING, datetime=None, reference='TTS-ag2012'),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_4', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 39, 53)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_4', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 39, 53)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_753490688_4', type=OrderType.LIMIT, direction=Direction.LONG, offset=Offset.OPEN, price=6494.0, volume=3, traded=3, status=Status.ALLTRADED, datetime=CHINA_TZ.localize(datetime(2020, 8, 13, 21, 39, 53)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_1962356227_1', type=OrderType.LIMIT, direction=Direction.SHORT, offset=Offset.CLOSEYESTERDAY, price=5870.0, volume=12.0, traded=0, status=Status.SUBMITTING, datetime=None, reference='TTS-ag2012'),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_1962356227_1', type=OrderType.LIMIT, direction=Direction.SHORT, offset=Offset.CLOSEYESTERDAY, price=5870.0, volume=12, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 14, 1, 44,20)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_1962356227_1', type=OrderType.LIMIT, direction=Direction.SHORT, offset=Offset.CLOSEYESTERDAY, price=5870.0, volume=12, traded=0, status=Status.SUBMITTING, datetime=CHINA_TZ.localize(datetime(2020, 8, 14, 1, 44,25)), reference=''),
OrderData(gateway_name='CTP', symbol='ag2012', exchange=Exchange.SHFE, orderid='3_1962356227_1', type=OrderType.LIMIT, direction=Direction.SHORT, offset=Offset.CLOSEYESTERDAY, price=5870.0, volume=12, traded=12, status=Status.ALLTRADED, datetime=CHINA_TZ.localize(datetime(2020, 8, 14, 1, 44,35)), reference=''),
4 OrderItem的一点遗憾,有兴趣的可以帮忙改进
add_order()中在查找委托单所属bar的ix的时候,代码效率不高,当self._manager._datetime_index_map很大的时候,可能存在效率问题。
希望有兴趣的大侠可以帮忙改进,让后贡献vnpy社区,代表社区先行谢过!