English Русский Español Deutsch 日本語 Português
preview
开发回放系统(第 47 部分):Chart Trade 项目(六)

开发回放系统(第 47 部分):Chart Trade 项目(六)

MetaTrader 5示例 | 5 十二月 2024, 14:38
182 0
Daniel Jose
Daniel Jose

概述

在上一篇文章开发回放系统(第 46 部分):Chart Trade Project (五)中,我展示了如何将数据添加到可执行文件中,这样就不必单独传输数据了。这些知识对于不久的将来要做的事情非常重要。但现在,我们将继续开发需要首先实现的内容。

在本文中,我们将改进 Chart Trade 指标,使其功能足以与一些 EA 配合使用。这样,我们就可以访问 Chart Trade 指标,并像实际连接 EA 一样使用它。但是,让我们把它变得比过去的一篇文章更有趣从零开始开发 EA 交易(第 30 部分):把 Chart Trader 作为指标? 。在那篇文章中,我们使用 Chart Trade 作为一个条件指标。而这一次,它将成为一个真正的指标。 

为此,我们将以一种非常特殊的方式使其发挥作用,就像使用任何其他类型的指标一样。为此,我们将创建一个对应的数据缓冲区。这个过程在其他文章中有过描述,相关信息可在此处找到:

这三篇文章包含了我们实际要做的工作的基础。如果您还没有读过,我建议您读一读。否则,您可能会在阅读本文时感到困惑,并且由于缺乏作为本文基础的深层知识而难以理解本文。因此,您应该阅读上述文章,并充分理解其内容。

在开始改动之前,我们需要做一些小修改。它们都包含在现有的 C_ChartFloatingRAD 类代码中,以便于我们轻松、充分地访问所需的数据。因此,我们将进入 Chart Trade 指标工作的最后阶段。


小改变,大成果

将做出的修改很少,也很简单。当然,前提是您一直在关注本系列文章。现在,我们正处于回放/模拟系统文章的第二阶段。以下是 Chart Trade 指标的完整代码。请务必先复习这些代码,以便更轻松地解释类的代码。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property description "Chart Trade base indicator."
04. #property description "This version communicates via buffer with the EA."
05. #property description "See the articles for more details."
06. #property version   "1.47"
07. #property icon "/Images/Market Replay/Icons/Indicators.ico"
08. #property link "https://www.mql5.com/es/articles/11760"
09. #property indicator_chart_window
10. #property indicator_plots 0
11. #property indicator_buffers 1
12. //+------------------------------------------------------------------+
13. #include <Market Replay\Chart Trader\C_ChartFloatingRAD.mqh>
14. //+------------------------------------------------------------------+
15. C_ChartFloatingRAD *chart = NULL;
16. //+------------------------------------------------------------------+
17. input int      user01 = 1;       //Leverage
18. input double   user02 = 100.1;   //Finance Take
19. input double   user03 = 75.4;    //Finance Stop
20. //+------------------------------------------------------------------+
21. double m_Buff[];
22. //+------------------------------------------------------------------+
23. int OnInit()
24. {
25.     bool bErr;
26.             
27.     chart = new C_ChartFloatingRAD("Indicator Chart Trade", new C_Mouse("Indicator Mouse Study"), user01, user02, user03);
28.     
29.     if (bErr = (_LastError != ERR_SUCCESS)) Print(__FILE__, " - [Error]: ", _LastError);
30. 
31.     SetIndexBuffer(0, m_Buff, INDICATOR_DATA);
32.     ArrayInitialize(m_Buff, EMPTY_VALUE);
33.     
34.     return (bErr ? INIT_FAILED : INIT_SUCCEEDED);
35. }
36. //+------------------------------------------------------------------+
37. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
38. {
39.     (*chart).MountBuffer(m_Buff, rates_total);
40.     
41.     return rates_total;
42. }
43. //+------------------------------------------------------------------+
44. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
45. {
46.     (*chart).DispatchMessage(id, lparam, dparam, sparam);
47.     (*chart).MountBuffer(m_Buff);
48.     
49.     ChartRedraw();
50. }
51. //+------------------------------------------------------------------+
52. void OnDeinit(const int reason)
53. {
54.     if (reason == REASON_CHARTCHANGE) (*chart).SaveState();
55. 
56.     delete chart;
57. }
58. //+------------------------------------------------------------------+

Chart Trade 指标源代码

请注意,上面的所有代码包含了 Chart Trade 指标运行所需的所有内容。不过,出于实用的考虑,大部分代码都被移到了一个类中,稍后将对此进行讨论。但这些代码是如何工作的呢?它是如何让我们向 EA 发送命令以执行操作的?等一下,让我们先弄清楚指标代码中发生了什么。

第 11 行包含我们需要的第一个阶段,在这一行中,我们定义将使用一个缓冲区。我们可以使用更多的缓冲区,但一个就足够了。

我们将使用的缓冲区在第 21 行中声明,但我们只是在第 31 行定义了如何使用它。由于我们不希望缓冲区被 "垃圾" 填满,我们在第 32 行将其初始化为只包含零值。

正如你所看到的,与之前的文章相比,指标代码没有发生任何重大变化。但它现在有了两行新代码:第 39 行和第 47 行。这两行都调用了类中的同一个函数,我们很快就会看到。由于数量和参数不同,您可以认为这些是不同的函数。不过,你很快就会发现,它们都是一样的。为了理解这一点,让我们看看该类的完整代码,如下所示。  

