市场模拟(第 12 部分):套接字(六)
概述
在上一篇文章“市场模拟(第 11 部分):套接字(五)”中,我们在文中解释了如何创建一个可在 Excel 中使用的 Python 应用程序。这个应用程序的目的是演示如何用 Python 构建回声服务器。其显著特点是,与连接和断开事件相关的数据直接显示在 Excel 中。
事实上,这个服务器对我们来说并没有特别大的用处,主要是因为它只允许一个连接 —— 而设计成只能处理一个连接的服务器,其实际价值是有限的。但是,我不希望你在这个细节上花费太多精力。其目的是展示用 Python 编写的脚本如何在 Excel 中透明地运行。但对于我们的实际需求,服务器必须更先进一些。为了实现这一目标,我们需要实现几个额外的功能。
这里的目标不是创建一个可用于生产环境的应用程序。如前所述,套接字是一个高度复杂的主题,需要大量的时间来研究和探索。不要指望一天之内就能开发出真正强大而完善的产品。处理套接字时,需要深入了解许多细节 —— 有些比较简单,而有些则相当复杂。
然而,由于我们的应用程序需要更复杂的解决方案来实现 Excel 和 MetaTrader 5 之间的通信,因此决定稍微缓解学习曲线。这是因为其目的是向所有刚刚开始探索套接字主题的人展示事物在实践中是如何工作的。
如果这篇文章内容重复或没有提供新的见解,我向更有经验的读者致歉。但这些材料对初学者非常有用,特别是因为我们将完全使用 Python 来完成所有操作。
本文中,我们将不会直接使用 Excel 或 MQL5。但是,在 MQL5 的情况下,我们将能够使用它。更确切地说,我们将利用本系列早些时候开发的内容。为了全面了解材料,回顾 MQL5 中已经实现的内容也会有所帮助。
如果您感兴趣,可以阅读以下文章:
正是在这两篇文章中,我们创建了将作为本文基础的内容。在这些文章中,我们开发了一个迷你聊天,允许 MetaTrader 5 用户通过文本消息交换信息。问题是,当时的服务器代码是用 C++ 编写的。现在我们将开发一个类似的服务器,但这次是用 Python。
让我们先澄清一下
将回声服务器转换为迷你服务器乍一看似乎并不复杂。同样,将回声服务器调整为我们需要的形式,以便在 Excel 和 MetaTrader 5 之间进行通信,也并非特别困难 —— 至少对于那些已经拥有足够经验和知识的人来说是这样。然而,当涉及到套接字时,特别是当多个客户端需要同时使用同一台服务器时,情况会变得更加复杂。这是因为许多人,尤其是初学者,并不真正知道实际需要做什么。
让我们回到上一篇文章中讨论的 Python 代码。如下所示:
01. import socket 02. import xlwings as xw 03. 04. def Echo(): 05. wb = xw.Book.caller() 06. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 07. server.bind(("127.0.0.1", 27015)) 08. wb.sheets[0]['A1'].value = "Waiting connection..." 09. server.listen(1) 10. client, addr = server.accept() 11. client.send("Welcome to Server in Python\n\r".encode()) 12. wb.sheets[0]['A2'].value = str(f"Client connected by {addr}") 13. while True: 14. info = client.recv(512) 15. if not info: 16. break 17. client.send(b"Echo Server:" + info) 18. wb.sheets[0]['A3'].value = "Client disconnected" 19. client.close()
Python 服务器
虽然如果没有上一篇文章中提供的材料,这段代码将无法工作,但它可以使其具有功能,并随后用作模块。鉴于 Excel 不会与 Python 结合使用,因此需要删除代码的某些部分才能实现这些更改。代码将如下所示:
01. import socket 02. 03. def Echo(): 04. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 05. server.bind(("127.0.0.1", 27015)) 06. server.listen() 07. client, addr = server.accept() 08. client.send("Welcome to Server in Python\n\r".encode()) 09. while True: 10. info = client.recv(512) 11. if not info: 12. break 13. client.send(b"Echo Server:" + info) 14. client.close() 15. 16. if __name__ == "__main__": 17. Echo()
Python 服务器
好吧,如果你已经对 Python 有点熟悉,你可能已经注意到这里发生了什么。但如果你不熟悉 Python,你可能会想:“怎么会这样疯狂?”事实上,这没什么疯狂的。简单来说,之前无法由 Python 解释器直接执行的代码,现在可以执行了。添加了第 16 行和第 17 行代码后,这一切成为可能 —— 而正是因为有了这两行代码,该代码仍然可以在模块中使用。
但这并非我们在此讨论的重点,问题在于如何使所提供的代码能够接受多个客户端,尽管原则上它目前无法做到这一点。
好吧,如果您已经研究了前面文章中包含的参考资料,那么您应该已经了解了此代码中存在的一些细节和问题。这是因为它本质上被设计为一次只接受一个连接。但这怎么可能呢?这是因为第 07 行的 accept 函数一旦执行,就不会再次运行。这会阻止其他客户端连接。即使同一客户端关闭了连接,它们也无法重新连接。
原因相同:accept 函数将不再执行。“那么,是否可以在这段代码中添加另一个循环,以便在客户端决定返回时再次运行第 7 行到第 14 行之间的内容?”是的,可以。事实上,在一些更简单的情况下,这正是程序员会做的。然而,让我们进一步思考,因为即使我们实现了该解决方案,我们仍然只有一个连接的客户端。对于我们的迷你聊天来说,这还不够。
除了这个问题之外,还有另一个问题。如果您测试了前两篇文章中介绍的内容,您可能已经注意到,当服务器正在使用时,Excel 实际上变得没有响应。上述文章包括:
这是给那些还没有读过这些文章的人的。现在的问题是:为什么在回声服务器运行时 Excel 会变得难以使用?要回答这个问题,就必须了解服务器代码内部发生了什么。必须记住,Excel 通过 VBA 调用需要执行的 Python 代码。当 Python 代码开始运行时,它开始与 Excel 争夺 CPU 使用率。
对操作系统而言,Python 代码并不是一个独立的进程。实际上,它更像是 Excel 的一个线程。在这种情况下,“线程”一词实际上并不是最合适的术语,因为线程通常不会与主程序竞争 CPU 时间。然而,由于关闭 Excel 也会终止 Python 代码,因此我们可以在这里谨慎地使用“线程”一词。但是,在使用这种术语时应该谨慎,原因稍后会解释。
然而,仍然存在一个合理的问题:当 Excel 有自己的处理时间窗口时,为什么 Python 代码会争夺 CPU 使用率?这是由代码中的两个特定点造成的。让我们回到最初的回声服务器代码。请注意,第 10 行调用了 accept 函数,此函数被阻塞。也就是说,执行时,代码会在此处停止,直到建立连接后才会继续执行。该函数代表了第一个瓶颈 —— Python 脚本与 Excel 争夺 CPU 使用率的第一个实例。
连接建立后,就会出现第二个问题。这种情况恰好发生在第 14 行,Python 脚本再次与 Excel 发生竞争。每次涉及第 14 行的交互都会重复这种竞争。因此,Excel 受到的关注度低于 Python 脚本,导致在服务器运行时难以使用。
但是有办法解决这个问题吗?是的,有好几种选择。第一种,可以让 Python 脚本成为 Excel 的一个真正线程。这样,当 Excel 进入执行窗口时,Excel 和 Python 脚本就不会再争夺 CPU 使用率了。这是因为操作系统会调度任务,以便每个任务都能获得一部分处理时间。对于多核处理器,操作系统可以允许 Excel 使用一个核心,而 Python 脚本使用另一个核心。然而,为了实现这一点,Excel 必须通知操作系统 Python 脚本将成为线程。
但我们究竟在讨论哪种类型的线程?为了理解这一点,让我们转向一个新的话题。
让我们了解一下线程是什么
粗略地说,线程就像主程序中存在的另一个程序。的确,这是一种描述线程的简单方法。线程仅在主程序运行时存在。当主程序(在本例中为 Excel)停止运行时,与其相关的一切也会终止。
线程的概念是随着并行处理而出现的。事实上,这正是线程的目的:它帮助主程序执行很难在主代码中直接实现的任务。为了实现这一点,我们将一部分代码放入与主程序并行运行的段中。
线程完成其工作后,主程序就可以使用计算或接收的数据。这些数据将在我们预留的区域内提供。这是一种非常有趣的编程形式,因为通过使用线程,即使分配给线程的任务需要几分钟才能完成,您也可以在允许主程序继续运行的同时执行任务。
这种能力 —— 无论是在 Python 中还是在其他语言中 —— 都非常引人注目。然而,要真正了解正在发生的事情以及使用线程的优势是什么,有必要看到它的实际应用。为了避免在没有实际示例的情况下离开主题,我们将研究一个在 Python 中使用线程的案例。
01. import socket as sock 02. import threading as thread 03. 04. def NewClientHandler(conn, addr): 05. print(f"Client [%s:%s] is online..." % addr) 06. while True: 07. msg = conn.recv(512).decode().rstrip(None) 08. if msg: 09. print(f"Message from [%s:%s]: {msg}" % addr) 10. if msg.lower() == "/see you later": 11. break 12. print(f"Client [%s:%s] is disconnected..." % addr) 13. conn.close() 14. 15. server = sock.socket(sock.AF_INET, sock.SOCK_STREAM) 16. server.bind(('localhost', 27015)) 17. server.listen() 18. print("Waiting connections...") 19. while True: 20. conn, addr = server.accept() 21. conn.send("Welcome to Server.\n\r".encode()) 22. thread.Thread(target=NewClientHandler, args=(conn, addr)).start()
Python 服务器
上面提供了此服务器的代码,它使用线程同时处理多个客户端。请注意一些重要细节。首先,服务器不会将一个客户端提供的信息转发给其他客户端。其次,它仅用于教育目的 —— 即演示线程的使用方法。然而,如果你了解正在发生的事情,你就可以通过修改上面的代码来创建许多有趣的东西。
但让我们先了解一下这段代码中发生了什么。如果你已经熟悉Python,那么你可能需要对初学者多一些耐心。记住,总有人曾经教过你 —— 或者你从别人编写的文档中学习过,请耐心等待。
在第 01 行,我们导入 socket 包。请注意,我们的呈现方式略有不同。在第 02 行,我们导入了允许我们创建线程的包。与第 01 行一样,这里有些东西可能看起来不寻常,但不要惊慌。我们正在创建一个别名,使 Python 中的操作更加友好和易于理解。
第 04 行到第 13 行之间有一个过程。我们暂时搁置它,移至第 15 行。请注意,第 15 行到第 18 行之间的代码与今天文章中的前面示例几乎完全相同。这部分负责创建服务器套接字,所以代码是相同的。需要注意的一点是:在这些示例中,我们使用的是 TCP 协议。但值得记住的是,还有其他网络协议,因此代码可能会因服务器而异,主要是由于我们稍后将讨论的某些方面。。
总之,在第 18 行,我们表明服务器已准备好接受连接。还记得前面提到的细节吗 —— 需要在 accept 调用之前放置一个循环?没错,我们现在正是这么做的。因此,即使客户端断开连接,它也能重新连接到服务器,因为循环允许与 accept 调用进行多次交互。现在让我们回顾一下另一个细节:accept 调用会阻塞代码并强制其等待连接。当这种情况发生时,执行继续到第 21 行,该行向新客户端发送欢迎消息,确认连接已建立。然后,在第 22 行,用 Python 创建了一个线程。
事情从这里开始变得真正有趣起来,一些非常重要的事情也随之出现。如果我们把代码放在第 04 行和第 13 行之间,而不是放在第 22 行,服务器的行为将完全不同。这是因为代码不再允许多个连接 —— 它只接受一个连接。
“等等,这怎么可能?”要理解这一点,你需要明白第 22 行并不是神奇的一行。实际上,它调用了第 04 行定义的过程。但是,会成为线程的调用和不会成为线程的调用之间存在一个关键区别。一旦调用成为一个线程 —— 如这段代码所示 —— 操作系统就会执行以下操作:它获取线程代码,将其分配到内存中,并在主代码本身和线程之间划分主代码的执行时间或窗口。
起初,这可能有点令人困惑。但这样想吧:操作系统为程序执行分配的时间就像一块巧克力棒。当一个程序没有线程时,它可以占用整个棒。但当它有线程时,那根棒会被分成越来越小的片段。这样,主程序只能使用其中的一部分片段,其余部分将由线程使用。如果我们的处理器只有一个核心,那么这个解释就相当简单了。
回到我们的代码,请注意,执行第 22 行后,程序“分裂”成两部分。其中一部分立即返回到第 19 行,然后在第 20 行再次等待。需要注意的是,accept 函数会阻塞代码,阻止其继续执行。另一部分将转到第 04 行。
好吧,“我现在完全糊涂了 —— 如果代码在第 20 行被阻塞,那么第 4 行的代码怎么可能运行呢?这太令人困惑了。”亲爱的读者们,请冷静 —— 无需感到困惑。还记得巧克力棒的例子吗?主代码将在第 20 行阻塞,等待新的客户端连接。然而,第 4 行和第 13 行之间的代码将独立于新的客户端连接执行。重要的是,服务器将开始监听来自连接的客户端的信息。因此,我们在第 06 行引入一个新的循环。注意这一点,因为如果你不理解这部分,你会完全迷失在线程的工作方式中。
这个循环从第 06 行开始,到第 11 行结束,它只存在于该线程中。每个客户端 —— 这一点很重要 —— 都会有自己的循环。因此,即使连接了两个或多个客户端,一个客户端也不会干扰另一个客户端的运行。现在想象一下,每个客户端都有自己的服务器,专门服务于该客户端。换句话说,每个已连接或将要连接的客户端都会为自己创建一个服务器。而且这台服务器只会响应该客户端。
这就是线程的魔力。然而,并非所有这些奇迹都是完美的。使用线程时会出现一些问题。当我们作为程序员开始不加选择地使用它们时,许多问题就会出现。始终记住,线程会占用主程序的时间,即使它看起来是并行运行的。这是因为无论我们的处理器有多少个核心,它们的数量都是有限的。因此,过度使用线程可能会消耗所有可用核心,导致执行时间增加,从而降低使用线程的优势。
您可能还有其他疑问。虽然这段代码可以处理多个客户端,但它不允许客户端之间相互通信。能否使用线程在客户端之间传递信息?如果你脑海中闪过这个想法,那意味着你仍然不完全理解线程是如何工作的。但不要气馁。相反,你应该感到满意,因为你提出了这个问题。如果在查看代码和阅读文章时,你确实这么想,这表明你真正理解了服务器的工作原理。然而,问题出现的事实表明,你还没有完全掌握线程的概念。那么,让我们来消除这些疑虑。为了区分这些概念,我们将在下一节中进行探讨。
客户端到客户端的通信由线程管理
要理解这是如何工作的,你需要掌握到目前为止所涵盖的内容。如果你没有完全理解前面的主题,请回去再读一遍。理解它们很重要 —— 否则,你会对这一部分更加困惑,尽管这一部分相对较短,但可能会让你感到困惑,更糟糕的是,你可能完全不明白到底发生了什么。
我们来看一下代码。
01. import socket as sock 02. import threading as thread 03. 04. CONN_LIST = [] 05. 06. def NewClientHandler(conn, addr): 07. global CONN_LIST 08. CONN_LIST.append(conn) 09. print(f"Client [%s:%s] is online..." % addr) 10. while True: 11. msg = conn.recv(512).decode().rstrip(None) 12. if msg: 13. print(f"Message from [%s:%s]: {msg}" % addr) 14. for slave in CONN_LIST: 15. if slave != conn: 16. slave.send(f"[{addr[0]}]: {msg}\n\r".encode()) 17. if msg.lower() == "/see you later": 18. break 19. print(f"Client [%s:%s] is disconnecting..." % addr) 20. conn.close() 21. CONN_LIST.remove(conn) 22. 23. server = sock.socket(sock.AF_INET, sock.SOCK_STREAM) 24. server.bind(('0.0.0.0', 27015)) 25. server.listen() 26. print("Waiting connections...") 27. while True: 28. conn, addr = server.accept() 29. conn.send("Welcome to Server.\n\r".encode()) 30. thread.Thread(target=NewClientHandler, args=(conn, addr)).start()
Python 服务器
“但这是什么?你只添加了几行代码 —— 你确定这样就能让客户端之间互相发送消息吗?”是的,我向你保证,这段代码不仅使信息能够在客户端之间转发,而且使服务器显示这些消息。这可以在服务器运行的命令提示符窗口中看到。
然而,在这段代码中有一个重要方面需要注意:旧消息将无法访问。这意味着只有当前连接到服务器的客户端才会接收消息。“但这究竟是如何运作的呢?我看了代码,但还是不明白。”
要了解服务器如何设法传输发送给其他客户端的消息,您需要了解线程是如何工作的。我们在上一节中已经介绍过这一点。如果你已经掌握了线程的功能,我们现在就可以继续了解它们是如何相互通信的。这是正确的。为了使线程能够向其他客户端发送消息,它们需要共享信息。但这该如何实现呢?最简单的情况是,这是通过共享内存区域实现的 —— 该共享部分在第 04 行明确定义。换句话说,第 04 行声明的列表对所有线程都是可见的。
为了确保一切顺利运行,我们在线程的第 07 行将列表声明为全局列表。这样可以防止 Python 在本地创建它。如果 Python 在本地创建它,则内存不会在线程之间共享,而我们是需要共享的。在第 08 行,我们将创建线程的连接添加到我们的列表中。这一步至关重要,因为每个新连接都会生成一个新线程,并向列表中添加一个新条目。
当执行第 11 行时,它会阻塞,等待从连接接收数据 —— 这在每个线程中都是独立发生的。一旦客户端向服务器发送数据,我们就进入第 14 行的小循环。这就是“奇迹”发生的地方。请注意,我们会遍历各个线程创建的连接列表。然而,循环并不受此影响 —— 由于内存是线程之间共享的,它将逐个遍历所有连接。
如果第 15 行的条件为 false(即,如果连接与当前线程循环中的连接匹配),则我们什么也不做。但如果测试结果为 true,则执行第 16 行。它会将此线程接收到的所有数据发送到由另一个线程管理的连接。我希望你能理解这一部分。请记住:每个线程对应一个连接。当一个连接接收到数据时,它会触发循环将该数据转发给其他连接。但是,这并不会使其他线程变为活动状态。
“等一下。这怎么可能呢?如果一个线程向其他连接发送数据,则其他线程应该变为活动状态。不,亲爱的读者。你的推理有缺陷。并非完全错误,但你忽略了以下一点:服务器不会监听线程内部发生的事情。它会监听客户端发生的事情。对于每个客户端,服务器似乎都以独占方式连接到专用服务器。客户端完全不知道它位于一个线程中。
最后,当客户端断开连接时,我们会从列表中删除第 21 行添加的连接标识符。这样,所有其他线程将不再看到最近关闭的连接。
总结性思考
虽然这看起来可能很令人困惑,但线程这个话题与套接字这个话题一样重要。然而,使用线程的解决方案只是众多可能的解决方案之一。下一篇文章我们将讨论解决此问题的另一种方法,因为这种基于线程的解决方案无法解决 Excel 问题。这是因为我们仍然面临 accept 函数阻塞服务器的问题,使得在 Excel 中使用 Python 的体验并不特别愉快 —— 至少对于那些需要使用套接字的人来说是这样。
| 文件 | 描述 |
|---|---|
| Experts\Expert Advisor.mq5 | 演示 Chart Trade 与 EA 交易之间的交互(需要 Mouse Study 才能进行交互)。 |
| Indicators\Chart Trade.mq5 | 创建一个窗口,用于配置要发送的订单(需要 Mouse Study 进行交互)。 |
| Indicators\Market Replay.mq5 | 创建用于与回放/模拟服务交互的控件(交互需要 Mouse Study)。 |
| Indicators\Mouse Study.mq5 | 提供图形控件与用户之间的交互(回放系统和真实市场操作都需要)。 |
| Services/Market Replay.mq5 | 创建并维护市场回放/模拟服务(整个系统的主文件)。 |
| Code VS C++ Server.cpp | 创建并维护一个用 C++ 开发的套接字服务器(迷你聊天版本)。 |
| Python\Server.py 中的代码 | 创建并维护用于 MetaTrader 5 和 Excel 之间通信的 Python 套接字。 |
| ScriptsCheckSocket.mq5 | 允许测试与外部套接字的连接。 |
| Indicators\Mini Chat.mq5 | 通过指标实现迷你聊天(需要服务器运行)。 |
| Experts\Mini Chat.mq5 | 在 EA 交易中实现迷你聊天功能(需要服务器正常运行)。 |
本文由MetaQuotes Ltd译自葡萄牙语
原文地址: https://www.mql5.com/pt/articles/12745
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
新手在交易中的10个基本错误
基于混沌理论的超买超卖分析
感谢您提供的信息......插座如何帮助连接来自不同经纪商的两个 MT5 终端?一个是外汇,另一个是摩根士丹利 - 两个终端的配对交易 可以通过插座实现吗?
我自己也在研究这个话题......如果我的问题有点跑题,请事先见谅....。我仍在阅读文章并寻找解决方案,以实现两个 MT5 的联合交易,并在分析 2-3-4-5 个符号的报价数据后,从不同交易所获取符号报价,并进行联合交易.....。
我将套接字:
终端间交换:数据直接在 MT5 A 和 MT5 B 之间传输。
事件 : 收到数据时立即 触发 OnSocketEvent()。
数据灵活性:可传输 JSON、二进制结构和数组。
速度:延迟比变量轮询低一个数量级。
可靠性:有重新发送和确认机制。
在这种情况下,我计划制作一个高级 Python 服务器,其中包含传播计算、ACK/NACK、位置状态存储和用于监控的网络接口;
我自己也在研究这个话题......如果我的问题有点跑题,请事先见谅....。我仍在阅读文章并寻找解决方案,以便在一个套接字中进行两个 MT5 交易,并在分析 2-3-4-5 个符号的报价数据后,从不同交易所获取符号报价,然后在套接字中进行交易....。
在这里,我将套接字旋转:
终端间交换 :数据直接在 MT5 A 和 MT5 B 之间传输。
事件 : 收到数据时立即 触发 OnSocketEvent()。
数据灵活性 :可传输 JSON、二进制结构和数组。
速度 :延迟比变量轮询低一个数量级。
可靠性 :有重新发送和确认机制。
在这种情况下,我计划制作:一个先进的 Python 服务器,包括传播计算、ACK/NACK、位置状态存储和用于监控的网络接口;
您的问题很相关,也很有趣。但我认为您的结论过于草率。让我澄清一下:虽然 MQL5 实现了套接字,但正如我在文章中解释的那样,它不允许您创建服务器。只能创建客户端。因此,您打算做的很多事情都是不可能的。 不可能 在 MQL5 中实现。您需要外部代码。在您的案例中,您提到使用 Python,这本身就是一种解决方案。
事实上,您所需要的大部分内容都可以在 Python 中实现。但是,您要做的事情有一个小问题:直接与代理交互。我为什么这么说呢?出于安全考虑,代理通常不接受通过套接字进行访问。这种交互有一个特殊的协议,专门用来防止中断代理的内部机制。但也不是不可以尝试。他们可以告诉你通信协议,这样你就可以在适合的时候访问它。但不要以为这很容易,除非你在经纪公司有一个非常要好的朋友,可以为你提供所需的信息。
另一个引起我注意的问题是 MetaTrader 5 两个不同实例之间的互动和信息交换。依我之见,您的尝试并不是一个好主意。您不了解并行编程的一些概念和相关问题。如果您不介意,可以尝试研究一下 "生产者-消费者 "任务。它将帮助您了解在不同 MetaTrader 5 实例之间传输信息进行交易时可能遇到的复杂程度和陷阱。
无论如何,祝您的项目好运 🙂👍
你的问题很贴切,也很有趣。但我认为您的结论过于草率。让我澄清一下:虽然 MQL5 实现了套接字,但正如我在文章中解释的那样,它不允许您创建服务器。只能创建客户端。因此,您打算做的很多事情都是不可能的。 不可能 在 MQL5 中实现。您需要外部代码。在您的案例中,您提到使用 Python,这本身就是一种解决方案。
事实上,您需要的大部分功能都可以在 Python 中实现。但是,您要做的事情有一个小问题:直接与代理交互。我为什么这么说呢?出于安全考虑,代理通常不接受通过套接字进行访问。这种交互有一个特殊的协议,专门用来防止中断代理的内部机制。但也不是不可以尝试。他们可以告诉你通信协议,这样你就可以在适合的时候访问它。但不要以为这很容易,除非你在经纪公司有一个非常要好的朋友,可以为你提供所需的信息。
另一个引起我注意的问题是 MetaTrader 5 两个不同实例之间的互动和信息交换。依我之见,您的尝试并不是一个好主意。您不了解并行编程的一些概念和相关问题。如果您不介意,可以尝试研究一下 "生产者-消费者 "任务。这将有助于您了解在不同 MetaTrader 5 实例之间为交易目的传输信息时可能遇到的复杂程度和陷阱。
无论如何,祝您的项目好运 🙂👍
非常感谢您提供的反馈.....在两家不同的经纪公司都有 MT5 终端!需要让它们成为朋友.....。) 这是明年的一个项目!!!
这里 - 尝试...感谢您的文章 - 我正在阅读并研究其中的内容!!如果速度允许 - 也许我会直接通过文件来做...访问 - 就像早期的硬盘一样,在 BIOS 中连接两块:一块主硬盘,一块从硬盘...)
所以...在一台功能强大的计算机上有两个 MT5 终端,一个是主(主要)--另一个是从(次要),一个是证券交易所--另一个是 MT5 外汇交易!也许可以通过文件来实现)读取 - 写入就可以了......但我想在读取 - 接收数据方面实现更快的简便变....通过客户端的全局变量类型(我不使用文件 - 时间长了),但客户端的全局变量只在本终端可见.....。您需要连接外部进程...也许可以在内存中建立表格...比如连接的 dll 库,我会意识到的!..!
祝您愉快