MQL5. Need help with 2nd position and candle entry.

 

I'm trying to build an EA that can only allow a second trade (Position) only after the 1st trade is 10 candles behind.

Tried this but didn't activate any trades->


   MqlRates PriceInformation[];

   ArraySetAsSeries(PriceInformation, true);

int testData = CopyRates(Symbol(), Period(), 0, Bars(Symbol(), Period()), PriceInformation);

for (int i = testData; i <=10; i-- ){

if (PriceInformation[10].time < PriceInformation[0].time) {

Comment("Candle 10 is lower than candle 0");

}

else Comment("Not the case");

}

 
Dogooder:

I'm trying to build an EA that can only allow a second trade (Position) only after the 1st trade is 10 candles behind.

Tried this but didn't activate any trades->


   MqlRates PriceInformation[];

   ArraySetAsSeries(PriceInformation, true);

int testData = CopyRates(Symbol(), Period(), 0, Bars(Symbol(), Period()), PriceInformation);

for (int i = testData; i <=10; i-- ){

if (PriceInformation[10].time < PriceInformation[0].time) {

Comment("Candle 10 is lower than candle 0");

}

else Comment("Not the case");

}

Based on your code, you could simply check whether 'iTime(Symbol(),Period(),10)<iTime(Symbol(),Period(),0)', which will ALWAYS be true, so it is meaningless.

To achieve what you wanted in the first place, you'll need to retrieve the time that you opened your previous trade (*hint* one way is via using PositionSelect()/PositionGetInteger()), and compare that against iTime(Symbol(),Period(),0) instead.

 
Seng Joo Thio:

Based on your code, you could simply check whether 'iTime(Symbol(),Period(),10)<iTime(Symbol(),Period(),0)', which will ALWAYS be true, so it is meaningless.

To achieve what you wanted in the first place, you'll need to retrieve the time that you opened your previous trade (*hint* one way is via using PositionSelect()/PositionGetInteger()), and compare that against iTime(Symbol(),Period(),0) instead.

Tried this but only getting the else statement



if (PositionSelect(_Symbol) == true) {

for (int i = PositionsTotal(); i >= 0; i--){

 if (PositionGetInteger(POSITION_TIME) < iTime(Symbol(),Period(),0)) {

Comment("Candle 10 is lower than candle 0");

 } else Comment("Not the case");

}

}

 
Dogooder:

Tried this but only getting the else statement

I've tested, the code you showed should work (some "imperfections", but not critical, yet... LOL)...

So if it doesn't, then I'll need to see more of your codes.

 
Seng Joo Thio:

I've tested, the code you showed should work (some "imperfections", but not critical, yet... LOL)...

So if it doesn't, then I'll need to see more of your codes.


I want the indicator to only put through another trade after a trade is 10 candles behind candle 0. I deleted the trade.Sell code.



void OnTick()

  {

int IchimokoDefinition = iIchimoku(_Symbol,_Period,9,26,52);

double   Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK), _Digits);

double   Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID), _Digits);  

string signal = "";


MqlRates PriceInformation[];   

ArraySetAsSeries(PriceInformation, true);

int Data = CopyRates(Symbol(), Period(),0,10,PriceInformation);


if (PositionSelect(_Symbol) == true) {

for (int i = PositionsTotal(); i >= 0; i--){

if (PositionGetInteger(POSITION_TIME) < iTime(Symbol(),Period(),0)) {

Comment("Candle 10 is lower than candle 0");

 } else Comment("Not the case");

}

}


   ArraySetAsSeries(TenkansenArray, true);

   ArraySetAsSeries(KijunSenArray, true);

   ArraySetAsSeries(SenkouSpanAArray, true);

   ArraySetAsSeries(SenkouSpanBArray, true);

   ArraySetAsSeries(ChikouSpanArray, true);


   CopyBuffer(IchimokoDefinition,0, 0, 3, TenkansenArray);

   CopyBuffer(IchimokoDefinition,1, 0, 3, KijunSenArray);

   CopyBuffer(IchimokoDefinition,2, 0, 3, SenkouSpanAArray);

   CopyBuffer(IchimokoDefinition,3, 0, 3, SenkouSpanBArray);

   CopyBuffer(IchimokoDefinition,4, 0, 3, ChikouSpanArray);


   double TenkansenValue   = TenkansenArray[1];   

   double KijunSenValue    = KijunSenArray[1];     

   double SenkouSpanAValue = SenkouSpanAArray[1];     

   double SenkouSpanBValue = SenkouSpanBArray[1];  

   double ChikouSpanValue  = ChikouSpanArray[1];        


