//+------------------------------------------------------------------+ //| twoWavesLimits.mq5 | //| Copyright 2018, Benjamin Pillet | //| | //+------------------------------------------------------------------+ #include "JPBP.mqh" enum limitPolicy { passthrough,//pass through closeBeyond,//close beyond }; enum limitUsed { wave1,//use wave 1 limit wave2,//use wave 2 limit }; //--- main input parameters input double Lots = 0; //Lots, 0=compound //--- Entry input parameters input int MaxSpread = 0; //check spread and set a maximum, 0 = no check input bool OnePos = false; //open only one position input limitPolicy EntryPolicy = closeBeyond; //entry policy //--- exit input parameters input int SLpoints = 300; //--- global variables datetime expDate; ulong currentOrderTickets[2]; bool orderStatus[2]; datetime baseStartTime; double fprice; double fsl; double ftp; double fvolume; double prevBid; double w1High; double w1Low; double w2High; double w2Low; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- set variables setVariables(); trade.SetExpertMagicNumber(MagicNumber); arraySize = 0; orderPlaced[0] = false; orderPlaced[1] = false; positionTotal = 0; //--- recovery system //set order placed and base start time for(int i=0; i < OrdersTotal(); i++){ ulong oTicket = OrderGetTicket(i); if(OrderSelect(oTicket)){ if(OrderGetInteger(ORDER_MAGIC) == MagicNumber && OrderGetString(ORDER_SYMBOL) == _Symbol){ baseStartTime = OrderGetInteger(ORDER_TIME_SETUP); timeSet = true; orderPlaced[0] = true; orderPlaced[1] = true; if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP){ currentOrderTickets[0] = oTicket; } else if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP){ currentOrderTickets[1] = oTicket; } } } } //put position back into the system for(int i=0; i< PositionsTotal(); i++){ if(PositionSelectByTicket(PositionGetTicket(i))){ if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol){ positionTotal = positionTotal + 1; AddPosition(); orderPlaced[0] = true; orderPlaced[1] = true; } } } prevPositionTotal = positionTotal; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get market info refreshVariables(); //--- count the number of position opened by this EA and add new position to trailing system positionTotal = 0; for(int i=0; i< PositionsTotal(); i++){ posTicket = PositionGetTicket(i); if(PositionSelectByTicket(posTicket)){ if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetSymbol(i) == _Symbol){ positionTotal = positionTotal + 1; //set parameters if a new position was opened if(positionTotal > prevPositionTotal && (SafeMode || TrailingMode)){ AddPosition(); //adjust safe and trailing if not default policy if(SafeSetup != TP_SLratio && SafeMode){ if(positionType == POSITION_TYPE_BUY){ safeActivationPrice[arrayIndex] = SetBuyProfitLimit(SafeSetup); safeSL[arrayIndex] = NormalisePrice(positionOpenPrice + (positionOpenPrice-positionSL)*SafeSlRatio); } else if(positionType==POSITION_TYPE_SELL){ safeActivationPrice[arrayIndex] = SetSellProfitLimit(SafeSetup); safeSL[arrayIndex] = NormalisePrice(positionOpenPrice - (positionSL-positionOpenPrice)*SafeSlRatio); if(safeSL[arrayIndex]<0)safeSL[arrayIndex] = 0; } if(DrawLines){ ObjectMove(0,"Safe Activation #"+IntegerToString(positionTicket[arrayIndex]),0,0,safeActivationPrice[arrayIndex]); } } if(TrailingSetup != TP_SLratio && TrailingMode){ if(positionType == POSITION_TYPE_BUY){ trailingActivationPrice[arrayIndex] = SetBuyProfitLimit(TrailingSetup); trailingDistance[arrayIndex] = (trailingActivationPrice[arrayIndex]-positionOpenPrice)*(TrailingDistance/100); } else if(positionType==POSITION_TYPE_SELL){ trailingActivationPrice[arrayIndex] = SetSellProfitLimit(TrailingSetup); trailingDistance[arrayIndex] = (positionOpenPrice - trailingActivationPrice[arrayIndex])*(TrailingDistance/100); } if(DrawLines){ ObjectMove(0,"Trailing Activation #"+IntegerToString(positionTicket[arrayIndex]),0,0,trailingActivationPrice[arrayIndex]); } } } } } } //--- remove lines if a position was closed if(positionTotal < prevPositionTotal){ HistorySelect(0,TimeCurrent()); for(int i=0; i 0){ arraySize = 0; prevPositionTotal = 0; ArrayResize(positionTicket,arraySize,10); ArrayResize(safeActivationPrice,arraySize,10); ArrayResize(safeSL,arraySize,10); ArrayResize(trailingActivationPrice,arraySize,10); ArrayResize(trailingDistance,arraySize,10); } //if at least one position is open then follow up and place new SL if conditions are fulfilled if(positionTotal > 0){ for(int i=0; i safeActivationPrice[i] && positionSL < positionOpenPrice){ trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeSL[i],positionTP); positionSL = PositionGetDouble(POSITION_SL); ObjectDelete(0,"Safe Activation #"+IntegerToString(positionTicket[i])); if(orderStatus[1] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){ trade.OrderDelete(currentOrderTickets[1]); orderStatus[1] = false; } } else if(positionType==POSITION_TYPE_SELL && positionCurrentPrice < safeActivationPrice[i] && positionSL > positionOpenPrice){ trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeSL[i],positionTP); positionSL = PositionGetDouble(POSITION_SL); ObjectDelete(0,"Safe Activation #"+IntegerToString(positionTicket[i])); if(orderStatus[0] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){ trade.OrderDelete(currentOrderTickets[0]); orderStatus[0] = false; } } } if(TrailingMode){ if(positionType == POSITION_TYPE_BUY){ trailingSL = NormalisePrice(positionCurrentPrice - trailingDistance[i]); if(trailingSL<0)trailingSL = 0; if(positionCurrentPrice > trailingActivationPrice[i] && positionSL= baseStartTime && CancelOrderOnSL){ trade.OrderDelete(currentOrderTickets[1]); orderStatus[1] = false; } } } else if(positionType==POSITION_TYPE_SELL){ trailingSL = NormalisePrice(positionCurrentPrice + trailingDistance[i]); if(trailingSL<0)trailingSL = 0; if(positionCurrentPrice < trailingActivationPrice[i] && positionSL>trailingSL){ trade.PositionModify(PositionGetInteger(POSITION_TICKET),trailingSL,positionTP); positionSL = PositionGetDouble(POSITION_SL); ObjectDelete(0,"Trailing Activation #"+IntegerToString(positionTicket[i])); if(orderStatus[0] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL){ trade.OrderDelete(currentOrderTickets[0]); orderStatus[0] =false; } } } } } } } } } //+------------------------------------------------------------------+