在MQL5中一起学习和写作 - 页 35

 

谁知道我是否可以把一个非类成员 的函数作为一个参数传递给另一个根本不是任何类成员的函数的引用(地址)?

或者,我可以把一个函数作为参数传递给一个类成员,作为对另一个根本不是任何类成员的函数的引用(地址)吗?

Документация по MQL5: Основы языка / Типы данных / Структуры и классы
Документация по MQL5: Основы языка / Типы данных / Структуры и классы
  • www.mql5.com
Основы языка / Типы данных / Структуры и классы - Документация по MQL5
 
victorg:

谁知道我是否可以把一个非类成员 的函数作为一个参数传递给另一个根本不是任何类成员的函数的引用(地址)?

或者,我可以把一个函数作为参数传递给一个类成员,作为对另一个根本不是任何类成员的函数的引用(地址)吗?

不,不。

你不能。在MQL5中,没有 "函数地址 "或 "函数引用 "这样一个概念。

 

谢谢你!

另一个问题。

mql5中有两个带有代码的文件 第一个文件 是主文件--指标或脚本。第二个文件 mqh

// f_01.mqh
double extfunc(int a);
//-------------------------------------
double example(void)
  {
  double a;
  a=extfunc(35);
  return(a);
  }
//-------------------------------------
第二个mqh-文件在一开始就与主文件相连。 主文件的编译没有错误或警告 但当我试图单独编译 mqh-file,我得到了' 函数 必须 一个 '我的问题是,我怎样才能告诉编译器,这个函数没有问题,但它的主体在另一个文件中?


Документация по MQL5: Файловые операции / FileMove
Документация по MQL5: Файловые операции / FileMove
  • www.mql5.com
Файловые операции / FileMove - Документация по MQL5
 
victorg:

第二个mqh-文件被包含在主文件的开头。 主文件的编译没有错误和警告 但是,当我们试图单独编译 mqh-file,我们得到了' 函数 必须 一个 的主体'我的问题是:如何告诉编译器该函数没有问题,但其主体在另一个文件中?
没有办法。不要把它拆开,这并不能使它在阅读代码时更容易理解。
 
Yedelkin:

我可能反应过激了,但这里还有一个问题。在发送下市价单的请求(开仓)之前,我将交易票据重置为零,即我让 result.deal=0。我们能否期望服务器在MqlTradeResult 响应结构中返回一个空的交易票据,但稍后,交易将被执行,头寸将被打开?或者说,服务器返回的空交易单是否能保证该仓位无法打开,并且不会根据该请求进一步打开?

好吧,由于缺乏回应,并凭借这句话

struct MqlTradeResult
{
ulong deal;// Ticket to deal,if it was done
};

我的结论是,服务器返回的空交易单保证了该头寸不能被打开,并且不会根据这个请求进一步打开。

 

我不太了解论坛的结构,如果不在那里,请指引我到正确的方向。

由于我不是专家,但我对编程感兴趣,在培训过程中从自己的倾向出发,我试图通过分析现有的代码来了解

为了简单起见,我取了一段MA的自定义代码,并试图理解其中发生的情况(我在注释中反映了这一点)。

一般来说,如果不难的话,请对代码进行评论,我想了解每个命令之后会发生什么。谢谢你。

void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double&price[])//I figured it out &price[].

  {
   int i,limit;
//--- first calculation or number of bars was changed
   if(prev_calculated==0)// first calculation
     {
      limit=InpMAPeriod+begin;                                               //почему переменная begin=0 ???
      //--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            //здесь инициализируются значения индикатора на барах с индексами от 0 до limit-1 ??? крайне правых на графике???
      //--- calculate first visible value
      double firstValue=0;                                                    //при инициализации переменной имеющей тип double не обязательно использовать значения типа double???
      for(i=begin;i<limit;i++)
         firstValue+=price[i];                                               //разобрался, здесь идет накопление переданной цены
      firstValue/=InpMAPeriod;
      ExtLineBuffer[limit-1]=firstValue;                                      
     }
   else limit=prev_calculated-1;                                              //в результате чего prev_calcutated не должно равняться 0, если индикатор поместили на оффлайн график?
//--- main loop
   for(i=limit;i<rates_total && !IsStopped();i++)                              //цикл для индикатора на баре с индексами от limit до последнего на графике
      ExtLineBuffer[i]=ExtLineBuffer[i-1]+(price[i]-price[i-InpMAPeriod])/InpMAPeriod;
//---
  }

把它放在打印输出中,看到ExtLineBuffer中的值是从索引limit-1到索引rate_total-1 分配的,但在图表中,指标是在整个空间中绘制的,嗯,那么在1到 limit-1的区间上,指标缓冲区 值分配哪里

Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
Документация по MQL5: Основы языка / Операции и выражения / Операции присваивания
  • www.mql5.com
