-
Notifications
You must be signed in to change notification settings - Fork 2
/
FisherTransform.cs
142 lines (130 loc) · 5.55 KB
/
FisherTransform.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* 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;
namespace QuantConnect.Indicators
{
/// <summary>
/// The Fisher transform is a mathematical process which is used to convert any data set to a modified
/// data set whose Probabilty Distrbution Function is approximately Gaussian. Once the Fisher transform
/// is computed, the transformed data can then be analyzed in terms of it's deviation from the mean.
///
/// The equation is y = .5 * ln [ 1 + x / 1 - x ] where
/// x is the input
/// y is the output
/// ln is the natural logarithm
///
/// The Fisher transform has much sharper turning points than other indicators such as MACD
///
/// For more info, read chapter 1 of Cybernetic Analysis for Stocks and Futures by John F. Ehlers
///
/// We are implementing the lastest version of this indicator found at Fig. 4 of
/// http://www.mesasoftware.com/papers/UsingTheFisherTransform.pdf
///
/// </summary>
public class FisherTransform : BarIndicator
{
private double _alpha;
private double _previous;
private readonly Minimum _medianMin;
private readonly Maximum _medianMax;
/// <summary>
/// Initializes a new instance of the FisherTransform class with the default name and period
/// </summary>
/// <param name="period">The period of the WMA</param>
public FisherTransform(int period)
: this("FISH_" + period, period)
{
}
/// <summary>
/// A Fisher Transform of Prices
/// </summary>
/// <param name="name">string - the name of the indicator</param>
/// <param name="period">The number of periods for the indicator</param>
public FisherTransform(string name, int period)
: base(name)
{
_alpha = .33;
// Initialize the local variables
_medianMax = new Maximum("MedianMax", period);
_medianMin = new Minimum("MedianMin", period);
}
/// <summary>
/// Gets a flag indicating when this indicator is ready and fully initialized
/// </summary>
public override bool IsReady
{
get { return _medianMax.IsReady && _medianMax.IsReady; }
}
/// <summary>
/// Computes the next value in the transform.
/// value1 is a function used to normalize price withing the last _period day range.
/// value1 is centered on its midpoint and then doubled so that value1 wil swing between -1 and +1.
/// value1 is also smoothed with an exponential moving average whose alpha is 0.33.
///
/// Since the smoothing may allow value1 to exceed the _period day price range, limits are introduced to
/// preclude the transform from blowing up by having an input larger than unity.
/// </summary>
/// <param name="input">IndicatorDataPoint - the time and value of the next price</param>
/// <returns></returns>
protected override decimal ComputeNextValue(IBaseDataBar input)
{
var x = 0.0;
var y = 0.0;
var price = (input.Low + input.High) / 2m;
_medianMin.Update(input.Time, price);
_medianMax.Update(input.Time, price);
if (!IsReady) return 0;
var minL = _medianMin.Current.Value;
var maxH = _medianMax.Current.Value;
if (minL != maxH)
{
x = _alpha * 2 * ((double)((price - minL) / (maxH - minL)) - .5) + (1 - _alpha) * _previous;
y = FisherTransformFunction(x);
}
_previous = x;
return Convert.ToDecimal(y) + .5m * Current.Value;
}
/// <summary>
/// The Fisher transform is a mathematical process which is used to convert any data set to a modified
/// data set whose Probabilty Distrbution Function is approximately Gaussian. Once the Fisher transform
/// is computed, the transformed data can then be analyzed in terms of it's deviation from the mean.
///
/// The equation is y = .5 * ln [ 1 + x / 1 - x ] where
/// x is the input
/// y is the output
/// ln is the natural logarithm
///
/// The Fisher transform has much sharper turning points than other indicators such as MACD
///
/// For more info, read chapter 1 of Cybernetic Analysis for Stocks and Futures by John F. Ehlers
/// </summary>
/// <param name="x">Input</param>
/// <returns>Output</returns>
private double FisherTransformFunction(double x)
{
if (x > .99)
{
x = .999;
}
if (x < -.99)
{
x = -.999;
}
return .5 * Math.Log((1.0 + x) / (1.0 - x));
}
}
}