Multicharts 在台灣是很流行的程式交易套裝軟體,強大的回測功能總令人愛不釋手以下是我運用MC開發程式碼與回測的方法
步驟1 : 常見的Donchain Channel策略,搭配一個進場濾網以及一個出場策略
If EntriesToday(Date)=0 then begin
Buy next bar at Highest(High,55) stop;
SellShort next bar at Lowest(Low,55) stop;
End;
If BarsSinceEntry>=8 then begin
Sell next bar at Low stop;
BuyToCover next bar at High stop;
End;
步驟2 : 利用陣列填裝更多類似的通道策略、納入更多的濾網作為備選方案
Inputs:xxL(1),xxS(1);
Inputs:LenExit(8);
Arrays:BreakLong[10](0),BreakShort[10](0);
BreakLong[1]=Highest(High,55);
BreakLong[2]=MaxList(HighD(1),HighD(2),HighD(3));
BreakLong[3]=Average(High,30)+Highest(Range,500);
BreakLong[4]=Average(High,30)+1.85StdDev(High,60); BreakLong[5]=CloseD(1)+1.35(HighD(1)-LowD(1));
BreakLong[6]=OpenD(0)*1.0075;
BreakShort[1]=Lowest(Low,55);
BreakShort[2]=MinList(LowD(1),LowD(2),LowD(3));
BreakShort[3]=Average(Low,30)-Highest(Range,500);
BreakShort[4]=Average(Low,30)-1.85StdDev(Low,60); BreakShort[5]=CloseD(1)-1.35(HighD(1)-LowD(1));
BreakShort[6]=OpenD(0)*0.9925;
If Time>=CalcTime(Sess1StartTime,5BarInterval) then begin
If ADX(21)>ADX(21)[10] then begin
If EntriesToday(Date)=0 then begin
Buy next bar at BreakLong[xxL] stop;
SellShort next bar at BreakShort[xxS] stop;
End;
End;
End;
If BarsSinceEntry>=LenExit then begin
Sell next bar at Low stop;
BuyToCover next bar at High stop;
End;
步驟3 : 運用亂數,決定挑選的配對組合、長度參數、濾網是否啟用
Vars:ii(0),jj(0);
Inputs:Seed(131071);
Arrays:PRNumber[100,250](0);
Vars:MiddleSquare(0),RandomNumber(0);
//Distribution:Entry+Filter
Vars:xxL(1),xxS(1);
Arrays:BreakLong[10](0),BreakShort[10](0);
Arrays:LenLong[100](0),LenShort[100](0),RatioLong[100](0),RatioShort[100](0);
Arrays:LogisticOnOff[100](0),LenTimeLong[100](0),LenTimeShort[100](0);
//Distribution:Exit
Arrays:LenExit[10](0);
//Pseudo Random Parameterics
If CurrentBar=1 then begin
For ii = 1 to 100 begin
PRNumber[ii,0]=Seed+31*(ii-1);
End; //For ii = 1 to 100 begin
For ii = 1 to 100 begin
For jj = 1 to 200 begin
//Pseudo Random Number Middle Square Method
MiddleSquare=IntPortion(Power(PRNumber[ii,jj-1],2)0.001)0.000001;
RandomNumber=1000000*(MiddleSquare-IntPortion(MiddleSquare));
If RandomNumber<90000 then begin //Check Function
MiddleSquare=IntPortion(Power(PRNumber[ii,jj-1]+110011,2)0.001)0.000001;
RandomNumber=1000000*(MiddleSquare-IntPortion(MiddleSquare));
End; //If RandomNumber<90000 then begin //Check Function
PRNumber[ii,jj]=RandomNumber;
End; // For ii = 1 to 100
End; // For jj = 1 to 200
xxL=Mod(PRNumber[1,1],6)+1;
xxS=Mod(PRNumber[1,101],6)+1;
LenLong[1]=Mod(PRNumber[2,1],50)+21;
LenShort[1]=Mod(PRNumber[2,101],50)+21;
LenLong[2]=Mod(PRNumber[2,2],50)+21;
LenShort[2]=Mod(PRNumber[2,102],50)+21;
LenLong[3]=Mod(PRNumber[2,3],300)+350;
LenShort[3]=Mod(PRNumber[2,103],300)+350;
LenLong[4]=Mod(PRNumber[2,4],50)+55;
LenShort[4]=Mod(PRNumber[2,104],50)+55;
LenLong[5]=Mod(PRNumber[2,5],150)+55;
LenShort[5]=Mod(PRNumber[2,105],150)+55;
LenLong[6]=Mod(PRNumber[2,6],15)+15; //ADX
LenShort[6]=Mod(PRNumber[2,106],15)+15; //ADX
LenLong[7]=Mod(PRNumber[2,7],10)+5; //ADX
LenShort[7]=Mod(PRNumber[2,107],10)+5; //ADX
RatioLong[1]=Mod(PRNumber[3,1],150)0.01+1.64; RatioLong[2]=Mod(PRNumber[3,2],80)0.01+0.75;
RatioLong[3]=Mod(PRNumber[3,3],120)0.01+0.55; RatioShort[1]=Mod(PRNumber[3,101],150)0.01+1.64;
RatioShort[2]=Mod(PRNumber[3,102],80)0.01+0.75; RatioShort[3]=Mod(PRNumber[3,103],120)0.01+0.55;
For ii=1 to 100 begin
LogisticOnOff[ii]=Iff(PRNumber[4,ii]>500000,1,0);
End;
LenTimeLong[1]=Mod(PRNumber[5,1],10)+1;
LenTimeShort[1]=Mod(PRNumber[5,101],10)+1;
LenExit[1]=Mod(PRNumber[6,1],10)+5;
End; //If CurrentBar=1 then begin
//BaseInformation : 1 ~ 10
Vars:StartDate(0),TimeLen(0),BP(0);
Vars:Session(1),OpenDFirstBar(1),EndTime(0),OpenDFirstTime(0),IntraDayBarNo(0);
If CurrentBar=1 then begin //BaseInformation*
StartDate=DateToJulian(Date);
TimeLen=BarInterval;
BP=MinMove/PriceScale;
If Session=1 then EndTime=Sess1EndTime;
If Session=2 then EndTime=Sess2EndTime;
If OpenDFirstBar=1 then OpenDFirstTime=Sess1StartTime;
If OpenDFirstBar=2 then OpenDFirstTime=Sess2StartTime;
IntraDayBarNo=IntPortion((TimeToMinutes(EndTime)-TimeToMinutes(OpenDFirstTime))/TimeLen)+1;
End; //CurrentBar=1
//State Case//
Vars:MP(0),Liquidity(False),Price(0),NoBar(0),EEP(0),TN(0);
MP=MarketPosition;
Liquidity=Summation(Range,20)>80BP and Range>5BP and Range[1]>5BP; Price=0.5(High+Low);
NoBar=BarNumber;
EEP=EntryPrice(0);
TN=TotalTrades;
BreakLong[1]=Highest(High,LenLong[1]);
BreakLong[2]=MaxList(HighD(1),HighD(2),HighD(3));
BreakLong[3]=Average(High,LenLong[2])+Highest(Range,LenLong[3]);
BreakLong[4]=Average(High,LenLong[4])+RatioLong[1]StdDev(High,LenLong[5]);
BreakLong[5]=CloseD(1)+RatioLong[2](HighD(1)-LowD(1));
BreakLong[6]=OpenD(0)*RatioLong[3];
BreakShort[1]=Lowest(Low,LenShort[1]);
BreakShort[2]=MinList(LowD(1),LowD(2),LowD(3));
BreakShort[3]=Average(Low,LenShort[2])-Highest(Range,LenShort[3]);
BreakShort[4]=Average(Low,LenShort[4])-RatioShort[1]StdDev(Low,LenShort[5]);
BreakShort[5]=CloseD(1)-RatioShort[2](HighD(1)-LowD(1));
BreakShort[6]=OpenD(0)*RatioShort[3];
ClearDebug;
SetStopContract;
If IFFLogic(LogisticOnOff[1]=0,True,Time>=CalcTime(Sess1StartTime,LenTimeShort[1]BarInterval)) then begin
If IFFLogic(LogisticOnOff[2]=0,True,ADX(LenLong[6])>ADX(LenLong[6])[LenLong[7]]) then begin
If IFFLogic(LogisticOnOff[3]=0,True,EntriesToday(Date)=0) then begin
Buy next bar at BreakLong[xxL] stop;
End; //If EntriesToday(Date)=0 then begin
End; //If ADX(21)>ADX(21)[10] then begin
End; //If Time>=CalcTime(Sess1StartTime,5BarInterval) then begin
If IFFLogic(LogisticOnOff[1]=0,True,Time>=CalcTime(Sess1StartTime,LenTimeLong[1]BarInterval)) then begin
If IFFLogic(LogisticOnOff[2]=0,True,ADX(LenShort[6])>ADX(LenShort[6])[LenShort[7]]) then begin
If IFFLogic(LogisticOnOff[3]=0,True,EntriesToday(Date)=0) then begin
SellShort next bar at BreakShort[xxS] stop;
End; //If EntriesToday(Date)=0 then begin
End; //If ADX(21)>ADX(21)[10] then begin
End; //If Time>=CalcTime(Sess1StartTime,5BarInterval) then begin
If BarsSinceEntry>=LenExit[1] then begin
Sell next bar at Low stop;
BuyToCover next bar at High stop;
End;
步驟4 : 輸出績效文字檔,透過報酬、風險…等指標,排序模組的優劣相關程式碼,請待下篇文章分享