Основы языка / Операции и выражения / Операции присваивания - Документация по MQL5
 
Profi_R:

我不太了解论坛的结构,如果不在那里,请指引我到正确的方向。

由于我不是专家,但我对编程感兴趣,在培训过程中从自己的倾向出发,我试图通过分析现有的代码来了解

为了简单起见,我取了一段MA的自定义代码,并试图理解其中发生的事情(我在注释中反映了这一点)。

我想了解每个命令之后会发生什么。谢谢你。

我不会详细评论,这可能足以纠正你认知的基本错误,然后你会自己把拼图拼起来--这更有用。

所以,你的困惑的基础是,mql5中的许多指标(特别是这个)是在没有指标缓冲区索引的情况下编写的,也就是说,AsSeries=false这个值。

这意味着历史上最古老的酒吧的索引=0,"最新鲜 "的酒吧=RatesTotal-1。

// 有什么事情是清楚的吗?

这种方法的要点是在速度上有所提高,因为索引不需要在访问缓冲区时进行[隐藏的]重新计算(它仍然是 "硬件")。

//也许是(错误的)认为,指标缓冲区的索引总是从历史的尽头发生到开头这在mql4中一直是真实的,但在mql5中则没有必要

// 这里,索引的方向默认总是从历史的开始到结束。 要扭转索引,你应该使用SetAsSeries(...)函数的明确形式。

// 注意,开发者不建议使用默认值(以防止它们发生变化),一定要使用SetAsSeries()函数来设置索引方向

void CalculateSimpleMA(int rates_total,int prev_calculated,int begin,const double&price[])//I sorted out &price[]

把它放到打印输出中,看到ExtLineBuffer中的值是从索引limit-1到索引rate_total-1 分配的,但在图表中,指标是在整个空间中绘制的,嗯,那么在1到 limit-1的区间中 分配指标缓冲区 哪里

我想你可以自己想出来,但为了以防万一,我明天会去看看。
 
MetaDriver: ..

谢谢你的反馈意见)。

我读过关于数组中指令性的顺序以及在帮助中明确指定指令性的建议,但我有一些疑问,在取消变量中的中间数据设置后,这些疑问被消除了。

到目前为止,只确定了方向性,也就是说,关于初始化的评论是不正确的,指标缓冲区的值在图表左侧的指定范围内被初始化。

仍然存在以下问题

1.变量begin,终端是否负责将其值传递给事件处理程序?

2. 双重类型的变量可以传给int类型吗?

3.似乎终端也对变量prev_calculated的值负责。

4.不清楚从0到limit-1区间的指标计算 是在哪里进行的?

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
Основы языка / Функции / Функции обработки событий - Документация по MQL5
 
Profi_R:

仍然存在以下问题

1.begin变量,终端是否负责将其值发送给事件处理程序?

3.似乎变量prev_calculated的值也是造成终端的原因。

最有可能的是,讨论中的函数是为OnCalculate()函数调用的第一种形式编写的。见参考资料。

Profi_R:

我们仍有以下问题

2.一个双数类型的变量可以用一个int类型的值来代替吗?

是的,你可以。见隐式类型转换一节。在使用隐式类型转换时,编译器通常会给出一个警告,即可能会丢失数据。

Profi_R:

仍然存在着以下问题

4.我不明白指标 在哪里计算,从0到极限1的区间。

这些句子是否回答了你的问题。

//--- set empty value for first limit bars
      for(i=0;i<limit-1;i++) ExtLineBuffer[i]=0.0;                            
//--- calculate first visible value
... и далее по коду
?
 
Profi_R:

谢谢你的反馈意见)。

我读过关于数组中指令性的顺序以及在帮助中明确指定指令性的建议,但我有一些疑问,在取消变量中的中间数据设置后,这些疑问被消除了。

到目前为止,只确定了方向性,也就是说,关于初始化的评论是不正确的,指标缓冲区的值在图表左侧的指定范围内被初始化。

好的。

仍然存在以下问题

1.变量begin,终端是否负责将其值发送给事件处理程序?

是的,终端负责将其传输给指示器。


该参数向指标指出有多少输入系列的初始历史值应被忽略(跳过),因为它们不正确,不应参与计算。 这种不正确从何而来,它的起源是什么?这与创建指标的可能性有关,这些指标不是根据价格数据计算的,而是根据其他指标提供的数据计算的。 在MT5中,有三种机制允许接收其他指标的数据作为指标输入。

方法1.步骤的顺序。

使用iIndicator(...) 函数或IndicatorCreate(...)函数之一为输入指标创建一个句柄。

