//+------------------------------------------------------------------+ //| twoWavesLimits.mq5 | //| Copyright 2018, Benjamin Pillet | //| | //+------------------------------------------------------------------+ #include "JPBP.mqh"; #include ; enum SLstrat { SL_FixPoint,//fix amount of points SL_LastBarRatio,//based on last bar high-low distance SL_TPratio,//ratio of take profit SL_Wave1,//use wave 1 SL_Wave2//use wave 2 }; enum TPstrat { TP_SLratio,//ratio of stop loss TP_MovingW1 }; enum limitPolicy { passthrough,//pass through closeBeyond,//close beyond wave2InsidePass, wave2InsideBeyond, }; enum limitToUse { wave1,//use wave one limits wave2,//use wave two limits highestLowest //use the highest or lowest limits }; //--- Entry input parameters input group "entry 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 = wave2;//limit to use input bool OnePerLimit = true; //open only one time on the same limit input double MinSpreadRatio = 1; //minimal loss as ratio of the spead //--- exit input parameters input group "exit 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\\twoWavesLimits\\twoWaves.ex5"; double fprice; double fsl; double ftp; double fvolume; int twoWavesHandle; double w1High[]; double w1Low[]; double w2High[]; double w2Low[]; double buyLimit; double lastBuyLimit; double sellLimit; double lastSellLimit; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- set variables //if(gatherData || askML)initialiseIndicators(); setVariables(); trade.SetExpertMagicNumber(MagicNumber); arraySize = 0; orderPlaced[0] = false; orderPlaced[1] = false; positionTotal = 0; twoWavesHandle = iCustom(_Symbol,TimeFrame,indPath,TimeFrame); //---Set array as series ArraySetAsSeries(w1High,true); ArraySetAsSeries(w1Low,true); ArraySetAsSeries(w2High,true); ArraySetAsSeries(w2Low,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(twoWavesHandle); FileClose(fhBuy); //FileClose(fileHandle); //assignClassAll(); //saveDataArff(ORDER_TYPE_BUY,false); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- get market info refreshVariables(); if(gatherData) setMinMax(); if(gatherData) endSequences(); //updateSequences(); //---Acquires indicators informations CopyBuffer(twoWavesHandle,0,0,3,w1High); CopyBuffer(twoWavesHandle,1,0,3,w1Low); CopyBuffer(twoWavesHandle,2,0,3,w2High); CopyBuffer(twoWavesHandle,3,0,3,w2Low); //--- 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_MovingW1 || SafeWave)){ AddPosition(); //getData(posTicket,PositionGetInteger(POSITION_TYPE)); } } } } //--- remove lines if a position was closed if(positionTotal < prevPositionTotal){ //assignClass(); HistorySelect(0,TimeCurrent()); for(int i=0; i w1High[0]) buyLimit = w2High[0] + AddPoint; else buyLimit = w1High[0] + AddPoint; if(w2Low[0] < w1Low[0]) sellLimit = w2Low[0] - AddPoint; else sellLimit = w1Low[0] - AddPoint; break; } //general conditions bool notSameBar = lastOpen != bar[0].open; bool onlyOneTrade; bool buyLimitChanged; bool sellLimitChanged; if(OnePos) onlyOneTrade = positionTotal == 0; else onlyOneTrade = true; if(OnePerLimit){ buyLimitChanged = buyLimit != lastBuyLimit; sellLimitChanged = sellLimit != lastSellLimit; } else{ buyLimitChanged = true; sellLimitChanged = true; } bool bc = false; bool sc = false; if(EntryPolicy == passthrough){ if(Limit(buyLimit,PASS_ABOVE,BID) && buyLimit != 0) bc = true; if(Limit(sellLimit,PASS_BELOW,ASK) && sellLimit != 0) sc = true; } if(EntryPolicy == closeBeyond){ if(Limit(buyLimit,CLOSEandOPEN_ABOVE)) bc = true; if(Limit(sellLimit,CLOSEandOPEN_BELOW)) sc = true; } //--- market execution //buy if(bc && onlyOneTrade && buyLimitChanged){ //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_Wave1: fsl = w1Low[0]; break; case SL_Wave2: fsl = w2Low[0]; break; default: break; } //set take profit ftp = ask + (bid-fsl)*TpSlRatio; //set volume of transaction if(bid > fsl && bid-fsl > (ask-bid)*MinSpreadRatio){ if(Lots != 0){ fvolume = Lots; } else{ fvolume = LotsCalculator(bid,fsl,accountBalance); } if(askML || gatherData) getData(-1,ORDER_TYPE_BUY); //if(askML) saveDataArffLive(); datetime ptime = TimeCurrent(); if(true){ //if(false){ //if(askWekaFile(ORDER_TYPE_BUY)){ //always true if askML is false if(trade.Buy(fvolume,_Symbol,ask,fsl,ftp)){ if(gatherData) setID(ptime); lastBuyLimit = buyLimit; lastOpen = bar[0].open; } } } } //sell if(sc && onlyOneTrade && sellLimitChanged){ //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_Wave1: fsl = w1High[0]; break; case SL_Wave2: fsl = w2High[0]; break; default: break; } //set take profit ftp = bid - (fsl - ask)*TpSlRatio; //set volume of transaction if(ask < fsl && fsl-ask > (ask-bid)*MinSpreadRatio){ if(Lots != 0){ fvolume = Lots; } else{ fvolume = LotsCalculator(ask,fsl,accountBalance); } //if(askML || gatherData) getData(-1,ORDER_TYPE_SELL); //if(askML) saveDataArffLive(); datetime ptime = TimeCurrent(); if(false){ //if(askWekaFile(ORDER_TYPE_SELL)){ //always true if askML is false if(trade.Sell(fvolume,_Symbol,bid,fsl,ftp)){ if(gatherData) setID(ptime); lastSellLimit = sellLimit; lastOpen = bar[0].open; } } } } //--- safe mode and trailing mode if((SafeMode || TrailingMode || TPsetup == TP_MovingW1 || SafeWave)){ //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; } } } } } } } } getReadyForNextTick(); } void OnTrade() { //assignClass(); //PrintFormat("instance index: "+instanceIndex); } //+------------------------------------------------------------------+