文章 "扩展 MQL5 标准库和重用代码" - 页 2

 
Tango_X:


请帮助我理解这里如何设置 指标缓冲数组的索引方向,即与 ArraySetAsSeries 相同。默认方向是从现在到过去,但我需要从过去到现在。我从昨天开始就一直在纠结这个问题!帮帮我!

不需要,因为它使用的是标准的 ZigZag。

//--- 创建
   m_handle=iCustom(symbol,period,"zigzag",depth,deviation_create,backstep);

请在此ZigZag 中查找设置方向的位置,但仍不清楚为什么需要它 - 您可以随时自行更改索引方向 -https://www.mql5.com/zh/docs/series。

Документация по MQL5: Доступ к таймсериям и индикаторам
Документация по MQL5: Доступ к таймсериям и индикаторам
  • www.mql5.com
Доступ к таймсериям и индикаторам - справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Rashid Umarov:

不需要,因为它使用的是标准的 ZigZag(之字形)。

在这个"之 "字形 中,请查找设置方向的位置。 但仍不清楚为什么需要它--您可以随时自行更改索引方向 -https://www.mql5.com/zh/docs/series。


感谢您提供的信息,我们将对此进行研究!

 
Rashid Umarov:

不需要,因为它使用的是标准的 ZigZag 字形

在这个ZigZag 中,您可以找到设置方向的地方。 但仍然不清楚为什么需要它 - 您可以随时自行更改索引方向 -https://www.mql5.com/zh/docs/series。


我很抱歉,但还是不清楚如何改变索引方向,例如,如果你无法访问 Zigzag 源的话。索引方向是通过 ArraySetAsSeries() 设置的,输入参数是一个数组引用、

但我们没有这个数组,只有一个指向指示器缓冲数组的指针,形式为

//--- 创建缓冲区
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
 
//+------------------------------------------------------------------+
//|OOO_ZIGZAG.mq5
//| 版权所有 2017, MetaQuotes Software Corp.
//|https://www.mql5.com | |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#include <..\Include\Indicators\Indicator.mqh>


//--- 输入参数
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_CURRENT; //计划期
input string            CurrencyPair="EURUSD.m"; //符号

//+------------------------------------------------------------------+
//| Class CiZigZag.|
//| 用途:"之 "字形指示器类。
//| CIndicator 类的输出。|
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- 访问受保护数据的方法
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- 创建方法
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- 访问指标数据的方法
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- 识别方法
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- 个性化方法
   virtual bool      Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[]);
   bool              Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                                const int depth,const int deviation_init,const int backstep);
  };
//+------------------------------------------------------------------+
//| 构造函数|
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| 销毁器|
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//|| 创建 "之 "字形指示器|
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- 检查历史记录
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- 创建
   m_handle=iCustom(symbol,period,"Examples\\ZigZag",depth,deviation_create,backstep);
//--- 检查结果
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- 指标创建成功
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- 初始化错误
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| 使用通用参数初始化指标 | //| 使用通用参数初始化指标 | //| 使用通用参数初始化指标 | //| 使用通用参数初始化指标
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
// 使用特殊参数初始化指标
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- 渲染状态行
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- 保存设置
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- 创建缓冲区
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- 错误
   return(false);
  }
//+------------------------------------------------------------------+
//| 访问 "之 "字形指示符的 "之 "字形缓冲区
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- 检查
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| 访问 "之 "字形指标的高点缓冲区
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
   //--- 检查
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| 访问 "之 "字形指标的低位缓冲区
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- 检查
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+



CiZigZag *Zig;
//+------------------------------------------------------------------+
//| 自定义指示器初始化函数
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 指示器缓冲区映射
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);
//---
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   delete(Zig);
  }  
//+------------------------------------------------------------------+
//| 自定义指标迭代函数
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int limit;
   if(prev_calculated==0)limit=0;
   else
     limit=prev_calculated-1; 
     
   for(int i=limit;i<rates_total && !IsStopped();i++)
      {
       Zig.Refresh();
       if (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]);  
      }
