How to use CopyRates() to search and filter through several timeframes for Bullish Engulfing pattern
Asked Answered
T

2

15

I am trying to use CopyRates() to search for a bullish engulfing candlestick pattern (bearish candle followed by a bigger bullish candle) on several timeframes (all timeframes H2 to M10 within an H4 bullish candle after it closes). I read the definition of CopyRates() but I'm finding it a bit challenging to implement. The idea here is from the patterns I want to filter the pattern that has the biggest bearish to bullish candle pair ratio. See what I've done so far below:

In the OnTick():

for (int i=ArraySize(timeframes); i>=1; i--)   {
    
    if(CopyRates(Symbol(), timeframes[i - 1], 1, MyPeriod, rates)!=MyPeriod) {
        Print("Error CopyRates errcode = ",GetLastError()); 
        return;
    }

    // Using bullish engulfing pattern:
    if ((rates[numCandle].open < rates[numCandle].close) &&
        (rates[numCandle + 1].open > rates[numCandle + 1].close) &&
        (rates[numCandle + 1].open < rates[numCandle].close) &&
        (rates[numCandle + 1].close > rates[numCandle].open)) {

        // Not too certain what should be done here
    }
}

Here's the other related code:

input int numCandle=0; 
MqlRates rates[];
ENUM_TIMEFRAMES timeframes[7] = {PERIOD_H2, PERIOD_H1, PERIOD_M30, PERIOD_M20, PERIOD_M15, PERIOD_M12, PERIOD_M10};

void OnInit() {
   ArraySetAsSeries(rates, true);
}

UPDATED

Below is the definition of the bullish engulfing pattern:

enter image description here

The bullish engulfing pattern as shown in the above image is a bearish candle followed by a bullish candle. The bearish candle’s open less than the bullish candle’s close and the bearish candle’s close is greater than the bullish candle’s open. Please note that in several cases, the bearish candle's close is greater than the bullish candle's open by only a fraction. Each of the candles has a body size bigger than it’s upper and lower wicks combined.

