diff --git a/vnpy/app/algo_trading/algos/iceberg_algo.py b/vnpy/app/algo_trading/algos/iceberg_algo.py index e69de29b..74ab7f44 100644 --- a/vnpy/app/algo_trading/algos/iceberg_algo.py +++ b/vnpy/app/algo_trading/algos/iceberg_algo.py @@ -0,0 +1,137 @@ +from vnpy.trader.constant import Offset, Direction +from vnpy.trader.object import TradeData, OrderData, TickData +from vnpy.trader.engine import BaseEngine + +from vnpy.app.algo_trading import AlgoTemplate + + +class IcebergAlgo(AlgoTemplate): + """""" + + display_name = "Iceberg 冰山" + + default_setting = { + "vt_symbol": "", + "direction": [Direction.LONG.value, Direction.SHORT.value], + "price": 0.0, + "volume": 0.0, + "display_volume": 0.0, + "interval": 0, + "offset": [ + Offset.NONE.value, + Offset.OPEN.value, + Offset.CLOSE.value, + Offset.CLOSETODAY.value, + Offset.CLOSEYESTERDAY.value + ] + } + + variables = [ + "traded", + "timer_count", + "vt_orderid" + ] + + def __init__( + self, + algo_engine: BaseEngine, + algo_name: str, + setting: dict + ): + """""" + super().__init__(algo_engine, algo_name, setting) + + # Parameters + self.vt_symbol = setting["vt_symbol"] + self.direction = Direction(setting["direction"]) + self.price = setting["price"] + self.volume = setting["volume"] + self.display_volume = setting["display_volume"] + self.interval = setting["interval"] + self.offset = Offset(setting["offset"]) + + # Variables + self.timer_count = 0 + self.vt_orderid = "" + self.traded = 0 + + self.last_tick = None + + self.subscribe(self.vt_symbol) + self.put_parameters_event() + self.put_variables_event() + + def on_stop(self): + """""" + self.write_log("停止算法") + + def on_tick(self, tick: TickData): + """""" + self.last_tick = tick + + def on_order(self, order: OrderData): + """""" + msg = f"委托号:{order.vt_orderid},委托状态:{order.status.value}" + self.write_log(msg) + + if not order.is_active(): + self.vt_orderid = "" + self.put_variables_event() + + def on_trade(self, trade: TradeData): + """""" + self.traded += trade.volume + + if self.traded >= self.volume: + self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") + self.stop() + else: + self.put_variables_event() + + def on_timer(self): + """""" + self.timer_count += 1 + + if self.timer_count < self.interval: + self.put_variables_event() + return + + self.timer_count = 0 + + contract = self.get_contract(self.vt_symbol) + if not contract: + return + + # If order already finished, just send new order + if not self.vt_orderid: + order_volume = self.volume - self.traded + order_volume = min(order_volume, self.display_volume) + + if self.direction == Direction.LONG: + self.vt_orderid = self.buy( + self.vt_symbol, + self.price, + order_volume, + offset=self.offset + ) + else: + self.vt_orderid = self.sell( + self.vt_symbol, + self.price, + order_volume, + offset=self.offset + ) + # Otherwise check for cancel + else: + if self.direction == Direction.LONG: + if self.last_tick.ask_price_1 <= self.price: + self.cancel_order(self.vt_orderid) + self.vt_orderid = "" + self.write_log(u"最新Tick卖一价,低于买入委托价格,之前委托可能丢失,强制撤单") + else: + if self.last_tick.bid_price_1 >= self.price: + self.cancel_order(self.vt_orderid) + self.vt_orderid = "" + self.write_log(u"最新Tick买一价,高于卖出委托价格,之前委托可能丢失,强制撤单") + + self.put_variables_event() diff --git a/vnpy/app/algo_trading/algos/sniper_algo.py b/vnpy/app/algo_trading/algos/sniper_algo.py index e69de29b..5f4b1c56 100644 --- a/vnpy/app/algo_trading/algos/sniper_algo.py +++ b/vnpy/app/algo_trading/algos/sniper_algo.py @@ -0,0 +1,101 @@ +from vnpy.trader.constant import Offset, Direction +from vnpy.trader.object import TradeData, OrderData, TickData +from vnpy.trader.engine import BaseEngine + +from vnpy.app.algo_trading import AlgoTemplate + + +class SniperAlgo(AlgoTemplate): + """""" + + display_name = "Sniper 狙击手" + + default_setting = { + "vt_symbol": "", + "direction": [Direction.LONG.value, Direction.SHORT.value], + "price": 0.0, + "volume": 0.0, + "offset": [ + Offset.NONE.value, + Offset.OPEN.value, + Offset.CLOSE.value, + Offset.CLOSETODAY.value, + Offset.CLOSEYESTERDAY.value + ] + } + + variables = [ + "traded", + "vt_orderid" + ] + + def __init__( + self, + algo_engine: BaseEngine, + algo_name: str, + setting: dict + ): + """""" + super().__init__(algo_engine, algo_name, setting) + + # Parameters + self.vt_symbol = setting["vt_symbol"] + self.direction = Direction(setting["direction"]) + self.price = setting["price"] + self.volume = setting["volume"] + self.offset = Offset(setting["offset"]) + + # Variables + self.vt_orderid = "" + self.traded = 0 + + self.subscribe(self.vt_symbol) + self.put_parameters_event() + self.put_variables_event() + + def on_tick(self, tick: TickData): + """""" + if self.vt_orderid: + self.cancel_all() + return + + if self.direction == Direction.LONG: + if tick.ask_price_1 <= self.price: + order_volume = self.volume - self.traded + order_volume = min(order_volume, tick.ask_volume_1) + + self.vt_orderid = self.buy( + self.vt_symbol, + self.price, + order_volume, + offset=self.offset + ) + else: + if tick.bid_price_1 >= self.price: + order_volume = self.volume - self.traded + order_volume = min(order_volume, tick.bid_volume_1) + + self.vt_orderid = self.sell( + self.vt_symbol, + self.price, + order_volume, + offset=self.offset + ) + + self.put_variables_event() + + def on_order(self, order: OrderData): + """""" + if not order.is_active(): + self.vt_orderid = "" + self.put_variables_event() + + def on_trade(self, trade: TradeData): + """""" + self.traded += trade.volume + + if self.traded >= self.volume: + self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") + self.stop() + else: + self.put_variables_event() diff --git a/vnpy/app/algo_trading/algos/twap_algo.py b/vnpy/app/algo_trading/algos/twap_algo.py index 32fc6a65..ebd24833 100644 --- a/vnpy/app/algo_trading/algos/twap_algo.py +++ b/vnpy/app/algo_trading/algos/twap_algo.py @@ -26,6 +26,13 @@ class TwapAlgo(AlgoTemplate): ] } + variables = [ + "traded", + "order_volume", + "timer_count", + "total_count" + ] + def __init__( self, algo_engine: BaseEngine, @@ -50,13 +57,6 @@ class TwapAlgo(AlgoTemplate): self.total_count = 0 self.traded = 0 - self.variables.extend([ - "traded", - "order_volume", - "timer_count", - "total_count" - ]) - self.subscribe(self.vt_symbol) self.put_parameters_event() self.put_variables_event() @@ -66,6 +66,7 @@ class TwapAlgo(AlgoTemplate): self.traded += trade.volume if self.traded >= self.volume: + self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.stop() else: self.put_variables_event() @@ -98,15 +99,7 @@ class TwapAlgo(AlgoTemplate): if tick.ask_price_1 <= self.price: self.buy(self.vt_symbol, self.price, order_volume, offset=self.offset) - self.write_log( - f"委托买入{self.vt_symbol}:{order_volume}@{self.price}") else: if tick.bid_price_1 >= self.price: self.sell(self.vt_symbol, self.price, order_volume, offset=self.offset) - self.write_log( - f"委托卖出{self.vt_symbol}:{order_volume}@{self.price}") - - def get_default_setting(self): - """""" - return self.default_setting diff --git a/vnpy/app/algo_trading/engine.py b/vnpy/app/algo_trading/engine.py index fe551043..8607cc71 100644 --- a/vnpy/app/algo_trading/engine.py +++ b/vnpy/app/algo_trading/engine.py @@ -44,8 +44,16 @@ class AlgoEngine(BaseEngine): def load_algo_template(self): """""" from .algos.twap_algo import TwapAlgo + from .algos.iceberg_algo import IcebergAlgo + from .algos.sniper_algo import SniperAlgo - self.algo_templates[TwapAlgo.__name__] = TwapAlgo + self.add_algo_template(TwapAlgo) + self.add_algo_template(IcebergAlgo) + self.add_algo_template(SniperAlgo) + + def add_algo_template(self, template: AlgoTemplate): + """""" + self.algo_templates[template.__name__] = template def load_algo_setting(self): """""" diff --git a/vnpy/app/algo_trading/template.py b/vnpy/app/algo_trading/template.py index 758e526f..609641af 100644 --- a/vnpy/app/algo_trading/template.py +++ b/vnpy/app/algo_trading/template.py @@ -96,6 +96,8 @@ class AlgoTemplate: self.on_stop() self.put_variables_event() + self.write_log("停止算法") + def subscribe(self, vt_symbol): """""" self.algo_engine.subscribe(self, vt_symbol) @@ -109,6 +111,9 @@ class AlgoTemplate: offset: Offset = Offset.NONE ): """""" + msg = f"委托买入{vt_symbol}:{volume}@{price}" + self.write_log(msg) + return self.algo_engine.send_order( self, vt_symbol, @@ -128,6 +133,9 @@ class AlgoTemplate: offset: Offset = Offset.NONE ): """""" + msg = f"委托卖出{vt_symbol}:{volume}@{price}" + self.write_log(msg) + return self.algo_engine.send_order( self, vt_symbol, diff --git a/vnpy/app/algo_trading/ui/display.py b/vnpy/app/algo_trading/ui/display.py index 8d6b991b..4f7b9502 100644 --- a/vnpy/app/algo_trading/ui/display.py +++ b/vnpy/app/algo_trading/ui/display.py @@ -11,5 +11,6 @@ NAME_DISPLAY_MAP = { "order_volume": "单笔委托", "timer_count": "本轮读秒", "total_count": "累计读秒", - "template_name": "算法模板" + "template_name": "算法模板", + "display_volume": "挂出数量" } diff --git a/vnpy/app/algo_trading/ui/widget.py b/vnpy/app/algo_trading/ui/widget.py index 57976d92..111d599a 100644 --- a/vnpy/app/algo_trading/ui/widget.py +++ b/vnpy/app/algo_trading/ui/widget.py @@ -554,6 +554,10 @@ class AlgoManager(QtWidgets.QWidget): widget = self.algo_widgets[template_name] widget.update_setting(setting_name, setting) + ix = self.template_combo.findData(template_name) + self.template_combo.setCurrentIndex(ix) + self.show_algo_widget() + def show(self): """""" self.showMaximized()