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

 
阿尔乔姆-特里什金

高亮显示的 可以返回0。BCS碰上了。

是的,歪门邪道的经纪人。他们也会把负数放在那里。

如果开发者在经纪人设置符号时对每个参数的可能取值范围有一个限制,那就更好了。

 
阿尔乔姆-特里什金

究竟哪里出了问题?这就是问题所在--我做错了什么,才会从一个非本地的时间框架中获得指标数据?

例如:指标在M1上运行,AO的数据应从M5上获得。因此,当我们有limit>1(历史需要重新计算)时,来自M5的AO返回零,没有数据错误。一旦历史数据被计算出来(limit==0),数据就开始从带有M5的AO处到达。

对于初学者来说--你不需要做这样的条目。

periodForWork=PeriodForWork;

起初我以为你是在给一个变量赋值。

下一步。

size_ao=CopyBuffer(handle_ao,0,0,count,array_ao);

在初始化过程中不需要复制。初始化不是为了这个目的。此外,当从较早的TFs请求数据时,这条记录将没有意义,因为在OnInit()请求的那一刻,TFs还没有被计算。

ArraySetAsSeries(BufferAO,true);

但这个记录只需在初始化阶段做一次就够了。

进一步...嗯...主观上,这不是我的做法。

我喜欢将该计划分为。

1.第一次运行(历史分析)。

2.随后的运行。

2.1. 每个勾。

2.2. 形成的酒吧。

I.e:

if( prev_calculated > 0 )             // Не первый запуск
{
 if( rates_total <= prev_calculated ) // Новый бар не сформирован
  {
  }
 else                                 // Новый бар сформирован
  {
  }
}
else                                  // Первый запуск
{
}

而后才是--主计算周期(功能)。

你的复制功能给出了无信息的错误。代码不是很好。

没有检查旧TF的数据是否同步。

而这里最重要的是要了解顺序。我建议创建一个测试指标,这样它就会在第一次启动时只要求主要的TF的数据,并了解复制是如何进行的。也就是把这个从代码的开头删除。

ArraySetAsSeries(array_ao,true);

并取消数组的 第一个和最后一个元素 的设置。然后,如果有必要,才改变索引的方向。

 
总之,从那里开始。
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
input   ENUM_TIMEFRAMES inpTimeframe=PERIOD_M5;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int _handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   _handle=iAO(_Symbol,inpTimeframe);
   if(_handle==INVALID_HANDLE)
     {
      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),"! Хэндл индикатора iAO ТФ "+EnumToString(inpTimeframe)+" не получен!");
      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[])
  {
//--- Массив-приемник значений индикатора
   double ao[];
//---
   if(prev_calculated>0)
     {

     }
   else                                        // Если первый запуск
     {
      //--- Количество просчитанных баров старшего ТФ
      int bars;
      if(( bars=BarsCalculated(_handle))<0 || !(bool)SeriesInfoInteger(_Symbol,inpTimeframe,SERIES_SYNCHRONIZED))
         return( 0 );
      //--- 
      int num=CopyBuffer(_handle,0,0,bars,ao);
      //---
      if(num<0)
        {
         Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Запрашиваемая таймсерия еще не построена!");
         return( 0 );
        }
      else if(num!=bars)
        {
         Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": Скопированы не все данные (",num," из ",bars,")");
         return( 0 );
        }
      //---
      Print(__FUNCTION__,": Успех! Скопировано ",num," из ",bars," значение индикатора АО ТФ "+EnumToString(inpTimeframe));
     }
//---
   return( rates_total );
  }
//+------------------------------------------------------------------+
 
阿列克谢-科齐岑

首先--你不需要做这样的条目。

我最初以为你是在给一个变量分配自己的值。

下一步。

在初始化过程中不需要复制。初始化不是为了这个目的。此外,当从较早的TFs请求数据时,这条记录将没有意义,因为在OnInit()请求的那一刻,TFs还没有被计算。

但这个记录只需在初始化阶段做一次就够了。

进一步...嗯...主观上,这不是我的做法。

