错误、漏洞、问题 - 页 741

 
ivandurak:

我不太擅长解释。让我再试一次。任务是形成一个货币组合,每种货币都有自己的参数。在一个优化的投资组合中,一种货币可能不会参与。我在每一种货币的21个优化步骤中计算了六种货币,总和以十亿计。

现在的问题是。如果我们禁止一种货币与一个标志进行交易,那么优化其参数是没有意义的,反正它们不会以任何方式影响结果,但优化器将试图适应不影响结果的参数。像我自己一样,我知道你不能,但希望仍在茁壮成长。

是的,好的,会有不必要的传球。

如果TC允许,你应该分别优化每一对。

一般的优化涉及到imho落入魔法对冲的陷阱))。

还有另一个解决方案,与我提出的方向不同,但可以减少不必要的运行。

例如,你在50-150的区间内枚举了参数100。

这使选择的数量减少了一个维度。

input bool trpar2=true; // вЫключен флажок
input int grusdchf=100; // включен флажок перебора 49-150
input int grusdjpy=100; // включен флажок перебора 50-150

if (grusdchf==49)  // если 49 то запрет торговли
  {
   x_trpar2=false;
  }
 else              // иначе берет установленное значение флага и параметров
  {
   x_trpar2=trpar2;
  }

// далее по коду для запрета используем x_trpar2
 
ivandurak:

我不太擅长解释。让我再试一次。任务是形成一个货币组合,每种货币都有自己的参数。在一个优化的投资组合中,一种货币可能不会参与。我在每一种货币的21个优化步骤中计算了六种货币,总和以十亿计。

现在的问题是。如果我们禁止一种货币与一个标志进行交易,那么优化其参数是没有意义的,反正它们不会以任何方式影响结果,但优化器将试图适应不影响结果的参数。像我自己一样,我知道你不能,但希望仍在燃烧。

如果我有像Init()和Trade()这样的东西,对于每一对+参数已经选择好了,唯一剩下的就是确定股份,那么任务就可以解决了。虽然,不幸的是,在一般情况下,对于任何数量的系统 - 不能解决。

因此,我们需要指定步骤 "系统的分量"。对于6个系统,通过的次数由f-eye计算。

int PartCount6(double _mult) {
   int __= (int)(1.0 / _mult) + 1;
   int x, y, z, t, t1, t2, count = 0;
   for (t = 0; t < __; ++t) for (x = 0; x < __; ++x) 
      for (y = 0; y < __; ++y) for (z = 0; z < __; ++z) 
         for (t1 = 0; t1 < __; ++t1) for (t2 = 0; t2 < __; ++t2) 
            if (x + y + z + t + t1 + t2 == __- 1) ++count;
   return(count);     
}

有可能为此制作一个脚本。

input double Mult = 0.04;

void OnStart() {
   Alert(PartCount6(Mult));
}

此外,优化的任务有两个参数--Mult(未优化)和part--从1到PartCount6(Mult),步长为1。

input double Mult  = 0.04;
input int    part = 3276;

CZ1 gbp;
CZ2 jpy;
CZ3 eursek, eur;
CZ4 audcad, sek;

int x, y, z, t, t1, t2; 

int OnInit() {
   int __= (int)(1.0 / Mult) + 1;
   int count = 0;
   for (x = 0; x < __; ++x) {
      for (y = 0; y < __; ++y) {
         for (z = 0; z < __; ++z) {
            for (t = 0; t < __; ++t) {
               for (t1 = 0; t < __; ++t1) {
                  for (t2 = 0; t2 <__; ++t2) { 
                     if (x + y + z + t + t1 + t2 == __- 1) {
                        ++count;
                        if (count == part) break; // Вот где goto был бы полезен, или break n
                     }
                  }
                  if (count == part) break;
               }
               if (count == part) break; 
            }
            if (count == part) break;
         }
         if (count == part) break;
      }
      if (count == part) break;
   }
   if (x) gbp.Init(..);//его доля - x * Mult, т. е., нужно в Init долю передавать как параметр
   if (y) jpy.Init(..); 
   if (z) eur.Init(..);
   if (t) eursek.Init(..);
   if (t1) audcad.Init(..);
   if (t2) sek.Init(...);
}

void OnTick() {
   if (x) gbp.Trade();
   if (y) jpy.Trade();
   if (z) eur.Trade();
   if (t) eursek.Trade();
   if (t1) audcad.Trade();
   if (t2) sek.Init(Trade);
}

只要记住,步子越小,你需要经过的循环步骤就越多。例如,如果计算通过次数的脚本返回的数值不超过5分钟,那么最好减少这个步骤。如果你不想减少步骤,例如,将货币分成两半,对每组进行优化,然后再一起 "作为组"。(或者更好的是使用系统关联并成对优化--那么周期就不会那么糟糕,但这是另一个故事)。

对于其他数量的系统(甚至更少,甚至更多)--一切都一样。

 

我差点忘了--在优化之后,你需要知道分数--所以要运行你最喜欢的单程,并在OnDeinit中写入。

