Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

algorithmic trading - How to use CopyRates() to search and filter through several timeframes for Bullish Engulfing pattern

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
     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);
     }


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...