From 0836a5a7f8d3b20692cbcb336e7008c2dcb780ed Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Mon, 29 Apr 2019 23:18:27 +0800 Subject: [PATCH 1/4] [Add]supported exchanges for each gateway --- vnpy/gateway/bitfinex/bitfinex_gateway.py | 2 ++ vnpy/gateway/bitmex/bitmex_gateway.py | 2 ++ vnpy/gateway/ctp/ctp_gateway.py | 2 ++ vnpy/gateway/femas/femas_gateway.py | 8 ++------ vnpy/gateway/futu/futu_gateway.py | 2 ++ vnpy/gateway/huobi/huobi_gateway.py | 2 ++ vnpy/gateway/ib/ib_gateway.py | 2 ++ vnpy/gateway/oes/oes_gateway.py | 13 +++++++++---- vnpy/gateway/okex/okex_gateway.py | 2 ++ vnpy/gateway/okexf/okexf_gateway.py | 2 ++ vnpy/gateway/onetoken/onetoken_gateway.py | 2 ++ vnpy/gateway/tiger/tiger_gateway.py | 7 +++++++ vnpy/gateway/xtp/xtp_gateway.py | 2 ++ vnpy/trader/engine.py | 13 +++++++++++++ vnpy/trader/gateway.py | 3 +++ vnpy/trader/ui/widget.py | 3 ++- 16 files changed, 56 insertions(+), 11 deletions(-) diff --git a/vnpy/gateway/bitfinex/bitfinex_gateway.py b/vnpy/gateway/bitfinex/bitfinex_gateway.py index bcaab464..832c2969 100644 --- a/vnpy/gateway/bitfinex/bitfinex_gateway.py +++ b/vnpy/gateway/bitfinex/bitfinex_gateway.py @@ -72,6 +72,8 @@ class BitfinexGateway(BaseGateway): "proxy_port": 1080, } + exchanges = [Exchange.BITFINEX] + def __init__(self, event_engine): """Constructor""" super(BitfinexGateway, self).__init__(event_engine, "BITFINEX") diff --git a/vnpy/gateway/bitmex/bitmex_gateway.py b/vnpy/gateway/bitmex/bitmex_gateway.py index 11579c4b..678f09c9 100644 --- a/vnpy/gateway/bitmex/bitmex_gateway.py +++ b/vnpy/gateway/bitmex/bitmex_gateway.py @@ -75,6 +75,8 @@ class BitmexGateway(BaseGateway): "代理端口": "", } + exchanges = [Exchange.BITMEX] + def __init__(self, event_engine): """Constructor""" super(BitmexGateway, self).__init__(event_engine, "BITMEX") diff --git a/vnpy/gateway/ctp/ctp_gateway.py b/vnpy/gateway/ctp/ctp_gateway.py index 6dd92450..697c35b6 100644 --- a/vnpy/gateway/ctp/ctp_gateway.py +++ b/vnpy/gateway/ctp/ctp_gateway.py @@ -134,6 +134,8 @@ class CtpGateway(BaseGateway): "授权编码": "" } + exchanges = list(EXCHANGE_CTP2VT.values()) + def __init__(self, event_engine): """Constructor""" super(CtpGateway, self).__init__(event_engine, "CTP") diff --git a/vnpy/gateway/femas/femas_gateway.py b/vnpy/gateway/femas/femas_gateway.py index 5b45f4ed..47f80fbb 100644 --- a/vnpy/gateway/femas/femas_gateway.py +++ b/vnpy/gateway/femas/femas_gateway.py @@ -87,12 +87,6 @@ OFFSET_VT2FEMAS = { } OFFSET_FEMAS2VT = {v: k for k, v in OFFSET_VT2FEMAS.items()} -# PRODUCT_CTP2VT = { -# THOST_FTDC_PC_Futures: Product.FUTURES, -# THOST_FTDC_PC_Options: Product.OPTION, -# THOST_FTDC_PC_Combination: Product.SPREAD -# } - DIRECTION_FEMAS2VT = {v: k for k, v in DIRECTION_VT2FEMAS.items()} DIRECTION_FEMAS2VT[USTP_FTDC_PD_Long] = Direction.LONG DIRECTION_FEMAS2VT[USTP_FTDC_PD_Short] = Direction.SHORT @@ -128,6 +122,8 @@ class FemasGateway(BaseGateway): "md_address": "", } + exchanges = list(EXCHANGE_FEMAS2VT.values()) + def __init__(self, event_engine): """Constructor""" super(FemasGateway, self).__init__(event_engine, "FEMAS") diff --git a/vnpy/gateway/futu/futu_gateway.py b/vnpy/gateway/futu/futu_gateway.py index c6205da2..2f45adbe 100644 --- a/vnpy/gateway/futu/futu_gateway.py +++ b/vnpy/gateway/futu/futu_gateway.py @@ -86,6 +86,8 @@ class FutuGateway(BaseGateway): "环境": [TrdEnv.REAL, TrdEnv.SIMULATE], } + exchanges = list(EXCHANGE_FUTU2VT.values()) + def __init__(self, event_engine): """Constructor""" super(FutuGateway, self).__init__(event_engine, "FUTU") diff --git a/vnpy/gateway/huobi/huobi_gateway.py b/vnpy/gateway/huobi/huobi_gateway.py index 79de4023..4f9782d9 100644 --- a/vnpy/gateway/huobi/huobi_gateway.py +++ b/vnpy/gateway/huobi/huobi_gateway.py @@ -77,6 +77,8 @@ class HuobiGateway(BaseGateway): "代理端口": "", } + exchanges = [Exchange.HUOBI] + def __init__(self, event_engine): """Constructor""" super(HuobiGateway, self).__init__(event_engine, "HUOBI") diff --git a/vnpy/gateway/ib/ib_gateway.py b/vnpy/gateway/ib/ib_gateway.py index f7747995..0a7d0fb8 100644 --- a/vnpy/gateway/ib/ib_gateway.py +++ b/vnpy/gateway/ib/ib_gateway.py @@ -116,6 +116,8 @@ class IbGateway(BaseGateway): "客户号": 1 } + exchanges = list(EXCHANGE_VT2IB.keys()) + def __init__(self, event_engine): """""" super(IbGateway, self).__init__(event_engine, "IB") diff --git a/vnpy/gateway/oes/oes_gateway.py b/vnpy/gateway/oes/oes_gateway.py index 8918cb00..14afc678 100644 --- a/vnpy/gateway/oes/oes_gateway.py +++ b/vnpy/gateway/oes/oes_gateway.py @@ -12,7 +12,7 @@ from vnpy.trader.object import (CancelRequest, OrderRequest, SubscribeRequest) from vnpy.trader.utility import get_file_path from .oes_md import OesMdApi -from .oes_td import OesTdApi +from .oes_td import OesTdApi, EXCHANGE_VT2OES from .utils import config_template @@ -39,6 +39,8 @@ class OesGateway(BaseGateway): "hdd_serial": "", } + exchanges = list(EXCHANGE_VT2OES.keys()) + def __init__(self, event_engine): """Constructor""" super().__init__(event_engine, "OES") @@ -55,7 +57,8 @@ class OesGateway(BaseGateway): def connect(self, setting: dict): """""" if not setting['password'].startswith("md5:"): - setting['password'] = "md5:" + hashlib.md5(setting['password'].encode()).hexdigest() + setting['password'] = "md5:" + \ + hashlib.md5(setting['password'].encode()).hexdigest() username = setting['username'] password = setting['password'] @@ -80,13 +83,15 @@ class OesGateway(BaseGateway): self.md_api.tcp_server = setting['md_tcp_server'] self.md_api.qry_server = setting['md_qry_server'] - Thread(target=self._connect_md_sync, args=(config_path, username, password)).start() + Thread(target=self._connect_md_sync, args=( + config_path, username, password)).start() self.td_api.ord_server = setting['td_ord_server'] self.td_api.rpt_server = setting['td_rpt_server'] self.td_api.qry_server = setting['td_qry_server'] self.td_api.hdd_serial = setting['hdd_serial'] - Thread(target=self._connect_td_sync, args=(config_path, username, password)).start() + Thread(target=self._connect_td_sync, args=( + config_path, username, password)).start() def _connect_td_sync(self, config_path, username, password): self.td_api.config_path = config_path diff --git a/vnpy/gateway/okex/okex_gateway.py b/vnpy/gateway/okex/okex_gateway.py index 184c6452..ba7a2f80 100644 --- a/vnpy/gateway/okex/okex_gateway.py +++ b/vnpy/gateway/okex/okex_gateway.py @@ -78,6 +78,8 @@ class OkexGateway(BaseGateway): "代理端口": "", } + exchanges = [Exchange.OKEX] + def __init__(self, event_engine): """Constructor""" super(OkexGateway, self).__init__(event_engine, "OKEX") diff --git a/vnpy/gateway/okexf/okexf_gateway.py b/vnpy/gateway/okexf/okexf_gateway.py index ce9fbd68..24aea8f5 100644 --- a/vnpy/gateway/okexf/okexf_gateway.py +++ b/vnpy/gateway/okexf/okexf_gateway.py @@ -81,6 +81,8 @@ class OkexfGateway(BaseGateway): "代理端口": "", } + exchanges = [Exchange.OKEX] + def __init__(self, event_engine): """Constructor""" super(OkexfGateway, self).__init__(event_engine, "OKEXF") diff --git a/vnpy/gateway/onetoken/onetoken_gateway.py b/vnpy/gateway/onetoken/onetoken_gateway.py index 080d5bac..ece8f52a 100644 --- a/vnpy/gateway/onetoken/onetoken_gateway.py +++ b/vnpy/gateway/onetoken/onetoken_gateway.py @@ -71,6 +71,8 @@ class OnetokenGateway(BaseGateway): "代理端口": 1080, } + exchanges = list(EXCHANGE_VT2ONETOKEN.keys()) + def __init__(self, event_engine): """Constructor""" super(OnetokenGateway, self).__init__(event_engine, "1TOKEN") diff --git a/vnpy/gateway/tiger/tiger_gateway.py b/vnpy/gateway/tiger/tiger_gateway.py index 1b17ca2f..801f3f85 100644 --- a/vnpy/gateway/tiger/tiger_gateway.py +++ b/vnpy/gateway/tiger/tiger_gateway.py @@ -96,6 +96,13 @@ class TigerGateway(BaseGateway): "private_key": '', } + exchanges = [ + Exchange.SEHK, + Exchange.SMART, + Exchange.SSE, + Exchange.SZSE + ] + def __init__(self, event_engine): """Constructor""" super(TigerGateway, self).__init__(event_engine, "TIGER") diff --git a/vnpy/gateway/xtp/xtp_gateway.py b/vnpy/gateway/xtp/xtp_gateway.py index 726bf41e..0d8d784d 100644 --- a/vnpy/gateway/xtp/xtp_gateway.py +++ b/vnpy/gateway/xtp/xtp_gateway.py @@ -111,6 +111,8 @@ class XtpGateway(BaseGateway): "授权码": "" } + exchanges = list(EXCHANGE_VT2XTP.keys()) + def __init__(self, event_engine: EventEngine): """""" super().__init__(event_engine, "XTP") diff --git a/vnpy/trader/engine.py b/vnpy/trader/engine.py index 2d4a98e0..12e3c3d3 100644 --- a/vnpy/trader/engine.py +++ b/vnpy/trader/engine.py @@ -43,6 +43,7 @@ class MainEngine: self.gateways = {} self.engines = {} self.apps = {} + self.exchanges = [] self.init_engines() @@ -60,6 +61,12 @@ class MainEngine: """ gateway = gateway_class(self.event_engine) self.gateways[gateway.gateway_name] = gateway + + # Add gateway supported exchanges into engine + for exchange in gateway.exchanges: + if exchange not in self.exchanges: + self.exchanges.append(exchange) + return gateway def add_app(self, app_class: BaseApp): @@ -127,6 +134,12 @@ class MainEngine: """ return list(self.apps.values()) + def get_all_exchanges(self): + """ + Get all exchanges. + """ + return self.exchanges + def connect(self, setting: dict, gateway_name: str): """ Start connection of a specific gateway. diff --git a/vnpy/trader/gateway.py b/vnpy/trader/gateway.py index ce7aa591..edd2c6ab 100644 --- a/vnpy/trader/gateway.py +++ b/vnpy/trader/gateway.py @@ -72,6 +72,9 @@ class BaseGateway(ABC): # Fields required in setting dict for connect function. default_setting = {} + # Exchanges supported in the gateway. + exchanges = [] + def __init__(self, event_engine: EventEngine, gateway_name: str): """""" self.event_engine = event_engine diff --git a/vnpy/trader/ui/widget.py b/vnpy/trader/ui/widget.py index fa745825..e9accb07 100644 --- a/vnpy/trader/ui/widget.py +++ b/vnpy/trader/ui/widget.py @@ -582,8 +582,9 @@ class TradingWidget(QtWidgets.QWidget): self.setFixedWidth(300) # Trading function area + exchanges = self.main_engine.get_all_exchanges() self.exchange_combo = QtWidgets.QComboBox() - self.exchange_combo.addItems([exchange.value for exchange in Exchange]) + self.exchange_combo.addItems([exchange.value for exchange in exchanges]) self.symbol_line = QtWidgets.QLineEdit() self.symbol_line.returnPressed.connect(self.set_vt_symbol) From bfd5ac66d2e12d9c6b72c5bdb4ab88afaa4a649d Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 30 Apr 2019 13:57:14 +0800 Subject: [PATCH 2/4] [Fix]close #1646 --- vnpy/app/cta_strategy/converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnpy/app/cta_strategy/converter.py b/vnpy/app/cta_strategy/converter.py index e8d5423b..0ba57bba 100644 --- a/vnpy/app/cta_strategy/converter.py +++ b/vnpy/app/cta_strategy/converter.py @@ -219,7 +219,7 @@ class PositionHolding: elif order.offset == Offset.CLOSE: self.long_td_frozen += frozen - if self.long_td_frozen > self.short_td: + if self.long_td_frozen > self.long_td: self.long_yd_frozen += (self.long_td_frozen - self.long_td) self.long_td_frozen = self.long_td From dbf37c629a301cafb8276e9c21bbe3773779a6eb Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 30 Apr 2019 13:58:31 +0800 Subject: [PATCH 3/4] [Fix]close #1622 --- vnpy/trader/rqdata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vnpy/trader/rqdata.py b/vnpy/trader/rqdata.py index 9b573e0f..1e1b3209 100644 --- a/vnpy/trader/rqdata.py +++ b/vnpy/trader/rqdata.py @@ -12,7 +12,7 @@ from .object import BarData INTERVAL_VT2RQ = { Interval.MINUTE: "1m", - Interval.HOUR: "1h", + Interval.HOUR: "60m", Interval.DAILY: "1d", } From 791fb0d840279f195f3498d1e459367bec0800f0 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Tue, 30 Apr 2019 14:29:35 +0800 Subject: [PATCH 4/4] [Add]adjust timestamp of bar data from RQData, close #1573 --- vnpy/trader/rqdata.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/vnpy/trader/rqdata.py b/vnpy/trader/rqdata.py index 1e1b3209..965d32c7 100644 --- a/vnpy/trader/rqdata.py +++ b/vnpy/trader/rqdata.py @@ -16,6 +16,12 @@ INTERVAL_VT2RQ = { Interval.DAILY: "1d", } +INTERVAL_ADJUSTMENT_MAP = { + Interval.MINUTE: timedelta(minutes=1), + Interval.HOUR: timedelta(hours=1), + Interval.DAILY: timedelta() # no need to adjust for daily bar +} + class RqdataClient: """ @@ -102,7 +108,11 @@ class RqdataClient: if not rq_interval: return None - end += timedelta(1) # For querying night trading period data + # For adjust timestamp from bar close point (RQData) to open point (VN Trader) + adjustment = INTERVAL_ADJUSTMENT_MAP[interval] + + # For querying night trading period data + end += timedelta(1) df = rqdata_get_price( rq_symbol, @@ -118,7 +128,7 @@ class RqdataClient: symbol=symbol, exchange=exchange, interval=interval, - datetime=row.name.to_pydatetime(), + datetime=row.name.to_pydatetime() - adjustment, open_price=row["open"], high_price=row["high"], low_price=row["low"],