2026-02-15 05:13:55 +00:00
|
|
|
#ifndef NEWS_ENGINE_MQH
|
|
|
|
|
#define NEWS_ENGINE_MQH
|
|
|
|
|
|
|
|
|
|
string g_symbol_base = "";
|
|
|
|
|
string g_symbol_quote = "";
|
|
|
|
|
|
|
|
|
|
double NewsValueToDouble(const long v)
|
|
|
|
|
{
|
|
|
|
|
return ((double)v) / 1000000.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitNewsEngine()
|
|
|
|
|
{
|
2026-02-17 23:21:13 -06:00
|
|
|
string s = _Symbol;
|
|
|
|
|
StringToUpper(s);
|
2026-02-15 05:13:55 +00:00
|
|
|
g_symbol_base = StringSubstr(s, 0, 3);
|
|
|
|
|
g_symbol_quote = StringSubstr(s, 3, 3);
|
|
|
|
|
|
|
|
|
|
News_Bias_Direction = 0;
|
|
|
|
|
News_Bias_Strength = 0.0;
|
|
|
|
|
News_Trade_Block_Active = false;
|
|
|
|
|
News_Last_Headline = "";
|
|
|
|
|
News_Last_Update = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int CurrencyImpactSign(const string ccy)
|
|
|
|
|
{
|
|
|
|
|
if(ccy == g_symbol_base) return 1;
|
|
|
|
|
if(ccy == g_symbol_quote) return -1;
|
|
|
|
|
if(ccy == "USD" && (g_symbol_base == "XAU" || g_symbol_base == "XAG" || g_symbol_base == "BTC" || g_symbol_base == "ETH"))
|
|
|
|
|
return -1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UpdateNewsBiasFromCalendar()
|
|
|
|
|
{
|
|
|
|
|
if(!Use_News_Filter)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
datetime now = TimeTradeServer();
|
|
|
|
|
datetime from = now - (News_Lookback_Minutes * 60);
|
|
|
|
|
|
|
|
|
|
ulong last_id = 0;
|
|
|
|
|
MqlCalendarValue vals[];
|
|
|
|
|
ArrayResize(vals, 0);
|
|
|
|
|
|
|
|
|
|
int n = CalendarValueLast(last_id, vals, "", "");
|
|
|
|
|
if(n <= 0)
|
|
|
|
|
{
|
|
|
|
|
News_Last_Update = now;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double score = 0.0;
|
|
|
|
|
bool high_impact_near = false;
|
|
|
|
|
string last_headline = "";
|
|
|
|
|
|
|
|
|
|
for(int i = 0; i < n; ++i)
|
|
|
|
|
{
|
|
|
|
|
if(vals[i].time < from)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
MqlCalendarEvent evt;
|
|
|
|
|
if(!CalendarEventById(vals[i].event_id, evt))
|
|
|
|
|
continue;
|
|
|
|
|
|
2026-02-17 23:21:13 -06:00
|
|
|
MqlCalendarCountry country;
|
|
|
|
|
if(!CalendarCountryById(evt.country_id, country))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
int sign = CurrencyImpactSign(country.currency);
|
2026-02-15 05:13:55 +00:00
|
|
|
if(sign == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
int importance = (int)evt.importance;
|
|
|
|
|
double imp_weight = 1.0;
|
|
|
|
|
if(importance >= 2) imp_weight = 2.0;
|
|
|
|
|
if(importance >= 3) imp_weight = 3.0;
|
|
|
|
|
|
|
|
|
|
double actual = NewsValueToDouble(vals[i].actual_value);
|
|
|
|
|
double forecast = NewsValueToDouble(vals[i].forecast_value);
|
|
|
|
|
double previous = NewsValueToDouble(vals[i].prev_value);
|
|
|
|
|
|
|
|
|
|
double surprise = actual - forecast;
|
|
|
|
|
if(MathAbs(surprise) < 0.000001)
|
|
|
|
|
surprise = actual - previous;
|
|
|
|
|
|
|
|
|
|
if(MathAbs(surprise) < 0.000001)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
double ev_score = surprise * imp_weight * sign;
|
|
|
|
|
score += ev_score;
|
|
|
|
|
|
|
|
|
|
if(importance >= 3 && MathAbs(ev_score) > 0.0)
|
|
|
|
|
{
|
|
|
|
|
if(MathAbs((double)(vals[i].time - now)) <= (double)(News_HighImpact_Block_Minutes * 60))
|
|
|
|
|
high_impact_near = true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 23:21:13 -06:00
|
|
|
last_headline = country.currency + " " + evt.name;
|
2026-02-15 05:13:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(score > 0.0) News_Bias_Direction = 1;
|
|
|
|
|
else if(score < 0.0) News_Bias_Direction = -1;
|
|
|
|
|
else News_Bias_Direction = 0;
|
|
|
|
|
|
|
|
|
|
News_Bias_Strength = MathMin(100.0, MathAbs(score) * 10.0);
|
|
|
|
|
News_Trade_Block_Active = high_impact_near;
|
|
|
|
|
if(last_headline != "") News_Last_Headline = last_headline;
|
|
|
|
|
News_Last_Update = now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildNewsReport()
|
|
|
|
|
{
|
|
|
|
|
string dir = "NEUTRAL";
|
|
|
|
|
if(News_Bias_Direction > 0) dir = "BULL";
|
|
|
|
|
if(News_Bias_Direction < 0) dir = "BEAR";
|
|
|
|
|
|
|
|
|
|
News_Bias_Report = "NEWS " + dir +
|
|
|
|
|
" | strength=" + DoubleToString(News_Bias_Strength, 1) +
|
|
|
|
|
" | block=" + (News_Trade_Block_Active ? "YES" : "NO") +
|
|
|
|
|
" | " + News_Last_Headline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UpdateNewsEngine()
|
|
|
|
|
{
|
|
|
|
|
UpdateNewsBiasFromCalendar();
|
|
|
|
|
BuildNewsReport();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|