// // Copyright (C) 2007, NinjaTrader LLC . // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release. // #region Using declarations using System; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.ComponentModel; using System.Xml.Serialization; using NinjaTrader.Data; using NinjaTrader.Gui.Chart; #endregion // This namespace holds all indicators and is required. Do not change it. namespace NinjaTrader.Indicator { /// /// The Bar Timer displays the remaining time of a minute based bar. /// [Description("Displays remaining time of minute based bar")] public class BarTimer : Indicator { #region Variables private string errorDisabled = "Bar timer disabled since either you are disconnected or current time is outside session time or chart end date"; private string errorIntraday = "Bar timer only works on intraday time based intervals"; private float noTickTextWidth = 0; private float noTickTextHeight = 0; private float noConTextWidth = 0; private float noConTextHeight = 0; private StringFormat stringFormat = new StringFormat(); private SolidBrush textBrush = new SolidBrush(Color.Black); private Font textFont = new Font("Arial", 30); private float textWidth = 0; private float textHeight = 0; private System.Windows.Forms.Timer timer; #endregion /// /// This method is used to configure the indicator and is called once before any bar data is loaded. /// protected override void Initialize() { ChartOnly = true; Overlay = true; CalculateOnBarClose = false; } /// /// protected override void OnBarUpdate() { if (timer == null) { if (Bars.MarketData != null && Bars.MarketData.Connection.Options.Provider == Cbi.Provider.OpenTick && (Bars.MarketData.Connection.Options as Cbi.OpenTickOptions).UseDelayedData) errorDisabled = "Bar timer disabled since it will not work on delayed data"; else if (DisplayTime()) { timer = new System.Windows.Forms.Timer(); timer.Interval = 1000; timer.Tick += new EventHandler(OnTimerTick); timer.Enabled = true; } } } #region Properties #endregion #region Miscellaneous public override void Plot(Graphics graphics, Rectangle bounds, double min, double max) { if (Bars == null) return; // Recalculate the proper string size should the chart control object font and axis color change if (textBrush.Color != ChartControl.AxisColor || textFont != ChartControl.Font) { textBrush.Color = ChartControl.AxisColor; textFont = ChartControl.Font; SizeF size = graphics.MeasureString("Time remaining = -00:-00:-00", textFont); textWidth = size.Width + 5; textHeight = size.Height + 5; SizeF noTickSize = graphics.MeasureString(errorIntraday, textFont); noTickTextWidth = noTickSize.Width + 5; noTickTextHeight = noTickSize.Height + 5; SizeF noConSize = graphics.MeasureString(errorDisabled, textFont); noConTextWidth = noConSize.Width + 5; noConTextHeight = noConSize.Height + 5; } // Plot the time remaining message to the lower right hand corner of the chart if (Bars.Period.Id == PeriodType.Minute || Bars.Period.Id == PeriodType.Second) { if (DisplayTime()) { if (timer != null && !timer.Enabled) timer.Enabled = true; TimeSpan barTimeLeft = Bars.Get(Bars.Count - 1).Time.Subtract(Now); string timeLeft = (barTimeLeft.Ticks < 0 ? "00:00:00" : barTimeLeft.Hours.ToString("00") + ":" + barTimeLeft.Minutes.ToString("00") + ":" + barTimeLeft.Seconds.ToString("00")); graphics.DrawString("Time remaining = " + timeLeft, ChartControl.Font, textBrush, bounds.X + bounds.Width - textWidth, bounds.Y + bounds.Height - textHeight, stringFormat); } else graphics.DrawString(errorDisabled, ChartControl.Font, textBrush, bounds.X + bounds.Width - noConTextWidth, bounds.Y + bounds.Height - noConTextHeight, stringFormat); } else { graphics.DrawString(errorIntraday, ChartControl.Font, textBrush, bounds.X + bounds.Width - noTickTextWidth, bounds.Y + bounds.Height - noTickTextHeight, stringFormat); if (timer != null) timer.Enabled = false; } } private bool DisplayTime() { if (ChartControl != null && Bars != null && Bars.Count > 0 && Bars.MarketData != null && Bars.MarketData.Connection.PriceStatus == Cbi.ConnectionStatus.Connected && (Bars.MarketData.Connection.Options.Provider != Cbi.Provider.OpenTick || !(Bars.MarketData.Connection.Options as Cbi.OpenTickOptions).UseDelayedData) && Bars.Session.InSession(Now, Bars.Period.Id, true)) return true; return false; } public override void Dispose() { if (timer != null) { timer.Enabled = false; timer = null; } base.Dispose(); } private DateTime Now { get { return (Bars.MarketData.Connection.Options.Provider == Cbi.Provider.Replay ? Bars.MarketData.Connection.Now : DateTime.Now); } } private void OnTimerTick(object sender, EventArgs e) { if (DisplayTime()) ChartControl.ChartPanel.Invalidate(); } #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 BarTimer[] cacheBarTimer = null; private static BarTimer checkBarTimer = new BarTimer(); /// /// Displays remaining time of minute based bar /// /// public BarTimer BarTimer() { return BarTimer(Input); } /// /// Displays remaining time of minute based bar /// /// public BarTimer BarTimer(Data.IDataSeries input) { if (cacheBarTimer != null) for (int idx = 0; idx < cacheBarTimer.Length; idx++) if (cacheBarTimer[idx].EqualsInput(input)) return cacheBarTimer[idx]; BarTimer indicator = new BarTimer(); indicator.BarsRequired = BarsRequired; indicator.CalculateOnBarClose = CalculateOnBarClose; indicator.Input = input; indicator.SetUp(); BarTimer[] tmp = new BarTimer[cacheBarTimer == null ? 1 : cacheBarTimer.Length + 1]; if (cacheBarTimer != null) cacheBarTimer.CopyTo(tmp, 0); tmp[tmp.Length - 1] = indicator; cacheBarTimer = tmp; Indicators.Add(indicator); 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 { /// /// Displays remaining time of minute based bar /// /// [Gui.Design.WizardCondition("Indicator")] public Indicator.BarTimer BarTimer() { return _indicator.BarTimer(Input); } /// /// Displays remaining time of minute based bar /// /// public Indicator.BarTimer BarTimer(Data.IDataSeries input) { return _indicator.BarTimer(input); } } } // This namespace holds all strategies and is required. Do not change it. namespace NinjaTrader.Strategy { public partial class Strategy : StrategyBase { /// /// Displays remaining time of minute based bar /// /// [Gui.Design.WizardCondition("Indicator")] public Indicator.BarTimer BarTimer() { return _indicator.BarTimer(Input); } /// /// Displays remaining time of minute based bar /// /// public Indicator.BarTimer BarTimer(Data.IDataSeries input) { 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.BarTimer(input); } } } #endregion