python接收_MT5与PYTHON的集成:接收和发送数据
为什么要把 MQL5 与 Python 集成?
全⽅位的数据处理需要⼤量⼯具,并且经常超出单⼀应⽤程序的功能沙箱。专⽤编程语⾔正在⽤于处理和分析数据,统计和机器学习。Python 是数据处理的主要编程语⾔之⼀。⼀个⾮常有效的解决⽅案是利⽤语⾔的⼒量并包含函数库来开发交易系统。
在两个或更多个程序之间实现交互存在众多不同的解决⽅案。套接字是最快速、最灵活的解决⽅案之⼀。
⽹络套接字是计算机⽹络上进程间通信的端点。MQL5 标准库包含⼀组 Socket 函数,这些函数为在互联⽹上操作提供了⼀个低层接⼝。这是不同编程语⾔的通⽤接⼝,因为它在操作系统级别进⾏系统调⽤。
价格之间的数据交换是通过 TCP/IP(传输控制协议/互联⽹协议)实现的。因此,进程可以在单个计算机内,以及通过局域⽹或互联⽹进⾏交互。
若要建⽴连接,必须创建并初始化 TCP 服务器,以便客户端进程连接。⼀旦交互进程完成,则连接必须强制关闭。TCP 交换中的数据是字节流。
创建服务器时,我们需要将套接字与⼀个或多个主机(IP 地址)的未使⽤端⼝相关联。如果未设置主机列表,或将其指定为 “0.0.0.0”,则套接字将监听所有主机。如果指定 “127.0.0.1” 或 “localhost”,则只能在 “内部循环” 内连接,即仅在⼀台计算机内监听。
由于在 MQL5 中只提供客户端,我们利⽤ Python 创建⼀个服务器。
利⽤ Python 创建套接字服务器
本⽂的⽬的并⾮教授 Python 编程的基础知识。因此,假定读者熟悉这种语⾔。
我们将使⽤ 3.7.2 版本的内置 socket 软件包。更详细信息,请阅读相关⽂档。
我们将编写⼀个简单的程序,它创建⼀个套接字服务器,并从客户端(MQL5 程序)接收必要的信息,处理它并发回结果。这似乎是最有效的交互⽅法。假设我们需要使⽤机器学习函数库,例如 scikit learn,它将计算价格的线性回归并返回坐标,根据这些坐标可以在MetaTrader 5 终端中绘制⼀条线。这是基本的⽰例。然⽽,这种交互也可以⽤于训练神经⽹络,⽤于从终端发送数据(报价),学习并将结果返回给终端。
我们来创建 socketserver.py 程序并导⼊上述函数库:
import socket, numpy as np
from sklearn.linear_model import LinearRegression
现在我们可以继续创建⼀个负责处理套接字操作的类:
class socketserver:
def __init__(self, address = '', port = 9090):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.address = address
self.port = port
self.sock.bind((self.address, self.port))
self.cummdata = ''
def recvmsg(self):
self.sock.listen(1)
<, self.addr = self.sock.accept()
print('connected to', self.addr)
self.cummdata = ''while True:
data = v(10000)
self.cummdata+=data.decode("utf-8")if not data:break
def __del__(self):
self.sock.close()
创建类的对象时,构造函数将获取主机名(IP 地址)和端⼝编号。然后创建 sock 对象,该对象与地址和端⼝ sock.bind() 相关联。
recvmsg ⽅法监听传⼊连接 sock.listen(1)。当传⼊的客户端连接到达时,服务器会接受它 self.sock.accept()。
然后,服务器在⽆限循环中等待传⼊的客户端消息,该消息抵达时是为数位流。由于事先不知道消息长度,服务器会分帧接收该消息,⽐如⼀次 1K 字节,直到读取整个消息 v(10000)。接收到的数据⽚段将会被转换为字符串 data.decode(“utf-8”),并添加到字符串 summdata 的其余部分。
⼀旦收到所有数据(如果不是数据 :),服务器就会向客户端发送⼀个字符串,其中包含计算出的回归线的最右边和最左边的坐标。该字符串初步转换为字节数组 conn.send(bytes(calcregr(self.cummdata),"utf-8"))。
在末尾,该⽅法返回从客户端收到的字符串。它可以⽤于所接收报价的可视化,亦或其它。
⼀旦 Python 程序执⾏完毕,析构函数就会关闭套接字。
请注意,这并⾮该类唯⼀可能的实现。替代⽅案,您可以分离接收和发送消息的⽅法,并在不同的时间点以不同的⽅式使⽤它。我只是描述创建连接的基本技术。您可以实现⾃⼰的⽅案。
我们来更详尽地考察当前实现中的线性回归学习⽅法:
def calcregr(msg = ''):
chartdata = np.fromstring(msg, dtype=float, sep= ' ')
Y = np.array(chartdata).reshape(-1,1)
X = np.array(np.arange(len(chartdata))).reshape(-1,1)
lr = LinearRegression()
lr.fit(X, Y)
Y_pred = lr.predict(X)
type(Y_pred)
P = Y_pred.astype(str).item(-1) + ' ' + Y_pred.astype(str).item(0)
print(P)
return str(P)
接收到的字节流转换为 utf-8 字符串,然后由 calcregr(msg ='') ⽅法接受。由于字符串包含若⼲由空格分隔的价格序列(在客户端中实现),因此它将被转换⾄ float 类型的 NumPy 数组。之后价格数组会被转换为⼀列(数据接收格式为 sclearn)Y =
np.array(chartdata).reshape(-1,1)。模型的预测变量是线性时间(⼀个数值序列; 其⼤⼩等于训练样本的长度)X =
np.array(np).arange(len(chartdata))).reshape(-1,1)
接下来是训练和模型预测,⽽回归线的第⼀个和最后⼀个值(线段的边缘)被写⼊ “P” 变量,转换为字符串,并以字节形式传递给客户端。
现在,我们只需要创建类对象,并在循环中调⽤ recvmsg() ⽅法:
serv = socketserver('127.0.0.1', 9090)
while True:
msg = vmsg()
利⽤ MQL5 创建套接字客户端
我们创建⼀个简单的智能交易系统,它可以连接到服务器,传递指定数量的近期收盘价,得到反馈的回归线坐标,并将其绘制在图表上。
socksend() 函数将数据传递给服务器:
bool socksend(int sock,string request)
{  char req[];  int  len=StringToCharArray(request,req)-1;  if(len<0) return(false);  return(SocketSend(sock,req,len)==len);
}
它接收字符串,转换为字节数组,并发送到服务器。
socketreceive() 函数监听端⼝。⼀旦收到服务器响应后,该函数将其作为字符串返回:
string socketreceive(int sock,int timeout)
{char rsp[];string result="";uint len;uint timeout_check=GetTickCount()+timeout;do
{
len=SocketIsReadable(sock);if(len)
{int rsp_len;
rsp_len=SocketRead(sock,rsp,len,timeout);if(rsp_len>0)
{
result+=CharArrayToString(rsp,0,rsp_len);
}
}
}while((GetTickCount()IsStopped());return result;
}
最后⼀个函数 drawlr() 接收⼀个字符串,其中写⼊左、右线坐标,然后将字符串解析为字符串数组,并在图表上绘制线性回归线:
void drawlr(string points)
{string res[];StringSplit(points,' ',res);if(ArraySize(res)==2)
{Print(StringToDouble(res[0]));Print(StringToDouble(res[1]));datetime temp[];CopyTime(Symbol(),Period(),TimeCurrent(),lrlenght,temp);ObjectCreate(0,"regrlin      }
该函数在 OnTick() 处理程序中实现。
void OnTick() {
socket=SocketCreate();if(socket!=INVALID_HANDLE) {if(SocketConnect(socket,"localhost",9090,1000)) {Print("Connected to "," localhost",":",9090);double clpr[];  drawlr(recieved); }else Print("Connection ","localhost",":",9090," error ",GetLastError());
SocketClose(socket); }else Print("Socket creation error ",GetLastError()); }
测试 MQL5-Python 客户端 - 服务器应⽤程序
为了运⾏该应⽤程序,您需要安装 Python 解释器。您可以从 官⽅⽹站 下载。
然后运⾏服务器应⽤程序 socketserver.py。它创建⼀个套接字,并监听来⾃ MQL5 程序 socketclientEA.mq5 的新连接。
连接成功后,连接过程和回归线价格将显⽰在程序窗⼝中。价格会反馈给客户端:
连接活动和回归线价格也会在 MetaTrader 5 终端中显⽰。回归线也会在图表上绘制,并在每次新的即时报价来临时进⼀步更新:
我们已考研究通过套接字连接实现两个程序的直接交互。与此同时,MetaQuotes 已开发了⼀个 Python 软件包,允许直接从终端接收数据。更多有关详细信息,请参阅与 在 MetaTrader 中使⽤ Python 相关的论坛讨论(俄语版,请酌情使⽤⾃动翻译选项)。 s0>
我们创建⼀个脚本来演⽰如何从终端接收报价。
使⽤ MetaTrader 5 Python API 获取并分析报价
⾸先,您需要安装 MetaTrader5 Python 模块(Python 讨论摘要在此)。
pip install MetaTrader5
将其导⼊程序,并初始化与终端的连接:
from MetaTrader5 import *from datetime import date
import pandas as pd
import matplotlib.pyplot as plt
# 初始化 MT5 连接
MT5Initialize()
MT5WaitForTerminal()
print(MT5TerminalInfo())
print(MT5Version())
之后创建所需品种列表,并从终端连续请求每个货币对的收盘价发⾄ pandas 数据帧:
# 为需要绘制相关矩阵的货币创建清单
sym = ['EURUSD','GBPUSD','USDJPY','USDCHF','AUDUSD','GBPJPY']
# 将数据复制到数据帧
d = pd.DataFrame()for i in sym:
rates = MT5CopyRatesFromPos(i, MT5_TIMEFRAME_M1, 0, 1000)
d[i] = [y.close for y in rates]
现在我们可以断开与终端的连接,然后计算相关矩阵,并在屏幕上显⽰货币对价格变化的百分⽐:
# 逆初始化 MT5 连接
MT5Shutdown()
# ⽐较百分⽐变化
rets = d.pct_change()
# 计算相关性
corr = ()
# 绘制相关性矩阵
plt.figure(figsize=(10, 10))
plt.imshow(corr, cmap='RdYlGn', interpolation='none', aspect='auto')
python货币转换
plt.suptitle('FOREX Correlations Heat Map', fontsize=15, fontweight='bold')
plt.show()
我们可以从上⾯的热图中看到 GBPUSD 与 GBPJPY 之间的良好相关性。然后我们可以通过导⼊ statsmodels 函数库来测试协整:
# 导⼊ statsmodels 进⾏协整检验
import statsmodels
from statsmodels.tsa.stattools import coint
x = d['GBPUSD']
y = d['GBPJPY']
x = (x-min(x))/(max(x)-min(x))
y = (y-min(y))/(max(y)-min(y))
score = coint(x, y)
print('t-statistic: ', score[0], ' p-value: ', score[1])
两个货币对之间的关系可以显⽰为 Z 分值:
# 绘制 z-分值变换
diff_series = (x - y)
zscore = (diff_series - an()) / diff_series.std()
plt.plot(zscore)
plt.axhline(2.0, color='red', linestyle='--')
plt.axhline(-2.0, color='green', linestyle='--')
plt.show()

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。