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

 
fxsaber:

这是个小问题。是的,编译器优化器还不知道如何优化这种字符串时刻。但是,字符串分配才是放慢速度的问题。

我相信它是主要的。哪种方法更有效:更快的字符串赋值或将其从代码中排除?当然,在有些情况下,我们需要字符串赋值本身,但我们有多少次这样的机会?在绝大多数情况下,我们只是在处理临时变量。

而这些字符串操作的实现速度如何,也是一个问题。你把它说得好像可以加速许多倍。我怀疑这一点。他们已经对那里的一切进行了多次的优化--过度优化。假设他们设法再挤出20-30%,也不会有什么影响。

顺便说一下,你没有尝试将字符串变量声明为常数吗?

因此,如果你在写这样的东西。

if ((OrderSymbol() == Symb) && (OrderMagicNumber == Magic))

最好把OrderSymbol条款放在一般条件的最后。

嗯,当然了。而且它与OrderSymbol或MQL没有关系。字符串操作本身就很昂贵,所以你不应该白白地使用它们。

 

因此在这之间

fxsaber:

例如,如果我们在FIBO上运行一个月的真实ticks,将是约100万ticks。如果在每一个tick上,你得到PositionGetString的值,并与之进行比较,性能是可以接受的,但如果你先把函数的结果赋给一个字符串变量,然后再进行比较,运行时间会增加一秒钟左右。


如果这看起来是一件小事,那是错误的设想。当这样的EA在优化模式下运行几千次时,多出的这一秒就会转化为额外的几个小时的等待时间。也就是说,一个无害的字符串赋值可能会在优化过程中造成额外的时间等待。要小心并考虑到这种细微差别。

我希望你自己明白,这种方法是非常低效的。为什么我们要在每个刻度 上获得PositionGetString?它在那里能改变什么?特别是考虑到你自己开设了这个职位,也就是说,一切都已经事先知道了。

因此,如果我们谈论的是速度优化,那么我们必须首先优化程序逻辑本身。

 
阿列克谢-纳沃伊科夫

而这些字符串操作的加速速度如何,也是一个问题。你把它说得好像可以加速许多倍。我怀疑这一点。他们已经对那里的一切进行了多次的优化--过度优化。即使你设法多榨出20-30%,也不会有什么不同。

有时。

顺便说一下,你难道没有尝试过将字符串变量声明为常量吗?

是的,我做到了。
 
阿列克谢-纳沃伊科夫

为什么要在每个刻度 上获取PositionGetString?那里能有什么变化?特别是考虑到你自己开设了这个职位,也就是说,一切都已经提前知道了。

好吧,如果我们在谈论优化性能,那么我们必须首先优化程序逻辑本身。

一个战斗机器人有这样的逻辑:在这样的时间间隔内,欧元兑美元应该没有开仓。如果有,就关闭它们。

你有一个未平仓的英镑兑美元头寸。我们怎样才能在不检查每个tick的情况下满足上述条件?

或者你建议为测试者编写一个特殊版本的专家顾问?在这里,一个人买了一个战斗机器人,正在测试它。如何在市场上解释一切以速度为导向的优化?

 
fxsaber:

有这种逻辑的战斗机器人--在这个时间间隔内,欧元兑美元应该没有开仓。如果有,就关闭它们。

你有一个未平仓的英镑兑美元头寸。我们怎样才能在不检查每个tick的情况下满足上述条件?

或者你建议为测试者编写一个特殊版本的专家顾问?在这里,一个人买了一个战斗机器人,正在测试它。我们是否应该在市场中写明,所有的东西都是为测试人员特别优化的速度?

那么,只检查当前开仓 的票据就足够了(从而保持一个数组)。如果有一张新票,那么所有其他检查都必须用它来进行。为什么我们要把同样的东西检查一百万次?

顺便说一下,MQL5有贸易活动。因此,没有必要在每次打勾时都检查它。

 
Alexey Navoykov:

那么,只检查当前开仓 的股票就足够了(并相应地维护一个数组)。

这将不会便宜很多。

顺便说一下,MQL5有贸易活动。因此,没有必要对每一个蜱虫进行检查。

有时会写出跨平台的解决方案。此外,不存在也不可能保证获得所有的贸易活动。

 
fxsaber:

这不会便宜很多。

整数操作与字符串操作相比,并没有便宜多少?好吧,随你便。

 
阿列克谢-纳沃伊科夫

整数操作与字符串操作相比,并没有便宜多少?好吧,随你便。

我不明白你为什么需要它,但你让我很困惑。而且我不得不同意,有一系列门票的选项会更有成效。

诚然,从一些逻辑的角度来看,这样的变体看起来非常做作,奠定了技术上的细微差别,而不是程序的逻辑构造。

但我还是会考虑到这一点。当然,我在kodobase中从未遇到过这种方法。

 

当然,MQL中缺乏多重继承是令人沮丧的。然而,你可以用任何可能的方式使它工作--用模板和宏--你将不需要它们 )

这是我所做的。所有的源类都应该被声明为定义父类的模板。

class CBase { };  // базовый класс

// Макросы, задающие список наследования:

#define  INHERIT1(T)  T<CBase>

#define  INHERIT2(T1, T2)  T2<INHERIT1(T1)>

#define  INHERIT3(T1, T2, T3)  T3<INHERIT2(T1,T2)>

#define  INHERIT4(T1, T2, T3, T4)  T4<INHERIT3(T1,T2,T3)>


// Различные пользовательские классы:

template<typename TParent>
class A : public TParent { public: void a() { Print("A"); } };

template<typename TParent>
class B : public TParent { public: void b() { Print("B"); } };

template<typename TParent>
class C : public TParent { public: void c() { Print("C"); } };


class X : public INHERIT3(A, B, C)  {  };   // Объявляем класс, наследуемый от A, B, C


template<typename T>
void SomeFunc(B<T>& obj)  { obj.b(); }   // Проверочная функция, принимающая класс B


void OnInit()
{
  X x;
  x.a();
  x.b();
  x.c();
  
  SomeFunc(x);
}

当然,还有一些微妙之处,与类是按顺序继承的(按照我们设定的顺序),而不是同时继承的(如真正的多重继承)这一事实有关。特别是,当发生过载时,它们会有不同的优先级。此外,如果一个相同的模板类多次参与继承链,它们将是完全不同的类,彼此之间没有任何关系。所以我们在这里必须小心。但是接口没有问题,你可以不受限制地继承。

 
阿列克谢-纳沃伊科夫

当然,MQL中缺乏多重继承是令人沮丧的。然而,你可以用任何可能的方式使它工作--用模板和宏--你将不需要它们 )

这是我所做的。所有的源类都应该被声明为定义父类的模板。

当然,还有一些微妙之处,与类是按顺序继承的(按照我们设定的顺序),而不是同时继承的(如真正的多重继承)这一事实有关。特别是,当发生过载时,它们会有不同的优先级。此外,如果一个相同的模板类多次参与继承链,它们将是完全不同的类,彼此之间没有任何关系。所以我们在这里必须小心。但在接口方面没有问题,你可以不受限制地继承。

这是个好把戏。整个诀窍在于将模式应用 于TParent。我以前没有见过这样的情况。