分享本人2017-2019年白银跨期实盘年化7%-15%策略.
比较基础的跨期套利模型,需要注意的重点是:确保双腿交易的速度以及瘸腿的追单处理。
本模型不涉及交易细节的处理,主要是核心逻辑模块。
采用白银品种做跨期主要是基差非常平稳,同时采用众数对上下轨进行控制。
模型代码如下
import time
import numpy as np
from collections import Counter
####
class timer():
def __init__(self):
self._keep_time_list=[]
def keep(self,sec):
self._keep_time_list.append(time.time())
if self._keep_time_list[-1]-self._keep_time_list[0]>=sec:
self._keep_time_list = []
self._keep_time_list.append(time.time())
return 1
else:
return 0
class arbitrage_model():
def __init__(self):
self._turn_smaller_spread_list=[]
self._turn_smaller_spread_basket=[]
self._turn_bigger_spread_list=[]
self._turn_bigger_spread_basket=[]
self._lastprice_list=[]
self._mytimer=timer()
self._UPdata_time_span=60*5
self._turn_smaller_most_spread_list=[]
self._turn_bigger_most_spread_list=[]
self._min_tick=1
#ma run
self._ma_turn_bigger_data_dict={}
self._ma_turn_smaller_data_dict={}
self._min_turn_bigger_data_list=[]
self._min_turn_smaller_data_list=[]
def run(self,highdata_askprice,highdata_bidprice,data_lastprice,lowdata_askprice,lowdata_bidprice):
# signal
# turn to smaller
self._turn_smaller_spread_list.append(highdata_bidprice - lowdata_askprice)
self._turn_smaller_spread_basket.append(highdata_bidprice - lowdata_askprice)
# turn to bigger
self._turn_bigger_spread_list.append(highdata_askprice - lowdata_bidprice)
self._turn_bigger_spread_basket.append(highdata_askprice - lowdata_bidprice)
# get quote_std
self._lastprice_list.append(data_lastprice)
if len(self._lastprice_list) > 200:
quote_std = np.std(self._lastprice_list)
del self._lastprice_list[0]
else:
quote_std = 10
if self._mytimer.keep(self._UPdata_time_span):
turn_smaller_most_spread = Counter(self._turn_smaller_spread_basket).most_common(1)[0][0]
self._turn_smaller_most_spread_list.append(turn_smaller_most_spread)
turn_bigger_most_spread = Counter(self._turn_bigger_spread_basket).most_common(1)[0][0]
self._turn_bigger_most_spread_list.append(turn_bigger_most_spread)
self._turn_smaller_spread_basket = []
self._turn_bigger_spread_basket = []
if len(self._turn_smaller_most_spread_list) > 12 * 2:
del self._turn_smaller_most_spread_list[0]
if len(self._turn_bigger_most_spread_list) > 12 * 2:
del self._turn_bigger_most_spread_list[0]
#signal to smaller
if len(self._turn_smaller_most_spread_list)>0 and max(self._turn_smaller_most_spread_list) <= self._turn_smaller_spread_list[-1] and self._turn_smaller_most_spread_list[-1] + 3 * self._min_tick <= self._turn_smaller_spread_list[-1]:
signal_smaller=1
else:
signal_smaller=0
#signal to bigger
if len(self._turn_bigger_most_spread_list)>0 and self._turn_bigger_spread_list[-1] <= min(self._turn_bigger_most_spread_list) and self._turn_bigger_spread_list[-1] <=self._turn_bigger_most_spread_list[-1] - 3 * self._min_tick:
signal_bigger=1
else:
signal_bigger=0
return quote_std,signal_bigger,signal_smaller
def ma_run(self, highdata_askprice, highdata_bidprice, data_lastprice, lowdata_askprice, lowdata_bidprice):
#signal
#data
self._ma_turn_bigger_data_dict[time.time()]=(highdata_askprice-lowdata_bidprice)
self._ma_turn_smaller_data_dict[time.time()]=(highdata_bidprice-lowdata_askprice)
# get quote_std
self._lastprice_list.append(data_lastprice)
if len(self._lastprice_list) > 200:
quote_std = np.std(self._lastprice_list)
del self._lastprice_list[0]
else:
quote_std = 10
bigger_keys_list=list(self._ma_turn_bigger_data_dict.keys())
#smaller_keys_list=list(self._ma_turn_smaller_data_dict.keys())
if bigger_keys_list[-1]-bigger_keys_list[0]>60*1:
self._min_turn_bigger_data_list.append(sum(list(self._ma_turn_bigger_data_dict.values()))/len(list(self._ma_turn_bigger_data_dict.values())))
self._min_turn_smaller_data_list.append(sum(list(self._ma_turn_smaller_data_dict.values()))/len(list(self._ma_turn_smaller_data_dict.values())))
self._ma_turn_bigger_data_dict = {}
self._ma_turn_smaller_data_dict = {}
signal_bigger=0
signal_smaller=0
min_span=20
if len(self._min_turn_bigger_data_list)>min_span and len(self._min_turn_smaller_data_list)>min_span:
if self._min_turn_bigger_data_list[-1]-sum(self._min_turn_bigger_data_list[-(1+min_span):-1])/min_span<-1.5:
signal_bigger=1
if self._min_turn_smaller_data_list[-1]-sum(self._min_turn_smaller_data_list[-(1+min_span):-1])/min_span>1.5:
signal_smaller=1
return quote_std,signal_bigger,signal_smaller