forked from airat77786/MQL5Book
144 lines
7.2 KiB
MQL5
144 lines
7.2 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| wschat.mq5 |
| |||
//| Copyright 2022, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
| |||
#include "..\..\..\Include\ws\wsclient.mqh"
| |||
#include <VirtualKeys.mqh>
| |||
| |||
input string Server = "ws://localhost:9000/";
| |||
input bool TryCompression = false;
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom client class to handle WebSocket events |
| |||
//+------------------------------------------------------------------+
| |||
class MyWebSocket: public WebSocketClient<Hybi>
| |||
{
| |||
public:
| |||
MyWebSocket(const string address, const bool compress = false):
| |||
WebSocketClient(address, compress) { }
| |||
| |||
/* void onConnected() override { } */
| |||
| |||
void onDisconnect() override
| |||
{
| |||
// can do something more and call (or not) inherited code
| |||
WebSocketClient<Hybi>::onDisconnect();
| |||
}
| |||
| |||
void onMessage(IWebSocketMessage *msg) override
| |||
{
| |||
// TODO: we can drop off echoes of our own messages
| |||
Alert(msg.getString());
| |||
delete msg;
| |||
}
| |||
};
| |||
| |||
MyWebSocket wss(Server, TryCompression);
| |||
string message = "";
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Initialization handler |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit()
| |||
{
| |||
Print("\n");
| |||
ChartSetInteger(0, CHART_QUICK_NAVIGATION, false);
| |||
EventSetTimer(1);
| |||
wss.setTimeOut(1000);
| |||
Print("Opening...");
| |||
return wss.open() ? INIT_SUCCEEDED : INIT_FAILED;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Chart events handler |
| |||
//+------------------------------------------------------------------+
| |||
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
| |||
{
| |||
if(id == CHARTEVENT_KEYDOWN)
| |||
{
| |||
if(lparam == VK_RETURN)
| |||
{
| |||
const static string longmessage =
| |||
"For the mql5-program to operate, it must be compiled (Compile button or F7 key). Compilation should "
| |||
"pass without errors (some warnings are possible; they should be analyzed). At this process, an "
| |||
"executable file with the same name and with EX5 extension must be created in the corresponding "
| |||
"directory, terminal_dir\\MQL5\\Experts, terminal_dir\\MQL5\\indicators or terminal_dir\\MQL5\\scripts. "
| |||
"This file can be run. "
| |||
"Operating features of MQL5 programs are described in the following sections: "
| |||
"- Program running – order of calling predefined event-handlers. "
| |||
"- Testing trading strategies – operating features of MQL5 programs in the Strategy Tester. "
| |||
"- Client terminal events – description of events, which can be processed in programs. "
| |||
"- Call of imported functions – description order, allowed parameters, search details and call agreement "
| |||
"for imported functions. "
| |||
"· Runtime errors – getting information about runtime and critical errors. "
| |||
"Expert Advisors, custom indicators and scripts are attached to one of opened charts by Drag'n'Drop "
| |||
"method from the Navigator window. "
| |||
"For an expert Advisor to stop operating, it should be removed from a chart. To do it select 'Expert' "
| |||
"'list' in chart context menu, then select an Expert Advisor from list and click 'Remove' button. "
| |||
"Operation of Expert Advisors is also affected by the state of the 'AutoTrading' button. "
| |||
"In order to stop a custom indicator, it should be removed from a chart. "
| |||
"Custom indicators and Expert Advisors work until they are explicitly removed from a chart; "
| |||
"information about attached Expert Advisors and Indicators is saved between client terminal sessions. "
| |||
"Scripts are executed once and are deleted automatically upon operation completion or change of the "
| |||
"current chart state, or upon client terminal shutdown. After the restart of the client terminal scripts "
| |||
"are not started, because the information about them is not saved. "
| |||
"Maximum one Expert Advisor, one script and unlimited number of indicators can operate in one chart. "
| |||
"Services do not require to be bound to a chart to work and are designed to perform auxiliary functions. "
| |||
"For example, in a service, you can create a custom symbol, open its chart, receive data for it in an "
| |||
"endless loop using the network functions and constantly update it. "
| |||
"Each script, each service and each Expert Advisor runs in its own separate thread. All indicators "
| |||
"calculated on one symbol, even if they are attached to different charts, work in the same thread. "
| |||
"Thus, all indicators on one symbol share the resources of one thread. "
| |||
"All other actions associated with a symbol, like processing of ticks and history synchronization, are "
| |||
"also consistently performed in the same thread with indicators. This means that if an infinite action is "
| |||
"performed in an indicator, all other events associated with its symbol will never be performed. "
| |||
"When running an Expert Advisor, make sure that it has an actual trading environment and can access "
| |||
"the history of the required symbol and period, and synchronize data between the terminal and the "
| |||
"server. For all these procedures, the terminal provides a start delay of no more than 5 seconds, after "
| |||
"which the Expert Advisor will be started with available data. Therefore, in case there is no connection "
| |||
"to the server, this may lead to a delay in the start of an Expert Advisor.";
| |||
if(message == "long") wss.send(longmessage);
| |||
else if(message == "bye") wss.close();
| |||
else wss.send(message);
| |||
message = "";
| |||
}
| |||
else if(lparam == VK_BACK)
| |||
{
| |||
StringSetLength(message, StringLen(message) - 1);
| |||
}
| |||
else
| |||
{
| |||
ResetLastError();
| |||
const short c = TranslateKey((int)lparam);
| |||
if(_LastError == 0)
| |||
{
| |||
message += ShortToString(c);
| |||
}
| |||
}
| |||
Comment(message);
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Timer events handler |
| |||
//+------------------------------------------------------------------+
| |||
void OnTimer()
| |||
{
| |||
wss.checkMessages(false); // in timer use non-blocking check
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Finalization handler |
| |||
//+------------------------------------------------------------------+
| |||
void OnDeinit(const int)
| |||
{
| |||
if(wss.isConnected())
| |||
{
| |||
Print("Closing...");
| |||
wss.close();
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
|