// SMI Candle Paintbar // Modified by Prospectus (readtheprospectus@yahoo.com) // This indicator paints the candles to match the same colors as the SMI. // Also contains an audio alert and signal arrows. // // Author: Mathew Wyatt (mathew.wyatt at gmail.com) // This indicator is the Stochastic Momentum Index by William Blau. Formula for the indicator was found - http://www.purebytes.com/archives/metastock/1998/msg06283.html. // #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 Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// [Description("The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100.")] public class SMI: Indicator { #region Variables private int range = 13; private int emaperiod1 = 25; private int emaperiod2 = 1; private int smiemaperiod = 25; private DataSeries sms; private DataSeries hls; private DataSeries smis; private Color dnColor = Color.Gold; private Color upColor = Color.Lime; #endregion /// /// This method is used to configure the indicator and is called once before any bar data is loaded. /// protected override void Initialize() { Add(new Line(Color.DarkGray, 0, "Zero line")); Add(new Plot(Color.Green, PlotStyle.Line, "SMI")); Add(new Plot(Color.Orange, "SMIEMA")); Plots[0].Pen.Width = 2; //stochastic momentums sms = new DataSeries(this); //high low diffs hls = new DataSeries(this); //stochastic momentum indexes smis = new DataSeries(this); //CalculateOnBarClose = false; } /// /// Calculates the indicator value(s) at the current index. /// protected override void OnBarUpdate() { if (( CurrentBar < emaperiod2) | ( CurrentBar < emaperiod1)) { return; } //Stochastic Momentum = SM {distance of close - midpoint} sms.Set(Close[0] - 0.5 * ((MAX(High, range)[0] + MIN(Low, range)[0]))); //High low diffs hls.Set(MAX(High, range)[0] - MIN(Low, range)[0]); //Stochastic Momentum Index = SMI double denom = 0.5*EMA(EMA(hls,emaperiod1),emaperiod2)[0]; smis.Set(100*(EMA(EMA(sms,emaperiod1),emaperiod2))[0] / (denom ==0 ? 1 : denom )); //Set the current SMI line value smi.Set(smis[0]); //************************************************************************************* double smiVal = (smis[0]); if (Falling(smis)) { DrawOnPricePanel = false; DrawDot(CurrentBar.ToString(),true,0,smiVal,DnColor); } if (Rising(smis)) { DrawOnPricePanel = false; DrawDot(CurrentBar.ToString(),true,0,smiVal,UpColor); } //***************************************************************************** //Set the line value for the SMIEMA by taking the EMA of the SMI SMIEMA.Set(EMA(smis, smiemaperiod)[0]); //Print("SMI: " + EMA(smis, smiemaperiod)[0].ToString()); } #region Properties /// /// Gets the fast D value. /// [Browsable(false)] [XmlIgnore()] public DataSeries smi { get { return Values[0]; } } /// /// Gets the fast K value. /// [Browsable(false)] [XmlIgnore()] public DataSeries SMIEMA { get { return Values[1]; } } /// /// [Description("Range for momentum calculation. ( Q )")] [Category("Parameters")] public int Range { get { return range; } set { range = Math.Max(1, value); } } /// /// [Description("1st ema smothing period. ( R )")] [Category("Parameters")] public int EMAPeriod1 { get { return emaperiod1; } set { emaperiod1 = Math.Max(1, value); } } /// /// [Description("2nd ema smoothing period. ( S )")] [Category("Parameters")] public int EMAPeriod2 { get { return emaperiod2; } set { emaperiod2 = Math.Max(1, value); } } /// /// [Description("SMI EMA smoothing period.")] [Category("Parameters")] public int SMIEMAPeriod { get { return smiemaperiod; } set { smiemaperiod = Math.Max(1, value); } } // Create our user definable color input [Description("Color for painted region")] [Category("Parameters")] public Color UpColor { get { return upColor; } set { upColor = value; } } // Serialize our Color object [Browsable(false)] public string UpColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(upColor); } set { upColor = NinjaTrader.Gui.Design.SerializableColor.FromString(value); } } // Create our user definable color input [Description("Color for painted region")] [Category("Parameters")] public Color DnColor { get { return dnColor; } set {dnColor = value; } } // Serialize our Color object [Browsable(false)] public string DnColorSerialize { get { return NinjaTrader.Gui.Design.SerializableColor.ToString(dnColor); } set { dnColor = NinjaTrader.Gui.Design.SerializableColor.FromString(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 SMI[] cacheSMI = null; private static SMI checkSMI = new SMI(); /// /// The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// /// public SMI SMI(Color dnColor, int eMAPeriod1, int eMAPeriod2, int range, int sMIEMAPeriod, Color upColor) { return SMI(Input, dnColor, eMAPeriod1, eMAPeriod2, range, sMIEMAPeriod, upColor); } /// /// The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// /// public SMI SMI(Data.IDataSeries input, Color dnColor, int eMAPeriod1, int eMAPeriod2, int range, int sMIEMAPeriod, Color upColor) { if (cacheSMI != null) for (int idx = 0; idx < cacheSMI.Length; idx++) if (cacheSMI[idx].DnColor == dnColor && cacheSMI[idx].EMAPeriod1 == eMAPeriod1 && cacheSMI[idx].EMAPeriod2 == eMAPeriod2 && cacheSMI[idx].Range == range && cacheSMI[idx].SMIEMAPeriod == sMIEMAPeriod && cacheSMI[idx].UpColor == upColor && cacheSMI[idx].EqualsInput(input)) return cacheSMI[idx]; lock (checkSMI) { checkSMI.DnColor = dnColor; dnColor = checkSMI.DnColor; checkSMI.EMAPeriod1 = eMAPeriod1; eMAPeriod1 = checkSMI.EMAPeriod1; checkSMI.EMAPeriod2 = eMAPeriod2; eMAPeriod2 = checkSMI.EMAPeriod2; checkSMI.Range = range; range = checkSMI.Range; checkSMI.SMIEMAPeriod = sMIEMAPeriod; sMIEMAPeriod = checkSMI.SMIEMAPeriod; checkSMI.UpColor = upColor; upColor = checkSMI.UpColor; if (cacheSMI != null) for (int idx = 0; idx < cacheSMI.Length; idx++) if (cacheSMI[idx].DnColor == dnColor && cacheSMI[idx].EMAPeriod1 == eMAPeriod1 && cacheSMI[idx].EMAPeriod2 == eMAPeriod2 && cacheSMI[idx].Range == range && cacheSMI[idx].SMIEMAPeriod == sMIEMAPeriod && cacheSMI[idx].UpColor == upColor && cacheSMI[idx].EqualsInput(input)) return cacheSMI[idx]; SMI indicator = new SMI(); indicator.BarsRequired = BarsRequired; indicator.CalculateOnBarClose = CalculateOnBarClose; #if NT7 indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256; indicator.MaximumBarsLookBack = MaximumBarsLookBack; #endif indicator.Input = input; indicator.DnColor = dnColor; indicator.EMAPeriod1 = eMAPeriod1; indicator.EMAPeriod2 = eMAPeriod2; indicator.Range = range; indicator.SMIEMAPeriod = sMIEMAPeriod; indicator.UpColor = upColor; Indicators.Add(indicator); indicator.SetUp(); SMI[] tmp = new SMI[cacheSMI == null ? 1 : cacheSMI.Length + 1]; if (cacheSMI != null) cacheSMI.CopyTo(tmp, 0); tmp[tmp.Length - 1] = indicator; cacheSMI = 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 { /// /// The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// /// [Gui.Design.WizardCondition("Indicator")] public Indicator.SMI SMI(Color dnColor, int eMAPeriod1, int eMAPeriod2, int range, int sMIEMAPeriod, Color upColor) { return _indicator.SMI(Input, dnColor, eMAPeriod1, eMAPeriod2, range, sMIEMAPeriod, upColor); } /// /// The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// /// public Indicator.SMI SMI(Data.IDataSeries input, Color dnColor, int eMAPeriod1, int eMAPeriod2, int range, int sMIEMAPeriod, Color upColor) { return _indicator.SMI(input, dnColor, eMAPeriod1, eMAPeriod2, range, sMIEMAPeriod, upColor); } } } // This namespace holds all strategies and is required. Do not change it. namespace NinjaTrader.Strategy { public partial class Strategy : StrategyBase { /// /// The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// /// [Gui.Design.WizardCondition("Indicator")] public Indicator.SMI SMI(Color dnColor, int eMAPeriod1, int eMAPeriod2, int range, int sMIEMAPeriod, Color upColor) { return _indicator.SMI(Input, dnColor, eMAPeriod1, eMAPeriod2, range, sMIEMAPeriod, upColor); } /// /// The Stochastic Momentum Index is made up of two lines that oscillate between a vertical scale of -100 to 100. /// /// public Indicator.SMI SMI(Data.IDataSeries input, Color dnColor, int eMAPeriod1, int eMAPeriod2, int range, int sMIEMAPeriod, Color upColor) { 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.SMI(input, dnColor, eMAPeriod1, eMAPeriod2, range, sMIEMAPeriod, upColor); } } } #endregion