English Русский Español Deutsch 日本語 Português
preview
开发回放系统(第 42 部分):图表交易项目(I)

开发回放系统(第 42 部分):图表交易项目(I)

MetaTrader 5示例 | 11 十一月 2024, 11:28
209 0
Daniel Jose
Daniel Jose

概述

在上一篇文章《开发回放系统(第 41 部分):开始第二阶段(II)》中,我展示了如何创建由鼠标控制的指标。您也许会认为这很无聊,且长远来看这并无益处。如果是这样的话,那只是因为您从未明白发生了什么。

每次我们创建新事物时,我们都必须进行一连串测试并创造条件,如此某个程序或过程才能与其它程序或过程共存。该条件的实现展示您是否准备好宣示自己是专业人士。

当一个程序或进程与其它模块发生冲突时,初学者通常会遇到问题。在这种情况下,任何奇怪的事情都可能发生。初学者也许会发现这些问题很难或不可能解决,但专业人士应该能够应对这种状况。

我的观点是:编写一款智能系统,其可执行一千零一种操作、或拥有一系列指标和图形元素、或包含许多基于市场工作的程序或进程,但若您尝试将它们组合在一个图表上时,它们开始相互冲突,那么这样的智能系统是没有意义的。

或者更糟糕的是,在创建了一个极其可靠和稳定的程序之后,有时您需要开发的另一个程序会用到第一个程序的部分功能,而在此过程中,新程序开始爆出一连串错误并失败,尤其是当与其它进程放在一起时。排除这些故障肯定需要时间,在于其中一些故障很简单,但有些则非常复杂。

我为什么这么说呢?因为我们已经为鼠标创建了一个指标。MetaTrader 5 平台有各种可以帮助我们的工具。其中一些较简单,需要改进从而满足每个人的独特需求。您可以通过创建各种程序来获得完美的枪械,这是在市场上使用的完美武器。但我希望您思考的是:如果我们取代尝试创造完美的武器,转而开始创造各种兼容的零部件,当组合后,每次都可以为我们遇到的问题组装成专门设计的武器,那会怎样?

这似乎是一个不错的解决方案,不是吗?这正是我们在创建鼠标指标时所做的。基于该指标,我们将开始创建一系列对我们有很大帮助的零部件。

自本系列开发回放/模拟器系统的最开始,我就一直说,我们的意图是按相同的方式使用 MetaTrader 5 平台,无论正在开发的系统中,亦或真实市场中。重点是要正确完成。没有人愿意在训练和学习时用一种工具,而在战斗时不得不换另一种工具。相信我,使用回放/模拟器是学习,但在真实账户上交易是一场真正的战斗。在实战中,您需要运用训练时之所学,并成为习惯。

在鼠标指标之后,还需要尽快创建另外两个工具。其一很简单,另一个相当复杂,因为我们将不得不处置数据模拟。故此,我们从一些简事开始,慢慢习惯,当我们转到更复杂的事情时,我们对一切如何运作已具备了良好的概念。

简单工具就是图表交易(Chart Trade)。其最后版本,是在文章中《从头开始开发智能交易系统(第 30 部分):图表交易作为指标?!》中加以讲述。与我们现在要做的事情相比,该指标看似一个孩子的玩具,在于它是如此简单、且非通用。我们创建一个新的图表交易,它可以与已创建的指标(即鼠标指标)和谐共存。


新的图表交易

图表交易,我们曾在上述文章中讨论过,将作为基础,但我们不会使用其代码或模板。我们将创建另一个,更成熟、更符合我们的需求。

您将看到我将讲述的新代码要简单得多,且更紧凑,这意味着修改和更正内容会更容易。这个思路是使用鼠标指标来移动、单击、并与图表上的任意元素交互。为此,我们需要创建一些相当不寻常的代码。我将逐步演示所有内容,如此轻松跟踪正在做什么、以及如何完成,因为它与许多人已习惯在 MetaTrader 5 中所见和所用的内容非常不同。当来到编程时,一开始很多东西也许不明白。

