使用 ZeroMQ Push/Pull 模式将非常长的字符串从 MetaTrader 4 发送到 Python 后端
Sending very long strings from MetaTrader 4 to Python backend using ZeroMQ Push/Pull Pattern
我有一个非常奇怪的问题,与 MetaTrader 4 和 python 后端之间的 ZeroMQ 消息传递有关。
下面显示的代码创建了三个字符串,它们应该被转发到 ZeroMQ PUSH
套接字。但是,它仅通过套接字发送 live_trades
字符串。 account_info
和 historical_trades
字符串均未发送。
调试的时候怪怪的只增加了:
- 当我打印
historical_trades
字符串时,它显示在 MT4 专家日志中,但没有显示在 MT4 日志编辑器中
- 当我在
pushSocket.send(StringFormat("%s", historical_trades, true));
之前或之后添加 Print( historical_trades )
时,它会发送字符串。
我实际排除的可能问题:
PUSH
套接字太慢:我将计时器减少到 10 秒或更多,结果相同
- MT4 本身创建字符串的速度太慢:它可以正确打印它们,所以速度足够快
- ZeroMQ
SNDHWM
( HighWaterMark ) 立即阻止 EA/socket 发送多个字符串:已经将其增加到 100,这应该绰绰有余
任何其他我无法通过调试验证的想法:
- MT4
Print()
函数在幕后做了一些其他的事情,使 EA 能够发送字符串?
- 也许 MT4 中存在最大字符串大小限制,这会阻止字符串创建循环(我的字符串长度约为 35.000 个字符)。但是为什么当我在
onTimer()
函数中只 Print()
一次字符串时它会起作用?...
- 是否有可能在周末无法访问帐户相关信息?
或者我的代码可能有问题..
非常感谢任何想法!
int OnInit()
{
//---
EventSetTimer(2); // Set Second Timer as push intervall
context.setBlocky(false);
// Send data to PULL_PORT that consumer is listening to.
Print("Connecting MT4 Dashex Feeder to Dashboard on Port " + IntegerToString(PUSH_PORT) + "..");
pushSocket.connect(StringFormat("%s://%s:%d", ZEROMQ_PROTOCOL, HOSTNAME, PUSH_PORT));
pushSocket.setSendHighWaterMark(100);
pushSocket.setLinger(0);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
Print("Disconnecting MT4 Dashex Feeder on Port " + IntegerToString(PUSH_PORT) + "..");
pushSocket.disconnect(StringFormat("%s://%s:%d", ZEROMQ_PROTOCOL, HOSTNAME, PUSH_PORT));
// Shutdown ZeroMQ Context
context.shutdown();
context.destroy(0);
EventKillTimer();
}
//---
//+------------------------------------------------------------------+
//| Expert timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
/*
1.) Account information
*/
string account_info = "";
account_info = account_info +
"account_info|" +
version + "|" +
DID + "|" +
IntegerToString(AccountNumber()) + "|" +
AccountInfoString(ACCOUNT_COMPANY) + "|" +
IntegerToString(AccountInfoInteger(ACCOUNT_LEVERAGE)) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_PROFIT),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_FREE),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL),2) + "|" +
AccountInfoString(ACCOUNT_CURRENCY) + "|" +
IntegerToString(IsDemo()) + "|" +
pushSocket.send(StringFormat("%s", account_info, true));
Print("Pushing Account Information To Dashex.Finance Dashboard For Account No. " + IntegerToString(AccountNumber()));
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
/*
2.) Pending and running trades
*/
int live_orders = OrdersTotal();
string live_trades = "";
for(int i=live_orders; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS)==false) continue;
live_trades = live_trades +
"live_trades|" +
version + "|" +
DID + "|" +
IntegerToString(AccountNumber()) + "|" +
IntegerToString(OrderTicket()) + "|" +
TimeToString(OrderOpenTime(), TIME_DATE|TIME_SECONDS) + "|" +
TimeToString(OrderCloseTime(), TIME_DATE|TIME_SECONDS) + "|" +
IntegerToString(OrderType()) + "|" +
DoubleToString(OrderLots(),2) + "|" +
OrderSymbol() + "|" +
DoubleToString(OrderOpenPrice(),5) + "|" +
DoubleToString(OrderClosePrice(),5) + "|" +
DoubleToString(OrderStopLoss(),5) + "|" +
DoubleToString(OrderTakeProfit(),5) + "|" +
DoubleToString(OrderCommission(),2) + "|" +
DoubleToString(OrderSwap(),2) + "|" +
DoubleToString(OrderProfit(),2) + "|" +
"<" + OrderComment() + ">|";
}
pushSocket.send(StringFormat("%s", live_trades, true));
Print("Pushing Live Trades To Dashex.Finance Dashboard For Account No. " + IntegerToString(AccountNumber()));
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
/*
3.) History Trades
*/
int hstTotal = OrdersHistoryTotal();
string historical_trades = "";
Print(hstTotal);
for(int i=hstTotal; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) continue;
historical_trades = historical_trades +
"historical_trades|" +
version + "|" +
DID + "|" +
IntegerToString(AccountNumber()) + "|" +
IntegerToString(OrderTicket()) + "|" +
TimeToString(OrderOpenTime(), TIME_DATE|TIME_SECONDS) + "|" +
TimeToString(OrderCloseTime(), TIME_DATE|TIME_SECONDS) + "|" +
IntegerToString(OrderType()) + "|" +
DoubleToString(OrderLots(),2) + "|" +
OrderSymbol() + "|" +
DoubleToString(OrderOpenPrice(),5) + "|" +
DoubleToString(OrderClosePrice(),5) + "|" +
DoubleToString(OrderStopLoss(),5) + "|" +
DoubleToString(OrderTakeProfit(),5) + "|" +
DoubleToString(OrderCommission(),2) + "|" +
DoubleToString(OrderSwap(),2) + "|" +
DoubleToString(OrderProfit(),2) + "|" +
"<" + OrderComment() + ">|";
}
pushSocket.send(StringFormat("%s", historical_trades, true));
Print("Pushing History Trades To Dashex.Finance Dashboard For Account No. " + IntegerToString(AccountNumber()));
Sleep(1);
}
MetaTrader 4 log.editor:
MetaTrader 4 控制台:
Q : Any chance that the account related information is not accessible on weekends?
这有一个简单的证明:做一个 Comment( aStringUnderTEST );
+ 检查所有与账户/经纪人相关的项目。
Q : Maybe there is a maximum string size in MT4 which blocks the string creation loop...?
除了等待 BugFIX 的 MT4-Build-X.Y.Z 发布错误之外,这是非常低概率的假设。
然而它有一个简单的证明:做一个不断增加字符串长度的循环并测试直到处理保持工作的大小。间接证明的大小限制将帮助您追踪根本原因,MT4 不是这里的 SPoF,是吗?
Q : The MT4 Print
function does some other stuff behind the scenes which enables the EA to send the string?
如果要确认或拒绝,应联系 MT4 支持。该软件作为原样产品获得许可,因此如果您试图深入了解其封闭和密封产品内的螺栓和螺母,不要指望会发生任何快速响应或火箭科学。
我有一个非常奇怪的问题,与 MetaTrader 4 和 python 后端之间的 ZeroMQ 消息传递有关。
下面显示的代码创建了三个字符串,它们应该被转发到 ZeroMQ PUSH
套接字。但是,它仅通过套接字发送 live_trades
字符串。 account_info
和 historical_trades
字符串均未发送。
调试的时候怪怪的只增加了:
- 当我打印
historical_trades
字符串时,它显示在 MT4 专家日志中,但没有显示在 MT4 日志编辑器中 - 当我在
pushSocket.send(StringFormat("%s", historical_trades, true));
之前或之后添加Print( historical_trades )
时,它会发送字符串。
我实际排除的可能问题:
PUSH
套接字太慢:我将计时器减少到 10 秒或更多,结果相同- MT4 本身创建字符串的速度太慢:它可以正确打印它们,所以速度足够快
- ZeroMQ
SNDHWM
( HighWaterMark ) 立即阻止 EA/socket 发送多个字符串:已经将其增加到 100,这应该绰绰有余
任何其他我无法通过调试验证的想法:
- MT4
Print()
函数在幕后做了一些其他的事情,使 EA 能够发送字符串? - 也许 MT4 中存在最大字符串大小限制,这会阻止字符串创建循环(我的字符串长度约为 35.000 个字符)。但是为什么当我在
onTimer()
函数中只Print()
一次字符串时它会起作用?... - 是否有可能在周末无法访问帐户相关信息?
或者我的代码可能有问题..
非常感谢任何想法!
int OnInit()
{
//---
EventSetTimer(2); // Set Second Timer as push intervall
context.setBlocky(false);
// Send data to PULL_PORT that consumer is listening to.
Print("Connecting MT4 Dashex Feeder to Dashboard on Port " + IntegerToString(PUSH_PORT) + "..");
pushSocket.connect(StringFormat("%s://%s:%d", ZEROMQ_PROTOCOL, HOSTNAME, PUSH_PORT));
pushSocket.setSendHighWaterMark(100);
pushSocket.setLinger(0);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
Print("Disconnecting MT4 Dashex Feeder on Port " + IntegerToString(PUSH_PORT) + "..");
pushSocket.disconnect(StringFormat("%s://%s:%d", ZEROMQ_PROTOCOL, HOSTNAME, PUSH_PORT));
// Shutdown ZeroMQ Context
context.shutdown();
context.destroy(0);
EventKillTimer();
}
//---
//+------------------------------------------------------------------+
//| Expert timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
/*
1.) Account information
*/
string account_info = "";
account_info = account_info +
"account_info|" +
version + "|" +
DID + "|" +
IntegerToString(AccountNumber()) + "|" +
AccountInfoString(ACCOUNT_COMPANY) + "|" +
IntegerToString(AccountInfoInteger(ACCOUNT_LEVERAGE)) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_PROFIT),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_FREE),2) + "|" +
DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL),2) + "|" +
AccountInfoString(ACCOUNT_CURRENCY) + "|" +
IntegerToString(IsDemo()) + "|" +
pushSocket.send(StringFormat("%s", account_info, true));
Print("Pushing Account Information To Dashex.Finance Dashboard For Account No. " + IntegerToString(AccountNumber()));
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
/*
2.) Pending and running trades
*/
int live_orders = OrdersTotal();
string live_trades = "";
for(int i=live_orders; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS)==false) continue;
live_trades = live_trades +
"live_trades|" +
version + "|" +
DID + "|" +
IntegerToString(AccountNumber()) + "|" +
IntegerToString(OrderTicket()) + "|" +
TimeToString(OrderOpenTime(), TIME_DATE|TIME_SECONDS) + "|" +
TimeToString(OrderCloseTime(), TIME_DATE|TIME_SECONDS) + "|" +
IntegerToString(OrderType()) + "|" +
DoubleToString(OrderLots(),2) + "|" +
OrderSymbol() + "|" +
DoubleToString(OrderOpenPrice(),5) + "|" +
DoubleToString(OrderClosePrice(),5) + "|" +
DoubleToString(OrderStopLoss(),5) + "|" +
DoubleToString(OrderTakeProfit(),5) + "|" +
DoubleToString(OrderCommission(),2) + "|" +
DoubleToString(OrderSwap(),2) + "|" +
DoubleToString(OrderProfit(),2) + "|" +
"<" + OrderComment() + ">|";
}
pushSocket.send(StringFormat("%s", live_trades, true));
Print("Pushing Live Trades To Dashex.Finance Dashboard For Account No. " + IntegerToString(AccountNumber()));
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
/*
3.) History Trades
*/
int hstTotal = OrdersHistoryTotal();
string historical_trades = "";
Print(hstTotal);
for(int i=hstTotal; i >= 0; i--)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) continue;
historical_trades = historical_trades +
"historical_trades|" +
version + "|" +
DID + "|" +
IntegerToString(AccountNumber()) + "|" +
IntegerToString(OrderTicket()) + "|" +
TimeToString(OrderOpenTime(), TIME_DATE|TIME_SECONDS) + "|" +
TimeToString(OrderCloseTime(), TIME_DATE|TIME_SECONDS) + "|" +
IntegerToString(OrderType()) + "|" +
DoubleToString(OrderLots(),2) + "|" +
OrderSymbol() + "|" +
DoubleToString(OrderOpenPrice(),5) + "|" +
DoubleToString(OrderClosePrice(),5) + "|" +
DoubleToString(OrderStopLoss(),5) + "|" +
DoubleToString(OrderTakeProfit(),5) + "|" +
DoubleToString(OrderCommission(),2) + "|" +
DoubleToString(OrderSwap(),2) + "|" +
DoubleToString(OrderProfit(),2) + "|" +
"<" + OrderComment() + ">|";
}
pushSocket.send(StringFormat("%s", historical_trades, true));
Print("Pushing History Trades To Dashex.Finance Dashboard For Account No. " + IntegerToString(AccountNumber()));
Sleep(1);
}
MetaTrader 4 log.editor:
MetaTrader 4 控制台:
Q : Any chance that the account related information is not accessible on weekends?
这有一个简单的证明:做一个 Comment( aStringUnderTEST );
+ 检查所有与账户/经纪人相关的项目。
Q : Maybe there is a maximum string size in MT4 which blocks the string creation loop...?
除了等待 BugFIX 的 MT4-Build-X.Y.Z 发布错误之外,这是非常低概率的假设。
然而它有一个简单的证明:做一个不断增加字符串长度的循环并测试直到处理保持工作的大小。间接证明的大小限制将帮助您追踪根本原因,MT4 不是这里的 SPoF,是吗?
Q : The MT4
如果要确认或拒绝,应联系 MT4 支持。该软件作为原样产品获得许可,因此如果您试图深入了解其封闭和密封产品内的螺栓和螺母,不要指望会发生任何快速响应或火箭科学。