//+------------------------------------------------------------------+ //| PivotPullback.mq5 | //| Copyright 2018, Benjamin Pillet | //| | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, Benjamin Pillet" #property link "" #define VERSION "1.10" #property version VERSION //#include #include "JPBP.mqh" enum SLstrat { SL_FixPoint,//fix amount of points SL_SR1,//S1/R1 SL_SR2,//S2/R2 SL_SR3,//S3/R3 SL_TPratio//ratio of take profit }; enum TPstrat { TP_SLratio,//ratio of stop loss TP_SR1,//S1/R1 or closest pivot line TP_SR2,//S2/R2 or closest pivot line TP_SR3//S3/R3 or closest pivot line }; enum Exit { NoExit,//no other exit than TP/SL InstantEMA1EMA2cross,//instantly exit if EMA1 cross EMA2 InstantEMA1EMA3cross,//instantly exit if EMA1 cross EMA3 DelayEMA1EMA2cross,//exit if EMA1 crossed EMA2 in previous bar DelayEMA1EMA3cross//exit if EMA1 crossed EMA3 in previous bar }; //--- 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 bool NotOneMonday = false; // do not open on Monday input bool CheckPrevPivot = true; //check previous central pivot input bool SR2Check = false;// do not open if price above/below R2/S2 input bool CheckOnlyLowHigh = false; //delay entry input bool CheckEMAsDirection = false; //check the slopes of EMAs input int Ema3Offset = 0; //EMA3 offset input int DiffEMA1EMA2 = 0;//distance between EMA1 and EMA2 input int DiffEMA2EMA3 = 0;//distance between EMA2 and EMA3 //--- exit input parameters input SLstrat SLsetup = SL_SR1;//stop loss policy input int SLpoints = 300; input TPstrat TPsetup = TP_SR1;//take profit policy input TPstrat SafeSetup = TP_SR1;//safe policy input TPstrat TrailingSetup = TP_SLratio;//trailing policy input Exit ExitSetup = NoExit; //exit policy //--- input parameters for indicators input int Ema1Period = 4;//period of EMA1 input int Ema2Period = 15;//period of EMA2 input int Ema3Period = 30;//period of EMA3 input color Ema1Colour = clrRed;//colour of EMA1 input color Ema2Colour = clrYellow;//colour of EMA2 input color Ema3Colour = clrLightGray;//colour of EMA3 //--- global variables string pivotPath = "Shared Projects\\PivotPullback\\PivotPoint.ex5"; string colourMAPath = "Shared Projects\\PivotPullback\\ColourMA.ex5"; datetime expDate; ulong currentOrderTickets[2]; bool orderStatus[2]; datetime baseStartTime; double fprice; double fsl; double ftp; double fvolume; double prevBid; double prevPivot; //---Indicator handle int ema1Handle; int ema2Handle; int ema3Handle; int pivotHandle; //---Indicator buffer double ema1Value[]; double ema2Value[]; double ema3Value[]; double pivotValue[]; double R1[]; double R2[]; double R3[]; double S1[]; double S2[]; double S3[]; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- set indicators ema1Handle = iCustom(_Symbol,TimeFrame,colourMAPath,TimeFrame,Ema1Period,MODE_EMA,Ema1Colour); ema2Handle = iCustom(_Symbol,TimeFrame,colourMAPath,TimeFrame,Ema2Period,MODE_EMA,Ema2Colour); ema3Handle = iCustom(_Symbol,TimeFrame,colourMAPath,TimeFrame,Ema3Period,MODE_EMA,Ema3Colour); //ema1Handle = iMA(_Symbol,TimeFrame,Ema1Period,0,MODE_EMA,PRICE_CLOSE); //ema2Handle = iMA(_Symbol,TimeFrame,Ema2Period,0,MODE_EMA,PRICE_CLOSE); //ema3Handle = iMA(_Symbol,TimeFrame,Ema3Period,0,MODE_EMA,PRICE_CLOSE); pivotHandle = iCustom(_Symbol,TimeFrame,pivotPath); //---Set array as series ArraySetAsSeries(ema1Value,true); ArraySetAsSeries(ema2Value,true); ArraySetAsSeries(ema3Value,true); ArraySetAsSeries(pivotValue,true); ArraySetAsSeries(R1,true); ArraySetAsSeries(S1,true); ArraySetAsSeries(R2,true); ArraySetAsSeries(S2,true); ArraySetAsSeries(R3,true); ArraySetAsSeries(S3,true); //--- 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) { //---release indicators IndicatorRelease(ema1Handle); IndicatorRelease(ema2Handle); IndicatorRelease(ema3Handle); IndicatorRelease(pivotHandle); } //+------------------------------------------------------------------+ //| Custom functions | //+------------------------------------------------------------------+ double SetBuyProfitLimit(TPstrat policy){ double p=0; switch(policy){ case TP_SLratio: p = ask + (bid-fsl)*TpSlRatio; break; case TP_SR1: if(ask < R3[0]){ p = R3[0]; if(ask < R2[0]){ p = R2[0]; if(ask < R1[0]){ p = R1[0]; } } } break; case TP_SR2: if(ask < R3[0]){ p = R3[0]; if(ask < R2[0]){ p = R2[0]; } } break; case TP_SR3: if(ask < R3[0]){ p = R3[0]; } break; } return p; } double SetSellProfitLimit(TPstrat policy){ double p=0; switch(policy){ case TP_SLratio: p = bid - (fsl - ask)*TpSlRatio; break; case TP_SR1: if(bid > S3[0]){ p = S3[0]; if(bid > S2[0]){ p = S2[0]; if(bid > S1[0]){ p = S1[0]; } } } break; case TP_SR2: if(bid > S3[0]){ p = S3[0]; if(bid > S2[0]){ p = S2[0]; } } break; case TP_SR3: if(bid > S3[0]){ p = S3[0]; } break; } return p; } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //---Acquires indicators informations CopyBuffer(ema1Handle,0,0,3,ema1Value); CopyBuffer(ema2Handle,0,0,3,ema2Value); CopyBuffer(ema3Handle,0,0,3,ema3Value); CopyBuffer(pivotHandle,0,0,3,pivotValue); CopyBuffer(pivotHandle,1,0,3,R1); CopyBuffer(pivotHandle,2,0,3,R2); CopyBuffer(pivotHandle,3,0,3,R3); CopyBuffer(pivotHandle,4,0,3,S1); CopyBuffer(pivotHandle,5,0,3,S2); CopyBuffer(pivotHandle,6,0,3,S3); if(today.day_of_year != prevDay){ prevDay = today.day_of_year; prevPivot = pivotValue[1]; } //--- 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 pivotValue[0] && ema2Value[0] > pivotValue[0] && ema3Value[0] > pivotValue[0]; bool buyCondition3 = ema1Value[0] - ema2Value[0] > DiffEMA1EMA2*_Point && ema2Value[0] - ema3Value[0] > DiffEMA2EMA3*_Point; //sell conditions bool sellCondition2 = ema1Value[0] < pivotValue[0] && ema2Value[0] < pivotValue[0] && ema3Value[0] < pivotValue[0]; bool sellCondition3 = ema2Value[0] - ema1Value[0] > DiffEMA1EMA2*_Point && ema3Value[0] - ema2Value[0] > DiffEMA2EMA3*_Point; bool buyCondition1; bool buyCondition4; bool buyCondition5; bool buyCondition6; bool sellCondition1; bool sellCondition4; bool sellCondition5; bool sellCondition6; if(CheckPrevPivot){ buyCondition1 = prevPivot < pivotValue[0]; sellCondition1 = prevPivot > pivotValue[0]; } else{ buyCondition1 = true; sellCondition1 = true; } if(CheckOnlyLowHigh){ buyCondition4 = bar[0].low < ema3Value[0]+Ema3Offset*_Point; sellCondition4 = bar[0].high > ema3Value[0]-Ema3Offset*_Point; } else{ buyCondition4 = prevBid > ema3Value[0]+Ema3Offset*_Point && bid < ema3Value[0]+Ema3Offset*_Point; sellCondition4 = prevBid < ema3Value[0]-Ema3Offset*_Point && bid > ema3Value[0]-Ema3Offset*_Point; } if(CheckEMAsDirection){ buyCondition5 = ema1Value[1] < ema1Value[0] && ema2Value[1] < ema2Value[0] && ema3Value[1] < ema3Value[0]; sellCondition5 = ema1Value[1] > ema1Value[0] && ema2Value[1] > ema2Value[0] && ema3Value[1] > ema3Value[0]; } else{ buyCondition5 = true; sellCondition5 = true; } if(SR2Check){ buyCondition6 = bid < R2[0]; sellCondition6 = bid > S2[0]; } else{ buyCondition6 = true; sellCondition6 = true; } //--- market execution if(spreadOK && onlyOneTrade && notMonday && notSameBar && buyCondition1 && buyCondition2 && buyCondition3 && buyCondition4 && buyCondition5 && buyCondition6){ //set stop loss switch(SLsetup){ case SL_FixPoint: fsl = bid - SLpoints * _Point; break; case SL_SR1: fsl = S1[0]; break; case SL_SR2: fsl = S2[0]; break; case SL_SR3: fsl = S3[0]; break; default: break; } //set take profit ftp = SetBuyProfitLimit(TPsetup); //reset stop loss if TP need to be calculated first if(SLsetup == SL_TPratio){ fsl = bid - (ftp - ask)/TpSlRatio; } //set volume of transaction if(Lots != 0){ fvolume = Lots; } else{ fvolume = LotsCalculator(bid,fsl,accountBalance); } trade.Buy(fvolume,_Symbol,ask,fsl,ftp); lastOpen = bar[0].open; } if(spreadOK && onlyOneTrade && notMonday && notSameBar && sellCondition1 && sellCondition2 && sellCondition3 && sellCondition4 && sellCondition5 && sellCondition6){ //set stop loss switch(SLsetup){ case SL_FixPoint: fsl = ask + SLpoints * _Point; break; case SL_SR1: fsl = R1[0]; break; case SL_SR2: fsl = R2[0]; break; case SL_SR3: fsl = R3[0]; break; default: break; } //set take profit ftp = SetSellProfitLimit(TPsetup); //reset stop loss if TP need to be calculated first if(SLsetup == SL_TPratio){ fsl = ask + (bid - ftp)/TpSlRatio; } //set volume of transaction if(Lots != 0){ fvolume = Lots; } else{ fvolume = LotsCalculator(ask,fsl,accountBalance); } trade.Sell(fvolume,_Symbol,bid,fsl,ftp); lastOpen = bar[0].open; } prevBid = bid; //--- conditional exit if(positionTotal > 0){ switch(ExitSetup){ case InstantEMA1EMA2cross: if(ema1Value[0] < ema2Value[0]){ CloseAllLongPositions(); } else{ CloseAllShortPositions(); } break; case InstantEMA1EMA3cross: if(ema1Value[0] < ema3Value[0]){ CloseAllLongPositions(); } else{ CloseAllShortPositions(); } break; case DelayEMA1EMA2cross: if(ema1Value[1] < ema2Value[1]){ CloseAllLongPositions(); } else{ CloseAllShortPositions(); } break; case DelayEMA1EMA3cross: if(ema1Value[1] < ema3Value[1]){ CloseAllLongPositions(); } else{ CloseAllShortPositions(); } break; default: break; } } //--- safe mode and trailing mode if((SafeMode || TrailingMode)){ //reset arrays if no position if(positionTotal == 0 && arraySize > 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; } } } } } } } } } //+------------------------------------------------------------------+