文章 "计算数学表达式(第二部分)。 普拉特和分流场解析器"

 

新文章 计算数学表达式(第二部分)。 普拉特和分流场解析器已发布:

在本文中,我们基于运算符优先级的解析器,研究数学表达式解析和评估的原理。 我们将实现普拉特(Pratt)和分流场解析器,字节代码的生成和代码计算,查看如何在表达式中将指标用作函数,以及如何基于这些指标在智能交易系统中设置交易信号。

如果在策略测试器中启动 EA,结果很可能不是很好。 然而,重要的是,交易现由解析器管理。 它们未提供现成的盈利系统,但提供了寻找策略的额外工具。

利用表达式计算信号进行交易的示例

利用表达式计算信号进行交易的示例

作者:Stanislav Korotky

 
在比较性能时,请将其与纯 MQL 进行比较。
 

考虑到本地 MQL5,性能比较如下:

ExpresSParserS (EURUSD,D1)      Evaluation: 105109
ExpresSParserS (EURUSD,D1)      Compilation: 26090
ExpresSParserS (EURUSD,D1)      Pratt bytecode: 24030
ExpresSParserS (EURUSD,D1)      Pratt: 26567
ExpresSParserS (EURUSD,D1)      ShuntingYard: 23884
ExpresSParserS (EURUSD,D1)      MQL5: 12901

MQL5 比目前最快的解析器快约 2 倍。

添加了测试代码:

class FuncCalc
{
  private:
    double a;
    double b;
    double c;
  public:
    void setup(double _a, double _b, double _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    double execute()
    {
      return (a + b) * (c > 10000 ? c / 4 : c * 4);
    }
};

ulong testMQL5(const int n)
{
  ulong ul = 0, total = 0;
  double r;
  FuncCalc f;

  for(int i = 0; i < n; i++)
  {
    f.setup(rand(), rand(), rand());
    ul = GetMicrosecondCount();
    r = f.execute();
    total += GetMicrosecondCount() - ul;
  }
  return total;
}

这只是粗略估计。仍有很大的研究空间(例如,不同类型的表达式)和解析器优化。

 

现在我只能赞美。

当然,我应该提到 Dijkstra,因为从历史上看,"射击场 "与他的关系更为密切。

我曾有过写一篇类似文章的想法,我甚至还在为自己打材料,是您抢先了一步(关于第二部分),但我有个习惯,就是把所有东西都卷进堡垒和堆垛机里。

你成功了,没有把文章卷进去(或蹩脚)......!

蛋糕上的樱桃应该是 Y 组合器。

PS. 不过,你的字节码被证明是 "宽泛 "的,并被类所扼杀。你可以吹口哨,也可以容忍 64 位。老板就是老板 :-)

 
Maxim Kuznetsov:

现在我只能赞美。

当然,值得一提的还有 Dijkstra,因为从历史上看,"射击场 "与他的关系更为密切

我曾有过写一篇类似文章的想法,我甚至还在为自己打材料,但你比我更早(关于第二部分),但我把所有常见的东西都卷进了堡垒和堆垛机中

你成功地没有把文章卷进去(或 lisp)......!

蛋糕上的樱桃将是 Y 型组合器。

PS. 但你的字节码看起来 "太宽",会被类杀死。您可以吹个口哨,容忍 64 位。好吧,老大就是老大 :-)

你可以写一部关于字节码缩减、加速和新型解析器的续集。我没能涵盖所有内容,事实上,我本想只写一篇文章,但和往常一样,它并不合适。

 
Stanislav Korotky:

你可以写一部关于字节码缩减、加速和新型解析器的续集。我没能涵盖所有内容,事实上,我本想只写一篇文章,但和往常一样,还是写不完。

字节码取决于虚拟机。一方面,我很想为操作码 "两数相加 "提供 128 位或更多 ....

而新型解析器尚未发明,它们都是多年前的了;-)而且只有两个半解析器。

PS 针对终端用户需求的排序站已经过时了--您可以在输入框中输入一个熟悉的公式,然后得到结果。

 
与其他一些文章不同,这两篇文章非常好。清晰、详细、易懂。谢谢。
 
计算器 1.1 的更新版本附在有关粒子群优化 的文章中。此外,讨论中还有一个小错误修复。
Параллельная оптимизация методом роя частиц (Particle Swarm Optimization)
Параллельная оптимизация методом роя частиц (Particle Swarm Optimization)
  • www.mql5.com
Как известно, MetaTrader 5 позволяет оптимизировать торговые стратегии с помощью встроенного тестера на основе двух алгоритмов: прямого перебора входных параметров и генетики (генетический алгоритм - ГА). Генетическая оптимизация является одной из разновидностей эволюционных алгоритмов, которые предоставляют значительное ускорение процесса...
 
请说明如何使用这种字符串的解析器。
"(EURUSD^2) / (GBPUSD * AUDUSD)"

困难在于,我们需要自动确定在哪种情况下以及在何处替换买入价/卖出价。

在上面的例子中,应该是这样的

Value_Bid = (EURUSD_Bid * EURUSD_Bid / (GBPUSD_Ask * AUDUSD__Ask);
Value_Ask = (EURUSD_Ask * EURUSD_Ask / (GBPUSD_Bid * AUDUSD__Bid);


确定买入价/卖出价的算法如下。使用相同的示例。

F(EURUSD, GBPUSD, AUDUSD) = (EURUSD^2) / (GBPUSD * AUDUSD);

bool EURUSD_flag = (F(1, 1, 1) < F(2, 1, 1));
bool GBPUSD_flag = (F(1, 1, 1) < F(1, 2, 1));
bool AUDUSD_flag = (F(1, 1, 1) < F(1, 1, 2));

Value_Bid = F(EURUSD_flag ? EURUSD_Bid : EURUSD_Ask,
              GBPUSD_flag ? GBPUSD_Bid : GBPUSD_Ask,
              AUDUSD_flag ? AUDUSD_Bid : AUDUSD_Ask);

Value_Ask = F(EURUSD_flag ? EURUSD_Ask : EURUSD_Bid,
              GBPUSD_flag ? GBPUSD_Ask : GBPUSD_Bid,
              AUDUSD_flag ? AUDUSD_Ask : AUDUSD_Bid);
 
fxsaber:
请告诉我如何使用解析器来处理这样的字符串。

主要困难在于确定表达式中所有变量的名称。这样你就可以写出类似的内容。

TestSuiteEvaluator evaluator("EURUSD=1.5;GBPUSD=2.5;AUDUSD=5");
 
从解析器的角度来看,一个变量不能有两个值:出价和要价。也许可以用函数来封装组件(或者引入 Bid(symbol)、Ask(symbol) 函数,或者在组件数量预定义的情况下引入整个 "篮子 "函数)。从根本上说,最初的问题并不清楚:如果我们谈论的是一个由三个符号组成的合成/篮子,那么在其中,每个成分都可以明确地通过 Ask 或 Bid 获得,具体取决于方向。您还可以考虑根据交易方向选择不同的表达方式。