//+------------------------------------------------------------------+ //| Zig Zag Trader iCustom.mq4 | //| Copyright 2016, MetaQuotes Software Corp. | //| https://www.mql5.com | // Best settings : // SL 100 TP 1500 TS 200 MP 200 BE 200 (LP 0) Theres no need for BE if i use Trailing Stop // SL 100 TP 1500 TS 100 MP 0 // As opposed to the problem with HiLo Trader this EA works On Tick // similar to On Open. //+------------------------------------------------------------------+ #property copyright "Copyright 2016, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property strict // Input variables input int MagicNumber = 101; input int Slippage = 10; input double LotSize = 0.01; input int StopLoss = 150; input int TakeProfit = 1500; input int TrailingStop = 150; input int MinimumProfit = 0; input int MinProfitBE = 0; // Minimum Profit To Break Even input int LockProfit = 0; //---- indicator parameters input int InpDepth=12; // Depth input int InpDeviation=5; // Deviation input int InpBackstep=3; // Backstep //---- indicator dynamic arrays double ExtZigzagBuffer[]; double ExtHighBuffer[]; double ExtLowBuffer[]; // Global variables int gBuyTicket, gSellTicket; //--- globals int ExtLevel=3; // OnTick() event handler void OnTick() { static bool buySwitch = false; static bool sellSwitch = false; // Resizing of dynamic arrays ArrayResize(ExtZigzagBuffer,6); // 2nd parameter is in price and is why ii wont work. 1.09365 is 6 digits for EURUSD ArrayResize(ExtHighBuffer,6); // Not sure why we must use 0 in the dynamic array it doesnt understand anything else? ArrayResize(ExtLowBuffer,6); double ZigZag=0.0; double extremlow=0; double extremhigh=0; int counterZ,i = 0; i = counterZ = 0; while(counterZ < ExtLevel && i < 100) { //--- find lowest low in depth of bars extremlow=Low[iLowest(NULL,0,MODE_LOW,InpDepth,i)]; //--- found extremum is current low if(Low[i] == extremlow) ExtLowBuffer[0]=extremlow; else ExtLowBuffer[0]=0.0; //--- find highest high in depth of bars extremhigh=High[iHighest(NULL,0,MODE_HIGH,InpDepth,i)]; //--- found extremum is current high if(High[i] == extremhigh) ExtHighBuffer[0] = extremhigh; else ExtHighBuffer[0] = 0.0; // Finds zig zag ZigZag = iCustom(_Symbol,_Period,"ZigZag",InpDepth,InpDeviation,InpBackstep,0,i); if(ZigZag != 0.0) counterZ++; // ExtHighBuffer[0] != 0.0 || ExtLowBuffer[0] != 0.0 i++; // We compare our Zig Zag with our ExtLowBuffer[0] or ExtHighBuffer[0] to see which value is found and assign the value to an object double lowestLow = 0.0; double highestHigh = 0.0; if(ZigZag == ExtLowBuffer[0]) lowestLow = ZigZag; else lowestLow = 0.0; if(ZigZag == ExtHighBuffer[0]) highestHigh = ZigZag; else highestHigh = 0.0; // After a 10 bar count we add order/objects int length = 25; int prelength = 9; int period = 0; if(Period() == PERIOD_H1) period = 3600; // 3600 = 1hr (60sec x 60 min) Datetime reads by the second // Pending orders if(i == 11 && highestHigh != 0.0 && Bid < highestHigh && gBuyTicket < 1) // Im only allowing 1 buy order { double orderopenprice = OrderOpenPrice(); // Here I use my bar counting code to hold the price at condition start double pendingBuyPrice = highestHigh; // Create stop and take profit values for our pendingorder parameters double stopLoss = 0, takeProfit = 0; if(StopLoss > 0) stopLoss = pendingBuyPrice - (StopLoss * _Point); // Here we place our SL TP onto the order before its placed if(TakeProfit > 0) takeProfit = pendingBuyPrice + (TakeProfit * _Point); // Verify Buy stop loss & take profit (This stops order send problems when i exclude SLTP) double stopLevel = MarketInfo(_Symbol,MODE_STOPLEVEL) * _Point; RefreshRates(); double upperStopLevel = Ask + stopLevel; // All buystop(pendingorder), selllimit(pendingorder), buytakeprofit and sellstoploss prices must be > upperStopLevel. // Buy if(pendingBuyPrice <= upperStopLevel) { pendingBuyPrice = upperStopLevel + _Point; // buystop (pendingorder) must be > upperStopLevel stopLoss = pendingBuyPrice - (StopLoss * _Point); // Also SL TP must be moved alongwith pendingBuyPrice takeProfit = pendingBuyPrice + (TakeProfit * _Point); } // Open pending buy order gBuyTicket = OrderSend(_Symbol,OP_BUYSTOP,LotSize,pendingBuyPrice,Slippage,stopLoss,takeProfit,"BuyOrder",MagicNumber,0,clrGreen); buySwitch = true; } if(buySwitch) // OrderType() == OP_BUYSTOP { bool buySelect = OrderSelect(gBuyTicket,SELECT_BY_TICKET); // Must select order before i can do anything with it datetime buyOpenTime = OrderOpenTime(); // Finds time at when order was openned for use in iBarShift. double buyorderopenprice = OrderOpenPrice(); int buyBarShiftCount = iBarShift(_Symbol,_Period,buyOpenTime); // Returns the shift of open time resulting in a barcount. Same both tick and open bar test if(Bid > buyorderopenprice) // Try figure out another way of reseting these when stopped out or hit limit. This could be the problem? Bid > buyorderopenprice { gBuyTicket = 0; // Possibly sometimes its making ticket = 0 while its openning order buySwitch = false; } if(buySelect && buyBarShiftCount >= 24 && OrdersTotal() > 0 && OrderType() == OP_BUYSTOP) { bool buyclose = OrderDelete(gBuyTicket,clrGreen); // Possibly sometimes its trying to delete whats already been closed gBuyTicket = 0; buySwitch = false; } } // oneSellTrade < 1 && if(i == 11 && lowestLow != 0.0 && Ask > lowestLow && gSellTicket < 1) { double orderopenprice = OrderOpenPrice(); // Here I use my bar counting code to hold the price at condition start double pendingSellPrice = lowestLow; // Create stop and take profit values for our pendingorder parameters double stopLoss = 0, takeProfit = 0; if(StopLoss > 0) stopLoss = pendingSellPrice + (StopLoss * _Point); // Here we place our SL TP onto the order before its placed if(TakeProfit > 0) takeProfit = pendingSellPrice - (TakeProfit * _Point); // Verify Buy stop loss & take profit (This stops order send problems when i exclude SLTP) double stopLevel = MarketInfo(_Symbol,MODE_STOPLEVEL) * _Point; RefreshRates(); double lowerStopLevel = Bid - stopLevel; // All sellstop(pendingorder), buylimit(pendingorder), selltakeprofit and buystoploss prices must be < lowerStopLevel. // Sell if(pendingSellPrice >= lowerStopLevel) { pendingSellPrice = lowerStopLevel - _Point; // sellstop(pendingorder) must be < lowerStopLevel stopLoss = pendingSellPrice + (StopLoss * _Point); // Also SL TP must be moved alongwith pendingSellPrice takeProfit = pendingSellPrice - (TakeProfit * _Point); } // Open pending sell order gSellTicket = OrderSend(_Symbol,OP_SELLSTOP,LotSize,pendingSellPrice,Slippage,stopLoss,takeProfit,"SellOrder",MagicNumber,0,clrRed); sellSwitch = true; } if(sellSwitch) // OrderType() == OP_SELLSTOP { bool sellSelect = OrderSelect(gSellTicket,SELECT_BY_TICKET); // Must select order before i can do anything with it datetime sellOpenTime = OrderOpenTime(); // Finds time at when order was openned. double sellorderopenprice = OrderOpenPrice(); int sellBarShiftCount = iBarShift(_Symbol,_Period,sellOpenTime); // Returns the shift of open time resulting in a barcount. Same both tick and open bar test if(Ask < sellorderopenprice) { gSellTicket = 0; sellSwitch = false; } if(sellSelect && sellBarShiftCount >= 24 && OrdersTotal() > 0 && OrderType() == OP_SELLSTOP) { bool sellclose = OrderDelete(gSellTicket,clrRed); gSellTicket = 0; sellSwitch = false; } } } // Trailing stop for(int order = 0; order <= OrdersTotal() - 1; order++) { bool select = OrderSelect(order,SELECT_BY_POS); if(TrailingStop > 0 && OrderMagicNumber() == MagicNumber && select == true) { RefreshRates(); // Check buy order trailing stops if(OrderType() == OP_BUY) // For some reason it selects as OP_BUY when the order is OP_BUYSTOP { double trailStopPrice = Bid - (TrailingStop * _Point); trailStopPrice = NormalizeDouble(trailStopPrice,_Digits); double currentStopLoss = NormalizeDouble(OrderStopLoss(),_Digits); // 2nd parameter means how many digits to after decimal to round of by EG 1.11029348 Normalized by 4 is 1.11020000 EG _Digits 0.00001 5dgs on EUR/USD double currentProfit = Bid - OrderOpenPrice(); double minProfit = MinimumProfit * _Point; if(trailStopPrice > currentStopLoss && currentProfit >= minProfit) // EG price is 1.09602 trailstop is 1.09402 stop is 1.09402 So when 1.09402 > 1.09402 its true { // currentProfit = price + 200 so when price > 1.09802 its true bool modify = OrderModify(OrderTicket(),OrderOpenPrice(),trailStopPrice,OrderTakeProfit(),0); } } // Check sell order trailing stops if(OrderType() == OP_SELL) { double trailStopPrice = Ask + (TrailingStop * _Point); trailStopPrice = NormalizeDouble(trailStopPrice,_Digits); double currentStopLoss = NormalizeDouble(OrderStopLoss(),_Digits); double currentProfit = OrderOpenPrice() - Ask; double minProfit = MinimumProfit * _Point; if(trailStopPrice < currentStopLoss && currentProfit >= minProfit) { bool modify = OrderModify(OrderTicket(),OrderOpenPrice(),trailStopPrice,OrderTakeProfit(),0); } } } } //------------- // Break Even //-------------- // Stop Loss, Take Profit & Break Even for(int order = 0; order <= OrdersTotal() - 1; order++) { bool select = OrderSelect(order,SELECT_BY_POS); // Order must be selected before it can be processed. Not sure why it cant be in buy or sell each section? if(MinProfitBE > 0 && OrderType() == OP_BUY) { bool setBreakEvenStop = false; double breakEvenStop = 0; double currentProfit = 0; double orderStopLoss = OrderStopLoss(); double minProfit = MinProfitBE * _Point; // Modify Order For Break Even breakEvenStop = OrderOpenPrice() + (LockProfit * _Point); breakEvenStop = NormalizeDouble(breakEvenStop,_Digits); orderStopLoss = NormalizeDouble(orderStopLoss,_Digits); currentProfit = Bid - OrderOpenPrice(); currentProfit = NormalizeDouble(currentProfit,_Digits); if(breakEvenStop > orderStopLoss && currentProfit >= minProfit) { bool selectBreakEven = OrderModify(OrderTicket(),0,OrderOpenPrice(),OrderTakeProfit(),0); } } if(MinProfitBE > 0 && OrderType() == OP_SELL) { bool setBreakEvenStop = false; double breakEvenStop = 0; double currentProfit = 0; double orderStopLoss = OrderStopLoss(); double minProfit = MinProfitBE * _Point; // Modify Order For Break Even breakEvenStop = OrderOpenPrice() - (LockProfit * _Point); breakEvenStop = NormalizeDouble(breakEvenStop,_Digits); orderStopLoss = NormalizeDouble(orderStopLoss,_Digits); currentProfit = OrderOpenPrice() - Ask; // Remember Bid and Ask are the spread apart if 20pts thats 20pts above Bid line currentProfit = NormalizeDouble(currentProfit,_Digits); if(breakEvenStop < orderStopLoss && currentProfit >= minProfit) { bool selectBreakEven = OrderModify(OrderTicket(),0,OrderOpenPrice(),OrderTakeProfit(),0); } } } } // Batman Settings : // 1) SL 150 TP 1000 MP 10 TS 30 BE 20 Max Spread 60 // Gives PFR 2.99 DD 0.12 181 trades <<< Performs smoothest // 2) SL 200 TP 1500 MP 0 TS 100 BE 50 Max Spread 60 // Gives PFR 1.71 DD 0.22 // Zig Zag Trader iCustom : // 1) SL 150 TP 1000 MP 10 TS 30 BE 20 Max Spread n/a // Gives PFR 3.33 DD 0.10 145 trades // Tests on 1Hr // 2) SL 200 TP 1500 MP 0 TS 100 BE 50 <<< Performs better long term over 5yrs tested still proved the same psotive equity. Some break even patches but // overall the best EA ive coded. // Gives PFR 2.84 DD 0.12 66 Trades £63 // Tests on 5m // 3) SL 50 TP 375 MP 0 TS 25 BE 12 <<< Works but it cut out after 3 months // Optimized over 10/05 - 12/07 // SL 100 // TP 500 // MP 10,20,30,50 // TS 175 // BE 50 // Best PFR 1.60 // Tests on 1m // 3) SL 50 TP 375 MP 0 TS 25 BE 12 <<< Works 561 trades over 6 months // PFR 1.43 DD 0.21 // I tried optimizing but i dont like what it does to my CPU. I had to many permutations. The ones that did work over 11/2 - 11/16 gave // SL 190 // TP 300 // MP 50,30 // TS 25 // BE 50,20,10 // Best combinations // SL 190 TP 300 MP 30 TS 25 BE 10 // PFR 1.62 DD 0.18 591 Trades // PFR 1.42 £44 500 trades // SL 190 TP 300 MP 50 TS 25 BE 50 // PFR 1.23 DD 0.28 587 Trades £58 // For now im going to stick with the 1Hr chart setup like Batman recomendations. Im gettting procrastinated again. // Small problems are i still get occasional delete errors. Only needs fixed if i was to sell the EA. // So it behaves in an almost identical way to Batman. This proves it to me Batman at $300 is a legitimate non Scam EA that ive managed to copy as close as. // And trade with and maybe even sell as my own. // Also why is it that bad Indicators like VJ Sniper get good reviews and good EA's like Bataman get bad to medium reviews? // Is there something dubious about the ratings part of MT4? Putting people of trading? // This shows me to stop going by forum negativity and make your own judgements. Beat that negative psychology ingrained.