forked from qmhedging/poboquant
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path做空豆粕隐含波动率Short Soymeal IV
157 lines (134 loc) · 7.12 KB
/
做空豆粕隐含波动率Short Soymeal IV
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# coding:utf-8
#!/usr/bin/env python
from PoboAPI import *
import datetime
import numpy as np
#用poboquant python实现,在poboquant上运行,如果有问题 可加群 726895887 咨询
#做空豆粕期权隐含波动率策略,比如你认为豆粕期权隐含波动率随着到期临近会持续下降
#short soybean meal implied volatility, like you believe the IV will decline when expire date appoaching
#开始时间,用于初始化一些参数
def OnStart(context) :
print "system starting..."
#设定一个全局变量品种
g.code1 = "m1901-C-3300.DCE"
g.code0 = "m1901.DCE" #
#订阅实时数据,用于驱动OnQuote事件
SubscribeQuote([g.code1,g.code0])
#订阅K线数据,用于驱动OnBar事件
SubscribeBar(g.code1, BarType.Day)
#登录交易账号,需在主页用户管理中设置账号,并把证券测试替换成您的账户名称
context.myacc = None
if context.accounts.has_key("回测期货") :
print "登录交易账号[回测期货]"
if context.accounts["回测期货"].Login() :
context.myacc = context.accounts["回测期货"]
#实时行情事件,当有新行情出现时调用该事件
def OnQuote(context, code) :
#过滤掉不需要的行情通知
# if code != g.code1 :
# return
# if code != g.code2 :
# return
#获取最新行情
dyndata1 = GetQuote(g.code1)
dyndata0 = GetQuote(g.code0)
tradingtime=GetQuote(g.code0).time
print "tradingtime ",tradingtime
if dyndata1 and dyndata0 :
#.now指最新价,详细属性见API文档
now1 = dyndata1.now
now0 = dyndata0.now
#打印最新价
log.info("m1901c3300最新价: " + str(dyndata1.now))
log.info("m1901最新价: " + str(dyndata1.now))
#获取K线数据
klinedata1 = GetHisData(g.code1, BarType.Day)
klinedata0 = GetHisData(g.code0, BarType.Day)
#打印K线数据,如最新一根K线的收盘价
CalOBJ = CreateCalcObj() #创建一个计算对象
option = PBObj()
#option.StartDate = datetime.datetime(int(tradingtime.year), int(tradingtime.month), int(tradingtime.day))
yearstring=int(tradingtime.year)
#print "yearstring=int(tradingtime.year)",int(tradingtime.year)
monthstring=int(tradingtime.month)
daystring=int(tradingtime.day)
#准备计算期货的历史波动率
if monthstring-1 in [1,3,5,7,8,10,12]:
option.StartDate = datetime.datetime(yearstring,monthstring-1,daystring)
if monthstring-1==2:
if daystring>28:
option.StartDate = datetime.datetime(yearstring,monthstring-1,28)
else:
option.StartDate = datetime.datetime(yearstring,monthstring-1,daystring)
if monthstring-1 in [4,6,9,11]:
if daystring>30:
option.StartDate = datetime.datetime(yearstring,monthstring-1,30)
else:
option.StartDate = datetime.datetime(yearstring,monthstring-1,daystring)
#format (directtion,asset type,asset price,)
option.Count = 30 #计算30天历史波动率
klinedata = GetHisData(g.code0, BarType.Day, option)
#print "len(klinedata) ",len(klinedata)
klist = []
i=0
while i<len(klinedata):
klist.append(klinedata[i].close)
#print "klinedata[i].close",klinedata[i].close
i+=1
if len(klist)>0:
Kl = np.array(klist, dtype=np.double)
HisVola=CalOBJ.GetVolatility(Kl) #得到历史波动率
print "30D HisVola "+str(HisVola)
#cal IV based on 8 paras, refer to https://quant.pobo.net.cn/quant/doc?name=api#%E8%AE%A1%E7%AE%97%E9%9A%90%E5%90%AB%E6%B3%A2%E5%8A%A8%E7%8E%87%E2%80%94getimpliedvolatility
OptDirection=0 # 0 for call, 1 for put
AssetType=2 # 0 for stock opt,1 for etf opt, 2 for futures opt
AssetPrice=now0 # here is the soymeal futures price
print "AssetPrice ",AssetPrice
StrikePrice=3300 # for soymeal opt m1901-C-3300
InterestRate=4.5*0.01 # the risk free interest rate
print "g.code ",g.code0
#dates=GetOptionsLastDates("m1901.DCE")# not working
#dates=GetOptionsLastDates("SR901C6000.CZCE") # not working
#dates=GetOptionsLastDates("510050.SHSE")# working
#dates=GetOptionsLastDates("m1805-C-3300.DCE")
dates=datetime.datetime(2018,12,7) # expire date for m1901 options, if the date is known,should be searchable by GetOptionsLastDates soon.
print "dates of expire ",str(dates)
#ExpireinYear=(GetOptionsLastDates(g.code1) - tradingtime).days / 365.0 # years to expire
ExpireinYear=(dates - tradingtime).days / 365.0 # years to expire
print "ExpireinYear ",ExpireinYear
OptionPrice=now1 # for option price
#calculate the implied volatility
#format (direction,asset type,asset price,strikeprice,HisVola,interest rate,expire year,option price)
print "opt para:"+str(OptDirection)+","+str(AssetType)+","+str(AssetPrice)+","+str(StrikePrice)+","+str(HisVola)+","+str(InterestRate)+","+str(ExpireinYear)+","+str(OptionPrice)
ImpliedVola=CalOBJ.GetImpliedVolatility(OptDirection,AssetType,AssetPrice,StrikePrice,HisVola,InterestRate,ExpireinYear,OptionPrice)
print "Implied Volatility is " + str(ImpliedVola)
bal = context.myacc.AccountBalance #获取账户资金状况
posmargin=bal.MarketValue
pos = context.myacc.GetPositions()
poslength=len(pos)
print "持仓合约数: "+str(poslength)
#如果配置好交易账号了,可以根据条件下单,需把下面中的证券测试账号换成您设置的账号名称
if len(klinedata1) > 1 and ImpliedVola>0.23 and context.myacc and posmargin<100000 :
# 豆粕隐含波动率大于23%就卖出m1901c3300
print "buy open the spread with HisVola"+str(ImpliedVola)
print "trading day "+str(tradingtime)
print "期权持仓市值 "+str(posmargin)
context.myacc.InsertOrder(g.code1, BSType.SellOpen, dyndata1.now, 10)
#context.myacc.InsertOrder(g.code2, BSType.BuyOpen, dyndata2.now, 10)
if len(klinedata1) > 1 and ImpliedVola<0.1 and poslength>0 and context.myacc :
# 豆粕隐含波动率小于10%就买平m1901c3300,获利平仓
print "sell close the spread,take profit "+str(ImpliedVola)
print "trading day "+str(tradingtime)
context.myacc.InsertOrder(g.code1, BSType.BuyClose, dyndata1.now, 10)
#context.myacc.InsertOrder(g.code2, BSType.SellClose, dyndata2.now, 10)
if len(klinedata1) > 1 and ImpliedVola>0.30 and poslength>0 and context.myacc :
# 豆粕隐含波动率大于30%就买平m1901c3300,止损平仓
print "sell close the spread,cut loss "+str(ImpliedVola)
print "trading day "+str(tradingtime)
context.myacc.InsertOrder(g.code1, BSType.BuyClose, dyndata1.now, 10)
#context.myacc.InsertOrder(g.code2, BSType.SellClose, dyndata2.now, 10)
#委托回报事件,当有委托回报时调用
def OnOrderChange(context, AccountName, order) :
#打印委托信息,id是编号,volume是数量,详细见API文档
print "委托编号: " + order.id + " 账号名称: " + AccountName
print "Vol: " + str(order.volume) + " Price: " + str(order.price)