mql5语言的特点、微妙之处以及技巧 - 页 30

 

我一点也不明白...

我在指标中创建了一个标准AO的手柄,但有一个设定的时间框架。当我从AO收到的数据的时间框架与当前的不一致时,我得到...我什么也没得到--错误4806。

问题:从时间范围与当前时间范围不一致的标准指标中获取数据的正确方法是什么?

//+------------------------------------------------------------------+
//|                                                      iMTF_AO.mq5 |
//|              Copyright 2017, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property  indicator_label1  "AO"
#property  indicator_type1   DRAW_LINE
#property  indicator_color1  clrRed
#property  indicator_style1  STYLE_SOLID
#property  indicator_width1  1
//--- input parameters
sinput   ENUM_TIMEFRAMES   PeriodForWork  =  PERIOD_H4;  // Таймфрейм, с которого берём данные AO
//--- indicator buffers
double         Buffer[];
int   handle, error=ERR_SUCCESS;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   handle=iAO(NULL,PeriodForWork);
   if(handle==INVALID_HANDLE) return(INIT_FAILED);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   ArraySetAsSeries(Buffer,true);
   if(rates_total<1) return(0);
   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-1;
      }
   //---
   static string txt="";
   for(int i=limit; i>=0; i--) {
      Buffer[i]=AO(i);
      if(i<11 && i>0) {
         string ao=(Buffer[i]==EMPTY_VALUE?"EMPTY_VALUE":DoubleToString(AO(i),Digits()));
         txt+="\nAO("+(string)i+")="+ao;
         }
      }
   Comment("handle AO: ",handle,", TIMEFRAME AO: ",GetNameTF(PeriodForWork),", error: ",error,"\n-----------",txt,"\n-----------");
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
double AO(int shift){
   double array[1];
   error=ERR_SUCCESS;
   ResetLastError();
   if(CopyBuffer(handle,0,shift,1,array)==1) return(array[0]);
   else error=GetLastError();
   return(EMPTY_VALUE);
}
//+------------------------------------------------------------------+
string GetNameTF(int timeframe=PERIOD_CURRENT) {
   if(timeframe==PERIOD_CURRENT) timeframe=Period();
   switch(timeframe) {
      //--- MQL4
      case 1: return("M1");
      case 5: return("M5");
      case 15: return("M15");
      case 30: return("M30");
      case 60: return("H1");
      case 240: return("H4");
      case 1440: return("D1");
      case 10080: return("W1");
      case 43200: return("MN");
      //--- MQL5
      case 2: return("M2");
      case 3: return("M3");
      case 4: return("M4");      
      case 6: return("M6");
      case 10: return("M10");
      case 12: return("M12");
      case 16385: return("H1");
      case 16386: return("H2");
      case 16387: return("H3");
      case 16388: return("H4");
      case 16390: return("H6");
      case 16392: return("H8");
      case 16396: return("H12");
      case 16408: return("D1");
      case 32769: return("W1");
      case 49153: return("MN");      
      default: return("UnknownPeriod");
   }
}
//+------------------------------------------------------------------+
附加的文件:
iMTF_AO.mq5  9 kb
 
阿尔乔姆-特里什金

我一点也不明白...

我在指标中创建了一个标准AO的手柄,但有一个设定的时间框架。当我从AO收到的数据的时间框架与当前的不一致时,我得到...我什么也没得到--错误4806。

问题是什么,从时间框架与当前时间框架不一致的标准指标中获取数据的正确方法是什么?


关于在INDICATOR中获取INDICATOR值。

关于交易、自动交易系统和策略测试的论坛

如何在一个指标中从另一个指标中获取数据

Vladimir Karputov, 2016.12.27 08:41

考虑到在MQL5指标中,指数为 "0 "的条形图默认为图表上的左侧条形图,让我们尝试从其他两个指标--MA和Alligator(本例在指标 "IndicatorFromIndicators.mql5")获取数据到我们的指标。

