ファイナンス機械学習:バックテストの統計値 練習問題 シャープレシオ
二年間のバックテストの結果、月次リターンの平均が3.6%、標準偏差が0.079%であった時の、日次のリターンと標準偏差は以下の様に計算される。
まず、月次リターンは$${r_m=\frac{Close_{the\_last\_day}-Open_{the\_1st\_day}}{Open_{the\_1st\_day}}\times 100}$$で計算されるから、
日次リターン$${r_d=\displaystyle{\left(1+\frac{r_m}{100}\right)^{1/days\_of\_the\_month }-1}}$$
日次標準偏差$${std_d=std_m/\sqrt{days\_of\_the month}}$$
よって、日次のシャープレシオは、
r_m=3.6
std_m=0.079
r_d=(1+r_m/100.)**(1.0/20)-1
std_d=std_m/20.0**.5
sr=r_d/std_d
print(f'Daily SR:{np.round(sr,3)}')
print(f'Annualized SR:{sr*250**.5}')
から、$${\widehat{SR}=0.1}$$となる。
これから、年率換算SRは、$${1.584}$$が得られる。
この時、リターンの歪度(skewness $${\gamma_3}$$)は0、尖度(kurtosis $${\gamma_4}$$)は3であったとし、PSRを求める。
PSRを求めるコードは、以下の様になる。
import scipy.stats as ss
def getProbSR(sr, sr_, t,skew=0, kurt=3):
z=(sr-sr_)*((t-1)**.5)
z/=(1-skew*sr+(kurt-1)/4.*sr**2)**.5
return(ss.norm.cdf(z))
g3=0
g4=3
T=2*250
PSR=getProbSR(sr,0,T,g3,g4)
print(f'PSR:{np.round(PSR,5)}')
このリターン系列からのPSRは、$${0.9872}$$となる。
また、リターンの歪度(skewness $${\gamma_3}$$)が$${-2.448}$$、尖度(kurtosis $${\gamma_4}$$)は$${10.164}$$であった時の、PSRは$${0.977}$$である。この歪度と尖度で、バックテスト期間が3年間であった場合、PSRは$${0.993}$$となった。
5年間のバックテストがあり、年率換算シャープレシオが2.5、歪度(skewness $${\gamma_3}$$)は-3、尖度(kurtosis $${\gamma_4}$$)は10であった時、日次シャープレシオは$${\widehat{SR}=2.5/\sqrt{250}=0.0707}$$、よって、$${\widehat{PSR}[SR^\ast]=0.997}$$。
試行回数$${K=100}$$、シャープレシオの分散が$${0.5}$$である時、
の収縮ポートフォリオは、期待最大シャープレシオ値を用いて得られる。
import scipy.stats as ss
def getExpectedMaxSR(nTrials, meanSR, stdSR):
#Expected max SR, controlling for SBuMT
emc = 0.477215664901532860606512090082402431042159336 #Euler-Mascheronis Constant
sr0 = (1-emc)*norm.ppf(1-1./nTrials)+emc*norm.ppf(1-(nTrials*np.e)**-1)
sr0 = meanSR + stdSR*sr0
return sr0
def getProbSR(sr, sr_, t,skew=0, kurt=3):
z=(sr-sr_)*((t-1)**.5)
z/=(1-skew*sr+(kurt-1)/4.*sr**2)**.5
return(ss.norm.cdf(z))
def getDeflatedSR(sr, t, Emaxsr, skew=0, kurt=3):
return getProbSR(sr=sr,sr_=Emaxsr,t=t,skew=skew,kurt=kurt)
g3=-3
g4=10
anSR=2.5
sr=anSR/250**.5
sr_=1/250**.5
print(sr,sr_)
K=100
V=(0.5/250)**.5
T=5*250
PSR=getProbSR(sr,sr_,T,g3,g4)
ExpMaxSR=getExpectedMaxSR(K,sr,V)
DSR=getDeflatedSR(sr=sr,t=T,Emaxsr=ExpMaxSR,skew=g3,kurt=g4)
print(f'PSR:{np.round(PSR,3)}')
print(f'ExpMaxSR:{np.round(ExpMaxSR,3)},DeflatedSR:{np.round(DSR,3)}')