我们从图表交易用到的、我最近叙述过的一个概念开始:RAD 编程。RAD 这个词代表 RapidAapplicationDevelopment。多年前,当我开始为 Windows 系统编程时,我就被灌输了这个概念。它极大有助于创建高效的应用程序,令您可以把更多时间直接花用在代码上,取代有关程序外观的忧虑。在文章《一个图表上的多指标(第 06 部分):将 MetaTrader 5 转变为 RAD 系统(II)》中,我展示过如何在 MetaTrader 5 中使用类似的东西。

然而,在此处的改进版本中,再次用到相同的概念。如果您想从正确的立足点开始,请阅读上述文章、以及更前面的文章,这对于了解我们将要做什么也很重要。此处是文章《一个图表上的多指标(第 05 部分):将 MetaTrader 5 转变为 RAD 系统(I)》。重点是理解那里的解释。当前的话题将更加丰富和复杂,尽管与未来我们的期待相比,这个指标是最简单的部分。

新模板将如下图例所示 01:

图例 01

图例 01 - RAD 模板

图例 01 展示了图表交易所具有的实际视图。这是一个图表交易模板,而非图表交易本身。后者可以在下面的视频 01 中看到,我在其中演示了它与鼠标指标之间的交互。观看视频,并了解其工作原理。该视频清晰地展示了本文将要讨论的所有内容,因此建议观看。


视频 01 - 演示视频

考虑到您已经观看了视频 01,我们开始查看图表交易指标代码。但首先我们需要对 C_Terminal 类的代码进行少量追加,如以下代码快照所示。

图表交易指标源代码

156. //+------------------------------------------------------------------+
157.            bool IndicatorCheckPass(const string szShortName)
158.                    {
159.                            string szTmp = szShortName + "_TMP";
160.                            
161.                            if (_LastError != ERR_SUCCESS) return false;
162.                            IndicatorSetString(INDICATOR_SHORTNAME, szTmp);
163.                            if (ChartWindowFind(m_Infos.ID, szShortName) != -1)
164.                            {
165.                                    ChartIndicatorDelete(m_Infos.ID, 0, szTmp);
166.                                    Print("Only one instance is allowed...");
167.            
168.                                    return false;
169.                            }
170.                            IndicatorSetString(INDICATOR_SHORTNAME, szShortName);
171.                            ResetLastError();
172.    
173.                            return true;
174.                    }
175. //+------------------------------------------------------------------+

C_Terminal 类的片段

这段代码也许看似不寻常。我们之前已经见过它,但现在它是 C_Terminal 类的一部分,因此所有用到它的类或指标都能从这段代码受益。该段代码是防止在图表上多次放置指标。有绕过它的方式,我们以后会用到它,但现在不用担心这个细节。请记住,这段代码是防止两个相同的指标同时出现在图表上。

但在转去讨论支持我们的图表交易的源类之前,我们先看一下指标代码。我正在修改表达顺序,从而令该类解释更合适。完整的指标代码如下所示。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property description "Base version for Chart Trade (DEMO version)"
04. #property version   "1.42"
05. #property link "https://www.mql5.com/pt/articles/11652"
06. #property indicator_chart_window
07. #property indicator_plots 0
08. //+------------------------------------------------------------------+
09. #include <Market Replay\Chart Trader\C_ChartFloatingRAD.mqh>
10. //+------------------------------------------------------------------+
11. C_ChartFloatingRAD *chart = NULL;
12. //+------------------------------------------------------------------+
13. int OnInit()
14. {
15.     chart = new C_ChartFloatingRAD("Indicator Chart Trade", new C_Mouse("Indicator Mouse Study"));
16.     if (_LastError != ERR_SUCCESS)
17.     {
18.             Print("Error number:", _LastError);
19.             return INIT_FAILED;
20.     }
21.     
22.     return INIT_SUCCEEDED;
23. }
24. //+------------------------------------------------------------------+
25. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
26. {
27.     return rates_total;
28. }
29. //+------------------------------------------------------------------+
30. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
31. {
32.     (*chart).DispatchMessage(id, lparam, dparam, sparam);
33.     
34.     ChartRedraw();
35. }
36. //+------------------------------------------------------------------+
37. void OnDeinit(const int reason)
38. {
39.     delete chart;
40.     
41.     ChartRedraw();
42. }
43. //+------------------------------------------------------------------+

