commit
9571bf083e
161
vnpy/app/algo_trading/algos/arbitrage_algo.py
Normal file
161
vnpy/app/algo_trading/algos/arbitrage_algo.py
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
from vnpy.trader.constant import Direction
|
||||||
|
from vnpy.trader.object import TradeData, OrderData
|
||||||
|
from vnpy.trader.engine import BaseEngine
|
||||||
|
|
||||||
|
from vnpy.app.algo_trading import AlgoTemplate
|
||||||
|
|
||||||
|
|
||||||
|
class ArbitrageAlgo(AlgoTemplate):
|
||||||
|
""""""
|
||||||
|
|
||||||
|
display_name = "Arbitrage 套利"
|
||||||
|
|
||||||
|
default_setting = {
|
||||||
|
"active_vt_symbol": "",
|
||||||
|
"passive_vt_symbol": "",
|
||||||
|
"spread_up": 0.0,
|
||||||
|
"spread_down": 0.0,
|
||||||
|
"max_pos": 0,
|
||||||
|
"interval": 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
variables = [
|
||||||
|
"timer_count",
|
||||||
|
"active_vt_orderid",
|
||||||
|
"passive_vt_orderid",
|
||||||
|
"net_pos",
|
||||||
|
"acum_pos"
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
algo_engine: BaseEngine,
|
||||||
|
algo_name: str,
|
||||||
|
setting: dict
|
||||||
|
):
|
||||||
|
""""""
|
||||||
|
super().__init__(algo_engine, algo_name, setting)
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
self.active_vt_symbol = setting["active_vt_symbol"]
|
||||||
|
self.passive_vt_symbol = setting["passive_vt_symbol"]
|
||||||
|
self.spread_up = setting["spread_up"]
|
||||||
|
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.timer_count = 0
|
||||||
|
|
||||||
|
self.subscribe(self.active_vt_symbol)
|
||||||
|
self.subscribe(self.passive_vt_symbol)
|
||||||
|
self.put_parameters_event()
|
||||||
|
self.put_variables_event()
|
||||||
|
|
||||||
|
def on_stop(self):
|
||||||
|
""""""
|
||||||
|
self.write_log("停止算法")
|
||||||
|
|
||||||
|
def on_order(self, order: OrderData):
|
||||||
|
""""""
|
||||||
|
if order.vt_symbol == self.active_vt_symbol:
|
||||||
|
if not order.is_active():
|
||||||
|
self.active_vt_orderid = ""
|
||||||
|
elif order.vt_symbol == self.passive_vt_symbol:
|
||||||
|
if not order.is_active():
|
||||||
|
self.passive_vt_orderid = ""
|
||||||
|
self.put_variables_event()
|
||||||
|
|
||||||
|
def on_trade(self, trade: TradeData):
|
||||||
|
""""""
|
||||||
|
# Update net position volume
|
||||||
|
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
|
||||||
|
else:
|
||||||
|
self.acum_pos -= trade.volume
|
||||||
|
|
||||||
|
# Hedge if active symbol traded
|
||||||
|
if trade.vt_symbol == self.active_vt_symbol:
|
||||||
|
self.hedge()
|
||||||
|
|
||||||
|
self.put_variables_event()
|
||||||
|
|
||||||
|
def on_timer(self):
|
||||||
|
""""""
|
||||||
|
self.timer_count += 1
|
||||||
|
if self.timer_count < self.interval:
|
||||||
|
self.put_variables_event()
|
||||||
|
return
|
||||||
|
self.timer_count = 0
|
||||||
|
|
||||||
|
if self.active_vt_orderid or self.passive_vt_orderid:
|
||||||
|
self.cancel_all()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.net_pos:
|
||||||
|
self.hedge()
|
||||||
|
return
|
||||||
|
|
||||||
|
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:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Calculate spread
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Sell condition
|
||||||
|
if spread_bid_price > self.spread_up:
|
||||||
|
if self.acum_pos <= -self.max_pos:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.active_vt_orderid = self.sell(
|
||||||
|
self.active_vt_symbol,
|
||||||
|
active_tick.bid_price_1,
|
||||||
|
spread_bid_volume
|
||||||
|
)
|
||||||
|
|
||||||
|
# Buy condition
|
||||||
|
elif spread_ask_price < -self.spread_down:
|
||||||
|
if self.acum_pos >= self.max_pos:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.active_vt_orderid = self.buy(
|
||||||
|
self.active_vt_symbol,
|
||||||
|
active_tick.ask_price_1,
|
||||||
|
spread_ask_volume
|
||||||
|
)
|
||||||
|
self.put_variables_event()
|
||||||
|
|
||||||
|
def hedge(self):
|
||||||
|
""""""
|
||||||
|
tick = self.get_tick(self.passive_vt_symbol)
|
||||||
|
volume = abs(self.net_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:
|
||||||
|
self.passive_vt_orderid = self.buy(
|
||||||
|
self.passive_vt_symbol,
|
||||||
|
tick.ask_price_5,
|
||||||
|
volume
|
||||||
|
)
|
@ -50,6 +50,7 @@ class AlgoEngine(BaseEngine):
|
|||||||
from .algos.best_limit_algo import BestLimitAlgo
|
from .algos.best_limit_algo import BestLimitAlgo
|
||||||
from .algos.grid_algo import GridAlgo
|
from .algos.grid_algo import GridAlgo
|
||||||
from .algos.dma_algo import DmaAlgo
|
from .algos.dma_algo import DmaAlgo
|
||||||
|
from .algos.arbitrage_algo import ArbitrageAlgo
|
||||||
|
|
||||||
self.add_algo_template(TwapAlgo)
|
self.add_algo_template(TwapAlgo)
|
||||||
self.add_algo_template(IcebergAlgo)
|
self.add_algo_template(IcebergAlgo)
|
||||||
@ -58,6 +59,7 @@ class AlgoEngine(BaseEngine):
|
|||||||
self.add_algo_template(BestLimitAlgo)
|
self.add_algo_template(BestLimitAlgo)
|
||||||
self.add_algo_template(GridAlgo)
|
self.add_algo_template(GridAlgo)
|
||||||
self.add_algo_template(DmaAlgo)
|
self.add_algo_template(DmaAlgo)
|
||||||
|
self.add_algo_template(ArbitrageAlgo)
|
||||||
|
|
||||||
def add_algo_template(self, template: AlgoTemplate):
|
def add_algo_template(self, template: AlgoTemplate):
|
||||||
""""""
|
""""""
|
||||||
|
Loading…
Reference in New Issue
Block a user