001.//+------------------------------------------------------------------+
002.#property copyright "Daniel Jose"
003.//+------------------------------------------------------------------+
004.#include "../Auxiliar/C_Mouse.mqh"
005.#include "../Auxiliar/Interprocess.mqh"
006.#include "C_AdjustTemplate.mqh"
007.//+------------------------------------------------------------------+
008.#define macro_NameGlobalVariable(A) StringFormat("ChartTrade_%u%s", GetInfoTerminal().ID, A)
009.//+------------------------------------------------------------------+
010.class C_ChartFloatingRAD : private C_Terminal
011.{
012.    public          :
013.            enum eObjectsIDE {MSG_LEVERAGE_VALUE, MSG_TAKE_VALUE, MSG_STOP_VALUE, MSG_MAX_MIN, MSG_TITLE_IDE, MSG_DAY_TRADE, MSG_BUY_MARKET, MSG_SELL_MARKET, MSG_CLOSE_POSITION, MSG_NULL};
014.            struct stData
015.            {
016.                    int             Leverage;
017.                    double          PointsTake,
018.                                    PointsStop;
019.                    bool            IsDayTrade;
020.                    union u01
021.                    {
022.                            ulong   TickCount;
023.                            double  dValue;
024.                    }uCount;
025.                    eObjectsIDE Msg;
026.            };
027.    private :
028.            struct st00
029.            {
030.                    int     x, y, minx, miny;
031.                    string  szObj_Chart,
032.                            szObj_Editable,
033.                            szFileNameTemplate;
034.                    long    WinHandle;
035.                    double  FinanceTake,
036.                            FinanceStop;
037.                    bool    IsMaximized;
038.                    stData  ConfigChartTrade;
039.                    struct st01
040.                    {
041.                            int    x, y, w, h;
042.                            color  bgcolor;
043.                            int    FontSize;
044.                            string FontName;
045.                    }Regions[MSG_NULL];
046.            }m_Info;
047.//+------------------------------------------------------------------+
048.            C_Mouse   *m_Mouse;
049.            string    m_szShortName;
050.//+------------------------------------------------------------------+
051.            void CreateWindowRAD(int w, int h)
052.                    {
053.                            m_Info.szObj_Chart = "Chart Trade IDE";
054.                            m_Info.szObj_Editable = m_Info.szObj_Chart + " > Edit";
055.                            ObjectCreate(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJ_CHART, 0, 0, 0);
056.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x);
057.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y);
058.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XSIZE, w);
059.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YSIZE, h);
060.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_DATE_SCALE, false);
061.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_PRICE_SCALE, false);
062.                            m_Info.WinHandle = ObjectGetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_CHART_ID);
063.                    };
064.//+------------------------------------------------------------------+
065.            void AdjustEditabled(C_AdjustTemplate &Template, bool bArg)
066.                    {
067.                            for (eObjectsIDE c0 = 0; c0 <= MSG_STOP_VALUE; c0++)
068.                                    if (bArg)
069.                                    {
070.                                            Template.Add(EnumToString(c0), "bgcolor", NULL);
071.                                            Template.Add(EnumToString(c0), "fontsz", NULL);
072.                                            Template.Add(EnumToString(c0), "fontnm", NULL);
073.                                    }
074.                                    else
075.                                    {
076.                                            m_Info.Regions[c0].bgcolor = (color) StringToInteger(Template.Get(EnumToString(c0), "bgcolor"));
077.                                            m_Info.Regions[c0].FontSize = (int) StringToInteger(Template.Get(EnumToString(c0), "fontsz"));
078.                                            m_Info.Regions[c0].FontName = Template.Get(EnumToString(c0), "fontnm");
079.                                    }
080.                    }
081.//+------------------------------------------------------------------+
082.inline void AdjustTemplate(const bool bFirst = false)
083.                    {
084.#define macro_AddAdjust(A) {                         \
085.             (*Template).Add(A, "size_x", NULL);     \
086.             (*Template).Add(A, "size_y", NULL);     \
087.             (*Template).Add(A, "pos_x", NULL);      \
088.             (*Template).Add(A, "pos_y", NULL);      \
089.                           }
090.#define macro_GetAdjust(A) {                                                                                                                                                        \
091.             m_Info.Regions[A].x = (int) StringToInteger((*Template).Get(EnumToString(A), "pos_x"));   \
092.             m_Info.Regions[A].y = (int) StringToInteger((*Template).Get(EnumToString(A), "pos_y"));   \
093.             m_Info.Regions[A].w = (int) StringToInteger((*Template).Get(EnumToString(A), "size_x"));  \
094.             m_Info.Regions[A].h = (int) StringToInteger((*Template).Get(EnumToString(A), "size_y"));  \
095.                           }
096.#define macro_PointsToFinance(A) A * (GetInfoTerminal().VolumeMinimal + (GetInfoTerminal().VolumeMinimal * (m_Info.ConfigChartTrade.Leverage - 1))) * GetInfoTerminal().AdjustToTrade
097.                            
098.                            C_AdjustTemplate  *Template;
099.                            
100.                            if (bFirst)
101.                            {
102.                                    Template = new C_AdjustTemplate(m_Info.szFileNameTemplate = IntegerToString(GetInfoTerminal().ID) + ".tpl", true);
103.                                    for (eObjectsIDE c0 = 0; c0 <= MSG_CLOSE_POSITION; c0++) macro_AddAdjust(EnumToString(c0));
104.                                    AdjustEditabled(Template, true);
105.                            }else Template = new C_AdjustTemplate(m_Info.szFileNameTemplate);
106.                            m_Info.ConfigChartTrade.Leverage = (m_Info.ConfigChartTrade.Leverage <= 0 ? 1 : m_Info.ConfigChartTrade.Leverage);
107.                            m_Info.FinanceTake = macro_PointsToFinance(FinanceToPoints(MathAbs(m_Info.FinanceTake), m_Info.ConfigChartTrade.Leverage));
108.                            m_Info.FinanceStop = macro_PointsToFinance(FinanceToPoints(MathAbs(m_Info.FinanceStop), m_Info.ConfigChartTrade.Leverage));
109.                            m_Info.ConfigChartTrade.PointsTake = FinanceToPoints(m_Info.FinanceTake, m_Info.ConfigChartTrade.Leverage);
110.                            m_Info.ConfigChartTrade.PointsStop = FinanceToPoints(m_Info.FinanceStop, m_Info.ConfigChartTrade.Leverage);
111.                            (*Template).Add("MSG_NAME_SYMBOL", "descr", GetInfoTerminal().szSymbol);
112.                            (*Template).Add("MSG_LEVERAGE_VALUE", "descr", IntegerToString(m_Info.ConfigChartTrade.Leverage));
113.                            (*Template).Add("MSG_TAKE_VALUE", "descr", DoubleToString(m_Info.FinanceTake, 2));
114.                            (*Template).Add("MSG_STOP_VALUE", "descr", DoubleToString(m_Info.FinanceStop, 2));
115.                            (*Template).Add("MSG_DAY_TRADE", "state", (m_Info.ConfigChartTrade.IsDayTrade ? "1" : "0"));
116.                            (*Template).Add("MSG_MAX_MIN", "state", (m_Info.IsMaximized ? "1" : "0"));
117.                            (*Template).Execute();
118.                            if (bFirst)
119.                            {
120.                                    for (eObjectsIDE c0 = 0; c0 <= MSG_CLOSE_POSITION; c0++) macro_GetAdjust(c0);
121.                                    m_Info.Regions[MSG_TITLE_IDE].w = m_Info.Regions[MSG_MAX_MIN].x;
122.                                    AdjustEditabled(Template, false);
123.                            };
124.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YSIZE, (m_Info.IsMaximized ? 210 : m_Info.Regions[MSG_TITLE_IDE].h + 6));
125.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, (m_Info.IsMaximized ? m_Info.x : m_Info.minx));
126.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, (m_Info.IsMaximized ? m_Info.y : m_Info.miny));
127.
128.                            delete Template;
129.                            
130.                            ChartApplyTemplate(m_Info.WinHandle, "/Files/" + m_Info.szFileNameTemplate);
131.                            ChartRedraw(m_Info.WinHandle);
132.
133.#undef macro_PointsToFinance
134.#undef macro_GetAdjust
135.#undef macro_AddAdjust
136.                    }
137.//+------------------------------------------------------------------+
138.            eObjectsIDE CheckMousePosition(const int x, const int y)
139.                    {
140.                            int xi, yi, xf, yf;
141.                            
142.                            for (eObjectsIDE c0 = 0; c0 <= MSG_CLOSE_POSITION; c0++)
143.                            {
144.                                    xi = (m_Info.IsMaximized ? m_Info.x : m_Info.minx) + m_Info.Regions[c0].x;
145.                                    yi = (m_Info.IsMaximized ? m_Info.y : m_Info.miny) + m_Info.Regions[c0].y;
146.                                    xf = xi + m_Info.Regions[c0].w;
147.                                    yf = yi + m_Info.Regions[c0].h;
148.                                    if ((x > xi) && (y > yi) && (x < xf) && (y < yf)) return c0;
149.                            }
150.                            return MSG_NULL;
151.                    }
152.//+------------------------------------------------------------------+
153.inline void DeleteObjectEdit(void)
154.                    {
155.                            ChartRedraw();
156.                            ObjectsDeleteAll(GetInfoTerminal().ID, m_Info.szObj_Editable);
157.                            m_Info.ConfigChartTrade.Msg = MSG_NULL;
158.                    }
159.//+------------------------------------------------------------------+
160.            template <typename T >
161.            void CreateObjectEditable(eObjectsIDE arg, T value)
162.                    {
163.                            long id = GetInfoTerminal().ID;
164.                            
165.                            DeleteObjectEdit();
166.                            CreateObjectGraphics(m_Info.szObj_Editable, OBJ_EDIT, clrBlack, 0);
167.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_XDISTANCE, m_Info.Regions[arg].x + m_Info.x + 3);
168.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_YDISTANCE, m_Info.Regions[arg].y + m_Info.y + 3);
169.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_XSIZE, m_Info.Regions[arg].w);
170.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_YSIZE, m_Info.Regions[arg].h);
171.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_BGCOLOR, m_Info.Regions[arg].bgcolor);
172.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_ALIGN, ALIGN_CENTER);
173.                            ObjectSetInteger(id, m_Info.szObj_Editable, OBJPROP_FONTSIZE, m_Info.Regions[arg].FontSize - 1);
174.                            ObjectSetString(id, m_Info.szObj_Editable, OBJPROP_FONT, m_Info.Regions[arg].FontName);
175.                            ObjectSetString(id, m_Info.szObj_Editable, OBJPROP_TEXT, (typename(T) == "double" ? DoubleToString(value, 2) : (string) value));
176.                            ChartRedraw();
177.                            m_Info.ConfigChartTrade.Msg = MSG_NULL;
178.                    }
179.//+------------------------------------------------------------------+
180.            bool RestoreState(void)
181.                    {
182.                            uCast_Double info;
183.                            bool bRet;
184.                            
185.                            if (bRet = GlobalVariableGet(macro_NameGlobalVariable("P"), info.dValue))
186.                            {
187.                                    m_Info.x = info._int[0];
188.                                    m_Info.y = info._int[1];
189.                            }
190.                            if (bRet = (bRet ? GlobalVariableGet(macro_NameGlobalVariable("M"), info.dValue) : bRet))
191.                            {
192.                                    m_Info.minx = info._int[0];
193.                                    m_Info.miny = info._int[1];
194.                            }
195.                            if (bRet = (bRet ? GlobalVariableGet(macro_NameGlobalVariable("B"), info.dValue) : bRet))
196.                            {
197.                                    m_Info.ConfigChartTrade.IsDayTrade = info._char[0];
198.                                    m_Info.IsMaximized = info._char[1];
199.                                    m_Info.ConfigChartTrade.Msg = (eObjectsIDE)info._char[2];
200.                            }
201.                            if (bRet = (bRet ? GlobalVariableGet(macro_NameGlobalVariable("L"), info.dValue) : bRet))
202.                                    m_Info.ConfigChartTrade.Leverage = info._int[0];
203.                            bRet = (bRet ? GlobalVariableGet(macro_NameGlobalVariable("Y"), m_Info.ConfigChartTrade.uCount.dValue) : bRet);
204.                            bRet = (bRet ? GlobalVariableGet(macro_NameGlobalVariable("T"), m_Info.FinanceTake) : bRet);
205.                            bRet = (bRet ? GlobalVariableGet(macro_NameGlobalVariable("S"), m_Info.FinanceStop) : bRet);
206.                            
207.                            
208.                            GlobalVariablesDeleteAll(macro_NameGlobalVariable(""));
209.                            
210.                            return bRet;
211.                    }
212.//+------------------------------------------------------------------+
213.    public  :
214.//+------------------------------------------------------------------+
215.            C_ChartFloatingRAD(const string szShortName)
216.                    :m_Mouse(NULL),
217.                     m_szShortName(szShortName)
218.                    {
219.                    }
220.//+------------------------------------------------------------------+
221.            C_ChartFloatingRAD(string szShortName, C_Mouse *MousePtr, const int Leverage, const double FinanceTake, const double FinanceStop)
222.                    :C_Terminal(),
223.                     m_szShortName(NULL)
224.                    {
225.                            if (!IndicatorCheckPass(szShortName)) SetUserError(C_Terminal::ERR_Unknown);
226.                            m_Mouse = MousePtr;
227.                            if (!RestoreState())
228.                            {
229.                                    m_Info.ConfigChartTrade.Leverage = Leverage;
230.                                    m_Info.FinanceTake = FinanceTake;
231.                                    m_Info.FinanceStop = FinanceStop;
232.                                    m_Info.ConfigChartTrade.IsDayTrade = true;
233.                                    m_Info.ConfigChartTrade.uCount.TickCount = 0;
234.                                    m_Info.ConfigChartTrade.Msg = MSG_NULL;
235.                                    m_Info.IsMaximized = true;
236.                                    m_Info.minx = m_Info.x = 115;
237.                                    m_Info.miny = m_Info.y = 64;
238.                            }
239.                            CreateWindowRAD(170, 210);
240.                            AdjustTemplate(true);
241.                    }
242.//+------------------------------------------------------------------+
243.            ~C_ChartFloatingRAD()
244.                    {
245.                            if (m_Mouse == NULL) return;
246.                            ChartRedraw();
247.                            ObjectsDeleteAll(GetInfoTerminal().ID, m_Info.szObj_Chart);
248.                            FileDelete(m_Info.szFileNameTemplate);
249.                                                            
250.                            delete m_Mouse;
251.                    }
252.//+------------------------------------------------------------------+
253.            void SaveState(void)
254.                    {
255.#define macro_GlobalVariable(A, B) if (GlobalVariableTemp(A)) GlobalVariableSet(A, B);
256.                            
257.                            uCast_Double info;
258.                            
259.                            if (m_Mouse == NULL) return;
260.                            info._int[0] = m_Info.x;
261.                            info._int[1] = m_Info.y;
262.                            macro_GlobalVariable(macro_NameGlobalVariable("P"), info.dValue);
263.                            info._int[0] = m_Info.minx;
264.                            info._int[1] = m_Info.miny;
265.                            macro_GlobalVariable(macro_NameGlobalVariable("M"), info.dValue);
266.                            info._char[0] = m_Info.ConfigChartTrade.IsDayTrade;
267.                            info._char[1] = m_Info.IsMaximized;
268.                            info._char[2] = (char)m_Info.ConfigChartTrade.Msg;
269.                            macro_GlobalVariable(macro_NameGlobalVariable("B"), info.dValue);
270.                            info._int[0] = m_Info.ConfigChartTrade.Leverage;
271.                            macro_GlobalVariable(macro_NameGlobalVariable("L"), info.dValue);
272.                            macro_GlobalVariable(macro_NameGlobalVariable("T"), m_Info.FinanceTake);
273.                            macro_GlobalVariable(macro_NameGlobalVariable("S"), m_Info.FinanceStop);
274.                            macro_GlobalVariable(macro_NameGlobalVariable("Y"), m_Info.ConfigChartTrade.uCount.dValue);
275.                            
276.#undef macro_GlobalVariable
277.                    }
278.//+------------------------------------------------------------------+
279.inline void MountBuffer(double &Buff[], const int iPos = -1)
280.                    {
281.                            static int posBuff = 0;
282.                            uCast_Double info;
283.
284.                            if ((m_szShortName != NULL) || (m_Info.ConfigChartTrade.Msg == MSG_NULL)) return;
285.                            posBuff = (iPos > 5 ? iPos - 5 : posBuff);
286.                            Buff[posBuff + 0] = m_Info.ConfigChartTrade.uCount.dValue;
287.                            info._char[0] = (char)m_Info.ConfigChartTrade.IsDayTrade;
288.                            info._char[1] = (char)m_Info.ConfigChartTrade.Msg;
289.                            Buff[posBuff + 1] = info.dValue;
290.                            info._int[0] = m_Info.ConfigChartTrade.Leverage;
291.                            Buff[posBuff + 2] = info.dValue;
292.                            Buff[posBuff + 3] = m_Info.ConfigChartTrade.PointsTake;
293.                            Buff[posBuff + 4] = m_Info.ConfigChartTrade.PointsStop;
294.                    }
295.//+------------------------------------------------------------------+
296.inline const stData GetDataBuffer(void)
297.                    {
298.                            double Buff[];
299.                            int handle;
300.                            uCast_Double info;
301.                            stData data;
302.                            
303.                            ZeroMemory(data);
304.                            if (m_szShortName == NULL) return data;
305.                            if ((handle = ChartIndicatorGet(ChartID(), 0, m_szShortName)) == INVALID_HANDLE) return data;
306.                            if (CopyBuffer(handle, 0, 0, 5, Buff) == 5)
307.                            {
308.                                    data.uCount.dValue = Buff[0];
309.                                    info.dValue = Buff[1];
310.                                    data.IsDayTrade = (bool)info._char[0];
311.                                    data.Msg = (C_ChartFloatingRAD::eObjectsIDE) info._char[1];
312.                                    info.dValue = Buff[2];
313.                                    data.Leverage = info._int[0];
314.                                    data.PointsTake = Buff[3];
315.                                    data.PointsStop = Buff[4];
316.                            }
317.                            if (handle != INVALID_HANDLE) IndicatorRelease(handle);
318.                            
319.                            return data;
320.                    };
321.//+------------------------------------------------------------------+
322.            void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
323.                    {
324.#define macro_AdjustMinX(A, B)  {                            \
325.             B = (A + m_Info.Regions[MSG_TITLE_IDE].w) > x;  \
326.             mx = x - m_Info.Regions[MSG_TITLE_IDE].w;       \
327.             A = (B ? (mx > 0 ? mx : 0) : A);                \
328.                                }
329.#define macro_AdjustMinY(A, B)  {                            \
330.             B = (A + m_Info.Regions[MSG_TITLE_IDE].h) > y;  \
331.             my = y - m_Info.Regions[MSG_TITLE_IDE].h;       \
332.             A = (B ? (my > 0 ? my : 0) : A);                \
333.                                }
334.                                                                  
335.                            static int sx = -1, sy = -1;
336.                            int x, y, mx, my;
337.                            static eObjectsIDE obj = MSG_NULL;
338.                            double dvalue;
339.                            bool b1, b2, b3, b4;
340.                            eObjectsIDE tmp;
341.    
342.                            if (m_szShortName == NULL) switch (id)
343.                            {
344.                                    case CHARTEVENT_CHART_CHANGE:
345.                                            x = (int)ChartGetInteger(GetInfoTerminal().ID, CHART_WIDTH_IN_PIXELS);
346.                                            y = (int)ChartGetInteger(GetInfoTerminal().ID, CHART_HEIGHT_IN_PIXELS);
347.                                            macro_AdjustMinX(m_Info.x, b1);
348.                                            macro_AdjustMinY(m_Info.y, b2);
349.                                            macro_AdjustMinX(m_Info.minx, b3);
350.                                            macro_AdjustMinY(m_Info.miny, b4);
351.                                            if (b1 || b2 || b3 || b4) AdjustTemplate();
352.                                            break;
353.                                    case CHARTEVENT_MOUSE_MOVE:
354.                                            if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft)) switch (tmp = CheckMousePosition(x = (int)lparam, y = (int)dparam))
355.                                            {
356.                                                    case MSG_TITLE_IDE:
357.                                                            if (sx < 0)
358.                                                            {
359.                                                                    DeleteObjectEdit();
360.                                                                    ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false);
361.                                                                    sx = x - (m_Info.IsMaximized ? m_Info.x : m_Info.minx);
362.                                                                    sy = y - (m_Info.IsMaximized ? m_Info.y : m_Info.miny);
363.                                                            }
364.                                                            if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, mx);
365.                                                            if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, my);
366.                                                            if (m_Info.IsMaximized)
367.                                                            {
368.                                                                    m_Info.x = (mx > 0 ? mx : m_Info.x);
369.                                                                    m_Info.y = (my > 0 ? my : m_Info.y);
370.                                                            }else
371.                                                            {
372.                                                                    m_Info.minx = (mx > 0 ? mx : m_Info.minx);
373.                                                                    m_Info.miny = (my > 0 ? my : m_Info.miny);
374.                                                            }
375.                                                            break;
376.                                                    case MSG_BUY_MARKET:
377.                                                    case MSG_SELL_MARKET:
378.                                                    case MSG_CLOSE_POSITION:
379.                                                            DeleteObjectEdit();
380.                                                            m_Info.ConfigChartTrade.Msg = tmp;
381.                                                            m_Info.ConfigChartTrade.uCount.TickCount = GetTickCount64();
382.                                                            break;
383.                                            }else if (sx > 0)
384.                                            {
385.                                                    ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true);                                                
386.                                                    sx = sy = -1;
387.                                            }
388.                                            break;
389.                                    case CHARTEVENT_OBJECT_ENDEDIT:
390.                                            switch (obj)
391.                                            {
392.                                                    case MSG_LEVERAGE_VALUE:
393.                                                    case MSG_TAKE_VALUE:
394.                                                    case MSG_STOP_VALUE:
395.                                                            dvalue = StringToDouble(ObjectGetString(GetInfoTerminal().ID, m_Info.szObj_Editable, OBJPROP_TEXT));
396.                                                            if (obj == MSG_TAKE_VALUE)
397.                                                                    m_Info.FinanceTake = (dvalue <= 0 ? m_Info.FinanceTake : dvalue);
398.                                                            else if (obj == MSG_STOP_VALUE)
399.                                                                    m_Info.FinanceStop = (dvalue <= 0 ? m_Info.FinanceStop : dvalue);
400.                                                            else
401.                                                                    m_Info.ConfigChartTrade.Leverage = (dvalue <= 0 ? m_Info.ConfigChartTrade.Leverage : (int)MathFloor(dvalue));
402.                                                            AdjustTemplate();
403.                                                            obj = MSG_NULL;
404.                                                            ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Editable);
405.                                                            break;
406.                                            }
407.                                            break;
408.                                    case CHARTEVENT_OBJECT_CLICK:
409.                                            if (sparam == m_Info.szObj_Chart) switch (obj = CheckMousePosition(x = (int)lparam, y = (int)dparam))
410.                                            {
411.                                                    case MSG_DAY_TRADE:
412.                                                            m_Info.ConfigChartTrade.IsDayTrade = (m_Info.ConfigChartTrade.IsDayTrade ? false : true);
413.                                                            DeleteObjectEdit();
414.                                                            break;
415.                                                    case MSG_MAX_MIN:
416.                                                            m_Info.IsMaximized = (m_Info.IsMaximized ? false : true);
417.                                                            DeleteObjectEdit();
418.                                                            break;
419.                                                    case MSG_LEVERAGE_VALUE:
420.                                                            CreateObjectEditable(obj, m_Info.ConfigChartTrade.Leverage);
421.                                                            break;
422.                                                    case MSG_TAKE_VALUE:
423.                                                            CreateObjectEditable(obj, m_Info.FinanceTake);
424.                                                            break;
425.                                                    case MSG_STOP_VALUE:
426.                                                            CreateObjectEditable(obj, m_Info.FinanceStop);
427.                                                            break;
428.                                            }
429.                                            if (obj != MSG_NULL) AdjustTemplate();
430.                                            break;
431.                            }
432.                    }
433.//+------------------------------------------------------------------+
434.};
435.//+------------------------------------------------------------------+
436.#undef macro_NameGlobalVariable
437.//+------------------------------------------------------------------+

