FSBNewsGate_v2.1 by zenoni
0 downloads / 10 views / Created: 23.03.2026Indicator Description
1. Downloader = data source updater for MT4 (EA for MT4).
2. Gate = strategy execution filter on FSB Pro and exported strategies for MT4 (.cs and .mqh files)
It doesn't work without the Downloader component.
See more information and get Downloader EA:
https://forexsb.com/forum/topic/10055/news-filter-solution-for-fsb-pro-and-mt4-working/
Comments
// FSBNewsGate_v2_1.cs
// -----------------------------------------------------------------------------
// LIVE MT4 ONLY news permission gate.
//
// DESIGN INTENT
// - In FSB Pro (C# runtime): always outputs Allow=1.0.
// - Real blocking happens only in exported MT4 .mqh reading offline news-feed.txt.
// - Therefore this indicator has NO backtesting effect inside FSB Pro by design.
// - This is a directionless OpenFilter permission gate.
//
// PARAM INDEX CONTRACT (CS + MQH must match)
// ListParam[0] = News Priority UI (Disabled / High only / High+Medium) [FSB UI source]
// NumParam[0] = Before High (minutes)
// NumParam[1] = After High (minutes)
// NumParam[2] = Before Medium (minutes)
// NumParam[3] = After Medium (minutes)
// NumParam[4] = Tolerance (seconds)
// NumParam[5] = MT4-visible Priority Mode mirror (0 Disabled / 1 High only / 2 High+Medium)
// CheckParam[0]= Continue on error fallback [exported constant / legacy semantics]
//
// NOTES
// - This indicator is a time-based gate, not a bar-series indicator.
// - LTF is disabled because it does not make sense for a real-time calendar gate.
// - FSB runtime always allows by design because the indicator is forward-looking.
// - v2.1 adds an MT4-visible priority mode mirror so MT4 users can switch:
// Disabled / High only / High and Medium.
// -----------------------------------------------------------------------------
using System;
using System.Drawing;
using ForexStrategyBuilder.Infrastructure.Entities;
using ForexStrategyBuilder.Infrastructure.Enums;
using ForexStrategyBuilder.Infrastructure.Interfaces;
namespace ForexStrategyBuilder.Indicators.Custom
{
public class FSBNewsGate_v2_1 : Indicator
{
private enum NewsPriorityMode
{
Disabled = 0,
HighOnly = 1,
HighAndMedium = 2
}
public FSBNewsGate_v2_1()
{
IndicatorName = "FSBNewsGate_v2_1";
PossibleSlots = SlotTypes.OpenFilter;
SeparatedChart = false;
IsDiscreteValues = false;
IsGeneratable = false;
CustomIndicator = true;
IndicatorAuthor = "Custom v2.1";
IndicatorVersion = "2.1";
IndicatorDescription = "Directionless LIVE MT4 news permission gate. FSB runtime always allows; real blocking happens only in exported MT4 using offline news-feed.txt. v2.1 adds MT4-visible priority mode switching.";
}
public override void Initialize(SlotTypes slotType)
{
SlotType = slotType;
IndParam.IndicatorType = TypeOfIndicator.Additional;
IndParam.IsAllowLTF = false;
// ListParam[0] - FSB UI priority mode
IndParam.ListParam[0].Caption = "News priority";
IndParam.ListParam[0].ItemList = new[]
{
"Disabled",
"High only",
"High and Medium"
};
IndParam.ListParam[0].Index = (int)NewsPriorityMode.HighOnly;
IndParam.ListParam[0].Text = IndParam.ListParam[0].ItemList[IndParam.ListParam[0].Index];
IndParam.ListParam[0].Enabled = true;
IndParam.ListParam[0].ToolTip = "Select which news priorities can block entries. v2.1 mirrors this setting into an MT4-visible numeric export parameter.";
// NumParam[0] - Before High (min)
IndParam.NumParam[0].Caption = "Before High (min)";
IndParam.NumParam[0].Value = 2;
IndParam.NumParam[0].Min = 0;
IndParam.NumParam[0].Max = 240;
IndParam.NumParam[0].Point = 0;
IndParam.NumParam[0].Enabled = true;
IndParam.NumParam[0].ToolTip = "Minutes to block BEFORE a high priority news event (LIVE MT4).";
// NumParam[1] - After High (min)
IndParam.NumParam[1].Caption = "After High (min)";
IndParam.NumParam[1].Value = 5;
IndParam.NumParam[1].Min = 0;
IndParam.NumParam[1].Max = 240;
IndParam.NumParam[1].Point = 0;
IndParam.NumParam[1].Enabled = true;
IndParam.NumParam[1].ToolTip = "Minutes to block AFTER a high priority news event (LIVE MT4).";
// NumParam[2] - Before Medium (min)
IndParam.NumParam[2].Caption = "Before Medium (min)";
IndParam.NumParam[2].Value = 2;
IndParam.NumParam[2].Min = 0;
IndParam.NumParam[2].Max = 240;
IndParam.NumParam[2].Point = 0;
IndParam.NumParam[2].Enabled = true;
IndParam.NumParam[2].ToolTip = "Minutes to block BEFORE a medium priority news event (LIVE MT4).";
// NumParam[3] - After Medium (min)
IndParam.NumParam[3].Caption = "After Medium (min)";
IndParam.NumParam[3].Value = 2;
IndParam.NumParam[3].Min = 0;
IndParam.NumParam[3].Max = 240;
IndParam.NumParam[3].Point = 0;
IndParam.NumParam[3].Enabled = true;
IndParam.NumParam[3].ToolTip = "Minutes to block AFTER a medium priority news event (LIVE MT4).";
// NumParam[4] - Tolerance seconds
IndParam.NumParam[4].Caption = "Tolerance (sec)";
IndParam.NumParam[4].Value = 15;
IndParam.NumParam[4].Min = 0;
IndParam.NumParam[4].Max = 60;
IndParam.NumParam[4].Point = 0;
IndParam.NumParam[4].Enabled = true;
IndParam.NumParam[4].ToolTip = "Timing tolerance in seconds around release time (LIVE MT4).";
// NumParam[5] - MT4-visible priority mirror
IndParam.NumParam[5].Caption = "MT4 Priority Mode (0/1/2)";
IndParam.NumParam[5].Value = (int)NewsPriorityMode.HighOnly;
IndParam.NumParam[5].Min = 0;
IndParam.NumParam[5].Max = 2;
IndParam.NumParam[5].Point = 0;
IndParam.NumParam[5].Enabled = true;
IndParam.NumParam[5].ToolTip = "MT4-visible priority mode mirror: 0=Disabled, 1=High only, 2=High and Medium. In FSB Pro this value is auto-synced from the dropdown.";
// CheckParam[0] - fallback fail-open semantics
IndParam.CheckParam[0].Caption = "Continue on error (fallback)";
IndParam.CheckParam[0].Checked = true;
IndParam.CheckParam[0].Enabled = true;
IndParam.CheckParam[0].ToolTip = "Fallback fail-open setting. Exported into MT4 as a fixed strategy setting; not MT4-editable in v2.1.";
}
public override void Calculate(IDataSet dataSet)
{
DataSet = dataSet;
// v2.1: keep MT4-visible numeric mirror synchronized from the FSB dropdown.
int priorityIndex = ClampInt(IndParam.ListParam[0].Index, 0, 2);
SyncPriorityMirror(priorityIndex);
int beforeHigh = ClampInt((int)IndParam.NumParam[0].Value, 0, 240);
int afterHigh = ClampInt((int)IndParam.NumParam[1].Value, 0, 240);
int beforeMed = ClampInt((int)IndParam.NumParam[2].Value, 0, 240);
int afterMed = ClampInt((int)IndParam.NumParam[3].Value, 0, 240);
int tolSec = ClampInt((int)IndParam.NumParam[4].Value, 0, 60);
bool continueFallback = IndParam.CheckParam[0].Checked;
bool keepAlive = continueFallback;
if (priorityIndex == (int)NewsPriorityMode.Disabled)
keepAlive = true;
if (beforeHigh < 0 || afterHigh < 0 || beforeMed < 0 || afterMed < 0 || tolSec < 0)
keepAlive = true;
int firstBar = 0;
Component = new IndicatorComp[2];
Component[0] = new IndicatorComp
{
CompName = "Allow long entry",
DataType = IndComponentType.AllowOpenLong,
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
ShowInDynInfo = true,
Value = new double[Bars]
};
Component[1] = new IndicatorComp
{
CompName = "Allow short entry",
DataType = IndComponentType.AllowOpenShort,
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
ShowInDynInfo = true,
Value = new double[Bars]
};
// Forward-looking LIVE MT4 only:
// In FSB Pro runtime always allow. Real blocking happens only in exported MT4.
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = 1.0;
Component[1].Value[bar] = 1.0;
}
}
public override void SetDescription()
{
int priorityIndex = ClampInt(IndParam.ListParam[0].Index, 0, 2);
SyncPriorityMirror(priorityIndex);
string priorityText = PriorityModeToText(priorityIndex);
string text = string.Format(
"FSBNewsGate_v2_1 directionless LIVE MT4 news permission gate ({0}); FSB runtime always allows; real blocking happens only in exported MT4. v2.1 adds MT4-visible priority mode switching.",
priorityText);
EntryFilterLongDescription = text;
EntryFilterShortDescription = text;
ExitFilterLongDescription = string.Empty;
ExitFilterShortDescription = string.Empty;
}
public override string ToString()
{
int priorityIndex = ClampInt(IndParam.ListParam[0].Index, 0, 2);
SyncPriorityMirror(priorityIndex);
string priorityText = PriorityModeToText(priorityIndex);
return string.Format(
"{0} ({1}, H:{2}/{3} M:{4}/{5}, tol:{6}s, fallback:{7})",
IndicatorName,
priorityText,
(int)IndParam.NumParam[0].Value,
(int)IndParam.NumParam[1].Value,
(int)IndParam.NumParam[2].Value,
(int)IndParam.NumParam[3].Value,
(int)IndParam.NumParam[4].Value,
IndParam.CheckParam[0].Checked ? "ON" : "OFF");
}
private void SyncPriorityMirror(int priorityIndex)
{
priorityIndex = ClampInt(priorityIndex, 0, 2);
IndParam.ListParam[0].Index = priorityIndex;
IndParam.ListParam[0].Text = PriorityModeToText(priorityIndex);
if (IndParam.NumParam[5].Enabled)
IndParam.NumParam[5].Value = priorityIndex;
}
private string PriorityModeToText(int priorityIndex)
{
priorityIndex = ClampInt(priorityIndex, 0, 2);
return IndParam.ListParam[0].ItemList[priorityIndex];
}
private int ClampInt(int value, int min, int max)
{
if (value < min) return min;
if (value > max) return max;
return value;
}
}
}
class FSBNewsGate_v2_1 : public Indicator { public: FSBNewsGate_v2_1(SlotTypes slotType); virtual void Calculate(DataSet &dataSet); private: datetime m_newsUtc[]; string m_newsPriority[]; string m_newsCurrency[]; string m_newsTitle[]; double m_lastFeedStamp; datetime m_lastLoadOk; datetime m_lastLoadTry; datetime m_lastPanelUpdate; datetime m_lastHealthCheck; string m_lastError; string m_cachedFile; void EnsureInit(); int ClampInt(int value, int minValue, int maxValue); bool ResolveContinueOnError(); int ResolvePriorityMode(); string PriorityModeText(const int priorityMode); bool FileHealthCheck(const string fileName, string &errText); string ReadFileUtf8(const string fileName, string &error); string TrimSimple(string s); void ResetNewsArrays(); int ParseNewsContent(const string content); int LoadNewsIfNeeded(); bool AcceptPriority(const string prio, const int priorityMode); bool AcceptCurrency(const string ccy, const string baseCcy, const string quoteCcy); string FirstSixLettersUpperFromDataSymbol(); string GetSymbolBase(); string GetSymbolQuote(); int ActiveNewsIndex(const datetime nowUtc, const int priorityMode, const int beforeHigh, const int afterHigh, const int beforeMed, const int afterMed, const int tolSec, const string baseCcy, const string quoteCcy); void UpdateStatusPanel(const bool allowNow, const int priorityMode, const bool continueOnError, const int records, const double stamp, const datetime lastLoadOk, const double ageMin, const double bypass, const string lastError); }; void FSBNewsGate_v2_1::FSBNewsGate_v2_1(SlotTypes slotType) { SlotType = slotType; IndicatorName = "FSBNewsGate_v2_1"; WarningMessage = ""; IsAllowLTF = false; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDeafultGroupAll = false; IsDefaultGroupAll = false; m_lastFeedStamp = -1.0; m_lastLoadOk = 0; m_lastLoadTry = 0; m_lastPanelUpdate = 0; m_lastHealthCheck = 0; m_lastError = ""; m_cachedFile = "news-feed.txt"; ArrayResize(m_newsUtc, 0); ArrayResize(m_newsPriority, 0); ArrayResize(m_newsCurrency, 0); ArrayResize(m_newsTitle, 0); } void FSBNewsGate_v2_1::EnsureInit() { if(m_cachedFile == "") m_cachedFile = "news-feed.txt"; } int FSBNewsGate_v2_1::ClampInt(int value, int minValue, int maxValue) { if(value < minValue) return minValue; if(value > maxValue) return maxValue; return value; } bool FSBNewsGate_v2_1::ResolveContinueOnError() { if(CheckParam[0].Enabled) return CheckParam[0].Checked; return true; } int FSBNewsGate_v2_1::ResolvePriorityMode() { if(NumParam[5].Enabled) return ClampInt((int)NumParam[5].Value, 0, 2); if(ListParam[0].Enabled) return ClampInt(ListParam[0].Index, 0, 2); return 1; } string FSBNewsGate_v2_1::PriorityModeText(const int priorityMode) { if(priorityMode == 0) return "Disabled"; if(priorityMode == 1) return "HighOnly"; return "High+Med"; } bool FSBNewsGate_v2_1::FileHealthCheck(const string fileName, string &errText) { errText = ""; datetime now = TimeCurrent(); if(now <= m_lastHealthCheck + 15) return (m_lastError == ""); m_lastHealthCheck = now; int h = FileOpen(fileName, FILE_READ | FILE_BIN); if(h < 0) { errText = "Missing/unreadable: " + fileName + " err=" + IntegerToString(GetLastError()); return false; } int sz = (int)FileSize(h); FileClose(h); if(sz <= 0) { errText = "Empty file: " + fileName; return false; } return true; } string FSBNewsGate_v2_1::ReadFileUtf8(const string fileName, string &error) { error = ""; int h = FileOpen(fileName, FILE_READ | FILE_BIN); if(h < 0) { error = "Cannot open news file: " + fileName + " err=" + IntegerToString(GetLastError()); return ""; } int sz = (int)FileSize(h); if(sz <= 0) { FileClose(h); error = "News file is empty: " + fileName; return ""; } char buf[]; ArrayResize(buf, sz); FileReadArray(h, buf, 0, sz); FileClose(h); return CharArrayToString(buf, 0, sz, CP_UTF8); } string FSBNewsGate_v2_1::TrimSimple(string s) { StringReplace(s, "\r", ""); StringTrimLeft(s); StringTrimRight(s); return s; } void FSBNewsGate_v2_1::ResetNewsArrays() { ArrayResize(m_newsUtc, 0); ArrayResize(m_newsPriority, 0); ArrayResize(m_newsCurrency, 0); ArrayResize(m_newsTitle, 0); } int FSBNewsGate_v2_1::ParseNewsContent(const string content) { ResetNewsArrays(); string lines[]; int ln = StringSplit(content, '\n', lines); if(ln <= 0) { m_lastError = "Cannot parse news feed (no lines)"; return 0; } int added = 0; for(int i = 0; i < ln; i++) { string line = TrimSimple(lines[i]); if(line == "") continue; if(StringSubstr(line, 0, 1) == "#") continue; string f[]; int fn = StringSplit(line, ';', f); if(fn != 4) continue; string tsText = TrimSimple(f[0]); string pr = TrimSimple(f[1]); string cc = TrimSimple(f[2]); string title = TrimSimple(f[3]); StringToLower(pr); StringToUpper(cc); if(tsText == "" || pr == "" || cc == "") continue; datetime t = (datetime)StringToInteger(tsText); if((int)t <= 0) continue; int k = ArraySize(m_newsUtc); ArrayResize(m_newsUtc, k + 1); ArrayResize(m_newsPriority, k + 1); ArrayResize(m_newsCurrency, k + 1); ArrayResize(m_newsTitle, k + 1); m_newsUtc[k] = t; m_newsPriority[k] = pr; m_newsCurrency[k] = cc; m_newsTitle[k] = title; added++; } if(added == 0) m_lastError = "Parsed 0 news records"; return added; } int FSBNewsGate_v2_1::LoadNewsIfNeeded() { m_lastError = ""; m_lastLoadTry = TimeCurrent(); double stamp = -1.0; if(GlobalVariableCheck("FSB_NEWS_FEED_TS")) stamp = GlobalVariableGet("FSB_NEWS_FEED_TS"); bool needReload = false; if(stamp > 0.0 && stamp != m_lastFeedStamp) { needReload = true; m_lastFeedStamp = stamp; } else { if(m_lastLoadOk == 0 || TimeCurrent() > m_lastLoadOk + 600) needReload = true; } if(!needReload && ArraySize(m_newsUtc) > 0 && m_lastError == "") return 1; string err = ""; string content = ReadFileUtf8(m_cachedFile, err); if(err != "") { m_lastError = err; ResetNewsArrays(); return 0; } int parsed = ParseNewsContent(content); if(parsed > 0) { m_lastLoadOk = TimeCurrent(); m_lastError = ""; return 1; } if(m_lastError == "") m_lastError = "Parsed 0 news records"; ResetNewsArrays(); return 0; } bool FSBNewsGate_v2_1::AcceptPriority(const string prio, const int priorityMode) { if(priorityMode == 2) return (prio == "high" || prio == "medium"); if(priorityMode == 1) return (prio == "high"); return false; } bool FSBNewsGate_v2_1::AcceptCurrency(const string ccy, const string baseCcy, const string quoteCcy) { if(ccy == "ALL") return true; if(baseCcy != "" && ccy == baseCcy) return true; if(quoteCcy != "" && ccy == quoteCcy) return true; return false; } string FSBNewsGate_v2_1::FirstSixLettersUpperFromDataSymbol() { string up = Data.Symbol; StringToUpper(up); string letters = ""; int len = StringLen(up); for(int i = 0; i < len; i++) { int ch = StringGetCharacter(up, i); if(ch >= 65 && ch <= 90) { letters += StringSubstr(up, i, 1); if(StringLen(letters) >= 6) break; } } return letters; } string FSBNewsGate_v2_1::GetSymbolBase() { string letters = FirstSixLettersUpperFromDataSymbol(); if(StringLen(letters) < 6) return ""; return StringSubstr(letters, 0, 3); } string FSBNewsGate_v2_1::GetSymbolQuote() { string letters = FirstSixLettersUpperFromDataSymbol(); if(StringLen(letters) < 6) return ""; return StringSubstr(letters, 3, 3); } int FSBNewsGate_v2_1::ActiveNewsIndex(const datetime nowUtc, const int priorityMode, const int beforeHigh, const int afterHigh, const int beforeMed, const int afterMed, const int tolSec, const string baseCcy, const string quoteCcy) { int n = ArraySize(m_newsUtc); if(n <= 0) return -1; for(int i = 0; i < n; i++) { string pr = m_newsPriority[i]; string cc = m_newsCurrency[i]; datetime t = m_newsUtc[i]; if(!AcceptPriority(pr, priorityMode)) continue; if(!AcceptCurrency(cc, baseCcy, quoteCcy)) continue; if(pr == "high") { datetime start = t - beforeHigh * 60 - tolSec; datetime end = t + afterHigh * 60 + tolSec; if(nowUtc >= start && nowUtc <= end) return i; } else if(pr == "medium") { datetime start = t - beforeMed * 60 - tolSec; datetime end = t + afterMed * 60 + tolSec; if(nowUtc >= start && nowUtc <= end) return i; } } return -1; } void FSBNewsGate_v2_1::UpdateStatusPanel(const bool allowNow, const int priorityMode, const bool continueOnError, const int records, const double stamp, const datetime lastLoadOk, const double ageMin, const double bypass, const string lastError) { datetime now = TimeCurrent(); if(now <= m_lastPanelUpdate + 5) return; m_lastPanelUpdate = now; string name = "FSBNewsGate_Status_" + Data.Symbol + "_" + IntegerToString((int)Data.Period) + "_" + IntegerToString(priorityMode); string prTxt = PriorityModeText(priorityMode); string coeTxt = continueOnError ? "ON" : "OFF"; string stampTxt = (stamp > 0.0) ? TimeToString((datetime)stamp, TIME_DATE | TIME_SECONDS) : "n/a"; string loadTxt = (lastLoadOk > 0) ? TimeToString(lastLoadOk, TIME_DATE | TIME_SECONDS) : "n/a"; string utcTxt = TimeToString(TimeGMT(), TIME_DATE | TIME_SECONDS); string srvTxt = TimeToString(TimeCurrent(), TIME_DATE | TIME_SECONDS); string st; if(lastError != "") st = continueOnError ? "ERROR (Fail-Open)" : "ERROR (Fail-Closed)"; else st = allowNow ? "OK (Allow)" : "OK (Blocked)"; string text = "FSBNewsGate_v2_1\n" + "Status: " + st + "\n" + "Priority: " + prTxt + "\n" + "ContinueOnError: " + coeTxt + "\n" + "Records: " + IntegerToString(records) + "\n" + "Now UTC: " + utcTxt + "\n" + "Now Server: " + srvTxt + "\n" + "FeedTS: " + stampTxt + "\n" + "LastLoad: " + loadTxt + "\n" + "AgeMin: " + DoubleToString(ageMin, 2) + "\n" + "Bypass: " + DoubleToString(bypass, 0) + "\n" + "File: " + m_cachedFile + "\n"; if(lastError != "") text += "Err: " + lastError + "\n"; if(ObjectFind(0, name) < 0) { ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER); ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 10); ObjectSetInteger(0, name, OBJPROP_YDISTANCE, 10); ObjectSetString(0, name, OBJPROP_FONT, "Arial"); ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 9); ObjectSetInteger(0, name, OBJPROP_BACK, true); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); } color c = clrLime; if(lastError != "") c = continueOnError ? clrOrange : clrRed; else if(!allowNow) c = clrGold; ObjectSetInteger(0, name, OBJPROP_COLOR, c); ObjectSetString(0, name, OBJPROP_TEXT, text); } void FSBNewsGate_v2_1::Calculate(DataSet &dataSet) { EnsureInit(); Data = GetPointer(dataSet); int bars = Data.Bars; if(bars <= 0) return; int last = bars - 1; int prev = bars - 2; int priorityMode = ResolvePriorityMode(); int beforeHigh = ClampInt((int)NumParam[0].Value, 0, 240); int afterHigh = ClampInt((int)NumParam[1].Value, 0, 240); int beforeMed = ClampInt((int)NumParam[2].Value, 0, 240); int afterMed = ClampInt((int)NumParam[3].Value, 0, 240); int tolSec = ClampInt((int)NumParam[4].Value, 0, 60); bool continueOnError = ResolveContinueOnError(); int firstBar = 0; ArrayResize(Component[0].Value, bars); ArrayInitialize(Component[0].Value, 1.0); ArrayResize(Component[1].Value, bars); ArrayInitialize(Component[1].Value, 1.0); ArrayResize(Component[2].Value, bars); ArrayInitialize(Component[2].Value, 1.0); ArrayResize(Component[3].Value, bars); ArrayInitialize(Component[3].Value, -1.0); ArrayResize(Component[4].Value, bars); ArrayInitialize(Component[4].Value, 0.0); ArrayResize(Component[5].Value, bars); ArrayInitialize(Component[5].Value, 0.0); Component[0].CompName = "Allow long entry"; Component[0].DataType = IndComponentType_AllowOpenLong; Component[0].FirstBar = firstBar; Component[0].ShowInDynInfo = true; Component[1].CompName = "Allow short entry"; Component[1].DataType = IndComponentType_AllowOpenShort; Component[1].FirstBar = firstBar; Component[1].ShowInDynInfo = true; Component[2].CompName = "NewsFeed OK"; Component[2].DataType = IndComponentType_IndicatorValue; Component[2].FirstBar = firstBar; Component[2].ShowInDynInfo = true; Component[3].CompName = "NewsLoadAgeMin"; Component[3].DataType = IndComponentType_IndicatorValue; Component[3].FirstBar = firstBar; Component[3].ShowInDynInfo = true; Component[4].CompName = "FailOpenBypass"; Component[4].DataType = IndComponentType_IndicatorValue; Component[4].FirstBar = firstBar; Component[4].ShowInDynInfo = true; Component[5].CompName = "NewsLastLoadTS"; Component[5].DataType = IndComponentType_IndicatorValue; Component[5].FirstBar = firstBar; Component[5].ShowInDynInfo = true; Component[6].DataType = IndComponentType_NotDefined; Component[7].DataType = IndComponentType_NotDefined; Component[8].DataType = IndComponentType_NotDefined; Component[9].DataType = IndComponentType_NotDefined; double stampNow = GlobalVariableCheck("FSB_NEWS_FEED_TS") ? GlobalVariableGet("FSB_NEWS_FEED_TS") : -1.0; double ageMin = (m_lastLoadOk > 0) ? (double)(TimeCurrent() - m_lastLoadOk) / 60.0 : -1.0; if(priorityMode == 0) { if(last >= 0) { Component[2].Value[last] = 2.0; Component[3].Value[last] = 0.0; Component[4].Value[last] = 0.0; Component[5].Value[last] = (double)m_lastLoadOk; } if(prev >= 0) { Component[2].Value[prev] = 2.0; Component[3].Value[prev] = 0.0; Component[4].Value[prev] = 0.0; Component[5].Value[prev] = (double)m_lastLoadOk; } UpdateStatusPanel(true, priorityMode, continueOnError, ArraySize(m_newsUtc), stampNow, m_lastLoadOk, 0.0, 0.0, ""); return; } string healthErr = ""; if(!FileHealthCheck(m_cachedFile, healthErr)) { m_lastError = healthErr; ResetNewsArrays(); double bypass = continueOnError ? 1.0 : 0.0; if(last >= 0) { Component[2].Value[last] = 0.0; Component[3].Value[last] = ageMin; Component[4].Value[last] = bypass; Component[5].Value[last] = (double)m_lastLoadOk; Component[0].Value[last] = continueOnError ? 1.0 : 0.0; Component[1].Value[last] = continueOnError ? 1.0 : 0.0; } if(prev >= 0) { Component[2].Value[prev] = 0.0; Component[3].Value[prev] = ageMin; Component[4].Value[prev] = bypass; Component[5].Value[prev] = (double)m_lastLoadOk; Component[0].Value[prev] = continueOnError ? 1.0 : 0.0; Component[1].Value[prev] = continueOnError ? 1.0 : 0.0; } UpdateStatusPanel(continueOnError, priorityMode, continueOnError, 0, stampNow, m_lastLoadOk, ageMin, bypass, m_lastError); return; } int ok = LoadNewsIfNeeded(); int recordsNow = ArraySize(m_newsUtc); ageMin = (m_lastLoadOk > 0) ? (double)(TimeCurrent() - m_lastLoadOk) / 60.0 : -1.0; int staleAfterMin = 180; bool stale = (m_lastLoadOk > 0 && ageMin > staleAfterMin); if(stale && m_lastError == "") m_lastError = "Stale feed: last successful load is older than " + IntegerToString(staleAfterMin) + " min"; if(ok == 0 || stale) { double bypass2 = continueOnError ? 1.0 : 0.0; if(last >= 0) { Component[2].Value[last] = 0.0; Component[3].Value[last] = ageMin; Component[4].Value[last] = bypass2; Component[5].Value[last] = (double)m_lastLoadOk; Component[0].Value[last] = continueOnError ? 1.0 : 0.0; Component[1].Value[last] = continueOnError ? 1.0 : 0.0; } if(prev >= 0) { Component[2].Value[prev] = 0.0; Component[3].Value[prev] = ageMin; Component[4].Value[prev] = bypass2; Component[5].Value[prev] = (double)m_lastLoadOk; Component[0].Value[prev] = continueOnError ? 1.0 : 0.0; Component[1].Value[prev] = continueOnError ? 1.0 : 0.0; } UpdateStatusPanel(continueOnError, priorityMode, continueOnError, recordsNow, stampNow, m_lastLoadOk, ageMin, bypass2, m_lastError); return; } if(last >= 0) { Component[2].Value[last] = 1.0; Component[3].Value[last] = ageMin; Component[4].Value[last] = 0.0; Component[5].Value[last] = (double)m_lastLoadOk; } if(prev >= 0) { Component[2].Value[prev] = 1.0; Component[3].Value[prev] = ageMin; Component[4].Value[prev] = 0.0; Component[5].Value[prev] = (double)m_lastLoadOk; } string baseCcy = GetSymbolBase(); string quoteCcy = GetSymbolQuote(); datetime nowUtc = TimeGMT(); int idx = ActiveNewsIndex(nowUtc, priorityMode, beforeHigh, afterHigh, beforeMed, afterMed, tolSec, baseCcy, quoteCcy); bool allowNow = (idx < 0); if(last >= 0) { Component[0].Value[last] = allowNow ? 1.0 : 0.0; Component[1].Value[last] = allowNow ? 1.0 : 0.0; } if(prev >= 0) { Component[0].Value[prev] = allowNow ? 1.0 : 0.0; Component[1].Value[prev] = allowNow ? 1.0 : 0.0; } UpdateStatusPanel(allowNow, priorityMode, continueOnError, recordsNow, stampNow, m_lastLoadOk, ageMin, 0.0, ""); }
Risk warning: Forex, spread bets and CFD are leveraged products. They may not be suitable for you as they carry a high degree of risk to your capital and you can lose more than your initial investment. You should ensure you understand all of the risks.
Copyright © 2006 - 2026, Forex Software Ltd.
Copyright © 2006 - 2026, Forex Software Ltd.