【问题标题】:How to use CopyRates() to search and filter through several timeframes for Bullish Engulfing pattern如何使用 CopyRates() 在多个时间范围内搜索和过滤牛市吞没形态
【发布时间】:2020-10-13 03:12:03
【问题描述】:

我正在尝试使用 CopyRates() 在几个时间范围内(所有时间范围 H2 到 M10 在 H4 之后的看涨蜡烛内搜索看涨吞没烛台模式(看跌蜡烛,然后是更大的看涨蜡烛)它关闭)。我阅读了CopyRates() 的定义,但我发现实施起来有点挑战性。这里的想法来自我想要过滤具有最大看跌/看涨蜡烛对比率的模式的模式。看看我到目前为止做了什么:

在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
    }
}

这是其他相关代码:

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

更新

以下是看涨吞没形态的定义:

如上图所示的看涨吞没形态是看跌蜡烛和看涨蜡烛。看跌蜡烛的开盘价小于看涨蜡烛的收盘价,看跌蜡烛的收盘价大于看涨蜡烛的开盘价。请注意,在某些情况下,看跌蜡烛的收盘价仅比看涨蜡烛的开盘价高一小部分。每根蜡烛的主体尺寸都大于其上下灯芯的总和。

【问题讨论】:

  • 基于对这个问题的兴趣,我创建了一个详细说明所有必要部分的赏金。请随时提出任何问题,以澄清您需要获得指定解决方案的任何其他信息。
  • 我讨厌那些“错误地”对齐蜡烛的照片。它们具有误导性,使新来的交易者认为可以看到以前的 close 与新的 open 不一致的巨大差距。 唯一 可以这样做的情况是,如果某些 股票 经纪商允许 隔夜 和时段外交易。如果在外汇中看到,在正常的日常市场条件下,你会被迷惑!

标签: algorithmic-trading mql5 metatrader5


【解决方案1】:
     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);
     }

【讨论】:

  • 1.我正在使用您在解决方案中提供的相同模式。我所做的唯一更改是在我提供的moveRectangle() 链接中。 2. 糟糕,忘记查看专家日志了。我收到了这个错误25 MultiTimeframeTest.mq5: failed to load/copy rates on 240. error=4003,它出现在我尝试测试的每一对上。
  • @DanielKniaz 我想我应该在我的问题中更好地解释它。我对收盘后的H4 看涨蜡烛感兴趣。这基本上是在H4 图表上搜索蜡烛索引 1。当蜡烛形成时,有时它会从看涨转为看跌,因此对于我的情况来说,检查蜡烛形成时是不必要的。我将更新问题以明确说明这一点。请您更新您的解决方案以考虑这一点,然后我将奖励您。
  • @DanielKniaz 矩形背后的想法也是打开一个交易,因此移动矩形直到找到总体最高比率将导致打开和关闭几笔交易,直到找到最高比率。我一直在尝试找出一种方法来重组代码以在仅绘制一次之前找到整体最高的矩形,但我无法做到。我想问另一个问题,但我觉得这不需要另一个问题。能否请您帮忙。
  • @DanielKniaz 我也收到了array out of range 错误。我昨天尝试修复它,但不能。我还尝试了一种截然不同的方法来解决您的解决方案,该方法不需要移动矩形,因此它仅在 H4 蜡烛中最终需要的区域上绘制。但我意识到这不是一件容易的事:) 虽然它解决了 SuperHueman 在此过程中的另一个问题。荣誉,当你完成修复错误并添加 SuperHueman 的最新请求后,你肯定会得到我的 +50 票
  • @DanielKniaz 请注意,这也将使许多对此问题和解决方案表现出兴趣的人受益。 2/2
【解决方案2】:

假设 MyPeriod 被初始化为 2,其余代码似乎是正确的。您应该创建一个变量来保留具有最大比率的时间范围。在您的if 中,您必须计算candle+1 和candle 的烛台主体大小并计算比率,然后如果计算的比率大于先前计算的比率,则更改值并更新找到它的时间范围.

在for 循环结束时,您可以决定要在哪个时间段下订单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2019-11-17
    • 1970-01-01
    相关资源
    最近更新 更多