让我们尝试从指数为 "0"、"1 "和 "2 "的柱子上接收MA和Alligator的数据。

  {
//---
   Comment("Проверка: time[0]=",time[0],"\n",
           "rates_total-1: ",rates_total,"\n",
           "BarsCalculated(iMA): ",BarsCalculated(handle_iMA),"\n",
           "BarsCalculated(iAlligator): ",BarsCalculated(handle_iAlligator),"\n",
           "MA[",0,"]=",StringFormat("%."+IntegerToString(Digits()+1)+"f",iMAGet(0)),"\n",
           "MA[",1,"]=",StringFormat("%."+IntegerToString(Digits()+1)+"f",iMAGet(1)),"\n",
           "MA[",2,"]=",StringFormat("%."+IntegerToString(Digits()+1)+"f",iMAGet(2)),"\n",
           "Jaws[",0,"]=",StringFormat("%."+IntegerToString(Digits())+"f",iAlligatorGet(GATORJAW_LINE,0)),"\n",
           "Jaws[",1,"]=",StringFormat("%."+IntegerToString(Digits())+"f",iAlligatorGet(GATORJAW_LINE,1)),"\n",
           "Jaws[",2,"]=",StringFormat("%."+IntegerToString(Digits())+"f",iAlligatorGet(GATORJAW_LINE,2)));
//--- return value of prev_calculated for next call
   return(rates_total);
  }

让我们把测试指标"IndicatorFromIndicators.mql5"附在图表上,并把十字准线设置在最右边的柱子上--即不是零柱这就是它看起来的样子。

从指标看指标

尽管十字准线被设置为最右边的柱子--即肯定不是索引为 "0 "的柱子,但在使用CopyBuffer 时,你应该注意CopyBuffer 将把数据从现在复制到过去,即索引为 "0 "的柱子意味着当前的柱子。


CopyBuffer:要复制的数据元素(指标缓冲区,索引为buffer_num)从现在的起始位置开始计算,即起始位置为0意味着当前的条形(当前条形的指标值)。


也就是说,在MQL5指标中,如果它使用CopyBuffer操作,你必须翻转数组(ArraySetAsSeries),使图表中最右边的条形对应于指标缓冲区的索引 "0"(现在在例子 "iMTF_AO.mq5 "中,图表中最右边的条形对应于rate_total-1)。

 
弗拉基米尔-卡尔普托夫


关于在INDICATOR中获取INDICATOR值。


CopyBuffer:复制的数据元素(指标缓冲区,索引为buffer_num)从现在的起始位置开始计算,也就是说,起始位置等于0表示当前的条形(当前条形的指标值)。


也就是说,在MQL5指标中,如果它使用CopyBuffer操作,你必须翻转数组(ArraySetAsSeries),使图表中最右边的条形对应于指标缓冲区的索引 "0"(现在在例子 "iMTF_AO.mq5 "中,图表中最右边的条形对应于rate_total-1)。

我只得到一个酒吧。而 "原生 "时间框架上的指标则正常显示数据。关于 "非本地"--空白值。我根据经验发现,在我从AO接收数据的时间范围内加载整个历史记录之前,会返回一个空值。