如上所示,该指标的代码非常简单。当然,我们将添加更多信息来进行适当的描述,但目前来说这已经足够满足我们的需求。

请注意,我们唯一要做的就是指定在第 07 行不显示任何数据。其余的工作包括初始化一个指向所有类的指针,以便支持从图表进行交易,并销毁同一的指针。不过,我们将在视频 01 中演示该行为。

我认为理解指标的代码行应该没有任何困难。大概仅有一处第 15 行需要多做一点工作。但这也很简单。我们使用两个运算符 new 来初始化这两个类。

注意以字符串变量形式传递的信息。当指标加载到图表上时,MetaTrader 5 会把第一个字符串变量引用的名称辨别为指标名称。第二个参数引用的是鼠标指标的名称。这在鼠标指标代码中定义。更详细的信息可以在文章中找到《开发回放系统(第 41 部分):开始第二阶段(II)》

现在您已经看到了图表交易指标代码是多么简单,我们来看看类代码。请记住,您看到的代码是原始代码,并且将添加其它元素,以便指标能真正发挥作用。


C_ChartFloatingRAD 类

尽管名称如此,但该类主要设计用于协同图表交易指标工作。在当前的开发阶段,它已经包含所有必要的逻辑,可为我们提供像视频 01 中一样的行为。也就是说,如果我们正在做研究,即使我们单击窗口并拖动鼠标,我们也无法移动窗口。如果研究正在进行,则无法移动窗口。

为了达成这一目标,也许看似需要创建一个复杂的图表,以及视频中的图像,其已经显示出指标的最终外观。我们看看这是否属实。看看类代码就知道了。其完整代码如下。

C_ChartFloatingRAD 类源代码

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #include "../Auxiliar/C_Terminal.mqh"
05. #include "../Auxiliar/C_Mouse.mqh"
06. //+------------------------------------------------------------------+
07. class C_ChartFloatingRAD : private C_Terminal
08. {
09.     private :
10.             struct st00
11.             {
12.                     int     x, y, cx, cy;
13.                     string  szObj_Chart;
14.                     long    WinHandle;
15.             }m_Info;
16. //+------------------------------------------------------------------+
17.             C_Mouse *m_Mouse;
18. //+------------------------------------------------------------------+
19.             void CreateWindowRAD(int x, int y, int w, int h)
20.                     {
21.                             m_Info.szObj_Chart = (string)ObjectsTotal(GetInfoTerminal().ID);
22.                             ObjectCreate(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJ_CHART, 0, 0, 0);
23.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = x);
24.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = y);
25.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XSIZE, w);
26.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YSIZE, h);
27.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_DATE_SCALE, false);
28.                             ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_PRICE_SCALE, false);
29.                             m_Info.WinHandle = ObjectGetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_CHART_ID);
30.                             m_Info.cx = w;
31.                             m_Info.cy = 26;
32.                     };
33. //+------------------------------------------------------------------+
34. inline void UpdateChartTemplate(void)
35.                     {
36.                             ChartApplyTemplate(m_Info.WinHandle, "IDE_RAD.tpl");
37.                             ChartRedraw(m_Info.WinHandle);
38.                     }
39. //+------------------------------------------------------------------+
40.     public  :
41. //+------------------------------------------------------------------+
42.             C_ChartFloatingRAD(string szShortName, C_Mouse *MousePtr)
43.                     :C_Terminal()
44.                     {
45.                             if (!IndicatorCheckPass(szShortName)) SetUserError(C_Terminal::ERR_Unknown);
46.                             m_Mouse = MousePtr;
47.                             CreateWindowRAD(0, 0, 170, 240);
48.                             UpdateChartTemplate();
49.                     }
50. //+------------------------------------------------------------------+
51.             ~C_ChartFloatingRAD()
52.                     {
53.                             ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Chart);
54.                             delete m_Mouse;
55.                     }
56. //+------------------------------------------------------------------+
57.             void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
58.                     {
59.                             static int sx = -1, sy = -1;
60.                             int x, y, mx, my;
61.     
62.                             switch (id)
63.                             {
64.                                     case CHARTEVENT_MOUSE_MOVE:
65.                                             if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft))
66.                                             {
67.                                                     x = (int)lparam;
68.                                                     y = (int)dparam;
69.                                                     if ((x > m_Info.x) && (x < (m_Info.x + m_Info.cx)) && (y > m_Info.y) && (y < (m_Info.y + m_Info.cy)))
70.                                                     {
71.                                                             if (sx < 0)
72.                                                             {
73.                                                                     ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false);
74.                                                                     sx = x - m_Info.x;
75.                                                                     sy = y - m_Info.y;
76.                                                             }
77.                                                             if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = mx);
78.                                                             if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = my);
79.                                                     }
80.                                             }else if (sx > 0)
81.                                             {
82.                                                     ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true);                                                
83.                                                     sx = sy = -1;
84.                                             }
85.                                             break;
86.                             }
87.                     }
88. //+------------------------------------------------------------------+
89. };
90. //+------------------------------------------------------------------+
91. 

