Lin Reg Slope w/ Exp Weighting
#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;
#endregion
// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
/// <summary>
/// Linear regression slope - w/ exponential weighting option
/// </summary>
[Description("Linear regression slope - w/ exponential weighting option")]
public class mlLinRegSlope : Indicator
{
#region Variables
// Wizard generated variables
private int period = 8; // Default setting for Period
private bool exponential = false; // Default setting for Exponential
private int returnval = 0; // Default setting for returnval
// exponential moving regression slope variables
private int nn = 0;
private double n, w, sumX, sumX2, sumY1, sumXY1, correction;
// super fast linear regression slope variables
private double m1, m2, sumP, sumIP;
// public results, updated each bar
public double slope, yvalue, err;
#endregion
/// <summary>
/// This method is used to configure the indicator and is called once before any bar data is loaded.
/// </summary>
protected override void Initialize()
{
Add(new Plot(Color.FromKnownColor(KnownColor.MediumBlue), PlotStyle.Line, "SlopeSFX"));
Add(new Line(Color.FromKnownColor(KnownColor.DarkOliveGreen), 0, "Zero"));
CalculateOnBarClose = true;
Overlay = false;
PriceTypeSupported = true;
}
/// <summary>
/// Called on each bar update event (incoming tick)
/// </summary>
protected override void OnBarUpdate()
{
double rtn;
int ix;
if (exponential) {
// Super optimised calulations. very fast.
double denom, sumY = 0.0, sumXY = 0.0;
if (period != nn || CurrentBar < 1) {
nn = period;
n = (nn-1.0)*0.75 + 1.0;
sumX = 0.5 * n*(n-1.0);
sumX2 = (n-1.0)*n*(2.0*n-1.0)/6.0;
sumY = Input[0] * n;
sumXY = sumX*Input[0];
w = 2.0 / (n + 1.0);
correction = (n+1.0) / (3.0*n);
if (CurrentBar < 1) {
sumY1 = sumY;
sumXY1 = sumXY;
}
} else {
sumY = w*Input[0]*n + (1.0-w)*sumY1;
sumXY = Input[0]*(n-1.0) + sumXY1*(n-2.0)/n;
sumY1 = sumY;
sumXY1 = sumXY;
}
denom = n*sumX2 - sumX*sumX;
if (denom < 0.00001) denom = 0.00001;
slope = correction * n*(n*sumXY - sumX*sumY) / denom;
yvalue = sumY/n + slope * 0.5*n;
}
else {
int ix1;
if (CurrentBar < period || nn != period || CurrentBar % 10000 == 0) {
nn = period;
m1 = 6.0 / ((double)period * ((double)period + 1.0));
m2 = 2.0 / ((double)period - 1.0);
sumP = 0.0; sumIP = 0.0;
for (ix = 0; ix < period; ++ix) {
ix1 = (ix < CurrentBar) ? ix : CurrentBar;
sumP += Input[ix1];
sumIP += (ix1 * Input[ix1]);
}
} else {
sumIP += (sumP - period * Input[period]);
sumP += (Input[0] - Input[period]);
}
slope = m1 * (sumP - m2 * sumIP);
yvalue = sumP/period + slope * period * 0.5;
}
switch (returnval) {
case 3:
rtn = 0.0;
if (CurrentBar > 1) {
for (ix = 0; ix < ((CurrentBar <= period) ? CurrentBar+1 : period); ++ix) {
rtn = (Input[ix] - (-slope * ix + yvalue));
err += rtn*rtn;
}
rtn = err = Math.Sqrt(err/ix);
}
break;
case 2: rtn = yvalue; break;
default: rtn = slope; break;
}
SlopeSFX.Set(rtn); // result
}
#region Properties
[Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
[XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
public DataSeries SlopeSFX
{
get { return Values[0]; }
}
[Description("Lookback interval")]
[Category("Parameters")]
public int Period
{
get { return period; }
set { period = Math.Max(1, value); }
}
[Description("true=exponential moving slope, false=normal weighting")]
[Category("Parameters")]
public bool Exponential
{
get { return exponential; }
set { exponential = value; }
}
[Description("Return value 1=slope, 2=LinReg value, 3=average error")]
[Category("Parameters")]
public int Returnval
{
get { return returnval; }
set { returnval = Math.Max(1, 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 mlLinRegSlope[] cachemlLinRegSlope = null;
private static mlLinRegSlope checkmlLinRegSlope = new mlLinRegSlope();
/// <summary>
/// Linear regression slope - super fast calc with exponential weighting option
/// </summary>
/// <returns></returns>
public mlLinRegSlope mlLinRegSlope(bool exponential, int period, int returnval)
{
return mlLinRegSlope(Input, exponential, period, returnval);
}
/// <summary>
/// Linear regression slope - super fast calc with exponential weighting option
/// </summary>
/// <returns></returns>
public mlLinRegSlope mlLinRegSlope(Data.IDataSeries input, bool exponential, int period, int returnval)
{
if (cachemlLinRegSlope != null)
for (int idx = 0; idx < cachemlLinRegSlope.Length; idx++)
if (cachemlLinRegSlope[idx].Exponential == exponential && cachemlLinRegSlope[idx].Period == period && cachemlLinRegSlope[idx].Returnval == returnval && cachemlLinRegSlope[idx].EqualsInput(input))
return cachemlLinRegSlope[idx];
lock (checkmlLinRegSlope)
{
checkmlLinRegSlope.Exponential = exponential;
exponential = checkmlLinRegSlope.Exponential;
checkmlLinRegSlope.Period = period;
period = checkmlLinRegSlope.Period;
checkmlLinRegSlope.Returnval = returnval;
returnval = checkmlLinRegSlope.Returnval;
if (cachemlLinRegSlope != null)
for (int idx = 0; idx < cachemlLinRegSlope.Length; idx++)
if (cachemlLinRegSlope[idx].Exponential == exponential && cachemlLinRegSlope[idx].Period == period && cachemlLinRegSlope[idx].Returnval == returnval && cachemlLinRegSlope[idx].EqualsInput(input))
return cachemlLinRegSlope[idx];
mlLinRegSlope indicator = new mlLinRegSlope();
indicator.BarsRequired = BarsRequired;
indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
indicator.Input = input;
indicator.Exponential = exponential;
indicator.Period = period;
indicator.Returnval = returnval;
Indicators.Add(indicator);
indicator.SetUp();
mlLinRegSlope[] tmp = new mlLinRegSlope[cachemlLinRegSlope == null ? 1 : cachemlLinRegSlope.Length + 1];
if (cachemlLinRegSlope != null)
cachemlLinRegSlope.CopyTo(tmp, 0);
tmp[tmp.Length - 1] = indicator;
cachemlLinRegSlope = 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
{
/// <summary>
/// Linear regression slope - super fast calc with exponential weighting option
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition("Indicator")]
public Indicator.mlLinRegSlope mlLinRegSlope(bool exponential, int period, int returnval)
{
return _indicator.mlLinRegSlope(Input, exponential, period, returnval);
}
/// <summary>
/// Linear regression slope - super fast calc with exponential weighting option
/// </summary>
/// <returns></returns>
public Indicator.mlLinRegSlope mlLinRegSlope(Data.IDataSeries input, bool exponential, int period, int returnval)
{
return _indicator.mlLinRegSlope(input, exponential, period, returnval);
}
}
}
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
/// <summary>
/// Linear regression slope - super fast calc with exponential weighting option
/// </summary>
/// <returns></returns>
[Gui.Design.WizardCondition("Indicator")]
public Indicator.mlLinRegSlope mlLinRegSlope(bool exponential, int period, int returnval)
{
return _indicator.mlLinRegSlope(Input, exponential, period, returnval);
}
/// <summary>
/// Linear regression slope - super fast calc with exponential weighting option
/// </summary>
/// <returns></returns>
public Indicator.mlLinRegSlope mlLinRegSlope(Data.IDataSeries input, bool exponential, int period, int returnval)
{
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.mlLinRegSlope(input, exponential, period, returnval);
}
}
}
#endregion