From b89eeb8d573d0a7ab17eb76041960af93fad3e49 Mon Sep 17 00:00:00 2001 From: 1122455801 Date: Tue, 5 Mar 2019 23:15:31 +0800 Subject: [PATCH 1/6] Update run.py --- tests/trader/run.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/trader/run.py b/tests/trader/run.py index c616b85a..98a4b1e8 100644 --- a/tests/trader/run.py +++ b/tests/trader/run.py @@ -4,10 +4,11 @@ from vnpy.event import EventEngine from vnpy.trader.engine import MainEngine from vnpy.trader.ui import MainWindow, create_qapp -from vnpy.gateway.bitmex import BitmexGateway -from vnpy.gateway.futu import FutuGateway -from vnpy.gateway.ib import IbGateway -from vnpy.gateway.ctp import CtpGateway +#from vnpy.gateway.bitmex import BitmexGateway +#from vnpy.gateway.futu import FutuGateway +#from vnpy.gateway.ib import IbGateway +#from vnpy.gateway.ctp import CtpGateway +from vnpy.gateway.tiger import TigerGateway from vnpy.app.cta_strategy import CtaStrategyApp @@ -19,10 +20,11 @@ def main(): event_engine = EventEngine() main_engine = MainEngine(event_engine) - main_engine.add_gateway(CtpGateway) - main_engine.add_gateway(IbGateway) - main_engine.add_gateway(FutuGateway) - main_engine.add_gateway(BitmexGateway) + #main_engine.add_gateway(CtpGateway) + #main_engine.add_gateway(IbGateway) + #main_engine.add_gateway(FutuGateway) + #main_engine.add_gateway(BitmexGateway) + main_engine.add_gateway(TigerGateway) main_engine.add_app(CtaStrategyApp) From 861bda1fafe77c97ec4098d644d673717407b694 Mon Sep 17 00:00:00 2001 From: 1122455801 Date: Tue, 5 Mar 2019 23:15:35 +0800 Subject: [PATCH 2/6] Create __init__.py --- vnpy/gateway/tiger/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 vnpy/gateway/tiger/__init__.py diff --git a/vnpy/gateway/tiger/__init__.py b/vnpy/gateway/tiger/__init__.py new file mode 100644 index 00000000..76710f42 --- /dev/null +++ b/vnpy/gateway/tiger/__init__.py @@ -0,0 +1 @@ +from .tiger_gateway import TigerGateway \ No newline at end of file From 4609854f7c0d6c5c39d73d03457d7ce53875e90c Mon Sep 17 00:00:00 2001 From: 1122455801 Date: Tue, 5 Mar 2019 23:15:38 +0800 Subject: [PATCH 3/6] Create tiger_gateway.py --- vnpy/gateway/tiger/tiger_gateway.py | 579 ++++++++++++++++++++++++++++ 1 file changed, 579 insertions(+) create mode 100644 vnpy/gateway/tiger/tiger_gateway.py diff --git a/vnpy/gateway/tiger/tiger_gateway.py b/vnpy/gateway/tiger/tiger_gateway.py new file mode 100644 index 00000000..2ab0badb --- /dev/null +++ b/vnpy/gateway/tiger/tiger_gateway.py @@ -0,0 +1,579 @@ +# encoding: UTF-8 +""" +Please install tiger-api before use. +pip install tigeropen +""" + +from copy import copy +from datetime import datetime +from threading import Thread +from time import sleep +import time +import pandas as pd +from pandas import DataFrame + +from tigeropen.tiger_open_config import TigerOpenClientConfig +from tigeropen.common.consts import Language, Currency ,Market +from tigeropen.quote.quote_client import QuoteClient +from tigeropen.trade.trade_client import TradeClient +from tigeropen.trade.domain.order import ORDER_STATUS +from tigeropen.push.push_client import PushClient +from tigeropen.common.exceptions import ApiException + +from vnpy.trader.constant import Direction, Product, Status, PriceType, Exchange + + +from vnpy.trader.event import EVENT_TIMER +from vnpy.trader.gateway import BaseGateway +from vnpy.trader.object import ( + TickData, + OrderData, + TradeData, + AccountData, + ContractData, + PositionData, + SubscribeRequest, + OrderRequest, + CancelRequest, + ) + + +PRODUCT_VT2TIGER = { + Product.EQUITY: "STK", + Product.OPTION: "OPT", + Product.WARRANT: "WAR", + Product.WARRANT: "IOPT", + Product.FUTURES: "FUT", + Product.OPTION: "FOP", + Product.FOREX: "CASH" + } + +DIRECTION_VT2TIGER = { + Direction.LONG: "BUY", + Direction.SHORT: "SELL", + } +DIRECTION_TIGER2VT = {v: k for k, v in DIRECTION_VT2TIGER.items()} + +PRICETYPE_VT2TIGER = { + PriceType.LIMIT: "LMT", + PriceType.MARKET: "MKT", + } + +STATUS_TIGER2VT = { + ORDER_STATUS.PENDING_NEW: Status.SUBMITTING, + ORDER_STATUS.NEW: Status.SUBMITTING, + ORDER_STATUS.HELD: Status.SUBMITTING, + ORDER_STATUS.PARTIALLY_FILLED: Status.PARTTRADED, + ORDER_STATUS.FILLED: Status.ALLTRADED, + ORDER_STATUS.CANCELLED: Status.CANCELLED, + ORDER_STATUS.PENDING_CANCEL: Status.CANCELLED, + ORDER_STATUS.REJECTED: Status.REJECTED, + ORDER_STATUS.EXPIRED: Status.NOTTRADED + } + + +class TigerGateway(BaseGateway): + """""" + + default_setting = { + "private_key": "MIICXQIBAAKBgQC1amZa5YsGTklry7DAsUBOwXJCgrsZZtB21PImw/yLmrbqRfsS3vawvMigLWcCwIDnHa+hpdpeze0eHIwbZzJzUDGvRALYK9t3D8pwPVxpwX1OF8RfHCM7YQvSOvPPnHHuVQvKaR7NNm1/WmvGXC9kVJdkYQ7kCmh52siFoy1MLQIDAQABAoGAVabcmIHTt7ByncBXvUJymDxhE+HhMEcImXJEueTCca8kOUu9FNXMJvmax3VoMzZsJbIwX+OMTEJxd0wHIlEA0gECjDwFK4Q42q+ptO4QABJQVSC6I+dOt2OIY28uvT3rkenOO8KRIDt4F52PFd71ZdB1aaXixORORq1MdSLi8EkCQQDiviAB+L5R/HVxwxvqZfJ530OtFd5IipZC9YZlY1CtXWCmu89LK7UUlEuNXyGsOxyz5jLqFuNRsie5AC23tfEPAkEAzNMCa8axJWfPZIH4tGrbZ1F3I41BQdgp2zBmR7AyUMBDkli86OzmJ7QUCJA/PJxK43/IYUWm4OU5Q+SvXCr3AwJBAJTBj1Y7zwES1CpSitn5EF+MbmX71t1YrsQ3OHkD80YJ4QMCbDkw75gUwox5QSoxjd8ow3Z4laJfc1gYGeZQ41kCQQCCiQwm8cceBq3W6To+iUdw7itWngRz2Ta7uXnFwFYgvpeR4jnq3GfF7+9AkeWrVBQqLtrem0xCUfQP/+N+gudPAkBFLbt78/MpQGEDc7jyu/KE5Mp4wMMDQQwch9VLvsAZwWLysB6rZWpo3jIfp9zZ7c3zOYGNMWAZjtMmNkRJ8COH", + "tiger_id": "1", + "account": "DU575569", + "standard_account": "", + "paper_account": "DU575569", + "language": "Language.zh_CN", + } + + def __init__(self, event_engine): + """Constructor""" + super(TigerGateway, self).__init__(event_engine, "TIGER") + + self.private_key = "" + self.tiger_id = "" + self.account = "" + self.standard_account = "" + self.paper_account = "" + self.language = "" + + self.client_config = None + self.quote_client = None + self.push_client = None + + self.ticks = {} + self.trades = set() + self.contracts = {} + self.symbol_names = {} + + self.thread = Thread(target=self.query_data) + + # For query function. + self.count = 0 + self.interval = 1 + self.query_funcs = [self.query_account, self.query_position,self.query_order, self.query_trade] + + def connect(self, setting: dict): + """""" + self.private_key = setting["private_key"] + self.tiger_id = setting["tiger_id"] + self.account = setting["account"] + self.standard_account = setting["standard_account"] + self.paper_account = setting["paper_account"] + self.languege = setting["language"] + + + self.get_client_config() + self.connect_quote() + self.connect_trade() + self.connect_push() + + self.thread.start() + + def query_data(self): + """ + Query all data necessary. + """ + #self.write_log("query_data") + sleep(2.0) # Wait 2 seconds till connection completed. + + self.query_contract() + self.query_trade() #1 + self.query_order() #2 + self.query_position() # + self.query_account() + + + # Start fixed interval query. + self.event_engine.register(EVENT_TIMER, self.process_timer_event) + + + def process_timer_event(self, event): + """""" + #self.write_log("process_time_event") + self.count += 1 + if self.count < self.interval: + return + self.count = 0 + func = self.query_funcs.pop(0) + func() + self.query_funcs.append(func) + + + def get_client_config(self, sandbox=True): + """""" + self.client_config = TigerOpenClientConfig(sandbox_debug=sandbox) + self.client_config.private_key = self.private_key + self.client_config.tiger_id = self.tiger_id + self.client_config.account = self.account + self.client_config.standard_account = self.standard_account + self.client_config.paper_account = self.paper_account + self.client_config.language = self.language + return self.client_config + + def connect_quote(self): + """ + Connect to market data server. + """ + self.quote_client = QuoteClient(self.client_config) + try: + symbol_names = self.quote_client.get_symbol_names(lang=Language.zh_CN) + self.symbol_names =dict(symbol_names) + except ApiException: + self.write_log("行情接口连接失败") + return + + if self.symbol_names: + self.write_log("行情接口连接成功") + + def connect_trade(self): + """ + Connect to trade server. + """ + self.trade_client = TradeClient(self.client_config) + try: + data = self.trade_client.get_managed_accounts() + except ApiException: + self.write_log("交易接口连接失败") + return + + if data: + self.write_log("交易接口连接成功") + + def connect_push(self): + """ + Connect to push server. + """ + protocol, host, port = self.client_config.socket_host_port + self.push_client = PushClient(host, port, (protocol == 'ssl')) + + self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key) + + self.write_log("推送接口连接成功") + +########################################################## + def subscribe(self, req: SubscribeRequest): + """""" + symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) + self.push_client.subscribe_quote(symbol) + + data = self.push_client.on_quote_change(symbol=req.symbol) + tick = self.ticks.get(data,None) + if not tick: + tick = TickData( + symbol=symbol, + exchange=None, + datetime=None, + gateway_name=self.gateway_name, + ) + self.ticks[data] = tick + self.process_quote() + contract = self.contracts.get(tick.vt_symbol, None) + if contract: + tick.name = contract.name + + return tick + + def process_quote(self,data): + """报价推送""" + symbol,info,_= data + volume, latest_price, high_price, prev_close, low_price, open_price, latest_time = [i[1] for i in info] + tick = self.get_tick(symbol) + time_local = time.localtime(latest_time/1000) + tick.datetime = time.strftime("%Y-%m-%d %H:%M:%S", time_local) + tick.open_price = open_price + tick.high_price = open_price + tick.low_price = low_price + tick.pre_close = prev_close + tick.last_price = latest_price + tick.volume = volume + + self.on_tick(copy(tick)) + + + + + + +########################################### + def send_order(self, req: OrderRequest): + """""" + symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) + currency = config_symbol_currency(req.symbol) + order_type = PRICETYPE_VT2TIGER[req.price_type] + + # first, get contract + try: + contract = self.trade_client.get_contracts(symbol=symbol,currency=currency)[0] + except ApiException: + self.write_log("获取合约对象失败") + return + + # second, create order + try: + order = self.trade_client.create_order( + account=self.account, + contract=contract, + action=DIRECTION_VT2TIGER[req.direction], + order_type=order_type, + quantity=req.volume, + limit_price=req.price + ) + except ApiException: + self.write_log("创建订单失败") + return + + # third, place order + try: + data = self.trade_client.place_order(order) + except ApiException: + self.write_log("发送订单失败") + return + + if data: + orderid = order.order_id + + order = req.create_order_data(orderid, self.gateway_name) + self.on_order(order) + return order.vt_orderid + + def cancel_order(self, req: CancelRequest): + """""" + try: + data = self.trade_client.cancel_order(order_id=req.orderid) + except ApiException: + self.write_log("撤单失败") + return + + if not data: + self.write_log('撤单成功') + + def query_contract(self): + """""" + # HK Stock + + try: + symbols_names_HK = self.quote_client.get_symbol_names(lang=Language.zh_CN ,market=Market.HK) + contract_names_HK = DataFrame(symbols_names_HK,columns=['symbol', 'name']) + except ApiException: + self.write_log("查询合约失败") + return + + contractList = list(contract_names_HK["symbol"]) + i, n = 0, len(contractList) + result = pd.DataFrame() + while i < n: + i += 500 + c = contractList[i - 500:i] + r = self.quote_client.get_trade_metas(c) + result = result.append(r) + pass + + contract_detail_HK = result.sort_values(by="symbol", ascending=True) + contract_HK = pd.merge(contract_names_HK, contract_detail_HK, how='left', on='symbol') + + for ix, row in contract_HK.iterrows(): + contract = ContractData( + symbol=row["symbol"], + exchange=Exchange.SEHK, + name=row["name"], + product=Product.EQUITY, + size=1, + pricetick=row["min_tick"], + gateway_name=self.gateway_name, + ) + self.on_contract(contract) + self.contracts[contract.vt_symbol] = contract + + # US Stock + symbols_names_US = self.quote_client.get_symbol_names(lang=Language.zh_CN ,market=Market.US) + contract_US = DataFrame(symbols_names_US,columns=['symbol', 'name']) + + for ix, row in contract_US.iterrows(): + contract = ContractData( + symbol=row["symbol"], + exchange=Exchange.SMART, + name=row["name"], + product=Product.EQUITY, + size=1, + pricetick=0.001, + gateway_name=self.gateway_name, + ) + self.on_contract(contract) + self.contracts[contract.vt_symbol] = contract + + # CN Stock + symbols_names_CN = self.quote_client.get_symbol_names(lang=Language.zh_CN ,market=Market.CN) + contract_CN = DataFrame(symbols_names_CN,columns=['symbol', 'name']) + + for ix, row in contract_CN.iterrows(): + symbol = row["symbol"] + symbol, exchange = convert_symbol_tiger2vt(symbol) + + contract = ContractData( + symbol=symbol, + exchange=exchange, + name=row["name"], + product=Product.EQUITY, + size=1, + pricetick=0.001, + gateway_name=self.gateway_name, + ) + self.on_contract(contract) + self.contracts[contract.vt_symbol] = contract + + self.write_log("合约查询成功") + + + def query_account(self): + """""" + #self.write_log("query_account_##") + try: + assets = self.trade_client.get_assets() + except ApiException: + self.write_log("查询资金失败") + return + + for i in assets: + account = AccountData( + accountid=self.tiger_id, + balance=float(i.summary.net_liquidation), + frozen=0.0, + gateway_name=self.gateway_name, + ) + + self.on_account(account) + + def query_position(self): + """""" + #self.write_log("query_position_##") + try: + position = self.trade_client.get_positions() + except ApiException: + self.write_log("查询持仓失败") + return + + for i in position: + symbol = i.contract.symbol + symbol, exchange = convert_symbol_tiger2vt(symbol) + volume = float(i.quantity) + # 判断方向 + if volume > 0: + direction = Direction.LONG + else: + direction = Direction.SHORT + + pos = PositionData( + symbol=symbol, + exchange=exchange, + direction=direction, + volume=volume, + frozen=0.0, + price=float(i.market_price), # market_price = 0.0 + pnl=float(i.average_cost), # 未知?? + gateway_name=self.gateway_name, + ) + + self.on_position(pos) + + def query_order(self): + """""" + #self.write_log("query_order") + try: + data = self.trade_client.get_orders() + except ApiException: + self.write_log("查询委托失败") + return + + self.process_order(data) + self.process_deal(data) + #self.write_log("委托查询成功") + + def query_trade(self): + """""" + #self.write_log("query_trade") + + def close(self): + """""" + if self.push_client: + self.push_client.disconnect() + + def process_order(self, data): + """""" + #self.write_log("process_order") + for i in data: + symbol = str(i.contract) + symbol, exchange = convert_symbol_tiger2vt(symbol) + time_local = time.localtime(i.order_time/1000) + + if i.order_type =="LMT": + price = i.limit_price + else: + price = i.avg_fill_price + + order = OrderData( + symbol=symbol, + exchange=exchange, + orderid=str(i.order_id), + direction=DIRECTION_TIGER2VT[i.action], + price=float(price), + volume=float(i.quantity), + traded=float(i.filled), + status=STATUS_TIGER2VT[i.status], + time=time.strftime("%Y-%m-%d %H:%M:%S", time_local).split(" ")[-1], + gateway_name=self.gateway_name, + ) + + self.on_order(order) + + def process_deal(self, data): + """ + Process trade data for both query and update. + """ + #self.write_log("process_deal_###") + for i in data: + if i.status == ORDER_STATUS.PARTIALLY_FILLED or i.status == ORDER_STATUS.FILLED: + symbol = str(i.contract) + symbol, exchange = convert_symbol_tiger2vt(symbol) + time_local = time.localtime(i.trade_time/1000) + + trade = TradeData( + symbol=symbol, + exchange=exchange, + direction=DIRECTION_TIGER2VT[i.action], + tradeid=i.order_id, + orderid=i.order_id, + price=float(i.avg_fill_price), + volume=float(i.filled), + time=time.strftime("%Y-%m-%d %H:%M:%S", time_local).split(" ")[-1], + gateway_name=self.gateway_name, + ) + + self.on_trade(trade) + + + + +def convert_symbol_tiger2vt(symbol): + """ + Convert symbol from vt to tiger. + """ + if symbol.encode("UTF-8").isalpha(): + exchange = Exchange.SMART + else: + if len(symbol) < 6: + exchange = Exchange.SEHK + elif symbol.startswith("6"): + exchange = Exchange.SSE + elif symbol.endswith(".SH"): + exchange = Exchange.SSE + symbol = symbol.strip(".SH") + else: + exchange = Exchange.SZSE + return symbol, exchange + + +def convert_symbol_vt2tiger(symbol, exchange): + """ + Convert symbol from vt to tiger. + """ + if exchange == Exchange.SSE and symbol.startswith("0"): + symbol = symbol + ".SH" + else: + symbol = symbol + return symbol + +def config_symbol_currency(symbol): + """ + Config symbol to corresponding currency + """ + if symbol.encode("UTF-8").isalpha(): + currency = Currency.USD + else: + if len(symbol) < 6: + currency = Currency.HKD + else: + currency = Currency.CNH + + return currency + + + + + + + + + + + + + + + + + + + + + + + From 897f8988441776d929f9fb21c4b337377fc030cb Mon Sep 17 00:00:00 2001 From: 1122455801 Date: Wed, 6 Mar 2019 10:54:56 +0800 Subject: [PATCH 4/6] Update tiger_gateway.py --- vnpy/gateway/tiger/tiger_gateway.py | 95 ++++++++++++----------------- 1 file changed, 38 insertions(+), 57 deletions(-) diff --git a/vnpy/gateway/tiger/tiger_gateway.py b/vnpy/gateway/tiger/tiger_gateway.py index 2ab0badb..697bed03 100644 --- a/vnpy/gateway/tiger/tiger_gateway.py +++ b/vnpy/gateway/tiger/tiger_gateway.py @@ -5,7 +5,6 @@ pip install tigeropen """ from copy import copy -from datetime import datetime from threading import Thread from time import sleep import time @@ -13,7 +12,7 @@ import pandas as pd from pandas import DataFrame from tigeropen.tiger_open_config import TigerOpenClientConfig -from tigeropen.common.consts import Language, Currency ,Market +from tigeropen.common.consts import Language, Currency, Market from tigeropen.quote.quote_client import QuoteClient from tigeropen.trade.trade_client import TradeClient from tigeropen.trade.domain.order import ORDER_STATUS @@ -35,7 +34,7 @@ from vnpy.trader.object import ( SubscribeRequest, OrderRequest, CancelRequest, - ) +) PRODUCT_VT2TIGER = { @@ -46,18 +45,18 @@ PRODUCT_VT2TIGER = { Product.FUTURES: "FUT", Product.OPTION: "FOP", Product.FOREX: "CASH" - } +} DIRECTION_VT2TIGER = { Direction.LONG: "BUY", Direction.SHORT: "SELL", - } +} DIRECTION_TIGER2VT = {v: k for k, v in DIRECTION_VT2TIGER.items()} PRICETYPE_VT2TIGER = { PriceType.LIMIT: "LMT", PriceType.MARKET: "MKT", - } +} STATUS_TIGER2VT = { ORDER_STATUS.PENDING_NEW: Status.SUBMITTING, @@ -69,7 +68,7 @@ STATUS_TIGER2VT = { ORDER_STATUS.PENDING_CANCEL: Status.CANCELLED, ORDER_STATUS.REJECTED: Status.REJECTED, ORDER_STATUS.EXPIRED: Status.NOTTRADED - } +} class TigerGateway(BaseGateway): @@ -82,7 +81,7 @@ class TigerGateway(BaseGateway): "standard_account": "", "paper_account": "DU575569", "language": "Language.zh_CN", - } + } def __init__(self, event_engine): """Constructor""" @@ -109,7 +108,7 @@ class TigerGateway(BaseGateway): # For query function. self.count = 0 self.interval = 1 - self.query_funcs = [self.query_account, self.query_position,self.query_order, self.query_trade] + self.query_funcs = [self.query_account, self.query_position, self.query_order] def connect(self, setting: dict): """""" @@ -120,7 +119,6 @@ class TigerGateway(BaseGateway): self.paper_account = setting["paper_account"] self.languege = setting["language"] - self.get_client_config() self.connect_quote() self.connect_trade() @@ -132,23 +130,19 @@ class TigerGateway(BaseGateway): """ Query all data necessary. """ - #self.write_log("query_data") sleep(2.0) # Wait 2 seconds till connection completed. self.query_contract() - self.query_trade() #1 - self.query_order() #2 - self.query_position() # + # self.query_trade() + self.query_order() + self.query_position() self.query_account() - # Start fixed interval query. self.event_engine.register(EVENT_TIMER, self.process_timer_event) - def process_timer_event(self, event): """""" - #self.write_log("process_time_event") self.count += 1 if self.count < self.interval: return @@ -157,7 +151,6 @@ class TigerGateway(BaseGateway): func() self.query_funcs.append(func) - def get_client_config(self, sandbox=True): """""" self.client_config = TigerOpenClientConfig(sandbox_debug=sandbox) @@ -209,35 +202,37 @@ class TigerGateway(BaseGateway): self.write_log("推送接口连接成功") -########################################################## def subscribe(self, req: SubscribeRequest): """""" - symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) - self.push_client.subscribe_quote(symbol) + # symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) + self.push_client.subscribe_quote([req.symbol]) - data = self.push_client.on_quote_change(symbol=req.symbol) - tick = self.ticks.get(data,None) + def on_quote_change(*args): + print(args) + data = self.push_client.quote_changed = on_quote_change + + tick = self.ticks.get(data, None) if not tick: tick = TickData( - symbol=symbol, - exchange=None, + symbol=req.symbol, + exchange=req.exchange, datetime=None, gateway_name=self.gateway_name, ) self.ticks[data] = tick - self.process_quote() + self.process_quote(data) contract = self.contracts.get(tick.vt_symbol, None) if contract: tick.name = contract.name return tick - def process_quote(self,data): + def process_quote(self, data): """报价推送""" - symbol,info,_= data + symbol, info, _ = data volume, latest_price, high_price, prev_close, low_price, open_price, latest_time = [i[1] for i in info] - tick = self.get_tick(symbol) - time_local = time.localtime(latest_time/1000) + tick = self.get_tick(symbol) + time_local = time.localtime(latest_time / 1000) tick.datetime = time.strftime("%Y-%m-%d %H:%M:%S", time_local) tick.open_price = open_price tick.high_price = open_price @@ -248,12 +243,6 @@ class TigerGateway(BaseGateway): self.on_tick(copy(tick)) - - - - - -########################################### def send_order(self, req: OrderRequest): """""" symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) @@ -262,7 +251,7 @@ class TigerGateway(BaseGateway): # first, get contract try: - contract = self.trade_client.get_contracts(symbol=symbol,currency=currency)[0] + contract = self.trade_client.get_contracts(symbol=symbol, currency=currency)[0] except ApiException: self.write_log("获取合约对象失败") return @@ -311,8 +300,8 @@ class TigerGateway(BaseGateway): # HK Stock try: - symbols_names_HK = self.quote_client.get_symbol_names(lang=Language.zh_CN ,market=Market.HK) - contract_names_HK = DataFrame(symbols_names_HK,columns=['symbol', 'name']) + symbols_names_HK = self.quote_client.get_symbol_names(lang=Language.zh_CN, market=Market.HK) + contract_names_HK = DataFrame(symbols_names_HK, columns=['symbol', 'name']) except ApiException: self.write_log("查询合约失败") return @@ -341,11 +330,11 @@ class TigerGateway(BaseGateway): gateway_name=self.gateway_name, ) self.on_contract(contract) - self.contracts[contract.vt_symbol] = contract + self.contracts[contract.vt_symbol] = contract # US Stock - symbols_names_US = self.quote_client.get_symbol_names(lang=Language.zh_CN ,market=Market.US) - contract_US = DataFrame(symbols_names_US,columns=['symbol', 'name']) + symbols_names_US = self.quote_client.get_symbol_names(lang=Language.zh_CN, market=Market.US) + contract_US = DataFrame(symbols_names_US, columns=['symbol', 'name']) for ix, row in contract_US.iterrows(): contract = ContractData( @@ -361,8 +350,8 @@ class TigerGateway(BaseGateway): self.contracts[contract.vt_symbol] = contract # CN Stock - symbols_names_CN = self.quote_client.get_symbol_names(lang=Language.zh_CN ,market=Market.CN) - contract_CN = DataFrame(symbols_names_CN,columns=['symbol', 'name']) + symbols_names_CN = self.quote_client.get_symbol_names(lang=Language.zh_CN, market=Market.CN) + contract_CN = DataFrame(symbols_names_CN, columns=['symbol', 'name']) for ix, row in contract_CN.iterrows(): symbol = row["symbol"] @@ -382,10 +371,8 @@ class TigerGateway(BaseGateway): self.write_log("合约查询成功") - def query_account(self): """""" - #self.write_log("query_account_##") try: assets = self.trade_client.get_assets() except ApiException: @@ -404,7 +391,6 @@ class TigerGateway(BaseGateway): def query_position(self): """""" - #self.write_log("query_position_##") try: position = self.trade_client.get_positions() except ApiException: @@ -436,7 +422,6 @@ class TigerGateway(BaseGateway): def query_order(self): """""" - #self.write_log("query_order") try: data = self.trade_client.get_orders() except ApiException: @@ -445,11 +430,10 @@ class TigerGateway(BaseGateway): self.process_order(data) self.process_deal(data) - #self.write_log("委托查询成功") def query_trade(self): """""" - #self.write_log("query_trade") + pass def close(self): """""" @@ -458,13 +442,12 @@ class TigerGateway(BaseGateway): def process_order(self, data): """""" - #self.write_log("process_order") for i in data: symbol = str(i.contract) symbol, exchange = convert_symbol_tiger2vt(symbol) - time_local = time.localtime(i.order_time/1000) + time_local = time.localtime(i.order_time / 1000) - if i.order_type =="LMT": + if i.order_type == "LMT": price = i.limit_price else: price = i.avg_fill_price @@ -488,12 +471,11 @@ class TigerGateway(BaseGateway): """ Process trade data for both query and update. """ - #self.write_log("process_deal_###") for i in data: if i.status == ORDER_STATUS.PARTIALLY_FILLED or i.status == ORDER_STATUS.FILLED: symbol = str(i.contract) symbol, exchange = convert_symbol_tiger2vt(symbol) - time_local = time.localtime(i.trade_time/1000) + time_local = time.localtime(i.trade_time / 1000) trade = TradeData( symbol=symbol, @@ -510,8 +492,6 @@ class TigerGateway(BaseGateway): self.on_trade(trade) - - def convert_symbol_tiger2vt(symbol): """ Convert symbol from vt to tiger. @@ -541,6 +521,7 @@ def convert_symbol_vt2tiger(symbol, exchange): symbol = symbol return symbol + def config_symbol_currency(symbol): """ Config symbol to corresponding currency From ae81b29f9cb197dc8efca92d93eea67750adf852 Mon Sep 17 00:00:00 2001 From: 1122455801 Date: Wed, 6 Mar 2019 16:17:17 +0800 Subject: [PATCH 5/6] Update tiger_gateway.py --- vnpy/gateway/tiger/tiger_gateway.py | 41 +++++++++++++---------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/vnpy/gateway/tiger/tiger_gateway.py b/vnpy/gateway/tiger/tiger_gateway.py index 697bed03..eacab507 100644 --- a/vnpy/gateway/tiger/tiger_gateway.py +++ b/vnpy/gateway/tiger/tiger_gateway.py @@ -10,6 +10,7 @@ from time import sleep import time import pandas as pd from pandas import DataFrame +from datetime import datetime from tigeropen.tiger_open_config import TigerOpenClientConfig from tigeropen.common.consts import Language, Currency, Market @@ -197,6 +198,8 @@ class TigerGateway(BaseGateway): """ protocol, host, port = self.client_config.socket_host_port self.push_client = PushClient(host, port, (protocol == 'ssl')) + + self.push_client.quote_changed = self.on_quote_change self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key) @@ -207,39 +210,33 @@ class TigerGateway(BaseGateway): # symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) self.push_client.subscribe_quote([req.symbol]) - def on_quote_change(*args): - print(args) - data = self.push_client.quote_changed = on_quote_change + def on_quote_change(self, symbol: str, data: list, trading: bool): + #print(symbol, data, trading) - tick = self.ticks.get(data, None) + tick = self.ticks.get(symbol, None) if not tick: tick = TickData( - symbol=req.symbol, - exchange=req.exchange, + symbol=symbol, + exchange=Exchange.SSE, datetime=None, gateway_name=self.gateway_name, ) - self.ticks[data] = tick - self.process_quote(data) + self.ticks[symbol] = tick + # self.process_quote(data) contract = self.contracts.get(tick.vt_symbol, None) if contract: tick.name = contract.name - return tick + # volume, latest_price, high_price, prev_close, low_price, open_price, latest_time = [i[1] for i in info] - def process_quote(self, data): - """报价推送""" - symbol, info, _ = data - volume, latest_price, high_price, prev_close, low_price, open_price, latest_time = [i[1] for i in info] - tick = self.get_tick(symbol) - time_local = time.localtime(latest_time / 1000) - tick.datetime = time.strftime("%Y-%m-%d %H:%M:%S", time_local) - tick.open_price = open_price - tick.high_price = open_price - tick.low_price = low_price - tick.pre_close = prev_close - tick.last_price = latest_price - tick.volume = volume + #tick.datetime = datetime.utcfromtimestamp(data[6][1] / 1000) + tick.datetime = datetime.now() + tick.open_price = data[5][1] + tick.high_price = data[2][1] + tick.low_price = data[4][1] + tick.pre_close = data[3][1] + tick.last_price = data[0][1] + tick.volume = data[1][1] self.on_tick(copy(tick)) From 30a65dfd437cd382f3e4e2f34e95ce35dbd9160d Mon Sep 17 00:00:00 2001 From: 1122455801 Date: Thu, 7 Mar 2019 14:58:44 +0800 Subject: [PATCH 6/6] Update tiger_gateway.py --- vnpy/gateway/tiger/tiger_gateway.py | 125 ++++++++++++++++++++++------ 1 file changed, 100 insertions(+), 25 deletions(-) diff --git a/vnpy/gateway/tiger/tiger_gateway.py b/vnpy/gateway/tiger/tiger_gateway.py index eacab507..e678afa1 100644 --- a/vnpy/gateway/tiger/tiger_gateway.py +++ b/vnpy/gateway/tiger/tiger_gateway.py @@ -52,7 +52,12 @@ DIRECTION_VT2TIGER = { Direction.LONG: "BUY", Direction.SHORT: "SELL", } -DIRECTION_TIGER2VT = {v: k for k, v in DIRECTION_VT2TIGER.items()} + +DIRECTION_TIGER2VT = { + "BUY": Direction.LONG, + "SELL": Direction.SHORT, + "sell": Direction.SHORT, +} PRICETYPE_VT2TIGER = { PriceType.LIMIT: "LMT", @@ -71,16 +76,17 @@ STATUS_TIGER2VT = { ORDER_STATUS.EXPIRED: Status.NOTTRADED } +# "1_key": "MIICXQIBAAKBgQC1amZa5YsGTklry7DAsUBOwXJCgrsZZtB21PImw/yLmrbqRfsS3vawvMigLWcCwIDnHa+hpdpeze0eHIwbZzJzUDGvRALYK9t3D8pwPVxpwX1OF8RfHCM7YQvSOvPPnHHuVQvKaR7NNm1/WmvGXC9kVJdkYQ7kCmh52siFoy1MLQIDAQABAoGAVabcmIHTt7ByncBXvUJymDxhE+HhMEcImXJEueTCca8kOUu9FNXMJvmax3VoMzZsJbIwX+OMTEJxd0wHIlEA0gECjDwFK4Q42q+ptO4QABJQVSC6I+dOt2OIY28uvT3rkenOO8KRIDt4F52PFd71ZdB1aaXixORORq1MdSLi8EkCQQDiviAB+L5R/HVxwxvqZfJ530OtFd5IipZC9YZlY1CtXWCmu89LK7UUlEuNXyGsOxyz5jLqFuNRsie5AC23tfEPAkEAzNMCa8axJWfPZIH4tGrbZ1F3I41BQdgp2zBmR7AyUMBDkli86OzmJ7QUCJA/PJxK43/IYUWm4OU5Q+SvXCr3AwJBAJTBj1Y7zwES1CpSitn5EF+MbmX71t1YrsQ3OHkD80YJ4QMCbDkw75gUwox5QSoxjd8ow3Z4laJfc1gYGeZQ41kCQQCCiQwm8cceBq3W6To+iUdw7itWngRz2Ta7uXnFwFYgvpeR4jnq3GfF7+9AkeWrVBQqLtrem0xCUfQP/+N+gudPAkBFLbt78/MpQGEDc7jyu/KE5Mp4wMMDQQwch9VLvsAZwWLysB6rZWpo3jIfp9zZ7c3zOYGNMWAZjtMmNkRJ8COH", class TigerGateway(BaseGateway): """""" - default_setting = { - "private_key": "MIICXQIBAAKBgQC1amZa5YsGTklry7DAsUBOwXJCgrsZZtB21PImw/yLmrbqRfsS3vawvMigLWcCwIDnHa+hpdpeze0eHIwbZzJzUDGvRALYK9t3D8pwPVxpwX1OF8RfHCM7YQvSOvPPnHHuVQvKaR7NNm1/WmvGXC9kVJdkYQ7kCmh52siFoy1MLQIDAQABAoGAVabcmIHTt7ByncBXvUJymDxhE+HhMEcImXJEueTCca8kOUu9FNXMJvmax3VoMzZsJbIwX+OMTEJxd0wHIlEA0gECjDwFK4Q42q+ptO4QABJQVSC6I+dOt2OIY28uvT3rkenOO8KRIDt4F52PFd71ZdB1aaXixORORq1MdSLi8EkCQQDiviAB+L5R/HVxwxvqZfJ530OtFd5IipZC9YZlY1CtXWCmu89LK7UUlEuNXyGsOxyz5jLqFuNRsie5AC23tfEPAkEAzNMCa8axJWfPZIH4tGrbZ1F3I41BQdgp2zBmR7AyUMBDkli86OzmJ7QUCJA/PJxK43/IYUWm4OU5Q+SvXCr3AwJBAJTBj1Y7zwES1CpSitn5EF+MbmX71t1YrsQ3OHkD80YJ4QMCbDkw75gUwox5QSoxjd8ow3Z4laJfc1gYGeZQ41kCQQCCiQwm8cceBq3W6To+iUdw7itWngRz2Ta7uXnFwFYgvpeR4jnq3GfF7+9AkeWrVBQqLtrem0xCUfQP/+N+gudPAkBFLbt78/MpQGEDc7jyu/KE5Mp4wMMDQQwch9VLvsAZwWLysB6rZWpo3jIfp9zZ7c3zOYGNMWAZjtMmNkRJ8COH", - "tiger_id": "1", - "account": "DU575569", - "standard_account": "", - "paper_account": "DU575569", + default_setting = { + "private_key": "MIICXAIBAAKBgQC2s9fGSfp86pYpK/9FFtdzZXcpncxDMaWww9WPPn2EnZC9zqIamz4nUewDGgya33VgoHNL7a3iGNCe4zqivhr8k1ACG68psElaRjALl1UzdAMv4xwnrxpceTCgA9AZM8x+BmVXvO5cfgIfGdoahtdxjMNjIYDkx+HORGJ1cFcmrQIDAQABAoGBAIwf8uYJ5yvXX8PEEsyScDv5HiO0+uyuLz4bdLegXfRQRKrOyFVPq6PMmQ7n87L0n7m0VbluWWaHUboK3PXkiBzTsmx0aFS3aNyr203QGXXwp9hxF2WS968/6K2zSikaDrmSkWps5dVVqhnkJ6STj7cvM6ZGYIHWPC7W79qTYHihAkEA3FvFSznaTTajvZpHq83rrCh3wmI2ggeh1M1i89HAv0EfTLkWweyNM8qO39qeaGzB/TZiOal0LR8Mk7HbGPOTVwJBANRA4LyhwczHEdwH16n5QPcrogoSsPM6uq9ZL8zYwaMTcHvEJUhW6hUMQPyWcNtenH9mwcgRF78TFGLqIH9s95sCP1bv3ebP7FCKPg+Pzrb5hwFk9dq65MZoPHC4l1Gab3EFQFQEsfXQXeURBU1L8zM/tUkxK4+US0GB/nRGtyog7wJBALU4a2lCpqgDc4EshPsP4GLosyHskX4qL4hVGpXIn5NvnoNdlgNsidHMs5O1ksgJwI6aGmuKBH9Ud/x4L6T8UW8CQEbrCa3/vIv5mHzGe9G7ZsK5VaPx3VETSeRbDUai8KGpcMXX7nFUnhsBd7YvehOSwRSd5SCWrZuejhIdn5V7hYM=", + "tiger_id": "20150008", + "account": "DU575568", + "standard_account": "DU575568", + "paper_account": "DU575568", "language": "Language.zh_CN", } @@ -109,7 +115,7 @@ class TigerGateway(BaseGateway): # For query function. self.count = 0 self.interval = 1 - self.query_funcs = [self.query_account, self.query_position, self.query_order] + self.query_funcs = [self.query_order] def connect(self, setting: dict): """""" @@ -198,38 +204,43 @@ class TigerGateway(BaseGateway): """ protocol, host, port = self.client_config.socket_host_port self.push_client = PushClient(host, port, (protocol == 'ssl')) - - self.push_client.quote_changed = self.on_quote_change - self.push_client.connect(self.client_config.tiger_id, self.client_config.private_key) + self.push_client.quote_changed = self.on_quote_change + + self.push_client.subscribe_asset() + self.push_client.asset_changed = self.on_asset_changed + + self.push_client.subscribe_position() + self.push_client.position_changed = self.on_position_changed + + self.push_client.subscribe_order() + self.push_client.order_changed = self.on_order_changed + self.write_log("推送接口连接成功") def subscribe(self, req: SubscribeRequest): - """""" - # symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) + """""" self.push_client.subscribe_quote([req.symbol]) + # self.push_client.subscribe_asset() + # self.push_client.subscribe_position() + # self.push_client.subscribe_order() def on_quote_change(self, symbol: str, data: list, trading: bool): - #print(symbol, data, trading) + symbol, exchange = convert_symbol_tiger2vt(symbol) + name = self.symbol_names[symbol] tick = self.ticks.get(symbol, None) if not tick: tick = TickData( symbol=symbol, - exchange=Exchange.SSE, + exchange=exchange, datetime=None, gateway_name=self.gateway_name, + name=name, ) self.ticks[symbol] = tick - # self.process_quote(data) - contract = self.contracts.get(tick.vt_symbol, None) - if contract: - tick.name = contract.name - - # volume, latest_price, high_price, prev_close, low_price, open_price, latest_time = [i[1] for i in info] - - #tick.datetime = datetime.utcfromtimestamp(data[6][1] / 1000) + tick.datetime = datetime.now() tick.open_price = data[5][1] tick.high_price = data[2][1] @@ -240,6 +251,70 @@ class TigerGateway(BaseGateway): self.on_tick(copy(tick)) + def on_asset_changed(self, account: str, data: list): + """""" + print("账号", data) + + account = AccountData( + accountid=account, + balance=data[7][1], + frozen=0.0, + gateway_name=self.gateway_name, + ) + self.on_account(account) + + def on_position_changed(self, account: str, data: list): + """""" + print("持仓", data) + + symbol = data[3][1] + volume = data[5][1] + # 判断方向 + if volume > 0: + direction = Direction.LONG + else: + direction = Direction.SHORT + + symbol, exchange = convert_symbol_tiger2vt(symbol) + + pos = PositionData( + symbol=symbol, + exchange=exchange, + direction=direction, + volume=volume, + frozen=0.0, + price=data[0][1], + pnl=data[4][1], + gateway_name=self.gateway_name, + ) + self.on_position(pos) + + def on_order_changed(self, account: str, data: list): + """""" + print("委托", data) + symbol = data[6][1] + volume = data[7][1] + if volume > 0: + direction = Direction.LONG + else: + direction = Direction.SHORT + + symbol, exchange = convert_symbol_tiger2vt(symbol) + + order = OrderData( + symbol=symbol, + exchange=exchange, + orderid=data[2][1], + direction=direction, + price=data[8][1], + volume=volume, + traded=data[4][1], + status=None, + time=datetime.now(), + gateway_name=self.gateway_name, + ) + self.on_order(order) + def send_order(self, req: OrderRequest): """""" symbol = convert_symbol_vt2tiger(req.symbol, req.exchange) @@ -378,7 +453,7 @@ class TigerGateway(BaseGateway): for i in assets: account = AccountData( - accountid=self.tiger_id, + accountid=self.account, balance=float(i.summary.net_liquidation), frozen=0.0, gateway_name=self.gateway_name, @@ -447,7 +522,7 @@ class TigerGateway(BaseGateway): if i.order_type == "LMT": price = i.limit_price else: - price = i.avg_fill_price + price = 0 order = OrderData( symbol=symbol,