//+------------------------------------------------------------------+ //| SRL.mq5 | //| Benjamin Pillet | //| | //+------------------------------------------------------------------+ #include "base.mqh" enum SLstrat { SL_FixPoint,//fix amount of points SL_LastBarRatio,//based on last bar high-low distance SL_TPratio,//ratio of take profit SL_SR,//base on upper-lower limits }; enum TPstrat { TP_SLratio,//ratio of stop loss TP_SR, TP_Moving }; enum limitPolicy { passthrough,//pass through closeBeyond,//close beyond wave2InsidePass, wave2InsideBeyond, }; enum limitToUse { SR1,//use wave one limits SR2,//use wave two limits highestLowest //use the highest or lowest limits }; //--- 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 input limitToUse LimitToUse = SR1;//limit to use input bool OnePerLimit = true; //open only one time on the same limit //--- exit input parameters input SLstrat SLsetup = SL_FixPoint;//stop loss policy input int SLpoints = 300; input double SLbaseRatio = 2; input TPstrat TPsetup = TP_SLratio;//take profit policy //--- global variables datetime expDate; ulong currentOrderTickets[2]; bool orderStatus[2]; datetime baseStartTime; string indPath = "Shared Projects\\SRL\\SandR.ex5"; double fprice; double fsl; double ftp; double fvolume; int SandRHandle; double R1[]; double R2[]; double S1[]; double S2[]; double upperLimit; double lastupperLimit; double lowerLimit; double lastlowerLimit; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- set variables setVariables(); trade.SetExpertMagicNumber(MagicNumber); arraySize = 0; orderPlaced[0] = false; orderPlaced[1] = false; positionTotal = 0; SandRHandle = iCustom(_Symbol,TimeFrame,indPath,2,50); //---Set array as series ArraySetAsSeries(R1,true); ArraySetAsSeries(R2,true); ArraySetAsSeries(S1,true); ArraySetAsSeries(S2,true); //--- 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) { //--- IndicatorRelease(SandRHandle); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get market info refreshVariables(); //---Acquires indicators informations CopyBuffer(SandRHandle,0,0,3,R1); CopyBuffer(SandRHandle,1,0,3,R2); CopyBuffer(SandRHandle,5,0,3,S1); CopyBuffer(SandRHandle,6,0,3,S2); //--- 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 || TPsetup == TP_Moving)){ AddPosition(); } } } } //--- remove lines if a position was closed if(positionTotal < prevPositionTotal){ HistorySelect(0,TimeCurrent()); for(int i=0; i R1[0]) upperLimit = R2[0] + AddPoint; else upperLimit = R1[0] + AddPoint; if(S2[0] < S1[0]) lowerLimit = S2[0] - AddPoint; else lowerLimit = S1[0] - AddPoint; break; } //general conditions bool notSameBar = lastOpen != bar[0].open; bool onlyOneTrade; bool upperLimitChanged; bool lowerLimitChanged; if(OnePos) onlyOneTrade = positionTotal == 0; else onlyOneTrade = true; if(OnePerLimit){ upperLimitChanged = upperLimit != lastupperLimit; lowerLimitChanged = lowerLimit != lastlowerLimit; } else{ upperLimitChanged = true; lowerLimitChanged = true; } bool bc = false; bool sc = false; if(EntryPolicy == passthrough){ if((prevBid < upperLimit && bid > upperLimit) || (prevBid > lowerLimit && bid < lowerLimit)) bc = true; if((prevBid < upperLimit && bid > upperLimit) || (prevBid > lowerLimit && bid < lowerLimit)) sc = true; } if(EntryPolicy == closeBeyond){ if(bar[1].close > upperLimit && bar[1].open < upperLimit) bc = true; if(bar[1].close < lowerLimit && bar[1].open > lowerLimit) sc = true; } //--- market execution bool upper = false; if(MathAbs(R1[0]-bid) < MathAbs(S1[0]-bid)) upper = true; //buy if(bc && onlyOneTrade && ((upperLimitChanged && upper) || (lowerLimitChanged && !upper))){ //set stoploss switch(SLsetup){ case SL_FixPoint: fsl = bid - SLpoints * _Point; break; case SL_LastBarRatio: fsl = bid - (bar[1].high-bar[1].low)/SLbaseRatio; break; case SL_SR: fsl = bid - (upperLimit - lowerLimit)/SLbaseRatio; break; default: break; } //set take profit switch(TPsetup){ case TP_SLratio: ftp = ask + (bid-fsl)*TpSlRatio; break; } //set volume of transaction if(Lots != 0){ fvolume = Lots; } else{ fvolume = LotsCalculator(bid,fsl,accountBalance); } trade.Buy(fvolume,_Symbol,ask,fsl,ftp); lastupperLimit = upperLimit; } //sell if(sc && onlyOneTrade && ((upperLimitChanged && upper) || (lowerLimitChanged && !upper))){ //set stoploss switch(SLsetup){ case SL_FixPoint: fsl = ask + SLpoints * _Point; break; case SL_LastBarRatio: fsl = ask + (bar[1].high-bar[1].low)/SLbaseRatio; break; case SL_SR: fsl = ask + (upperLimit-lowerLimit)/SLbaseRatio; break; default: break; } //set take profit switch(TPsetup){ case TP_SLratio: ftp = bid - (fsl - ask)*TpSlRatio; break; } //set volume of transaction if(Lots != 0){ fvolume = Lots; } else{ fvolume = LotsCalculator(ask,fsl,accountBalance); } trade.Sell(fvolume,_Symbol,bid,fsl,ftp); lastlowerLimit = lowerLimit; } //--- reset prev variables prevAsk = ask; prevBid = bid; //--- safe mode and trailing mode if((SafeMode || TrailingMode || TPsetup == TP_Moving)){ //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; } } } } /*if(TPsetup == TP_MovingW1){ if(positionType == POSITION_TYPE_BUY && bar[0].open < w1High[0] && positionTP != w1High[0] && w1High[0] != w2High[0]){ //PrintFormat("Hello"); trade.PositionModify(PositionGetInteger(POSITION_TICKET),positionSL,w1High[0]); } if(positionType == POSITION_TYPE_SELL && bar[0].open > w1Low[0] && positionTP != w1Low[0] && w1Low[0] != w2Low[0]){ trade.PositionModify(PositionGetInteger(POSITION_TICKET),positionSL,w1Low[0]); } }*/ /*if(SafeWave){ if(positionType == POSITION_TYPE_BUY){ if(bar[2].close > bar[2].open && bar[1].close < bar[1].open){ safeWaveActivationPrice[i] = bar[2].high; if(bar[1].high > safeWaveActivationPrice[i]){ safeWaveActivationPrice[i] = bar[1].high; } safeWaveSL[i] = bar[1].low; ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]); ObjectCreate(0,"Safe Wave Activation #"+positionTicket[i],OBJ_HLINE,0,0,safeWaveActivationPrice[arrayIndex]); ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_COLOR,clrOrange); ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_STYLE,STYLE_DASH); } if(bar[1].low < safeWaveSL[i]){ safeWaveSL[i] = bar[1].low; } if(positionCurrentPrice > safeWaveActivationPrice[i] && positionSL < safeWaveSL[i]){ trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeWaveSL[i],positionTP); positionSL = PositionGetDouble(POSITION_SL); ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]); if(orderStatus[1] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL && positionSL > positionOpenPrice){ trade.OrderDelete(currentOrderTickets[1]); orderStatus[1] = false; } } } if(positionType == POSITION_TYPE_SELL){ if(bar[2].close < bar[2].open && bar[1].close > bar[1].open){ safeWaveActivationPrice[i] = bar[2].low; if(bar[1].low < safeWaveActivationPrice[i]){ safeWaveActivationPrice[i] = bar[1].low; } safeWaveSL[i] = bar[1].high; ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]); ObjectCreate(0,"Safe Wave Activation #"+positionTicket[i],OBJ_HLINE,0,0,safeWaveActivationPrice[arrayIndex]); ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_COLOR,clrOrange); ObjectSetInteger(0,"Safe Wave Activation #"+positionTicket[i],OBJPROP_STYLE,STYLE_DASH); } if(bar[1].high > safeWaveSL[i]){ safeWaveSL[i] = bar[1].high; } if(positionCurrentPrice < safeWaveActivationPrice[i] && positionSL > safeWaveSL[i]){ trade.PositionModify(PositionGetInteger(POSITION_TICKET),safeWaveSL[i],positionTP); positionSL = PositionGetDouble(POSITION_SL); ObjectDelete(0,"Safe Wave Activation #"+positionTicket[i]); if(orderStatus[0] && PositionGetInteger(POSITION_TIME) >= baseStartTime && CancelOrderOnSL && positionSL < positionOpenPrice){ trade.OrderDelete(currentOrderTickets[0]); orderStatus[0] = false; } } } }*/ } } } } } //+------------------------------------------------------------------+