2.根据需要,使用CopyBuffer(...) 函数从其缓冲区取值。

第二种方式。如果在第一种情况下,我们想传递的不是一个价格系列,而是一个指标系列到输入 指标,这是必要的。 也就是说,在这种情况下,我们将接收由输入指标(2)计算的值,该指标在它自己的输入上接受另一个指标(1)的数据。 也就是说,我们想建立指标-完全-指标链。

步骤的顺序。

1. 使用iIndicator(...) 函数或IndicatorCreate(...)函数之一为第一个(1)输入指标创建一个句柄。

2.用同样的方法创建第二个(2)指标的句柄,但在创建时指定第一个(1)指标的句柄作为最后一个参数(applied_price)。

使用CopyBuffer(...) 函数,根据需要从指标缓冲区检索其值。

第三种方法也用于建立指标链,但与前一种方法不同的是,数据源(输入序列)在编译前并不固定,它可以由用户直接在终端设置。 通过 在指标启动的时刻 指定适当的参数。

我将让你自己去理解这些机制。 我在前面的文字中提供了很多直接的链接,以帮助你在文件中的关键位置做到这一点。

让我们只关注调用OnCalculate()的简短形式的参数。

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])

它们的目的有相当明确的记载。在这里,我只想解释一下把它们放到这个函数中的必要性(合理性)。 有了第一个和最后一个参数,我希望一切都足够清楚了。为了进行计算,我们必须有一个包含输入数据(price[])的缓冲区,并知道其当前 长度。(别忘了,它的长度随着引号在终端的填充而增加)。

但除此之外,我们还必须从输入行的一开始就知道其数据是严格正确的,或者由于其(可能的或保证的)不正确,初始值应被忽略。在大多数情况下,当 输入数据是另一个指标的输出 时,不正确性是可以保证 的,但还能怎样?大多数指标为了计算任何一个柱状体的价值,必须使用一定量的历史数据。 但是在哪里可以找到 "时间的开始 "呢? 它们不存在,因此它们被迫不是从开始的历史柱状体开始生成它们的输出值,而是在后来(向右),从已经存在必要量的历史数据的左边的柱状体开始生成。

现在,由于我上面描述的细节,问题的答案是

它的值从哪里来? //我们正在讨论参数begin的问题。

答案是:尽管这个参数是由终端在函数中传递的,但输入指示器必须照顾其内容!终端本身只能检查价格输入行(在这种情况下,begin的值将是0,这是一个正确的值)。因此,当你编写任何指标时(除了纯粹的实验性指标),你应该确保 它通知终端关于其输出缓冲区中正确数据的开始索引。 清楚了吗?否则,这个指标的 "后代 "会吃到非常不愉快的不正确数据,在某些情况下,他们甚至会生病......。:) 现在,如何做,使用PlotIndexSetInteger()函数,通过指定PLOT_DRAW_BEGIN属性的标识符。 重要!为了使生成的指标属性100%正确,单次调用PlotIndexSetInteger(....PLOT_DRAW_BEGIN, ...)在OnInit()中!为什么这么说? 因为我们的指标本身可以在另一个指标的数据上形成,这个指标在历史上有一个初始缩进。也就是说,我们在输入历史上有一个非零的begin值,而在OnInit()中没有可能接收到它。

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod-1+begin);

而且我们必须在OnCalculate()中进行(最好是一次),因为在OnInit中begin的值是未知的。

这当然也给我们留下了一个初步的(虽然意义不大)呼吁的权利

  PlotIndexSetInteger(MySymbol,PLOT_DRAW_BEGIN,MyBeginPeriod);

在OnInit()中。

这正是你用来研究的那个指标(Custom Moving Average.mq5)的做法。

2. 双重类型的变量可以是int类型的吗?

是的,一个双倍类型的变量可以不费吹灰之力地用一个int类型的值来初始化,如果它是由一个常量定义的。//这正是我们在你的例子中可以做到的。

3.似乎终端也要对变量prev_calculated的值负责

这里有一个微妙的问题。在大多数情况下,这个值将等于前一个调用中OnCalculate()函数返回的值。换句话说,事实上,它就在你的手中。:) 另一方面, 在第一次调用时,会有一个零值。 此外, 当终端需要时,该值可以(由终端)始终重置为零。例如,这可能发生在经纪人的报价修正期间,在中断后的通信重启期间,在重新初始化以前的(输入)指标期间,等等。

4.不清楚在0到极限1的区间内,指标的计算 位置。

在这种情况下,这些数值无法正确计算(我们没有足够的历史数据用于计算)。 这就是为什么它们被简单地分配为零值。

// 我更愿意给他们分配相应的输入数据,但这并不改变事情的本质。