From 4aa372c91c3537f86696fd152efcdd0b2479dc00 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Fri, 4 Nov 2022 11:13:26 +0800 Subject: [PATCH 01/45] =?UTF-8?q?[Mod]=20algo=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E6=8C=87=E5=AE=9Avt=5Fsymbol=E4=BC=A0=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 10 ++++----- vnpy_algotrading/algos/dma_algo.py | 10 ++++----- vnpy_algotrading/algos/iceberg_algo.py | 12 +++++------ vnpy_algotrading/algos/sniper_algo.py | 10 ++++----- vnpy_algotrading/algos/stop_algo.py | 10 ++++----- vnpy_algotrading/algos/twap_algo.py | 16 ++++++-------- vnpy_algotrading/engine.py | 26 +++++++++++------------ vnpy_algotrading/template.py | 26 +++++++++++------------ 8 files changed, 53 insertions(+), 67 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index 52fd90f..5243ede 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -47,13 +47,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ): """""" - super().__init__(algo_engine, algo_name, setting) + super().__init__(algo_engine, algo_name, setting, vt_symbol) # 参数 - self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.volume = setting["volume"] self.offset = Offset(setting["offset"]) @@ -86,7 +86,7 @@ def __init__( self.stop() return - self.subscribe(self.vt_symbol) + self.subscribe() def on_tick(self, tick: TickData): """""" @@ -131,7 +131,6 @@ def buy_best_limit(self): 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 @@ -146,7 +145,6 @@ def sell_best_limit(self): 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 diff --git a/vnpy_algotrading/algos/dma_algo.py b/vnpy_algotrading/algos/dma_algo.py index 79aca34..b9f3822 100644 --- a/vnpy_algotrading/algos/dma_algo.py +++ b/vnpy_algotrading/algos/dma_algo.py @@ -41,13 +41,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ): """""" - super().__init__(algo_engine, algo_name, setting) + super().__init__(algo_engine, algo_name, setting, vt_symbol) # 参数 - self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.order_type = OrderType(setting["order_type"]) self.price = setting["price"] @@ -59,7 +59,7 @@ def __init__( self.traded = 0 self.order_status = "" - self.subscribe(self.vt_symbol) + self.subscribe() self.put_parameters_event() self.put_variables_event() @@ -68,7 +68,6 @@ def on_tick(self, tick: TickData): if not self.vt_orderid: if self.direction == Direction.LONG: self.vt_orderid = self.buy( - self.vt_symbol, self.price, self.volume, self.order_type, @@ -77,7 +76,6 @@ def on_tick(self, tick: TickData): else: self.vt_orderid = self.sell( - self.vt_symbol, self.price, self.volume, self.order_type, diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index 482aeaa..408b0a1 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -36,13 +36,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ): """""" - super().__init__(algo_engine, algo_name, setting) + super().__init__(algo_engine, algo_name, setting, vt_symbol) # 参数 - self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.price = setting["price"] self.volume = setting["volume"] @@ -57,7 +57,7 @@ def __init__( self.last_tick = None - self.subscribe(self.vt_symbol) + self.subscribe() self.put_parameters_event() self.put_variables_event() @@ -98,7 +98,7 @@ def on_timer(self): self.timer_count = 0 - contract = self.get_contract(self.vt_symbol) + contract = self.get_contract() if not contract: return @@ -109,14 +109,12 @@ def on_timer(self): 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 diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index 3feed9a..c337ba4 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -33,13 +33,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ): """""" - super().__init__(algo_engine, algo_name, setting) + super().__init__(algo_engine, algo_name, setting, vt_symbol) # 参数 - self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.price = setting["price"] self.volume = setting["volume"] @@ -49,7 +49,7 @@ def __init__( self.vt_orderid = "" self.traded = 0 - self.subscribe(self.vt_symbol) + self.subscribe() self.put_parameters_event() self.put_variables_event() @@ -65,7 +65,6 @@ def on_tick(self, tick: TickData): order_volume = min(order_volume, tick.ask_volume_1) self.vt_orderid = self.buy( - self.vt_symbol, self.price, order_volume, offset=self.offset @@ -76,7 +75,6 @@ def on_tick(self, tick: TickData): order_volume = min(order_volume, tick.bid_volume_1) self.vt_orderid = self.sell( - self.vt_symbol, self.price, order_volume, offset=self.offset diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index 3cca78b..b00aa44 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -35,13 +35,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ): """""" - super().__init__(algo_engine, algo_name, setting) + super().__init__(algo_engine, algo_name, setting, vt_symbol) # 参数 - self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.stop_price = setting["stop_price"] self.volume = setting["volume"] @@ -53,7 +53,7 @@ def __init__( self.traded = 0 self.order_status = "" - self.subscribe(self.vt_symbol) + self.subscribe() self.put_parameters_event() self.put_variables_event() @@ -70,7 +70,6 @@ def on_tick(self, tick: TickData): price = min(price, tick.limit_up) self.vt_orderid = self.buy( - self.vt_symbol, price, self.volume, offset=self.offset @@ -86,7 +85,6 @@ def on_tick(self, tick: TickData): price = max(price, tick.limit_down) self.vt_orderid = self.sell( - self.vt_symbol, price, self.volume, offset=self.offset diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index a1a8ce1..8644671 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -38,13 +38,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ): """""" - super().__init__(algo_engine, algo_name, setting) + super().__init__(algo_engine, algo_name, setting, vt_symbol) # 参数 - self.vt_symbol = setting["vt_symbol"] self.direction = Direction(setting["direction"]) self.price = setting["price"] self.volume = setting["volume"] @@ -54,7 +54,7 @@ def __init__( # 变量 self.order_volume = self.volume / (self.time / self.interval) - contract = self.get_contract(self.vt_symbol) + contract = self.get_contract() if contract: self.order_volume = round_to(self.order_volume, contract.min_volume) @@ -64,7 +64,7 @@ def __init__( self.last_tick = None - self.subscribe(self.vt_symbol) + self.subscribe() self.put_parameters_event() self.put_variables_event() @@ -109,9 +109,7 @@ def on_timer(self): if self.direction == Direction.LONG: if tick.ask_price_1 <= self.price: - self.buy(self.vt_symbol, self.price, - order_volume, offset=self.offset) + self.buy(self.price, order_volume, offset=self.offset) else: if tick.bid_price_1 >= self.price: - self.sell(self.vt_symbol, self.price, - order_volume, offset=self.offset) + self.sell(self.price, order_volume, offset=self.offset) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 5d47ae2..ede6623 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -144,6 +144,7 @@ def start_algo(self, setting: dict) -> str: algo.start() self.algos[algo.algo_name] = algo + return algo.algo_name def stop_algo(self, algo_name: str) -> None: @@ -157,14 +158,14 @@ def stop_all(self) -> None: for algo_name in list(self.algos.keys()): self.stop_algo(algo_name) - def subscribe(self, algo: AlgoTemplate, vt_symbol: str) -> None: + def subscribe(self, algo: AlgoTemplate) -> None: """""" - contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) + contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) if not contract: - self.write_log(f'订阅行情失败,找不到合约:{vt_symbol}', algo) + self.write_log(f'订阅行情失败,找不到合约:{algo.vt_symbol}', algo) return - algos: set = self.symbol_algo_map[vt_symbol] + algos: set = self.symbol_algo_map[algo.vt_symbol] if not algos: req: SubscribeRequest = SubscribeRequest( @@ -178,7 +179,6 @@ def subscribe(self, algo: AlgoTemplate, vt_symbol: str) -> None: def send_order( self, algo: AlgoTemplate, - vt_symbol: str, direction: Direction, price: float, volume: float, @@ -186,9 +186,9 @@ def send_order( offset: Offset ) -> str: """""" - contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) + contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) if not contract: - self.write_log(f'委托下单失败,找不到合约:{vt_symbol}', algo) + self.write_log(f'委托下单失败,找不到合约:{algo.vt_symbol}', algo) return volume: float = round_to(volume, contract.min_volume) @@ -221,21 +221,21 @@ def cancel_order(self, algo: AlgoTemplate, vt_orderid: str) -> None: req: CancelRequest = order.create_cancel_request() self.main_engine.cancel_order(req, order.gateway_name) - def get_tick(self, algo: AlgoTemplate, vt_symbol: str) -> Optional[TickData]: + def get_tick(self, algo: AlgoTemplate) -> Optional[TickData]: """""" - tick: Optional[TickData] = self.main_engine.get_tick(vt_symbol) + tick: Optional[TickData] = self.main_engine.get_tick(algo.vt_symbol) if not tick: - self.write_log(f"查询行情失败,找不到行情:{vt_symbol}", algo) + self.write_log(f"查询行情失败,找不到行情:{algo.vt_symbol}", algo) return tick - def get_contract(self, algo: AlgoTemplate, vt_symbol: str) -> Optional[ContractData]: + def get_contract(self, algo: AlgoTemplate) -> Optional[ContractData]: """""" - contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) + contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) if not contract: - self.write_log(f"查询合约失败,找不到合约:{vt_symbol}", algo) + self.write_log(f"查询合约失败,找不到合约:{algo.vt_symbol}", algo) return contract diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 6efc445..c0bd54c 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -17,11 +17,13 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict + setting: dict, + vt_symbol: str ) -> None: """构造函数""" self.algo_engine: BaseEngine = algo_engine self.algo_name: str = algo_name + self.vt_symbol: str = vt_symbol self.active: bool = False self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order @@ -33,7 +35,7 @@ def new(cls, algo_engine: BaseEngine, setting: dict) -> "AlgoTemplate": """创建一个新的算法实例""" cls._count += 1 algo_name: str = f"{cls.__name__}_{cls._count}" - algo: AlgoTemplate = cls(algo_engine, algo_name, setting) + algo: AlgoTemplate = cls(algo_engine, algo_name, setting, setting["vt_symbol"]) return algo def update_tick(self, tick: TickData) -> None: @@ -103,13 +105,12 @@ def stop(self) -> None: self.write_log("停止算法") - def subscribe(self, vt_symbol: str) -> None: + def subscribe(self) -> None: """""" - self.algo_engine.subscribe(self, vt_symbol) + self.algo_engine.subscribe(self) def buy( self, - vt_symbol: str, price: float, volume: float, order_type: OrderType = OrderType.LIMIT, @@ -119,12 +120,11 @@ def buy( if not self.active: return - msg: str = f"委托买入{vt_symbol}:{volume}@{price}" + msg: str = f"委托买入{self.vt_symbol}:{volume}@{price}" self.write_log(msg) return self.algo_engine.send_order( self, - vt_symbol, Direction.LONG, price, volume, @@ -134,7 +134,6 @@ def buy( def sell( self, - vt_symbol: str, price: float, volume: float, order_type: OrderType = OrderType.LIMIT, @@ -144,12 +143,11 @@ def sell( if not self.active: return - msg: str = f"委托卖出{vt_symbol}:{volume}@{price}" + msg: str = f"委托卖出{self.vt_symbol}:{volume}@{price}" self.write_log(msg) return self.algo_engine.send_order( self, - vt_symbol, Direction.SHORT, price, volume, @@ -169,13 +167,13 @@ def cancel_all(self) -> None: for vt_orderid in self.active_orders.keys(): self.cancel_order(vt_orderid) - def get_tick(self, vt_symbol: str) -> Optional[TickData]: + def get_tick(self) -> Optional[TickData]: """""" - return self.algo_engine.get_tick(self, vt_symbol) + return self.algo_engine.get_tick(self) - def get_contract(self, vt_symbol: str) -> Optional[ContractData]: + def get_contract(self) -> Optional[ContractData]: """""" - return self.algo_engine.get_contract(self, vt_symbol) + return self.algo_engine.get_contract(self) def write_log(self, msg: str) -> None: """""" From 6f3d8ee8f8dc2beee932d3d0a845c13c3b5ec3f7 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Fri, 4 Nov 2022 16:32:57 +0800 Subject: [PATCH 02/45] =?UTF-8?q?[Mod]=20=E8=B0=83=E6=95=B4=E5=90=88?= =?UTF-8?q?=E7=BA=A6=E8=BF=87=E6=BB=A4=E9=80=BB=E8=BE=91=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index ede6623..6febb14 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -137,6 +137,11 @@ def process_order_event(self, event: Event) -> None: def start_algo(self, setting: dict) -> str: """""" + contract: Optional[ContractData] = self.main_engine.get_contract(setting["vt_symbol"]) + if not contract: + self.write_log(f'算法启动失败,找不到合约:{setting["vt_symbol"]}') + return "" + template_name: str = setting["template_name"] algo_template: AlgoTemplate = self.algo_templates[template_name] @@ -161,10 +166,6 @@ def stop_all(self) -> None: def subscribe(self, algo: AlgoTemplate) -> None: """""" contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) - if not contract: - self.write_log(f'订阅行情失败,找不到合约:{algo.vt_symbol}', algo) - return - algos: set = self.symbol_algo_map[algo.vt_symbol] if not algos: @@ -187,10 +188,6 @@ def send_order( ) -> str: """""" contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) - if not contract: - self.write_log(f'委托下单失败,找不到合约:{algo.vt_symbol}', algo) - return - volume: float = round_to(volume, contract.min_volume) if not volume: return "" From b2b48c288020f9e559a5767d51a34ea345b79ce9 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Fri, 4 Nov 2022 16:48:47 +0800 Subject: [PATCH 03/45] =?UTF-8?q?[Mod]=20=E8=B0=83=E6=95=B4=E8=AE=A2?= =?UTF-8?q?=E9=98=85=E8=A1=8C=E6=83=85=E9=80=BB=E8=BE=91=EF=BC=8C=E5=8F=AA?= =?UTF-8?q?=E5=9C=A8=E5=90=AF=E5=8A=A8=E7=AE=97=E6=B3=95=E6=97=B6=E8=AE=A2?= =?UTF-8?q?=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 2 -- vnpy_algotrading/algos/dma_algo.py | 1 - vnpy_algotrading/algos/iceberg_algo.py | 1 - vnpy_algotrading/algos/sniper_algo.py | 1 - vnpy_algotrading/algos/stop_algo.py | 1 - vnpy_algotrading/algos/twap_algo.py | 1 - vnpy_algotrading/engine.py | 28 +++++++++++------------ vnpy_algotrading/template.py | 4 ---- 8 files changed, 14 insertions(+), 25 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index 5243ede..dc21e63 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -86,8 +86,6 @@ def __init__( self.stop() return - self.subscribe() - def on_tick(self, tick: TickData): """""" self.last_tick = tick diff --git a/vnpy_algotrading/algos/dma_algo.py b/vnpy_algotrading/algos/dma_algo.py index b9f3822..d423605 100644 --- a/vnpy_algotrading/algos/dma_algo.py +++ b/vnpy_algotrading/algos/dma_algo.py @@ -59,7 +59,6 @@ def __init__( self.traded = 0 self.order_status = "" - self.subscribe() self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index 408b0a1..1bb9eba 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -57,7 +57,6 @@ def __init__( self.last_tick = None - self.subscribe() self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index c337ba4..99e2686 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -49,7 +49,6 @@ def __init__( self.vt_orderid = "" self.traded = 0 - self.subscribe() self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index b00aa44..de8f56f 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -53,7 +53,6 @@ def __init__( self.traded = 0 self.order_status = "" - self.subscribe() self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index 8644671..ab3414b 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -64,7 +64,6 @@ def __init__( self.last_tick = None - self.subscribe() self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 6febb14..fe72d35 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -46,6 +46,7 @@ def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None: self.algo_templates: dict = {} self.algo_settings: dict = {} + self.algo_count: dict = {} self.load_algo_template() self.register_event() @@ -145,7 +146,20 @@ def start_algo(self, setting: dict) -> str: template_name: str = setting["template_name"] algo_template: AlgoTemplate = self.algo_templates[template_name] + # 创建算法实例 algo: AlgoTemplate = algo_template.new(self, setting) + + # 订阅行情 + algos: set = self.symbol_algo_map[algo.vt_symbol] + if not algos: + req: SubscribeRequest = SubscribeRequest( + symbol=contract.symbol, + exchange=contract.exchange + ) + self.main_engine.subscribe(req, contract.gateway_name) + algos.add(algo) + + # 启动算法 algo.start() self.algos[algo.algo_name] = algo @@ -163,20 +177,6 @@ def stop_all(self) -> None: for algo_name in list(self.algos.keys()): self.stop_algo(algo_name) - def subscribe(self, algo: AlgoTemplate) -> None: - """""" - contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) - algos: set = self.symbol_algo_map[algo.vt_symbol] - - if not algos: - req: SubscribeRequest = SubscribeRequest( - symbol=contract.symbol, - exchange=contract.exchange - ) - self.main_engine.subscribe(req, contract.gateway_name) - - algos.add(algo) - def send_order( self, algo: AlgoTemplate, diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index c0bd54c..9169fe7 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -105,10 +105,6 @@ def stop(self) -> None: self.write_log("停止算法") - def subscribe(self) -> None: - """""" - self.algo_engine.subscribe(self) - def buy( self, price: float, From 243f11acac96d6f70ea25f79514f0a38974931a5 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Fri, 4 Nov 2022 17:01:56 +0800 Subject: [PATCH 04/45] =?UTF-8?q?[Mod]=20=E4=BF=AE=E6=94=B9=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E5=AE=9E=E4=BE=8B=E5=8C=96=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 14 ++++++++------ vnpy_algotrading/template.py | 8 -------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index fe72d35..b4d9f18 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -46,7 +46,6 @@ def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None: self.algo_templates: dict = {} self.algo_settings: dict = {} - self.algo_count: dict = {} self.load_algo_template() self.register_event() @@ -138,16 +137,19 @@ def process_order_event(self, event: Event) -> None: def start_algo(self, setting: dict) -> str: """""" - contract: Optional[ContractData] = self.main_engine.get_contract(setting["vt_symbol"]) + vt_symbol: str = setting["vt_symbol"] + contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) if not contract: - self.write_log(f'算法启动失败,找不到合约:{setting["vt_symbol"]}') + self.write_log(f'算法启动失败,找不到合约:{vt_symbol}') return "" template_name: str = setting["template_name"] algo_template: AlgoTemplate = self.algo_templates[template_name] # 创建算法实例 - algo: AlgoTemplate = algo_template.new(self, setting) + algo_template._count += 1 + algo_name: str = f"{algo_template.__name__}_{algo_template._count}" + algo: AlgoTemplate = algo_template(self, algo_name, setting, vt_symbol) # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] @@ -162,9 +164,9 @@ def start_algo(self, setting: dict) -> str: # 启动算法 algo.start() - self.algos[algo.algo_name] = algo + self.algos[algo_name] = algo - return algo.algo_name + return algo_name def stop_algo(self, algo_name: str) -> None: """""" diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 9169fe7..886d4ba 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -30,14 +30,6 @@ def __init__( self.variables.insert(0, "active") - @classmethod - def new(cls, algo_engine: BaseEngine, setting: dict) -> "AlgoTemplate": - """创建一个新的算法实例""" - cls._count += 1 - algo_name: str = f"{cls.__name__}_{cls._count}" - algo: AlgoTemplate = cls(algo_engine, algo_name, setting, setting["vt_symbol"]) - return algo - def update_tick(self, tick: TickData) -> None: """""" if self.active: From 3a152387c2a84d824895f9c1b70d2b41c4fe3534 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Fri, 4 Nov 2022 17:54:48 +0800 Subject: [PATCH 05/45] =?UTF-8?q?[Mod]=20=E4=BF=AE=E6=94=B9=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E5=88=9D=E5=A7=8B=E5=8C=96=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 13 ++++++------- vnpy_algotrading/algos/dma_algo.py | 12 ++++++------ vnpy_algotrading/algos/iceberg_algo.py | 12 ++++++------ vnpy_algotrading/algos/sniper_algo.py | 12 ++++++------ vnpy_algotrading/algos/stop_algo.py | 12 ++++++------ vnpy_algotrading/algos/twap_algo.py | 12 ++++++------ vnpy_algotrading/engine.py | 5 +++-- vnpy_algotrading/template.py | 11 +++++++++-- 8 files changed, 48 insertions(+), 41 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index dc21e63..787bcef 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -47,17 +47,16 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ): """""" - super().__init__(algo_engine, algo_name, setting, vt_symbol) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) # 参数 - self.direction = Direction(setting["direction"]) - self.volume = setting["volume"] - self.offset = Offset(setting["offset"]) - self.min_volume = setting["min_volume"] self.max_volume = setting["max_volume"] diff --git a/vnpy_algotrading/algos/dma_algo.py b/vnpy_algotrading/algos/dma_algo.py index d423605..27951c1 100644 --- a/vnpy_algotrading/algos/dma_algo.py +++ b/vnpy_algotrading/algos/dma_algo.py @@ -41,18 +41,18 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ): """""" - super().__init__(algo_engine, algo_name, setting, vt_symbol) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) # 参数 - self.direction = Direction(setting["direction"]) self.order_type = OrderType(setting["order_type"]) self.price = setting["price"] - self.volume = setting["volume"] - self.offset = Offset(setting["offset"]) # 变量 self.vt_orderid = "" diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index 1bb9eba..9b597d0 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -36,19 +36,19 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ): """""" - super().__init__(algo_engine, algo_name, setting, vt_symbol) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) # 参数 - 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"]) # 变量 self.timer_count = 0 diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index 99e2686..a7be112 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -33,17 +33,17 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ): """""" - super().__init__(algo_engine, algo_name, setting, vt_symbol) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) # 参数 - self.direction = Direction(setting["direction"]) self.price = setting["price"] - self.volume = setting["volume"] - self.offset = Offset(setting["offset"]) # 变量 self.vt_orderid = "" diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index de8f56f..38d8b13 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -35,18 +35,18 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ): """""" - super().__init__(algo_engine, algo_name, setting, vt_symbol) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) # 参数 - 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"]) # 变量 self.vt_orderid = "" diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index ab3414b..9e28bb8 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -38,19 +38,19 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ): """""" - super().__init__(algo_engine, algo_name, setting, vt_symbol) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) # 参数 - self.direction = Direction(setting["direction"]) self.price = setting["price"] - self.volume = setting["volume"] self.time = setting["time"] self.interval = setting["interval"] - self.offset = Offset(setting["offset"]) # 变量 self.order_volume = self.volume / (self.time / self.interval) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index b4d9f18..298796b 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -137,7 +137,7 @@ def process_order_event(self, event: Event) -> None: def start_algo(self, setting: dict) -> str: """""" - vt_symbol: str = setting["vt_symbol"] + vt_symbol: str = setting.pop("vt_symbol") contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) if not contract: self.write_log(f'算法启动失败,找不到合约:{vt_symbol}') @@ -149,7 +149,8 @@ def start_algo(self, setting: dict) -> str: # 创建算法实例 algo_template._count += 1 algo_name: str = f"{algo_template.__name__}_{algo_template._count}" - algo: AlgoTemplate = algo_template(self, algo_name, setting, vt_symbol) + algo: AlgoTemplate = algo_template(self, algo_name, vt_symbol, setting.pop("direction"), + setting.pop("offset"), setting.pop("volume"), setting) # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 886d4ba..531f0e3 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -17,13 +17,20 @@ def __init__( self, algo_engine: BaseEngine, algo_name: str, - setting: dict, - vt_symbol: str + vt_symbol: str, + direction: str, + offset: str, + volume: float, + setting: dict ) -> None: """构造函数""" self.algo_engine: BaseEngine = algo_engine self.algo_name: str = algo_name + self.vt_symbol: str = vt_symbol + self.direction = Direction(direction) + self.volume = volume + self.offset = Offset(offset) self.active: bool = False self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order From 858da01e2df8e48e6933dfed6b217376344eb260 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 8 Nov 2022 10:04:03 +0800 Subject: [PATCH 06/45] =?UTF-8?q?[Mod]=20=E4=BF=AE=E6=94=B9=E7=AE=97?= =?UTF-8?q?=E6=B3=95active=E7=8A=B6=E6=80=81=E8=BF=87=E6=BB=A4=E4=B8=BAsta?= =?UTF-8?q?tus=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/base.py | 13 +++++++++++++ vnpy_algotrading/engine.py | 6 +++--- vnpy_algotrading/template.py | 19 +++++++++++-------- vnpy_algotrading/ui/widget.py | 5 +++-- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index c08ba37..4aceead 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -1,6 +1,19 @@ +from enum import Enum + + EVENT_ALGO_LOG = "eAlgoLog" EVENT_ALGO_SETTING = "eAlgoSetting" EVENT_ALGO_VARIABLES = "eAlgoVariables" EVENT_ALGO_PARAMETERS = "eAlgoParameters" APP_NAME = "AlgoTrading" + + +class AlgoStatus(Enum): + """ + Order status. + """ + NOTINITED = "尚未初始化" + RUNNING = "运行中" + PAUSED = "暂停" + STOPPED = "停止" diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 298796b..57981d4 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -28,7 +28,8 @@ EVENT_ALGO_PARAMETERS, EVENT_ALGO_SETTING, EVENT_ALGO_VARIABLES, - APP_NAME + APP_NAME, + AlgoStatus ) @@ -164,7 +165,6 @@ def start_algo(self, setting: dict) -> str: # 启动算法 algo.start() - self.algos[algo_name] = algo return algo_name @@ -292,7 +292,7 @@ def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: """""" # 检查算法是否运行结束 - if not variables["active"] and algo in self.algos.values(): + if algo in self.algos.values() and algo.status == AlgoStatus.STOPPED: self.algos.pop(algo.algo_name) for algos in self.symbol_algo_map.values(): diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 531f0e3..4cf7b87 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -5,6 +5,8 @@ from vnpy.trader.constant import OrderType, Offset, Direction from vnpy.trader.utility import virtual +from .base import AlgoStatus + class AlgoTemplate: """""" @@ -32,14 +34,14 @@ def __init__( self.volume = volume self.offset = Offset(offset) - self.active: bool = False + self.status: str = AlgoStatus.NOTINITED self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order - self.variables.insert(0, "active") + self.variables.insert(0, "status") def update_tick(self, tick: TickData) -> None: """""" - if self.active: + if self.status == AlgoStatus.RUNNING: self.on_tick(tick) def update_order(self, order: OrderData) -> None: @@ -57,9 +59,10 @@ def update_trade(self, trade: TradeData) -> None: def update_timer(self) -> None: """""" - if self.active: + if self.status == AlgoStatus.RUNNING: self.on_timer() + @virtual def on_start(self) -> None: """""" pass @@ -91,13 +94,13 @@ def on_timer(self) -> None: def start(self) -> None: """""" - self.active = True + self.status = AlgoStatus.RUNNING self.on_start() self.put_variables_event() def stop(self) -> None: """""" - self.active = False + self.status = AlgoStatus.STOPPED self.cancel_all() self.on_stop() self.put_variables_event() @@ -112,7 +115,7 @@ def buy( offset: Offset = Offset.NONE ) -> None: """""" - if not self.active: + if self.status != AlgoStatus.RUNNING: return msg: str = f"委托买入{self.vt_symbol}:{volume}@{price}" @@ -135,7 +138,7 @@ def sell( offset: Offset = Offset.NONE ) -> None: """""" - if not self.active: + if self.status != AlgoStatus.RUNNING: return msg: str = f"委托卖出{self.vt_symbol}:{volume}@{price}" diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index cd7fe01..61c0e3e 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -14,7 +14,8 @@ EVENT_ALGO_LOG, EVENT_ALGO_PARAMETERS, EVENT_ALGO_VARIABLES, - EVENT_ALGO_SETTING + EVENT_ALGO_SETTING, + AlgoStatus ) from .display import NAME_DISPLAY_MAP @@ -286,7 +287,7 @@ def process_variables_event(self, event: Event) -> None: variables_cell.setText(text) row: int = self.row(variables_cell) - active: bool = variables["active"] + active: bool = variables["status"] != AlgoStatus.STOPPED if self.mode_active: if active: From 7eb6e1f13ac72fbf31caa94a66ba6ee8cb66029d Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 8 Nov 2022 10:07:16 +0800 Subject: [PATCH 07/45] =?UTF-8?q?[Add]=20=E5=A2=9E=E5=8A=A0=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E6=9A=82=E5=81=9C=E5=92=8C=E9=87=8D=E5=90=AF=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 13 +++++++++++++ vnpy_algotrading/template.py | 13 +++++++++++++ vnpy_algotrading/ui/widget.py | 31 ++++++++++++++++++++++++++----- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 57981d4..2332490 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -169,6 +169,19 @@ def start_algo(self, setting: dict) -> str: return algo_name + def pause_algo(self, algo_name: str) -> None: + """""" + algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) + if algo: + algo.pause() + + def restart_algo(self, algo_name: str) -> None: + """""" + algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) + if algo: + algo.start() + algo.write_log("重启算法") + def stop_algo(self, algo_name: str) -> None: """""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 4cf7b87..fbe6aab 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -72,6 +72,10 @@ def on_stop(self) -> None: """""" pass + def on_pause(self) -> None: + """""" + pass + @virtual def on_tick(self, tick: TickData) -> None: """""" @@ -107,6 +111,15 @@ def stop(self) -> None: self.write_log("停止算法") + def pause(self) -> None: + """""" + self.status = AlgoStatus.PAUSED + self.cancel_all() + self.on_pause() + self.put_variables_event() + + self.write_log("暂停算法") + def buy( self, price: float, diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 61c0e3e..77602b9 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -231,6 +231,7 @@ def __init__( def init_ui(self) -> None: """""" labels: list = [ + "", "", "算法", "参数", @@ -245,7 +246,7 @@ def init_ui(self) -> None: QtWidgets.QHeaderView.ResizeToContents ) - for column in range(2, 4): + for column in range(3, 5): self.horizontalHeader().setSectionResizeMode( column, QtWidgets.QHeaderView.Stretch @@ -254,6 +255,7 @@ def init_ui(self) -> None: if not self.mode_active: self.hideColumn(0) + self.hideColumn(1) def register_event(self) -> None: """""" @@ -304,6 +306,18 @@ def stop_algo(self, algo_name: str) -> None: """""" self.algo_engine.stop_algo(algo_name) + def switch(self, algo_name: str) -> None: + """""" + button: QtWidgets.QPushButton = self.algo_cells[algo_name]["button"] + if button.text() == "暂停": + self.algo_engine.pause_algo(algo_name) + button.setText("启动") + else: + self.algo_engine.restart_algo(algo_name) + button.setText("暂停") + + self.algo_cells[algo_name]["button"] = button + def get_algo_cells(self, algo_name: str) -> dict: """""" cells: Optional[dict] = self.algo_cells.get(algo_name, None) @@ -313,20 +327,27 @@ def get_algo_cells(self, algo_name: str) -> dict: stop_button: QtWidgets.QPushButton = QtWidgets.QPushButton("停止") stop_button.clicked.connect(stop_func) + # 初始化时先设置暂停按钮 + switch_func = partial(self.switch, algo_name=algo_name) + switch_button: QtWidgets.QPushButton = QtWidgets.QPushButton("暂停") + switch_button.clicked.connect(switch_func) + name_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(algo_name) parameters_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() variables_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() self.insertRow(0) self.setCellWidget(0, 0, stop_button) - self.setItem(0, 1, name_cell) - self.setItem(0, 2, parameters_cell) - self.setItem(0, 3, variables_cell) + self.setCellWidget(0, 1, switch_button) + self.setItem(0, 2, name_cell) + self.setItem(0, 3, parameters_cell) + self.setItem(0, 4, variables_cell) cells: dict = { "name": name_cell, "parameters": parameters_cell, - "variables": variables_cell + "variables": variables_cell, + "button": switch_button # 缓存对应algo_name的button进字典便于更新按钮状态 } self.algo_cells[algo_name] = cells From d7e179ebc09128b070cba63b07d71861ebc9744d Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 8 Nov 2022 10:13:16 +0800 Subject: [PATCH 08/45] [Mod] NAME_DISPLAY_MAP --- vnpy_algotrading/ui/display.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnpy_algotrading/ui/display.py b/vnpy_algotrading/ui/display.py index dce3822..d35db4a 100644 --- a/vnpy_algotrading/ui/display.py +++ b/vnpy_algotrading/ui/display.py @@ -6,7 +6,7 @@ "time": "执行时间(秒)", "interval": "每轮间隔(秒)", "offset": "开平", - "active": "算法状态", + "status": "算法状态", "traded": "成交数量", "order_volume": "单笔委托", "timer_count": "本轮读秒", From bcf55d1256d040263eaf7bffdd88cf87b9ace4c3 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 9 Nov 2022 16:12:06 +0800 Subject: [PATCH 09/45] =?UTF-8?q?[Mod]=20=E8=B0=83=E6=95=B4=E9=87=8D?= =?UTF-8?q?=E5=90=AF=E5=87=BD=E6=95=B0=E5=91=BD=E5=90=8D=20+=20start=5Falg?= =?UTF-8?q?o=E6=94=B9=E4=B8=BA=E6=98=BE=E7=A4=BA=E4=BC=A0=E5=8F=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/base.py | 1 - vnpy_algotrading/engine.py | 11 ++++------- vnpy_algotrading/template.py | 18 +++++++++++++++++- vnpy_algotrading/ui/widget.py | 12 +++++++++--- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index 4aceead..b2af10b 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -13,7 +13,6 @@ class AlgoStatus(Enum): """ Order status. """ - NOTINITED = "尚未初始化" RUNNING = "运行中" PAUSED = "暂停" STOPPED = "停止" diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 2332490..0717051 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -136,9 +136,8 @@ def process_order_event(self, event: Event) -> None: if algo: algo.update_order(order) - def start_algo(self, setting: dict) -> str: + def start_algo(self, vt_symbol: str, direction: Direction, offset: Offset, volume: float, setting: dict) -> str: """""" - vt_symbol: str = setting.pop("vt_symbol") contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) if not contract: self.write_log(f'算法启动失败,找不到合约:{vt_symbol}') @@ -150,8 +149,7 @@ def start_algo(self, setting: dict) -> str: # 创建算法实例 algo_template._count += 1 algo_name: str = f"{algo_template.__name__}_{algo_template._count}" - algo: AlgoTemplate = algo_template(self, algo_name, vt_symbol, setting.pop("direction"), - setting.pop("offset"), setting.pop("volume"), setting) + algo: AlgoTemplate = algo_template(self, algo_name, vt_symbol, direction, offset, volume, setting) # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] @@ -175,12 +173,11 @@ def pause_algo(self, algo_name: str) -> None: if algo: algo.pause() - def restart_algo(self, algo_name: str) -> None: + def resume_algo(self, algo_name: str) -> None: """""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) if algo: - algo.start() - algo.write_log("重启算法") + algo.resume() def stop_algo(self, algo_name: str) -> None: """""" diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index fbe6aab..f1f5ee9 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -34,7 +34,7 @@ def __init__( self.volume = volume self.offset = Offset(offset) - self.status: str = AlgoStatus.NOTINITED + self.status: str = AlgoStatus.PAUSED self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order self.variables.insert(0, "status") @@ -72,10 +72,16 @@ def on_stop(self) -> None: """""" pass + @virtual def on_pause(self) -> None: """""" pass + @virtual + def on_resume(self) -> None: + """""" + pass + @virtual def on_tick(self, tick: TickData) -> None: """""" @@ -102,6 +108,8 @@ def start(self) -> None: self.on_start() self.put_variables_event() + self.write_log("启动算法") + def stop(self) -> None: """""" self.status = AlgoStatus.STOPPED @@ -120,6 +128,14 @@ def pause(self) -> None: self.write_log("暂停算法") + def resume(self) -> None: + """""" + self.status = AlgoStatus.RUNNING + self.on_resume() + self.put_variables_event() + + self.write_log("重启算法") + def buy( self, price: float, diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 77602b9..e4b30c9 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -15,7 +15,9 @@ EVENT_ALGO_PARAMETERS, EVENT_ALGO_VARIABLES, EVENT_ALGO_SETTING, - AlgoStatus + AlgoStatus, + Direction, + Offset ) from .display import NAME_DISPLAY_MAP @@ -178,7 +180,11 @@ def start_algo(self) -> None: """启动交易算法""" setting: dict = self.get_setting() if setting: - self.algo_engine.start_algo(setting) + vt_symbol: str = setting.pop("vt_symbol") + direction: Direction = Direction(setting.pop("direction")) + offset: Offset = Offset(setting.pop("offset")) + volume: float = setting.pop("volume") + self.algo_engine.start_algo(vt_symbol, direction, offset, volume, setting) def update_setting(self, setting_name: str, setting: dict) -> None: """更新控件配置""" @@ -313,7 +319,7 @@ def switch(self, algo_name: str) -> None: self.algo_engine.pause_algo(algo_name) button.setText("启动") else: - self.algo_engine.restart_algo(algo_name) + self.algo_engine.resume_algo(algo_name) button.setText("暂停") self.algo_cells[algo_name]["button"] = button From 0cc948646324d79b6078bcedbdc65d80129a0a54 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Thu, 10 Nov 2022 11:21:23 +0800 Subject: [PATCH 10/45] =?UTF-8?q?[Mod]=20=E7=AE=80=E5=8C=96start=5Falgo?= =?UTF-8?q?=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 0717051..2703118 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -18,7 +18,8 @@ OrderData, TickData, TradeData, - CancelRequest + CancelRequest, + Exchange ) from vnpy.trader.utility import load_json, save_json, round_to @@ -154,11 +155,7 @@ def start_algo(self, vt_symbol: str, direction: Direction, offset: Offset, volum # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] if not algos: - req: SubscribeRequest = SubscribeRequest( - symbol=contract.symbol, - exchange=contract.exchange - ) - self.main_engine.subscribe(req, contract.gateway_name) + self.subscribe(contract.symbol, contract.exchange, contract.gateway_name) algos.add(algo) # 启动算法 @@ -190,6 +187,14 @@ def stop_all(self) -> None: for algo_name in list(self.algos.keys()): self.stop_algo(algo_name) + def subscribe(self, symbol: str, exchange: Exchange, gateway_name: str) -> None: + """""" + req: SubscribeRequest = SubscribeRequest( + symbol=symbol, + exchange=exchange + ) + self.main_engine.subscribe(req, gateway_name) + def send_order( self, algo: AlgoTemplate, From f5eed6ac111c8a1fd3661d0efc0784ca10b18d32 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Thu, 10 Nov 2022 11:24:19 +0800 Subject: [PATCH 11/45] =?UTF-8?q?[Mod]=20algo=E7=8A=B6=E6=80=81=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/base.py | 11 +++++++++-- vnpy_algotrading/engine.py | 4 ++-- vnpy_algotrading/template.py | 32 +++++++++++++++++++++++--------- vnpy_algotrading/ui/widget.py | 2 +- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index b2af10b..79742f5 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -11,8 +11,15 @@ class AlgoStatus(Enum): """ - Order status. + Algo status. """ RUNNING = "运行中" PAUSED = "暂停" - STOPPED = "停止" + TERMINATED = "终止" + FINISHED = "结束" + + def is_active(self) -> bool: + """ + Check if the algo is active. + """ + return self == AlgoStatus.RUNNING diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 2703118..b014031 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -180,7 +180,7 @@ def stop_algo(self, algo_name: str) -> None: """""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) if algo: - algo.stop() + algo.terminate() def stop_all(self) -> None: """""" @@ -307,7 +307,7 @@ def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: """""" # 检查算法是否运行结束 - if algo in self.algos.values() and algo.status == AlgoStatus.STOPPED: + if algo in self.algos.values() and algo.status in [AlgoStatus.TERMINATED, AlgoStatus.FINISHED]: self.algos.pop(algo.algo_name) for algos in self.symbol_algo_map.values(): diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index f1f5ee9..25bcd61 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -41,7 +41,7 @@ def __init__( def update_tick(self, tick: TickData) -> None: """""" - if self.status == AlgoStatus.RUNNING: + if self.status.is_active(): self.on_tick(tick) def update_order(self, order: OrderData) -> None: @@ -59,7 +59,7 @@ def update_trade(self, trade: TradeData) -> None: def update_timer(self) -> None: """""" - if self.status == AlgoStatus.RUNNING: + if self.status.is_active(): self.on_timer() @virtual @@ -82,6 +82,11 @@ def on_resume(self) -> None: """""" pass + @virtual + def on_terminate(self) -> None: + """""" + pass + @virtual def on_tick(self, tick: TickData) -> None: """""" @@ -108,16 +113,25 @@ def start(self) -> None: self.on_start() self.put_variables_event() - self.write_log("启动算法") + self.write_log("算法启动") def stop(self) -> None: """""" - self.status = AlgoStatus.STOPPED + self.status = AlgoStatus.FINISHED self.cancel_all() self.on_stop() self.put_variables_event() - self.write_log("停止算法") + self.write_log("算法结束") + + def terminate(self) -> None: + """""" + self.status = AlgoStatus.TERMINATED + self.cancel_all() + self.on_terminate() + self.put_variables_event() + + self.write_log("算法停止") def pause(self) -> None: """""" @@ -126,7 +140,7 @@ def pause(self) -> None: self.on_pause() self.put_variables_event() - self.write_log("暂停算法") + self.write_log("算法暂停") def resume(self) -> None: """""" @@ -134,7 +148,7 @@ def resume(self) -> None: self.on_resume() self.put_variables_event() - self.write_log("重启算法") + self.write_log("算法重启") def buy( self, @@ -144,7 +158,7 @@ def buy( offset: Offset = Offset.NONE ) -> None: """""" - if self.status != AlgoStatus.RUNNING: + if not self.status.is_active(): return msg: str = f"委托买入{self.vt_symbol}:{volume}@{price}" @@ -167,7 +181,7 @@ def sell( offset: Offset = Offset.NONE ) -> None: """""" - if self.status != AlgoStatus.RUNNING: + if not self.status.is_active(): return msg: str = f"委托卖出{self.vt_symbol}:{volume}@{price}" diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index e4b30c9..9e1490d 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -295,7 +295,7 @@ def process_variables_event(self, event: Event) -> None: variables_cell.setText(text) row: int = self.row(variables_cell) - active: bool = variables["status"] != AlgoStatus.STOPPED + active: bool = variables["status"] not in [AlgoStatus.TERMINATED, AlgoStatus.FINISHED] if self.mode_active: if active: From 223605865199e04398afa98242e4d6a2af58f993 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Fri, 11 Nov 2022 16:26:32 +0800 Subject: [PATCH 12/45] =?UTF-8?q?[Fix]=20=E4=BF=AE=E5=A4=8Dstart=5Falgo?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BC=A0=E5=8F=82=E5=90=8E=E5=AF=BC=E8=87=B4?= =?UTF-8?q?csv=E5=90=AF=E5=8A=A8=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/ui/widget.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 9e1490d..af4d772 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -150,7 +150,11 @@ def load_csv(self) -> None: # 当没有错误发生时启动算法 for setting in settings: - self.algo_engine.start_algo(setting) + vt_symbol: str = setting.pop("vt_symbol") + direction: Direction = Direction(setting.pop("direction")) + offset: Offset = Offset(setting.pop("offset")) + volume: float = setting.pop("volume") + self.algo_engine.start_algo(vt_symbol, direction, offset, volume, setting) def get_setting(self) -> dict: """获取配置""" From 989fd5dab0725bb7bf19efd3a4db4e18a6e79e68 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 14 Nov 2022 10:15:13 +0800 Subject: [PATCH 13/45] =?UTF-8?q?[Mod]=20=E8=B0=83=E6=95=B4=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E7=8A=B6=E6=80=81=E6=9E=9A=E4=B8=BE=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/base.py | 10 ++-------- vnpy_algotrading/engine.py | 2 +- vnpy_algotrading/template.py | 10 +++++----- vnpy_algotrading/ui/widget.py | 2 +- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index 79742f5..c96e094 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -13,13 +13,7 @@ class AlgoStatus(Enum): """ Algo status. """ - RUNNING = "运行中" + RUNNING = "运行" PAUSED = "暂停" - TERMINATED = "终止" + STOPPED = "停止" FINISHED = "结束" - - def is_active(self) -> bool: - """ - Check if the algo is active. - """ - return self == AlgoStatus.RUNNING diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index b014031..388de20 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -307,7 +307,7 @@ def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: """""" # 检查算法是否运行结束 - if algo in self.algos.values() and algo.status in [AlgoStatus.TERMINATED, AlgoStatus.FINISHED]: + if algo in self.algos.values() and algo.status in [AlgoStatus.STOPPED, AlgoStatus.FINISHED]: self.algos.pop(algo.algo_name) for algos in self.symbol_algo_map.values(): diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 25bcd61..82bcda5 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -41,7 +41,7 @@ def __init__( def update_tick(self, tick: TickData) -> None: """""" - if self.status.is_active(): + if self.status == AlgoStatus.RUNNING: self.on_tick(tick) def update_order(self, order: OrderData) -> None: @@ -59,7 +59,7 @@ def update_trade(self, trade: TradeData) -> None: def update_timer(self) -> None: """""" - if self.status.is_active(): + if self.status == AlgoStatus.RUNNING: self.on_timer() @virtual @@ -126,7 +126,7 @@ def stop(self) -> None: def terminate(self) -> None: """""" - self.status = AlgoStatus.TERMINATED + self.status = AlgoStatus.STOPPED self.cancel_all() self.on_terminate() self.put_variables_event() @@ -158,7 +158,7 @@ def buy( offset: Offset = Offset.NONE ) -> None: """""" - if not self.status.is_active(): + if self.status == AlgoStatus.RUNNING: return msg: str = f"委托买入{self.vt_symbol}:{volume}@{price}" @@ -181,7 +181,7 @@ def sell( offset: Offset = Offset.NONE ) -> None: """""" - if not self.status.is_active(): + if self.status == AlgoStatus.RUNNING: return msg: str = f"委托卖出{self.vt_symbol}:{volume}@{price}" diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index af4d772..ee90129 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -299,7 +299,7 @@ def process_variables_event(self, event: Event) -> None: variables_cell.setText(text) row: int = self.row(variables_cell) - active: bool = variables["status"] not in [AlgoStatus.TERMINATED, AlgoStatus.FINISHED] + active: bool = variables["status"] not in [AlgoStatus.STOPPED, AlgoStatus.FINISHED] if self.mode_active: if active: From b902d4ea49d6e7570abffec6ed051610f0bc1ab9 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 14 Nov 2022 10:40:33 +0800 Subject: [PATCH 14/45] =?UTF-8?q?[Mod]=20=E7=AE=80=E5=8C=96=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E5=BC=80=E5=8F=91=E6=A8=A1=E6=9D=BF=E7=9A=84=E5=9B=9E?= =?UTF-8?q?=E8=B0=83=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/base.py | 5 +- vnpy_algotrading/template.py | 111 +++++++++++++---------------------- 2 files changed, 43 insertions(+), 73 deletions(-) diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index c96e094..ac10225 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -10,9 +10,8 @@ class AlgoStatus(Enum): - """ - Algo status. - """ + """算法状态""" + RUNNING = "运行" PAUSED = "暂停" STOPPED = "停止" diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 82bcda5..ce44f79 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -9,19 +9,21 @@ class AlgoTemplate: - """""" - _count: int = 0 - display_name: str = "" - default_setting: dict = {} - variables: list = [] + """算法模板""" + + _count: int = 0 # 算法实例的计数 + + display_name: str = "" # 显示名称 + default_setting: dict = {} # 默认参数 + variables: list = [] # 变量名称 def __init__( self, algo_engine: BaseEngine, algo_name: str, vt_symbol: str, - direction: str, - offset: str, + direction: Direction, + offset: Offset, volume: float, setting: dict ) -> None: @@ -30,9 +32,9 @@ def __init__( self.algo_name: str = algo_name self.vt_symbol: str = vt_symbol - self.direction = Direction(direction) + self.direction = direction + self.offset = offset self.volume = volume - self.offset = Offset(offset) self.status: str = AlgoStatus.PAUSED self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order @@ -40,12 +42,12 @@ def __init__( self.variables.insert(0, "status") def update_tick(self, tick: TickData) -> None: - """""" + """行情数据更新""" if self.status == AlgoStatus.RUNNING: self.on_tick(tick) def update_order(self, order: OrderData) -> None: - """""" + """委托数据更新""" if order.is_active(): self.active_orders[order.vt_orderid] = order elif order.vt_orderid in self.active_orders: @@ -54,101 +56,70 @@ def update_order(self, order: OrderData) -> None: self.on_order(order) def update_trade(self, trade: TradeData) -> None: - """""" + """成交数据更新""" self.on_trade(trade) def update_timer(self) -> None: - """""" + """每秒定时更新""" if self.status == AlgoStatus.RUNNING: self.on_timer() - @virtual - def on_start(self) -> None: - """""" - pass - - @virtual - def on_stop(self) -> None: - """""" - pass - - @virtual - def on_pause(self) -> None: - """""" - pass - - @virtual - def on_resume(self) -> None: - """""" - pass - - @virtual - def on_terminate(self) -> None: - """""" - pass - @virtual def on_tick(self, tick: TickData) -> None: - """""" + """行情回调""" pass @virtual def on_order(self, order: OrderData) -> None: - """""" + """委托回调""" pass @virtual def on_trade(self, trade: TradeData) -> None: - """""" + """成交回调""" pass @virtual def on_timer(self) -> None: - """""" + """定时回调""" pass def start(self) -> None: - """""" + """启动""" self.status = AlgoStatus.RUNNING - self.on_start() self.put_variables_event() self.write_log("算法启动") def stop(self) -> None: - """""" - self.status = AlgoStatus.FINISHED + """停止""" + self.status = AlgoStatus.STOPPED self.cancel_all() - self.on_stop() self.put_variables_event() - self.write_log("算法结束") + self.write_log("算法停止") - def terminate(self) -> None: - """""" - self.status = AlgoStatus.STOPPED + def finish(self) -> None: + """结束""" + self.status = AlgoStatus.FINISHED self.cancel_all() - self.on_terminate() self.put_variables_event() - self.write_log("算法停止") + self.write_log("算法结束") def pause(self) -> None: - """""" + """暂停""" self.status = AlgoStatus.PAUSED - self.cancel_all() - self.on_pause() self.put_variables_event() self.write_log("算法暂停") def resume(self) -> None: - """""" + """恢复""" self.status = AlgoStatus.RUNNING - self.on_resume() self.put_variables_event() - self.write_log("算法重启") + self.write_log("算法恢复") def buy( self, @@ -157,11 +128,11 @@ def buy( order_type: OrderType = OrderType.LIMIT, offset: Offset = Offset.NONE ) -> None: - """""" + """买入""" if self.status == AlgoStatus.RUNNING: return - msg: str = f"委托买入{self.vt_symbol}:{volume}@{price}" + msg: str = f"{self.vt_symbol},委托买入{order_type.value},{volume}@{price}" self.write_log(msg) return self.algo_engine.send_order( @@ -180,11 +151,11 @@ def sell( order_type: OrderType = OrderType.LIMIT, offset: Offset = Offset.NONE ) -> None: - """""" + """卖出""" if self.status == AlgoStatus.RUNNING: return - msg: str = f"委托卖出{self.vt_symbol}:{volume}@{price}" + msg: str = f"{self.vt_symbol}委托卖出{order_type.value},{volume}@{price}" self.write_log(msg) return self.algo_engine.send_order( @@ -197,11 +168,11 @@ def sell( ) def cancel_order(self, vt_orderid: str) -> None: - """""" + """撤销委托""" self.algo_engine.cancel_order(self, vt_orderid) def cancel_all(self) -> None: - """""" + """全撤委托""" if not self.active_orders: return @@ -209,19 +180,19 @@ def cancel_all(self) -> None: self.cancel_order(vt_orderid) def get_tick(self) -> Optional[TickData]: - """""" + """查询行情""" return self.algo_engine.get_tick(self) def get_contract(self) -> Optional[ContractData]: - """""" + """查询合约""" return self.algo_engine.get_contract(self) def write_log(self, msg: str) -> None: - """""" + """输出日志""" self.algo_engine.write_log(msg, self) def put_parameters_event(self) -> None: - """""" + """推送参数更新""" parameters: dict = {} for name in self.default_setting.keys(): parameters[name] = getattr(self, name) @@ -229,7 +200,7 @@ def put_parameters_event(self) -> None: self.algo_engine.put_parameters_event(self, parameters) def put_variables_event(self) -> None: - """""" + """推送变量更新""" variables: dict = {} for name in self.variables: variables[name] = getattr(self, name) From a3aae5f6c9643cd48ff9b217e2a6d1ca86a50fdb Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 14 Nov 2022 10:52:33 +0800 Subject: [PATCH 15/45] =?UTF-8?q?[Mod]=20=E7=A7=BB=E9=99=A4=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E9=85=8D=E7=BD=AE=E7=BC=93=E5=AD=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/base.py | 1 - vnpy_algotrading/engine.py | 126 ++++++++++++------------------------- 2 files changed, 40 insertions(+), 87 deletions(-) diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index ac10225..68882f3 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -2,7 +2,6 @@ EVENT_ALGO_LOG = "eAlgoLog" -EVENT_ALGO_SETTING = "eAlgoSetting" EVENT_ALGO_VARIABLES = "eAlgoVariables" EVENT_ALGO_PARAMETERS = "eAlgoParameters" diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 388de20..9800c80 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -18,16 +18,14 @@ OrderData, TickData, TradeData, - CancelRequest, - Exchange + CancelRequest ) -from vnpy.trader.utility import load_json, save_json, round_to +from vnpy.trader.utility import round_to from .template import AlgoTemplate from .base import ( EVENT_ALGO_LOG, EVENT_ALGO_PARAMETERS, - EVENT_ALGO_SETTING, EVENT_ALGO_VARIABLES, APP_NAME, AlgoStatus @@ -35,8 +33,7 @@ class AlgoEngine(BaseEngine): - """""" - setting_filename: str = "algo_trading_setting.json" + """算法引擎""" def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None: """构造函数""" @@ -47,22 +44,20 @@ def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None: self.orderid_algo_map: dict = {} self.algo_templates: dict = {} - self.algo_settings: dict = {} self.load_algo_template() self.register_event() def init_engine(self) -> None: - """""" + """初始化引擎""" self.write_log("算法交易引擎启动") - self.load_algo_setting() def close(self) -> None: - """""" + """关闭引擎""" pass def load_algo_template(self) -> None: - """""" + """载入算法类""" from .algos.twap_algo import TwapAlgo from .algos.iceberg_algo import IcebergAlgo from .algos.sniper_algo import SniperAlgo @@ -78,43 +73,30 @@ def load_algo_template(self) -> None: self.add_algo_template(DmaAlgo) def add_algo_template(self, template: AlgoTemplate) -> None: - """""" + """添加算法类""" self.algo_templates[template.__name__] = template def get_algo_template(self) -> dict: - """""" + """获取算法类""" return self.algo_templates - def load_algo_setting(self) -> None: - """""" - self.algo_settings: dict = load_json(self.setting_filename) - - for setting_name, setting in self.algo_settings.items(): - self.put_setting_event(setting_name, setting) - - self.write_log("算法配置载入成功") - - def save_algo_setting(self) -> None: - """""" - save_json(self.setting_filename, self.algo_settings) - def register_event(self) -> None: - """""" + """注册事件监听""" self.event_engine.register(EVENT_TICK, self.process_tick_event) self.event_engine.register(EVENT_TIMER, self.process_timer_event) self.event_engine.register(EVENT_ORDER, self.process_order_event) self.event_engine.register(EVENT_TRADE, self.process_trade_event) def process_tick_event(self, event: Event) -> None: - """""" + """处理行情事件""" tick: TickData = event.data - algos: Optional[Set[AlgoTemplate]] = self.symbol_algo_map[tick.vt_symbol] + algos: Set[AlgoTemplate] = self.symbol_algo_map[tick.vt_symbol] for algo in algos: algo.update_tick(tick) def process_timer_event(self, event: Event) -> None: - """""" + """处理定时事件""" # 生成列表避免字典改变 algos: List[AlgoTemplate] = list(self.algos.values()) @@ -122,7 +104,7 @@ def process_timer_event(self, event: Event) -> None: algo.update_timer() def process_trade_event(self, event: Event) -> None: - """""" + """处理成交事件""" trade: TradeData = event.data algo: Optional[AlgoTemplate] = self.orderid_algo_map.get(trade.vt_orderid, None) @@ -130,15 +112,22 @@ def process_trade_event(self, event: Event) -> None: algo.update_trade(trade) def process_order_event(self, event: Event) -> None: - """""" + """处理委托事件""" order: OrderData = event.data algo: Optional[AlgoTemplate] = self.orderid_algo_map.get(order.vt_orderid, None) if algo: algo.update_order(order) - def start_algo(self, vt_symbol: str, direction: Direction, offset: Offset, volume: float, setting: dict) -> str: - """""" + def start_algo( + self, + vt_symbol: str, + direction: Direction, + offset: Offset, + volume: float, + setting: dict + ) -> str: + """启动算法""" contract: Optional[ContractData] = self.main_engine.get_contract(vt_symbol) if not contract: self.write_log(f'算法启动失败,找不到合约:{vt_symbol}') @@ -155,7 +144,12 @@ def start_algo(self, vt_symbol: str, direction: Direction, offset: Offset, volum # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] if not algos: - self.subscribe(contract.symbol, contract.exchange, contract.gateway_name) + req: SubscribeRequest = SubscribeRequest( + symbol=contract.symbol, + exchange=contract.exchange + ) + self.main_engine.subscribe(req, contract.gateway_name) + algos.add(algo) # 启动算法 @@ -165,36 +159,28 @@ def start_algo(self, vt_symbol: str, direction: Direction, offset: Offset, volum return algo_name def pause_algo(self, algo_name: str) -> None: - """""" + """暂停算法""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) if algo: algo.pause() def resume_algo(self, algo_name: str) -> None: - """""" + """恢复算法""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) if algo: algo.resume() def stop_algo(self, algo_name: str) -> None: - """""" + """停止算法""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) if algo: algo.terminate() def stop_all(self) -> None: - """""" + """停止全部算法""" for algo_name in list(self.algos.keys()): self.stop_algo(algo_name) - def subscribe(self, symbol: str, exchange: Exchange, gateway_name: str) -> None: - """""" - req: SubscribeRequest = SubscribeRequest( - symbol=symbol, - exchange=exchange - ) - self.main_engine.subscribe(req, gateway_name) - def send_order( self, algo: AlgoTemplate, @@ -204,7 +190,7 @@ def send_order( order_type: OrderType, offset: Offset ) -> str: - """""" + """委托下单""" contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) volume: float = round_to(volume, contract.min_volume) if not volume: @@ -226,7 +212,7 @@ def send_order( return vt_orderid def cancel_order(self, algo: AlgoTemplate, vt_orderid: str) -> None: - """""" + """委托撤单""" order: Optional[OrderData] = self.main_engine.get_order(vt_orderid) if not order: @@ -237,7 +223,7 @@ def cancel_order(self, algo: AlgoTemplate, vt_orderid: str) -> None: self.main_engine.cancel_order(req, order.gateway_name) def get_tick(self, algo: AlgoTemplate) -> Optional[TickData]: - """""" + """查询行情""" tick: Optional[TickData] = self.main_engine.get_tick(algo.vt_symbol) if not tick: @@ -246,7 +232,7 @@ def get_tick(self, algo: AlgoTemplate) -> Optional[TickData]: return tick def get_contract(self, algo: AlgoTemplate) -> Optional[ContractData]: - """""" + """查询合约""" contract: Optional[ContractData] = self.main_engine.get_contract(algo.vt_symbol) if not contract: @@ -255,7 +241,7 @@ def get_contract(self, algo: AlgoTemplate) -> Optional[ContractData]: return contract def write_log(self, msg: str, algo: AlgoTemplate = None) -> None: - """""" + """输出日志""" if algo: msg: str = f"{algo.algo_name}:{msg}" @@ -263,40 +249,8 @@ def write_log(self, msg: str, algo: AlgoTemplate = None) -> None: event: Event = Event(EVENT_ALGO_LOG, data=log) self.event_engine.put(event) - def put_setting_event(self, setting_name: str, setting: dict) -> None: - """""" - event: Event = Event(EVENT_ALGO_SETTING) - event.data = { - "setting_name": setting_name, - "setting": setting - } - self.event_engine.put(event) - - def update_algo_setting(self, setting_name: str, setting: dict) -> None: - """""" - self.algo_settings[setting_name] = setting - - self.save_algo_setting() - - self.put_setting_event(setting_name, setting) - - def remove_algo_setting(self, setting_name: str) -> None: - """""" - if setting_name not in self.algo_settings: - return - self.algo_settings.pop(setting_name) - - event: Event = Event(EVENT_ALGO_SETTING) - event.data = { - "setting_name": setting_name, - "setting": None - } - self.event_engine.put(event) - - self.save_algo_setting() - def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: - """""" + """推送算法参数更新""" event: Event = Event(EVENT_ALGO_PARAMETERS) event.data = { "algo_name": algo.algo_name, @@ -305,7 +259,7 @@ def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: self.event_engine.put(event) def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: - """""" + """推送算法状态更新""" # 检查算法是否运行结束 if algo in self.algos.values() and algo.status in [AlgoStatus.STOPPED, AlgoStatus.FINISHED]: self.algos.pop(algo.algo_name) From 17cc2e876d48ff754b5fa6bdc246777b3edae7c2 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 14 Nov 2022 11:00:53 +0800 Subject: [PATCH 16/45] =?UTF-8?q?[Del]=20=E7=A7=BB=E9=99=A4DMA=E7=AE=97?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/dma_algo.py | 96 ------------------------------ 1 file changed, 96 deletions(-) delete mode 100644 vnpy_algotrading/algos/dma_algo.py diff --git a/vnpy_algotrading/algos/dma_algo.py b/vnpy_algotrading/algos/dma_algo.py deleted file mode 100644 index 27951c1..0000000 --- a/vnpy_algotrading/algos/dma_algo.py +++ /dev/null @@ -1,96 +0,0 @@ -from vnpy.trader.constant import Offset, Direction, OrderType -from vnpy.trader.object import TradeData, OrderData, TickData -from vnpy.trader.engine import BaseEngine - -from ..template import AlgoTemplate - - -class DmaAlgo(AlgoTemplate): - """""" - - display_name = "DMA 直接委托" - - default_setting = { - "vt_symbol": "", - "direction": [Direction.LONG.value, Direction.SHORT.value], - "order_type": [ - OrderType.MARKET.value, - OrderType.LIMIT.value, - OrderType.STOP.value, - OrderType.FAK.value, - OrderType.FOK.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", - "order_status", - ] - - def __init__( - self, - algo_engine: BaseEngine, - algo_name: str, - vt_symbol: str, - direction: str, - offset: str, - volume: float, - setting: dict - ): - """""" - super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) - - # 参数 - self.order_type = OrderType(setting["order_type"]) - self.price = setting["price"] - - # 变量 - self.vt_orderid = "" - self.traded = 0 - self.order_status = "" - - self.put_parameters_event() - self.put_variables_event() - - def on_tick(self, tick: TickData): - """""" - if not self.vt_orderid: - if self.direction == Direction.LONG: - self.vt_orderid = self.buy( - self.price, - self.volume, - self.order_type, - self.offset - ) - - else: - self.vt_orderid = self.sell( - self.price, - self.volume, - self.order_type, - 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 From 137279de24953bdf4d435213cb2ab5098028971b Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 14 Nov 2022 11:15:10 +0800 Subject: [PATCH 17/45] =?UTF-8?q?[Mod]=20=E7=AE=97=E6=B3=95=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E7=9A=84=E6=9E=84=E9=80=A0=E5=87=BD=E6=95=B0=E4=B8=AD?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0price=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 14 ++++++++++++-- vnpy_algotrading/template.py | 10 ++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 9800c80..717e4a9 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -124,7 +124,8 @@ def start_algo( vt_symbol: str, direction: Direction, offset: Offset, - volume: float, + price: float, + volume: int, setting: dict ) -> str: """启动算法""" @@ -139,7 +140,16 @@ def start_algo( # 创建算法实例 algo_template._count += 1 algo_name: str = f"{algo_template.__name__}_{algo_template._count}" - algo: AlgoTemplate = algo_template(self, algo_name, vt_symbol, direction, offset, volume, setting) + algo: AlgoTemplate = algo_template( + self, + algo_name, + vt_symbol, + direction, + offset, + price, + volume, + setting + ) # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index ce44f79..c6c88aa 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -24,7 +24,8 @@ def __init__( vt_symbol: str, direction: Direction, offset: Offset, - volume: float, + price: float, + volume: int, setting: dict ) -> None: """构造函数""" @@ -32,9 +33,10 @@ def __init__( self.algo_name: str = algo_name self.vt_symbol: str = vt_symbol - self.direction = direction - self.offset = offset - self.volume = volume + self.direction: Direction = direction + self.offset: Offset = offset + self.price: float = price + self.volume: int = volume self.status: str = AlgoStatus.PAUSED self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order From 758d1397e8d6899dbd7401785efdc50d70bee27c Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 14 Nov 2022 11:19:12 +0800 Subject: [PATCH 18/45] =?UTF-8?q?[Mod]=20AlgoWidget=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=97=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=AE=97=E6=B3=95=E9=80=9A=E7=94=A8=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/twap_algo.py | 36 ++--- vnpy_algotrading/ui/widget.py | 216 +++++----------------------- 2 files changed, 47 insertions(+), 205 deletions(-) diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index 9e28bb8..47aef99 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -1,5 +1,5 @@ from vnpy.trader.utility import round_to -from vnpy.trader.constant import Offset, Direction +from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, TickData from vnpy.trader.engine import BaseEngine @@ -7,24 +7,13 @@ class TwapAlgo(AlgoTemplate): - """""" + """TWAP算法类""" display_name = "TWAP 时间加权平均" default_setting = { - "vt_symbol": "", - "direction": [Direction.LONG.value, Direction.SHORT.value], - "price": 0.0, - "volume": 0.0, "time": 600, - "interval": 60, - "offset": [ - Offset.NONE.value, - Offset.OPEN.value, - Offset.CLOSE.value, - Offset.CLOSETODAY.value, - Offset.CLOSEYESTERDAY.value - ] + "interval": 60 } variables = [ @@ -62,44 +51,37 @@ def __init__( self.total_count = 0 self.traded = 0 - self.last_tick = None - self.put_parameters_event() self.put_variables_event() - def on_tick(self, tick: TickData): - """""" - self.last_tick = tick - 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() + self.finish() else: self.put_variables_event() def on_timer(self): - """""" + """定时回调""" self.timer_count += 1 self.total_count += 1 self.put_variables_event() if self.total_count >= self.time: self.write_log("执行时间已结束,停止算法") - self.stop() + self.finish() return if self.timer_count < self.interval: return self.timer_count = 0 - if not self.last_tick: + tick: TickData = self.get_tick() + if not tick: return - tick = self.last_tick - self.last_tick = None self.cancel_all() diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index ee90129..a538f95 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -14,7 +14,6 @@ EVENT_ALGO_LOG, EVENT_ALGO_PARAMETERS, EVENT_ALGO_VARIABLES, - EVENT_ALGO_SETTING, AlgoStatus, Direction, Offset @@ -23,19 +22,36 @@ class AlgoWidget(QtWidgets.QWidget): - """算法交易控件""" + """算法启动控件""" def __init__( self, algo_engine: AlgoEngine, algo_template: AlgoTemplate ) -> None: - """""" + """构造函数""" super().__init__() self.algo_engine: AlgoEngine = algo_engine self.template_name: str = algo_template.__name__ - self.default_setting: dict = algo_template.default_setting + + self.default_setting: dict = { + "vt_symbol": "", + "direction": [ + Direction.LONG.value, + Direction.SHORT.value + ], + "offset": [ + Offset.NONE.value, + Offset.OPEN.value, + Offset.CLOSE.value, + Offset.CLOSETODAY.value, + Offset.CLOSEYESTERDAY.value + ], + "price": 0.0, + "volume": 0, + } + self.default_setting.update(algo_template.default_setting) self.widgets: dict = {} @@ -73,24 +89,16 @@ def init_ui(self) -> None: form.addRow(QtWidgets.QLabel("")) form.addRow(QtWidgets.QLabel("")) - self.setting_name_line: str = QtWidgets.QLineEdit() - form.addRow("配置名称", self.setting_name_line) - - save_setting_button: QtWidgets.QPushButton = QtWidgets.QPushButton("保存配置") - save_setting_button.clicked.connect(self.save_setting) - form.addRow(save_setting_button) - for button in [ start_algo_button, - load_csv_button, - save_setting_button + load_csv_button ]: button.setFixedHeight(button.sizeHint().height() * 2) self.setLayout(form) def load_csv(self) -> None: - """""" + """加载CSV文件中的算法配置""" # 从对话框获取csv地址 path, type_ = QtWidgets.QFileDialog.getOpenFileName( self, @@ -157,7 +165,7 @@ def load_csv(self) -> None: self.algo_engine.start_algo(vt_symbol, direction, offset, volume, setting) def get_setting(self) -> dict: - """获取配置""" + """获取当前配置""" setting: dict = {"template_name": self.template_name} for field_name, tp in self.widgets.items(): @@ -183,40 +191,19 @@ def get_setting(self) -> dict: def start_algo(self) -> None: """启动交易算法""" setting: dict = self.get_setting() + if setting: vt_symbol: str = setting.pop("vt_symbol") direction: Direction = Direction(setting.pop("direction")) offset: Offset = Offset(setting.pop("offset")) - volume: float = setting.pop("volume") - self.algo_engine.start_algo(vt_symbol, direction, offset, volume, setting) - - def update_setting(self, setting_name: str, setting: dict) -> None: - """更新控件配置""" - self.setting_name_line.setText(setting_name) - - for name, tp in self.widgets.items(): - widget, _ = tp - value = setting[name] - - if isinstance(widget, QtWidgets.QLineEdit): - widget.setText(str(value)) - elif isinstance(widget, QtWidgets.QComboBox): - ix = widget.findText(value) - widget.setCurrentIndex(ix) - - def save_setting(self) -> None: - """保存算法配置""" - setting_name: str = self.setting_name_line.text() - if not setting_name: - return - - setting: dict = self.get_setting() - if setting: - self.algo_engine.update_algo_setting(setting_name, setting) + price: float = setting.pop("price") + volume: int = setting.pop("volume") + self.algo_engine.start_algo(vt_symbol, direction, offset, price, volume, setting) class AlgoMonitor(QtWidgets.QTableWidget): - """""" + """算法监控组件""" + parameters_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) variables_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) @@ -365,7 +352,7 @@ def get_algo_cells(self, algo_name: str) -> dict: class ActiveAlgoMonitor(AlgoMonitor): - """监控激活算法""" + """活动算法监控组件""" def __init__(self, algo_engine: AlgoEngine, event_engine: EventEngine) -> None: """""" @@ -373,125 +360,16 @@ def __init__(self, algo_engine: AlgoEngine, event_engine: EventEngine) -> None: class InactiveAlgoMonitor(AlgoMonitor): - """监控未激活算法""" + """结束算法监控组件""" def __init__(self, algo_engine: AlgoEngine, event_engine: EventEngine) -> None: """""" super().__init__(algo_engine, event_engine, False) -class SettingMonitor(QtWidgets.QTableWidget): - """""" - setting_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) - use_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(dict) - - def __init__(self, algo_engine: AlgoEngine, event_engine: EventEngine) -> None: - """""" - super().__init__() - - self.algo_engine: AlgoEngine = algo_engine - self.event_engine: EventEngine = event_engine - - self.settings: dict = {} - self.setting_cells: dict = {} - - self.init_ui() - self.register_event() - - def init_ui(self) -> None: - """""" - labels: list = [ - "", - "", - "名称", - "配置" - ] - self.setColumnCount(len(labels)) - self.setHorizontalHeaderLabels(labels) - self.verticalHeader().setVisible(False) - self.setEditTriggers(self.NoEditTriggers) - - self.verticalHeader().setSectionResizeMode( - QtWidgets.QHeaderView.ResizeToContents - ) - - self.horizontalHeader().setSectionResizeMode( - 3, - QtWidgets.QHeaderView.Stretch - ) - self.setWordWrap(True) - - def register_event(self) -> None: - """""" - self.setting_signal.connect(self.process_setting_event) - - self.event_engine.register( - EVENT_ALGO_SETTING, self.setting_signal.emit) - - def process_setting_event(self, event: Event) -> None: - """""" - data: Any = event.data - setting_name: str = data["setting_name"] - setting: dict = data["setting"] - cells: dict = self.get_setting_cells(setting_name) - - if setting: - self.settings[setting_name] = setting - - cells["setting"].setText(to_text(setting)) - else: - if setting_name in self.settings: - self.settings.pop(setting_name) - - row: int = self.row(cells["setting"]) - self.removeRow(row) - - self.setting_cells.pop(setting_name) - - def get_setting_cells(self, setting_name: str) -> dict: - """""" - cells: Optional[dict] = self.setting_cells.get(setting_name, None) - - if not cells: - use_func = partial(self.use_setting, setting_name=setting_name) - use_button: QtWidgets.QPushButton = QtWidgets.QPushButton("使用") - use_button.clicked.connect(use_func) - - remove_func = partial(self.remove_setting, - setting_name=setting_name) - remove_button: QtWidgets.QPushButton = QtWidgets.QPushButton("移除") - remove_button.clicked.connect(remove_func) - - name_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(setting_name) - setting_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - - self.insertRow(0) - self.setCellWidget(0, 0, use_button) - self.setCellWidget(0, 1, remove_button) - self.setItem(0, 2, name_cell) - self.setItem(0, 3, setting_cell) - - cells: dict = { - "name": name_cell, - "setting": setting_cell - } - self.setting_cells[setting_name] = cells - - return cells - - def use_setting(self, setting_name: str) -> None: - """""" - setting: dict = self.settings[setting_name] - setting["setting_name"] = setting_name - self.use_signal.emit(setting) - - def remove_setting(self, setting_name: str) -> None: - """""" - self.algo_engine.remove_algo_setting(setting_name) - - class LogMonitor(QtWidgets.QTableWidget): - """""" + """日志组件""" + signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) def __init__(self, event_engine: EventEngine) -> None: @@ -545,7 +423,7 @@ def process_log_event(self, event: Event) -> None: class AlgoManager(QtWidgets.QWidget): - """""" + """算法交易管理控件""" def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None: """""" @@ -610,19 +488,13 @@ def init_ui(self) -> None: tab2: QtWidgets.QTabWidget = QtWidgets.QTabWidget() tab2.addTab(log_monitor, "日志") - setting_monitor: SettingMonitor = SettingMonitor(self.algo_engine, self.event_engine) - setting_monitor.use_signal.connect(self.use_setting) - tab3: QtWidgets.QTabWidget = QtWidgets.QTabWidget() - tab3.addTab(setting_monitor, "配置") - - grid: QtWidgets.QGridLayout = QtWidgets.QGridLayout() - grid.addWidget(tab1, 0, 0, 1, 2) - grid.addWidget(tab2, 1, 0) - grid.addWidget(tab3, 1, 1) + vbox2: QtWidgets.QVBoxLayout = QtWidgets.QVBoxLayout() + vbox2.addWidget(tab1) + vbox2.addWidget(tab2) hbox2: QtWidgets.QHBoxLayout = QtWidgets.QHBoxLayout() hbox2.addLayout(vbox) - hbox2.addLayout(grid) + hbox2.addLayout(vbox2) self.setLayout(hbox2) self.show_algo_widget() @@ -638,18 +510,6 @@ def show_algo_widget(self) -> None: else: widget.hide() - def use_setting(self, setting: dict) -> None: - """""" - setting_name: str = setting["setting_name"] - template_name: str = setting["template_name"] - - widget: AlgoWidget = self.algo_widgets[template_name] - widget.update_setting(setting_name, setting) - - ix: int = self.template_combo.findData(template_name) - self.template_combo.setCurrentIndex(ix) - self.show_algo_widget() - def show(self) -> None: """""" self.showMaximized() From 4ae5c0b52321e97f1f0f07d7ebc34742f9f168b5 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:26:09 +0800 Subject: [PATCH 19/45] =?UTF-8?q?[Mod]=20=E5=A2=9E=E5=8A=A0price=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/twap_algo.py | 4 ++-- vnpy_algotrading/ui/widget.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index 47aef99..a34b4f4 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -30,14 +30,14 @@ def __init__( vt_symbol: str, direction: str, offset: str, + price: float, volume: float, setting: dict ): """""" - super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.price = setting["price"] self.time = setting["time"] self.interval = setting["interval"] diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index a538f95..bb66b81 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -161,8 +161,9 @@ def load_csv(self) -> None: vt_symbol: str = setting.pop("vt_symbol") direction: Direction = Direction(setting.pop("direction")) offset: Offset = Offset(setting.pop("offset")) + price: float = setting.pop("price") volume: float = setting.pop("volume") - self.algo_engine.start_algo(vt_symbol, direction, offset, volume, setting) + self.algo_engine.start_algo(vt_symbol, direction, offset, price, volume, setting) def get_setting(self) -> dict: """获取当前配置""" From 510a87f2d9003a757ae92432ddf111aea27bec68 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:26:24 +0800 Subject: [PATCH 20/45] [Fix] typo --- vnpy_algotrading/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index c6c88aa..810c59f 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -131,7 +131,7 @@ def buy( offset: Offset = Offset.NONE ) -> None: """买入""" - if self.status == AlgoStatus.RUNNING: + if self.status != AlgoStatus.RUNNING: return msg: str = f"{self.vt_symbol},委托买入{order_type.value},{volume}@{price}" @@ -154,7 +154,7 @@ def sell( offset: Offset = Offset.NONE ) -> None: """卖出""" - if self.status == AlgoStatus.RUNNING: + if self.status != AlgoStatus.RUNNING: return msg: str = f"{self.vt_symbol}委托卖出{order_type.value},{volume}@{price}" From 7537d8a3ef90906ecaaa49dc4f8b40f08e663f77 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:26:41 +0800 Subject: [PATCH 21/45] =?UTF-8?q?[Fix]=20=E6=89=BE=E4=B8=8D=E5=88=B0termin?= =?UTF-8?q?ate=E5=87=BD=E6=95=B0=E7=9A=84=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 717e4a9..d7e5920 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -59,18 +59,16 @@ def close(self) -> None: def load_algo_template(self) -> None: """载入算法类""" 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 - from .algos.dma_algo import DmaAlgo +# 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) - self.add_algo_template(DmaAlgo) +# 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) -> None: """添加算法类""" @@ -184,7 +182,7 @@ def stop_algo(self, algo_name: str) -> None: """停止算法""" algo: Optional[AlgoTemplate] = self.algos.get(algo_name, None) if algo: - algo.terminate() + algo.stop() def stop_all(self) -> None: """停止全部算法""" From cd44ea827a2ca9c95c47f14de799ea83f7c24d86 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 14:34:13 +0800 Subject: [PATCH 22/45] =?UTF-8?q?[Mod]=20=E5=A2=9E=E5=8A=A0subscribe?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index d7e5920..4d6a57f 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -9,7 +9,7 @@ EVENT_ORDER, EVENT_TRADE ) -from vnpy.trader.constant import Direction, Offset, OrderType +from vnpy.trader.constant import Direction, Offset, OrderType, Exchange from vnpy.trader.object import ( SubscribeRequest, OrderRequest, @@ -152,12 +152,7 @@ def start_algo( # 订阅行情 algos: set = self.symbol_algo_map[algo.vt_symbol] if not algos: - req: SubscribeRequest = SubscribeRequest( - symbol=contract.symbol, - exchange=contract.exchange - ) - self.main_engine.subscribe(req, contract.gateway_name) - + self.subscribe(contract.symbol, contract.exchange, contract.gateway_name) algos.add(algo) # 启动算法 @@ -189,6 +184,14 @@ def stop_all(self) -> None: for algo_name in list(self.algos.keys()): self.stop_algo(algo_name) + def subscribe(self, symbol: str, exchange: Exchange, gateway_name: str) -> None: + """订阅行情""" + req: SubscribeRequest = SubscribeRequest( + symbol=symbol, + exchange=exchange + ) + self.main_engine.subscribe(req, gateway_name) + def send_order( self, algo: AlgoTemplate, From 24af5bb96503d7e76c876f6f58208dae950cda6d Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:05:03 +0800 Subject: [PATCH 23/45] [Mod] BestLimitAlgo --- vnpy_algotrading/algos/best_limit_algo.py | 57 +++++++++-------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index 787bcef..8f774dd 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -1,6 +1,6 @@ from random import uniform -from vnpy.trader.constant import Offset, Direction +from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, OrderData, TickData from vnpy.trader.engine import BaseEngine from vnpy.trader.utility import round_to @@ -9,14 +9,11 @@ class BestLimitAlgo(AlgoTemplate): - """""" + """最优限价算法类""" display_name = "BestLimit 最优限价" default_setting = { - "vt_symbol": "", - "direction": [Direction.LONG.value, Direction.SHORT.value], - "volume": 0.0, "min_volume": 0.0, "max_volume": 0.0, "volume_change": [ @@ -26,21 +23,13 @@ class BestLimitAlgo(AlgoTemplate): "0.001", "0.0001", "0.00001" - ], - "offset": [ - Offset.NONE.value, - Offset.OPEN.value, - Offset.CLOSE.value, - Offset.CLOSETODAY.value, - Offset.CLOSEYESTERDAY.value ] } variables = [ "traded", "vt_orderid", - "order_price", - "last_tick", + "order_price" ] def __init__( @@ -50,11 +39,12 @@ def __init__( vt_symbol: str, direction: str, offset: str, + price: float, volume: float, setting: dict ): """""" - super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 self.min_volume = setting["min_volume"] @@ -68,7 +58,6 @@ def __init__( # 变量 self.vt_orderid = "" self.traded = 0 - self.last_tick = None self.order_price = 0 self.put_parameters_event() @@ -77,70 +66,68 @@ def __init__( # 检查最大/最小挂单量 if self.min_volume <= 0: self.write_log("最小挂单量必须大于0,算法启动失败") - self.stop() + self.finish() return if self.max_volume < self.min_volume: self.write_log("最大挂单量必须不小于最小委托量,算法启动失败") - self.stop() + self.finish() return def on_tick(self, tick: TickData): - """""" - self.last_tick = 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.buy_best_limit(tick.bid_price_1) + elif self.order_price != 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.sell_best_limit(tick.ask_price_1) + elif self.order_price != 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() + self.finish() 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): - """""" + def buy_best_limit(self, bid_price_1: float): + """最优限价买入""" volume_left = self.volume - self.traded rand_volume = self.generate_rand_volume() order_volume = min(rand_volume, volume_left) - self.order_price = self.last_tick.bid_price_1 + self.order_price = bid_price_1 self.vt_orderid = self.buy( self.order_price, order_volume, offset=self.offset ) - def sell_best_limit(self): - """""" + def sell_best_limit(self, ask_price_1: float): + """最优限价卖出""" volume_left = self.volume - self.traded rand_volume = self.generate_rand_volume() order_volume = min(rand_volume, volume_left) - self.order_price = self.last_tick.ask_price_1 + self.order_price = ask_price_1 self.vt_orderid = self.sell( self.order_price, order_volume, @@ -148,7 +135,7 @@ def sell_best_limit(self): ) def generate_rand_volume(self): - """""" + """随机生成委托数量""" rand_volume = uniform(self.min_volume, self.max_volume) rand_volume = round_to(rand_volume, self.volume_change) From d1d3a921613a54b8e7e50f2701ef69b406462a3d Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:05:20 +0800 Subject: [PATCH 24/45] [Mod] IcebergAlgo --- vnpy_algotrading/algos/iceberg_algo.py | 47 +++++++------------------- 1 file changed, 13 insertions(+), 34 deletions(-) diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index 9b597d0..1cb0307 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -1,4 +1,4 @@ -from vnpy.trader.constant import Offset, Direction +from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, OrderData, TickData from vnpy.trader.engine import BaseEngine @@ -6,24 +6,13 @@ 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 - ] + "interval": 0 } variables = [ @@ -39,14 +28,14 @@ def __init__( vt_symbol: str, direction: str, offset: str, + price: float, volume: float, setting: dict ): """""" - super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.price = setting["price"] self.display_volume = setting["display_volume"] self.interval = setting["interval"] @@ -55,21 +44,11 @@ def __init__( self.vt_orderid = "" self.traded = 0 - self.last_tick = None - 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) @@ -78,17 +57,17 @@ def on_order(self, order: OrderData): 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() + self.finish() else: self.put_variables_event() def on_timer(self): - """""" + """定时回调""" self.timer_count += 1 if self.timer_count < self.interval: @@ -97,8 +76,8 @@ def on_timer(self): self.timer_count = 0 - contract = self.get_contract() - if not contract: + tick: TickData = self.get_tick() + if not tick: return # 当委托完成后,发起新的委托 @@ -121,12 +100,12 @@ def on_timer(self): # 否则检查撤单 else: if self.direction == Direction.LONG: - if self.last_tick.ask_price_1 <= self.price: + if 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: + if tick.bid_price_1 >= self.price: self.cancel_order(self.vt_orderid) self.vt_orderid = "" self.write_log(u"最新Tick买一价,高于卖出委托价格,之前委托可能丢失,强制撤单") From 977aee76232220a54b43a8fb38c8092002494d67 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:05:35 +0800 Subject: [PATCH 25/45] [Mod] SniperAlgo --- vnpy_algotrading/algos/sniper_algo.py | 32 ++++++++------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index a7be112..b944489 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -1,4 +1,4 @@ -from vnpy.trader.constant import Offset, Direction +from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, OrderData, TickData from vnpy.trader.engine import BaseEngine @@ -6,23 +6,11 @@ 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 - ] - } + default_setting = {} variables = [ "traded", @@ -36,14 +24,12 @@ def __init__( vt_symbol: str, direction: str, offset: str, + price: float, volume: float, setting: dict ): """""" - super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) - - # 参数 - self.price = setting["price"] + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 变量 self.vt_orderid = "" @@ -53,7 +39,7 @@ def __init__( self.put_variables_event() def on_tick(self, tick: TickData): - """""" + """Tick行情回调""" if self.vt_orderid: self.cancel_all() return @@ -82,17 +68,17 @@ def on_tick(self, tick: TickData): 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() + self.finish() else: self.put_variables_event() From b0609306c27542d5c70c2d59e86cfd7469854e55 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:05:51 +0800 Subject: [PATCH 26/45] [Mod] StopAlgo --- vnpy_algotrading/algos/stop_algo.py | 31 +++++++++-------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index 38d8b13..43cf2c4 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -1,28 +1,18 @@ -from vnpy.trader.constant import Offset, Direction -from vnpy.trader.object import TradeData, OrderData, TickData +from vnpy.trader.constant import Direction +from vnpy.trader.object import OrderData, TickData from vnpy.trader.engine import BaseEngine from ..template 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 - ] + "price_add": 0.0 } variables = [ @@ -38,11 +28,12 @@ def __init__( vt_symbol: str, direction: str, offset: str, + price: float, volume: float, setting: dict ): """""" - super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, volume, setting) + super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 self.stop_price = setting["stop_price"] @@ -57,7 +48,7 @@ def __init__( self.put_variables_event() def on_tick(self, tick: TickData): - """""" + """Tick行情回调""" if self.vt_orderid: return @@ -94,14 +85,10 @@ def on_tick(self, tick: TickData): 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.finish() self.put_variables_event() - - def on_trade(self, trade: TradeData): - """""" - pass From 4c671f55bd595d833eb502c6d472c9746254e005 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Mon, 14 Nov 2022 17:06:23 +0800 Subject: [PATCH 27/45] =?UTF-8?q?[Mod]=20=E5=A2=9E=E5=8A=A0=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=8F=82=E6=95=B0=E6=98=BE=E7=A4=BA=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 16 ++++++++-------- vnpy_algotrading/template.py | 5 ++++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 4d6a57f..6974119 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -59,16 +59,16 @@ def close(self) -> None: def load_algo_template(self) -> None: """载入算法类""" 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 + 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) + 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) -> None: """添加算法类""" diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 810c59f..d01e12b 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -195,8 +195,11 @@ def write_log(self, msg: str) -> None: def put_parameters_event(self) -> None: """推送参数更新""" + keys: list = list(self.default_setting.keys()) + keys.extend(["vt_symbol", "direction", "offset", "price", "volume"]) + parameters: dict = {} - for name in self.default_setting.keys(): + for name in keys: parameters[name] = getattr(self, name) self.algo_engine.put_parameters_event(self, parameters) From 8462fe9dedd330d09e9b3c939ae0cff95271a688 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 15 Nov 2022 14:11:03 +0800 Subject: [PATCH 28/45] =?UTF-8?q?[Mod]=20=E8=B0=83=E6=95=B4=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=98=BE=E7=A4=BA=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index d01e12b..e8d15e3 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -195,8 +195,8 @@ def write_log(self, msg: str) -> None: def put_parameters_event(self) -> None: """推送参数更新""" - keys: list = list(self.default_setting.keys()) - keys.extend(["vt_symbol", "direction", "offset", "price", "volume"]) + keys: list = ["vt_symbol", "direction", "offset", "price", "volume"] + keys.extend(self.default_setting.keys()) parameters: dict = {} for name in keys: From b86ac3fb64316b2d3764b7d2612864f2b17db8a9 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 15 Nov 2022 14:16:44 +0800 Subject: [PATCH 29/45] =?UTF-8?q?[Mod]=20StopAlgo=E7=9A=84=E5=81=9C?= =?UTF-8?q?=E6=AD=A2=E5=8D=95=E4=BB=B7=E6=A0=BC=E6=94=B9=E4=B8=BA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8price=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/stop_algo.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index 43cf2c4..a0e2cf5 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -11,7 +11,6 @@ class StopAlgo(AlgoTemplate): display_name = "Stop 条件委托" default_setting = { - "stop_price": 0.0, "price_add": 0.0 } @@ -36,7 +35,6 @@ def __init__( super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.stop_price = setting["stop_price"] self.price_add = setting["price_add"] # 变量 @@ -53,8 +51,8 @@ def on_tick(self, tick: TickData): return if self.direction == Direction.LONG: - if tick.last_price >= self.stop_price: - price = self.stop_price + self.price_add + if tick.last_price >= self.price: + price = self.price + self.price_add if tick.limit_up: price = min(price, tick.limit_up) @@ -65,11 +63,11 @@ def on_tick(self, tick: TickData): offset=self.offset ) self.write_log( - f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.stop_price},数量:{self.volume},开平:{self.offset}") + f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.price},数量:{self.volume},开平:{self.offset}") else: - if tick.last_price <= self.stop_price: - price = self.stop_price - self.price_add + if tick.last_price <= self.price: + price = self.price - self.price_add if tick.limit_down: price = max(price, tick.limit_down) @@ -80,7 +78,7 @@ def on_tick(self, tick: TickData): offset=self.offset ) self.write_log( - f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.stop_price},数量:{self.volume},开平:{self.offset}") + f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.price},数量:{self.volume},开平:{self.offset}") self.put_variables_event() From 3d2edc6f67c11e866176ac7c540b7d6e892acfa9 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 15 Nov 2022 14:34:37 +0800 Subject: [PATCH 30/45] =?UTF-8?q?[Mod]=20BestLimitAlgo=E4=B8=AD=E7=9A=84vo?= =?UTF-8?q?lume=5Fchange=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index 8f774dd..d309211 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -14,16 +14,8 @@ class BestLimitAlgo(AlgoTemplate): display_name = "BestLimit 最优限价" default_setting = { - "min_volume": 0.0, - "max_volume": 0.0, - "volume_change": [ - "1", - "0.1", - "0.01", - "0.001", - "0.0001", - "0.00001" - ] + "min_volume": 0, + "max_volume": 0, } variables = [ @@ -50,11 +42,6 @@ def __init__( self.min_volume = setting["min_volume"] self.max_volume = setting["max_volume"] - if "." in setting["volume_change"]: - self.volume_change = float(setting["volume_change"]) - else: - self.volume_change = int(setting["volume_change"]) - # 变量 self.vt_orderid = "" self.traded = 0 @@ -138,8 +125,4 @@ def generate_rand_volume(self): """随机生成委托数量""" rand_volume = uniform(self.min_volume, self.max_volume) rand_volume = round_to(rand_volume, self.volume_change) - - if self.volume_change == 1: - rand_volume = int(rand_volume) - - return rand_volume + return int(rand_volume) From 014ac487e5e4b67f9d4d64176ef66b0315df20eb Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:41:13 +0800 Subject: [PATCH 31/45] =?UTF-8?q?[Add]=20=E5=A2=9E=E5=8A=A0algos=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 47 +++++++++++------------ vnpy_algotrading/algos/iceberg_algo.py | 30 +++++++-------- vnpy_algotrading/algos/sniper_algo.py | 20 +++++----- vnpy_algotrading/algos/stop_algo.py | 26 ++++++------- vnpy_algotrading/algos/twap_algo.py | 32 +++++++-------- 5 files changed, 77 insertions(+), 78 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index d309211..c9a2641 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -11,14 +11,14 @@ class BestLimitAlgo(AlgoTemplate): """最优限价算法类""" - display_name = "BestLimit 最优限价" + display_name: str = "BestLimit 最优限价" - default_setting = { + default_setting: dict = { "min_volume": 0, "max_volume": 0, } - variables = [ + variables: list = [ "traded", "vt_orderid", "order_price" @@ -34,18 +34,18 @@ def __init__( price: float, volume: float, setting: dict - ): - """""" + ) -> None: + """构造函数""" super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.min_volume = setting["min_volume"] - self.max_volume = setting["max_volume"] + self.min_volume: float = setting["min_volume"] + self.max_volume: float = setting["max_volume"] # 变量 - self.vt_orderid = "" - self.traded = 0 - self.order_price = 0 + self.vt_orderid: str = "" + self.traded: float = 0 + self.order_price: float = 0 self.put_parameters_event() self.put_variables_event() @@ -61,7 +61,7 @@ def __init__( self.finish() return - def on_tick(self, tick: TickData): + def on_tick(self, tick: TickData) -> None: """Tick行情回调""" if self.direction == Direction.LONG: if not self.vt_orderid: @@ -76,7 +76,7 @@ def on_tick(self, tick: TickData): self.put_variables_event() - def on_trade(self, trade: TradeData): + def on_trade(self, trade: TradeData) -> None: """成交回调""" self.traded += trade.volume @@ -86,19 +86,19 @@ def on_trade(self, trade: TradeData): else: self.put_variables_event() - def on_order(self, order: OrderData): + def on_order(self, order: OrderData) -> None: """委托回调""" if not order.is_active(): self.vt_orderid = "" self.order_price = 0 self.put_variables_event() - def buy_best_limit(self, bid_price_1: float): + def buy_best_limit(self, bid_price_1: float) -> None: """最优限价买入""" - volume_left = self.volume - self.traded + volume_left: float = self.volume - self.traded - rand_volume = self.generate_rand_volume() - order_volume = min(rand_volume, volume_left) + rand_volume: int = self.generate_rand_volume() + order_volume: float = min(rand_volume, volume_left) self.order_price = bid_price_1 self.vt_orderid = self.buy( @@ -107,12 +107,12 @@ def buy_best_limit(self, bid_price_1: float): offset=self.offset ) - def sell_best_limit(self, ask_price_1: float): + def sell_best_limit(self, ask_price_1: float) -> None: """最优限价卖出""" - volume_left = self.volume - self.traded + volume_left: float = self.volume - self.traded - rand_volume = self.generate_rand_volume() - order_volume = min(rand_volume, volume_left) + rand_volume: int = self.generate_rand_volume() + order_volume: float = min(rand_volume, volume_left) self.order_price = ask_price_1 self.vt_orderid = self.sell( @@ -121,8 +121,7 @@ def sell_best_limit(self, ask_price_1: float): offset=self.offset ) - def generate_rand_volume(self): + def generate_rand_volume(self) -> int: """随机生成委托数量""" - rand_volume = uniform(self.min_volume, self.max_volume) - rand_volume = round_to(rand_volume, self.volume_change) + rand_volume: float = uniform(self.min_volume, self.max_volume) return int(rand_volume) diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index 1cb0307..cd15abe 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -8,14 +8,14 @@ class IcebergAlgo(AlgoTemplate): """冰山算法类""" - display_name = "Iceberg 冰山" + display_name: str = "Iceberg 冰山" - default_setting = { + default_setting: dict = { "display_volume": 0.0, "interval": 0 } - variables = [ + variables: list = [ "traded", "timer_count", "vt_orderid" @@ -31,32 +31,32 @@ def __init__( price: float, volume: float, setting: dict - ): - """""" + ) -> None: + """构造函数""" super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.display_volume = setting["display_volume"] - self.interval = setting["interval"] + self.display_volume: float = setting["display_volume"] + self.interval: int = setting["interval"] # 变量 - self.timer_count = 0 - self.vt_orderid = "" - self.traded = 0 + self.timer_count: int = 0 + self.vt_orderid: str = "" + self.traded: float = 0 self.put_parameters_event() self.put_variables_event() - def on_order(self, order: OrderData): + def on_order(self, order: OrderData) -> None: """委托回调""" - msg = f"委托号:{order.vt_orderid},委托状态:{order.status.value}" + msg: str = 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): + def on_trade(self, trade: TradeData) -> None: """成交回调""" self.traded += trade.volume @@ -66,7 +66,7 @@ def on_trade(self, trade: TradeData): else: self.put_variables_event() - def on_timer(self): + def on_timer(self) -> None: """定时回调""" self.timer_count += 1 @@ -82,7 +82,7 @@ def on_timer(self): # 当委托完成后,发起新的委托 if not self.vt_orderid: - order_volume = self.volume - self.traded + order_volume: float = self.volume - self.traded order_volume = min(order_volume, self.display_volume) if self.direction == Direction.LONG: diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index b944489..f5aa9d9 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -8,11 +8,11 @@ class SniperAlgo(AlgoTemplate): """狙击手算法类""" - display_name = "Sniper 狙击手" + display_name: str = "Sniper 狙击手" - default_setting = {} + default_setting: dict = {} - variables = [ + variables: list = [ "traded", "vt_orderid" ] @@ -27,8 +27,8 @@ def __init__( price: float, volume: float, setting: dict - ): - """""" + ) -> None: + """构造函数""" super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 变量 @@ -38,7 +38,7 @@ def __init__( self.put_parameters_event() self.put_variables_event() - def on_tick(self, tick: TickData): + def on_tick(self, tick: TickData) -> None: """Tick行情回调""" if self.vt_orderid: self.cancel_all() @@ -46,7 +46,7 @@ def on_tick(self, tick: TickData): if self.direction == Direction.LONG: if tick.ask_price_1 <= self.price: - order_volume = self.volume - self.traded + order_volume: float = self.volume - self.traded order_volume = min(order_volume, tick.ask_volume_1) self.vt_orderid = self.buy( @@ -56,7 +56,7 @@ def on_tick(self, tick: TickData): ) else: if tick.bid_price_1 >= self.price: - order_volume = self.volume - self.traded + order_volume: float = self.volume - self.traded order_volume = min(order_volume, tick.bid_volume_1) self.vt_orderid = self.sell( @@ -67,13 +67,13 @@ def on_tick(self, tick: TickData): self.put_variables_event() - def on_order(self, order: OrderData): + def on_order(self, order: OrderData) -> None: """委托回调""" if not order.is_active(): self.vt_orderid = "" self.put_variables_event() - def on_trade(self, trade: TradeData): + def on_trade(self, trade: TradeData) -> None: """成交回调""" self.traded += trade.volume diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index a0e2cf5..0869799 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -8,13 +8,13 @@ class StopAlgo(AlgoTemplate): """条件委托算法类""" - display_name = "Stop 条件委托" + display_name: str = "Stop 条件委托" - default_setting = { + default_setting: dict = { "price_add": 0.0 } - variables = [ + variables: list = [ "traded", "vt_orderid", "order_status", @@ -30,29 +30,29 @@ def __init__( price: float, volume: float, setting: dict - ): - """""" + ) -> None: + """构造函数""" super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.price_add = setting["price_add"] + self.price_add: float = setting["price_add"] # 变量 - self.vt_orderid = "" - self.traded = 0 - self.order_status = "" + self.vt_orderid: str = "" + self.traded: float = 0 + self.order_status: str = "" self.put_parameters_event() self.put_variables_event() - def on_tick(self, tick: TickData): + def on_tick(self, tick: TickData) -> None: """Tick行情回调""" if self.vt_orderid: return if self.direction == Direction.LONG: if tick.last_price >= self.price: - price = self.price + self.price_add + price: float = self.price + self.price_add if tick.limit_up: price = min(price, tick.limit_up) @@ -67,7 +67,7 @@ def on_tick(self, tick: TickData): else: if tick.last_price <= self.price: - price = self.price - self.price_add + price: float = self.price - self.price_add if tick.limit_down: price = max(price, tick.limit_down) @@ -82,7 +82,7 @@ def on_tick(self, tick: TickData): self.put_variables_event() - def on_order(self, order: OrderData): + def on_order(self, order: OrderData) -> None: """委托回调""" self.traded = order.traded self.order_status = order.status diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index a34b4f4..5f3c515 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -1,6 +1,6 @@ from vnpy.trader.utility import round_to from vnpy.trader.constant import Direction -from vnpy.trader.object import TradeData, TickData +from vnpy.trader.object import TradeData, TickData, ContractData from vnpy.trader.engine import BaseEngine from ..template import AlgoTemplate @@ -9,14 +9,14 @@ class TwapAlgo(AlgoTemplate): """TWAP算法类""" - display_name = "TWAP 时间加权平均" + display_name: str = "TWAP 时间加权平均" - default_setting = { + default_setting: dict = { "time": 600, "interval": 60 } - variables = [ + variables: list = [ "traded", "order_volume", "timer_count", @@ -33,28 +33,28 @@ def __init__( price: float, volume: float, setting: dict - ): - """""" + ) -> None: + """构造函数""" super().__init__(algo_engine, algo_name, vt_symbol, direction, offset, price, volume, setting) # 参数 - self.time = setting["time"] - self.interval = setting["interval"] + self.time: int = setting["time"] + self.interval: int = setting["interval"] # 变量 - self.order_volume = self.volume / (self.time / self.interval) - contract = self.get_contract() + self.order_volume: int = self.volume / (self.time / self.interval) + contract: ContractData = self.get_contract() if contract: self.order_volume = round_to(self.order_volume, contract.min_volume) - self.timer_count = 0 - self.total_count = 0 - self.traded = 0 + self.timer_count: int = 0 + self.total_count: int = 0 + self.traded: int = 0 self.put_parameters_event() self.put_variables_event() - def on_trade(self, trade: TradeData): + def on_trade(self, trade: TradeData) -> None: """成交回调""" self.traded += trade.volume @@ -64,7 +64,7 @@ def on_trade(self, trade: TradeData): else: self.put_variables_event() - def on_timer(self): + def on_timer(self) -> None: """定时回调""" self.timer_count += 1 self.total_count += 1 @@ -85,7 +85,7 @@ def on_timer(self): self.cancel_all() - left_volume = self.volume - self.traded + left_volume: int = self.volume - self.traded order_volume = min(self.order_volume, left_volume) if self.direction == Direction.LONG: From 344060cfd8a5f59a9b662cf73a12345530d127d3 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:45:42 +0800 Subject: [PATCH 32/45] =?UTF-8?q?[Del]=20=E5=88=A0=E9=99=A4=E7=94=A8?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index c9a2641..ac38d40 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -3,7 +3,6 @@ from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, OrderData, TickData from vnpy.trader.engine import BaseEngine -from vnpy.trader.utility import round_to from ..template import AlgoTemplate From 72f891e5392839d2a837834fc6b24fd3c3ed5686 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:53:34 +0800 Subject: [PATCH 33/45] =?UTF-8?q?[Del]=20=E5=88=A0=E9=99=A4=E7=94=A8?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vnpy_algotrading/__init__.py b/vnpy_algotrading/__init__.py index c7da03a..83803b1 100644 --- a/vnpy_algotrading/__init__.py +++ b/vnpy_algotrading/__init__.py @@ -27,7 +27,6 @@ from vnpy.trader.app import BaseApp from .engine import AlgoEngine, APP_NAME -from .template import AlgoTemplate try: From f4fcc67961aa542c9067b3ab6be2ddd386780c7a Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 15 Nov 2022 17:13:45 +0800 Subject: [PATCH 34/45] =?UTF-8?q?[Mod]=20=E6=8A=8Atraded=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E6=94=BE=E5=9C=A8template=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 3 +-- vnpy_algotrading/algos/iceberg_algo.py | 2 -- vnpy_algotrading/algos/sniper_algo.py | 6 +----- vnpy_algotrading/algos/stop_algo.py | 2 -- vnpy_algotrading/algos/twap_algo.py | 2 -- vnpy_algotrading/template.py | 2 ++ 6 files changed, 4 insertions(+), 13 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index ac38d40..a717cd3 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -3,6 +3,7 @@ from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, OrderData, TickData from vnpy.trader.engine import BaseEngine +from vnpy.trader.utility import round_to from ..template import AlgoTemplate @@ -18,7 +19,6 @@ class BestLimitAlgo(AlgoTemplate): } variables: list = [ - "traded", "vt_orderid", "order_price" ] @@ -43,7 +43,6 @@ def __init__( # 变量 self.vt_orderid: str = "" - self.traded: float = 0 self.order_price: float = 0 self.put_parameters_event() diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index cd15abe..059e6c4 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -16,7 +16,6 @@ class IcebergAlgo(AlgoTemplate): } variables: list = [ - "traded", "timer_count", "vt_orderid" ] @@ -42,7 +41,6 @@ def __init__( # 变量 self.timer_count: int = 0 self.vt_orderid: str = "" - self.traded: float = 0 self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index f5aa9d9..1eb612c 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -12,10 +12,7 @@ class SniperAlgo(AlgoTemplate): default_setting: dict = {} - variables: list = [ - "traded", - "vt_orderid" - ] + variables: list = ["vt_orderid"] def __init__( self, @@ -33,7 +30,6 @@ def __init__( # 变量 self.vt_orderid = "" - self.traded = 0 self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index 0869799..1599db3 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -15,7 +15,6 @@ class StopAlgo(AlgoTemplate): } variables: list = [ - "traded", "vt_orderid", "order_status", ] @@ -39,7 +38,6 @@ def __init__( # 变量 self.vt_orderid: str = "" - self.traded: float = 0 self.order_status: str = "" self.put_parameters_event() diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index 5f3c515..61005f8 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -17,7 +17,6 @@ class TwapAlgo(AlgoTemplate): } variables: list = [ - "traded", "order_volume", "timer_count", "total_count" @@ -49,7 +48,6 @@ def __init__( self.timer_count: int = 0 self.total_count: int = 0 - self.traded: int = 0 self.put_parameters_event() self.put_variables_event() diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index e8d15e3..7f63cb6 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -39,9 +39,11 @@ def __init__( self.volume: int = volume self.status: str = AlgoStatus.PAUSED + self.traded: float = 0 self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order self.variables.insert(0, "status") + self.variables.insert(1, "traded") def update_tick(self, tick: TickData) -> None: """行情数据更新""" From 918ef7dfa233bb916ae81e7754eea1206f20a7f7 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 15 Nov 2022 17:54:01 +0800 Subject: [PATCH 35/45] =?UTF-8?q?[Mod]=20=E5=A2=9E=E5=8A=A0=E6=88=90?= =?UTF-8?q?=E4=BA=A4=E5=9D=87=E4=BB=B7=E6=98=BE=E7=A4=BA=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 2 -- vnpy_algotrading/algos/iceberg_algo.py | 2 -- vnpy_algotrading/algos/sniper_algo.py | 2 -- vnpy_algotrading/algos/stop_algo.py | 1 - vnpy_algotrading/algos/twap_algo.py | 2 -- vnpy_algotrading/template.py | 6 ++++++ vnpy_algotrading/ui/display.py | 1 + 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index a717cd3..8db6212 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -76,8 +76,6 @@ def on_tick(self, tick: TickData) -> None: def on_trade(self, trade: TradeData) -> None: """成交回调""" - self.traded += trade.volume - if self.traded >= self.volume: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index 059e6c4..f3a9c60 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -56,8 +56,6 @@ def on_order(self, order: OrderData) -> None: def on_trade(self, trade: TradeData) -> None: """成交回调""" - self.traded += trade.volume - if self.traded >= self.volume: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index 1eb612c..0b950ed 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -71,8 +71,6 @@ def on_order(self, order: OrderData) -> None: def on_trade(self, trade: TradeData) -> None: """成交回调""" - self.traded += trade.volume - if self.traded >= self.volume: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index 1599db3..c83bf43 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -82,7 +82,6 @@ def on_tick(self, tick: TickData) -> None: def on_order(self, order: OrderData) -> None: """委托回调""" - self.traded = order.traded self.order_status = order.status if not order.is_active(): diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index 61005f8..9215439 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -54,8 +54,6 @@ def __init__( def on_trade(self, trade: TradeData) -> None: """成交回调""" - self.traded += trade.volume - if self.traded >= self.volume: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 7f63cb6..c2709cb 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -40,10 +40,12 @@ def __init__( self.status: str = AlgoStatus.PAUSED self.traded: float = 0 + self.traded_price: float = 0 self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order self.variables.insert(0, "status") self.variables.insert(1, "traded") + self.variables.insert(2, "traded_price") def update_tick(self, tick: TickData) -> None: """行情数据更新""" @@ -61,6 +63,10 @@ def update_order(self, order: OrderData) -> None: def update_trade(self, trade: TradeData) -> None: """成交数据更新""" + cost: float = self.traded_price * self.traded + trade.price * trade.volume + self.traded += trade.volume + self.traded_price = cost / self.traded + self.on_trade(trade) def update_timer(self) -> None: diff --git a/vnpy_algotrading/ui/display.py b/vnpy_algotrading/ui/display.py index d35db4a..d3b7452 100644 --- a/vnpy_algotrading/ui/display.py +++ b/vnpy_algotrading/ui/display.py @@ -8,6 +8,7 @@ "offset": "开平", "status": "算法状态", "traded": "成交数量", + "traded_price": "成交均价", "order_volume": "单笔委托", "timer_count": "本轮读秒", "total_count": "累计读秒", From fbb133417fcdb445b0b6b76e6c250656b0e64819 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 16 Nov 2022 14:31:28 +0800 Subject: [PATCH 36/45] =?UTF-8?q?[Mod]=20=E6=8A=8A=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=8B=86=E5=87=BA=E5=8D=95=E7=8B=AC=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 4 ++++ vnpy_algotrading/template.py | 5 +---- vnpy_algotrading/ui/widget.py | 41 ++++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 6974119..7897468 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -262,11 +262,15 @@ def write_log(self, msg: str, algo: AlgoTemplate = None) -> None: def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: """推送算法参数更新""" + params: list = ["vt_symbol", "direction", "offset", "price", "volume"] event: Event = Event(EVENT_ALGO_PARAMETERS) + event.data = { "algo_name": algo.algo_name, "parameters": parameters } + for i in params: + event.data[i] = getattr(algo, i) self.event_engine.put(event) def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index c2709cb..c499ec8 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -203,11 +203,8 @@ def write_log(self, msg: str) -> None: def put_parameters_event(self) -> None: """推送参数更新""" - keys: list = ["vt_symbol", "direction", "offset", "price", "volume"] - keys.extend(self.default_setting.keys()) - parameters: dict = {} - for name in keys: + for name in self.default_setting.keys(): parameters[name] = getattr(self, name) self.algo_engine.put_parameters_event(self, parameters) diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index bb66b81..1c11788 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -232,6 +232,11 @@ def init_ui(self) -> None: "", "", "算法", + "本地代码", + "方向", + "开平", + "价格", + "数量", "参数", "状态" ] @@ -244,7 +249,7 @@ def init_ui(self) -> None: QtWidgets.QHeaderView.ResizeToContents ) - for column in range(3, 5): + for column in range(8, 10): self.horizontalHeader().setSectionResizeMode( column, QtWidgets.QHeaderView.Stretch @@ -269,9 +274,21 @@ def process_parameters_event(self, event: Event) -> None: """""" data: Any = event.data algo_name: str = data["algo_name"] + vt_symbol: str = data["vt_symbol"] + direction: str = data["direction"].value + offset: str = data["offset"].value + price: str = str(data["price"]) + volume: str = str(data["volume"]) parameters: dict = data["parameters"] cells: dict = self.get_algo_cells(algo_name) + + cells["vt_symbol"].setText(vt_symbol) + cells["direction"].setText(direction) + cells["offset"].setText(offset) + cells["price"].setText(price) + cells["volume"].setText(volume) + text: str = to_text(parameters) cells["parameters"].setText(text) @@ -331,6 +348,14 @@ def get_algo_cells(self, algo_name: str) -> dict: switch_button.clicked.connect(switch_func) name_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(algo_name) + name_cell.setTextAlignment(QtCore.Qt.AlignCenter) + + vtsymbol_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + direction_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + offset_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + price_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + volume_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + parameters_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() variables_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() @@ -338,11 +363,21 @@ def get_algo_cells(self, algo_name: str) -> dict: self.setCellWidget(0, 0, stop_button) self.setCellWidget(0, 1, switch_button) self.setItem(0, 2, name_cell) - self.setItem(0, 3, parameters_cell) - self.setItem(0, 4, variables_cell) + self.setItem(0, 3, vtsymbol_cell) + self.setItem(0, 4, direction_cell) + self.setItem(0, 5, offset_cell) + self.setItem(0, 6, price_cell) + self.setItem(0, 7, volume_cell) + self.setItem(0, 8, parameters_cell) + self.setItem(0, 9, variables_cell) cells: dict = { "name": name_cell, + "vt_symbol": vtsymbol_cell, + "direction": direction_cell, + "offset": offset_cell, + "price": price_cell, + "volume": volume_cell, "parameters": parameters_cell, "variables": variables_cell, "button": switch_button # 缓存对应algo_name的button进字典便于更新按钮状态 From 0ff68e39b830af57a9c3bb0cc18109663576df09 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 16 Nov 2022 14:32:05 +0800 Subject: [PATCH 37/45] =?UTF-8?q?[Mod]=20=E5=B1=85=E4=B8=AD=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=9B=BA=E5=AE=9A=E5=8F=82=E6=95=B0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/ui/widget.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 1c11788..9928028 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -351,10 +351,15 @@ def get_algo_cells(self, algo_name: str) -> dict: name_cell.setTextAlignment(QtCore.Qt.AlignCenter) vtsymbol_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + vtsymbol_cell.setTextAlignment(QtCore.Qt.AlignCenter) direction_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + direction_cell.setTextAlignment(QtCore.Qt.AlignCenter) offset_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + offset_cell.setTextAlignment(QtCore.Qt.AlignCenter) price_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + price_cell.setTextAlignment(QtCore.Qt.AlignCenter) volume_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + volume_cell.setTextAlignment(QtCore.Qt.AlignCenter) parameters_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() variables_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() From e42727456d649b5e2df2efeeeb1a3bba757d8293 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 16 Nov 2022 16:39:57 +0800 Subject: [PATCH 38/45] =?UTF-8?q?[Mod]=20=E6=8A=8Astatus/traded/traded=5Fp?= =?UTF-8?q?rice=E6=8B=86=E5=87=BA=E5=8D=95=E7=8B=AC=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/engine.py | 9 +++++-- vnpy_algotrading/template.py | 4 --- vnpy_algotrading/ui/widget.py | 48 +++++++++++++++++++++++++---------- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 7897468..0d779ec 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -32,6 +32,10 @@ ) +algo_params: list = ["vt_symbol", "direction", "offset", "price", "volume"] +algo_variables: list = ["status", "traded", "traded_price"] + + class AlgoEngine(BaseEngine): """算法引擎""" @@ -262,14 +266,13 @@ def write_log(self, msg: str, algo: AlgoTemplate = None) -> None: def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: """推送算法参数更新""" - params: list = ["vt_symbol", "direction", "offset", "price", "volume"] event: Event = Event(EVENT_ALGO_PARAMETERS) event.data = { "algo_name": algo.algo_name, "parameters": parameters } - for i in params: + for i in algo_params: event.data[i] = getattr(algo, i) self.event_engine.put(event) @@ -289,4 +292,6 @@ def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: "algo_name": algo.algo_name, "variables": variables } + for i in algo_variables: + event.data[i] = getattr(algo, i) self.event_engine.put(event) diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index c499ec8..ee7b82d 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -43,10 +43,6 @@ def __init__( self.traded_price: float = 0 self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order - self.variables.insert(0, "status") - self.variables.insert(1, "traded") - self.variables.insert(2, "traded_price") - def update_tick(self, tick: TickData) -> None: """行情数据更新""" if self.status == AlgoStatus.RUNNING: diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 9928028..6051d95 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -237,8 +237,11 @@ def init_ui(self) -> None: "开平", "价格", "数量", + "算法状态", + "已成交", + "成交均价", "参数", - "状态" + "执行状态" ] self.setColumnCount(len(labels)) self.setHorizontalHeaderLabels(labels) @@ -249,7 +252,7 @@ def init_ui(self) -> None: QtWidgets.QHeaderView.ResizeToContents ) - for column in range(8, 10): + for column in range(11, 13): self.horizontalHeader().setSectionResizeMode( column, QtWidgets.QHeaderView.Stretch @@ -275,19 +278,19 @@ def process_parameters_event(self, event: Event) -> None: data: Any = event.data algo_name: str = data["algo_name"] vt_symbol: str = data["vt_symbol"] - direction: str = data["direction"].value - offset: str = data["offset"].value - price: str = str(data["price"]) - volume: str = str(data["volume"]) + direction: Direction = data["direction"] + offset: Offset = data["offset"] + price: float = data["price"] + volume: float = data["volume"] parameters: dict = data["parameters"] cells: dict = self.get_algo_cells(algo_name) cells["vt_symbol"].setText(vt_symbol) - cells["direction"].setText(direction) - cells["offset"].setText(offset) - cells["price"].setText(price) - cells["volume"].setText(volume) + cells["direction"].setText(direction.value) + cells["offset"].setText(offset.value) + cells["price"].setText(str(price)) + cells["volume"].setText(str(volume)) text: str = to_text(parameters) cells["parameters"].setText(text) @@ -296,15 +299,22 @@ def process_variables_event(self, event: Event) -> None: """""" data: Any = event.data algo_name: str = data["algo_name"] + traded: float = data["traded"] + traded_price: float = data["traded_price"] variables: dict = data["variables"] + status: AlgoStatus = data["status"] cells: dict = self.get_algo_cells(algo_name) + + cells["status"].setText(status.value) + cells["traded"].setText(str(traded)) + cells["traded_price"].setText(str(traded_price)) variables_cell: Optional[QtWidgets.QTableWidgetItem] = cells["variables"] text: str = to_text(variables) variables_cell.setText(text) row: int = self.row(variables_cell) - active: bool = variables["status"] not in [AlgoStatus.STOPPED, AlgoStatus.FINISHED] + active: bool = status not in [AlgoStatus.STOPPED, AlgoStatus.FINISHED] if self.mode_active: if active: @@ -360,6 +370,12 @@ def get_algo_cells(self, algo_name: str) -> dict: price_cell.setTextAlignment(QtCore.Qt.AlignCenter) volume_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() volume_cell.setTextAlignment(QtCore.Qt.AlignCenter) + status_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + status_cell.setTextAlignment(QtCore.Qt.AlignCenter) + traded_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + traded_cell.setTextAlignment(QtCore.Qt.AlignCenter) + tradedprice_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + tradedprice_cell.setTextAlignment(QtCore.Qt.AlignCenter) parameters_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() variables_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() @@ -373,8 +389,11 @@ def get_algo_cells(self, algo_name: str) -> dict: self.setItem(0, 5, offset_cell) self.setItem(0, 6, price_cell) self.setItem(0, 7, volume_cell) - self.setItem(0, 8, parameters_cell) - self.setItem(0, 9, variables_cell) + self.setItem(0, 8, status_cell) + self.setItem(0, 9, traded_cell) + self.setItem(0, 10, tradedprice_cell) + self.setItem(0, 11, parameters_cell) + self.setItem(0, 12, variables_cell) cells: dict = { "name": name_cell, @@ -383,6 +402,9 @@ def get_algo_cells(self, algo_name: str) -> dict: "offset": offset_cell, "price": price_cell, "volume": volume_cell, + "traded": traded_cell, + "traded_price": tradedprice_cell, + "status": status_cell, "parameters": parameters_cell, "variables": variables_cell, "button": switch_button # 缓存对应algo_name的button进字典便于更新按钮状态 From ecba146ff6e1778901f4f3308dbc969defa6871d Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 16 Nov 2022 17:17:10 +0800 Subject: [PATCH 39/45] =?UTF-8?q?[Mod]=20=E6=95=B4=E5=90=88=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=87=BD=E6=95=B0=E4=B8=BAput=5Fevent=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 9 ++-- vnpy_algotrading/algos/iceberg_algo.py | 11 ++--- vnpy_algotrading/algos/sniper_algo.py | 9 ++-- vnpy_algotrading/algos/stop_algo.py | 7 ++- vnpy_algotrading/algos/twap_algo.py | 7 ++- vnpy_algotrading/base.py | 4 +- vnpy_algotrading/engine.py | 33 ++----------- vnpy_algotrading/template.py | 60 +++++++++++++++-------- vnpy_algotrading/ui/widget.py | 40 ++++++--------- 9 files changed, 79 insertions(+), 101 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index 8db6212..af9531f 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -45,8 +45,7 @@ def __init__( self.vt_orderid: str = "" self.order_price: float = 0 - self.put_parameters_event() - self.put_variables_event() + self.put_event() # 检查最大/最小挂单量 if self.min_volume <= 0: @@ -72,7 +71,7 @@ def on_tick(self, tick: TickData) -> None: elif self.order_price != tick.ask_price_1: self.cancel_all() - self.put_variables_event() + self.put_event() def on_trade(self, trade: TradeData) -> None: """成交回调""" @@ -80,14 +79,14 @@ def on_trade(self, trade: TradeData) -> None: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() else: - self.put_variables_event() + self.put_event() def on_order(self, order: OrderData) -> None: """委托回调""" if not order.is_active(): self.vt_orderid = "" self.order_price = 0 - self.put_variables_event() + self.put_event() def buy_best_limit(self, bid_price_1: float) -> None: """最优限价买入""" diff --git a/vnpy_algotrading/algos/iceberg_algo.py b/vnpy_algotrading/algos/iceberg_algo.py index f3a9c60..aab54ae 100644 --- a/vnpy_algotrading/algos/iceberg_algo.py +++ b/vnpy_algotrading/algos/iceberg_algo.py @@ -42,8 +42,7 @@ def __init__( self.timer_count: int = 0 self.vt_orderid: str = "" - self.put_parameters_event() - self.put_variables_event() + self.put_event() def on_order(self, order: OrderData) -> None: """委托回调""" @@ -52,7 +51,7 @@ def on_order(self, order: OrderData) -> None: if not order.is_active(): self.vt_orderid = "" - self.put_variables_event() + self.put_event() def on_trade(self, trade: TradeData) -> None: """成交回调""" @@ -60,14 +59,14 @@ def on_trade(self, trade: TradeData) -> None: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() else: - self.put_variables_event() + self.put_event() def on_timer(self) -> None: """定时回调""" self.timer_count += 1 if self.timer_count < self.interval: - self.put_variables_event() + self.put_event() return self.timer_count = 0 @@ -106,4 +105,4 @@ def on_timer(self) -> None: self.vt_orderid = "" self.write_log(u"最新Tick买一价,高于卖出委托价格,之前委托可能丢失,强制撤单") - self.put_variables_event() + self.put_event() diff --git a/vnpy_algotrading/algos/sniper_algo.py b/vnpy_algotrading/algos/sniper_algo.py index 0b950ed..19ea052 100644 --- a/vnpy_algotrading/algos/sniper_algo.py +++ b/vnpy_algotrading/algos/sniper_algo.py @@ -31,8 +31,7 @@ def __init__( # 变量 self.vt_orderid = "" - self.put_parameters_event() - self.put_variables_event() + self.put_event() def on_tick(self, tick: TickData) -> None: """Tick行情回调""" @@ -61,13 +60,13 @@ def on_tick(self, tick: TickData) -> None: offset=self.offset ) - self.put_variables_event() + self.put_event() def on_order(self, order: OrderData) -> None: """委托回调""" if not order.is_active(): self.vt_orderid = "" - self.put_variables_event() + self.put_event() def on_trade(self, trade: TradeData) -> None: """成交回调""" @@ -75,4 +74,4 @@ def on_trade(self, trade: TradeData) -> None: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() else: - self.put_variables_event() + self.put_event() diff --git a/vnpy_algotrading/algos/stop_algo.py b/vnpy_algotrading/algos/stop_algo.py index c83bf43..e8c1245 100644 --- a/vnpy_algotrading/algos/stop_algo.py +++ b/vnpy_algotrading/algos/stop_algo.py @@ -40,8 +40,7 @@ def __init__( self.vt_orderid: str = "" self.order_status: str = "" - self.put_parameters_event() - self.put_variables_event() + self.put_event() def on_tick(self, tick: TickData) -> None: """Tick行情回调""" @@ -78,7 +77,7 @@ def on_tick(self, tick: TickData) -> None: self.write_log( f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.price},数量:{self.volume},开平:{self.offset}") - self.put_variables_event() + self.put_event() def on_order(self, order: OrderData) -> None: """委托回调""" @@ -86,4 +85,4 @@ def on_order(self, order: OrderData) -> None: if not order.is_active(): self.finish() - self.put_variables_event() + self.put_event() diff --git a/vnpy_algotrading/algos/twap_algo.py b/vnpy_algotrading/algos/twap_algo.py index 9215439..37a9303 100644 --- a/vnpy_algotrading/algos/twap_algo.py +++ b/vnpy_algotrading/algos/twap_algo.py @@ -49,8 +49,7 @@ def __init__( self.timer_count: int = 0 self.total_count: int = 0 - self.put_parameters_event() - self.put_variables_event() + self.put_event() def on_trade(self, trade: TradeData) -> None: """成交回调""" @@ -58,13 +57,13 @@ def on_trade(self, trade: TradeData) -> None: self.write_log(f"已交易数量:{self.traded},总数量:{self.volume}") self.finish() else: - self.put_variables_event() + self.put_event() def on_timer(self) -> None: """定时回调""" self.timer_count += 1 self.total_count += 1 - self.put_variables_event() + self.put_event() if self.total_count >= self.time: self.write_log("执行时间已结束,停止算法") diff --git a/vnpy_algotrading/base.py b/vnpy_algotrading/base.py index 68882f3..3220a30 100644 --- a/vnpy_algotrading/base.py +++ b/vnpy_algotrading/base.py @@ -2,8 +2,8 @@ EVENT_ALGO_LOG = "eAlgoLog" -EVENT_ALGO_VARIABLES = "eAlgoVariables" -EVENT_ALGO_PARAMETERS = "eAlgoParameters" +EVENT_ALGO_UPDATE = "eAlgoUpdate" + APP_NAME = "AlgoTrading" diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index 0d779ec..b81b457 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -25,17 +25,12 @@ from .template import AlgoTemplate from .base import ( EVENT_ALGO_LOG, - EVENT_ALGO_PARAMETERS, - EVENT_ALGO_VARIABLES, + EVENT_ALGO_UPDATE, APP_NAME, AlgoStatus ) -algo_params: list = ["vt_symbol", "direction", "offset", "price", "volume"] -algo_variables: list = ["status", "traded", "traded_price"] - - class AlgoEngine(BaseEngine): """算法引擎""" @@ -264,21 +259,8 @@ def write_log(self, msg: str, algo: AlgoTemplate = None) -> None: event: Event = Event(EVENT_ALGO_LOG, data=log) self.event_engine.put(event) - def put_parameters_event(self, algo: AlgoTemplate, parameters: dict) -> None: - """推送算法参数更新""" - event: Event = Event(EVENT_ALGO_PARAMETERS) - - event.data = { - "algo_name": algo.algo_name, - "parameters": parameters - } - for i in algo_params: - event.data[i] = getattr(algo, i) - self.event_engine.put(event) - - def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: - """推送算法状态更新""" - # 检查算法是否运行结束 + def put_algo_event(self, algo: AlgoTemplate, data: dict) -> None: + """推送更新""" if algo in self.algos.values() and algo.status in [AlgoStatus.STOPPED, AlgoStatus.FINISHED]: self.algos.pop(algo.algo_name) @@ -286,12 +268,5 @@ def put_variables_event(self, algo: AlgoTemplate, variables: dict) -> None: if algo in algos: algos.remove(algo) - # 推送事件 - event: Event = Event(EVENT_ALGO_VARIABLES) - event.data = { - "algo_name": algo.algo_name, - "variables": variables - } - for i in algo_variables: - event.data[i] = getattr(algo, i) + event: Event = Event(EVENT_ALGO_UPDATE, data) self.event_engine.put(event) diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index ee7b82d..f2809d4 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -93,7 +93,7 @@ def on_timer(self) -> None: def start(self) -> None: """启动""" self.status = AlgoStatus.RUNNING - self.put_variables_event() + self.put_event() self.write_log("算法启动") @@ -101,7 +101,7 @@ def stop(self) -> None: """停止""" self.status = AlgoStatus.STOPPED self.cancel_all() - self.put_variables_event() + self.put_event() self.write_log("算法停止") @@ -109,21 +109,21 @@ def finish(self) -> None: """结束""" self.status = AlgoStatus.FINISHED self.cancel_all() - self.put_variables_event() + self.put_event() self.write_log("算法结束") def pause(self) -> None: """暂停""" self.status = AlgoStatus.PAUSED - self.put_variables_event() + self.put_event() self.write_log("算法暂停") def resume(self) -> None: """恢复""" self.status = AlgoStatus.RUNNING - self.put_variables_event() + self.put_event() self.write_log("算法恢复") @@ -193,22 +193,42 @@ def get_contract(self) -> Optional[ContractData]: """查询合约""" return self.algo_engine.get_contract(self) - def write_log(self, msg: str) -> None: - """输出日志""" - self.algo_engine.write_log(msg, self) - - def put_parameters_event(self) -> None: - """推送参数更新""" - parameters: dict = {} + def get_parameters(self) -> dict: + """获取算法参数""" + strategy_parameters: dict = {} for name in self.default_setting.keys(): - parameters[name] = getattr(self, name) - - self.algo_engine.put_parameters_event(self, parameters) + strategy_parameters[name] = getattr(self, name) + return strategy_parameters - def put_variables_event(self) -> None: - """推送变量更新""" - variables: dict = {} + def get_variables(self) -> dict: + """获取算法变量""" + strategy_variables: dict = {} for name in self.variables: - variables[name] = getattr(self, name) + strategy_variables[name] = getattr(self, name) + return strategy_variables + + def get_data(self) -> dict: + """获取算法信息""" + algo_data: dict = { + "algo_name": self.algo_name, + "vt_symbol": self.vt_symbol, + "direction": self.direction, + "offset": self.offset, + "price": self.price, + "volume": self.volume, + "status": self.status, + "traded": self.traded, + "traded_price": self.traded_price, + "parameters": self.get_parameters(), + "variables": self.get_variables() + } + return algo_data + + def write_log(self, msg: str) -> None: + """输出日志""" + self.algo_engine.write_log(msg, self) - self.algo_engine.put_variables_event(self, variables) + def put_event(self) -> None: + """推送更新""" + data: dict = self.get_data() + self.algo_engine.put_algo_event(self, data) diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 6051d95..f3cc47e 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -12,8 +12,7 @@ AlgoTemplate, APP_NAME, EVENT_ALGO_LOG, - EVENT_ALGO_PARAMETERS, - EVENT_ALGO_VARIABLES, + EVENT_ALGO_UPDATE, AlgoStatus, Direction, Offset @@ -205,8 +204,7 @@ def start_algo(self) -> None: class AlgoMonitor(QtWidgets.QTableWidget): """算法监控组件""" - parameters_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) - variables_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) + algo_signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) def __init__( self, @@ -265,24 +263,26 @@ def init_ui(self) -> None: def register_event(self) -> None: """""" - self.parameters_signal.connect(self.process_parameters_event) - self.variables_signal.connect(self.process_variables_event) - - self.event_engine.register( - EVENT_ALGO_PARAMETERS, self.parameters_signal.emit) + self.algo_signal.connect(self.process_algo_event) self.event_engine.register( - EVENT_ALGO_VARIABLES, self.variables_signal.emit) + EVENT_ALGO_UPDATE, self.algo_signal.emit) - def process_parameters_event(self, event: Event) -> None: + def process_algo_event(self, event: Event) -> None: """""" data: Any = event.data + algo_name: str = data["algo_name"] vt_symbol: str = data["vt_symbol"] direction: Direction = data["direction"] offset: Offset = data["offset"] price: float = data["price"] volume: float = data["volume"] + traded: float = data["traded"] + traded_price: float = data["traded_price"] + status: AlgoStatus = data["status"] + parameters: dict = data["parameters"] + variables: dict = data["variables"] cells: dict = self.get_algo_cells(algo_name) @@ -291,24 +291,12 @@ def process_parameters_event(self, event: Event) -> None: cells["offset"].setText(offset.value) cells["price"].setText(str(price)) cells["volume"].setText(str(volume)) - - text: str = to_text(parameters) - cells["parameters"].setText(text) - - def process_variables_event(self, event: Event) -> None: - """""" - data: Any = event.data - algo_name: str = data["algo_name"] - traded: float = data["traded"] - traded_price: float = data["traded_price"] - variables: dict = data["variables"] - status: AlgoStatus = data["status"] - - cells: dict = self.get_algo_cells(algo_name) - cells["status"].setText(status.value) cells["traded"].setText(str(traded)) cells["traded_price"].setText(str(traded_price)) + + text: str = to_text(parameters) + cells["parameters"].setText(text) variables_cell: Optional[QtWidgets.QTableWidgetItem] = cells["variables"] text: str = to_text(variables) variables_cell.setText(text) From 62a9506e5b6a9bf3e4a4df4e7598cc686b867de9 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 16 Nov 2022 18:16:45 +0800 Subject: [PATCH 40/45] =?UTF-8?q?[Mod]=20=E7=AE=80=E5=8C=96get=5Falgo=5Fce?= =?UTF-8?q?lls=E5=92=8Cprocess=5Falgo=5Fevent=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/ui/widget.py | 65 +++++++++-------------------------- 1 file changed, 17 insertions(+), 48 deletions(-) diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index f3cc47e..dbcd67f 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -270,27 +270,21 @@ def register_event(self) -> None: def process_algo_event(self, event: Event) -> None: """""" data: Any = event.data - algo_name: str = data["algo_name"] vt_symbol: str = data["vt_symbol"] direction: Direction = data["direction"] offset: Offset = data["offset"] price: float = data["price"] volume: float = data["volume"] + + cells: dict = self.get_algo_cells(algo_name, vt_symbol, direction, offset, price, volume) + traded: float = data["traded"] traded_price: float = data["traded_price"] status: AlgoStatus = data["status"] - parameters: dict = data["parameters"] variables: dict = data["variables"] - cells: dict = self.get_algo_cells(algo_name) - - cells["vt_symbol"].setText(vt_symbol) - cells["direction"].setText(direction.value) - cells["offset"].setText(offset.value) - cells["price"].setText(str(price)) - cells["volume"].setText(str(volume)) cells["status"].setText(status.value) cells["traded"].setText(str(traded)) cells["traded_price"].setText(str(traded_price)) @@ -331,7 +325,7 @@ def switch(self, algo_name: str) -> None: self.algo_cells[algo_name]["button"] = button - def get_algo_cells(self, algo_name: str) -> dict: + def get_algo_cells(self, algo_name: str, vt_symbol: str, direction: Direction, offset: Offset, price: float, volume: float) -> dict: """""" cells: Optional[dict] = self.algo_cells.get(algo_name, None) @@ -345,58 +339,33 @@ def get_algo_cells(self, algo_name: str) -> dict: switch_button: QtWidgets.QPushButton = QtWidgets.QPushButton("暂停") switch_button.clicked.connect(switch_func) - name_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(algo_name) - name_cell.setTextAlignment(QtCore.Qt.AlignCenter) - - vtsymbol_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - vtsymbol_cell.setTextAlignment(QtCore.Qt.AlignCenter) - direction_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - direction_cell.setTextAlignment(QtCore.Qt.AlignCenter) - offset_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - offset_cell.setTextAlignment(QtCore.Qt.AlignCenter) - price_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - price_cell.setTextAlignment(QtCore.Qt.AlignCenter) - volume_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - volume_cell.setTextAlignment(QtCore.Qt.AlignCenter) - status_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - status_cell.setTextAlignment(QtCore.Qt.AlignCenter) - traded_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - traded_cell.setTextAlignment(QtCore.Qt.AlignCenter) - tradedprice_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() - tradedprice_cell.setTextAlignment(QtCore.Qt.AlignCenter) - parameters_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() variables_cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() self.insertRow(0) self.setCellWidget(0, 0, stop_button) self.setCellWidget(0, 1, switch_button) - self.setItem(0, 2, name_cell) - self.setItem(0, 3, vtsymbol_cell) - self.setItem(0, 4, direction_cell) - self.setItem(0, 5, offset_cell) - self.setItem(0, 6, price_cell) - self.setItem(0, 7, volume_cell) - self.setItem(0, 8, status_cell) - self.setItem(0, 9, traded_cell) - self.setItem(0, 10, tradedprice_cell) self.setItem(0, 11, parameters_cell) self.setItem(0, 12, variables_cell) cells: dict = { - "name": name_cell, - "vt_symbol": vtsymbol_cell, - "direction": direction_cell, - "offset": offset_cell, - "price": price_cell, - "volume": volume_cell, - "traded": traded_cell, - "traded_price": tradedprice_cell, - "status": status_cell, "parameters": parameters_cell, "variables": variables_cell, "button": switch_button # 缓存对应algo_name的button进字典便于更新按钮状态 } + + items: list = [(2, "name", algo_name), (3, "vt_symbol", vt_symbol), (4, "direction", direction.value), (5, "offset", offset.value), + (6, "price", str(price)), (7, "volume", str(volume)), (8, "status", ""), (9, "traded", ""), (10, "traded_price", "")] + + for column, name, content in items: + if content: + cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(content) + else: + cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + cell.setTextAlignment(QtCore.Qt.AlignCenter) + self.setItem(0, column, cell) + cells[name] = cell + self.algo_cells[algo_name] = cells return cells From 3907138e7b803754c6ce5fc5214bc5676f173d8d Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 16 Nov 2022 18:17:03 +0800 Subject: [PATCH 41/45] =?UTF-8?q?[Del]=20=E5=88=A0=E9=99=A4=E7=94=A8?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/ui/display.py | 1 - 1 file changed, 1 deletion(-) diff --git a/vnpy_algotrading/ui/display.py b/vnpy_algotrading/ui/display.py index d3b7452..306b7f6 100644 --- a/vnpy_algotrading/ui/display.py +++ b/vnpy_algotrading/ui/display.py @@ -14,7 +14,6 @@ "total_count": "累计读秒", "template_name": "算法模板", "display_volume": "挂出数量", - "stop_price": "触发价格", "price_add": "委托超价", "step_price": "网格交易间距", "step_volume": "网格交易数量", From 19fa95c5b30c226c5b19206dd2bfbca803c95de4 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Tue, 22 Nov 2022 17:16:40 +0800 Subject: [PATCH 42/45] =?UTF-8?q?[Mod]=20=E5=8F=98=E9=87=8F=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/template.py | 3 ++- vnpy_algotrading/ui/display.py | 5 +++-- vnpy_algotrading/ui/widget.py | 23 +++++++++++++---------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index f2809d4..4b4bab4 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -217,8 +217,9 @@ def get_data(self) -> dict: "price": self.price, "volume": self.volume, "status": self.status, - "traded": self.traded, "traded_price": self.traded_price, + "traded": self.traded, + "nottraded": self.volume - self.traded, "parameters": self.get_parameters(), "variables": self.get_variables() } diff --git a/vnpy_algotrading/ui/display.py b/vnpy_algotrading/ui/display.py index 306b7f6..c0e5462 100644 --- a/vnpy_algotrading/ui/display.py +++ b/vnpy_algotrading/ui/display.py @@ -2,13 +2,14 @@ "vt_symbol": "本地代码", "direction": "方向", "price": "价格", - "volume": "数量", + "volume": "委托数量", "time": "执行时间(秒)", "interval": "每轮间隔(秒)", "offset": "开平", "status": "算法状态", - "traded": "成交数量", "traded_price": "成交均价", + "traded": "成交数量", + "nottraded": "剩余数量", "order_volume": "单笔委托", "timer_count": "本轮读秒", "total_count": "累计读秒", diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index dbcd67f..8e65a67 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -234,12 +234,13 @@ def init_ui(self) -> None: "方向", "开平", "价格", - "数量", + "委托数量", "算法状态", - "已成交", "成交均价", + "成交数量", + "剩余数量", "参数", - "执行状态" + "变量" ] self.setColumnCount(len(labels)) self.setHorizontalHeaderLabels(labels) @@ -250,7 +251,7 @@ def init_ui(self) -> None: QtWidgets.QHeaderView.ResizeToContents ) - for column in range(11, 13): + for column in range(12, 14): self.horizontalHeader().setSectionResizeMode( column, QtWidgets.QHeaderView.Stretch @@ -279,15 +280,17 @@ def process_algo_event(self, event: Event) -> None: cells: dict = self.get_algo_cells(algo_name, vt_symbol, direction, offset, price, volume) - traded: float = data["traded"] traded_price: float = data["traded_price"] + traded: float = data["traded"] + nottraded: float = data["nottraded"] status: AlgoStatus = data["status"] parameters: dict = data["parameters"] variables: dict = data["variables"] cells["status"].setText(status.value) - cells["traded"].setText(str(traded)) cells["traded_price"].setText(str(traded_price)) + cells["traded"].setText(str(traded)) + cells["nottraded"].setText(str(nottraded)) text: str = to_text(parameters) cells["parameters"].setText(text) @@ -345,8 +348,8 @@ def get_algo_cells(self, algo_name: str, vt_symbol: str, direction: Direction, o self.insertRow(0) self.setCellWidget(0, 0, stop_button) self.setCellWidget(0, 1, switch_button) - self.setItem(0, 11, parameters_cell) - self.setItem(0, 12, variables_cell) + self.setItem(0, 12, parameters_cell) + self.setItem(0, 13, variables_cell) cells: dict = { "parameters": parameters_cell, @@ -354,8 +357,8 @@ def get_algo_cells(self, algo_name: str, vt_symbol: str, direction: Direction, o "button": switch_button # 缓存对应algo_name的button进字典便于更新按钮状态 } - items: list = [(2, "name", algo_name), (3, "vt_symbol", vt_symbol), (4, "direction", direction.value), (5, "offset", offset.value), - (6, "price", str(price)), (7, "volume", str(volume)), (8, "status", ""), (9, "traded", ""), (10, "traded_price", "")] + items: list = [(2, "name", algo_name), (3, "vt_symbol", vt_symbol), (4, "direction", direction.value), (5, "offset", offset.value), (6, "price", str(price)), + (7, "volume", str(volume)), (8, "status", ""), (9, "traded_price", ""), (10, "traded", ""), (11, "nottraded", "")] for column, name, content in items: if content: From 10a09dfb2353227a529827b34cbfb35e47ce31c8 Mon Sep 17 00:00:00 2001 From: noranhe <63988546+noranhe@users.noreply.github.com> Date: Wed, 23 Nov 2022 09:40:26 +0800 Subject: [PATCH 43/45] =?UTF-8?q?[Mod]=20=E4=BF=AE=E6=94=B9=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=8F=98=E9=87=8F=E6=98=BE=E7=A4=BA=E7=9A=84=E9=97=B4?= =?UTF-8?q?=E9=9A=94=E7=AC=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/ui/widget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 8e65a67..08773ea 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -544,5 +544,5 @@ def to_text(data: dict) -> str: for key, value in data.items(): key: str = NAME_DISPLAY_MAP.get(key, key) buf.append(f"{key}:{value}") - text: str = ",".join(buf) + text: str = ";".join(buf) return text From 1be99be38780ce293cbceb4ec4d272982bc9d943 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Fri, 25 Nov 2022 17:46:55 +0800 Subject: [PATCH 44/45] =?UTF-8?q?[Mod]=20=E4=BC=98=E5=8C=96=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=86=E8=8A=82=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vnpy_algotrading/algos/best_limit_algo.py | 1 - vnpy_algotrading/engine.py | 18 ++- vnpy_algotrading/template.py | 14 +- vnpy_algotrading/ui/display.py | 4 +- vnpy_algotrading/ui/widget.py | 157 ++++++++++++---------- 5 files changed, 106 insertions(+), 88 deletions(-) diff --git a/vnpy_algotrading/algos/best_limit_algo.py b/vnpy_algotrading/algos/best_limit_algo.py index af9531f..d72b59f 100644 --- a/vnpy_algotrading/algos/best_limit_algo.py +++ b/vnpy_algotrading/algos/best_limit_algo.py @@ -3,7 +3,6 @@ from vnpy.trader.constant import Direction from vnpy.trader.object import TradeData, OrderData, TickData from vnpy.trader.engine import BaseEngine -from vnpy.trader.utility import round_to from ..template import AlgoTemplate diff --git a/vnpy_algotrading/engine.py b/vnpy_algotrading/engine.py index b81b457..db735d2 100644 --- a/vnpy_algotrading/engine.py +++ b/vnpy_algotrading/engine.py @@ -1,5 +1,5 @@ from collections import defaultdict -from typing import Dict, List, Optional, Set +from typing import Dict, List, Optional, Set, Type from vnpy.event import EventEngine, Event from vnpy.trader.engine import BaseEngine, MainEngine @@ -38,11 +38,11 @@ def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None: """构造函数""" super().__init__(main_engine, event_engine, APP_NAME) + self.algo_templates: Dict[str, Type[AlgoTemplate]] = {} + self.algos: Dict[str, AlgoTemplate] = {} self.symbol_algo_map: Dict[str, Set[AlgoTemplate]] = defaultdict(set) - self.orderid_algo_map: dict = {} - - self.algo_templates: dict = {} + self.orderid_algo_map: Dict[str, AlgoTemplate] = {} self.load_algo_template() self.register_event() @@ -53,7 +53,7 @@ def init_engine(self) -> None: def close(self) -> None: """关闭引擎""" - pass + self.stop_all() def load_algo_template(self) -> None: """载入算法类""" @@ -118,6 +118,7 @@ def process_order_event(self, event: Event) -> None: def start_algo( self, + template_name: str, vt_symbol: str, direction: Direction, offset: Offset, @@ -131,7 +132,6 @@ def start_algo( self.write_log(f'算法启动失败,找不到合约:{vt_symbol}') return "" - template_name: str = setting["template_name"] algo_template: AlgoTemplate = self.algo_templates[template_name] # 创建算法实例 @@ -261,7 +261,11 @@ def write_log(self, msg: str, algo: AlgoTemplate = None) -> None: def put_algo_event(self, algo: AlgoTemplate, data: dict) -> None: """推送更新""" - if algo in self.algos.values() and algo.status in [AlgoStatus.STOPPED, AlgoStatus.FINISHED]: + # 移除运行结束的算法实例 + if ( + algo in self.algos.values() + and algo.status in [AlgoStatus.STOPPED, AlgoStatus.FINISHED] + ): self.algos.pop(algo.algo_name) for algos in self.symbol_algo_map.values(): diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 4b4bab4..430a687 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -1,4 +1,4 @@ -from typing import Dict, Optional +from typing import Dict, Optional, TYPE_CHECKING from vnpy.trader.engine import BaseEngine from vnpy.trader.object import TickData, OrderData, TradeData, ContractData @@ -7,6 +7,9 @@ from .base import AlgoStatus +if TYPE_CHECKING: + from .engine import AlgoEngine + class AlgoTemplate: """算法模板""" @@ -19,7 +22,7 @@ class AlgoTemplate: def __init__( self, - algo_engine: BaseEngine, + algo_engine: "AlgoEngine", algo_name: str, vt_symbol: str, direction: Direction, @@ -38,9 +41,10 @@ def __init__( self.price: float = price self.volume: int = volume - self.status: str = AlgoStatus.PAUSED + self.status: AlgoStatus = AlgoStatus.PAUSED self.traded: float = 0 self.traded_price: float = 0 + self.active_orders: Dict[str, OrderData] = {} # vt_orderid:order def update_tick(self, tick: TickData) -> None: @@ -217,9 +221,9 @@ def get_data(self) -> dict: "price": self.price, "volume": self.volume, "status": self.status, - "traded_price": self.traded_price, "traded": self.traded, - "nottraded": self.volume - self.traded, + "left": self.volume - self.traded, + "traded_price": self.traded_price, "parameters": self.get_parameters(), "variables": self.get_variables() } diff --git a/vnpy_algotrading/ui/display.py b/vnpy_algotrading/ui/display.py index c0e5462..de36bea 100644 --- a/vnpy_algotrading/ui/display.py +++ b/vnpy_algotrading/ui/display.py @@ -9,7 +9,7 @@ "status": "算法状态", "traded_price": "成交均价", "traded": "成交数量", - "nottraded": "剩余数量", + "left": "剩余数量", "order_volume": "单笔委托", "timer_count": "本轮读秒", "total_count": "累计读秒", @@ -24,10 +24,8 @@ "spread_up": "价差上限", "spread_down": "价差下限", "max_pos": "最大持仓", - "start_time": "开始时间", "end_time": "结束时间", - "min_volume": "最小委托量", "max_volume": "最大委托量", "volume_change": "委托量变化" diff --git a/vnpy_algotrading/ui/widget.py b/vnpy_algotrading/ui/widget.py index 08773ea..760824c 100644 --- a/vnpy_algotrading/ui/widget.py +++ b/vnpy_algotrading/ui/widget.py @@ -1,7 +1,7 @@ import csv from functools import partial from datetime import datetime -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, List, Tuple from vnpy.event import EventEngine, Event from vnpy.trader.engine import MainEngine, LogData @@ -52,7 +52,7 @@ def __init__( } self.default_setting.update(algo_template.default_setting) - self.widgets: dict = {} + self.widgets: Dict[str, QtWidgets.QWidget] = {} self.init_ui() @@ -84,10 +84,6 @@ def init_ui(self) -> None: load_csv_button.clicked.connect(self.load_csv) form.addRow(load_csv_button) - form.addRow(QtWidgets.QLabel("")) - form.addRow(QtWidgets.QLabel("")) - form.addRow(QtWidgets.QLabel("")) - for button in [ start_algo_button, load_csv_button @@ -128,9 +124,7 @@ def load_csv(self) -> None: for d in reader: # 用模版名初始化算法配置 - setting: dict = { - "template_name": self.template_name - } + setting: dict = {} # 读取csv文件每行中各个字段内容 for field_name, tp in self.widgets.items(): @@ -157,16 +151,19 @@ def load_csv(self) -> None: # 当没有错误发生时启动算法 for setting in settings: - vt_symbol: str = setting.pop("vt_symbol") - direction: Direction = Direction(setting.pop("direction")) - offset: Offset = Offset(setting.pop("offset")) - price: float = setting.pop("price") - volume: float = setting.pop("volume") - self.algo_engine.start_algo(vt_symbol, direction, offset, price, volume, setting) + self.algo_engine.start_algo( + template_name=self.template_name, + vt_symbol=setting.pop("vt_symbol"), + direction=Direction(setting.pop("direction")), + offset=Offset(setting.pop("offset")), + price=setting.pop("price"), + volume=setting.pop("volume"), + setting=setting + ) def get_setting(self) -> dict: """获取当前配置""" - setting: dict = {"template_name": self.template_name} + setting: dict = {} for field_name, tp in self.widgets.items(): widget, field_type = tp @@ -191,14 +188,18 @@ def get_setting(self) -> dict: def start_algo(self) -> None: """启动交易算法""" setting: dict = self.get_setting() + if not setting: + return - if setting: - vt_symbol: str = setting.pop("vt_symbol") - direction: Direction = Direction(setting.pop("direction")) - offset: Offset = Offset(setting.pop("offset")) - price: float = setting.pop("price") - volume: int = setting.pop("volume") - self.algo_engine.start_algo(vt_symbol, direction, offset, price, volume, setting) + self.algo_engine.start_algo( + template_name=self.template_name, + vt_symbol=setting.pop("vt_symbol"), + direction=Direction(setting.pop("direction")), + offset=Offset(setting.pop("offset")), + price=setting.pop("price"), + volume=setting.pop("volume"), + setting=setting + ) class AlgoMonitor(QtWidgets.QTableWidget): @@ -212,7 +213,7 @@ def __init__( event_engine: EventEngine, mode_active: bool ): - """""" + """构造函数""" super().__init__() self.algo_engine: AlgoEngine = algo_engine @@ -225,7 +226,7 @@ def __init__( self.register_event() def init_ui(self) -> None: - """""" + """初始化界面""" labels: list = [ "", "", @@ -234,11 +235,11 @@ def init_ui(self) -> None: "方向", "开平", "价格", - "委托数量", - "算法状态", + "总数量", + "成交量", + "剩余量", "成交均价", - "成交数量", - "剩余数量", + "状态", "参数", "变量" ] @@ -263,14 +264,15 @@ def init_ui(self) -> None: self.hideColumn(1) def register_event(self) -> None: - """""" + """注册事件监听""" self.algo_signal.connect(self.process_algo_event) - self.event_engine.register( - EVENT_ALGO_UPDATE, self.algo_signal.emit) + self.event_engine.register(EVENT_ALGO_UPDATE, self.algo_signal.emit) def process_algo_event(self, event: Event) -> None: - """""" - data: Any = event.data + """处理算法更新事件""" + data: dict = event.data + + # 读取算法的标准参数,并获取内容单元格字典 algo_name: str = data["algo_name"] vt_symbol: str = data["vt_symbol"] direction: Direction = data["direction"] @@ -280,25 +282,26 @@ def process_algo_event(self, event: Event) -> None: cells: dict = self.get_algo_cells(algo_name, vt_symbol, direction, offset, price, volume) + # 读取算法的标准变量,并更新到内容单元格 traded_price: float = data["traded_price"] traded: float = data["traded"] - nottraded: float = data["nottraded"] + left: float = data["left"] status: AlgoStatus = data["status"] - parameters: dict = data["parameters"] - variables: dict = data["variables"] cells["status"].setText(status.value) cells["traded_price"].setText(str(traded_price)) cells["traded"].setText(str(traded)) - cells["nottraded"].setText(str(nottraded)) + cells["left"].setText(str(left)) - text: str = to_text(parameters) - cells["parameters"].setText(text) - variables_cell: Optional[QtWidgets.QTableWidgetItem] = cells["variables"] - text: str = to_text(variables) - variables_cell.setText(text) + # 读取算法的自定义参数和变量,并显示到单元格 + parameters: dict = data["parameters"] + cells["parameters"].setText(to_text(parameters)) - row: int = self.row(variables_cell) + variables: dict = data["variables"] + cells["variables"].setText(to_text(variables)) + + # 基于显示模式决定是否隐藏 + row: int = self.row(cells["variables"]) active: bool = status not in [AlgoStatus.STOPPED, AlgoStatus.FINISHED] if self.mode_active: @@ -313,23 +316,32 @@ def process_algo_event(self, event: Event) -> None: self.showRow(row) def stop_algo(self, algo_name: str) -> None: - """""" + """停止算法""" self.algo_engine.stop_algo(algo_name) def switch(self, algo_name: str) -> None: - """""" + """算法开关调整""" button: QtWidgets.QPushButton = self.algo_cells[algo_name]["button"] + if button.text() == "暂停": self.algo_engine.pause_algo(algo_name) - button.setText("启动") + button.setText("恢复") else: self.algo_engine.resume_algo(algo_name) button.setText("暂停") self.algo_cells[algo_name]["button"] = button - def get_algo_cells(self, algo_name: str, vt_symbol: str, direction: Direction, offset: Offset, price: float, volume: float) -> dict: - """""" + def get_algo_cells( + self, + algo_name: str, + vt_symbol: str, + direction: Direction, + offset: Offset, + price: float, + volume: float + ) -> Dict[str, QtWidgets.QTableWidgetItem]: + """获取算法对应的单元格字典""" cells: Optional[dict] = self.algo_cells.get(algo_name, None) if not cells: @@ -351,21 +363,29 @@ def get_algo_cells(self, algo_name: str, vt_symbol: str, direction: Direction, o self.setItem(0, 12, parameters_cell) self.setItem(0, 13, variables_cell) - cells: dict = { + cells: Dict[str, QtWidgets.QTableWidgetItem] = { "parameters": parameters_cell, "variables": variables_cell, "button": switch_button # 缓存对应algo_name的button进字典便于更新按钮状态 } - items: list = [(2, "name", algo_name), (3, "vt_symbol", vt_symbol), (4, "direction", direction.value), (5, "offset", offset.value), (6, "price", str(price)), - (7, "volume", str(volume)), (8, "status", ""), (9, "traded_price", ""), (10, "traded", ""), (11, "nottraded", "")] + items: List[Tuple[int, str, str]] = [ + (2, "name", algo_name), + (3, "vt_symbol", vt_symbol), + (4, "direction", direction.value), + (5, "offset", offset.value), + (6, "price", str(price)), + (7, "volume", str(volume)), + (8, "traded", ""), + (9, "left", ""), + (10, "traded_price", ""), + (11, "status", ""), + ] for column, name, content in items: - if content: - cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(content) - else: - cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem() + cell: QtWidgets.QTableWidgetItem = QtWidgets.QTableWidgetItem(content) cell.setTextAlignment(QtCore.Qt.AlignCenter) + self.setItem(0, column, cell) cells[name] = cell @@ -396,7 +416,7 @@ class LogMonitor(QtWidgets.QTableWidget): signal: QtCore.pyqtSignal = QtCore.pyqtSignal(Event) def __init__(self, event_engine: EventEngine) -> None: - """""" + """构造函数""" super().__init__() self.event_engine: EventEngine = event_engine @@ -405,34 +425,27 @@ def __init__(self, event_engine: EventEngine) -> None: self.register_event() def init_ui(self) -> None: - """""" + """初始化界面""" labels: list = [ "时间", "信息" ] self.setColumnCount(len(labels)) self.setHorizontalHeaderLabels(labels) - self.verticalHeader().setVisible(False) self.setEditTriggers(self.NoEditTriggers) - - self.verticalHeader().setSectionResizeMode( - QtWidgets.QHeaderView.ResizeToContents - ) - - self.horizontalHeader().setSectionResizeMode( - 1, - QtWidgets.QHeaderView.Stretch - ) + self.verticalHeader().setVisible(False) + self.verticalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) + self.horizontalHeader().setSectionResizeMode(1, QtWidgets.QHeaderView.Stretch) self.setWordWrap(True) def register_event(self) -> None: - """""" + """注册事件监听""" self.signal.connect(self.process_log_event) self.event_engine.register(EVENT_ALGO_LOG, self.signal.emit) def process_log_event(self, event: Event) -> None: - """""" + """处理日志事件""" log: LogData = event.data msg: str = log.msg timestamp: str = datetime.now().strftime("%H:%M:%S") @@ -543,6 +556,6 @@ def to_text(data: dict) -> str: buf: list = [] for key, value in data.items(): key: str = NAME_DISPLAY_MAP.get(key, key) - buf.append(f"{key}:{value}") - text: str = ";".join(buf) + buf.append(f"{key}:{value}") + text: str = ";".join(buf) return text From 6577f2d7079cc2e950b6a118e59c440d18040109 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Sun, 4 Dec 2022 13:31:25 +0800 Subject: [PATCH 45/45] =?UTF-8?q?[Mod]=20=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E5=88=B01.0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ README.md | 2 +- setup.cfg | 2 +- vnpy_algotrading/template.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e19d998..f8e241a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# 1.0.3版本 + +1. 调整模块设计(模板、引擎),只支持单合约算法执行交易 +2. 调整算法模板,增加默认参数和变量字段,以及对应函数传参 +3. 优化算法状态控制,增加状态枚举值,算法支持暂停和恢复运行 +4. 移除DMA算法 +5. 移除算法配置缓存和加载功能 +6. 调整图形界面,优化算法状态信息显示 + # 1.0.2版本 1. 将模块的图标文件信息,改为完整路径字符串 diff --git a/README.md b/README.md index 3abdfca..323e290 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

- + diff --git a/setup.cfg b/setup.cfg index 4b7eca4..6a335ab 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = vnpy_algotrading -version = 1.0.2 +version = 1.0.3 url = https://www.vnpy.com license = MIT author = Xiaoyou Chen diff --git a/vnpy_algotrading/template.py b/vnpy_algotrading/template.py index 430a687..1497096 100644 --- a/vnpy_algotrading/template.py +++ b/vnpy_algotrading/template.py @@ -14,7 +14,7 @@ class AlgoTemplate: """算法模板""" - _count: int = 0 # 算法实例的计数 + _count: int = 0 # 实例计数 display_name: str = "" # 显示名称 default_setting: dict = {} # 默认参数