就这些吗?对象创建代码在哪里?鼠标操作?

我不敢相信这两段简单的代码可以完成视频 01 中所示的操作。看似是个笑话。但我并非在开玩笑。这几行可以在图例 01 中看到的窗口如视频 01 中所示的表现。

您可以使用鼠标研究图表,您可以单击并拖动图表交易窗口,这一切都归功于该段代码。将要往该类的代码中添加少量内容,从而令窗口正常运行,并允许显示资产。这些按钮将变得有效,您就能够编辑尚未显示的值。实际上,这里还缺少一些调整,但不要指望在此处看到这些对象被创建。我使用另一种方法来令我们的窗口正常运行,并将在下一篇文章中展示它。

但等等,我们尚未完工呢。若要真正理解发生了什么,我们来看看类代码的解释,以及为什么它包含该特定代码。

我们从第 07 行开始。注意,C_ChartFloatingRAD 类继承自 C_Terminal 类。因为我们必须始终为继承者提供最低权限,所以我们将继承设为私密。以这种方式,其它代码将无法访问 C_Terminal 类,至少不能通过 C_ChartFloatingRAD 类访问。这不是问题,因为指标代码没有提到任何 C_Terminal 类代码。

如果您已经理解了这一点,就可以转到构造函数了。这令执行过程更易于理解。

构造函数从第 42 行开始。注意,它需要一个字符串和一个对象(实际上是一个指针)来引用鼠标指标。在第 43 行,我们执行必要的 C_Terminal 类初始化。当我们进入构造函数代码时,从第 45 行开始,我们调用验证码,以确保图表交易指标不在图表上。如果该检查失败,我们调用 SetUserError_LastError 常量中指出此情况。

请注意以下事项。如果您不明白我所解释的内容,您会完全迷失在这个系列的其余部分。因此,您应该密切关注我所说的话。

在第 46 行,我们存储调用 new 运算符创建对象后传递过来的指针。这发生在图表交易指标代码当中。您可以在指标代码的第 15 行看到该调用。在执行第 46 行时,鼠标指标是否存在于图表上并不重要。我再说一遍,因为这很重要:调用时图表上是否存在指标并不重要

真正重要的是(许多人可能不理解这一点)是在图表交易指标代码第 15 行所示的调用中传递的名称。这个传递给 C_Mouse 类的构造函数的字符串变量才是最重要的。但不是图表上指标的存在与否。

这也许看似没有意义。但它仍如此做。为了理解它,您需要返回上一篇文章《开发回放系统(第 41 部分):开始第二阶段(II)》,并注意 C_Mouse 类代码中的第 169 行。只有此行将确保 C_ChartFloatingRAD 类中显示的代码的正确操作。因此,有必要正确指定鼠标指标的名称,以便 MetaTrader 5 平台在需要执行 C_Mouse 类中的第 169 行时可以找到它。