C_ChartFloatingRAD 类源代码

我在文章中公布源代码似乎是在开玩笑,但这不是玩笑。事实上,我想尽可能详细地解释一下正在发生的事情。这样做并不是为了让你真正使用这些代码,而是为了让你理解这些代码并创造出更好的内容。

所以,让我们来弄清楚这到底是怎么回事。如果不了解这个类是如何运作的,就无法理解接下来要开发的内容。

我们一开始就有一些变化。在第 12 行,我们声明了一个公共子句。我们用它来使数据可以在类外访问。你可能会认为,我们可以把同样的数据放在其他地方。在这里,我只声明了一个结构和一个枚举。枚举对我们来说已经很熟悉了,但结构却是新的。在第 14 行和第 26 行之间,我们可以看到一个用于组织所需数据的结构声明。

这种结构大多比较容易理解,几乎不需要解释。不过,这里有些东西看起来很奇怪。第 20 行和第 24 行之间的联合有什么作用?第 25 行是做什么用的?联合将使我们能够更容易地传递数据。而且,第 25 行将在一个非常特殊的时刻使用。我们稍后再谈。

第 38 行提到了相同的结构。请记住:类中的数据不能在类外直接访问,因此,我们需要一些方法来访问这些数据。实际上,我们不会直接解决这个问题。从该指标的源代码中可以看出,并没有这种访问。接下来是第 49 行,它做了一件有趣的事情。它将作为一种选择器,但这一点稍后会更清楚。