//--- 为下一次调用返回 prev_calculated 的值
   return(rates_total);
  }
//+------------------------------------------------------------------+

以下是该指标的完整代码,其中指标值的输出是从现在到过去,反之亦然。

 
Tango_X:

很抱歉,但仍不清楚如何改变索引方向,例如在无法访问源 Zigzag 的情况下。索引方向由 ArraySetAsSeries() 设置,其中输入参数是一个数组引用、

但我们没有这个数组,只有一个指向指示器缓冲数组的指针,其形式为

CIndicator 基类有一个GetData 方法,可用于从指标缓冲区获取数据。

按起始位置和编号从指标缓冲区获取数据

int GetData(
const intstart_pos, // position
const intcount, // number
const int buffer_num, // 缓冲区编号
double&buffer[]// 数组
) 常量



然后,使用 ArraySetAsSeries 为数组设置所需的索引方向

 
Rashid Umarov:

CIndicator 基类有一个GetData 方法,可用于从指标缓冲区获取数据。

从指示器缓冲区中按开始位置和

int GetData(
const intstart_pos, // position
const intcount, // 数目
const int buffer_num, // 缓冲区编号
double&buffer[]// 数组
) 常量



然后,为数组设置所需的索引方向。

那么,访问指示器缓冲区的次数是两次,但访问方式不同?毕竟,下面我们已经可以访问指示器缓冲区的值?我们会得到一个中间数组 double &buffer[],我的理解对吗?

//+------------------------------------------------------------------+
//| 访问 "之 "字形指示符的 "之 "字形缓冲区
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- 检查
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
 
Rashid Umarov:

CIndicator 基类有一个GetData 方法,可用于从指标缓冲区获取数据。

从指示器缓冲区中按开始位置和

int GetData(
const intstart_pos, // position
const intcount, // 数目
const int buffer_num, // 缓冲区编号
double&buffer[]// 数组
) 常量



然后,使用 ArraySetAsSeries 为数组设置所需的索引方向。

我的理解正确吗?

CiZigZag *Zig;
double ArrZig[];
//+------------------------------------------------------------------+
//| 自定义指示器初始化函数
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 指示器缓冲区映射
   Zig=new CiZigZag;
   Zig.Create(CurrencyPair,EAPeriod,12,5,3);

   SetIndexBuffer(0,ArrZig,INDICATOR_CALCULATIONS);
   ArraySetAsSeries(ArrZig,false);

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete(Zig);
  }
//+------------------------------------------------------------------+
//| 自定义指标迭代函数
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int limit;
   if(prev_calculated==0) limit=0;
   else
      limit=prev_calculated-1;

   Zig.Refresh();
   Zig.GetData(0,rates_total-1,0,ArrZig);

   for(int i=limit;i<rates_total-1 && !IsStopped();i++)
     {

      //if (Zig.ZigZag(i)!=0) Print(Zig.ZigZag(i)," ",time[i]); 
      if(ArrZig[i]!=0) Print(ArrZig[i]," ",time[i]);
     }
//--- 为下一次调用返回 prev_calculated 的值
   return(rates_total);
  }
//+------------------------------------------------------------------+
您需要在每个 tick 复制整个历史记录?
 
Tango_X:

我的理解正确吗?

原来每次打勾都需要复制整个历史记录?

1.您可以在打开新条形图 时进行复制 2.

2.为什么每次都要获取所有指标值,同时还要注意索引方向? 这到底是什么任务?

 

如果以后要在图表中或通过 iCustom 使用一个简单的指标,为什么还要把它包装成一个类呢?

Второе решение лучше, потому что является объектно-ориентированным

为了 OOP 而 OOP,好吧。

 
Rashid Umarov:

1.可以打开一个新的条形图; 2.

2. 为什么每次都要获取所有指标值,同时还要考虑索引方向? 这到底是什么任务?


通过循环条件,问题已经解决,现在一切正常!