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
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.
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);
}