这也许看似仍然令人困惑,故我们转入解释代码如何工作。我们稍后会回到这一点,以更清晰地说明事情。

在第 47 行,我们调用第 19 行的函数。第 19 行的这个函数只是一个在图表上创建 OBJ_CHART 对象的过程。只有这个。不过,在第 29 行,我们保存了这个对象的 ID,如此这般可以稍后按十分特殊的方式使用它。我认为没有人难以理解这个程序的其余行。

返回到构造函数代码,在第 48 行有另一个调用。在所示的第 34 行执行该调用。此刻,我们有 36 和 37 两行。第 36 行将查找我们指定的模板,正是图例 01 中所示的模板。在第 37 行,我们强制 MetaTrader 5 更新 OBJ_CHART 对象,以便显示模板。

因此,我们展示了我们的图表交易。好吧,它尚未发挥作用。不过,我们可以做一些 “操纵” 来了解鼠标指标和图表交易指标之间的交互。

析构函数代码非常简单,不需要太多解释。我们细看一下消息处理代码:DispatchMessage 过程从第 57 行开始。两个指标之间的交互发生在这里。

基本上,现在,我们只处理从第 64 行开始的鼠标移动事件。注意:我们不按寻常方式操作。我们在处理鼠标移动事件时将采用完全不同的方式。对于那些习惯于以某种方式编程的人来说,这似乎是 非常疯狂。  

为了更好地理解(这也是我在本文中不展示其它内容的原因),您需要参考前面的资料《开发回放系统(第 41 部分):开始第二阶段(II)》。我们处理的不是一个,而是同时处理两个指标。它们相互作用并和谐共存,用户可以做到视频 01 中所示的操作。

在这个图表交易指标消息处理代码中,我们只提到一次鼠标指标。它在第 65 行中被提及。尝试了解发生了什么。如果您明白了这一点,剩下的就很容易了。

这里可能有两种状况。第一个是当鼠标指标在图表上时,第二个是当指标不在图表上时。我要提醒您,指标必须含有我们在 C_ChartFloatingRAD 类的构造函数中指定的名称。如果名称不同,MetaTrader 5 不会帮到我们,我们将面临指标不在图表上的状况。注意这个细节。

一旦清楚了这一点,并且您清楚地了解了这两种状况,我们就可以开始进一步解释了。

当此情发生时,第 65 行的调用将执行第 C_Mouse 类第 158 行的调用(来自上一篇文章)在图表交易指标代码的第 15 行,我们告诉 C_Mouse 类的构造函数,我们将使用 C_Mouse 类作为转换器。C_Mouse 类的第 158 行将调用第 163 行,以便检查 C_ChartFloatingRAD 类第 65 行指定的按钮是否被点击。

当第 165 行在 C_Mouse 类中执行时,代码将理解我们正在使用转换器。然后,我们将执行第 169 行来捕获鼠标指标句柄。此时我们将向 MetaTrader 5 寻求帮助,故提供的名称必须匹配。如果 MetaTrader 5 找到了我们引用的指标,句柄将接收一个索引,以便访问指标的缓冲区。如果缓冲区可以读取,则第 172 行将捕获鼠标指针数据。如果无法读取缓冲区,则函数将失败,这也会导致第 158 行的函数失败。这将导致 C_ChartFloatingRAD 类的第 65 行上的检查失败。因此,我们将收到未发生点击的指示。

该逻辑将在两种状况下起作用:

  • 当图表中缺失鼠标指标时。记住,它必须与指定的名称相同,以便 MetaTrader 5 能够找到它。
  • 当我们利用鼠标指标在图表上进行研究时。

这两种状况中的任一种,C_ChartFloatingRAD 类的第 65 行将指示鼠标单击失败。

这部分所做所为看似很混乱?别担心,从此处开始事情会变得更加有趣。

现在我们来分析一种状况,其中 MetaTrader 5 找到鼠标指标,我们想在图表上移动图表交易指标,如视频 01 所示。为了搞明白这将如何发生,您需要理解以下文章:

