diff --git a/vnpy/app/algo_trading/algos/best_limit_algo.py b/vnpy/app/algo_trading/algos/best_limit_algo.py new file mode 100644 index 00000000..1fc252ea --- /dev/null +++ b/vnpy/app/algo_trading/algos/best_limit_algo.py @@ -0,0 +1,112 @@ +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 BestLimitAlgo(AlgoTemplate): + """""" + + display_name = "BestLimit 最优限价" + + default_setting = { + "vt_symbol": "", + "direction": [Direction.LONG.value, Direction.SHORT.value], + "volume": 0.0, + "offset": [ + Offset.NONE.value, + Offset.OPEN.value, + Offset.CLOSE.value, + Offset.CLOSETODAY.value, + Offset.CLOSEYESTERDAY.value + ] + } + + variables = [ + "traded", + "vt_orderid", + "order_price", + "last_tick", + ] + + 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.volume = setting["volume"] + self.offset = Offset(setting["offset"]) + + # Variables + self.vt_orderid = "" + self.traded = 0 + self.last_tick = None + self.order_price = 0 + + self.subscribe(self.vt_symbol) + self.put_parameters_event() + self.put_variables_event() + + def on_tick(self, tick: TickData): + """""" + self.last_tick = tick + + if self.direction == Direction.LONG: + if not self.vt_orderid: + self.buy_best_limit() + elif self.order_price != self.last_tick.bid_price_1: + self.cancel_all() + else: + if not self.vt_orderid: + self.sell_best_limit() + elif self.order_price != self.last_tick.ask_price_1: + self.cancel_all() + + 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_order(self, order: OrderData): + """""" + if not order.is_active(): + self.vt_orderid = "" + self.order_price = 0 + self.put_variables_event() + + def buy_best_limit(self): + """""" + order_volume = self.volume - self.traded + self.order_price = self.last_tick.bid_price_1 + self.vt_orderid = self.buy( + self.vt_symbol, + self.order_price, + order_volume, + offset=self.offset + ) + + def sell_best_limit(self): + """""" + order_volume = self.volume - self.traded + self.order_price = self.last_tick.ask_price_1 + self.vt_orderid = self.sell( + self.vt_symbol, + self.order_price, + order_volume, + offset=self.offset + ) \ No newline at end of file diff --git a/vnpy/app/algo_trading/algos/stop_algo.py b/vnpy/app/algo_trading/algos/stop_algo.py new file mode 100644 index 00000000..54b45bf7 --- /dev/null +++ b/vnpy/app/algo_trading/algos/stop_algo.py @@ -0,0 +1,108 @@ +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 StopAlgo(AlgoTemplate): + """""" + + display_name = "Stop 条件委托" + + default_setting = { + "vt_symbol": "", + "direction": [Direction.LONG.value, Direction.SHORT.value], + "stop_price": 0.0, + "volume": 0.0, + "price_add": 0.0, + "offset": [ + Offset.NONE.value, + Offset.OPEN.value, + Offset.CLOSE.value, + Offset.CLOSETODAY.value, + Offset.CLOSEYESTERDAY.value + ] + } + + variables = [ + "traded", + "vt_orderid", + "order_status", + ] + + 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.stop_price = setting["stop_price"] + self.volume = setting["volume"] + self.price_add = setting["price_add"] + self.offset = Offset(setting["offset"]) + + # Variables + self.vt_orderid = "" + self.traded = 0 + self.order_status = "" + + self.subscribe(self.vt_symbol) + self.put_parameters_event() + self.put_variables_event() + + def on_tick(self, tick: TickData): + """""" + if self.vt_orderid: + return + + if self.direction == Direction.LONG: + if tick.last_price >= self.stop_price: + price = self.stop_price + self.price_add + + if tick.limit_up: + price = min(price, tick.limit_up) + + self.vt_orderid = self.buy( + self.vt_symbol, + price, + self.volume, + offset=self.offset + ) + self.write_log(f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.stop_price},数量:{self.volume},开平:{self.offset}") + + else: + if tick.last_price <= self.stop_price: + price = self.stop_price - self.price_add + + if tick.limit_down: + price = max(price, tick.limit_down) + + self.vt_orderid = self.buy( + self.vt_symbol, + price, + self.volume, + offset=self.offset + ) + self.write_log(f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.stop_price},数量:{self.volume},开平:{self.offset}") + + self.put_variables_event() + + def on_order(self, order: OrderData): + """""" + self.traded = order.traded + self.order_status = order.status + + if not order.is_active(): + self.stop() + self.put_variables_event() + + def on_trade(self, trade: TradeData): + """""" + pass diff --git a/vnpy/app/algo_trading/engine.py b/vnpy/app/algo_trading/engine.py index 9429e06a..81949739 100644 --- a/vnpy/app/algo_trading/engine.py +++ b/vnpy/app/algo_trading/engine.py @@ -46,10 +46,14 @@ class AlgoEngine(BaseEngine): from .algos.twap_algo import TwapAlgo from .algos.iceberg_algo import IcebergAlgo from .algos.sniper_algo import SniperAlgo + from .algos.stop_algo import StopAlgo + from .algos.best_limit_algo import BestLimitAlgo self.add_algo_template(TwapAlgo) self.add_algo_template(IcebergAlgo) self.add_algo_template(SniperAlgo) + self.add_algo_template(StopAlgo) + self.add_algo_template(BestLimitAlgo) def add_algo_template(self, template: AlgoTemplate): """"""