我喜欢将该计划分为。

1.第一次运行(历史分析)。

2.随后的运行。

2.1. 每个勾。

2.2. 形成的酒吧。

I.e:

而后才是--主计算周期(功能)。

你的复制功能给出了无信息的错误。代码不是很好。

没有检查旧TF的数据是否同步。

而这里最重要的是要了解顺序。我建议创建一个测试指标,这样它就会在第一次启动时只要求主要的TF的数据,并了解复制是如何进行的。也就是把这个从代码的开头删除。

并取消数组的 第一个和最后一个元素 的设置。只有在那时,如果有必要,才改变索引的方向。

我做出的变量对我来说一目了然。如果你不理解他们,就用你理解的方式来做;)。

我总是在写非全局变量时用一个小字母开头--原因很简单:大小写敏感的智能...

这是测试代码,因为非测试代码足够大,在MT4上,当切换traf时,它就会飞起来,而且没有丢失数据的错误 - 一切都在那里。但MT5当我切换MTF时,只有半分钟的时间加载历史,然后不工作的数据不是他的TF - 说他们没有。

这就是为什么我讨论我做错了什么。事实证明,有必要为init中所有使用的客户请求数据。我认为,如果你事先不知道使用过的电话的估计数量,你需要全部要求。只有一个半分钟的时间算数。总共有21个...

又出问题了?

 
这对初学者 来说非常有用。

在MT5中,当切换一个ETF时,只需要半分钟的时间来下载历史记录。


写到了这一点

я правильно понимаю тогда, что подготовив кэш,терминал при последующих обращениях (начиная со 2 обращения) затрачивает на порядки меньше времени?

можно ли как-то уменьшить время первого обращения после перезагрузки терминала,чтобы было как в МТ4?
Теперь выводы:

    Разница только в скорости начальной инициализации кеша чарта 0.6 мс МТ4 против 113 мс у МТ5

更多详情请点击这里

https://www.mql5.com/ru/forum/1111/page1871#comment_4866969

https://www.mql5.com/ru/forum/1111/page1871#comment_4867939

它要求的TF或符号越多,启动速度就越慢。

Ошибки, баги, вопросы
Ошибки, баги, вопросы
  • www.mql5.com
Форум алго-трейдеров MQL5
 
kaus_bonus:


写到了这一点

更多详情请点击这里

https://www.mql5.com/ru/forum/1111/page1871#comment_4866969

https://www.mql5.com/ru/forum/1111/page1871#comment_4867939

查询的TF或字符越多,启动速度就越慢。

我认为,如果只有在指标首次启动时才会有好处。但当我切换时间框架时,每次切换时历史记录都要加载半分钟。我知道这不应该是这样的,但是...我做错了什么...只有在一个指标上发生这种情况--当我试图访问一个非本地的时间框架。
 
阿尔乔姆-特里什金
如果只有在我第一次启动指标时才会好。每次切换时间段,我都有半分钟的加载历史。我知道这不应该是这样的,但是...我做错了什么...我试图只在一个指标中访问一个非本地的时间框架。

那么,测量一下从另一个时间段复制数据的速度,看看瓶颈在哪里。
 
阿尔乔姆-特里什金

如果你需要使用来自不同TF的几个指标进行计算--你需要获得每个TF的手柄。

如果你想让它更快--减少终端中历史记录的大小。

你运行了我的测试指标吗?它在收集数据吗?

 
阿列克谢-科齐岑

如果你需要使用来自不同TF的几个指标进行计算--你需要获得每个TF的手柄。

如果你想让它更快--减少终端中历史记录的大小。

你运行了我的测试指标吗?它在收集数据吗?

不,我没有。

事实证明,如果我需要所有的时间段,我应该创建21个AO指标的手柄?这不是浪费吗?

 
Artyom Trishkin:

不,还没有运行。

事实证明,如果你需要所有的时间框架,你需要创建21个AO指标柄?这不是浪费吗?

我还能如何从正确的符号/TF中获得数据?CopyBuffer 只对句柄起作用。