if (isNewCandle()) {

tradeNow = 1;

}

   if (TenkansenValue < PriceInformation[0].open)

   signal = "buy";

   if (TenkansenValue < PriceInformation[0].open)

   signal = "buy";

   if (TenkansenValue > KijunSenValue && TenkansenValue > SenkouSpanAValue && 

   PriceInformation[0].open > SenkouSpanAValue && SenkouSpanAValue > SenkouSpanBValue && tradeNow == 1) {

   buyTP = Ask + (TakeProfit * Point()); 

   buySL = Ask - (StopLoss * Point());

   trade.Buy(LotSize, NULL, Ask, buySL, buyTP, NULL);

   tradeNow = 0;

}

 }


// Insuring a new candle is created.

bool isNewCandle()

  {

static int BarsOnChart=0;

if(Bars(_Symbol,PERIOD_CURRENT)==BarsOnChart)

return false;

BarsOnChart=Bars(_Symbol,PERIOD_CURRENT);

return true;

  }

 
Dogooder:

I want the indicator to only put through another trade after a trade is 10 candles behind candle 0. I deleted the trade.Sell code.

Ok, this will work:

   bool timeLapsed = true;
   for (int i = PositionsTotal()-1; i >= 0; i--)
   {
      if (PositionGetSymbol(i)==_Symbol &&
          PositionSelectByTicket(PositionGetTicket(i)))
      {
         if (PositionGetInteger(POSITION_TIME) > iTime(Symbol(),Period(),candlesToLapse))
         {
            timeLapsed = false;
            break;
         }
      }
   }
   
   if (timeLapsed && isNewCandle())
      tradeNow = 1;

In your original code, you used PositionSelect(<Symbol>) which returns true when you have one or more positions - which explains why you use PositionTotal() later on... but when you use PositionTotal(), you also need to use PositionGetSymbol() to pin-point the exact position you're interested in, before using PositionGetInteger() to get its open time, otherwise it won't be accurate.

So my code above simply loops through all positions, making sure they're all 10 candles earlier before allowing tradeNow to be set to 1.

Lastly, hope you're able to improve on your code formatting... LOL.

 
Seng Joo Thio:

Ok, this will work:

In your original code, you used PositionSelect(<Symbol>) which returns true when you have one or more positions - which explains why you use PositionTotal() later on... but when you use PositionTotal(), you also need to use PositionGetSymbol() to pin-point the exact position you're interested in, before using PositionGetInteger() to get its open time, otherwise it won't be accurate.

So my code above simply loops through all positions, making sure they're all 10 candles earlier before allowing tradeNow to be set to 1.

Lastly, hope you're able to improve on your code formatting... LOL.

  void OnTick()
  {

   int IchimokoDefinition = iIchimoku(_Symbol,_Period,9,26,52);
   double   Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK), _Digits);
   double   Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID), _Digits);  
   
   string signal = "";     
   
   MqlRates PriceInformation[];   
   ArraySetAsSeries(PriceInformation, true);
   CopyRates(Symbol(), Period(),0,10,PriceInformation);

if (isNewCandle()) {
tradeNow = 1;
}

