forked from airat77786/MQL5Book
195 lines
6.4 KiB
MQL5
195 lines
6.4 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| CalendarMonitor.mq5 |
| |||
//| Copyright (c) 2022, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Copyright (c) 2022, MetaQuotes Ltd."
| |||
#property description "Output a table with selected calendar events."
| |||
#property indicator_chart_window
| |||
#property indicator_buffers 0
| |||
#property indicator_plots 0
| |||
| |||
// #define LOGGING
| |||
#include "..\..\Include\CalendarFilter.mqh"
| |||
#include "..\..\Include\Tableau.mqh"
| |||
#include "..\..\Include\AutoPtr.mqh"
| |||
#include "..\..\Include\StringUtils.mqh"
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| I N P U T S |
| |||
//+------------------------------------------------------------------+
| |||
input group "General filters";
| |||
input string Context; // Context (country - 2 chars, currency - 3 chars, empty - all)
| |||
input ENUM_CALENDAR_SCOPE Scope = SCOPE_WEEK;
| |||
input bool UseChartCurrencies = true;
| |||
| |||
input group "Optional filters";
| |||
input ENUM_CALENDAR_EVENT_TYPE_EXT Type = TYPE_ANY;
| |||
input ENUM_CALENDAR_EVENT_SECTOR_EXT Sector = SECTOR_ANY;
| |||
input ENUM_CALENDAR_EVENT_IMPORTANCE_EXT Importance = IMPORTANCE_MODERATE; // Importance (at least)
| |||
input string Text;
| |||
input ENUM_CALENDAR_HAS_VALUE HasActual = HAS_ANY;
| |||
input ENUM_CALENDAR_HAS_VALUE HasForecast = HAS_ANY;
| |||
input ENUM_CALENDAR_HAS_VALUE HasPrevious = HAS_ANY;
| |||
input ENUM_CALENDAR_HAS_VALUE HasRevised = HAS_ANY;
| |||
input int Limit = 30;
| |||
| |||
input group "Rendering settings";
| |||
input ENUM_BASE_CORNER Corner = CORNER_RIGHT_LOWER;
| |||
input int Margins = 8;
| |||
input int FontSize = 8;
| |||
input string FontName = "Consolas";
| |||
input color BackgroundColor = clrSilver;
| |||
input uchar BackgroundTransparency = 128; // BackgroundTransparency (255 - opaque, 0 - glassy)
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| G L O B A L S |
| |||
//+------------------------------------------------------------------+
| |||
CalendarFilter f(Context);
| |||
AutoPtr<Tableau> t;
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator initialization function |
| |||
//+------------------------------------------------------------------+
| |||
int OnInit()
| |||
{
| |||
if(!f.isLoaded()) return INIT_FAILED;
| |||
| |||
if(UseChartCurrencies)
| |||
{
| |||
const string base = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_BASE);
| |||
const string profit = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT);
| |||
f.let(base);
| |||
if(base != profit)
| |||
{
| |||
f.let(profit);
| |||
}
| |||
}
| |||
| |||
if(Type != TYPE_ANY)
| |||
{
| |||
f.let((ENUM_CALENDAR_EVENT_TYPE)Type);
| |||
}
| |||
| |||
if(Sector != SECTOR_ANY)
| |||
{
| |||
f.let((ENUM_CALENDAR_EVENT_SECTOR)Sector);
| |||
}
| |||
| |||
if(Importance != IMPORTANCE_ANY)
| |||
{
| |||
f.let((ENUM_CALENDAR_EVENT_IMPORTANCE)(Importance - 1), GREATER);
| |||
}
| |||
| |||
if(StringLen(Text))
| |||
{
| |||
f.let(Text);
| |||
}
| |||
| |||
if(HasActual != HAS_ANY)
| |||
{
| |||
f.let(LONG_MIN, CALENDAR_PROPERTY_RECORD_ACTUAL, HasActual == HAS_SET ? NOT_EQUAL : EQUAL);
| |||
}
| |||
| |||
if(HasPrevious != HAS_ANY)
| |||
{
| |||
f.let(LONG_MIN, CALENDAR_PROPERTY_RECORD_PREVIOUS, HasPrevious == HAS_SET ? NOT_EQUAL : EQUAL);
| |||
}
| |||
| |||
if(HasRevised != HAS_ANY)
| |||
{
| |||
f.let(LONG_MIN, CALENDAR_PROPERTY_RECORD_REVISED, HasRevised == HAS_SET ? NOT_EQUAL : EQUAL);
| |||
}
| |||
| |||
if(HasForecast != HAS_ANY)
| |||
{
| |||
f.let(LONG_MIN, CALENDAR_PROPERTY_RECORD_FORECAST, HasForecast == HAS_SET ? NOT_EQUAL : EQUAL);
| |||
}
| |||
| |||
EventSetTimer(1);
| |||
| |||
return INIT_SUCCEEDED;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Timer event handler (main processing of calendar goes here) |
| |||
//+------------------------------------------------------------------+
| |||
void OnTimer()
| |||
{
| |||
static const ENUM_CALENDAR_PROPERTY props[] =
| |||
{
| |||
CALENDAR_PROPERTY_RECORD_TIME,
| |||
CALENDAR_PROPERTY_COUNTRY_CURRENCY,
| |||
CALENDAR_PROPERTY_EVENT_NAME,
| |||
CALENDAR_PROPERTY_EVENT_IMPORTANCE,
| |||
CALENDAR_PROPERTY_RECORD_ACTUAL,
| |||
CALENDAR_PROPERTY_RECORD_FORECAST,
| |||
CALENDAR_PROPERTY_RECORD_PREVISED,
| |||
CALENDAR_PROPERTY_RECORD_IMPACT,
| |||
CALENDAR_PROPERTY_EVENT_SECTOR,
| |||
};
| |||
static const int p = ArraySize(props);
| |||
| |||
MqlCalendarValue records[];
| |||
| |||
f.let(TimeTradeServer() - Scope, TimeTradeServer() + Scope);
| |||
| |||
const ulong trackID = f.getChangeID();
| |||
if(trackID) // already has a state, try to detect changes
| |||
{
| |||
if(f.update(records)) // find changes that match filters
| |||
{
| |||
// notify user about new changes
| |||
string result[];
| |||
f.format(records, props, result);
| |||
for(int i = 0; i < ArraySize(result) / p; ++i)
| |||
{
| |||
Alert(SubArrayCombine(result, " | ", i * p, p));
| |||
}
| |||
// fall through to the table redraw
| |||
}
| |||
else if(trackID == f.getChangeID())
| |||
{
| |||
return; // no changes in the calendar
| |||
}
| |||
}
| |||
| |||
// request complete set of events according to filters
| |||
f.select(records, true, Limit);
| |||
| |||
// rebuild the table displayed on chart
| |||
string result[];
| |||
f.format(records, props, result, true, true);
| |||
| |||
/*
| |||
// on-chart table copy in the log
| |||
for(int i = 0; i < ArraySize(result) / p; ++i)
| |||
{
| |||
Print(SubArrayCombine(result, " | ", i * p, p));
| |||
}
| |||
*/
| |||
| |||
if(t[] == NULL || t[].getRows() != ArraySize(records) + 1)
| |||
{
| |||
t = new Tableau("CALT", ArraySize(records) + 1, p,
| |||
TBL_CELL_HEIGHT_AUTO, TBL_CELL_WIDTH_AUTO,
| |||
Corner, Margins, FontSize, FontName, FontName + " Bold",
| |||
TBL_FLAG_ROW_0_HEADER,
| |||
BackgroundColor, BackgroundTransparency);
| |||
}
| |||
const string hints[] = {};
| |||
t[].fill(result, hints);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Custom indicator iteration function (dummy here) |
| |||
//+------------------------------------------------------------------+
| |||
int OnCalculate(const int rates_total,
| |||
const int prev_calculated,
| |||
const int begin,
| |||
const double &price[])
| |||
{
| |||
return rates_total;
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
|