在第 106 行,我们收集并调整了第 38 行结构中声明的第一个变量。请注意,这与我们之前所做的基本相同,但是我们现在使用的模型略有不同。

因此,在第 109 行,我们调整了其中一个变量,这是获利值点数的变量。请注意,我说的不是金融数值,而是点数。不要混淆这两种东西。我也不是指基于当前交易价格的点数,我说的是一般的点数。价格并不重要,重要的是我们有多少个偏移点数。同样重要的是,这一点数值随后将在金融方面进行调整。这一调整是在第 107 行完成的。

在第 110 行,我们也有类似的操作,只不过这次是针对止损值。正如第 107 行所做的那样,在考虑到第 109 行的点数之前调整金融值。在第 108 行,我们在考虑止损点之前调整止损金融数据。了解此时此刻正在发生的事情非常重要,如果您不能理解这一点,您就很难理解稍后下订单时所作的调整。

为了让您更容易理解,附件中包含了 Mouse 和 Chart Trade 指标以及一个相当简单的 EA 交易,这样您就可以了解发生了什么。出于安全考虑,附件中的 EA 不会下订单,只会打印输入的数值。这可以帮助您了解系统的实际运作方式。

现在,在第 157 行和第 177 行,同样出于实际考虑,我们还要调整一个变量的值。迄今为止,还没有进行过访问,我们要做的就是设置和调整变量的值。但看第 203 行,似乎有些奇怪。为什么要将该值保存在全局终端变量中?我们真的需要这样做吗,还是在浪费时间?事实上,这样做是必要的。原因是删除 Chart Trade 指标并重新加载到图表上时,内存中的所有值都会丢失。但这一数值对我们来说非常重要。