//+------------------------------------------------------------------+
//|                                                      iMTF_AO.mq5 |
//|              Copyright 2017, Artem A. Trishkin, Skype artmedia70 |
//|                       https://login.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70"
#property link      "https://login.mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Label1
#property  indicator_label1  "AO"
#property  indicator_type1   DRAW_LINE
#property  indicator_color1  clrRed
#property  indicator_style1  STYLE_SOLID
#property  indicator_width1  1
//--- input parameters
sinput   ENUM_TIMEFRAMES   PeriodForWork  =  PERIOD_H4;  // Таймфрейм, с которого берём данные AO
//--- indicator buffers
double         Buffer[];
int   handle, error=ERR_SUCCESS;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Buffer,INDICATOR_DATA);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   handle=iAO(NULL,PeriodForWork);
   if(handle==INVALID_HANDLE) return(INIT_FAILED);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   ArraySetAsSeries(Buffer,true);
   int bars=Bars(NULL,PeriodForWork);
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);
   if(rates_total<1) return(0);
   int limit=(PeriodForWork==Period()?rates_total-prev_calculated:limit_p);
   if(limit>1) {
      limit=rates_total-1;
      }
   //---
   static string txt="";
   for(int i=limit; i>=0; i--) {
      Buffer[i]=AO(i);
      if(i<6 && i>0) {
         string ao=(Buffer[i]==EMPTY_VALUE?"EMPTY_VALUE":DoubleToString(AO(i),Digits()));
         txt+="\nAO("+(string)i+")="+ao;
         }
      }
   Comment("handle AO: ",handle,", TIMEFRAME AO: ",GetNameTF(PeriodForWork),", error: ",error,"\n-----------",(error>0?"\nLoading history":txt),
           "\n-----------",
           "\nAO(1)=",DoubleToString(AO(1),Digits()),
           "\nAO(",limit_p,")=",DoubleToString(AO(limit_p),Digits())
          );
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
double AO(int shift){
   double array[];
   ArrayResize(array,1);
   ArrayInitialize(array,EMPTY_VALUE);
   error=ERR_SUCCESS;
   ResetLastError();
   if(CopyBuffer(handle,0,shift,1,array)==1) {
      ArraySetAsSeries(array,false);
      return(array[0]);
      }
   else error=GetLastError();
   return(EMPTY_VALUE);
}
//+------------------------------------------------------------------+
datetime GetTime(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const int shift) {
   datetime array[1];
   ResetLastError();
   if(CopyTime(symbol_name,timeframe,shift,1,array)==1) return(array[0]);
   Print(__FUNCTION__," > Ошибка получения времени бара ",shift,": ",GetLastError());
   return(0);
}
//+------------------------------------------------------------------+
int GetBarShift(const string symbol_name, const ENUM_TIMEFRAMES timeframe, const datetime time) {
   int res=WRONG_VALUE;
   datetime last_bar;
   if(SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE,last_bar)) {
      if(time>last_bar) res=0;
      else {
         const int shift=Bars(symbol_name,timeframe,time,last_bar);
         if(shift>0) res=shift-1;
         }
      }
   return(res);
}
//+------------------------------------------------------------------+
string GetNameTF(int timeframe=PERIOD_CURRENT) {
   if(timeframe==PERIOD_CURRENT) timeframe=Period();
   switch(timeframe) {
      //--- MQL4
      case 1: return("M1");
      case 5: return("M5");
      case 15: return("M15");
      case 30: return("M30");
      case 60: return("H1");
      case 240: return("H4");
      case 1440: return("D1");
      case 10080: return("W1");
      case 43200: return("MN");
      //--- MQL5
      case 2: return("M2");
      case 3: return("M3");
      case 4: return("M4");      
      case 6: return("M6");
      case 10: return("M10");
      case 12: return("M12");
      case 16385: return("H1");
      case 16386: return("H2");
      case 16387: return("H3");
      case 16388: return("H4");
      case 16390: return("H6");
      case 16392: return("H8");
      case 16396: return("H12");
      case 16408: return("D1");
      case 32769: return("W1");
      case 49153: return("MN");      
      default: return("UnknownPeriod");
   }
}
//+------------------------------------------------------------------+

那么问题来了:如何避免在加载历史的时间段内进入循环?这只是一个测试,而在一般情况下,指标是根据指定时间段的历史进行计算的,在没有历史之前,没有必要尝试进行计算。

附加的文件:
iMTF_AO.mq5  12 kb
 
阿尔乔姆-特里什金

我只得到一个酒吧。而 "原生 "时间框架上的指标则正常显示数据。在 "非本地 "中,它显示一个空白值。我根据经验发现,在我从AO接收数据的时间段内,所有的历史记录都被加载之前,会返回一个空值。

那么问题就不同了:如何不进入循环,而时间框架的历史正在加载?这只是一个测试。 一般来说,该指标根据指定时间段的历史进行计算,在没有历史之前,没有必要尝试进行计算。

你是否尝试过同步化?另外,开发商建议通过计时器保持所需的TF/符号数据的更新。
 
在这里。
      Buffer[i]=AO(i);

这个 "i "不是 "0",而是一些过高的数值。底线:假设我们在M15上运行这个例子--我们在这个时期有5000个柱子。我们要求提供H4的数据--我们在上面只有400条。然后我们尝试请求 "AO(4999)"。

