一个简单量化策略回测
实现一个简单的指数定投策略,写一个回测脚本验证一下。策略定投创业板指数(场内ETF,或场外指数基金)一般的定投每期固定金额,而这里采取更激进的方法,每期定投金额随指数降低而增加,即越跌越投(策略详见脚本)获取指数历史行情如何获取历史行情数据? 由于我们是按月定投,只需要获取按月K线图即可。有付费软件和网站当然可以获取历史行情数据,但作为一个打游戏从来不充钱的人,本着能不花钱就不花钱的原则,在网上努
·
实现一个简单的指数定投策略,写一个回测脚本验证一下。
策略
- 定投创业板指数(场内ETF,或场外指数基金)
- 一般的定投每期固定金额,而这里采取更激进的方法,每期定投金额随指数降低而增加,即越跌越投(策略详见脚本)
获取指数历史行情
如何获取历史行情数据? 由于我们是按月定投,只需要获取按月K线图即可。有付费软件和网站当然可以获取历史行情数据,但作为一个打游戏从来不充钱的人,本着能不花钱就不花钱的原则,在网上努力找到了免费的资源。
在浏览器输入https://q.stock.sohu.com/hisHq?code=zs_399006&start=20210101&end=20210825&stat=1&order=A&period=m&callback=historySearchHandler&rt=jsonp&r=0.8391495715053367&0.9677250558488026
- code:合约代码,399006就是深证创业板指数代码
- star, end 分别代表开始、结束日期
- order 表示排序方式,Asce升序
- period 周期?month月K
获得数据格式如下:
historySearchHandler([{"status":0,"hq":[["2021-01-29","2977.32","3128.87","162.61","5.48%","2963.41","3427.44","482663424","212739920.00","-"],["2021-02-26","3134.79","2914.11","-214.76","-6.86%","2887.81","3476.00","327237024","139207552.00","-"],["2021-03-31","2958.53","2758.50","-155.61","-5.34%","2603.94","3023.21","393472384","150975600.00","-"],["2021-04-30","2766.42","3091.40","332.90","12.07%","2711.84","3110.16","318636480","125344720.00","-"],["2021-05-31","3059.58","3309.07","217.67","7.04%","2864.05","3309.75","293336448","123553176.00","-"],["2021-06-30","3290.53","3477.18","168.11","5.08%","3122.81","3484.19","362395232","159291744.00","-"],["2021-07-30","3486.78","3440.18","-37.00","-1.06%","3157.99","3576.12","453730144","222532864.00","-"],["2021-08-25","3448.26","3348.66","-91.52","-2.66%","3162.76","3569.84","373719520","182940192.00","-"]],"code":"zs_399006","stat":["累计:","2021-01-29至2021-08-25","382.40","12.89%",2603.94,3576.12,3005190656,1316585768,"-"]}])
简单处理一下为Json格式:
{"status":0,"hq":[["2021-01-29","2977.32","3128.87","162.61","5.48%","2963.41","3427.44","482663424","212739920.00","-"],["2021-02-26","3134.79","2914.11","-214.76","-6.86%","2887.81","3476.00","327237024","139207552.00","-"],["2021-03-31","2958.53","2758.50","-155.61","-5.34%","2603.94","3023.21","393472384","150975600.00","-"],["2021-04-30","2766.42","3091.40","332.90","12.07%","2711.84","3110.16","318636480","125344720.00","-"],["2021-05-31","3059.58","3309.07","217.67","7.04%","2864.05","3309.75","293336448","123553176.00","-"],["2021-06-30","3290.53","3477.18","168.11","5.08%","3122.81","3484.19","362395232","159291744.00","-"],["2021-07-30","3486.78","3440.18","-37.00","-1.06%","3157.99","3576.12","453730144","222532864.00","-"],["2021-08-25","3448.26","3348.66","-91.52","-2.66%","3162.76","3569.84","373719520","182940192.00","-"]],"code":"zs_399006","stat":["累计:","2021-01-29至2021-08-25","382.40","12.89%",2603.94,3576.12,3005190656,1316585768,"-"]}
python脚本实现
#!/usr/bin/python3
import sys
import json
import csv
dates = []
prices = []
baseAmt = 1000.0
maxAmt = 10000.0
with open('399006.month.json', 'r') as f:
data = json.load(f)
print("data['status']:", data['status'])
print("data['code']:", data['code'])
#print("data['hq'][0][1]:", data['hq'][0][1])
for hq in data['hq']:
dates.append(hq[0])
prices.append(float(hq[2]))
if len(dates) != len(prices):
print("error: len not equal!")
sys.exit()
# for i in range(len(dates)):
# print("%s %.2f" % (dates[i], prices[i]) )
def quant(start, end, strategy):
res = [] # totalAmt, pnl, maxPnl, minPnl
basePx = 0.0
amounts = []
totalVol = 0.0
totalAmt = 0.0
pnl = 0.0
maxPnl = 0.0
minPnl = 100.0
if start > end or start > len(dates) or start < 0:
return [0,0,0,0]
i = start - 1
while i < end and i < len(dates):
basePx = prices[i] if prices[i] > basePx else basePx
if strategy == "fixed":
amt = baseAmt
elif strategy == "linear":
amt = baseAmt * ( basePx / prices[i] )
elif strategy == "square":
amt = baseAmt * ( basePx / prices[i] ) ** 2
else:
print("unknown strategy: ", strategy)
return [0,0,0,0]
amt = maxAmt if amt > maxAmt else amt
amounts.append(amt)
totalAmt += amt
vol = amt / prices[i]
totalVol += vol
pnl = (totalVol * prices[i] - totalAmt) / totalAmt
maxPnl = pnl if pnl > maxPnl else maxPnl
minPnl = pnl if pnl < minPnl else minPnl
# print("%s %.2f %.2f %.2f %.2f %.2f" %(dates[i], prices[i], basePx, amt, vol, pnl*100))
i += 1
return [totalAmt, totalVol, pnl]
def main():
begin = 1
header = ['beginDate','beginPrice','endPrice','totalAmt','totalVol','pnl','totalAmt','totalVol','pnl','totalAmt','totalVol','pnl']
rows = []
with open('result.csv', 'w') as f:
f_csv = csv.writer(f)
f_csv.writerow(header)
while begin <= len(dates)-36:
row = [dates[begin-1],prices[begin-1],prices[begin+35]]
row += quant(begin,begin+35,"fixed")
row += quant(begin,begin+35,"linear")
row += quant(begin,begin+35,"square")
rows += row
print(row);
begin += 1
f_csv.writerow(row)
'''
res = quant(1,36,"linear")
print("totalAmt:", res[0])
print(" PNL:", res[1]*100)
print(" maxPNL:", res[2]*100)
print(" minPNL:", res[3]*100)
res = quant(1,36,"square")
print("totalAmt:", res[0])
print(" PNL:", res[1]*100)
print(" maxPNL:", res[2]*100)
print(" minPNL:", res[3]*100)
'''
if __name__=="__main__":
main()
结果:
固定定投36个月
定投至今
更多推荐


所有评论(0)