设为首页 收藏本站 切换语言

MT5向导建立交易系统2__交易信号Signal及解析部分代码(1)

| 发表于 2022-12-28 22:37:05 | 显示全部楼层 |复制链接
© 本贴为 xxtz 原创/首发,严禁抄袭!
这里记录学习MT5中级知识的通过MT5 EA向导建立EA过程,文中也提到通过改写系统自带的signal代码部分算法来实现自己创建signal。
非计算机本科,爱好编程而已,所以解释不很周全、错误之处,恳请善意指出。


MT5基于C++的,其中使用了大量的类,文中解析代码会对类层级间的继承派生关系及其中的成员函数做简要介绍,会大概有个朦胧印象,通过解析代码,可以分清哪些是为了程序更加健壮的,哪些是核心代码需要仔细斟酌的,具体细节请参看系统自带源码。
下面是有关EA向导生成代码涉及到类的继承派生关系等级图

image.png
EA使用MQL5向导产生基于如下基类:
CExpertTrade:执行交易操作
CIndicators:管理在EA使用的指标和时间序列数据(主要是开高低收价,成交量等等)
CSymbolInfo: 获得有关交易品种的信息
CAccountInfo: 获得交易账户状态和信息
CPositionInfo:获得已开仓订单信息
COrderInfo: 获得挂单信息

CExpertTrade类是EA向导的主要引擎,其产生的实例包括3个类的实例,分别是:
CExpertSignal: 主要参数交易信号提供给EA关于进出市场的可能性,价格和设置保护性订单。
CExpertMoney:主要是管理资金和风险:计算开仓量。
CExpertTrailing:开仓以后的管理,告诉EA是否要对订单修改保护机制。

内置交易信号标准库存放在.../MQL5/Include/Expert/Signal文件夹下,自己编写的信号不要放在这个文件夹下,可在.../MQL5/Include/Expert/文件下新建文件夹专门用于自己定制的signal程序。

以下以系统自带的SignalMACD.mqh为例解析源码,顺便说说如何编写自己的signal文件。
1. 程序开始让预处理器包括CExperSignal基类,定制signal照抄吧。
  1. #include <Expert\ExpertSignal.mqh>
复制代码
2. 接下来类描述,定制signal这段要改写以确保MQL5向导在”下一步”到选择signal时可见(如Title,Name等),改变成自己的类描述。定制signal参数描述块(parameter)要匹配即将使用的参数。
  1. // wizard description start
  2. //+-----------------------------------------------------------------------------+
  3. //| Description of the class                                                                            |
  4. //| Title=Signals of oscillator 'MACD'                                                            |
  5. //| Type=SignalAdvanced                                                                              |
  6. //| Name=MACD                                                                                           |
  7. //| ShortName=MACD                                                                                   |
  8. //| Class=CSignalMACD                                                                                 |
  9. //| Page=signal_macd                                                                                    |
  10. //| Parameter=PeriodFast,int,12,Period of fast EMA                                      |
  11. //| Parameter=PeriodSlow,int,24,Period of slow EMA                                   |
  12. //| Parameter=PeriodSignal,int,9,Period of averaging of difference             |
  13. //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
  14. //+------------------------------------------------------------------------------+
  15. // wizard description end
复制代码
3. 好的编程习惯一般都提供一些解释便于更好的理解代码。
  1. //+------------------------------------------------------------------+
  2. //| Class CSignalMACD.                                               |
  3. //| Purpose: Class of generator of trade signals based on            |
  4. //|          the 'Moving Average Convergence/Divergence' oscillator. |
  5. //| Is derived from the CExpertSignal class.                         |
  6. //+------------------------------------------------------------------+