也就是说,从H4时期开始,我们试图请求索引为 "4999 "的条形图--但H4上根本没有这样的条形图,那里只有400条,但我们请求条形图 "0",如果指标使用CopyBuffer操作,我们应该反转数组(ArraySetAsSeries),使图表中最右边的条形图对应于指标缓冲区 中的索引 "0"(现在在例子 "iMTF_AO.mq5 "中,图表上最右边条形图对应于rate_total-1)。

 

关于交易、自动交易系统和交易策略测试的论坛

虫子、虫子、问题

fxsaber, 2017.04.12 08:38

一个小小的提示。绕过赋值运算符
template <typename T>
struct STRUCT_COPY
{
  T Value;
  
  STRUCT_COPY( const T& tValue)
  {
    this = (STRUCT_COPY)tValue;
  }  
};

struct STRUCT
{
  int i;
  
  void operator =( const STRUCT& )
  {
    this.i = 5;
  }
};

#define  PRINT(A) ::Print(#A + " = " + (string)(A));

void OnStart()
{
  STRUCT Struct;  
  Struct.i = 1;  
  PRINT(Struct.i);
  
  STRUCT StructCopy1 = Struct;
  PRINT(StructCopy1.i);
  
  // Обходим void STRUCT::operator=(const STRUCT&)
  STRUCT_COPY<STRUCT> StructCopy2(Struct);
  PRINT(StructCopy2.Value.i);  
}

结果

Struct.i = 1
StructCopy1.i = 5
StructCopy2.Value.i = 1
 
弗拉基米尔-卡尔普托夫
在这里..:

这个 "i "不是 "0",而是一些过高的数值。底线:假设我们在M15上运行这个例子--我们在这个时期有5000个柱子。我们要求提供H4的数据--我们在上面只有400条。然后我们尝试请求 "AO(4999)"。

例如,从H4时期开始,我们试图请求索引为 "4999 "的条形图--但H4上没有这样的条形图,那里只有400条,但我们想要条形图 "0",如果指标使用CopyBuffer操作,我们应该反转数组(ArraySetAsSeries),使图表中最右边的条形图对应于指标缓冲区 的索引 "0"(现在在 "iMTF_AO.mq5 "例子中,最右边条形图对应于rate_total-1)。

不,我当然试图计算出极限

   int bars=Bars(NULL,PeriodForWork);                         
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);     
   if(rates_total<1) return(0);
   int limit=(PeriodForWork==Period()?rates_total-prev_calculated:limit_p);
   if(limit>1) {          
      limit=rates_total-1;
      }                   

...但我发现 匆忙中搞砸了--它只适合于当前的时间框架

 
阿尔乔姆-特里什金

不,我当然试图计算出极限

...但我明白了,我匆忙中 搞砸了--它只适合于当前的时间框架


  1. 反转缓冲区阵列(ArraySetAsSeries)--如果指标使用CopyBuffer,这是必须的。
  2. 请记住,CopyBuffer:复制的数据(指标缓冲区 的索引为buffer_num)的元素是从现在的 起始位置开始计算的,也就是说,起始位置为0意味着当前栏(当前栏的指标值)
之后在AO(开始的 "0 "意味着最右边的栏),而不是一些高昂的值。
 
弗拉基米尔-卡尔普托夫

  1. 反转缓冲区阵列(ArraySetAsSeries)--如果指标使用CopyBuffer,这是必须的。
  2. 请记住,CopyBuffer:复制的数据(指标缓冲区 的索引为buffer_num)的元素是从现在的 起始位置开始计算的,也就是说,起始位置等于0意味着当前栏(指标值为当前栏)
之后在AO(运行 "0 "意味着最右边的酒吧),而不是一些高昂的值。

你甚至看了我给你看的代码吗?还是你运行了它?

我没有问如何填充指标缓冲区,而是问为什么如果我从AO中取值而不是从当前条形图中取值,它们会返回空值。
我明白了--没有历史记录,它正在被加载,当它被加载时,来自非本地时间框架的AO返回错误 "没有数据"。

现在的问题是:如何知道所需时间框架的历史记录已经完全加载,以便不进入指标周期?

 
与本主题无关的评论已被移至"来自MQL5 MT5 MetaTrader 5初学者的问题"。