因此,我们在这里恢复之前保存的值。因此,我们在第 203 行恢复的这个值实际上是在第 274 行保存的。您可能已经注意到,我在解释中跳过了一些函数。那么,让我们一起回头看看它们吧。让我们从构造函数开始。是的,现在我们有了两个、而非一个类构造函数。其原因与我们在前一篇文章中讨论的 Mouse 指标相同。我们需要一种从缓冲区传输数据的方法。

说实话,我们并不是真的需要它。我们可以直接在 EA 或指标中实现这一点。不过,为了方便,我更喜欢把所有东西放在一起。使用这种方法,如果我以后需要做任何更改,只需修改 C_ChartFloatingRAD 类即可。我不必为实现模块标准化而对每个程序进行单独配置。回到构造函数,我们有一个从第 221 行开始的旧构造函数。基本上,它会从第 223 行获取数据,我们在该行初始化了指标名称。请注意:该名称不是用于向缓冲区写入数据的,而是用于从缓冲区读取数据的。此外,我们在第 232 行至第 234 行引入了新变量。不是全部,因为其余的都是根据模板设置过程配置的。

第二个构造函数非常简单,从第 215 行开始。在这里,我们主要赋值默认值。这发生在转换阶段。与 Mouse 指标一样,这里也有两个阶段:一个阶段是向缓冲区写入数据,另一个阶段是读取缓冲区。但这并不是因为编程出了问题。如果你在这里看到了一些错误,那么你可能没有理解我们在做什么。事实上,当我们使用指标时,我们会将数据写入缓冲区。这些数据由其他程序(通常是 EA)通过 CopyBuffer 读取。这就是为什么我们有两个阶段,也是为什么我们有两个构造函数。

