forked from rosh/MQL5Book
105 lines
3.9 KiB
MQL5
105 lines
3.9 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| MarketBookQuasiTicks.mq5 |
| |
//| Copyright 2022, MetaQuotes Ltd. |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "2022, MetaQuotes Ltd."
| |
#property link "https://www.mql5.com"
| |
#property description "Subscribe to market books for specified list of symbols."
| |
#property description "Extract Ask/Bid prices from received books and produce quasi-tick events for multiple symbols."
| |
| |
#property indicator_chart_window
| |
#property indicator_plots 0
| |
| |
#define N_LINES 25 // number of lines in multicomment
| |
#include "..\..\Include\Comments.mqh"
| |
| |
input string SymbolList = "EURUSD,GBPUSD,XAUUSD,USDJPY"; // SymbolList (comma,separated,list)
| |
| |
const string WorkSymbols = StringLen(SymbolList) == 0 ? _Symbol : SymbolList;
| |
string symbols[];
| |
| |
//+------------------------------------------------------------------+
| |
//| Custom indicator initialization function |
| |
//+------------------------------------------------------------------+
| |
void OnInit()
| |
{
| |
const int n = StringSplit(WorkSymbols, ',', symbols);
| |
for(int i = 0; i < n; ++i)
| |
{
| |
if(!MarketBookAdd(symbols[i]))
| |
{
| |
PrintFormat("MarketBookAdd(%s) failed with code %d", symbols[i], _LastError);
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Market book notification handler |
| |
//+------------------------------------------------------------------+
| |
void OnBookEvent(const string &symbol)
| |
{
| |
MqlBookInfo mbi[];
| |
if(MarketBookGet(symbol, mbi)) // retrieve current book
| |
{
| |
int half = ArraySize(mbi) / 2; // estimation of the middle slot
| |
bool correct = true;
| |
for(int i = 0; i < ArraySize(mbi); ++i)
| |
{
| |
if(i > 0) // find the middle of the book
| |
{
| |
if(mbi[i - 1].type == BOOK_TYPE_SELL
| |
&& mbi[i].type == BOOK_TYPE_BUY)
| |
{
| |
half = i;
| |
}
| |
| |
if(mbi[i - 1].price <= mbi[i].price)
| |
{
| |
correct = false;
| |
}
| |
}
| |
}
| |
| |
if(correct) // extract best Bid/Ask prices from proper book
| |
{
| |
// mbi[half - 1].price // Ask
| |
// mbi[half].price // Bid
| |
OnSymbolTick(symbol, mbi[half].price);
| |
}
| |
}
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Custom indicator iteration function (dummy) |
| |
//+------------------------------------------------------------------+
| |
int OnCalculate(const int rates_total, const int prev_calculated, const int, const double &price[])
| |
{
| |
return rates_total;
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Finalization handler |
| |
//+------------------------------------------------------------------+
| |
void OnDeinit(const int)
| |
{
| |
for(int i = 0; i < ArraySize(symbols); ++i)
| |
{
| |
if(!MarketBookRelease(symbols[i]))
| |
{
| |
PrintFormat("MarketBookRelease(%s) failed with code %d", symbols[i], _LastError);
| |
}
| |
}
| |
Comment("");
| |
}
| |
| |
//+------------------------------------------------------------------+
| |
//| Multisymbol tick custom event |
| |
//+------------------------------------------------------------------+
| |
void OnSymbolTick(const string &symbol, const double price)
| |
{
| |
const string message = StringFormat("%s %s",
| |
symbol, DoubleToString(price, (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS)));
| |
ChronoComment(message);
| |
}
| |
//+------------------------------------------------------------------+
|