bool timeLapsed = true;
   for (int i = PositionsTotal()-1; i >= 0; i--)
   {  
    if (PositionGetSymbol(i)==_Symbol && PositionSelectByTicket(PositionGetTicket(i))){
         if (PositionGetInteger(POSITION_TIME) > iTime(Symbol(), Period(), 0))
         {
            timeLapsed = false;
            break;
         }
      }
   if (timeLapsed && isNewCandle()) {
      tradeNow = 1;
}

   ArraySetAsSeries(TenkansenArray, true);
   ArraySetAsSeries(KijunSenArray, true);
   ArraySetAsSeries(SenkouSpanAArray, true);
   ArraySetAsSeries(SenkouSpanBArray, true);
   ArraySetAsSeries(ChikouSpanArray, true);

   CopyBuffer(IchimokoDefinition,0, 0, 3, TenkansenArray);
   CopyBuffer(IchimokoDefinition,1, 0, 3, KijunSenArray);
   CopyBuffer(IchimokoDefinition,2, 0, 3, SenkouSpanAArray);
   CopyBuffer(IchimokoDefinition,3, 0, 3, SenkouSpanBArray);
   CopyBuffer(IchimokoDefinition,4, 0, 3, ChikouSpanArray);

   double TenkansenValue   = TenkansenArray[1];   
   double KijunSenValue    = KijunSenArray[1];     
   double SenkouSpanAValue = SenkouSpanAArray[1];     
   double SenkouSpanBValue = SenkouSpanBArray[1];  
   double ChikouSpanValue  = ChikouSpanArray[1];        

   if (TenkansenValue < PriceInformation[0].open)
   signal = "buy";

   if (TenkansenValue > KijunSenValue && PriceInformation[0].open > SenkouSpanAValue &&  TenkansenValue > SenkouSpanAValue && 
   SenkouSpanAValue > SenkouSpanBValue && tradeNow == 1) {
   
   buyTP = Ask + (TakeProfit * Point()); 
   buySL = Ask - (StopLoss * Point());
   trade.Buy(LotSize, NULL, Ask, buySL, buyTP, NULL);
   tradeNow = 0;
      }
   }
}

// Insuring a new candle is created.
bool isNewCandle()
  {
   static int BarsOnChart=0;
   if(Bars(_Symbol,PERIOD_CURRENT)==BarsOnChart)
      return false;
   BarsOnChart=Bars(_Symbol,PERIOD_CURRENT);
   return true;
  }


Hey, I may have explained it improperly( I want a trade to only execute if a trade is AT LEAST 10 candles behind ).

The code didn't activate any trades.

I tried different combinations with iTime(Symbol(), Period(), 10) but still no trades were executed.

I have some clarification:

PositionSelectByticket: gives a true if there are any open positions

PositionGetTicket(i): Gets the earliest position in the index?

PositionGetInteger(POSITION_TIME): Open time of the earliest position in the index?

 
Dogooder:

Hey, I may have explained it improperly( I want a trade to only execute if a trade is AT LEAST 10 candles behind ).

The code didn't activate any trades.

I tried different combinations with iTime(Symbol(), Period(), 10) but still no trades were executed.

No problem with your explanation, but huge problem with your code formatting and copying skills :). Here's what your code, together with my changes, should have looked like (after fixing your misplaced {}, and improving on formatting):

void OnTick()
  {
   int IchimokoDefinition = iIchimoku(_Symbol,_Period,9,26,52);

   double   Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK), _Digits);
   double   Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID), _Digits);  

   int fibHigh = iHighest(Symbol(), Period(), MODE_HIGH, barsCount, 0);
   int fibLow  = iLowest(Symbol(), Period(), MODE_LOW, barsCount, 0);  

   string signal = "";

   MqlRates PriceInformation[];   
   ArraySetAsSeries(PriceInformation, true);
   int Data = CopyRates(Symbol(), Period(),0,10,PriceInformation);

   bool timeLapsed = true;

   for (int i = PositionsTotal()-1; i >= 0; i--)
   {
      if (PositionGetSymbol(i)==_Symbol &&
          PositionSelectByTicket(PositionGetTicket(i)))
      {
         if (PositionGetInteger(POSITION_TIME) > iTime(Symbol(),Period(),candlesToLapse))
         {
            timeLapsed = false;
            break;
         }
      }
   }
   
   if (timeLapsed && isNewCandle())
      tradeNow = 1;

   ArraySetAsSeries(TenkansenArray, true);
   ArraySetAsSeries(KijunSenArray, true);
   ArraySetAsSeries(SenkouSpanAArray, true);
   ArraySetAsSeries(SenkouSpanBArray, true);
   ArraySetAsSeries(ChikouSpanArray, true);

   CopyBuffer(IchimokoDefinition,0, 0, 3, TenkansenArray);
   CopyBuffer(IchimokoDefinition,1, 0, 3, KijunSenArray);
   CopyBuffer(IchimokoDefinition,2, 0, 3, SenkouSpanAArray);
   CopyBuffer(IchimokoDefinition,3, 0, 3, SenkouSpanBArray);
   CopyBuffer(IchimokoDefinition,4, 0, 3, ChikouSpanArray);

   double TenkansenValue   = TenkansenArray[1];   
   double KijunSenValue    = KijunSenArray[1];     
   double SenkouSpanAValue = SenkouSpanAArray[1];     
   double SenkouSpanBValue = SenkouSpanBArray[1];  
   double ChikouSpanValue  = ChikouSpanArray[1];        

   if (TenkansenValue < PriceInformation[0].open)
      signal = "buy";

   if (TenkansenValue < PriceInformation[0].open)
      signal = "buy";

   if (TenkansenValue > KijunSenValue && TenkansenValue > SenkouSpanAValue && 
       PriceInformation[0].open > SenkouSpanAValue && SenkouSpanAValue > SenkouSpanBValue && tradeNow == 1)
   {
      buyTP = Ask + (TakeProfit * Point()); 
      buySL = Ask - (StopLoss * Point());
      trade.Buy(LotSize, NULL, Ask, buySL, buyTP, NULL);
      tradeNow = 0;
   }
 }


