#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
//repaired by Zondor 12/28/2012
namespace NinjaTrader.Indicator
{
[Description("Ehlers Phase Angle")]
public class Phase2 : Indicator
{
#region Variables
private int cyclePeriod = 15;
private DataSeries Phase;
private DataSeries Imag_part;
private DataSeries Real_part;
private double weight = 0;
private double _r_calc = 0;
private double _i_calc = 0;
private double rc=0;
private double ic=0;
private double prevInput;
private double TwoPi;
#endregion
protected override void OnStartUp()
{
TwoPi=2*Math.PI;
}
protected override void Initialize()
{
Add(new Plot(Color.FromKnownColor(KnownColor.OrangeRed), PlotStyle.Line, "PhaseLine"));
Add(new Line(Color.FromKnownColor(KnownColor.LightCoral), 0, "Zero"));
Add(new Line(Color.FromKnownColor(KnownColor.LightCoral), 180, "OneEighty"));
Add(new Line(Color.FromKnownColor(KnownColor.LightCoral), 360, "ThreeSixty"));
Overlay = false;
Phase = new DataSeries(this);
Imag_part = new DataSeries(this);
Real_part = new DataSeries(this);
CalculateOnBarClose=false;
PriceTypeSupported=true;
this.Name="Phase Indicator, per John Ehlers";
}
protected override void OnBarUpdate()
{
if (CurrentBar < (CyclePeriod + 1) || (!FirstTickOfBar&&prevInput==Input[0]) ) return; prevInput=Input[0];
if(FirstTickOfBar)
{
rc = 0; ic = 0;
for (int j = 1; j < CyclePeriod; j++)
{
weight = Input[j];
rc += Math.Cos((TwoPi) * j / CyclePeriod) * weight;
ic += Math.Sin((TwoPi) * j / CyclePeriod) * weight;
}
}
Real_part.Set(rc+ Input[0]);
Imag_part.Set(ic);
if (Math.Abs(Real_part[0]) > 0.001)
Phase.Set(Math.Atan(Imag_part[0] / Real_part[0]));
else
Phase.Set((Math.PI / 2) * Math.Sign(Imag_part[0]));
if (Real_part[0] < 0)
Phase.Set(Phase[0] + Math.PI);
Phase.Set(Phase[0] + Math.PI / 2);
if (Phase[0] < 0)
Phase.Set(Phase[0] + Math.PI * 2);
if (Phase[0] > Math.PI * 2)
Phase.Set(Phase[0] - Math.PI * 2);
// Convert radians to degrees
Phase.Set(Phase[0] * 180 / Math.PI);
PhaseLine.Set(Phase[0]);
}
#region Properties
[Browsable(false)]
[XmlIgnore()]
public DataSeries PhaseLine
{
get { return Values[0]; }
}
[Description("")]
[GridCategory("Parameters")]
public int CyclePeriod
{
get { return cyclePeriod; }
set { cyclePeriod = 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 Phase2[] cachePhase2 = null;
private static Phase2 checkPhase2 = new Phase2();
///
/// Ehlers Phase Angle
///
///
public Phase2 Phase2(int cyclePeriod)
{
return Phase2(Input, cyclePeriod);
}
///
/// Ehlers Phase Angle
///
///
public Phase2 Phase2(Data.IDataSeries input, int cyclePeriod)
{
if (cachePhase2 != null)
for (int idx = 0; idx < cachePhase2.Length; idx++)
if (cachePhase2[idx].CyclePeriod == cyclePeriod && cachePhase2[idx].EqualsInput(input))
return cachePhase2[idx];
lock (checkPhase2)
{
checkPhase2.CyclePeriod = cyclePeriod;
cyclePeriod = checkPhase2.CyclePeriod;
if (cachePhase2 != null)
for (int idx = 0; idx < cachePhase2.Length; idx++)
if (cachePhase2[idx].CyclePeriod == cyclePeriod && cachePhase2[idx].EqualsInput(input))
return cachePhase2[idx];
Phase2 indicator = new Phase2();
indicator.BarsRequired = BarsRequired;
indicator.CalculateOnBarClose = CalculateOnBarClose;
#if NT7
indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
indicator.MaximumBarsLookBack = MaximumBarsLookBack;
#endif
indicator.Input = input;
indicator.CyclePeriod = cyclePeriod;
Indicators.Add(indicator);
indicator.SetUp();
Phase2[] tmp = new Phase2[cachePhase2 == null ? 1 : cachePhase2.Length + 1];
if (cachePhase2 != null)
cachePhase2.CopyTo(tmp, 0);
tmp[tmp.Length - 1] = indicator;
cachePhase2 = 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
{
///
/// Ehlers Phase Angle
///
///
[Gui.Design.WizardCondition("Indicator")]
public Indicator.Phase2 Phase2(int cyclePeriod)
{
return _indicator.Phase2(Input, cyclePeriod);
}
///
/// Ehlers Phase Angle
///
///
public Indicator.Phase2 Phase2(Data.IDataSeries input, int cyclePeriod)
{
return _indicator.Phase2(input, cyclePeriod);
}
}
}
// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
public partial class Strategy : StrategyBase
{
///
/// Ehlers Phase Angle
///
///
[Gui.Design.WizardCondition("Indicator")]
public Indicator.Phase2 Phase2(int cyclePeriod)
{
return _indicator.Phase2(Input, cyclePeriod);
}
///
/// Ehlers Phase Angle
///
///
public Indicator.Phase2 Phase2(Data.IDataSeries input, int cyclePeriod)
{
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.Phase2(input, cyclePeriod);
}
}
}
#endregion