与构造函数不同,我们只能有一个析构函数,它从第 243 行开始。我们在这里添加的唯一内容是第 245 行的代码。如果我们在指标中使用该类,当调用析构函数时,第 245 行的检查将通过,从而可以删除创建的对象。但如果该类用于读取指标缓冲区,第 245 行中的测试就会失败,然后阻止删除任何对象。这是一种简单而实用的机制。

之前是简单的部分,现在到了我们解释的关键部分。让我们看看如何进行交互,以及如何将数据保存到缓冲区和从缓冲区读取数据。这部分内容对于刚入门的人来说可能会有些困惑。因此,理解前几篇文章中讨论的概念非常重要。为了方便起见,我们来看看图 01。

图 01

图 01 - 交互图

在图 01 中,我们可以看到一个用于从指标向 EA 传输信息的通信系统。请注意,缓冲区实际上不是指标的一部分。尽管缓冲区是在指标中声明的,但它不应被视为指标内存的一部分。事实上,MetaTrader 5 支持这种方法,当我们从图表中删除指标时,后者会释放缓冲区所用的内存。但危险就在这里,数据实际上并没有被销毁,只是释放了内存。这样做的全部危险是什么,我试着用简单的语言来解释一下。

如果在 MetaTrader 5 中缓冲区所在的内存被释放 - 因为指标已从图表中删除,则在写入缓冲区后可能会出现这种情况。如果将指标放回到图表上,缓冲区可能仍包含一些数据。最后更新的时候可能会出现这种情况。因此,当 EA 使用 CopyBuffer 读取这些数据时,可能会读取到错误的数据。

