commit
4ec6ca2af7
@ -219,7 +219,7 @@ class PositionHolding:
|
|||||||
elif order.offset == Offset.CLOSE:
|
elif order.offset == Offset.CLOSE:
|
||||||
self.long_td_frozen += frozen
|
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_yd_frozen += (self.long_td_frozen
|
||||||
- self.long_td)
|
- self.long_td)
|
||||||
self.long_td_frozen = self.long_td
|
self.long_td_frozen = self.long_td
|
||||||
|
@ -72,6 +72,8 @@ class BitfinexGateway(BaseGateway):
|
|||||||
"proxy_port": 1080,
|
"proxy_port": 1080,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = [Exchange.BITFINEX]
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(BitfinexGateway, self).__init__(event_engine, "BITFINEX")
|
super(BitfinexGateway, self).__init__(event_engine, "BITFINEX")
|
||||||
|
@ -75,6 +75,8 @@ class BitmexGateway(BaseGateway):
|
|||||||
"代理端口": "",
|
"代理端口": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = [Exchange.BITMEX]
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(BitmexGateway, self).__init__(event_engine, "BITMEX")
|
super(BitmexGateway, self).__init__(event_engine, "BITMEX")
|
||||||
|
@ -134,6 +134,8 @@ class CtpGateway(BaseGateway):
|
|||||||
"授权编码": ""
|
"授权编码": ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_CTP2VT.values())
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(CtpGateway, self).__init__(event_engine, "CTP")
|
super(CtpGateway, self).__init__(event_engine, "CTP")
|
||||||
|
@ -87,12 +87,6 @@ OFFSET_VT2FEMAS = {
|
|||||||
}
|
}
|
||||||
OFFSET_FEMAS2VT = {v: k for k, v in OFFSET_VT2FEMAS.items()}
|
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 = {v: k for k, v in DIRECTION_VT2FEMAS.items()}
|
||||||
DIRECTION_FEMAS2VT[USTP_FTDC_PD_Long] = Direction.LONG
|
DIRECTION_FEMAS2VT[USTP_FTDC_PD_Long] = Direction.LONG
|
||||||
DIRECTION_FEMAS2VT[USTP_FTDC_PD_Short] = Direction.SHORT
|
DIRECTION_FEMAS2VT[USTP_FTDC_PD_Short] = Direction.SHORT
|
||||||
@ -128,6 +122,8 @@ class FemasGateway(BaseGateway):
|
|||||||
"md_address": "",
|
"md_address": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_FEMAS2VT.values())
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(FemasGateway, self).__init__(event_engine, "FEMAS")
|
super(FemasGateway, self).__init__(event_engine, "FEMAS")
|
||||||
|
@ -86,6 +86,8 @@ class FutuGateway(BaseGateway):
|
|||||||
"环境": [TrdEnv.REAL, TrdEnv.SIMULATE],
|
"环境": [TrdEnv.REAL, TrdEnv.SIMULATE],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_FUTU2VT.values())
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(FutuGateway, self).__init__(event_engine, "FUTU")
|
super(FutuGateway, self).__init__(event_engine, "FUTU")
|
||||||
|
@ -77,6 +77,8 @@ class HuobiGateway(BaseGateway):
|
|||||||
"代理端口": "",
|
"代理端口": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = [Exchange.HUOBI]
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(HuobiGateway, self).__init__(event_engine, "HUOBI")
|
super(HuobiGateway, self).__init__(event_engine, "HUOBI")
|
||||||
|
@ -116,6 +116,8 @@ class IbGateway(BaseGateway):
|
|||||||
"客户号": 1
|
"客户号": 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_VT2IB.keys())
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
""""""
|
""""""
|
||||||
super(IbGateway, self).__init__(event_engine, "IB")
|
super(IbGateway, self).__init__(event_engine, "IB")
|
||||||
|
@ -12,7 +12,7 @@ from vnpy.trader.object import (CancelRequest, OrderRequest,
|
|||||||
SubscribeRequest)
|
SubscribeRequest)
|
||||||
from vnpy.trader.utility import get_file_path
|
from vnpy.trader.utility import get_file_path
|
||||||
from .oes_md import OesMdApi
|
from .oes_md import OesMdApi
|
||||||
from .oes_td import OesTdApi
|
from .oes_td import OesTdApi, EXCHANGE_VT2OES
|
||||||
from .utils import config_template
|
from .utils import config_template
|
||||||
|
|
||||||
|
|
||||||
@ -39,6 +39,8 @@ class OesGateway(BaseGateway):
|
|||||||
"hdd_serial": "",
|
"hdd_serial": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_VT2OES.keys())
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super().__init__(event_engine, "OES")
|
super().__init__(event_engine, "OES")
|
||||||
@ -55,7 +57,8 @@ class OesGateway(BaseGateway):
|
|||||||
def connect(self, setting: dict):
|
def connect(self, setting: dict):
|
||||||
""""""
|
""""""
|
||||||
if not setting['password'].startswith("md5:"):
|
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']
|
username = setting['username']
|
||||||
password = setting['password']
|
password = setting['password']
|
||||||
@ -80,13 +83,15 @@ class OesGateway(BaseGateway):
|
|||||||
|
|
||||||
self.md_api.tcp_server = setting['md_tcp_server']
|
self.md_api.tcp_server = setting['md_tcp_server']
|
||||||
self.md_api.qry_server = setting['md_qry_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.ord_server = setting['td_ord_server']
|
||||||
self.td_api.rpt_server = setting['td_rpt_server']
|
self.td_api.rpt_server = setting['td_rpt_server']
|
||||||
self.td_api.qry_server = setting['td_qry_server']
|
self.td_api.qry_server = setting['td_qry_server']
|
||||||
self.td_api.hdd_serial = setting['hdd_serial']
|
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):
|
def _connect_td_sync(self, config_path, username, password):
|
||||||
self.td_api.config_path = config_path
|
self.td_api.config_path = config_path
|
||||||
|
@ -78,6 +78,8 @@ class OkexGateway(BaseGateway):
|
|||||||
"代理端口": "",
|
"代理端口": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = [Exchange.OKEX]
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(OkexGateway, self).__init__(event_engine, "OKEX")
|
super(OkexGateway, self).__init__(event_engine, "OKEX")
|
||||||
|
@ -81,6 +81,8 @@ class OkexfGateway(BaseGateway):
|
|||||||
"代理端口": "",
|
"代理端口": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = [Exchange.OKEX]
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(OkexfGateway, self).__init__(event_engine, "OKEXF")
|
super(OkexfGateway, self).__init__(event_engine, "OKEXF")
|
||||||
|
@ -71,6 +71,8 @@ class OnetokenGateway(BaseGateway):
|
|||||||
"代理端口": 1080,
|
"代理端口": 1080,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_VT2ONETOKEN.keys())
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(OnetokenGateway, self).__init__(event_engine, "1TOKEN")
|
super(OnetokenGateway, self).__init__(event_engine, "1TOKEN")
|
||||||
|
@ -96,6 +96,13 @@ class TigerGateway(BaseGateway):
|
|||||||
"private_key": '',
|
"private_key": '',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = [
|
||||||
|
Exchange.SEHK,
|
||||||
|
Exchange.SMART,
|
||||||
|
Exchange.SSE,
|
||||||
|
Exchange.SZSE
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, event_engine):
|
def __init__(self, event_engine):
|
||||||
"""Constructor"""
|
"""Constructor"""
|
||||||
super(TigerGateway, self).__init__(event_engine, "TIGER")
|
super(TigerGateway, self).__init__(event_engine, "TIGER")
|
||||||
|
@ -111,6 +111,8 @@ class XtpGateway(BaseGateway):
|
|||||||
"授权码": ""
|
"授权码": ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exchanges = list(EXCHANGE_VT2XTP.keys())
|
||||||
|
|
||||||
def __init__(self, event_engine: EventEngine):
|
def __init__(self, event_engine: EventEngine):
|
||||||
""""""
|
""""""
|
||||||
super().__init__(event_engine, "XTP")
|
super().__init__(event_engine, "XTP")
|
||||||
|
@ -43,6 +43,7 @@ class MainEngine:
|
|||||||
self.gateways = {}
|
self.gateways = {}
|
||||||
self.engines = {}
|
self.engines = {}
|
||||||
self.apps = {}
|
self.apps = {}
|
||||||
|
self.exchanges = []
|
||||||
|
|
||||||
self.init_engines()
|
self.init_engines()
|
||||||
|
|
||||||
@ -60,6 +61,12 @@ class MainEngine:
|
|||||||
"""
|
"""
|
||||||
gateway = gateway_class(self.event_engine)
|
gateway = gateway_class(self.event_engine)
|
||||||
self.gateways[gateway.gateway_name] = gateway
|
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
|
return gateway
|
||||||
|
|
||||||
def add_app(self, app_class: BaseApp):
|
def add_app(self, app_class: BaseApp):
|
||||||
@ -127,6 +134,12 @@ class MainEngine:
|
|||||||
"""
|
"""
|
||||||
return list(self.apps.values())
|
return list(self.apps.values())
|
||||||
|
|
||||||
|
def get_all_exchanges(self):
|
||||||
|
"""
|
||||||
|
Get all exchanges.
|
||||||
|
"""
|
||||||
|
return self.exchanges
|
||||||
|
|
||||||
def connect(self, setting: dict, gateway_name: str):
|
def connect(self, setting: dict, gateway_name: str):
|
||||||
"""
|
"""
|
||||||
Start connection of a specific gateway.
|
Start connection of a specific gateway.
|
||||||
|
@ -72,6 +72,9 @@ class BaseGateway(ABC):
|
|||||||
# Fields required in setting dict for connect function.
|
# Fields required in setting dict for connect function.
|
||||||
default_setting = {}
|
default_setting = {}
|
||||||
|
|
||||||
|
# Exchanges supported in the gateway.
|
||||||
|
exchanges = []
|
||||||
|
|
||||||
def __init__(self, event_engine: EventEngine, gateway_name: str):
|
def __init__(self, event_engine: EventEngine, gateway_name: str):
|
||||||
""""""
|
""""""
|
||||||
self.event_engine = event_engine
|
self.event_engine = event_engine
|
||||||
|
@ -12,10 +12,16 @@ from .object import BarData
|
|||||||
|
|
||||||
INTERVAL_VT2RQ = {
|
INTERVAL_VT2RQ = {
|
||||||
Interval.MINUTE: "1m",
|
Interval.MINUTE: "1m",
|
||||||
Interval.HOUR: "1h",
|
Interval.HOUR: "60m",
|
||||||
Interval.DAILY: "1d",
|
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:
|
class RqdataClient:
|
||||||
"""
|
"""
|
||||||
@ -102,7 +108,11 @@ class RqdataClient:
|
|||||||
if not rq_interval:
|
if not rq_interval:
|
||||||
return None
|
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(
|
df = rqdata_get_price(
|
||||||
rq_symbol,
|
rq_symbol,
|
||||||
@ -118,7 +128,7 @@ class RqdataClient:
|
|||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
exchange=exchange,
|
exchange=exchange,
|
||||||
interval=interval,
|
interval=interval,
|
||||||
datetime=row.name.to_pydatetime(),
|
datetime=row.name.to_pydatetime() - adjustment,
|
||||||
open_price=row["open"],
|
open_price=row["open"],
|
||||||
high_price=row["high"],
|
high_price=row["high"],
|
||||||
low_price=row["low"],
|
low_price=row["low"],
|
||||||
|
@ -582,8 +582,9 @@ class TradingWidget(QtWidgets.QWidget):
|
|||||||
self.setFixedWidth(300)
|
self.setFixedWidth(300)
|
||||||
|
|
||||||
# Trading function area
|
# Trading function area
|
||||||
|
exchanges = self.main_engine.get_all_exchanges()
|
||||||
self.exchange_combo = QtWidgets.QComboBox()
|
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 = QtWidgets.QLineEdit()
|
||||||
self.symbol_line.returnPressed.connect(self.set_vt_symbol)
|
self.symbol_line.returnPressed.connect(self.set_vt_symbol)
|
||||||
|
Loading…
Reference in New Issue
Block a user