#region Using declarations using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Xml.Serialization; using NinjaTrader.Cbi; using NinjaTrader.Data; using NinjaTrader.Gui.Chart; using System.Xml; using System.Net; using System.Net.Cache; using System.IO; using System.Text; using System.Globalization; #endregion /// /// jtEconNews2a - johnthom.com - 10/19/09 (please do not remove this line) /// with bugfix added by Fat Tails 11/25/01 namespace NinjaTrader.Indicator { /// /// /// NOTE: If you are reading this because you are getting errors pertaining to date parsing then please do this: /// /// 1) Set 'debug' to true in the indicator settings. /// 2) Open an Output Window. /// 3) Refresh your chart. /// 4) Do a select all of the Output Window text and post it on my blog entry here... http://www.johnthom.com/2009/10/economic-news-indicator.html /// /// I will attempt to fix the issue. I have done this once before but apparently there are certain /// country specific date parsing issues that I've still to address. /// /// ============================================================================================ /// /// This is my version of the old Metatrader FFCal indicator. I stuck with using ForexFactory /// as I think their events are more inclusive than econoday and fxstreet. /// /// Change Log: /// /// 10/19/09 - Fixed a bug with date/time parsing in a non-"en-US" culture. Thanks /// Harry104, from Berlin, for all your help tacking this down. Also, updated /// "No more News" messages to be more helpful. /// /// 10/29/09 - Added properties and logic to for a background. Fixed bugs. Improved effeciency. /// /// 11/02/09 - Final version. Code cleanup. Only bug fixes from this point on. /// /// [Description("jtEconNews2b - Display upcoming economic news events from ForexFactory.com")] public class jtEconNews2b : Indicator { /// /// Internal class used to hold news event state. /// public class NewsEvent { public int ID; public string Title; public string Country; public string Date; public string Time; public string Impact; public string Forecast; public string Previous; [XmlIgnore()] public DateTime DateTimeLocal; public override string ToString(){ return string.Format("ID: {0}, Title: {1}, Country: {2}, Date: {3}, Time: {4}, Impact: {5}, Forecast: {6}, Previous: {7}, DateTimeLocal: {8}", ID, Title, Country, Date, Time,Impact, Forecast, Previous, DateTimeLocal); } } // class variables private const string ffNewsUrl = @"http://www.forexfactory.com/ffcal_week_this.xml"; private const string TIME = "Time"; private const string IMPACT = "Impact"; private const string DESC = "News Event Description (prev/forecast)"; private const float TIME_PAD = 10; private const float IMPACT_PAD = 10; private const float DESC_PAD = 0; private NewsEvent[] newsEvents = null; private DateTime lastNewsUpdate = DateTime.MinValue; private string lastLoadError; private SolidBrush headerTitleBrush; private SolidBrush lineHighBrush; private SolidBrush lineMedBrush; private SolidBrush lineLowBrush; private SolidBrush lineNormalBrush; private System.Collections.Generic.List list; private float widestTimeCol = 0; private float widestImpactCol = 0; private float widestDescCol = 0; private float totalHeight = 0; private float longestLine = 0; private int lastNewsPtr = 0; private DateTime lastMinute; // Must specify that culture that should be used to parse the ForexFactory date/time data. private CultureInfo ffDateTimeCulture = CultureInfo.CreateSpecificCulture("en-US"); // property variables private bool debug = false; private float topOffset = 20; private float leftOffset = 10; private int maxNewsItems = 10; // max to display private int newsRefeshInterval = 15; private int newsItemPtr = 0; private bool use24timeFormat = false; private bool todaysNewsOnly = true; private bool sendAlerts = true; private int alertInterval = 15; private string alertWavFileName = "Alert1.wav"; // some fonts and colors changed by Fat Tails /// private Font titleFont = new Font("Arial", 1, FontStyle.Italic | FontStyle.Bold); private Font headerFont = new Font("Arial", 1, FontStyle.Bold); // this should be a property private Font lineFont = new Font("Arial", 10, FontStyle.Regular); private Font lineAlertFont = new Font("Arial", 10, FontStyle.Bold | FontStyle.Italic); private bool usaOnly = false; private bool showLowPriority = true; private Color headerColor = Color.Black; // some colors changed by Fat Tails January 25, 2011 private Color lineHighColor = Color.Red; // private Color lineMedColor = Color.Yellow; // private Color lineLowColor = Color.GreenYellow; // private Color lineNormalColor = Color.LightSkyBlue; // added by Fat Tails January 25, 2011 private Color backgroundColor = Color.Black; // private Color borderColor = Color.SlateBlue; // private bool showBackground = true; private int backgroundOpacity = 255; /// /// This method is used to configure the indicator and is called once before any bar data is loaded. /// protected override void Initialize() { this.Name="jtEconNews2b"; // changed by Fat Tails January 25, 2011 CalculateOnBarClose = false; Overlay = true; PriceTypeSupported = false; ZOrder = int.MaxValue;; headerTitleBrush = new SolidBrush(headerColor); lineHighBrush = new SolidBrush(lineHighColor); lineMedBrush = new SolidBrush(lineMedColor); lineLowBrush = new SolidBrush(lineLowColor); lineNormalBrush = new SolidBrush (lineNormalColor); // added by Fat Tails January 25, 2011 list = new System.Collections.Generic.List(); lastNewsPtr = -1; lastMinute = DateTime.MinValue; LoadNews(); } /// /// This will be called on Initialization and then every news refresh interval. If an /// error occurs calling the website then it will take another interval before we /// try again. /// private void LoadNews(){ lastNewsUpdate = DateTime.Now; lastLoadError = null; try { if (debug){ Print("LoadNews()...."); string[] patts = CultureInfo.CurrentCulture.DateTimeFormat.GetAllDateTimePatterns(); Print("All DateTime Patterns for culture: " + CultureInfo.CurrentCulture.Name); foreach(string patt in patts){ Print(" " + patt); } Print("End of DateTime Patterns"); } // add a random query string to defeat server side caching. string urltweak = ffNewsUrl + "?x=" + Convert.ToString(DateTime.Now.Ticks); if (debug) Print("Loading news from URL: " + urltweak); HttpWebRequest newsReq = (HttpWebRequest)HttpWebRequest.Create(urltweak); newsReq.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.Reload); // fetch the xml doc from the web server using (HttpWebResponse newsResp = (HttpWebResponse)newsReq.GetResponse()){ // check that we got a valid reponse if (newsResp != null && newsResp.StatusCode == HttpStatusCode.OK){ // read the response stream into and xml document Stream receiveStream = newsResp.GetResponseStream(); Encoding encode = System.Text.Encoding.GetEncoding("utf-8"); StreamReader readStream = new StreamReader( receiveStream, encode ); string xmlString = readStream.ReadToEnd(); if (debug) Print("RAW http response: " + xmlString); XmlDocument newsDoc = new XmlDocument(); newsDoc.LoadXml(xmlString); if (debug) Print("XML news event node count: " + newsDoc.DocumentElement.ChildNodes.Count ); // build collection of events System.Collections.ArrayList list = new System.Collections.ArrayList(); int itemId = 0; foreach(XmlNode xmlNode in newsDoc.DocumentElement.ChildNodes){ NewsEvent newsEvent = new NewsEvent(); newsEvent.Time = xmlNode.SelectSingleNode("time").InnerText; if (string.IsNullOrEmpty(newsEvent.Time)) continue; // ignore tentative events! newsEvent.Date = xmlNode.SelectSingleNode("date").InnerText; // assembly and convert event date/time to local time. if (debug) Print(string.Format("About to parse Date '{0}', Time '{1}'", newsEvent.Date, newsEvent.Time)); newsEvent.DateTimeLocal = DateTime.SpecifyKind(DateTime.Parse( newsEvent.Date + " " + newsEvent.Time, ffDateTimeCulture), DateTimeKind.Utc).ToLocalTime(); if (debug) Print("Succesfully parsed datetime: " + newsEvent.DateTimeLocal.ToString() + " to local time."); // filter events based on settings... DateTime startTime = DateTime.Now; DateTime endTime = startTime.AddDays(1); // filter news events based on various property settings... if (newsEvent.DateTimeLocal >= startTime && (!todaysNewsOnly || newsEvent.DateTimeLocal.Date < endTime.Date)) { newsEvent.ID = ++itemId; newsEvent.Country = xmlNode.SelectSingleNode("country").InnerText; if (usaOnly && newsEvent.Country != "USD") continue; newsEvent.Forecast = xmlNode.SelectSingleNode("forecast").InnerText; newsEvent.Impact = xmlNode.SelectSingleNode("impact").InnerText; if (!showLowPriority && newsEvent.Impact.ToUpper() == "LOW") continue; newsEvent.Previous = xmlNode.SelectSingleNode("previous").InnerText; newsEvent.Title = xmlNode.SelectSingleNode("title").InnerText; list.Add(newsEvent); if (debug) Print("Added: " + newsEvent.ToString()); } } // load the array newsEvents = (NewsEvent[])list.ToArray(typeof(NewsEvent)); if (debug) Print("Added a total of " + list.Count + " events to array."); } else { // handle unexpected scenarios... if (newsResp == null) throw new Exception("Web response was null."); else throw new Exception("Web response status code = " + newsResp.StatusCode.ToString()); } } } catch (Exception ex){ Print(ex.ToString()); lastLoadError = ex.Message; } } /// /// Called on each bar update event (incoming tick) /// protected override void OnBarUpdate() { // we only need to update at most every minute since this is the max granularity of the // date/time of the news events. This saves a little wear and tear. if (Time[0] >= lastMinute.AddMinutes(1)) { if (debug) Print("OnBarUpdate running..."); lastMinute = Time[0]; // download the news data every news refresh interval (not bar interval). if (lastNewsUpdate.AddMinutes(newsRefeshInterval) < DateTime.Now){ LoadNews(); } newsItemPtr = -1; // this will indicate that there are no pending items at this time. // set pointer to the first "pending" news item in the list based on current datetime. if (newsEvents != null && newsEvents.Length > 0) { for(int x = 0; x < newsEvents.Length ; x++){ NewsEvent item = newsEvents[x]; if (item.DateTimeLocal >= DateTime.Now ){ newsItemPtr = x; break; } } BuildList(); } } } private void BuildList(){ if (debug) Print("Building List. lastNewsPtr: " + lastNewsPtr + " newsItemPtr: " + newsItemPtr); list = new System.Collections.Generic.List(); // add headers TextLine line = new TextLine(headerFont, headerTitleBrush); line.timeColumn = new TextColumn(TIME_PAD, TIME); line.impactColumn = new TextColumn(IMPACT_PAD, IMPACT); line.descColumn = new TextColumn(DESC_PAD, DESC); list.Add(line); int lineCnt = 0; // add detail lines... for (int x = newsItemPtr; x < newsEvents.Length; x++){ lineCnt++; // limit the number of pending events to be displayed. if (lineCnt > maxNewsItems) break; NewsEvent item = newsEvents[x]; // Set the brush color and alert priority based on event impact level. Priority alertPriority = Priority.Low; SolidBrush lineBrush = lineNormalBrush; if (item.Impact.ToUpper() == "HIGH"){ lineBrush = lineHighBrush; alertPriority = Priority.High; } else if (item.Impact.ToUpper() == "MEDIUM"){ lineBrush = lineMedBrush; alertPriority = Priority.Medium; } else if (item.Impact.ToUpper() == "LOW"){ lineBrush = lineLowBrush; } // Format time based on option selected. string tempTime = null; if (use24timeFormat){ tempTime = item.DateTimeLocal.ToString(" HH:mm", ffDateTimeCulture); } else { tempTime = item.DateTimeLocal.ToString("hh:mm tt", ffDateTimeCulture); } // if we are displaying all pending news then include the month/day as part of the time. if (!todaysNewsOnly){ tempTime = item.DateTimeLocal.ToString("MM/dd ") + tempTime; } // if alerts are enable, check to see if event is within alert range. Font tempFont; TimeSpan diff = item.DateTimeLocal - DateTime.Now; if (sendAlerts && diff.TotalMinutes <= alertInterval ){ tempFont = lineAlertFont; Alert("jtEconNewsAlert"+item.ID,alertPriority, string.Format( "News Alert: {0} {1}: {2}" , item.DateTimeLocal,item.Country, item.Title),alertWavFileName, Int32.MaxValue, lineBrush.Color, Color.White); } else { tempFont = lineFont; } // create a text line for the event details line = new TextLine(tempFont, lineBrush); line.timeColumn = new TextColumn(TIME_PAD, tempTime); line.impactColumn = new TextColumn(IMPACT_PAD, item.Impact); string templine = null; if (item.Previous.Trim().Length == 0 && item.Forecast.Trim().Length == 0){ templine = string.Format("{0}{1}", usaOnly?"":item.Country+": " , item.Title); } else { templine = string.Format("{0}{1} ({2}/{3})", usaOnly?"":item.Country+": " , item.Title, item.Previous, item.Forecast ); } line.descColumn = new TextColumn(DESC_PAD, templine); list.Add(line); } } public override void Plot(Graphics graphics, Rectangle bounds, double min, double max) { base.Plot(graphics, bounds, min, max); float yOffset = bounds.Y + topOffset; float xOffset = bounds.X + leftOffset; graphics.DrawString("jtEconNews2a - news courtesy of ForexFactory.com - all times are local", titleFont, headerTitleBrush, xOffset, yOffset); yOffset += titleFont.Height; if (lastLoadError != null){ // an error occurred trying to load the xml data. graphics.DrawString("News load error: " + lastLoadError , lineFont,lineHighBrush, xOffset, yOffset); } else if (newsItemPtr == -1){ // there is no new news data yet. string tempString; if (todaysNewsOnly){ tempString = "(There are no pending news events for the rest of the day.)"; } else { tempString = "(There are no pending news events at this time.)"; } graphics.DrawString(tempString , lineFont, lineMedBrush, xOffset, yOffset); } else { widestTimeCol = 0; widestImpactCol = 0; widestDescCol = 0; totalHeight = 0; // pre-calc the max column widths and total line height foreach(TextLine tLine in list){ float f = tLine.timeColumn.GetLength(graphics, tLine.font); if (f > widestTimeCol) widestTimeCol = f; f = tLine.impactColumn.GetLength(graphics, tLine.font); if (f > widestImpactCol) widestImpactCol = f; f = tLine.descColumn.GetLength(graphics, tLine.font); if (f > widestDescCol) widestDescCol = f; totalHeight += tLine.font.Height; } longestLine = widestTimeCol + widestImpactCol + widestDescCol; // display graphics... if (showBackground){ Brush backBrush = new SolidBrush(Color.FromArgb(backgroundOpacity, backgroundColor)); graphics.FillRectangle(backBrush, xOffset, yOffset, longestLine, totalHeight); backBrush.Dispose(); Pen borderPen = new Pen(borderColor); graphics.DrawRectangle(borderPen, xOffset, yOffset, longestLine, totalHeight); borderPen.Dispose(); } float tempy = yOffset; foreach(TextLine tLine in list){ float tempx = xOffset; graphics.DrawString(tLine.timeColumn.text, tLine.font, tLine.brush, tempx, tempy); tempx += widestTimeCol; graphics.DrawString(tLine.impactColumn.text, tLine.font, tLine.brush, tempx, tempy); tempx += widestImpactCol; graphics.DrawString(tLine.descColumn.text, tLine.font, tLine.brush, tempx, tempy); tempy += tLine.font.Height; } } } /// /// Utility classes to encapsulate the graphical requirements for each line and column of data /// private class TextColumn { public TextColumn(float padding, string text){ this.padding = padding; this.text = text; } public float padding; public string text; public float GetLength(Graphics graphics, Font font){ return graphics.MeasureString(text, font).Width + padding; } } private class TextLine { public TextLine(Font font, Brush brush){ this.graphics = graphics; this.font = font; this.brush = brush; } public TextColumn timeColumn; public TextColumn impactColumn; public TextColumn descColumn; public Font font; public Brush brush; private Graphics graphics; } #region Properties [Description("Offset from top of window.")] [Category("Display")] public float TopOffset { get { return topOffset; } set { topOffset = value; } } [Description("Offset from left of window.")] [Category("Display")] public float LeftOffset { get { return leftOffset; } set { leftOffset = value; } } [Description("Enable or disable background display.")] [Category("Display")] public bool ShowBackground { get { return showBackground; } set { showBackground = value; } } [Description("Max number of pending news events to display.")] [Category("Filter News")] public int MaxNewsItems { get { return maxNewsItems; } set { maxNewsItems = value; } } [Description("News refresh interval in minutes.")] [Category("Parameters")] public int NewsRefeshInterval { get { return newsRefeshInterval; } set { newsRefeshInterval = value; } } [Description("Time display format, true for 24 hour, false for AM/PM")] [Category("Display")] public bool Use24HourTimeFormat { get { return use24timeFormat; } set { use24timeFormat = value; } } [Description("Debug to OutputWindow")] [Category("Debug")] public bool Debug { get { return debug; } set { debug = value; } } [Description("Show only todays news events.")] [Category("Filter News")] public bool TodaysNewsOnly { get { return todaysNewsOnly; } set { todaysNewsOnly = value; } } [Description("Send alerts to the Alerts Window.")] [Category("Alerts")] public bool UseAlerts { get { return sendAlerts; } set { sendAlerts = value; } } [Description("Number of minutes to warn before an event.")] [Category("Alerts")] public int WarningInterval { get { return alertInterval; } set { alertInterval = value; } } [Description("Alert wav file, blank to turn off audio alerts.")] [Category("Alerts")] public string AlertWavFileName { get { return alertWavFileName; } set { alertWavFileName = value; } } [Description("Header Font. This font is used determine the columns widths. The size of this font should be larger than the others.")] [Category("Fonts")] [XmlIgnore()] public Font HeaderFont { get { return headerFont; } set { headerFont = value; } } [Browsable(false)] public string HeaderFontSerialize { get { return NinjaTrader.Gui.Design.SerializableFont.ToString(headerFont); } set { headerFont = NinjaTrader.Gui.Design.SerializableFont.FromString(value); } } [Description("Default Event Font")] [Category("Fonts")] [XmlIgnore()] public Font DefaultFont { get { return lineFont; } set { lineFont = value; } } [Browsable(false)] public string DefaultFontSerialize { get { return NinjaTrader.Gui.Design.SerializableFont.ToString(lineFont); } set { lineFont = NinjaTrader.Gui.Design.SerializableFont.FromString(value); } } [Description("Warning Event Font")] [Category("Fonts")] [XmlIgnore()] public Font WarningFont { get { return lineAlertFont; } set { lineAlertFont = value; } } [Browsable(false)] public string WarningFontSerialize { get { return NinjaTrader.Gui.Design.SerializableFont.ToString(lineAlertFont); } set { lineAlertFont = NinjaTrader.Gui.Design.SerializableFont.FromString(value); } } [Description("Show only US events.")] [Category("Filter News")] public bool USOnlyEvents { get { return usaOnly; } set { usaOnly = value; } } [Description("Show on US events.")] [Category("Filter News")] public bool ShowLowPriority { get { return showLowPriority; } set { showLowPriority = value; } } [XmlIgnore()] [Description("Header Color")] [Category("Colors")] public Color HeaderColor { get { return headerColor; } set { headerColor = value; } } [Browsable(false)] public string HeaderColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(headerColor); } set { headerColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [XmlIgnore()] [Description("High Priority Color")] [Category("Colors")] public Color HighPriorityColor { get { return lineHighColor; } set { lineHighColor = value; } } [Browsable(false)] public string HighPriorityColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(lineHighColor); } set { lineHighColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [XmlIgnore()] [Description("Medium Priority Color")] [Category("Colors")] public Color MediumPriorityColor { get { return lineMedColor; } set { lineMedColor = value; } } [Browsable(false)] public string MediumPriorityColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(lineMedColor); } set { lineMedColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [XmlIgnore()] [Description("Low Priority Color")] [Category("Colors")] public Color LowPriorityColor { get { return lineLowColor; } set { lineLowColor = value; } } [Browsable(false)] public string LowPriorityColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(lineLowColor); } set { lineLowColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [XmlIgnore()] // added by Fat Tails January 25, 2011 [Description("Normal Priority Color")] [Category("Colors")] public Color NormalColor { get { return lineNormalColor; } set { lineNormalColor = value; } } [Browsable(false)] public string NormalColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(lineNormalColor); } set { lineNormalColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [XmlIgnore()] [Description("Background Color")] [Category("Colors")] public Color BackgroundColor { get { return backgroundColor; } set { backgroundColor = value; } } [Browsable(false)] public string BackgroundColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(backgroundColor); } set { backgroundColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [XmlIgnore()] [Description("Border Color")] [Category("Colors")] public Color BorderColor { get { return borderColor; } set { borderColor = value; } } [Browsable(false)] public string BorderColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(borderColor); } set { borderColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } [Description("Background Opacity")] [Category("Colors")] public int BackgroundOpacity { get { return backgroundOpacity; } set { backgroundOpacity = value; } } #endregion } } #region NinjaScript generated code. Neither change nor remove. // This namespace holds all indicators and is required. Do not change it. namespace NinjaTrader.Indicator { public partial class Indicator : IndicatorBase { private jtEconNews2b[] cachejtEconNews2b = null; private static jtEconNews2b checkjtEconNews2b = new jtEconNews2b(); /// /// jtEconNews2b - Display upcoming economic news events from ForexFactory.com /// /// public jtEconNews2b jtEconNews2b(int newsRefeshInterval) { return jtEconNews2b(Input, newsRefeshInterval); } /// /// jtEconNews2b - Display upcoming economic news events from ForexFactory.com /// /// public jtEconNews2b jtEconNews2b(Data.IDataSeries input, int newsRefeshInterval) { if (cachejtEconNews2b != null) for (int idx = 0; idx < cachejtEconNews2b.Length; idx++) if (cachejtEconNews2b[idx].NewsRefeshInterval == newsRefeshInterval && cachejtEconNews2b[idx].EqualsInput(input)) return cachejtEconNews2b[idx]; lock (checkjtEconNews2b) { checkjtEconNews2b.NewsRefeshInterval = newsRefeshInterval; newsRefeshInterval = checkjtEconNews2b.NewsRefeshInterval; if (cachejtEconNews2b != null) for (int idx = 0; idx < cachejtEconNews2b.Length; idx++) if (cachejtEconNews2b[idx].NewsRefeshInterval == newsRefeshInterval && cachejtEconNews2b[idx].EqualsInput(input)) return cachejtEconNews2b[idx]; jtEconNews2b indicator = new jtEconNews2b(); indicator.BarsRequired = BarsRequired; indicator.CalculateOnBarClose = CalculateOnBarClose; #if NT7 indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; indicator.MaximumBarsLookBack = MaximumBarsLookBack; #endif indicator.Input = input; indicator.NewsRefeshInterval = newsRefeshInterval; Indicators.Add(indicator); indicator.SetUp(); jtEconNews2b[] tmp = new jtEconNews2b[cachejtEconNews2b == null ? 1 : cachejtEconNews2b.Length + 1]; if (cachejtEconNews2b != null) cachejtEconNews2b.CopyTo(tmp, 0); tmp[tmp.Length - 1] = indicator; cachejtEconNews2b = tmp; return indicator; } } } } // This namespace holds all market analyzer column definitions and is required. Do not change it. namespace NinjaTrader.MarketAnalyzer { public partial class Column : ColumnBase { /// /// jtEconNews2b - Display upcoming economic news events from ForexFactory.com /// /// [Gui.Design.WizardCondition("Indicator")] public Indicator.jtEconNews2b jtEconNews2b(int newsRefeshInterval) { return _indicator.jtEconNews2b(Input, newsRefeshInterval); } /// /// jtEconNews2b - Display upcoming economic news events from ForexFactory.com /// /// public Indicator.jtEconNews2b jtEconNews2b(Data.IDataSeries input, int newsRefeshInterval) { return _indicator.jtEconNews2b(input, newsRefeshInterval); } } } // This namespace holds all strategies and is required. Do not change it. namespace NinjaTrader.Strategy { public partial class Strategy : StrategyBase { /// /// jtEconNews2b - Display upcoming economic news events from ForexFactory.com /// /// [Gui.Design.WizardCondition("Indicator")] public Indicator.jtEconNews2b jtEconNews2b(int newsRefeshInterval) { return _indicator.jtEconNews2b(Input, newsRefeshInterval); } /// /// jtEconNews2b - Display upcoming economic news events from ForexFactory.com /// /// public Indicator.jtEconNews2b jtEconNews2b(Data.IDataSeries input, int newsRefeshInterval) { if (InInitialize && input == null) throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method"); return _indicator.jtEconNews2b(input, newsRefeshInterval); } } } #endregion