这是非常严重的问题,我们在访问缓冲区时必须格外小心。为了在写入和读取之间提供一些同步,我们需要修改 C_ChartFloatingRAD 类中的 DispatchMessage 方法。写入缓冲区和读取缓冲区之间的同步非常重要,如果操作不当,用户提交的执行内容与实际执行内容之间就会出现延迟。也就是说,用户可能提交买入指令,但该指令不会被执行。但是,如果您在此之后立即发送卖出指令,则又会执行买入指令。这类故障并非由 MetaTrader 5 平台造成,而是由于误解了如何编写代码以确保正确的事件同步。

事实上,EA 和 Chart Trade 指标之间的代码没有任何联系。这种通信是通过使用缓冲区来实现的。因此,EA 不知道 Chart Trade 在做什么,就像 Chart Trade 不知道 EA 实际在做什么一样。不过,MetaTrader 5 知道这两者在做什么。由于指标和 EA 之间的共同点是 MetaTrader 5,因此我们使用 MetaTrader 5 进行操作。当您或用户觉得 EA 和 Chart Trade 指标是同一个程序时,这就就像变魔术一样。

还有一点同样重要,要知道,如果没有前面文章中提到的 Mouse 指标,Chart Trade 指标将不起作用。您需要在图表上使用所有三个应用程序:Mouse 指标、Chart Trade 指标和 EA,以及我们将来要讨论的其他东西。没有这一点,整个系统将什么都不能做。

这一切是如何工作的呢?所有这些都由位于 C_ChartFloatingRAD 类第 353 行的 CHARTEVENT_MOUSE_MOVE 事件来保证。如果 Mouse 指标不在图表上,则可以点击、编辑和修改 Chart Trade 指标的值。这是因为此类事件不一定与 Mouse 指标有关。但是,除非将 Mouse 指标放在图表上,否则您将无法发送买入、卖出、平仓指令或移动 Chart Trade 指标。

但等等,与 Chart Trade 交互时,是否需要在图表上显示 Mouse 指标?是的。虽然可以移除这种依赖关系,但如果以后要使用我将要谈到的其他方法,就会产生另外的问题。如果你想像我一样工作,就必须承受这些代价。因此,您必须充分了解该系统的工作原理,否则,您最终将无法信任该系统。

但让我们回到代码上来,了解我是如何实现系统同步的。要完全理解这一点,你需要了解指标源代码的作用,但如果你读过我在本文开头链接的文章,就应该不会有任何问题。因此,我们假设您已经了解了指标代码如何工作,这样我就可以专注于类的代码。

每次点击或移动鼠标,MetaTrader 5 都会生成一个事件。点击事件通常使用 CHARTEVENT_OBJECT_CLICK 来处理。但是,使用该处理函数无法保持同步。其中的原因解释起来相当复杂,它与执行操作的顺序有关。因此,为了在点击三个 Chart Trade 按钮(买入按钮、卖出按钮和平仓按钮)中的一个按钮时同时在 EA 中生成事件,我们采用了一些不同的方法。

因此,如果将 DispatchMessage 方法中的代码与前一篇文章中的相同代码进行比较,就会发现两者略有不同。不同之处在于处理上述按钮点击的方式。在以前的版本中,这种点击是在 CHARTEVENT_OBJECT_CLICK 事件中处理的,而现在我们是在 CHARTEVENT_MOUSE_MOVE 事件中处理的。由于代码本身会告诉我们哪个对象被点击了,所以我创建了一个新变量,使事情变得更有条理。该变量在第 340 行声明,其值在第 354 行设置。

现在请仔细听我接下来的解释。在第 376 至 378 行中,我们放置了按钮代码。因此,当 Mouse 指标向我们发送数据时,我们就可以向 EA 发送执行命令。但这里有一个小细节。如何告知 EA 按了哪个按钮?这很简单。我们将按钮的代码发送给 EA。这是在第 380 行完成的。现在,我们在第 381 行记录分时报价的数量,以生成一个唯一的数字。这对 EA 是必需的,你很快就会明白它到底是如何工作的。

因此,对于生成的每个事件,除了调用 DispatchMessage 函数准备将数据发送到缓冲区外,我们还将调用另一个函数。就是将数据实际放入缓冲区的那个函数。您可以从该类的第 279 行开始查看其代码。现在让我们看看第 281 行,该行有一个静态变量。它将存储 OnCalculate 事件传递的值。也就是说,我们需要保存 rates_total 的值,原因前面已经解释过了。请阅读开头列出的文章,了解其中的原因。这样,当 OnChartEvent 处理函数被调用时,我们就知道该把数据放在缓冲区的哪个位置了。

请注意,在第 284 行,我们执行了一项检查,以确保只有 Chart Trade 指标会向内存写入数据。此外,只有按下所需的一个按钮时,才会向内存中做记录。这一切都非常好。但是,如果 EA 无法解释 Chart Trade 指标发送给它的数据,这些都没有任何价值。为了了解 EA 如何解释数据,我们需要考虑一些其他代码,这些代码将尽可能基础。


使用测试 EA 交易

既然一切都需要测试,我们就必须确保测试的正确性,清楚地展示实际发生的情况。在这种情况下,为了测试 Chart Trade 指标、Mouse 指标和 EA 之间的交互作用,我们需要使用一个非常简单的系统。但与此同时,我们需要这个系统除了简单之外,还能以我们将来实际使用的方式运行。

