From 0e67e75d6c77957425f86d623ac085882910636b Mon Sep 17 00:00:00 2001 From: nanoric Date: Mon, 8 Apr 2019 04:56:42 -0400 Subject: [PATCH 1/2] [Add] virtual decorator --- vnpy/app/algo_trading/template.py | 6 ++++++ vnpy/app/cta_strategy/template.py | 14 ++++++++++++++ vnpy/trader/utility.py | 11 +++++++++++ 3 files changed, 31 insertions(+) diff --git a/vnpy/app/algo_trading/template.py b/vnpy/app/algo_trading/template.py index 609641af..3b6620b7 100644 --- a/vnpy/app/algo_trading/template.py +++ b/vnpy/app/algo_trading/template.py @@ -1,6 +1,7 @@ from vnpy.trader.engine import BaseEngine from vnpy.trader.object import TickData, OrderData, TradeData from vnpy.trader.constant import OrderType, Offset, Direction +from vnpy.trader.utility import virtual class AlgoTemplate: @@ -63,22 +64,27 @@ class AlgoTemplate: """""" pass + @virtual def on_stop(self): """""" pass + @virtual def on_tick(self, tick: TickData): """""" pass + @virtual def on_order(self, order: OrderData): """""" pass + @virtual def on_trade(self, trade: TradeData): """""" pass + @virtual def on_timer(self): """""" pass diff --git a/vnpy/app/cta_strategy/template.py b/vnpy/app/cta_strategy/template.py index 20cf88d2..0fde32c0 100644 --- a/vnpy/app/cta_strategy/template.py +++ b/vnpy/app/cta_strategy/template.py @@ -4,6 +4,7 @@ from typing import Any, Callable from vnpy.trader.constant import Interval, Direction, Offset from vnpy.trader.object import BarData, TickData, OrderData, TradeData +from vnpy.trader.utility import virtual from .base import StopOrder, EngineType @@ -87,48 +88,56 @@ class CtaTemplate(ABC): } return strategy_data + @virtual def on_init(self): """ Callback when strategy is inited. """ pass + @virtual def on_start(self): """ Callback when strategy is started. """ pass + @virtual def on_stop(self): """ Callback when strategy is stopped. """ pass + @virtual def on_tick(self, tick: TickData): """ Callback of new tick data update. """ pass + @virtual def on_bar(self, bar: BarData): """ Callback of new bar data update. """ pass + @virtual def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ pass + @virtual def on_order(self, order: OrderData): """ Callback of new order data update. """ pass + @virtual def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. @@ -255,12 +264,14 @@ class CtaSignal(ABC): """""" self.signal_pos = 0 + @virtual def on_tick(self, tick: TickData): """ Callback of new tick data update. """ pass + @virtual def on_bar(self, bar: BarData): """ Callback of new bar data update. @@ -292,6 +303,7 @@ class TargetPosTemplate(CtaTemplate): ) self.variables.append("target_pos") + @virtual def on_tick(self, tick: TickData): """ Callback of new tick data update. @@ -301,12 +313,14 @@ class TargetPosTemplate(CtaTemplate): if self.trading: self.trade() + @virtual def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.last_bar = bar + @virtual def on_order(self, order: OrderData): """ Callback of new order data update. diff --git a/vnpy/trader/utility.py b/vnpy/trader/utility.py index ca788227..9951e1f1 100644 --- a/vnpy/trader/utility.py +++ b/vnpy/trader/utility.py @@ -385,3 +385,14 @@ class ArrayManager(object): if array: return up, down return up[-1], down[-1] + + +def virtual(func: "callable"): + """ + mark a function as "virtual", which means that this function can be override. + any base class should use this or @abstractmethod to decorate all functions + that can be (re)implemented by subclasses. + """ + return func + + From 0260aa078403932a054b3a795771d4ff9ac0c842 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 8 Apr 2019 18:32:59 +0800 Subject: [PATCH 2/2] [Fix]convert str to float for price and volume data --- vnpy/gateway/okex/okex_gateway.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/vnpy/gateway/okex/okex_gateway.py b/vnpy/gateway/okex/okex_gateway.py index cc1e124c..4a1b2a93 100644 --- a/vnpy/gateway/okex/okex_gateway.py +++ b/vnpy/gateway/okex/okex_gateway.py @@ -298,7 +298,7 @@ class OkexRestApi(RestClient): name=symbol, product=Product.SPOT, size=1, - pricetick=instrument_data["tick_size"], + pricetick=float(instrument_data["tick_size"]), gateway_name=self.gateway_name ) self.gateway.on_contract(contract) @@ -336,6 +336,7 @@ class OkexRestApi(RestClient): direction=DIRECTION_OKEX2VT[order_data["side"]], price=float(order_data["price"]), volume=float(order_data["size"]), + traded=float(order_data["filled_size"]), time=order_data["timestamp"][11:19], status=STATUS_OKEX2VT[order_data["status"]], gateway_name=self.gateway_name, @@ -605,11 +606,11 @@ class OkexWebsocketApi(WebsocketClient): if not tick: return - tick.last_price = d["last"] - tick.open = d["open_24h"] - tick.high = d["high_24h"] - tick.low = d["low_24h"] - tick.volume = d["base_volume_24h"] + tick.last_price = float(d["last"]) + tick.open = float(d["open_24h"]) + tick.high = float(d["high_24h"]) + tick.low = float(d["low_24h"]) + tick.volume = float(d["base_volume_24h"]) tick.datetime = datetime.strptime( d["timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ") self.gateway.on_tick(copy(tick)) @@ -626,13 +627,13 @@ class OkexWebsocketApi(WebsocketClient): asks = d["asks"] for n, buf in enumerate(bids): price, volume, _ = buf - tick.__setattr__("bid_price_%s" % (n + 1), price) - tick.__setattr__("bid_volume_%s" % (n + 1), volume) + tick.__setattr__("bid_price_%s" % (n + 1), float(price)) + tick.__setattr__("bid_volume_%s" % (n + 1), float(volume)) for n, buf in enumerate(asks): price, volume, _ = buf - tick.__setattr__("ask_price_%s" % (n + 1), price) - tick.__setattr__("ask_volume_%s" % (n + 1), volume) + tick.__setattr__("ask_price_%s" % (n + 1), float(price)) + tick.__setattr__("ask_volume_%s" % (n + 1), float(volume)) tick.datetime = datetime.strptime( d["timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ") @@ -646,16 +647,16 @@ class OkexWebsocketApi(WebsocketClient): type=ORDERTYPE_OKEX2VT[d["type"]], orderid=d["client_oid"], direction=DIRECTION_OKEX2VT[d["side"]], - price=d["price"], - volume=d["size"], - traded=d["filled_size"], + price=float(d["price"]), + volume=float(d["size"]), + traded=float(d["filled_size"]), time=d["timestamp"][11:19], status=STATUS_OKEX2VT[d["status"]], gateway_name=self.gateway_name, ) self.gateway.on_order(copy(order)) - trade_volume = float(d.get("last_fill_qty", 0)) + trade_volume = d.get("last_fill_qty", 0) if not trade_volume: return