Trainbearer answered 23/6, 2020 at 6:2 Comment(2)
Based on the interest in this question I've created a bounty detailing all the necessary parts. Please feel free to ask any question to clarify any additional information you'll need to arrive at the specified solution.Trainbearer
I hate those pictures of "wrongly" aligned candles. They are misleading and making new comer traders believe it's ok to see huge gaps where the previous close does not align with the new open. The only time this is ok, is if there is overnight and out-of sessions trading allowed from some stock brokerages. If seen in FX, under normal daily market conditions, you are being bamboozled!Niobic
G
7
     ENUM_TIMEFRAMES timeframes[7] = {PERIOD_H2, PERIOD_H1, PERIOD_M30, PERIOD_M20, PERIOD_M15, PERIOD_M12, PERIOD_M10};
     //ENUM_TIMEFRAMES timeframes[4] = {PERIOD_H1, PERIOD_M30, PERIOD_M15, PERIOD_M5};
     //---
     const int LONG=1, SHORT=-1, NO_DIR=0;
     const ENUM_TIMEFRAMES timeframeHighest = PERIOD_H4;
     string bestRatioObjectName="bestBullish2BearishPattern!";
     
     datetime lastCandleTime=0;
     
     void OnTick()
     {
        if(!isNewBar(PERIOD_H4))
           return;
        //most likely you will call this block after new bar check?
        MqlRates rates[];
        ArraySetAsSeries(rates,true);
        if(CopyRates(_Symbol,timeframeHighest,0,2,rates)==-1)
        {
           printf("%i %s: failed to load/copy rates on %d. error=%d",__LINE__,__FILE__,PeriodSeconds(timeframeHighest)/60,_LastError);
           return;
        }
        if(getCandleDir(rates[1])!=LONG)
           return;
        const datetime timeStart=rates[1].time, timeEnd=rates[0].time;   //within a bullish H4 candle - DONE
        
        double bestRatio = -1;//once a bearish2bullish ratio is higher, we'll move to new place
        for(int i=ArraySize(timeframes)-1;i>=0;i--)
        {
           if(CopyRates(_Symbol,timeframes[i],timeStart,timeEnd,rates)<0)
           {
              printf("%i %s: failed to copy rates on %d. error=%d",__LINE__,__FILE__,PeriodSeconds(timeframeHighest)/60,_LastError);
              return;
           }
           processRates(rates,bestRatio,bestRatioObjectName);
        }
        printf("%i %s: best=%.5f, objName =%s: %.5f-%.5f",__LINE__,__FILE__,bestRatio,bestRatioObjectName,
         ObjectGetDouble(0,bestRatioObjectName,OBJPROP_PRICE1),ObjectGetDouble(0,bestRatioObjectName,OBJPROP_PRICE2));
        //ExpertRemove();//for scripting, a one time call
     }
     bool isNewBar(const ENUM_TIMEFRAMES tf)
       {
        const datetime time=iTime(_Symbol,tf,0);
        if(time>lastCandleTime)
          {
           lastCandleTime=time;
           return true;
          }
        return false;
       }
     int getCandleDir(const MqlRates& rate) // candle direction: +1 for BULL, -1 for BEAR
       {
        if(rate.close-rate.open>_Point/2.)
           return 1;
        if(rate.open-rate.close>_Point/2.)
           return-1;
        return 0;
       }
     void processRates(const MqlRates& rates[],double &best,const string bestObjName)
     {
        for(int i=ArraySize(rates)-2; i>0; /* no sense to catch last candle - we cant compare it with anybody */ i--)
        {
           if(getCandleDir(rates[i])!=LONG)
              continue;//current - bullish
           if(getCandleDir(rates[i+1])!=SHORT)
              continue;//prev - bearish
           if(rates[i].close-rates[i+1].open>_Point/2.){}
           else continue;
           if(rates[i+1].close-rates[i].open>_Point/2.){}
           else continue;
           const double body=rates[i].close-rates[i].open, twoWicks = rates[i].high-rates[i].low- body;
           if(body<twoWicks)
              continue;   //Each of the candles has a body size bigger than it’s upper and lower wicks combined.
     //---
           const double prevBody = rates[i+1].open - rates[i+1].close;
           const double newRatio = body / prevBody;
           if(newRatio>best) // eventually we'll find best bull2bear ratio
           {
              moveRectangle(rates[i+1],rates[i].time,bestObjName);
              best = newRatio;
           }
        }
     }
     void moveRectangle(const MqlRates& rate,const datetime rectEnd,const string objectName)
     {
        if(ObjectFind(0,objectName)<0)
        {
           if(!ObjectCreate(0,objectName,OBJ_RECTANGLE,0,0,0,0,0))
           {
              printf("%i %s: failed to draw %s. error=%d",__LINE__,__FILE__,objectName,_LastError);
              return;
           }
           //add GUI things like how to display the rectangle
        }
        //moving the rectangle to a new place, even for the first time
        ObjectSetDouble(0,objectName,OBJPROP_PRICE,0,rate.open);
        ObjectSetDouble(0,objectName,OBJPROP_PRICE,1,rate.close);
        ObjectSetInteger(0,objectName,OBJPROP_TIME,0,rate.time);
        ObjectSetInteger(0,objectName,OBJPROP_TIME,1,rectEnd);
     }