Dogooder:

I have some clarification:

PositionSelectByticket: gives a true if there are any open positions

PositionGetTicket(i): Gets the earliest position in the index?

PositionGetInteger(POSITION_TIME): Open time of the earliest position in the index?

No (returns true only if the supplied ticket number corresponds to an existing position).

No (returns the ticket number of the position referenced by index i (out of the total returned by the most recent call to PositionsTotal()), which is not necessarily the earliest).

No (returns the open time of the position "selected" by the most recent call to PositionSelectByTicket()).

 
bool timeLapsed = true;

   for (int i = PositionsTotal()-1; i >= 0; i--)
   {
      if (PositionGetSymbol(i)==_Symbol &&
          PositionSelectByTicket(PositionGetTicket(i)))
      {
         if (PositionGetInteger(POSITION_TIME) > iTime(Symbol(),Period(),10))
         {
            timeLapsed = false;
            break;
         }
      }
   }
   
   if (timeLapsed && isNewCandle())
      tradeNow = 1;

Tried your code. The trades are being executed, but they are still trading one candle after another ( not leaving at least a 10 candle space ).

According to the code you posted ( PositionSelectByTicket(PositionGetTicket(i)) : This will Select an open position ticket within the index ( i ) in a descending order. ( newest position first ).

The thing is, it doesn't state how to get the 10th candle's time to be the trigger for allowing a trade.


Attached is a backtest of the updated code.

Please help.

Files:
10Candle.PNG  81 kb
 
Dogooder:

Tried your code. The trades are being executed, but they are still trading one candle after another ( not leaving at least a 10 candle space ).

According to the code you posted ( PositionSelectByTicket(PositionGetTicket(i)) : This will Select an open position ticket within the index ( i ) in a descending order. ( newest position first ).

The thing is, it doesn't state how to get the 10th candle's time to be the trigger for allowing a trade.

Attached is a backtest of the updated code.

Please help.

This is my backtest screenshot:


And I'll just attach the complete .mq5 file here to eliminate further mis-communcations, once and for all... LOL. 

The sequence of i does not necessarily correspond to the timing of positions, so my code simply iterates through ALL positions, and check that their timings are more than 10 bars earlier (which will be " > iTime(Symbol(),Period(),10)"), before allowing a new trade.

Files:
Dogooder.mq5  7 kb
 
Seng Joo Thio:

This is my backtest screenshot:


And I'll just attach the complete .mq5 file here to eliminate further mis-communcations, once and for all... LOL. 

The sequence of i does not necessarily correspond to the timing of positions, so my code simply iterates through ALL positions, and check that their timings are more than 10 bars earlier (which will be " > iTime(Symbol(),Period(),10)"), before allowing a new trade.


Ran your code.

What's strange, if I set the backtest for H4, the candles wouldn't use timeLapsed, but when I set it to M1, it would work.

I saw you entered  EventSetTimer(60); but when I deleted it, the effect wouldn't change.

Reason: