量化小白系列之量化神器1–Tushare
tushare ID:444995
量化研究首先得有数据吧,今天初步介绍量化神器-Tushare。官网地址:tushare 关于Tushare,官网已经介绍的很详细了,这里不再赘述。下面我们就利用python获取数据。
量化研究我们使用jupyter作为主战场。不清楚jupyter看anaconda官网:anaconda 下面我根据官网提示,获得东方财富股票的18年到21年的日线数据。其中ts_code就是股票代码,SZ代表是深圳交易所的股票。
import tushare as ts
ts.set_token('your token here')
pro = ts.pro_api('your token here')
df = pro.daily(ts_code='300059.SZ', start_date='20180701', end_date='20210701')
df.head()
df2 = df.iloc[::-1]
df2.to_csv('ex01/ts_code300059.csv')
上面就是对dataframe倒序排列一下,这个纯属个人喜好,有的人就是喜欢正序,那当然可以。 倒序后结果如上所示。
有了数据就该分析啦,我就以经典的MACD为例,当快线上穿慢线买入,当快线下穿慢线卖出,也就是俗称的金叉买入,死叉买入。暂时不考虑实际交易成本,初始仓位1000W。
import pandas as pd
import numpy as np
allocation = 10000000
def cal_macd_system(data,short_,long_,m):
'''
data是包含高开低收成交量的标准dataframe
short_,long_,m分别是macd的三个参数
返回值是包含原始数据和diff,dea,macd三个列的dataframe
'''
data['diff']=data['close'].ewm(adjust=False,alpha=2/(short_+1),ignore_na=True).mean()-\
data['close'].ewm(adjust=False,alpha=2/(long_+1),ignore_na=True).mean()
data['dea']=data['diff'].ewm(adjust=False,alpha=2/(m+1),ignore_na=True).mean()
data['macd']=2*(data['diff']-data['dea'])
data.to_csv('ex01/macd.csv')
return data
def intersection(lst_1,lst_2):
insights = [0]
if len(lst_1) > len(lst_2):
settle = len(lst_2)
else:
settle = len(lst_1)
for i in range(settle-1):
if (lst_1[i+1] < lst_2[i+1]) != (lst_1[i] < lst_2[i]):
if ((lst_1[i+1] < lst_2[i+1]),(lst_1[i] < lst_2[i])) == (True,False):
insights.append('sell')
else:
insights.append('buy')
else:
insights.append(0)
return insights
def cal_sig(data):
res = cal_macd_system(data,13,23,9) #计算macd参数
insect_sig = intersection(res['diff'],res['dea'])
insect_sig_set = {'insect_sig':insect_sig}
insect_sig_pd = pd.DataFrame(insect_sig_set)
insect_sig_pd['trade_date'] = data['trade_date']
insect_sig_pd.to_csv('ex01/insect_sig_pd.csv')
trade_sig = list(range(len(res['close'])))
for i in range(len(res['close'])):
number = allocation//res['close'][i]
number_const =1000
if insect_sig[i] == 'buy':
trade_sig[i] = number
elif insect_sig[i] == 'sell':
trade_sig[i] = -number
else:
trade_sig[i] = 0
res['trade_sig'] = trade_sig
res_trade = pd.DataFrame()
res_trade['ts_code'] = res['ts_code']
res_trade['trade_date'] = res['trade_date']
res_trade['trade_sig'] = res['trade_sig']
res_trade['close'] = res['close']
res_trade.to_csv('ex01/trade_sig.csv')
return res_trade
def cal_pos(data):
pos = pd.DataFrame()
pos['ts_code'] = data['ts_code']
pos['trade_date'] = data['trade_date']
res_trade = cal_sig(data)
location_tem = list(range(len(res_trade['trade_sig'])))
location_tem[0] = res_trade['trade_sig'][0]
for i in range(1,len(res_trade['trade_sig'])):
location_tem[i] = location_tem[i-1]+res_trade['trade_sig'][i]
pos['LOCATION'] = location_tem
pos.to_csv('ex01/pos.csv')
return pos
def cal_analyse(trading_sig,data):
D1 = allocation #初始净值
pnl = pd.DataFrame()
pnl['trade_date'] = trading_sig['trade_date'] #定义pnl
pnl['PNL'] = trading_sig['trade_date']
pnl['PNL'][0] =allocation
pos = cal_pos(data)
trading_sig['rate_change'] = (trading_sig['close']-trading_sig['close'].shift(1))/trading_sig['close'].shift(1) #日变化率
for i in range(1,len(pnl['trade_date'])):
pnl['PNL'][i] = pnl['PNL'][i-1] + pos['LOCATION'][i-1]*data['close'][i-1]*trading_sig['rate_change'][i]
X = (pnl['PNL']-pnl['PNL'].shift(1))/D1
X = X.fillna(method = 'bfill')
std = X.std()
X = list(X)
x = np.mean(X)
n = len(pnl['PNL'])
year_std = ((250)**0.5)*std
sharpe = ((250)**0.5)*x/std
Win_percent = sum(i>0 for i in X)/sum(i!=0 for i in X)
if len([i for i in X if i<0]) != 0:
WinLoss_percent = sum(i>0 for i in X)/len([i for i in X if i<0])
else:
WinLoss_percent = 1
MaxDraw = 0
for i in range(len(pnl['PNL'])):
for j in range(len(pnl['PNL'])):
if i>j:
if (pnl['PNL'][i]-pnl['PNL'][j])<MaxDraw:
MaxDraw = (pnl['PNL'][i]-pnl['PNL'][j])
MaxDrawdown = abs(MaxDraw/D1)
years = len(pnl['PNL'])/250
AbsReturn = abs((pnl['PNL'][n-1]-D1)/D1)
Calmar = AbsReturn/(years*MaxDrawdown)
#计算年化收益率
year = n/250
anu_return = AbsReturn/year
cal_analyse = pd.DataFrame()
cal_analyse['para'] = ['sharpe','std', 'year','anu_return','Win_percent','WinLoss_percent','MaxDrawdown','Calmar']
cal_analyse['value'] = [sharpe,std, year,anu_return,Win_percent,WinLoss_percent,MaxDrawdown,Calmar]
pnl.to_csv('ex01/pnl.csv')
cal_analyse.to_csv('ex01/cal_analyse.csv')
return pnl,cal_analyse
def body():
data = pd.read_csv('ex01/ts_code300059.csv')
trading_sig = cal_sig(data)
position = cal_pos(trading_sig)
pnl,data_analyse = cal_analyse(trading_sig,data)
print(data_analyse)
body()
运行结果: 可以看到夏普:0.86,Calmar:1.2,年化收益27.3%,看到这是不是结果很激动啦!
(忘了说,东财期间涨幅近300%。)三年长途有几人坚守住了啊!
为了直观点我们画出收益曲线图。 可以看出,收益稳步向上,也证明了MACD有稳定盈利来源。
大家好,我是小李同学,欢迎一起探讨量化研究的问题!原创不易,点个赞鼓励一下!
对量化,数据分析,科研感兴趣的可以关注我的微信公众号:小李同学314 知乎:小李同学
|