diff --git a/examples/vn_trader/run.py b/examples/vn_trader/run.py index fb06ef2a..2ac64511 100644 --- a/examples/vn_trader/run.py +++ b/examples/vn_trader/run.py @@ -3,29 +3,30 @@ from vnpy.event import EventEngine from vnpy.trader.engine import MainEngine from vnpy.trader.ui import MainWindow, create_qapp -# from vnpy.gateway.binance import BinanceGateway -# from vnpy.gateway.bitmex import BitmexGateway -# from vnpy.gateway.futu import FutuGateway -# from vnpy.gateway.ib import IbGateway +from vnpy.gateway.binance import BinanceGateway +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.ctptest import CtptestGateway -# from vnpy.gateway.femas import FemasGateway -# from vnpy.gateway.tiger import TigerGateway -# from vnpy.gateway.oes import OesGateway -# from vnpy.gateway.okex import OkexGateway -# from vnpy.gateway.huobi import HuobiGateway -# from vnpy.gateway.bitfinex import BitfinexGateway -# from vnpy.gateway.onetoken import OnetokenGateway -# from vnpy.gateway.okexf import OkexfGateway +from vnpy.gateway.femas import FemasGateway +from vnpy.gateway.tiger import TigerGateway +from vnpy.gateway.oes import OesGateway +from vnpy.gateway.okex import OkexGateway +from vnpy.gateway.huobi import HuobiGateway +from vnpy.gateway.bitfinex import BitfinexGateway +from vnpy.gateway.onetoken import OnetokenGateway +from vnpy.gateway.okexf import OkexfGateway # from vnpy.gateway.xtp import XtpGateway -# from vnpy.gateway.hbdm import HbdmGateway +from vnpy.gateway.hbdm import HbdmGateway +# from vnpy.gateway.tap import TapGateway -# from vnpy.app.cta_strategy import CtaStrategyApp -# from vnpy.app.csv_loader import CsvLoaderApp +from vnpy.app.cta_strategy import CtaStrategyApp +from vnpy.app.csv_loader import CsvLoaderApp from vnpy.app.algo_trading import AlgoTradingApp -# from vnpy.app.cta_backtester import CtaBacktesterApp -# from vnpy.app.data_recorder import DataRecorderApp -# from vnpy.app.risk_manager import RiskManagerApp +from vnpy.app.cta_backtester import CtaBacktesterApp +from vnpy.app.data_recorder import DataRecorderApp +from vnpy.app.risk_manager import RiskManagerApp def main(): @@ -36,29 +37,30 @@ def main(): main_engine = MainEngine(event_engine) - # main_engine.add_gateway(BinanceGateway) - # main_engine.add_gateway(XtpGateway) + main_engine.add_gateway(BinanceGateway) main_engine.add_gateway(CtpGateway) # main_engine.add_gateway(CtptestGateway) - # main_engine.add_gateway(FemasGateway) - # main_engine.add_gateway(IbGateway) - # main_engine.add_gateway(FutuGateway) - # main_engine.add_gateway(BitmexGateway) - # main_engine.add_gateway(TigerGateway) - # main_engine.add_gateway(OesGateway) - # main_engine.add_gateway(OkexGateway) - # main_engine.add_gateway(HuobiGateway) - # main_engine.add_gateway(BitfinexGateway) - # main_engine.add_gateway(OnetokenGateway) - # main_engine.add_gateway(OkexfGateway) - # main_engine.add_gateway(HbdmGateway) + main_engine.add_gateway(FemasGateway) + main_engine.add_gateway(IbGateway) + main_engine.add_gateway(FutuGateway) + main_engine.add_gateway(BitmexGateway) + main_engine.add_gateway(TigerGateway) + main_engine.add_gateway(OesGateway) + main_engine.add_gateway(OkexGateway) + main_engine.add_gateway(HuobiGateway) + main_engine.add_gateway(BitfinexGateway) + main_engine.add_gateway(OnetokenGateway) + main_engine.add_gateway(OkexfGateway) + main_engine.add_gateway(HbdmGateway) + # main_engine.add_gateway(XtpGateway) + # main_engine.add_gateway(TapGateway) - # main_engine.add_app(CtaStrategyApp) - # main_engine.add_app(CtaBacktesterApp) - # main_engine.add_app(CsvLoaderApp) + main_engine.add_app(CtaStrategyApp) + main_engine.add_app(CtaBacktesterApp) + main_engine.add_app(CsvLoaderApp) main_engine.add_app(AlgoTradingApp) - # main_engine.add_app(DataRecorderApp) - # main_engine.add_app(RiskManagerApp) + main_engine.add_app(DataRecorderApp) + main_engine.add_app(RiskManagerApp) main_window = MainWindow(main_engine, event_engine) main_window.showMaximized() diff --git a/vnpy/app/algo_trading/algos/arbitrage_algo.py b/vnpy/app/algo_trading/algos/arbitrage_algo.py index 02d83786..24228cbd 100644 --- a/vnpy/app/algo_trading/algos/arbitrage_algo.py +++ b/vnpy/app/algo_trading/algos/arbitrage_algo.py @@ -12,7 +12,7 @@ class ArbitrageAlgo(AlgoTemplate): default_setting = { "active_vt_symbol": "", - "passive_vt_symbol": "", + "passive_vt_symbol": "", "spread_up": 0.0, "spread_down": 0.0, "max_pos": 0, @@ -23,8 +23,8 @@ class ArbitrageAlgo(AlgoTemplate): "timer_count", "active_vt_orderid", "passive_vt_orderid", - "net_pos", - "acum_pos" + "active_pos", + "passive_pos" ] def __init__( @@ -43,16 +43,17 @@ class ArbitrageAlgo(AlgoTemplate): self.spread_down = setting["spread_down"] self.max_pos = setting["max_pos"] self.interval = setting["interval"] - + # Variables self.active_vt_orderid = "" self.passive_vt_orderid = "" - self.net_pos = 0 - self.acum_pos = 0 + self.active_pos = 0 + self.passive_pos = 0 self.timer_count = 0 self.subscribe(self.active_vt_symbol) self.subscribe(self.passive_vt_symbol) + self.put_parameters_event() self.put_variables_event() @@ -72,41 +73,44 @@ class ArbitrageAlgo(AlgoTemplate): def on_trade(self, trade: TradeData): """""" - # Update net position volume + # Update pos if trade.direction == Direction.LONG: - self.net_pos += trade.volume - else: - self.net_pos -= trade.volume - - # Update active symbol position - if trade.vt_symbol == self.active_vt_symbol: - if trade.direction == Direction.LONG: - self.acum_pos += trade.volume + if trade.vt_symbol == self.active_vt_symbol: + self.active_pos += trade.volume else: - self.acum_pos -= trade.volume + self.passive_pos += trade.volume + else: + if trade.vt_symbol == self.active_vt_symbol: + self.active_pos -= trade.volume + else: + self.passive_pos -= trade.volume - # Hedge if active symbol traded + # Hedge if active symbol traded if trade.vt_symbol == self.active_vt_symbol: self.hedge() - + self.put_variables_event() def on_timer(self): """""" + # Run algo by fixed interval self.timer_count += 1 if self.timer_count < self.interval: self.put_variables_event() return self.timer_count = 0 + # Cancel all active orders before moving on if self.active_vt_orderid or self.passive_vt_orderid: self.cancel_all() return - - if self.net_pos: + + # Make sure that active leg is fully hedged by passive leg + if (self.active_pos + self.passive_pos) != 0: self.hedge() return - + + # Make sure that tick data of both leg are available active_tick = self.get_tick(self.active_vt_symbol) passive_tick = self.get_tick(self.passive_vt_symbol) if not active_tick or not passive_tick: @@ -116,46 +120,55 @@ class ArbitrageAlgo(AlgoTemplate): spread_bid_price = active_tick.bid_price_1 - passive_tick.ask_price_1 spread_ask_price = active_tick.ask_price_1 - passive_tick.bid_price_1 - spread_bid_volume = min(active_tick.bid_volume_1, passive_tick.ask_volume_1) - spread_ask_volume = min(active_tick.ask_volume_1, passive_tick.bid_volume_1) + spread_bid_volume = min(active_tick.bid_volume_1, + passive_tick.ask_volume_1) + spread_ask_volume = min(active_tick.ask_volume_1, + passive_tick.bid_volume_1) - # Sell condition + self.write_log(f"盘口价差,买:{spread_bid_volume}@{spread_bid_price}") + self.write_log(f"盘口价差,卖:{spread_ask_volume}@{spread_ask_price}") + + # Sell condition if spread_bid_price > self.spread_up: - if self.acum_pos <= -self.max_pos: - return - else: + if self.active_pos > -self.max_pos: + volume = min(spread_bid_volume, + self.active_pos + self.max_pos) + self.active_vt_orderid = self.sell( self.active_vt_symbol, active_tick.bid_price_1, - spread_bid_volume + volume ) # Buy condition elif spread_ask_price < -self.spread_down: - if self.acum_pos >= self.max_pos: - return - else: + if self.active_pos < self.max_pos: + volume = min(spread_ask_volume, + self.max_pos - self.active_pos) + self.active_vt_orderid = self.buy( self.active_vt_symbol, active_tick.ask_price_1, - spread_ask_volume + volume ) + + # Update GUI self.put_variables_event() - + def hedge(self): """""" tick = self.get_tick(self.passive_vt_symbol) - volume = abs(self.net_pos) + volume = -self.active_pos - self.passive_pos - if self.net_pos > 0: - self.passive_vt_orderid = self.sell( - self.passive_vt_symbol, - tick.bid_price_5, - volume - ) - elif self.net_pos < 0: + if volume > 0: self.passive_vt_orderid = self.buy( self.passive_vt_symbol, - tick.ask_price_5, + tick.ask_price_1, volume ) + elif volume < 0: + self.passive_vt_orderid = self.sell( + self.passive_vt_symbol, + tick.bid_price_1, + abs(volume) + ) diff --git a/vnpy/trader/rqdata.py b/vnpy/trader/rqdata.py index 630a82f6..1df27232 100644 --- a/vnpy/trader/rqdata.py +++ b/vnpy/trader/rqdata.py @@ -4,6 +4,7 @@ from typing import List from rqdatac import init as rqdata_init from rqdatac.services.basic import all_instruments as rqdata_all_instruments from rqdatac.services.get_price import get_price as rqdata_get_price +from rqdatac.share.errors import AuthenticationFailed from .setting import SETTINGS from .constant import Exchange, Interval @@ -55,7 +56,7 @@ class RqdataClient: df = rqdata_all_instruments(date=datetime.now()) for ix, row in df.iterrows(): self.symbols.add(row['order_book_id']) - except RuntimeError: + except (RuntimeError, AuthenticationFailed): return False self.inited = True