在 MultiCharts 的回測報表中,有一個欄項,策略分析-績效比率,項下有一個叫做夏普比率的東西,也就是 Sharpe Ratio。我看了它的說明,好像有點懂又不大懂,找了 Google 到的資料,其實我還是不大清楚怎麼算。而為什麼想要算這個呢?因為它可以用來做為各個策略間的績效優劣指標的比較。其實 MC 有內建這個函數,名稱就是 SharpeRatio。只是,我試了多次... 它給我回傳的數值,總是...零! T_T
讀了一本算是入門類的書籍「計量交易」,其中有一個篇章就講了 Sharpe Ratio 的計算,還給了範例,總算是讓我有 fu 了啊!既然,內建的函數總是不給我好臉色看,咱們自己弄一個總行了吧。不過,回測報表上的夏普比率說明是用月權益去計算的,我個人不愛,所以自己做的版本用日權益去做。
為了與內建的函數有所區別,這個自己做的函數名稱,多加一條底線在最前面,自製函數:_SharpeRatio(數值型、自動)。之前分享過一篇文章「陣列偏移」在這裡就用上了。
input:calcDays(Numeric),reInvestment(Numeric),initialMoney(Numeric);
array:equDayend[500](0),dayProfit[500](0);
var:avgDayProfit(0),stddevProfit(0);
var:tradeDays(0),started(0);
if i_marketposition<>0 and started=0 then
begin
tradeDays=1;
started=1;
end;
if sessionlastbar and started=1 then
begin
tradeDays= tradeDays+1;
_arrayShift(equDayend);
equDayend[1]= i_OpenEquity;
_arrayShift(dayProfit);
if equDayend[2]<>0 and reInvestment=1 then
dayProfit[1]= (equDayend[1]-equDayend[2])/equDayend[2];
if initialMoney<>0 and reInvestment=0 then
dayProfit[1]= (equDayend[1]-equDayend[2])/initialMoney;
end;
if tradeDays>calcDays and (reInvestment=0 or reInvestment=1) then
begin
avgDayProfit= Average_a(dayProfit,calcDays);
stddevProfit= StdDevP_a(dayProfit,calcDays);
_SharpeRatio= (avgDayProfit / stddevProfit) * SquareRoot(252);
end;
上面的 code,我簡單的做一些解釋,細節處請自行揣摩,或視你個人需要做修改(比如改成週權益、月權益?)。這個函數有三個參數。第一個:計算近幾個交易日的權益變化。第二個:要被計算的策略是否含有 reinvestment,0表示沒有、1則有。第三個:起始資金的金額。
用 tradeDays 來記錄從有交易訊號的第一天開始到目前有幾個交易日,這用來控制有足夠的統計量去計算 Sharpe Ratio。然後利用兩個陣列來處理每天權益值與變化的紀錄,接著計算統計區間內日權益變化的平均值與標準差。最後把平均值除以標準差後再乘上252的開平方,以求得年化的 Sharpe Ratio。這個計算方法,我是看「計量交易」這本書(page:80)所講述而得到的理解。
接下來,我們來驗證一下這個 fuction 計算出來的數值,是否正確?開一個指標,放到有策略訊號的圖表上。在這裡,我們計算近 50日,無 reinvestment,起始資金 100萬的策略。Print 出來 _SharpRatio 計算出來的數值,與內建函數回傳的,可以看到最後一列 _SharpRatio=1.9852(故意乘上100來輸出,不然小數位只有兩位),而內建計算夏普比率的函數,很不給力的送我...零。
再把 Print 出來的每日權益值,copy 到 Excel 去做一下計算,得到 1.985175453,就當它吻合吧,還有更多小數位就別太計較了。
ps. 疑,無風險利率呢,去哪裡了?因為我們搞期貨的,通常多空都做,不是 buy and hold,所以無風險利率就無視了。另外,那個乘上252開平方的常數,我覺得或許也可以去掉?畢竟 SharpeRatio 是用來作"相對"性比較的,不是個絕對衡量,如果每個策略統計取樣區間一樣大,那麼各自都乘上與不乘同一個常數,有差嗎?