复制代码
4.  以下正式进入类的定义。
  1. class CSignalMACD : public CExpertSignal
  2.   {
  3. protected:
  4.    CiMACD            m_MACD;           // object-oscillator
  5.    //--- adjusted parameters
  6.    int               m_period_fast;    // the "period of fast EMA" parameter of the oscillator
  7.    int               m_period_slow;    // the "period of slow EMA" parameter of the oscillator
  8.    int               m_period_signal;  // the "period of averaging of difference" parameter of the oscillator
  9.    ENUM_APPLIED_PRICE m_applied;       // the "price series" parameter of the oscillator
  10.    //--- "weights" of market models (0-100)
  11.    int               m_pattern_0;      // model 0 "the oscillator has required direction"
  12.    int               m_pattern_1;      // model 1 "reverse of the oscillator to required direction"
  13.    int               m_pattern_2;      // model 2 "crossing of main and signal line"
  14.    int               m_pattern_3;      // model 3 "crossing of main line an the zero level"
  15.    int               m_pattern_4;      // model 4 "divergence of the oscillator and price"
  16.    int               m_pattern_5;      // model 5 "double divergence of the oscillator and price"
  17.    //--- variables
  18.    double            m_extr_osc[10];   // array of values of extremums of the oscillator
  19.    double            m_extr_pr[10];    // array of values of the corresponding extremums of price
  20.    int               m_extr_pos[10];   // array of shifts of extremums (in bars)
  21.    uint              m_extr_map;       // resulting bit-map of ratio of extremums of the oscillator and the price
  22. public:
  23.                      CSignalMACD(void);
  24.                     ~CSignalMACD(void);
  25.    //--- methods of setting adjustable parameters
  26.    void              PeriodFast(int value)             { m_period_fast=value;           }
  27.    void              PeriodSlow(int value)             { m_period_slow=value;        }
  28.    void              PeriodSignal(int value)           { m_period_signal=value;     }
  29.    void              Applied(ENUM_APPLIED_PRICE value) { m_applied=value;}
  30.    //--- methods of adjusting "weights" of market models
  31.    void              Pattern_0(int value)              { m_pattern_0=value;             }
  32.    void              Pattern_1(int value)              { m_pattern_1=value;             }
  33.    void              Pattern_2(int value)              { m_pattern_2=value;             }
  34.    void              Pattern_3(int value)              { m_pattern_3=value;             }
  35.    void              Pattern_4(int value)              { m_pattern_4=value;             }
  36.    void              Pattern_5(int value)              { m_pattern_5=value;             }
  37.    //--- method of verification of settings
  38.    virtual bool      ValidationSettings(void);
  39.    //--- method of creating the indicator and timeseries
  40.    virtual bool      InitIndicators(CIndicators *indicators);
  41.    //--- methods of checking if the market models are formed
  42.    virtual int       LongCondition(void);
  43.    virtual int       ShortCondition(void);
  44. protected:
  45.    //--- method of initialization of the oscillator
  46.    bool              InitMACD(CIndicators *indicators);
  47.    //--- methods of getting data
  48.    double            Main(int ind)                     { return(m_MACD.Main(ind));      }
  49.    double            Signal(int ind)                   { return(m_MACD.Signal(ind));    }
  50.    double            DiffMain(int ind)                 { return(Main(ind)-Main(ind+1)); }
  51.    int               StateMain(int ind);
  52.    double            State(int ind) { return(Main(ind)-Signal(ind)); }
  53.    bool              ExtState(int ind);
  54.    bool              CompareMaps(int map,int count,bool minimax=false,int start=0);
  55.   };
复制代码
4.1    CSignalMACD继承于CExpertSignal
    首先定义CiMACD            m_MACD;           // object-oscillator 这句中CiMACD是标准库的技术指标类
    但如果自定义signal 可能根据自定义的指标编写定义自己的交易指标类:如CSignalMyCustInd:
class CSignalMyCustInd : public CExpertSignal
  {
protected:
   CiCustom          m_mci;            // 自己定义的指标对象m_mci
其中CiCustom类(继承于CIndicator)它提供创建、设置和取得定制指标的数据作用。
    Cindicator类让技术指标类的实例的创建、存储和管理技术指标变得方便。Cindicator类中有定义   

public:

//--- method for creating
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const ENUM_INDICATOR type,const int num_params,const MqlParam &params[]);
protected:
   //--- methods of tuning
   bool              CreateBuffers(const string symbol,const ENUM_TIMEFRAMES period,const int buffers);
   virtual bool   Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                                const int num_params,const MqlParam &params[]) {return(false);}

