#动量策略(改进策略请咨询博主)
import pandas as pd
import numpy as np
import datetime as dt
import matplotlib.pyplot as plt
Mdata = pd.read_csv(r'C:\Users\Lenovo\Desktop\work\量化投资\TRD_Mnth.csv')
Mdata.info() #or use Mdata.dtypes
Mdata.head()
Mdata.tail()
Mdata['Trdmnt1']=pd.to_datetime(Mdata.Trdmnt)
Mdata['date2']=Mdata.Trdmnt1.dt.year
Mdata['date3']=Mdata.Trdmnt1.dt.month
Mdata['date']=pd.PeriodIndex(year=Mdata.date2,month=Mdata.date3,day=Mdata.Clsdt, freq="D")
del Mdata['Trdmnt1']
del Mdata['date2']
del Mdata['date3']
del Mdata['Clsdt']
#1.calculate returen_6month
Mdata=Mdata.sort_values(by=['Stkcd','Trdmnt'],ascending=[True,True])
Mdata['ret_lag6']=(Mdata.Mclsprc-Mdata.Mclsprc.shift(6))/Mdata.Mclsprc.shift(6)
Mdata.loc[Mdata.loc[:,'date']<=dt.datetime(2011,6,30),'ret_lag6']=np.NaN
#2.select 10 stocks with highest return_6month
Mdata2=Mdata.dropna(subset=['ret_lag6']).loc[:,['Trdmnt','Stkcd','ret_lag6']]
Mdata2=Mdata2.sort_values(by=['Trdmnt','ret_lag6'],ascending=[True,False])
Mdata2['r_rank']=Mdata2.groupby(['Trdmnt'])['ret_lag6'].rank(ascending=False,method='first')
Mdata3=Mdata2.loc[Mdata2['r_rank']<=10,:]
td=Mdata3.loc[:,['Trdmnt','Stkcd','r_rank']]
td=td.pivot(index='Trdmnt',columns='r_rank',values='Stkcd')
#3.set assets allocation according to holding period
index1=td.index
columns1=td.columns
col=['Asset1','Asset2','Asset3','Asset4','Asset5','Asset6','Asset7','Asset8','Asset9','Asset10','flag']
Allocation=pd.DataFrame(np.empty((len(index1),len(col)),dtype=np.int64),index=td.index,columns=col)
Allocation.iloc[:,:]=np.nan
j=1
i=1
while(j<=len(index1)-1):
Allocation.iloc[j,0:len(columns1)]=td.iloc[j-i,:].values
Allocation.flag[j]=i
j+=1
if i<6:
i+=1
else:
i=1
#4.calculate actural return
R_col=['MReturn1','MReturn2','MReturn3','MReturn4','MReturn5','MReturn6','MReturn7','MReturn8','MReturn9','MReturn10','flag']
MReturn=pd.DataFrame(np.empty((len(index1),len(R_col)),dtype=np.int64),index=td.index,columns=R_col)
MReturn.iloc[:,:]=np.nan
for j in range(1,len(index1)): #不包括len(index1)本身
for i in range(0,len(R_col)):
if i!=len(R_col)-1:
month=index1[j]
stock=Allocation.iloc[j,i]
mr=Mdata[(Mdata.Trdmnt==month) & (Mdata.Stkcd==stock)].Mretwd
if len(mr) ==1:
MReturn.iloc[j,i]=mr.values
else:
MReturn.iloc[j,i]=0 #缺失的return用0代替
else:
MReturn.iloc[j,i]=Allocation.iloc[j,i] #flag
#求(每个配置期内累积收益率+1)和组合净值
CR_col=['CReturn1','CReturn2','CReturn3','CReturn4','CReturn5','CReturn6','CReturn7','CReturn8','CReturn9','CReturn10','flag','NetValue_P']
CReturn=pd.DataFrame(np.empty((len(index1),len(CR_col))),index=td.index,columns=CR_col)
CReturn.iloc[:,:]=np.nan
CReturn.flag=MReturn.flag
f1=lambda x:x+1
MReturn1=MReturn.iloc[:,0:len(columns1)].apply(f1)
CReturn.NetValue_P[0]=100 #假设初始投资额为100
wt0=1/len(columns1)
wt=[wt0]*len(columns1)
for j in range(1,len(index1)):
lag=int(CReturn.flag[j])
if lag==1:
CReturn.iloc[j,0:len(columns1)]=MReturn1.iloc[j,:].values
else:
CReturn.iloc[j,0:len(columns1)]=MReturn1.iloc[j,:].values*CReturn.iloc[j-1,0:len(columns1)].values
CReturn.NetValue_P[j]=CReturn.NetValue_P[j-lag]*(np.average(CReturn.iloc[j,0:len(columns1)].values,weights=wt))
#求月度收益率、年度收益率
CReturn['Return_month']=CReturn['NetValue_P']/CReturn['NetValue_P'].shift(1)-1
CReturn['a']=pd.to_datetime(CReturn.index)
CReturn['b']=CReturn['a'].dt.year
CReturn['c']=CReturn['a'].dt.month
YReturn=CReturn.loc[CReturn['c']==12,['NetValue_P','a','b']]
YReturn['Return_year']= YReturn['NetValue_P']/YReturn['NetValue_P'].shift(1)-1
AveReturn_year=YReturn['Return_year'].mean()
AveReturn_year
#绘图
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei"] #解决中文显示的问题
plt.rcParams['axes.unicode_minus'] = False
ax1=plt.subplot(311)
ax2=plt.subplot(312)
ax3=plt.subplot(313)
plt.subplots_adjust(wspace=0.8,hspace=0.8)
ax1.bar(YReturn['b'],YReturn['Return_year'])
ax1.set_title('中国A股动量策略组合年度收益率柱状图')
ax2.bar(CReturn.index,CReturn['Return_month'],color='y')
ax2.set_title('中国A股动量策略组合月度收益率柱状图')
ax3.plot(CReturn['NetValue_P'],color='k') #净值曲线
ax3.set_title('中国A股动量策略组合净值曲线')