上一次談到 蒙地卡羅模擬小樣本內隨機性的問題
隨後來了廣大的迴響,所以今天就來細看一下數據分析
策略原始設定是 勝率31% 賺賠比2.7 ,每次用資金的10%去下注,實驗結果是
即便是期望值大於0的策略
在小樣本內,還是有接近40%會賠錢
依照分類的數據,進行分組並且統計,發現:
1.所有樣本的 MaxDD 都太高了
所以代表預設的10%資金控管是有問題的,這往後有機會再討論
所有樣本的初始本金都是100萬
1000萬以上的天選組就不多說,因為就是運氣超好勝率高,所以爆賺
0~10萬 地獄倒霉鬼組慘到不行 只剩下15%的勝率 所以幾乎把錢賠光
10~50萬 (29%勝率)與 50~100萬(30%勝率) 讓我感到比較意外,因為依照理論來計算期望值
即便在29% 與 30%勝率的期望值下 理論上來說是可以獲利的
10~50 這組期望值 29%*2.7+71%*-1=0.083 >0
50~100 這組期望值 30%*2.7+70%*-1=0.11 >0
策略原始設定期望值 31%*2.7+69%*-1=0.147
10~50 與 50~100這兩組實驗起來是賠錢的,這裡面代表了一件事情
2.期望值不夠高的策略,在小樣本中賠錢機率很高
這跟量化交易一樣,幾乎所有策略在現實狀況中都會開始"退化"
所謂的"退化"就是 策略的勝率降低、 MaxDD增加
這也導致:為什麼回測的時候策略的時候都很棒 ,都可以賺錢
可是上架後,就開始賠錢了,因為策略開始產生"退化"
勝率一降低,就從天選之人變成地獄倒楣鬼
只會變成上架後賠錢那40%
因為跟蒙地卡羅模擬一樣,策略上架不退化就不錯了
難道你還期望勝率會比回測高,可以往天選之人那一邊去?
所以現實中,很難變成天選之人
前幾天有po一篇開槓桿的資金效率問題,談的是很類似的概念
Sharp Ratio 在1.5倍左右,最佳槓桿倍數大概是6倍左右
10%的風險控管代表說槓桿開太大,損益不夠穩定,
所以導致很容易陣亡
回到一個重點
策略不夠好,風險要控制得很嚴格,不然在現實狀況中
小心了,弄不好,你就會成為地獄倒霉鬼!
有興趣研究Python 的可以結合上一次的蒙地卡羅分析研究一下
----------------------------python 程式碼----------------------
import pandas as pd
import numpy as np
import random
import matplotlib.pyplot as plt
r=[]
rpt=pd.DataFrame() #創建紀錄策略參數的DF
bcolnames=['totalm','totalrate','winrate','maxdd','maxconwin','maxconloss','avgconwin','avgconloss']
rpt=pd.DataFrame(np.zeros(1))
rpt.columns=['totalm']
conwin=[]
conloss=[]
for i in range(0,len(bcolnames)):
text="rpt['"+bcolnames[i]+"']=0"
exec(text)
for i in range(0,100):
P=df.iloc[:,i]
cumret=P/100-1
r = P.diff() / P
r1=r.drop([0])
conwin=count_win(r)
conloss=count_loss(r)
rpt.at[i,'winrate']=sum(r1>0)/len(r1)
rpt.at[i,'totalm']=df.iloc[250,i]
rpt.at[i,'totalrate']=df.iloc[250,i]/100-1
rpt.at[i,'maxdd']= MAXDDM(P)*-1
rpt.at[i,'maxconwin']=max(conwin)
rpt.at[i,'maxconloss']=max(conloss)
rpt.at[i,'avgconwin']=np.mean(conwin)
rpt.at[i,'avgconloss']=np.max(conloss)
def count_win(r):
conwin=[]
#r.pop(0)
cur_win=0
max_win=0
for i in r:
if i >0: # 如果当前元素和上一个元素相同,连续出现次数+1,并更新最大值
cur_win += 1
max_win = max((cur_win, max_win))
else: # 不同则刷新计数器
if cur_win!=0:
conwin.append(cur_win )
cur_win = 0
return conwin
def MAXDDM(retm):
highwatermark=np.zeros(len(retm))
drawdown=np.zeros(len(retm))
highwatermark[0]=retm[0]
for i in range(1,len(retm)):
highwatermark[i]=highwatermark[i-1]
highwatermark[i]=max(highwatermark[i],retm[i])
drawdown[i]=(highwatermark[i]-retm[i])/highwatermark[i]
return(max(drawdown))
------------------python 程式碼----------------------