uqer实现期现套利

核心思想是股指期货和指数的基差会周期性变化,那么贴水的时候持有股指期货,升水的时候持有指数的可交易标的,可以实现套利的目的。

分三步:

  1. 基于分钟行情计算基差;
  2. 上传到有uqer生成交易逻辑,进行回测;
  3. 中间踩了不少坑,时间关系不细说;

总体来说,实现期现套利的过程比较麻烦,bigquant上不能跨品种回测,而uqer普通用户有没有分钟行情数据(但是可以自己上传信号文件实现目的),然后内存太小了,也没法很好的进行后续的参数优化,最终能实现大概10%的年化,16.2%的回撤。

主要是记录一下,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 期现套利
import pandas as pd
start = '2017-01-01' # 回测起始时间
end = '2021-09-22' # 回测结束时间
benchmark = 'ZZ500' # 策略参考标准
universe = ['510500.XSHG'] + ['ICM0'] # 证券池,也可以在这里添加多个证券, M0 主力合约, L0 当月合约
capital_base = 1000000 # 起始资金, 期货和etf各100w
freq = 'm' # 日线策略
refresh_rate = 1 # 每个交易日调仓

# 账户初始化配置
stock_commission = Commission(buycost=0, sellcost=0, unit='perValue')
futures_commission = Commission(buycost=0.000023, sellcost=0.000023, unit='perValue')
slippage = Slippage(value=0, unit='perValue')
#argin_rate = {'IC': 0.20}

accounts = {
'stock_account': AccountConfig(account_type='security', capital_base=capital_base, commission=stock_commission, slippage=slippage),
'futures_account': AccountConfig(account_type='futures', capital_base=capital_base, commission=futures_commission, slippage=slippage)
}

# 读取文件
dt = pd.read_csv('基差_etf1.csv')
dt = dt.set_index('date')

date_list = list()

stock_buy_date = list()
fut_buy_date = list()

stock_sell_date = list()
fut_sell_date = list()

# 贴水阈值
low_value = -20
# 升水阈值
high_value = 15

# 移仓日ic不交易
change_date = list()

def initialize(account):
pass

def handle_data(account):
stock_account = account.get_account('stock_account')
future_account = account.get_account("futures_account")
today = account.now.strftime('%Y-%m-%d')
minu = account.now.strftime('%Y-%m-%d %H:%M:%S')
#print(minu)
#print(type(minu))
if minu not in dt.index:
return
else:
basis = dt.loc[minu].basis
stock_pos = stock_account.get_positions()
future_pos = future_account.get_positions()

# etf
etf = '510500.XSHG'

# 获取主连, 映射
main_contract_IC = account.get_symbol('ICM0')

# 检查是否换合约
if account.mapping_changed('ICM0'):
symbol_before, symbol_after = account.get_rolling_tuple('ICM0')
#rint(symbol_before, 'changed to', symbol_after)
Position = future_account.get_position(symbol_before)
if Position> 0:

#print(minu, ': switch', symbol_before, symbol_after)

future_account.switch_position(symbol_before, symbol_after) #移仓指令
change_date.append(today)

#basis = DataAPI.MktFutIdxBasisGet(secID=u"",ticker=main_contract_IC,beginDate=today,endDate=today,field=['basis'],pandas="1")['basis'].iloc[0]
# 买卖etf
# 升水的时候买etf, 买入后
if basis >= high_value and etf not in stock_account.get_positions() and today not in stock_buy_date:
#print(minu, 'buy etf', basis, account.current_price(etf))
amount = int(stock_account.cash/account.current_price(etf) / 100) * 100
# 计算买入数量
#print('numbers:', amount)
stock_account.order_pct(etf, 0.99)
stock_buy_date.append(today)
#stock_account.order(etf, 10000)
# 贴水的时候卖etf , 卖出后不再卖出
elif basis <= low_value and etf in stock_account.get_positions() and today not in stock_buy_date and today not in stock_sell_date:
#print(minu, 'sell etf', basis, account.current_price(etf))
stock_account.order_to(etf, 0)

stock_sell_date.append(today)

# 买卖期货, 分开写,逻辑清晰一些
if basis >= high_value and main_contract_IC in future_account.get_positions() and today not in fut_sell_date and today not in fut_buy_date and today not in change_date:
# 当天买入后,不再卖出
# 当天卖出后,不再卖出..
#print(minu, 'sell ic', basis, account.current_price(main_contract_IC))
future_account.order(main_contract_IC, -1, 'close')
fut_sell_date.append(today)
elif basis <= low_value and main_contract_IC not in future_account.get_positions() and today not in fut_buy_date and today not in change_date:
# 当天买入后,不再买入
#print(minu, 'buy ic', basis, account.current_price(main_contract_IC))
future_account.order(main_contract_IC, 1, 'open')
fut_buy_date.append(today)
'''
stock_pos = stock_account.get_positions()

print('==========================', minu , '============================================')
print('stock position:')
print(stock_pos)
print('stock cash:')
fut_pos = future_account.get_positions()
print('future position:')
print(fut_pos)
print(stock_account.pending_blotter)
print(account.current_price(etf))
print('---------------------------------------------------------------------------------')
'''
(✪ω✪)