Gid answered 28/6, 2020 at 13:55 Comment(33)
I've been following this question closely because I'm very interested in the solution. I added (pastebin.com/rjdqtx1K) as the GUI. I tried running the code but didn't see any rectangle. The previous candle and current H4 candles on my chart are bullish. Am I missing something?Seat
difficult to say. first, are you sure the object exist (check with list of objects) ? Next, it might happen that you do not see an object because it's too small on H4 chart. I would rather inspect M1 charts for that. Next, full code showing where you added GUI objects is neededGid
There is no object in the object list. Not sure why it doesn't appear. Here's my full moveRectangle() (pastebin.com/0WmdTvTG). Also, if I understand your code well it should draw a rectangle if candle 0 on H4 is bullish, right? So will it be searching after H4 has closed or continually as H4 candle 0 is being formed? This seems to confuse me a bit.Seat
1. are you sure you have a pattern? 2. what do you see in the experts log file - if failed to create an object, an error would be loggedGid
1. I am using the same pattern you provided in your solution. The only changes I've made are in the moveRectangle() link I provided. 2. Oops, forgot to check the expert log. I got this error 25 MultiTimeframeTest.mq5: failed to load/copy rates on 240. error=4003 and it appeared on every pair I tried testing.Seat
@DanielKniaz please pardon me, I haven't checked on the question for a number of days. I'll definitely check the solution soon and get back to you before the bounty expiresTrainbearer
@DanielKniaz I seem to be getting the same error=4003 as SuperHyoerMegaSomething on the currency pairs I tested.Trainbearer
Oh, I see. made an error when copying the answer. please try againGid
@DanielKniaz I got the error array out of range in ‘MTFCopyRates.mq5' (59,30). Line 30 from my code is const datetime timeStart=rates[0].time, timeEnd=TimeCurrent(); //within a bullish H4 candle - DONE and line 59 is if(getCandleDir(rates[i+1])!=SHORT)Trainbearer
You didn't address "if I understand your code well it should draw a rectangle if candle 0 on H4 is bullish, right? So will it be searching after H4 has closed or continually as H4 candle 0 is being formed? This seems to confuse me a bit." in your reply to my comment.Seat
@Trainbearer it happens because sometimes there's not enough of candles from the start of current H4 candle, e.g. if it is 5:01 pm now - there are two H1 candles (4:00 and 5:00), and it is it 4:01 now - you can only find one H1 candle since H4 start (which is 4:00:00). need to make a logical decision to fix the possible errorGid
@Seat The code I uploaded makes a one-time operation then exits. If you need it to do constantly - describe what you expect to have (and code at the top), and remove ExpertRemove(); lineGid
@DanielKniaz I think I should have explained it better in my question. I am interested in the H4 bullish candle after it closes. That's basically searching through candle index 1 on the H4 chart. As a candle forms there are times when it switches from being bullish to bearish so checking on the candle as it forms wouldn't be necessary for my case. I will update the question to categorically state that. Please could you update your solution to factor this, then I'll award you the bounty.Trainbearer
@DanielKniaz the bounty will end in less than an hour, so I awarded you the bounty. Thank you. Please could you update the solution to search within an H4 bullish candle after it closes.Trainbearer
@DanielKniaz also the idea behind the rectangle is to open a trade, so shifting the rectangle till the overall highest ratio is found would lead to opening and closing several trades till the highest ratio one is found. I've been trying to figure out a way to restructure the code to find the overall highest rectangle before drawing it only once but I haven't been able to. I wanted to ask another question but I felt this didn't warrant another question. Could you please help in the regard.Trainbearer
@Trainbearer I updated - code is called once per bar, previous H4 bar (and all inner lower tf elements). If you need to open trades from the rectangle - keep in mind that you probably need to be specific and catch only the last vs previous bar analysis on the lower timeframesGid
@DanielKniaz I am getting an array out of range in ‘MTFNewCopyRates.mq5' (75,29) error. I tried it on several pairs that had the previous H4 candle as bull but got the same error. Line 29 is if(CopyRates(_Symbol,timeframeHighest,0,2,rates)==-1) and line 75 is if(getCandleDir(rates[i+1])!=SHORT).Trainbearer
@DanielKniaz I have to admit that figuring out how to catch the last region (that gives the overall highest ratio within the H4 candle) to open a trade has been quite a challenge for me. I wanted to ask another question on that but didn't think it warranted a new question since it's so closely related to this solution. Could you please help with this.Trainbearer
I do not know what you mean by highest ratio - what to compare, what to achieve ?Gid
@DanielKniaz Pardon me, I meant the biggest ratio for bullish engulfing pattern (as calculated above). Currently the code compares two bullish engulfing patterns and keeps moving the rectangle till it arrives at the one with the biggest ratio from H2 to M10. I want to place a trade after all the engulfing pattern ratio comparisons are done so the trade is taken on the bullish engulfing pattern with the biggest ration (where the rectangle finally settles).Trainbearer
@DanielKniaz I am also getting the array out of range error that SuperHueman gotAjani
@DanielKniaz I got the array out of range error too. I tried fixing it yesterday but couldn't. I also tried a sightly different approach to your solution that doesn't require moving the rectangle so it draws only on the finally desired region within the H4 candle. But I realised it's not an easy task :) though it solves SuperHueman's other issue in the process. Kudos, you'll definitely get my +50 votes when you're done fixing the errors and adding SuperHueman's latest requestAntonomasia
@DanielKniaz Nice solution. Just need to fix the array range error. As Bane stated, moving rectangle only once when H4 closes as bullish would be a wonderful additionKutzenco
@DanielKniaz I haven’t been here for a few days. This solution I believe deserves more credit but the errors might be preventing that. Any plans of fixing this one?Ajani
@Trainbearer @Kutzenco @Antonomasia @Ajani - error out of array fixed by shifting to the next candle (first candle within H4 bar is thrown. not a best solution, just as an example. More wise would be to compute the time more presicely, or call iClose,iOpen... for the candle before the first within H4Gid
@DanielKniaz Thanks for the update. I've still been trying to sort this out and forgot to check for your reply. Does "first candle within H4 bar is thrown" refer to the H2 bar? If that's the case then only half of the timeframe is searched, which is far from ideal as you said. How would I compute the time more precisely? Also I haven't been able to get a condition for the resting position of the rectangle in order to place a trade as I detailed in previous comments. Could you also please address this too.Trainbearer
in order to apply CopyRates you need to know either dates or number of candles. they are different for each timeframe. so you have to either recompute and pass for each TF, or live without first candle. no idea what you mean by resting position of the rectangleGid
@DanielKniaz I'm still not sure if by the "first candle within H4" is referring to an H2 candle. Please confirm that for me. To be honest, I've spent about 3 months plus researching on this and trying to figure out a way to search for a candlestick pattern through multiple timeframes but your solution here is the closest I've come. I really appreciate your assistance so far but I still really don't fully understand how I would go about completing the solution as you explained in your comment above. Please could you help further with this, possibly providing a more complete solution. 1/2Trainbearer
@DanielKniaz Please note that this would also benefit so many people who have shown interest in this question and solution. 2/2Trainbearer
@DanielKniaz In previous comments I mentioned that I want to open a trade based on the upper and lower values of the rectangle. Based on the current solution, the rectangle keeps moving as it compares ratios, so I've been trying to figure out how to filter the biggest ratio where the rectangle wont move again, that's what I meant when I said the resting position of the rectangle. Otherwise I was thinking of placing a pending order and cancelling it whenever the rectangle moves till it stops, which isn't a good way to go about solving the problem. How could I solve this issue?Trainbearer
@DanielKniaz I've been watching this closely. and judging from the response, and upvotes to SuperHueman's last but one comment, it's fair to say that a lot of users here, including me are really interested in a more effective or usable solution. It's definitely not something easy to code as I said earlier that I tried to fix your code but couldn't figure it out. Also I am willing to now award you an extra 100 points instead of 50 I mentioned earlier once this is done and the 'moving rectangle issue' (that SuperHueman mentioned in his previous comment) for opening trades is also done.Antonomasia
@DanielKniaz I just created a new bounty of 150 points for this.Antonomasia
@Antonomasia 150 points, wow. I've still been trying to get this fully figured out.Trainbearer
C
1

Assuming that MyPeriod is initialized to 2, the rest of the code seems correct. You should create a variable to keep the timeframe that had the greatest ratio. Inside your if you have to calculate the candlestick body size for candle+1 and candle and calculate the ratio, then if the calculated ratio is greater than the previous calculated you change the value AND update the timeframe in which you find it.

By the end of your for loop you may decide in which timeframe you want to put your order.

Cyanide answered 26/6, 2020 at 23:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.