//+------------------------------------------------------------------+
//| Creation of the indicator with universal parameters              |
//+------------------------------------------------------------------+
bool CIndicator::Create(const string symbol,const ENUM_TIMEFRAMES period,
                        const ENUM_INDICATOR type,const int num_params,const MqlParam &params[])
  {
//--- check history
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- create
   m_handle=IndicatorCreate(symbol,period,type,num_params,params);
//--- check result
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- idicator successfully created
   if(!Initialize(symbol,period,num_params,params))
     {
      //--- initialization failed
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
*************************************
SetSymbolPeriod函数,为了获取symbol,period,及PeriodToTimframeFlag(就是获取现在得到的period,比如15min,在ENUM_TIMEFRAMES这个枚举时间周期从小到大排列(静态数组_p_int[])的位置,15min位置是8,前面有1,2,3,4,5,6,10,12分钟,算法是:
//--- cycle for all timeframes
   for(int i=0;i<ArraySize(_p_int);i++)
      if(period==_p_int)
        {
         //--- at the same time generate the flag of the working timeframe
         m_timeframe_flags=((int)1)<<i;// 位左移运算,位移运算符优先级大于比较运算符,小于+-运算符
         return;
        }

*************************************

Cindicators类中有定义*Create方法   
//--- method for creation
   CIndicator       *Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const ENUM_INDICATOR type,const int count,const MqlParam &params[]);
//+------------------------------------------------------------------+
//| Indicator creation                                                                     |
//+------------------------------------------------------------------+
CIndicator *CIndicators::Create(const string symbol,const ENUM_TIMEFRAMES period,
                                const ENUM_INDICATOR type,const int count,const MqlParam &params[])
  {
   CIndicator *result=NULL;
//---
   switch(type)
     {
      case IND_AC:
         //--- Identifier of "Accelerator Oscillator"
         if(count==0)
            result=new CiAC;
         break;
      case IND_AD:
         //--- Identifier of "Accumulation/Distribution"
         if(count==1)
            result=new CiAD;
         break;
        ......
      case IND_VOLUMES:
         //--- Identifier of "Volumes"
         if(count==1)
            result=new CiVolumes;
         break;
         //--- Identifier of "Custom"
      case IND_CUSTOM:
         if(count>0)
         result=new CiCustom;
         break;
     }
   if(result!=NULL)
     {
      if(result.Create(symbol,period,type,count,params))
         Add(result);
      else
        {
         delete result;
         result=NULL;
        }
     }
//---
   return(result);
  }

类指针可以指向多个不同的对象,实现多态.
-----------------------------------------------------

如果是自编的定制指标,CiCustom类来实例化对象;而真正锁定定制函数在成员函数“Init指标名称(CIndicators *indicators)”方法中调用indicator中的Create方法(标准库指标有自己定义的类的Create方法,它也是从CIndicator继承来),设置parameters[0].string_value="Examples\\自定义指标名称.ex5"指定其引用的具体位置来锁定。

CIndicator::Create方法
//+------------------------------------------------------------------+
//| Creation of the indicator with universal parameters              |
//+------------------------------------------------------------------+
bool CIndicator::Create(const string symbol,const ENUM_TIMEFRAMES period,
                        const ENUM_INDICATOR type,const int num_params,const MqlParam &params[])
  {
//--- check history
   if(!SetSymbolPeriod(symbol,period))//后面有详细介绍
      return(false);
//--- create
   m_handle=IndicatorCreate(symbol,period,type,num_params,params);
//--- check result
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- idicator successfully created
   if(!Initialize(symbol,period,num_params,params))
     {
      //--- initialization failed
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }4.2  CSignalMACD< 继承CExpertSignal 继承于<CExpertBase,
这3个类中都有InitIndicators方法,CSignalMACD子类的该方法会调用父类的该方法,然后在调用子类自己的Init***方法,

4.2.1 CExpertBase::InitIndicators(indicators)主要是
1.检查初始化阶段[1.First(初始化赋值symbo,period,m_adjusted_point);2.Tuning(检查symbol和period是否正2.确);3.Validation;3.Complete]是否在INIT_PHASE_VALIDATION,
symbol和period是否正确,
3.时间序列数据(价格和其他)是否就位了,
4.最后m_init_phase=INIT_PHASE_COMPLETE];

4.2.2 CExpertSignal::InitIndicators(CIndicators *indicators) 获得进出场条件需要的时间序列数据SetPriceSeries


4.2.3 CSignalMACD::InitIndicators(CIndicators *indicators)   调用父类同名方法,再调用具体指标的Init***方法

4.2.4 Init***,这里是InitMACD,它完成:
4.2.4.1.indicators.Add(GetPointer(m_MACD))指标加入集合中,
4.2.4.2.m_MACD.Create 由于m_MACD是CiMACD实例,在CiMACD::Create会创建句柄iMACD,
4.2.4.3.再Initialize(symbol,period,fast_ema_period,slow_ema_period,signal_period,applied),该方法会
     4.2.4.3.1createbuffers(symbol,period,2) 该方法其中核心代码[result&=Add(new CIndicatorBuffer) m_buffers_total=buffers,其中m_buffers_total是CSeries类定义的成员变量]然后设name,status(指标描述),周期和价格设定
4.2.4.4.//--- create buffers
((CIndicatorBuffer*)At(0)).Name("MAIN_LINE");
((CIndicatorBuffer*)At(1)).Name("SIGNAL_LINE");
**注  
class CArrayObj继承于public CArray类中定义了,它在共有方法定义了 CObject   *At(const int index) const;//--- method of access to thre array
以及保护变量 CObject *m_data[];  
CObject类中定义了CObject类型的指针变量 *m_prev和*m_next,
//| Access to data in the specified position     
At方法代码:                    |
CObject *CArrayObj::At(const int index) const
  {
//--- check
   if(index<0 || index>=m_data_total)
      return(NULL);
//--- result
   return(m_data[index]);
  }


4.3. //--- adjusted parameters  在生成类的保护变量区中的可调变量(如 int   m_period_fast)应与参数描述块一致。
定制signal时更加自己信号相应指标参数

4.4.  //--- "weights" of market models (0-100) 部分是给交易信号的各种交易模型以相应的权重。
也可以不给各种pattern信号相应权重。
这里可以看到有6个model,从注释中可以大概了解各个模型意思
   model 0 "the oscillator has required direction"                      震荡指标有了所需要的开仓方向
   model 1 "reverse of the oscillator to required direction"       震荡指标反转到所需要的开仓方向
   model 2 "crossing of main and signal line"                            MACD线与macd的signal线交叉
   model 3 "crossing of main line an the zero level"                  MACD线与0轴交叉
   model 4 "divergence of the oscillator and price"                   震荡指标与价格发生背离
   model 5 "double divergence of the oscillator and price"      震荡指标与价格双背离
4.4     //--- variables   给出了震荡指标的极值、该极值对应的价格、该极值偏移K线根数、震荡指标与其价格的位掩码结果(后面会阐述意思)

5.公有区成员函数  public:
构建和析构函数、可调参数的设定方法(与可调变量定义个数一致);交易模型可调权重方法;设置验证方法;创建指标和时间序列数据方法,检查生成的模型的方法。
构建CSignalMyCustInd(void);和析构函数~CSignalMyCustInd(void);、可调参数的设定方法(与可调变量定义个数一致);交易模型可调权重方法在定制交易信号时做相应修改其他基本相同照抄。

6. 保护区成员函数:一般取得数据的短小成员函数用内联函数,有的用CIndicator类中的GetData方法直接获取。
6.1 GetData方法有3个同名函数的重载,分别是1.指定开始位置和元素的个数CopyBuffer;2.指定开始时间和结束时间CopyBuffer,3.直接指定元素位置通过buffer.At(index)获取(其中CIndicatorBuffer *buffer=At(buffer_num);)(At方法从父类Series调用它的父类CArrayDouble的方法,形如m_data[index]据数列下标取得数据,
6.2 CIndicatorBuffers类(里面成员变量name,offset,主要成员函数offset,Name,At,Refresh)继承于CDoublebuffer(里面成员变量symbol,period,size,成员函数Size,At,Refresh,SetSymbolPeriod),CIndicatorBuffers类为获得技术指标数据而生)
定制信号这块都需要根据自己的信号修改。

7.类声明以外的函数定义:
  1. 构建函数://--- initialization of protected data
  1. //+------------------------------------------------------------------+
  2. //| Constructor                                                                               |
  3. //+------------------------------------------------------------------+
  4. CSignalMACD::CSignalMACD(void) : m_period_fast(12),
  5.                                  m_period_slow(24),
  6.                                  m_period_signal(9),
  7.                                  m_applied(PRICE_CLOSE),
  8.                                  m_pattern_0(10),
  9.                                  m_pattern_1(30),
  10.                                  m_pattern_2(80),
  11.                                  m_pattern_3(50),
  12.                                  m_pattern_4(60),
  13.                                  m_pattern_5(100)
  14.   {
  15. //--- initialization of protected data
  16.    m_used_series=USE_SERIES_HIGH+USE_SERIES_LOW;
  17.   }
复制代码
主要是参数的初始化,一般都包括一句使用时间序列数据,例如m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;

m_used_series是有在class CExpertBase定义的
if(m_other_symbol || m_other_period)  return(0);
     return(m_used_series);
USE_SERIES_OPEN是在class CExpertBase定义的宏,例如:
#define IS_OPEN_SERIES_USAGE     ((m_used_series&USE_SERIES_OPEN)!=0)
自定义的信号可写成:CSignalMyCustInd::CSignalMyCustInd(void) , m_used_series根据策略需要使用的价格数据填入。

8.析构函数:一般为空
  1. //+------------------------------------------------------------------+
  2. //| Destructor                                                                                 |
  3. //+------------------------------------------------------------------+
  4. CSignalMACD::~CSignalMACD(void)
  5.   {
  6.   }
复制代码
自定义的信号可写成:CSignalMyCustInd::~CSignalMyCustInd(void)(){ }

9.ValidationSettings(void)
  1. //+------------------------------------------------------------------+
  2. //| Validation settings protected data.                                          |
  3. //+------------------------------------------------------------------+
  4. bool CSignalMACD::ValidationSettings(void)
  5.   {
  6. //--- validation settings of additional filters
  7.    if(!CExpertSignal::ValidationSettings())
  8.       return(false);
  9. //--- initial data checks
  10.    if(m_period_fast>=m_period_slow)
  11.      {
  12.       printf(__FUNCTION__+": slow period must be greater than fast period");
  13.       return(false);
  14.      }
  15. //--- ok
  16.    return(true);
  17.   }
复制代码
[先通过CExpertBase::Init(CSymbolInfo *symbol,ENUM_TIMEFRAMES period,double point) 对symbol和period赋值后,确保不是othersymbol和otherperiod(非MT5指定的时间周期),判断指标参数错误有时也放在这里,比如这里的 if(m_period_fast>=m_period_slow)
定制信号,函数名改下bool CSignalMyCustInd::ValidationSettings(void),没其他特别的事情照抄。

  10. InitIndicators(CIndicators *indicators):判断validationSeting通过否,时间序列数据是否就位了;
  1. //+------------------------------------------------------------------+
  2. //| Create indicators.                                                                     |
  3. //+------------------------------------------------------------------+
  4. bool CSignalMACD::InitIndicators(CIndicators *indicators)
  5.   {
  6. //--- check of pointer is performed in the method of the parent class
  7. //---
  8. //--- initialization of indicators and timeseries of additional filters
  9.    if(!CExpertSignal::InitIndicators(indicators))
  10.       return(false);
  11. //--- create and initialize MACD oscilator
  12.    if(!InitMACD(indicators))
  13.       return(false);
  14. //--- ok
  15.    return(true);
  16.   }
复制代码
定制信号,查找替换,函数名MACD替换为MyCustInd,InitMACD替换成InitMyCustomIndicator。
这两行代码干了什么事情,在第4项有较多讲述。

11. Init指标名称(CIndicators *indicators):把MACD加入指标集合中,检查symbol和period设置正确否,创建指标句柄。
  1. //+------------------------------------------------------------------+
  2. //| Initialize MACD oscillators.                                                       |
  3. //+------------------------------------------------------------------+
  4. bool CSignalMACD::InitMACD(CIndicators *indicators)
  5.   {
  6. //--- add object to collection
  7.    if(!indicators.Add(GetPointer(m_MACD)))
  8.      {
  9.       printf(__FUNCTION__+": error adding object");
  10.       return(false);
  11.      }
  12. //--- initialize object
  13.    if(!m_MACD.Create(m_symbol.Name(),m_period,m_period_fast,m_period_slow,m_period_signal,m_applied))
  14.      {
  15.       printf(__FUNCTION__+": error initializing object");
  16.       return(false);
  17.      }
  18. //--- ok
  19.    return(true);
  20.   }
复制代码

这里直接调用了CiMACD类的Create方法(系统帮咱编好了,不再需要设置参数啥的啦)。但定制信号这里要先设置参数parameter的type和值string_value或integer.value等,调用Indicator类中的Create方法,之前有详述,这里要加快,后面有关键的信号如何代码实现,那里烧脑要啰嗦啰嗦,是核心内容,写了这么多还没到核心内容




12. 从这开始进入关键的进出场条件的判断阶段了,前面全部是铺垫的检查准备数据阶段。
      检查指标的状态,这个不是所有策略都需要的。

  1. //+------------------------------------------------------------------+
  2. //| Check of the oscillator state.                                                    |
  3. //+------------------------------------------------------------------+
  4. int CSignalMACD::StateMain(int ind)
  5.   {
  6.    int    res=0;
  7.    double var;
  8. //---
  9.    for(int i=ind;;i++)
  10.      {
  11.       if(Main(i+1)==EMPTY_VALUE)
  12.          break;
  13.       var=DiffMain(i);                                // 第i根K线与前一根K线MACD差值
  14.       if(res>0)                                           //之前的MACD值是延续第i根K线MACD差值方向
  15.         {
  16.          if(var<0)
  17.             break;
  18.          res++;                                             // MACD值不减少,res++
  19.          continue;
  20.         }
  21.       if(res<0)
  22.         {
  23.          if(var>0)
  24.             break;
  25.          res--;                                                 // MACD值不增加,res--
  26.          continue;
  27.         }
  28.       if(var>0)                                             // MACD值增加,res++
  29.          res++;
  30.       if(var<0)
  31.          res--;                                               // MACD值减少,res++
  32.      }
  33. //---
  34.    return(res);
  35.   }
复制代码
返回连续的(与上根K线MACD差值为0也算同趋势)保持第i根K线的MACD走势的之前(偏移)的第几根K线


13. 英文注释段大概解释了这个函数的目的。
  1. //+------------------------------------------------------------------+
  2. //| Extended check of the oscillator state consists                  |
  3. //| in forming a bit-map according to certain rules,                 |
  4. //| which shows ratios of extremums of the oscillator and price.     |
  5. //+------------------------------------------------------------------+
  6. bool CSignalMACD::ExtState(int ind)
  7.   {
  8. //--- operation of this method results in a bit-map of extremums
  9. //--- practically, the bit-map of extremums is an "array" of 4-bit fields
  10. //--- each "element of the array" definitely describes the ratio
  11. //--- of current extremums of the oscillator and the price with previous ones
  12. //--- purpose of bits of an element of the analyzed bit-map
  13. //--- bit 3 - not used (always 0)
  14. //--- bit 2 - is equal to 1 if the current extremum of the oscillator is "more extreme" than the previous one
  15. //---         (a higher peak or a deeper valley), otherwise - 0
  16. //--- bit 1 - not used (always 0)
  17. //--- bit 0 - is equal to 1 if the current extremum of price is "more extreme" than the previous one
  18. //---         (a higher peak or a deeper valley), otherwise - 0
  19. //--- in addition to them, the following is formed:
  20. //--- array of values of extremums of the oscillator,
  21. //--- array of values of price extremums and
  22. //--- array of "distances" between extremums of the oscillator (in bars)
  23. //--- it should be noted that when using the results of the extended check of state,
  24. //--- you should consider, which extremum of the oscillator (peak or valley)
  25. //--- is the "reference point" (i.e. was detected first during the analysis)
  26. //--- if a peak is detected first then even elements of all arrays
  27. //--- will contain information about peaks, and odd elements will contain information about valleys
  28. //--- if a valley is detected first, then respectively in reverse
  29.    int    pos=ind,off,index;
  30.    uint   map;                 // intermediate bit-map for one extremum
  31. //---
  32.    m_extr_map=0;
  33.    for(int i=0;i<10;i++)
  34.      {
  35.       off=StateMain(pos);                 // 距离pos(初值是ind)的MACD极值找到了,赋给off
  36.       if(off>0)
  37.         {
  38.          //--- minimum of the oscillator is detected
  39.          pos+=off;                                 //pos=pos+off,距离当前是pos根K线
  40.          m_extr_pos[i]=pos;                  // 记录MACD极值的位置
  41.          m_extr_osc[i]=Main(pos);        // 记录MACD极值的价格
  42.          if(i>1)//如果i的前2根k线或以前
  43.            {
  44.             m_extr_pr[i]=m_low.MinValue(pos-2,5,index);//第pos-2根K线往前5根K线最低价,如果第//2根K线是极值,比较范围是包括当前价的(即使tick工作模式是FALSE)
  45.             //--- form the intermediate bit-map
  46.             map=0;
  47.             if(m_extr_pr[i-2]<m_extr_pr[i])
  48.                map+=1;  // set bit 0   ,二进制 0001, 第i个极值价格小于之前2位的极值价格
  49.             if(m_extr_osc[i-2]<m_extr_osc[i])
  50.                map+=4;  // set bit 2      二进制 0100, 第i个极值MACD值小于之前2位的MACD极值
  51.             //--- add the result
  52.             m_extr_map+=map<<(4*(i-2));  //map值左移4*(i-2)位
  53.            }
  54.          else
  55.             m_extr_pr[i]=m_low.MinValue(pos-1,4,index);
  56.             //当前根或上根K线是最低价,从上根或上上根K线起往前4根K线范围的最低价赋给        //m_extr_pr[i]
  57.         }
  58.       else
  59.         {
  60.          //--- maximum of the oscillator is detected
  61.          pos-=off;
  62.          m_extr_pos[i]=pos;
  63.          m_extr_osc[i]=Main(pos);
  64.          if(i>1)
  65.            {
  66.             m_extr_pr[i]=m_high.MaxValue(pos-2,5,index);
  67.             //--- form the intermediate bit-map
  68.             map=0;
  69.             if(m_extr_pr[i-2]>m_extr_pr[i])
  70.                map+=1;  // set bit 0
  71.             if(m_extr_osc[i-2]>m_extr_osc[i])
  72.                map+=4;  // set bit 2
  73.             //--- add the result
  74.             m_extr_map+=map<<(4*(i-2));
  75.            }
  76.          else
  77.             m_extr_pr[i]=m_high.MaxValue(pos-1,4,index);
  78.         }
  79.      }
  80. //---
  81.    return(true);
  82.   }
复制代码

通过4位二进制位图每个位的0或1的取值来描述MACD极值及其对应的价格

第0位等于1--当下价格比前面更加极端(更高或更低),0--不是更极端。
第1位等于0--没使用,总是0
第2位等于1--当下的MACD比前面更加极端(更高或更低),0--不是更极端。
第3位--    0-- 没使用,总是0


该方法会产生3个数组,MACD极端值数组,价格极端值数组,相邻极端值K线间距数组。
有趣的是,需要考虑哪种MACD的极值作为参考点。 如第一次发现了最高值那么数组中的偶数下标元素都包含了该最高值的信息,如果第一次发现的是最低值,奇数下标元素都包含了该最低值的信息。
因为它在最近的10根K线里寻找和记录波峰和波谷,她们总是间隔产生的。

看什么时候有时间再接着写......
举报

评论 使用道具

精彩评论3

ken138888
B
| 发表于 2022-12-29 07:02:34 | 显示全部楼层
谢谢分享
举报

点赞 评论 使用道具

daerwushen
DD
| 发表于 2022-12-29 09:20:02 | 显示全部楼层
MACD源码
举报

点赞 评论 使用道具

xxtz
DD
 楼主 | 发表于 2022-12-29 15:11:01 | 显示全部楼层

MACD是系统自带的(标准库文件),在MT5的   indicator/Example/能找到
举报

点赞 评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册

天眼云VPS
简体中文
繁體中文
English(英语)
日本語(日语)
Deutsch(德语)
Русский язык(俄语)
بالعربية(阿拉伯语)
Türkçe(土耳其语)
Português(葡萄牙语)
ภาษาไทย(泰国语)
한어(朝鲜语/韩语)
Français(法语)