如何正确计算Fisher变换指标

时间:2019-05-12 00:32:45

标签: c# technical-indicator

我正在写一个小的技术分析库,其中包含TA-lib中不可用的项目。我从在cTrader上找到的示例开始,并将其与TradingView版本中的代码进行了匹配。

这是TradingView中的 Pine脚本代码:

len = input(9, minval=1, title="Length")

high_ = highest(hl2, len)
low_ = lowest(hl2, len)

round_(val) => val > .99 ? .999 : val < -.99 ? -.999 : val

value = 0.0
value := round_(.66 * ((hl2 - low_) / max(high_ - low_, .001) - .5) + .67 * nz(value[1]))

fish1 = 0.0
fish1 := .5 * log((1 + value) / max(1 - value, .001)) + .5 * nz(fish1[1])

fish2 = fish1[1]

这是我我尝试执行的指标:

    public class FisherTransform : IndicatorBase
    {
        public int Length = 9;

        public decimal[] Fish { get; set; }
        public decimal[] Trigger { get; set; }

        decimal _maxHigh;
        decimal _minLow;

        private decimal _value1;
        private decimal _lastValue1;

        public FisherTransform(IEnumerable<Candle> candles, int length) 
            : base(candles)
        {
            Length = length;
            RequiredCount = Length;
            _lastValue1 = 1;
        }

        protected override void Initialize()
        {
            Fish = new decimal[Series.Length];
            Trigger = new decimal[Series.Length];
        }

        public override void Compute(int startIndex = 0, int? endIndex = null)
        {
            if (endIndex == null)
                endIndex = Series.Length;

            for (int index = 0; index < endIndex; index++)
            {
                if (index == 1)
                {
                    Fish[index - 1] = 1;
                }

                _minLow = Series.Average.Lowest(Length, index);
                _maxHigh = Series.Average.Highest(Length, index);

                _value1 = Maths.Normalize(0.66m * ((Maths.Divide(Series.Average[index] - _minLow, Math.Max(_maxHigh - _minLow, 0.001m)) - 0.5m) + 0.67m * _lastValue1));

                _lastValue1 = _value1;

                Fish[index] = 0.5m * Maths.Log(Maths.Divide(1 + _value1, Math.Max(1 - _value1, .001m))) + 0.5m * Fish[index - 1];
                Trigger[index] = Fish[index - 1];
            }
        }
    }

IndicatorBase class and CandleSeries class

Math Helpers

问题

输出值似乎在预期范围内,但是我的Fisher转换交叉 与我在TradingView版本的指标上看到的不匹配。

问题

如何在C#中正确实现Fisher变换指示器?我希望这与TradingView的Fisher转换输出相匹配。

我所知道的

我已经根据我个人编写的其他指标以及TA-Lib的指标检查了我的数据,这些指标通过了单元测试。我还按照蜡烛对TradingView数据进行了蜡烛检查,发现我的数据符合预期。所以我不怀疑我的数据是问题所在。

具体

CSV Data - NFLX 5 min agg

下图是上面显示的应用于TradingView图表的Fisher转换代码。我的目标是尽可能匹配此输出。

enter image description here

渔夫 青色 触发 洋红色

预期输出:

交叉在美国东部时间15:30完成

  • 大约Fisher值是2.86

  • 大约触发值为1.79

交叉在美国东部时间10:45完成

  • 大约Fisher值是-3.67

  • 大约触发值是-3.10

我的实际输出:

交叉在美国东部时间15:30完成

  • 我的Fisher值是1.64

  • 我的触发值是1.99

交叉在美国东部时间10:45完成

  • 我的Fisher值是-1.63

  • 我的触发值是-2.00

赏金

  

为了简化您的生活,我提供了一个小型控制台应用程序   通过和失败的单元测试的完成。所有单元测试都是   针对同一数据集进行。通过单元测试来自   经过测试的工作 简单移动平均线指标。失败的单位   测试是否与有问题的 Fisher Transform 指示器相符。

Project Files (更新5/14)

帮助我的FisherTransform测试通过,我将颁发赏金。

enter image description here

仅在需要任何其他资源或信息时发表评论。

我会考虑的替代答案

  • 使用C#提交自己工作的FisherTransform

  • 解释为什么我的FisherTransform实际上按预期工作

1 个答案:

答案 0 :(得分:5)

该代码有两个错误。

1)错误的额外括号。正确的行是:

_value1 = Maths.Normalize(0.66m * (Maths.Divide(Series.Average[index] - _minLow, Math.Max(_maxHigh - _minLow, 0.001m)) - 0.5m) + 0.67m * _lastValue1);

2)最小和最大函数必须为:

public static decimal Highest(this decimal[] series, int length, int index)
{
    var maxVal = series[index]; // <----- HERE WAS AN ERROR!

    var lookback = Math.Max(index - length, 0);

    for (int i = index; i-- > lookback;)
        maxVal = Math.Max(series[i], maxVal);

    return maxVal;
}

public static decimal Lowest(this decimal[] series, int length, int index)
{
    var minVal = series[index]; // <----- HERE WAS AN ERROR!

    var lookback = Math.Max(index - length, 0);

    for (int i = index; i-- > lookback;)
    {
        //if (series[i] != 0) // <----- HERE WAS AN ERROR!
            minVal = Math.Min(series[i], minVal);
    }

    return minVal;
}

3)混淆测试参数。请重新检查您的单元测试值。更新测试之后仍未修复。例如,第一个FisherTransforms_ValuesAreReasonablyClose_First()具有混合值

var fish = result.Fish.Last(); //is equal to -3.1113144510775780365063063706
var trig = result.Trigger.Last(); //is equal to -3.6057793808025449204415435710

// TradingView Values for NFLX 5m chart at 10:45 ET
var fisherValue = -3.67m;
var triggerValue = -3.10m;