//+------------------------------------------------------------------+ //| Recovery Grid Trade.mq4 | //| extraw | //| extraww@gmail.com | //+------------------------------------------------------------------+ #property copyright "extraw" #property link "extraww@gmail.com" #property version "1.60" // manage opened position by magic number #property strict //--- input parameters input string Part1 = "Grid trade settings:"; input int PointsRangeTrade = 2000; input int PointsRangeRecovery = 500; input double VolumeInitial = 1; input int MagicNumber = 54321; input int Slippage = 5; input bool ClosePositionInProfitIfSignalReverse = false; input string Part2 = "Tidane trend settings:"; input int Length = 13; input int Deviation = 3; //--- variables double RangeTrade_Points, RangeRecovery_Points; double Entry1Level, EndTradeTakeProfitLevel, EndTradeStopLossLevel, Entry2Level, Entry3Level, Entry4Level; double Entry2Volume, Entry3Volume, Entry4Volume; color Arrow_Buy = clrGreen, Arrow_Sell = clrRed, Arrow_Close_In_Profit = clrAqua; bool IsHoldingPosition = false; int Trade_Signal = 0; int Trade_Order_Type_Initial = -1; double CompareZeroError = 0.000001; int NumberOfPosition = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- RangeTrade_Points = PointsRangeTrade * MathPow(10, -Digits()); RangeRecovery_Points = PointsRangeRecovery * MathPow(10, -Digits()); Entry2Volume = NormalizeDouble((VolumeInitial * PointsRangeTrade) / (PointsRangeTrade - PointsRangeRecovery), 2); Entry3Volume = NormalizeDouble(((PointsRangeTrade + PointsRangeRecovery) * Entry2Volume - VolumeInitial * PointsRangeTrade) / PointsRangeTrade, 2); Entry4Volume = NormalizeDouble(Entry3Volume * PointsRangeTrade / (PointsRangeTrade - PointsRangeRecovery), 2); Trade_Signal = 0; Trade_Order_Type_Initial = -1; NumberOfPosition = 0; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- if (IsNewBar(Period()) == true) { //Comment("new bar"); // new signal if (TradeSignal() != 0) { //Comment("new signal"); Comment("vol1: " + DoubleToString(VolumeInitial, 2) + "\n" + "vol2: " + DoubleToString(Entry2Volume, 2) + "\n" + "vol3: " + DoubleToString(Entry3Volume, 2) + "\n" + "vol4: " + DoubleToString(Entry4Volume, 2) + "\n"); // if close on profit option is ON if (ClosePositionInProfitIfSignalReverse == true) { // close on profit if there is only one first entry and signal reverse if ((NumberOfPosition == 1) && (Trade_Signal * TradeSignal() < 0)) { if (Trade_Signal < 0) // currently selling { if (Bid < Entry1Level) { bool result; result = CloseOrdersByMagicNumber(MagicNumber); if (result == true) ResetTradeVariable(); } } if (Trade_Signal > 0) // currently buying { if (Bid > Entry1Level) { bool result; result = CloseOrdersByMagicNumber(MagicNumber); if (result == true) ResetTradeVariable(); } } } } // if there is no opened position, open initial position if (NumberOfPosition <= 0) { //Comment("new trade"); Trade_Signal = TradeSignal(); if (Trade_Signal < 0) Trade_Order_Type_Initial = 1; // sell else if (Trade_Signal > 0) Trade_Order_Type_Initial = 0; // buy int result = EntryInitial(Trade_Order_Type_Initial); if (result > 0) NumberOfPosition = 1; } } } // manage positions if (NumberOfPosition > 0) { // if all trades has ended, clear variable to wait for new signal /* if (IsHavingOpenedOrders(MagicNumber) == false) { ResetTradeVariable(); return; } */ // close orders when it reach initial stoploss or takeprofit if (Bid <= MathMin(EndTradeStopLossLevel, EndTradeTakeProfitLevel) || Bid >= MathMax(EndTradeStopLossLevel, EndTradeTakeProfitLevel)) { bool result = CloseOrdersByMagicNumber(MagicNumber); if (result == true) ResetTradeVariable(); return; } // manage opened positions if (NumberOfPosition == 1) // already have 1 entry { if (MathAbs(Bid - Entry2Level) < CompareZeroError) // Bid == Entry2Level { int result = Entry2(Trade_Order_Type_Initial); if (result > 0) NumberOfPosition = 2; } } if (NumberOfPosition == 2) // already have 2 entries { if (MathAbs(Bid - Entry3Level) < CompareZeroError) // Bid == Entry3Level { int result = Entry3(Trade_Order_Type_Initial); if (result > 0) NumberOfPosition = 3; } } if (NumberOfPosition == 3) // already have 3 entries { if (MathAbs(Bid - Entry4Level) < CompareZeroError) // Bid == Entry3Level { int result = Entry4(Trade_Order_Type_Initial); if (result > 0) NumberOfPosition = 4; } } //--- end manage positions } } //+------------------------------------------------------------------+ //| Check new bar function | //+------------------------------------------------------------------+ bool IsNewBar(int period) { static datetime oldtime; datetime newtime = iTime(NULL, period, 0); if (oldtime != newtime) { oldtime = newtime; //printf("newbar"); return(true); } return(false); } //+------------------------------------------------------------------+ //| Initial Entry function | //+------------------------------------------------------------------+ int EntryInitial(int order_type_initial) { //--- int result; color entry_arrow_color; int sign; switch (order_type_initial) { case 0: sign = 1; entry_arrow_color = Arrow_Buy; break; case 1: sign = -1; entry_arrow_color = Arrow_Sell; break; default: return(-1); } Entry1Level = Bid; EndTradeStopLossLevel = Entry1Level - sign * RangeTrade_Points; EndTradeTakeProfitLevel = Entry1Level + sign * RangeTrade_Points; Entry2Level = Entry1Level - sign * RangeRecovery_Points; Entry3Level = Entry1Level; Entry4Level = Entry2Level; result = OrderSend(Symbol(), order_type_initial, VolumeInitial, Entry1Level, Slippage, 0, 0, "1", MagicNumber, 0, entry_arrow_color); return(result); } //+------------------------------------------------------------------+ //| Second Entry function | //+------------------------------------------------------------------+ int Entry2(int order_type_initial) { //--- int result; color entry_arrow_color; int order_type_now; double stoploss, takeprofit; switch (order_type_initial) { case 0: order_type_now = 1; entry_arrow_color = Arrow_Sell; break; case 1: order_type_now = 0; entry_arrow_color = Arrow_Buy; break; default: return(-1); } stoploss = 0; takeprofit = 0; result = OrderSend(Symbol(), order_type_now, Entry2Volume, Entry2Level, Slippage, stoploss, takeprofit, "2", MagicNumber, 0, entry_arrow_color); return(result); } //+------------------------------------------------------------------+ //| Third Entry function | //+------------------------------------------------------------------+ int Entry3(int order_type_initial) { //--- int result; color entry_arrow_color; int order_type_now; double stoploss, takeprofit; switch (order_type_initial) { case 0: order_type_now = 0; entry_arrow_color = Arrow_Buy; break; case 1: order_type_now = 1; entry_arrow_color = Arrow_Sell; break; default: return(-1); } stoploss = 0; takeprofit = 0; result = OrderSend(Symbol(), order_type_now, Entry3Volume, Entry3Level, Slippage, stoploss, takeprofit, "3", MagicNumber, 0, entry_arrow_color); return(result); } //+------------------------------------------------------------------+ //| Fourth Entry function | //+------------------------------------------------------------------+ int Entry4(int order_type_initial) { //--- int result; color entry_arrow_color; int order_type_now; double stoploss, takeprofit; switch (order_type_initial) { case 0: order_type_now = 1; entry_arrow_color = Arrow_Sell; break; case 1: order_type_now = 0; entry_arrow_color = Arrow_Buy; break; default: return(-1); } stoploss = 0; takeprofit = 0; result = OrderSend(Symbol(), order_type_now, Entry4Volume, Entry4Level, Slippage, stoploss, takeprofit, "4", MagicNumber, 0, entry_arrow_color); return(result); } //+------------------------------------------------------------------+ //| Close Initial Position function | //+------------------------------------------------------------------+ int CloseInitialPosition() { bool result = false; for(int i=OrdersTotal()-1;i>=0;i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; // cannot select order => handle next order if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue; // not the order of current chart or order open by EA => handle next order //actualProfit = OrderProfit(); //if (isIncludeAllFees) actualProfit += OrderSwap() + OrderCommission(); if (true) //(actualProfit >= 0) { result = CloseOrder(); if (result == false) Print("Error Close Profit: ", GetLastError()); //result is global variable, get value from closeOrder2() function } } return result; } //+------------------------------------------------------------------+ //| Close Order by Magic number function | //+------------------------------------------------------------------+ int CloseOrdersByMagicNumber(int magic_number) { bool result = false; for(int i=OrdersTotal()-1;i>=0;i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; // cannot select order => handle next order if (OrderSymbol() != Symbol() && OrderMagicNumber() != magic_number) { continue; } else { result = CloseOrder(); if (result == false) Print("Error Close Profit: ", GetLastError()); //result is global variable, get value from closeOrder2() function } } return result; } //+------------------------------------------------------------------+ //| Close Selected Order function | //+------------------------------------------------------------------+ bool CloseOrder() { bool result = false; if (OrderType() == OP_BUY) { result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_BID), Slippage, Arrow_Close_In_Profit); } if (OrderType() == OP_SELL) { result = OrderClose(OrderTicket(), OrderLots(), MarketInfo(Symbol(), MODE_ASK), Slippage, Arrow_Close_In_Profit); } return result; } //+------------------------------------------------------------------+ //| Signal function. Output: -1 == Sell, 1 == Buy, 0 == no signal | //+------------------------------------------------------------------+ int TradeSignal() { double previous_signal, now_signal; previous_signal = iCustom(NULL, PERIOD_CURRENT, "Tidane trend", Length, Deviation, 0.5, 1, 1, 50000, 0, 2); now_signal = iCustom(NULL, PERIOD_CURRENT, "Tidane trend", Length, Deviation, 0.5, 1, 1, 50000, 0, 1); if (previous_signal < 0 && now_signal > 0) return 1; if (previous_signal > 0 && now_signal < 0) return -11; return 0; } //+------------------------------------------------------------------+ //| Reset variable function | //+------------------------------------------------------------------+ void ResetTradeVariable() { NumberOfPosition = 0; Trade_Order_Type_Initial = -1; Trade_Signal = 0; Entry2Level = 0; Entry3Level = 0; Entry4Level = 0; return; } //+------------------------------------------------------------------+ //| Check opened orders with magic number function | //+------------------------------------------------------------------+ bool IsHavingOpenedOrders(int magic_number) { for(int i=OrdersTotal()-1;i>=0;i--) { if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; // cannot select order => handle next order if (OrderSymbol() == Symbol() && OrderMagicNumber() == magic_number) return(true); } return(false); } //+------------------------------------------------------------------+