1 TradeItem介绍
TradeItem是ChartWidget的一个主图绘制部件,它的功能:
1)在成交单发生K线绘制成交单图形
2)当鼠标移动到成交单所在K线,在信息提示区提示成交的成交信息
2 TradeItem的实现
它是一个伪装成CandleItem的ScatterPlotItem。
class TradeItem(ScatterPlotItem,CandleItem):
"""
成交单绘图部件
"""
def __init__(self, manager: BarManager):
""""""
ScatterPlotItem.__init__(self)
# CandleItem.__init__(self,manager)
# super(TradeItem,self).__init__(manager)
super(CandleItem,self).__init__(manager)
self.blue_pen: QtGui.QPen = pg.mkPen(color=(100, 100, 255), width=2)
self.trades : Dict[int,Dict[str,TradeData]] = {} # {ix:{tradeid:trade}}
def add_trades(self,trades:List[TradeData]):
""" 增加成交单列表到TradeItem """
for trade in trades:
self.add_trade(trade)
self.set_scatter_data()
self.update()
def add_trade(self,trade:TradeData,draw:bool=False):
""" 增加一个成交单到TradeItem """
# 这里使用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 <= trade.datetime:
# print(f"【dt={dt},dt1={dt1},dt2={trade.datetime} ix={ix}】")
idx = ix
break
# 注意:一个bar期间可能发生多个成交单
if idx in self.trades:
self.trades[idx][trade.tradeid] = trade
else:
self.trades[idx] = {trade.tradeid:trade}
if draw:
self.set_scatter_data()
self.update()
# print(f"add_trade idx={idx} trade={trade}")
def set_scatter_data(self):
""" 把成交单列表绘制到ScatterPlotItem上 """
scatter_datas = []
for ix in self.trades:
for trade in self.trades[ix].values():
scatter = {
"pos" : (ix, trade.price),
"data": 1,
"size": 14,
"pen": pg.mkPen((255, 255, 255)),
}
if trade.direction == Direction.LONG:
scatter_symbol = "t1" # Up arrow
else:
scatter_symbol = "t" # Down arrow
if trade.offset == Offset.OPEN:
scatter_brush = pg.mkBrush((255, 255, 0)) # Yellow
else:
scatter_brush = pg.mkBrush((0, 0, 255)) # 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.trades:
for tradeid,trade in self.trades[ix].items():
# TradeData
text += f"成交:\n{trade.price}{trade.direction.value}{trade.offset.value}{trade.volume}手\n"
# else:
# text = f"{self.__class__}"
return text
3 测试效果
4 TradeItem的一点遗憾,有兴趣的可以帮忙改进
add_trade()中在查找成交单所属bar的ix的时候,代码效率不高,当self._manager._datetime_index_map很大的时候,可能存在效率问题。
希望有兴趣的大侠可以帮忙改进,然后贡献vnpy社区,代表社区先行谢过!