Skip to content

Instantly share code, notes, and snippets.

@currencysecrets
Last active February 4, 2017 19:36
Show Gist options
  • Save currencysecrets/3907816 to your computer and use it in GitHub Desktop.
Save currencysecrets/3907816 to your computer and use it in GitHub Desktop.
MQL4: Exit Strategy Tester (Script)
//+------------------------------------------------------------------+
//| Breakout Strategy Tester.mq4 |
//| Copyright 2012, MetaQuotes Software Corp. |
//| http://www.metaquotes.net |
//+------------------------------------------------------------------+
//
// With this script we will be doing the following:
// 1. Get all the trades (be wary of reversal trades!)
// 2.
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"
int TF = PERIOD_H4;
double PL1;
double ROR1;
double riskSize = 100;
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
//----
getTrades();
//----
return(0);
}
//+------------------------------------------------------------------+
void getTrades() {
int tot = OrdersHistoryTotal(), oBar, vIniStop = 6, vExit = 12, ordType, win, winA, trades;
string sym;
double PL = 0;
double PLx = 0;
double pipVal, p, px, DD, DDx, HiPL, HiPLx, ROR, RORx, iniStop, exit, diff, lotSize;
// first we'll progress through the historical trades
for ( int x = 1; x <= vExit; x++ ) {
for ( int ini = 1; ini <= vIniStop; ini++ ) {
// reset all reporting variables
PL = 0; DD = 0; PLx = 0; HiPL = 0; HiPLx = 0; DDx = 0; ROR = 0; RORx = 0; win = 0; trades = 0; winA = 0;
for ( int i = 0; i <= tot; i++ ) {
if ( OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) ) {
if ( OrderType() <= 1 ) {
sym = OrderSymbol();
pipVal = MarketInfo(sym, MODE_TICKVALUE);
oBar = entryBar(sym, OrderOpenTime());
getInitialStop(sym, OrderType(), oBar, OrderOpenPrice(), vIniStop );
iniStop = getInitialStop( sym, OrderType(), oBar, OrderOpenPrice(), ini );
lotSize = calcPositionSize( sym, OrderOpenPrice(), iniStop, riskSize );
exit = testExits(sym, oBar, OrderOpenPrice(), OrderType(), iniStop, x);
if ( OrderType() == OP_BUY ) {
p = (OrderClosePrice() - OrderOpenPrice()) * OrderLots() * (1 / MarketInfo(sym, MODE_POINT)) * pipVal;
px = (exit - OrderOpenPrice()) * lotSize * (1 / MarketInfo(sym, MODE_POINT)) * pipVal;
PL += p;
diff = (exit - OrderOpenPrice()) / (MarketInfo(sym, MODE_TICKSIZE) * 10);
} else if ( OrderType() == OP_SELL ) {
p = (OrderOpenPrice() - OrderClosePrice()) * OrderLots() * (1 / MarketInfo(sym, MODE_POINT)) * pipVal;
px = (OrderOpenPrice() - exit) * lotSize * (1 / MarketInfo(sym, MODE_POINT)) * pipVal;
PL += p;
diff = (OrderOpenPrice() - exit) / (MarketInfo(sym, MODE_TICKSIZE) * 10);
}
if ( px > 0 ) { win += 1; }
trades += 1;
HiPL = MathMax( HiPL, MathMax( 0, PL ));
DD = MathMin( DD, MathMin( 0, PL - HiPL ));
PLx += px;
HiPLx = MathMax( HiPLx, MathMax( 0, PLx ));
DDx = MathMin( DDx, MathMin( 0, PLx - HiPLx ));
ROR += p / riskSize;
RORx += px / riskSize;
// Print( TimeToStr(OrderOpenTime()) + " " + OrderSymbol() + " " + OrderType() +
// " actual P/L=$" + DoubleToStr(OrderProfit(), 2) + " new P/L=$" + DoubleToStr(px, 2) +
// " diff P/L=$" + DoubleToStr(px - OrderProfit(), 2) +
// " actual Qty=" + DoubleToStr(OrderLots(), 2) + " new Qty=" + DoubleToStr(lotSize, 2) +
// " diff Qty=" + DoubleToStr(lotSize - OrderLots(), 2) +
// " actual Exit=" + DoubleToStr(OrderClosePrice(), 5) + " new Exit=" +
// DoubleToStr(exit, 5) + " diff=" + DoubleToStr(diff, 1) );
}
}
}
//Print( "Current P/L = $" + DoubleToStr(PL, 2) + "; ROR = " + DoubleToStr(ROR/tot, 1) + " ; RF = " +
//DoubleToStr( PL / MathAbs(DD), 1) + " ; DD= $" + DoubleToStr(DD, 1) );
Print( "New strategy (ini=" + ini + ";exit=" + x + "): P/L = $" + DoubleToStr(PLx, 2) + "; ROR = " + DoubleToStr(RORx/tot, 1) + " ; RF = " +
DoubleToStr( PLx / MathAbs(DDx), 1) + " ; DDx= $" + DoubleToStr(DDx, 2 ) + " ; S/R = " + DoubleToStr( win * 100 / trades, 0) + " %" );
}
}
}
double calcPositionSize(string sym, double entry, double stop, double risk) {
double dist = MathAbs( entry - stop ) + (MarketInfo(sym, MODE_SPREAD) * MarketInfo(sym, MODE_POINT));
int dec = MathLog(1 / MarketInfo( Symbol(), MODE_LOTSTEP )) / MathLog(10);
double qty = NormalizeDouble((risk / dist) * MarketInfo(sym, MODE_POINT), dec);
return( qty );
}
int entryBar( string sym, datetime entryTime ) {
int result = 0;
int bars = iBars(sym, TF);
for ( int i = bars; i >= 0; i-- ) {
if ( iTime( sym, TF, i ) > entryTime ) {
result = i+1; // entry was the previous bar
break;
}
}
return( result );
}
double getInitialStop( string sym, int type, int entryBar, double oPrice, int version ) {
double result;
int bar, bars;
if ( type == OP_BUY ) {
switch ( version ) {
case 1:
result = iLow(sym, TF, iLowest(sym, TF, MODE_LOW, 2, entryBar+1));
break;
case 2:
result = iLow(sym, TF, iLowest(sym, TF, MODE_LOW, 5, entryBar+1));
break;
case 3:
bars = iBars(sym, TF);
for ( bar = entryBar; bar < bars; bar++ ) {
if ( iLow(sym, TF, bar) > iLow(sym, TF, bar+1) &&
iLow(sym, TF, bar+1) <= iLow(sym, TF, bar+2) ) {
// check if the opening price is below initial stop, if so use min price
if ( oPrice <= iLow(sym, TF, bar+1) ) {
result = iLow(sym, TF, iLowest(sym, TF, MODE_LOW, bar+1 - entryBar, entryBar));
} else {
result = iLow(sym, TF, bar+1);
}
break;
}
}
break;
case 4:
result = iClose(sym, TF, entryBar+1) - iATR(sym, TF, 30, entryBar+1);
break;
case 5:
result = oPrice - (500 * MarketInfo(sym, MODE_POINT));
break;
case 6:
result = iLow(sym, TF, iLowest(sym, TF, MODE_LOW, 30, entryBar+1));
break;
}
} else if ( type == OP_SELL ) {
switch ( version ) {
case 1:
result = iHigh(sym, TF, iHighest(sym, TF, MODE_HIGH, 2, entryBar+1));
break;
case 2:
result = iHigh(sym, TF, iHighest(sym, TF, MODE_HIGH, 5, entryBar+1));
break;
case 3:
bars = iBars(sym, TF);
for( bar = entryBar; bar < bars; bar++ ) {
if ( iHigh(sym, TF, bar) < iHigh(sym, TF, bar+1) &&
iHigh(sym, TF, bar+1) >= iHigh(sym, TF, bar+2) ) {
// if opening price is above initial stop change to use max price
if ( oPrice >= iHigh(sym, TF, bar+1) ) {
result = iHigh(sym, TF, iHighest(sym, TF, MODE_HIGH, bar+1 - entryBar, entryBar));
} else {
result = iHigh(sym, TF, bar+1);
}
break;
}
}
break;
case 4:
result = iClose(sym, TF, entryBar+1) + iATR(sym, TF, 30, entryBar+1);
break;
case 5:
result = oPrice + (500 * MarketInfo(sym, MODE_POINT));
break;
case 6:
result = iHigh(sym, TF, iHighest(sym, TF, MODE_HIGH, 30, entryBar+1));
break;
}
}
return( result );
}
double testExits( string sym, int entryBar, double oPrice, int type, double iStop, int version ) {
double result = iStop;
double trail = iStop;
double swing = iStop;
int i;
switch ( version ) {
case 1:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
if ( iLow(sym, TF, i) > iLow(sym, TF, i+1) && iLow(sym, TF, i+1) <= iLow(sym, TF, i+2) ) {
trail = MathMax( trail, iLow(sym, TF, i+1) );
}
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
if ( iHigh(sym, TF, i) < iHigh(sym, TF, i+1) && iHigh(sym, TF, i+1) >= iHigh(sym, TF, i+2) ) {
trail = MathMin( trail, iHigh(sym, TF, i+1) );
}
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 2:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
if ( iHigh(sym, TF, iHighest(sym, TF, MODE_HIGH, entryBar - i + 1, i)) == iHigh(sym, TF, i) ) {
trail = MathMax( trail, swing );
}
if ( iLow(sym, TF, i) > iLow(sym, TF, i+1) && iLow(sym, TF, i+1) <= iLow(sym, TF, i+2) ) {
swing = iLow(sym, TF, i+1);
}
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
if ( iLow(sym, TF, iLowest(sym, TF, MODE_LOW, entryBar - i + 1, i)) == iLow(sym, TF, i) ) {
trail = MathMin( trail, swing );
}
if ( iHigh(sym, TF, i) < iHigh(sym, TF, i+1) && iHigh(sym, TF, i+1) >= iHigh(sym, TF, i+2) ) {
swing = iHigh(sym, TF, i+1);
}
}
} else if ( i == 0 ) {
result = iClose(sym, TF, i);
break;
}
}
break;
case 3:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
if ( iLow(sym, TF, i) > iLow(sym, TF, i+1) && iLow(sym, TF, i+1) > iLow(sym, TF, i+2) &&
iLow(sym, TF, i+2) <= iLow(sym, TF, i+3) ) {
trail = MathMax( trail, iLow(sym, TF, i+2));
}
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
if ( iHigh(sym, TF, i) < iHigh(sym, TF, i+1) && iHigh(sym, TF, i+1) < iHigh(sym, TF, i+2) &&
iHigh(sym, TF, i+2) >= iHigh(sym, TF, i+3) ) {
trail = MathMin( trail, iHigh(sym, TF, i+2));
}
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 4:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
if ( iLow(sym, TF, i) >= iLow(sym, TF, i+1) && iHigh(sym, TF, i) <= iHigh(sym, TF, i+1) ) {
trail = MathMax( trail, iLow(sym, TF, i+1));
}
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
if ( iHigh(sym, TF, i) <= iHigh(sym, TF, i+1) && iLow(sym, TF, i) >= iLow(sym, TF, i+1) ) {
trail = MathMin( trail, iHigh(sym, TF, i+1));
}
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 5:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
trail = MathMax( trail, iBands(sym,TF,30,0.5,0,MODE_CLOSE,MODE_UPPER, i));
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
trail = MathMin( trail, iBands(sym, TF, 30, 0.5, 0, MODE_CLOSE, MODE_LOWER, i));
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 6:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
trail = MathMax( trail, iLow(sym, TF, iLowest(sym, TF, MODE_LOW, 30, i)));
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
trail = MathMin( trail, iHigh(sym, TF, iHighest(sym, TF, MODE_HIGH, 30, i)));
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 7:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
trail = MathMax( trail, iHigh(sym, TF, iLowest(sym, TF, MODE_HIGH, 30, i)));
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
trail = MathMin( trail, iLow(sym, TF, iHighest(sym, TF, MODE_LOW, 30, i)));
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 8:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
trail = MathMax(trail, iHigh(sym, TF, i) - (5 * iATR(sym, TF, 30, i)));
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
trail = MathMin(trail, iLow(sym, TF, i) + (5 * iATR(sym, TF, 30, i)));
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 9:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
if ( iLow(sym, TF, i) > iLow(sym, TF, i+1) && iHigh(sym, TF, i) < iHigh(sym, TF, i+1) ) {
trail = MathMax( trail, iLow(sym, TF, i+1));
}
if ( iClose(sym, TF, i) < iOpen(sym, TF, i+1) && iClose(sym, TF, i+1) - iOpen(sym, TF, i+1) > (2 * iATR(sym, TF, 30, i+2))) {
trail = MathMax( trail, iLow(sym, TF, i));
}
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
if ( iHigh(sym, TF, i) < iHigh(sym, TF, i+1) && iLow(sym, TF, i) > iLow(sym, TF, i+1) ) {
trail = MathMin( trail, iHigh(sym, TF, i+1));
}
if ( iClose(sym, TF, i) > iOpen(sym, TF, i+1) && iOpen(sym, TF, i+1) - iClose(sym, TF, i+1) > (2 * iATR(sym, TF, 30, i+2))) {
trail = MathMin( trail, iHigh(sym, TF, i));
}
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 10:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
trail = MathMax(trail, iMA(sym, TF, 30, 0, MODE_SMA, MODE_CLOSE, i));
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
trail = MathMin( trail, iMA(sym, TF, 30, 0, MODE_SMA, MODE_CLOSE, i));
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
case 11:
for( i = entryBar-1; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
trail = MathMax(trail,iSAR(sym, TF, 1, 2, i));
}
} else if ( type == OP_SELL ) {
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
trail = MathMin(trail, iSAR(sym, TF, 0.5, 20, i));
}
}
}
break;
case 12:
for(i = entryBar; i >= 0; i-- ) {
if ( type == OP_BUY ) {
if ( i == entryBar ) {
if ( oPrice < (iClose(sym, TF, i) + iOpen(sym, TF, i))/2 ) {
trail = MathMax( trail, iLow(sym, TF, i) );
}
}
if ( getExitPrice(sym, TF, trail, i, TRUE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, TRUE);
break;
} else {
if ( iLow(sym, TF, i) > iLow(sym, TF, i+1) && iLow(sym, TF, i+1) <= iLow(sym, TF, i+2) ) {
trail = MathMax( trail, iLow(sym, TF, i+1) );
}
}
} else if ( type == OP_SELL ) {
if ( i == entryBar ) {
if ( oPrice > (iClose(sym, TF, i) + iOpen(sym, TF, i))/2 ) {
trail = MathMin( trail, iHigh(sym, TF, i) );
}
}
if ( getExitPrice(sym, TF, trail, i, FALSE) > 0 ) {
result = getExitPrice(sym, TF, trail, i, FALSE);
break;
} else {
if ( iHigh(sym, TF, i) < iHigh(sym, TF, i+1) && iHigh(sym, TF, i+1) >= iHigh(sym, TF, i+2) ) {
trail = MathMin( trail, iHigh(sym, TF, i+1) );
}
}
} else if ( i == 0 ) {
result = iClose(sym, TF, 0);
break;
}
}
break;
}
return ( result );
}
double getExitPrice(string sym, int TF, double trail, int bar, bool long) {
double result = 0;
trail = NormalizeDouble(trail, MarketInfo(sym, MODE_DIGITS));
if ( long == TRUE ) {
if ( iLow(sym, TF, bar) <= trail ) {
if ( iOpen(sym, TF, bar) < trail ) {
result = iOpen(sym, TF, bar);
} else {
result = trail;
}
}
} else if ( long == FALSE ) {
if ( iHigh(sym, TF, bar) >= trail ) {
if ( iOpen(sym, TF, bar) > trail ) {
result = iOpen(sym, TF, bar);
} else {
result = trail;
}
}
}
return ( result );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment