C# 如何正确计算Fisher变换指标

C# 如何正确计算Fisher变换指标,c#,technical-indicator,C#,Technical Indicator,我正在编写一个小型的技术分析库,其中包含在TA库中不可用的项。我从我在上找到的一个示例开始,并将其与TradingView版本中的代码相匹配 以下是TradingView的Pine脚本代码: len = input(9, minval=1, title="Length") high_ = highest(hl2, len) low_ = lowest(hl2, len) round_(val) => val > .99 ? .999 : val < -.

我正在编写一个小型的技术分析库,其中包含在TA库中不可用的项。我从我在上找到的一个示例开始,并将其与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]
len=input(9,minval=1,title=“Length”)
高=最高(hl2,len)
低=最低(hl2,len)
圆形(val)=>val>0.99。999:val<-0.99?-。999:val
值=0.0
值:=四舍五入(.66*((hl2-低值)/max(高值-低值,.001)-.5)+.67*nz(值[1]))
鱼1=0.0
fish1:=.5*log((1+值)/max(1-值,.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];
            }
        }
    }
公共类FisherTransform:IndicatorBase
{
公共整数长度=9;
公共十进制[]Fish{get;set;}
公共十进制[]触发器{get;set;}
十进制最大值;
十进制_minLow;
私有十进制_值1;
私有十进制_lastValue1;
公共鱼类转移(IEnumerable烛光,整数长度)
:底座(蜡烛)
{
长度=长度;
所需计数=长度;
_lastValue1=1;
}
受保护的覆盖无效初始化()
{
Fish=新的十进制[系列.长度];
触发器=新的十进制[系列.长度];
}
公共覆盖无效计算(int startIndex=0,int?endIndex=null)
{
if(endIndex==null)
endIndex=系列长度;
对于(int index=0;index

问题

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

问题

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

我所知道的

我已经对照我个人编写的其他指标和TA库中的指标检查了我的数据,这些指标通过了我的单元测试。我还逐个检查了我的数据与TradingView数据,发现我的数据与预期相符。所以我不怀疑我的数据是个问题

细节

下图是应用于TradingView图表的上述Fisher变换代码。我的目标是尽可能接近这个输出

Fisher青色 触发洋红色

预期产出:

美国东部时间15:30完成渡线

  • 费希尔近似值为2.86

  • 大约触发值为1.79

美国东部时间10:45完成渡线

  • 费希尔近似值为-3.67

  • 大约触发值为-3.10

我的实际输出:

美国东部时间15:30完成渡线

  • 我的Fisher值是1.64

  • 我的触发值是1.99

美国东部时间10:45完成渡线

  • 我的Fisher值是-1.63

  • 我的触发值是-2.00

赏金 为了让您的生活更轻松,我提供了一个小型控制台应用程序 完成通过和失败的单元测试。所有单元测试都是 根据相同的数据集进行。通过的单元测试来自 测试工作简单移动平均值指标。失败的单位 测试针对所讨论的Fisher变换指标

(2014年5月更新)

帮助我通过鱼类转化测试,我将奖励奖金。

如果您需要任何其他资源或信息,只需发表评论即可

我将考虑的备选答案

  • 用C语言提交您自己的工作转换#

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


该代码有两个错误

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;
}

那么,我们如何测试我们是否正确?我们如何知道它是否符合您的规格?如果它符合TradingView的输出,我们将获得金牌@他们普遍认为您需要更多地考虑这一点,TradingViews的实现有可能是不正确的,而且我们没有可匹配的测试数据,只有一个答案,您测试它并告诉我们这不起作用,结果失败了。我的意思是,这可能永远持续下去。我同意“将军”的说法,我不止一次地发现了这一点。他们的商业模式主要依赖于用户提供的、可能未经验证的公式。为了进行比较,请在我的开源.NET库中查看的实现。我在GitHub回购协议中包含了手动计算以进行比较。我将在这里简要介绍一下。单元测试值源自操作图中圆圈所示的TradingView指示器。FisherTransform信号是基于交叉创建的。我的目标是使这些交叉点合理地接近我在TradingView上看到的,这应该是可能的,因为我们使用与T相同的计算
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;