Hi,
I'm trying to create an indicator based on the paper of John Ehler, but something is wrong, since I'm getting values above 1 and below 0, but I would expect it to range between 0 and 1. If you have any tips to provide... Thanks
/*
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using QuantConnect.Data.Market;
using System;
using System.Linq;
namespace QuantConnect.Indicators
{
/// <summary>
/// The Fractal Adaptive Moving Average (FRAMA) by John Ehlers
/// </summary>
public class RFSTO : BarIndicator
{
int _n = 16;
int bars = 48;
RollingWindow<double> _HighPass;
RollingWindow<double> _Close;
RollingWindow<double> _Filt;
RollingWindow<double> _Stoc;
RollingWindow<double> _MyStochastic;
/// <summary>
/// Initializes a new instance of the average class
/// </summary>
/// <param name="name">The name of the indicator instance</param>
/// <param name="n">The window period (must be even). Example value: 16</param>
/// <param name="longPeriod">The average period. Example value: 198</param>
public RFSTO(string name, int period)
: base(name)
{
_n = period;
_HighPass = new RollingWindow<double>(3);
_Stoc = new RollingWindow<double>(3);
_MyStochastic = new RollingWindow<double>(3);
_Close = new RollingWindow<double>(3);
_Filt = new RollingWindow<double>(period);
}
/// <summary>
/// Initializes a new instance of the average class
/// </summary>
/// <param name="n">The window period (must be even). Example value: 16</param>
public RFSTO(int n)
: this("RFSTO" + n, n)
{
}
/// <summary>
/// Computes the average value
/// </summary>
/// <param name="input">The data for the calculation</param>
/// <returns>The average value</returns>
protected override decimal ComputeNextValue(IBaseDataBar input)
{
if (!_Close.IsReady)
{
_Close.Add((double)input.Close);
_HighPass.Add((double)0);
_Filt.Add((double)0);
return 0;
}
double alpha1, HighPass, a1, b1, c1, c2, c3, Stoc, MyStochastic, Filt;
//Higass filter cyclic components whose periods are shorter than 48 bars
alpha1 = (Math.Cos(.707*360 / bars) + Math.Sin (.707*360 / bars) - 1) / Math.Cos(.707*360 / bars);
HighPass = (1 - alpha1 / 2)*(1 - alpha1 / 2)*((double)input.Close - 2 *_Close[1] + _Close[2]) + 2*(1 - alpha1)*_HighPass[1] - (1 - alpha1)*(1 - alpha1)*_HighPass[2];
//Smooth with a Super Smoother Filter
a1 = Math.Exp(-1.414*3.14159 / 10);
b1 = 2*a1*Math.Cos(1.414*180 / 10);
c2 = b1;
c3 = -a1*a1;
c1 = 1 - c2 - c3;
Filt = c1*(HighPass + _HighPass[1]) / 2 + c2*_Filt[1] + c3*_Filt[2];
double HighestC = Math.Max(Filt,_Filt.Max());
double LowestC = Math.Min(Filt,_Filt.Min());
Stoc = (Filt - LowestC) / (HighestC - LowestC);
_Filt.Add(Filt);
_HighPass.Add(HighPass);
_Close.Add((double)input.Close);
_Stoc.Add(Stoc);
if (!_MyStochastic.IsReady)
{
_MyStochastic.Add(Stoc);
return (decimal)0;
}
MyStochastic = c1*(Stoc + _Stoc[1]) / 2 + c2*_MyStochastic[1] + c3*_MyStochastic[2];
_MyStochastic.Add(MyStochastic);
return (decimal)MyStochastic;
}
/// <summary>
/// Returns whether the indicator will return valid results
/// </summary>
public override bool IsReady
{
get { return _MyStochastic.IsReady; }
}
/// <summary>
/// Resets the average to its initial state
/// </summary>
public override void Reset()
{
_HighPass.Reset();
_Close.Reset();
_Filt.Reset();
_Stoc.Reset();
_MyStochastic.Reset();
base.Reset();
}
}
}