股票量化軟件:赫茲量化軟件中如何評估智能交易測試結(jié)果
首先,我們來談?wù)劀y試程序。在測試開始之前,測試的子系統(tǒng)加載智能交易,設(shè)定用戶指定的先前參量并且調(diào)用init()函數(shù)。隨后通過生成次序測試開始,并且每次都會調(diào)用 start()函數(shù)。當測試的次序耗盡,會調(diào)用 deinit()函數(shù)。這樣,整個交易歷史在測試期間產(chǎn)生測試數(shù)據(jù)。在此時這個智能交易的效率可以進行分析。赫茲量化軟件
CalculateSummary函數(shù)提供以下測試結(jié)果計算,即,在策略測試的標準報告中給出數(shù)據(jù)。
void CalculateSummary(double initial_deposit) ?{ ? int ? ?sequence=0, profitseqs=0, lossseqs=0; ? double sequential=0.0, prevprofit=EMPTY_VALUE, drawdownpercent, drawdown; ? double maxpeak=initial_deposit, minpeak=initial_deposit, balance=initial_deposit; ? int ? ?trades_total=HistoryTotal(); //---- 初始化總結(jié) ? InitializeSummaries(initial_deposit); //---- ? for(int i=0; i<trades_total; i++) ? ? { ? ? ?if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue; ? ? ?int type=OrderType(); ? ? ?//---- 不考慮初始差額 ? ? ?if(i==0 && type==OP_BALANCE) continue; ? ? ?//---- 計算贏利 ? ? ?double profit=OrderProfit()+OrderCommission()+OrderSwap(); ? ? ?balance+=profit; ? ? ?//---- 檢測借款 ? ? ?if(maxpeak<balance) ? ? ? ?{ ? ? ? ? drawdown=maxpeak-minpeak; ? ? ? ? if(maxpeak!=0.0) ? ? ? ? ? { ? ? ? ? ? ?drawdownpercent=drawdown/maxpeak*100.0; ? ? ? ? ? ?if(RelDrawdownPercent<drawdownpercent) ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? RelDrawdownPercent=drawdownpercent; ? ? ? ? ? ? ? RelDrawdown=drawdown; ? ? ? ? ? ? ?} ? ? ? ? ? } ? ? ? ? if(MaxDrawdown<drawdown) ? ? ? ? ? { ? ? ? ? ? ?MaxDrawdown=drawdown; ? ? ? ? ? ?if(maxpeak!=0.0) MaxDrawdownPercent=MaxDrawdown/maxpeak*100.0; ? ? ? ? ? ?else MaxDrawdownPercent=100.0; ? ? ? ? ? } ? ? ? ? maxpeak=balance; ? ? ? ? minpeak=balance; ? ? ? ?} ? ? ?if(minpeak>balance) minpeak=balance; ? ? ?if(MaxLoss>balance) MaxLoss=balance; ? ? ?//---- 僅限市場定單 ? ? ?if(type!=OP_BUY && type!=OP_SELL) continue; ? ? ?SummaryProfit+=profit; ? ? ?SummaryTrades++; ? ? ?if(type==OP_BUY) LongTrades++; ? ? ?else ? ? ? ? ? ? ShortTrades++; ? ? ?//---- 虧損交易 ? ? ?if(profit<0) ? ? ? ?{ ? ? ? ? LossTrades++; ? ? ? ? GrossLoss+=profit; ? ? ? ? if(MinProfit>profit) MinProfit=profit; ? ? ? ? //---- fortune changed ? ? ? ? if(prevprofit!=EMPTY_VALUE && prevprofit>=0) ? ? ? ? ? { ? ? ? ? ? ?if(ConProfitTrades1<sequence || ? ? ? ? ? ? ? (ConProfitTrades1==sequence && ConProfit2<sequential)) ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ConProfitTrades1=sequence; ? ? ? ? ? ? ? ConProfit1=sequential; ? ? ? ? ? ? ?} ? ? ? ? ? ?if(ConProfit2<sequential || ? ? ? ? ? ? ? (ConProfit2==sequential && ConProfitTrades1<sequence)) ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ConProfit2=sequential; ? ? ? ? ? ? ? ConProfitTrades2=sequence; ? ? ? ? ? ? ?} ? ? ? ? ? ?profitseqs++; ? ? ? ? ? ?AvgConWinners+=sequence; ? ? ? ? ? ?sequence=0; ? ? ? ? ? ?sequential=0.0; ? ? ? ? ? } ? ? ? ?} ? ? ?//---- 贏利交易(profit>=0) ? ? ?else ? ? ? ?{ ? ? ? ? ProfitTrades++; ? ? ? ? if(type==OP_BUY) ?WinLongTrades++; ? ? ? ? if(type==OP_SELL) WinShortTrades++; ? ? ? ? GrossProfit+=profit; ? ? ? ? if(MaxProfit<profit) MaxProfit=profit; ? ? ? ? //---- fortune changed ? ? ? ? if(prevprofit!=EMPTY_VALUE && prevprofit<0) ? ? ? ? ? { ? ? ? ? ? ?if(ConLossTrades1<sequence || ? ? ? ? ? ? ? (ConLossTrades1==sequence && ConLoss2>sequential)) ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ConLossTrades1=sequence; ? ? ? ? ? ? ? ConLoss1=sequential; ? ? ? ? ? ? ?} ? ? ? ? ? ?if(ConLoss2>sequential || ? ? ? ? ? ? ? (ConLoss2==sequential && ConLossTrades1<sequence)) ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ConLoss2=sequential; ? ? ? ? ? ? ? ConLossTrades2=sequence; ? ? ? ? ? ? ?} ? ? ? ? ? ?lossseqs++; ? ? ? ? ? ?AvgConLosers+=sequence; ? ? ? ? ? ?sequence=0; ? ? ? ? ? ?sequential=0.0; ? ? ? ? ? } ? ? ? ?} ? ? ?sequence++; ? ? ?sequential+=profit; ? ? ?//---- ? ? ?prevprofit=profit; ? ? } //---- 最終借款檢驗 ? drawdown=maxpeak-minpeak; ? if(maxpeak!=0.0) ? ? { ? ? ?drawdownpercent=drawdown/maxpeak*100.0; ? ? ?if(RelDrawdownPercent<drawdownpercent) ? ? ? ?{ ? ? ? ? RelDrawdownPercent=drawdownpercent; ? ? ? ? RelDrawdown=drawdown; ? ? ? ?} ? ? } ? if(MaxDrawdown<drawdown) ? ? { ? ? ?MaxDrawdown=drawdown; ? ? ?if(maxpeak!=0) MaxDrawdownPercent=MaxDrawdown/maxpeak*100.0; ? ? ?else MaxDrawdownPercent=100.0; ? ? } //---- 考慮最后交易 ? if(prevprofit!=EMPTY_VALUE) ? ? { ? ? ?profit=prevprofit; ? ? ?if(profit<0) ? ? ? ?{ ? ? ? ? if(ConLossTrades1<sequence || ? ? ? ? ? ?(ConLossTrades1==sequence && ConLoss2>sequential)) ? ? ? ? ? { ? ? ? ? ? ?ConLossTrades1=sequence; ? ? ? ? ? ?ConLoss1=sequential; ? ? ? ? ? } ? ? ? ? if(ConLoss2>sequential || ? ? ? ? ? ?(ConLoss2==sequential && ConLossTrades1<sequence)) ? ? ? ? ? { ? ? ? ? ? ?ConLoss2=sequential; ? ? ? ? ? ?ConLossTrades2=sequence; ? ? ? ? ? } ? ? ? ? lossseqs++; ? ? ? ? AvgConLosers+=sequence; ? ? ? ?} ? ? ?else ? ? ? ?{ ? ? ? ? if(ConProfitTrades1<sequence || ? ? ? ? ? ?(ConProfitTrades1==sequence && ConProfit2<sequential)) ? ? ? ? ? { ? ? ? ? ? ?ConProfitTrades1=sequence; ? ? ? ? ? ?ConProfit1=sequential; ? ? ? ? ? } ? ? ? ? if(ConProfit2<sequential || ? ? ? ? ? ?(ConProfit2==sequential && ConProfitTrades1<sequence)) ? ? ? ? ? { ? ? ? ? ? ?ConProfit2=sequential; ? ? ? ? ? ?ConProfitTrades2=sequence; ? ? ? ? ? } ? ? ? ? profitseqs++; ? ? ? ? AvgConWinners+=sequence; ? ? ? ?} ? ? } //---- 收集完畢 ? double dnum, profitkoef=0.0, losskoef=0.0, avgprofit=0.0, avgloss=0.0; //---- 連續(xù)盈利和虧損的平均數(shù) ? dnum=AvgConWinners; ? if(profitseqs>0) AvgConWinners=dnum/profitseqs+0.5; ? dnum=AvgConLosers; ? if(lossseqs>0) ? AvgConLosers=dnum/lossseqs+0.5; //---- 絕對值 ? if(GrossLoss<0.0) GrossLoss*=-1.0; ? if(MinProfit<0.0) MinProfit*=-1.0; ? if(ConLoss1<0.0) ?ConLoss1*=-1.0; ? if(ConLoss2<0.0) ?ConLoss2*=-1.0; //---- 贏利原因 ? if(GrossLoss>0.0) ProfitFactor=GrossProfit/GrossLoss; //----期待盈利 ? if(ProfitTrades>0) avgprofit=GrossProfit/ProfitTrades; ? if(LossTrades>0) ? avgloss ?=GrossLoss/LossTrades; ? if(SummaryTrades>0) ? ? { ? ? ?profitkoef=1.0*ProfitTrades/SummaryTrades; ? ? ?losskoef=1.0*LossTrades/SummaryTrades; ? ? ?ExpectedPayoff=profitkoef*avgprofit-losskoef*avgloss; ? ? } //---- 絕對借款 ? AbsoluteDrawdown=initial_deposit-MaxLoss; ?}
計算正確,機會得知初始化存款額的值 。這樣,在init() 函數(shù)中AccountBalance()函數(shù)必須被調(diào)用,在測試開始時將給出差額。
void init() ?{ ? ExtInitialDeposit=AccountBalance(); ?}
在上面的CalculateSummary 函數(shù)中, 與標準的報告一樣,盈利在當前的存款額中計算。其他交易結(jié)果,像"最大盈利交易" 或 "最大連續(xù)虧損"在贏利基礎(chǔ)上計算,同樣要測量金錢數(shù)。隨后重新以點數(shù)計算贏利。赫茲量化軟件
... ? ? ?//---- 僅限市場定單 ? ? ?if(type!=OP_BUY && type!=OP_SELL) continue; ? ? ?//---- 以點數(shù)計算贏利 ? ? ?profit=(OrderClosePrice()-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT); ? ? ?SummaryProfit+=profit; ...
使用函數(shù)將得到結(jié)果寫入報告文件中。
void WriteReport(string report_name) ?{ ? int handle=FileOpen(report_name,FILE_CSV|FILE_WRITE,'\t'); ? if(handle<1) return; //---- ? FileWrite(handle,"Initial deposit ? ? ? ? ? ",InitialDeposit); ? FileWrite(handle,"Total net profit ? ? ? ? ?",SummaryProfit); ? FileWrite(handle,"Gross profit ? ? ? ? ? ? ?",GrossProfit); ? FileWrite(handle,"Gross loss ? ? ? ? ? ? ? ?",GrossLoss); ? if(GrossLoss>0.0) ? ? ?FileWrite(handle,"Profit factor ? ? ? ? ? ? ",ProfitFactor); ? FileWrite(handle,"Expected payoff ? ? ? ? ? ",ExpectedPayoff); ? FileWrite(handle,"Absolute drawdown ? ? ? ? ",AbsoluteDrawdown); ? FileWrite(handle,"Maximal drawdown ? ? ? ? ?", ? ? ? ? ? ? ? ? ? ? MaxDrawdown, ? ? ? ? ? ? ? ? ? ? StringConcatenate("(",MaxDrawdownPercent,"%)")); ? FileWrite(handle,"Relative drawdown ? ? ? ? ", ? ? ? ? ? ? ? ? ? ? StringConcatenate(RelDrawdownPercent,"%"), ? ? ? ? ? ? ? ? ? ? StringConcatenate("(",RelDrawdown,")")); ? FileWrite(handle,"Trades total ? ? ? ? ? ? ? ? ",SummaryTrades); ? if(ShortTrades>0) ? ? ?FileWrite(handle,"Short positions(won %) ? ?", ? ? ? ? ? ? ? ? ? ? ? ?ShortTrades, ? ? ? ? ? ? ? ? ? ? ? ?StringConcatenate("(",100.0*WinShortTrades/ShortTrades,"%)")); ? if(LongTrades>0) ? ? ?FileWrite(handle,"Long positions(won %) ? ? ", ? ? ? ? ? ? ? ? ? ? ? ?LongTrades, ? ? ? ? ? ? ? ? ? ? ? ?StringConcatenate("(",100.0*WinLongTrades/LongTrades,"%)")); ? if(ProfitTrades>0) ? ? ?FileWrite(handle,"Profit trades (% of total)", ? ? ? ? ? ? ? ? ? ? ? ?ProfitTrades, ? ? ? ? ? ? ? ? ? ? ? ?StringConcatenate("(",100.0*ProfitTrades/SummaryTrades,"%)")); ? if(LossTrades>0) ? ? ?FileWrite(handle,"Loss trades (% of total) ?", ? ? ? ? ? ? ? ? ? ? ? ?LossTrades, ? ? ? ? ? ? ? ? ? ? ? ?StringConcatenate("(",100.0*LossTrades/SummaryTrades,"%)")); ? FileWrite(handle,"Largest profit trade ? ? ?",MaxProfit); ? FileWrite(handle,"Largest loss trade ? ? ? ?",-MinProfit); ? if(ProfitTrades>0) ? ? ?FileWrite(handle,"Average profit trade ? ? ?",GrossProfit/ProfitTrades); ? if(LossTrades>0) ? ? ?FileWrite(handle,"Average loss trade ? ? ? ?",-GrossLoss/LossTrades); ? FileWrite(handle,"Average consecutive wins ?",AvgConWinners); ? FileWrite(handle,"Average consecutive losses",AvgConLosers); ? FileWrite(handle,"Maximum consecutive wins (profit in money)", ? ? ? ? ? ? ? ? ? ? ConProfitTrades1, ? ? ? ? ? ? ? ? ? ? StringConcatenate("(",ConProfit1,")")); ? FileWrite(handle,"Maximum consecutive losses (loss in money)", ? ? ? ? ? ? ? ? ? ? ConLossTrades1, ? ? ? ? ? ? ? ? ? ? StringConcatenate("(",-ConLoss1,")")); ? FileWrite(handle,"Maximal consecutive profit (count of wins)", ? ? ? ? ? ? ? ? ? ? ConProfit2, ? ? ? ? ? ? ? ? ? ? StringConcatenate("(",ConProfitTrades2,")")); ? FileWrite(handle,"Maximal consecutive loss (count of losses)", ? ? ? ? ? ? ? ? ? ? -ConLoss2, ? ? ? ? ? ? ? ? ? ? StringConcatenate("(",ConLossTrades2,")")); //---- ? FileClose(handle); ?}
以下給出范例,如何使用這些函數(shù)生成報告。
void deinit() ?{ ? if(!IsOptimization()) ? ? { ? ? ?if(!IsTesting()) ExtInitialDeposit=CalculateInitialDeposit(); ? ? ?CalculateSummary(ExtInitialDeposit); ? ? ?WriteReport("MACD_Sample_Report.txt"); ? ? } ?}
在上邊的范例中,您能夠看到報告結(jié)果不僅是在測試結(jié)束后生成, 智能交易的運作中。您也許會問如果在終端內(nèi)賬戶歷史沒有全部下載(例如,在賬戶欄中僅下載一個月的賬戶歷史),怎樣獲取初始存款額的大小呢。 CalculateInitialDeposit 函數(shù)將會幫助解決這個問題。赫茲量化軟件