forked from rosh/MQL5Book
139 lines
5.2 KiB
MQL5
139 lines
5.2 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| MarketBookVolumeAlert.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 symbol and monitor changes with large volumes."
| |||
| |||
#property indicator_chart_window
| |||
#property indicator_plots 0
| |||
| |||
#define N_LINES 25 // number of lines in multicomment
| |||
#include "..\..\Include\Comments.mqh"
| |||
| |||
input string WorkSymbol = ""; // WorkSymbol (if empty, use current chart symbol)
| |||
input bool CountVolumeInLots = false;
| |||
input double VolumeLimit = 0;
| |||
| |||
const string _WorkSymbol = StringLen(WorkSymbol) == 0 ? _Symbol : WorkSymbol;
| |||
double contract;
| |||
int digits;
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator initialization function |
| |||
//+------------------------------------------------------------------+
| |||
void OnInit()
| |||
{
| |||
MarketBookAdd(_WorkSymbol);
| |||
contract = SymbolInfoDouble(_WorkSymbol, SYMBOL_TRADE_CONTRACT_SIZE);
| |||
digits = (int)MathRound(MathLog10(contract));
| |||
Print(SymbolInfoDouble(_WorkSymbol, SYMBOL_SESSION_BUY_ORDERS_VOLUME));
| |||
Print(SymbolInfoDouble(_WorkSymbol, SYMBOL_SESSION_SELL_ORDERS_VOLUME));
| |||
}
| |||
| |||
#define VOL(V) (CountVolumeInLots ? V / contract : V)
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Market book notification handler |
| |||
//+------------------------------------------------------------------+
| |||
void OnBookEvent(const string &symbol)
| |||
{
| |||
if(symbol != _WorkSymbol) return;
| |||
| |||
static MqlBookInfo mbp[]; // previous table
| |||
MqlBookInfo mbi[];
| |||
if(MarketBookGet(symbol, mbi)) // retrieve current book
| |||
{
| |||
if(ArraySize(mbp) == 0)
| |||
{
| |||
ArrayCopy(mbp, mbi);
| |||
return;
| |||
}
| |||
| |||
int j = 0;
| |||
for(int i = 0; i < ArraySize(mbi); ++i)
| |||
{
| |||
bool found = false;
| |||
for( ; j < ArraySize(mbp); ++j)
| |||
{
| |||
if(MathAbs(mbp[j].price - mbi[i].price) < DBL_EPSILON * mbi[i].price) // mbp[j].price == mbi[i].price
| |||
{
| |||
if(VOL(mbi[i].volume_real - mbp[j].volume_real) >= VolumeLimit)
| |||
{
| |||
NotifyVolumeChange("Enlarged", mbp[j].price, VOL(mbp[j].volume_real), VOL(mbi[i].volume_real));
| |||
}
| |||
else
| |||
if(VOL(mbp[j].volume_real - mbi[i].volume_real) >= VolumeLimit)
| |||
{
| |||
NotifyVolumeChange("Reduced", mbp[j].price, VOL(mbp[j].volume_real), VOL(mbi[i].volume_real));
| |||
}
| |||
found = true;
| |||
++j;
| |||
break;
| |||
}
| |||
else if(mbp[j].price > mbi[i].price)
| |||
{
| |||
if(VOL(mbp[j].volume_real) >= VolumeLimit)
| |||
{
| |||
NotifyVolumeChange("Removed", mbp[j].price, VOL(mbp[j].volume_real), 0.0);
| |||
}
| |||
// keep loop incrementing ++j to lower prices
| |||
}
| |||
else // mbp[j].price < mbi[i].price
| |||
{
| |||
break;
| |||
}
| |||
}
| |||
if(!found) // unique price
| |||
{
| |||
if(VOL(mbi[i].volume_real) >= VolumeLimit)
| |||
{
| |||
NotifyVolumeChange("Added", mbi[i].price, 0.0, VOL(mbi[i].volume_real));
| |||
}
| |||
}
| |||
}
| |||
| |||
if(ArrayCopy(mbp, mbi) <= 0)
| |||
{
| |||
Print("ArrayCopy failed:", _LastError);
| |||
}
| |||
if(ArrayResize(mbp, ArraySize(mbi)) <= 0) // shrink if required
| |||
{
| |||
Print("ArrayResize failed:", _LastError);
| |||
}
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| 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)
| |||
{
| |||
MarketBookRelease(_WorkSymbol);
| |||
Comment("");
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Multisymbol tick custom event |
| |||
//+------------------------------------------------------------------+
| |||
void NotifyVolumeChange(const string action, const double price,
| |||
const double previous, const double volume)
| |||
{
| |||
const string message = StringFormat("%s: %s %s -> %s",
| |||
action,
| |||
DoubleToString(price, (int)SymbolInfoInteger(_WorkSymbol, SYMBOL_DIGITS)),
| |||
DoubleToString(previous, digits),
| |||
DoubleToString(volume, digits));
| |||
ChronoComment(message);
| |||
}
| |||
//+------------------------------------------------------------------+
|