void OnDeinit(const int reason) {
  Print("x:", x * Mult, "; y:", y * Mult, "; z:", z * Mult, "; t:", t * Mult, "; t1:", t1 * Mult, "; t2:", t2 * Mult);
}
 

我在一年前就发现并测试了这个错误,甚至在论坛上提到了它。

事实证明,它仍然活着。

一句话:当虚函数 在构造函数中被调用时,将调用祖先函数而不是本地函数。

class COracleTemplate
  {
private:
public:
   string            ClassName;
                     COracleTemplate(){Init();};
                    ~COracleTemplate(){DeInit();};
   virtual void      Init(){ClassName=this.Name();Print("loadSettings from ",ClassName);};
   virtual void      DeInit(){Print("saveSettings to ",ClassName);};
   virtual string    Name(){return("Prpototype");};
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CCO2:public COracleTemplate
  {
   virtual string    Name(){return("CO2");};
  };
class CH2O:public COracleTemplate
  {
   virtual string    Name(){return("H2O");};
  };
COracleTemplate* CO2,*H2O;
void OnStart()
  {
   CO2=new CCO2;
   CO2.Init();
   Print(CO2.Name()," ClassName=",CO2.ClassName);
   delete CO2;
   
   H2O=new CH2O;
//   H2O.Init();
   Print(H2O.Name()," ClassName=",H2O.ClassName);
   delete H2O;
  }

印刷品。

2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        saveSettings to Prpototype
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        H2O ClassName=Prpototype
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        loadSettings from Prpototype
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        saveSettings to CO2
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        CO2 ClassName=CO2
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        loadSettings from CO2
2012.05.18 14:13:48     VirtualTest (EURUSD,M15)        loadSettings from Prpototype

如果这是一个错误,请修复它。

如果它是一个功能,在帮助中详细介绍,并解释其好处是什么。

如果这是一个必要的罪恶,请在帮助中的特殊方框中提及。

否则,你就不会疯狂地寻找你的程序中的错误。

附加的文件:
 

祖先构造函数对其后代和它们的虚拟函数 一无所知。

一个物体是如何构建的?

1.首先,调用 "原动机 "的构造器。它暴露了它的虚拟函数表。祖先对遵循继承层次的后代一无所知,而且后代的虚拟函数表还不存在。

2.层次结构中的下一个子代的构造函数被调用。这个后裔暴露了它自己的虚拟函数表。子代的函数(包括虚拟函数)在子代中可用。但是,同样地,这个子孙对它后面的子孙在一个层次结构中一无所知(如第1点)。

3.重复第2点,直到层次结构得到满足。

摘要。不要在构造函数中使用虚拟函数。而且也不要在析构器中使用它。

 
MetaDriver:

如果是不可避免的邪恶,请在帮助中提到它,放在一个特殊的盒子里。

不在构造函数之前和析构函数开始之后调用虚函数 是一种常见的做法。
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Виртуальные функции - Документация по MQL5
 
stringo:

祖先构造函数对其后代和它们的虚拟函数 一无所知。

一个物体是如何构建的?

1.首先,调用 "原动机 "的构造器。它暴露了它的虚拟函数表。祖先对遵循继承层次的后代一无所知,而且后代的虚拟函数表还不存在。

2.层次结构中的下一个子代的构造函数被调用。这个后裔暴露了它的虚拟函数表。子代的函数(包括虚拟函数)在子代中可用。但是,同样地,这个子孙对它后面的子孙在一个层次结构中一无所知(如第1点)。

3.重复第2点,直到层次结构得到满足。

摘要。不要在构造函数中使用虚拟函数。也不在破坏者中。

好吧,但还是把它放在显眼的地方,如果它要这样的话。

一般来说,这不是关于汇编的层次结构(我是这么想的),而是在构造函数的哪个位置添加VMT。 如果它被添加在开头(在用户编写的代码之前),那么这个问题似乎就不存在了,而且后续的代码可能已经调用了虚拟函数。 这是不可能的,不可取的还是...?

TheXpert
不在构造函数结束前和析构函数开始后调用虚函数 是一种常见的做法。

我对这个问题一无所知,即使对其他面向对象的语言也有一些经验。 也许是因为在构造函数中不经常需要进行虚拟调用。

 
MetaDriver:

好吧,但还是要把它放在帮助台的显著位置,如果要这样的话。


文件将在几个地方反映这一事实
 
stringo:
在文件中,这一事实将反映在几个地方

好的,太好了。

Slava,我可以问一下(对于一般的开发),为什么你不能在构造函数的开头(祖先初始化之后)初始化虚拟方法表?

--

在某些情况下,构造函数中的虚拟调用的代码可能是相当方便的。最近的一个例子:我想在构造函数中直接从文件中加载对象。 计划是在加载时通过与虚拟函数 返回的类型ID进行比较来检查类型。这是一个无奈之举,因为不可能从构造函数中进行虚拟调用。解决了问题,但没有像计划的那样优雅。

Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
Документация по MQL5: Основы языка / Объектно-ориентированное программирование / Виртуальные функции
  • www.mql5.com
Основы языка / Объектно-ориентированное программирование / Виртуальные функции - Документация по MQL5
 
MetaDriver:
所以要做一个工厂。问题将得到解决。