根据这一标准,我们将使用以下代码:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property description "Demo version between interaction of Chart Trade and EA"
04. #property version   "1.47"
05. #property link "https://www.mql5.com/es/articles/11760"
06. //+------------------------------------------------------------------+
07. #include <Market Replay\Chart Trader\C_ChartFloatingRAD.mqh>
08. //+------------------------------------------------------------------+
09. C_ChartFloatingRAD *chart = NULL;
10. //+------------------------------------------------------------------+
11. int OnInit()
12. {
13.     chart = new C_ChartFloatingRAD("Indicator Chart Trade");
14.     
15.     return (CheckPointer(chart) != POINTER_INVALID ? INIT_SUCCEEDED : INIT_FAILED);
16. }
17. //+------------------------------------------------------------------+
18. void OnDeinit(const int reason)
19. {
20.     delete chart;
21. }
22. //+------------------------------------------------------------------+
23. void OnTick() {}
24. //+------------------------------------------------------------------+
25. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
26. {
27.     static ulong st_uTime = 0;
28.     C_ChartFloatingRAD::stData info;
29.     
30.     switch (id)
31.     {
32.             case CHARTEVENT_OBJECT_CLICK:
33.                     info = (*chart).GetDataBuffer();
34.                     if (st_uTime != info.uCount.TickCount)
35.                     {
36.                             st_uTime = info.uCount.TickCount;
37.                             PrintFormat("%u -- %s [%s] %d : %f <> %f", info.uCount.TickCount, info.IsDayTrade ? "DT" : "SW", EnumToString(info.Msg), info.Leverage, info.PointsTake, info.PointsStop);
38.                     }else Print("IGNORADO...");
39.                     break;
40.     }
41. }
42. //+------------------------------------------------------------------+

测试 EA 交易的源代码

请注意,这段代码非常简单、紧凑,大部分内容不言自明。不过,有些读者,尤其是初学者,可能无法真正理解它的工作原理。不必为此难过,所有初学者都会遇到类似的困难。但是,只要你努力学习,投入时间,严于律己,不断进取,将来一定会成为一名优秀的专业人员。向困难屈服是不专业的。

现在让我们快速看看代码,因为只有几行,应该很容易理解。

上一主题中介绍的 C_ChartFloatingRAD 类中的所有代码在 EA 这里使用时都进行了总结。虽然我们在第 7 行完全包含了该类,但编译器并不完全这么认为。因此,在第 9 行,我们在全局声明了指针。它将用于访问 C_ChartFloatingRAD 类。这似乎令人困惑,但这只是因为你认为访问该类的方式与访问指标代码的方式相同。

事实上,这样做也是可行的,只是不太实用。原因是该类不打算在没有指标的情况下使用。C_Mouse 类也是如此,该类用于 Mouse 指标,不应在非指标代码中使用。我知道,很多人可能都想这么做。但你不应该这样做。因为所有预期的安全性、建模和性能都不是为了在原始代码之外的代码中使用类。也就是说,如果在 EA 中采用与指标相同的编码方法,实际上就可以达到无需使用 Chart Trade 指标的目的。这是事实。

但是,如果将指标代码转移到 EA 中,整个系统的稳定性和安全性可能会出现问题,因为 EA 的设计并不具备这种稳定性。万物皆有其位置。因此,当我们在第 13 行调用构造函数创建指针时,请注意我使用了与 Chart Trade 指标名称相同的名称。这样,指标和 EA 都能完成各自的工作 。每个组件都各就各位。如果其中一个出现问题,只需在图表上重新启动即可。

现在请注意,几乎所有的代码都可以归结为这一点。指定指标名称,然后在 OnChartEvent 事件处理程序中捕获 CHARTEVENT_OBJECT_CLICK 事件并分析发生了什么。这里有一点很重要。每次点击鼠标时,都会在对象上产生一个点击事件,即使你认为你没有点击任何重要的东西。原因是 Mouse 指标必须始终在图表上。该指标有一条水平线,这就是对象。因此,只要您点击鼠标,这条水平线就会产生一个事件。

但是,系统如何区分对这条线的点击和对另一个对象的点击呢?这是一个相当有趣的问题,很快将成为另一篇文章的主题。不过,在图表上使用不同对象时要注意这一点,主要是因为我们即将添加其他指标。但这是未来的事情。

问题在于第 33 行,对象点击事件将尝试读取 Chart Trade 指标缓冲区的内容。如果成功,我们将获得返回的数据。然后,在第 34 行,我们将检查这是否是与 Chart Trade 相关的事件,还是其他可以忽略的事件。

如果 Chart Trade 中确实产生了一个事件,而且该事件是由点击订单系统交互按钮引起的,我们就会像第 36 行那样更新静态变量的值。之后,我们将向终端输出一条信息,以便分析发生了什么。如果由于某种原因需要忽略该事件,我们就将执行第 38 行。

 

结论

视频 01 展示了该系统的实际运行情况。然而,亲眼目睹系统运行的机会是任何东西都无法替代的。因此,文章附件中包含了当前状态的系统。


视频 01 - 演示



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

附加的文件 |
Anexo_47.zip (175.7 KB)
神经网络变得简单(第 80 部分):图形变换器生成式对抗模型(GTGAN) 神经网络变得简单(第 80 部分):图形变换器生成式对抗模型(GTGAN)
在本文中,我将领略 GTGAN 算法,该算法于 2024 年 1 月推出,是为解决依据图形约束生成架构布局的复杂问题。
在MQL5中相关性分析的要素:皮尔逊卡方独立性检验和相关比率 在MQL5中相关性分析的要素:皮尔逊卡方独立性检验和相关比率
该文章探讨了相关性分析中的经典工具。文章重点介绍了皮尔逊卡方独立性检验和相关比率的理论背景概述,以及它们的实际应用。
如何不通过翻找历史交易记录直接在图表上查看交易情况 如何不通过翻找历史交易记录直接在图表上查看交易情况
在本文中,我们将创建一个简单的工具,通过按键导航方式方便地直接在图表上查看持仓和交易。这将使交易者能够直观地检查每笔交易,并当场获取有关交易结果的所有信息。
最负盛名的人工协作搜索算法的改进版本(AXSm) 最负盛名的人工协作搜索算法的改进版本(AXSm)
在这里,我们将探讨 ACS 算法的演变:三种修改旨在改善收敛特性和算法效率。对最领先的优化算法之一进行修订改版。从数据矩阵修改到种群形成的革命性方法。