这些文章中的每一篇都是为即将到来的事情做准备。如果您还没有阅读它们、或不理解其内容,我建议您回到它们,并了解通信是如何发生的。虽然也许看似很简单,但这些概念在实践中变得相当难以理解,尤其是对于那些不曾应用该类方法的人来说。

我在此处展示的是最简单的部分。与接下来的相比,它看似学前教育。因此,理解该段代码的如何工作非常重要。

在某些时候,C_ChartFloatingRAD 第 65 行的调用将遇到第 181 行上显示的 C_Mouse 的调用。此情发生时,C_Mouse 类的第 160 行将检查传递给它的按钮码。如果编码与传入的编码匹配,则函数将返回 true。此刻,只要按下鼠标按钮,就会执行第 67 行和第 79 行之间的代码。

这段代码有一个小缺陷,但是由于代码只是一个演示,您现在可以忽略它。

现在问题浮现:为什么我在第 67 行和第 68 行使用的是 MetaTrader 5 提供的值,而不是鼠标指标?当然不是因为它更漂亮、或更简单。使用 MetaTrader 5 提供的值,而非指标值是有原因的。为了理解这一点,您需要查看 C_Mouse 类中第 203 行和第 206 行之间的代码。在这些行中,我们执行鼠标坐标的转换和调整。在这种情况下,鼠标坐标不再是屏幕上位置(x 和 y),而是变为活动状态(价格和时间)。

这对于处理某些类型的问题非常实用,但问题在于,我们需要以不同的方式工作。如果我们在 C_ChartFloatingRAD 类的第 67 行和第 68 行用到类似于以下的代码:

x = (*m_Mouse).GetInfoMouse().Position.X;
y = (*m_Mouse).GetInfoMouse().Position.Y;

我们将获得 OBJ_CHART 对象的移动,就好像它与资产坐标(价格和时间)相关联一样。但实际上,这样的对象使用屏幕坐标(x, y),故运动会很奇怪,不像视频 01 中那样流畅。对于某些类型的对象,实际上需要用到由鼠标指标提供的坐标。


结束语

在本文中,我们研究了创建图表交易指标的第一阶段。我展示了您该如何使用鼠标指标,来与我们正在创建的图表交易指标完美和谐,不过,除了在图表上拖放之外,它尚无任何功能。

在下一篇文章中,我们将开始扩展图表交易的功能。


本文由MetaQuotes Ltd译自葡萄牙语
原文地址: https://www.mql5.com/pt/articles/11652

附加的文件 |
Anexo.zip (420.65 KB)
DoEasy.服务功能(第 2 部分):孕线形态 DoEasy.服务功能(第 2 部分):孕线形态
本文将继续探讨 DoEasy 库中的价格形态。我们还将创建价格行为形态中的 "孕线"(Inside Bar)形态类。
自定义指标(第一部份):在MQL5中逐步开发简单自定义指标的入门指南 自定义指标(第一部份):在MQL5中逐步开发简单自定义指标的入门指南
学习如何使用MQL5创建自定义指标。这篇入门文章将指引您了解创建简单自定义指标的基础知识,并向初次接触这一有趣话题的MQL5程序员展示编写各种自定义指标的方法。
两样本Kolmogorov-Smirnov检验作为时间序列非平稳性的指标 两样本Kolmogorov-Smirnov检验作为时间序列非平稳性的指标
本文探讨了最著名的非参数同质性检验之一——两样本柯尔莫哥洛夫-斯米尔诺夫(Kolmogorov-Smirnov)检验。文章对模型数据和实际价格都进行了分析。此外,本文还给出了构建非平稳性指标(iSmirnovDistance)的一个示例。
神经网络变得简单(第 75 部分):提升轨迹预测模型的性能 神经网络变得简单(第 75 部分):提升轨迹预测模型的性能
我们创建的模型变得越来越大,越来越复杂。这不光提高了它们的训练成本,还有操作成本。不过,做出决定所需的时间往往很关键。有关于此,我们来研究在不损失品质的情况下优化模型性能的方法。