计算Aroon指标系列

时间:2015-04-20 12:26:43

标签: c# r indicator trading algorithmic-trading

我正在尝试建立一个类来创建Aroon系列。但似乎我不太了解这些步骤。我不确定我必须使用句点参数。

这是我的第一次尝试:

/// <summary>
/// Aroon
/// </summary>
public class Aroon : IndicatorCalculatorBase
{
    public override List<Ohlc> OhlcList { get; set; }
    public int Period { get; set; }

    public Aroon(int period) 
    {
        this.Period = period;
    }

    /// <summary>
    /// Aroon up: {((number of periods) - (number of periods since highest high)) / (number of periods)} x 100
    /// Aroon down: {((number of periods) - (number of periods since lowest low)) / (number of periods)} x 100
    /// </summary>
    /// <see cref="http://www.investopedia.com/ask/answers/112814/what-aroon-indicator-formula-and-how-indicator-calculated.asp"/>
    /// <returns></returns>
    public override IIndicatorSerie Calculate()
    {
        AroonSerie aroonSerie = new AroonSerie();

        int indexToProcess = 0;

        while (indexToProcess < this.OhlcList.Count)
        {
            List<Ohlc> tempOhlc = this.OhlcList.Skip(indexToProcess).Take(Period).ToList();
            indexToProcess += tempOhlc.Count;

            for (int i = 0; i < tempOhlc.Count; i++)
            {   
                int highestHighIndex = 0, lowestLowIndex = 0;
                double highestHigh = tempOhlc.Min(x => x.High), lowestLow = tempOhlc.Max(x => x.Low);
                for (int j = 0; j < i; j++)
                {
                    if (tempOhlc[j].High > highestHigh)
                    {
                        highestHighIndex = j;
                        highestHigh = tempOhlc[j].High;
                    }

                    if (tempOhlc[j].Low < lowestLow)
                    {
                        lowestLowIndex = j;
                        lowestLow = tempOhlc[j].Low;
                    }
                }

                int up = ((this.Period - (i - highestHighIndex)) / this.Period) * 100;
                aroonSerie.Up.Add(up);

                int down = ((this.Period - (i - lowestLowIndex)) / this.Period) * 100;
                aroonSerie.Down.Add(down);
            }
        }

        return aroonSerie;
   }
}

之前是否有其他人试图这样做?

这是我使用的csv文件:

https://drive.google.com/file/d/0Bwv_-8Q17wGaRDVCa2FhMWlyRUk/view

但Aroon上下结果设置与R的TTR包中的aroon函数结果不匹配。

table <- read.csv("table.csv", header = TRUE, sep = ",")
trend <- aroon(table[,c("High", "Low")], n=5)
View(trend)

R结果的屏幕截图:

enter image description here

提前致谢,

3 个答案:

答案 0 :(得分:2)

@anilca, 为了完整的披露,我学到了很多东西来回答你的问题(我对Finetec一无所知......)。谢谢!这是一次有趣的经历!

您的实施中存在几个问题:

  1. 在陈述中:
  2.   

    i - highestHighIndex

      

    i - lowestLowIndex

    变量&#34; i&#34;小于或等于highestHighIndex,lowestLowIndex 所以声明:

      

    this.Period - (i - highestHighIndex)

      

    this.Period - (i - lowestLowIndex)

    将返回错误的值(大部分时间......)

    1. Aroon上下都是百分比,因此&#34; int&#34;是一个错误的数据结构。

    2. 因为所有变量都在:

    3.   

      (this.Period - (i - highestHighIndex))/ this.Period)

        

      ((this.Period - (i - lowestLowIndex))/ this.Period)

      是您赢得的正确值的整数。

      1. 你的excel中的数字还有一个从最新到最旧的排序。(它对R包的影响)
      2. 我已根据您的代码(以及您的数据订单......)实施了算法

        public class Aroon : IndicatorCalculatorBase
        {
        
            public override List<OhlcSample> OhlcList { get; set; }
            private readonly int _period;
        
            public int Period
            {
                get { return _period; }
            }
        
            public Aroon(int period)
            {
                _period = period;
            }
        
            public override IIndicatorSerie Calculate()
            {
                var aroonSerie = new AroonSerie();
                for (var i = _period; i < OhlcList.Count; i++)
                {
        
                    var aroonUp = CalculateAroonUp(i);
                    var aroonDown = CalculateAroonDown(i);
        
                    aroonSerie.Down.Add(aroonDown);
                    aroonSerie.Up.Add(aroonUp);
                }
        
                return aroonSerie;
            }
        
            private double CalculateAroonUp(int i)
            {
                var maxIndex = FindMax(i - _period, i);
        
                var up = CalcAroon(i - maxIndex);
        
                return up;
            }
        
            private double CalculateAroonDown(int i)
            {
                var minIndex = FindMin(i - _period, i);
        
                var down = CalcAroon(i - minIndex);
        
                return down;
            }
        
            private double CalcAroon(int numOfDays)
            {
                var result = ((_period - numOfDays)) * ((double)100 / _period);
                return result;
            }
        
            private int FindMin(int startIndex, int endIndex)
            {
                var min = double.MaxValue;
                var index = startIndex;
                for (var i = startIndex; i <= endIndex; i++)
                {
                    if (min < OhlcList[i].Low)
                        continue;
        
                    min = OhlcList[i].Low;
                    index = i;
                }
                return index;
            }
        
            private int FindMax(int startIndex, int endIndex)
            {
                var max = double.MinValue;
                var index = startIndex;
                for (var i = startIndex; i <= endIndex; i++)
                {
                    if (max > OhlcList[i].High)
                        continue;
        
                    max = OhlcList[i].High;
                    index = i;
                }
                return index;
            }
        }
        
        public abstract class IndicatorCalculatorBase
        {
            public abstract List<OhlcSample> OhlcList { get; set; }
        
            public abstract IIndicatorSerie Calculate();
        }
        
        public interface IIndicatorSerie
        {
            List<double> Up { get; }
            List<double> Down { get; }
        }
        
        internal class AroonSerie : IIndicatorSerie
        {
            public List<double> Up { get; private set; }
            public List<double> Down { get; private set; }
        
            public AroonSerie()
            {
                Up = new List<double>();
                Down = new List<double>();
            }
        
        
        }
        
        public class OhlcSample
        {
        
            public double High { get; private set; }
            public double Low { get; private set; }
        
            public OhlcSample(double high, double low)
            {
                High = high;
                Low = low;
            }
        
        }
        

        使用此测试方法进行调试:

            private Aroon _target;
        
            [TestInitialize]
            public void TestInit()
            {
                _target=new Aroon(5)
                {
                    OhlcList = new List<OhlcSample>
                    {
                        new OhlcSample(166.90, 163.65),
                        new OhlcSample(165.00, 163.12),
                        new OhlcSample(165.91, 163.21),
                        new OhlcSample(167.29, 165.11),
                        new OhlcSample(169.99, 166.84),
                        new OhlcSample(170.92, 167.90),
                        new OhlcSample(168.47, 165.90),
                        new OhlcSample(167.75, 165.75),
                        new OhlcSample(166.14, 161.89),
                        new OhlcSample(164.77, 161.44),
                        new OhlcSample(163.19, 161.49),
                        new OhlcSample(162.50, 160.95),
                        new OhlcSample(163.25, 158.84),
                        new OhlcSample(159.20, 157.00),
                        new OhlcSample(159.33, 156.14),
                        new OhlcSample(160.00, 157.00),
                        new OhlcSample(159.35, 158.07),
                        new OhlcSample(160.70, 158.55),
                        new OhlcSample(160.90, 157.66),
                        new OhlcSample(164.38, 158.45),
                        new OhlcSample(167.75, 165.70),
                        new OhlcSample(168.93, 165.60),
                        new OhlcSample(165.73, 164.00),
                        new OhlcSample(167.00, 164.66),
                        new OhlcSample(169.35, 165.01),
                        new OhlcSample(168.12, 164.65),
                        new OhlcSample(168.89, 165.79),
                        new OhlcSample(168.65, 165.57),
                        new OhlcSample(170.85, 166.00),
                        new OhlcSample(171.61, 169.10)
                    }
                };
            }
        
        
            [TestMethod]
            public void JustToHelpYou()
            {
                var result = _target.Calculate();
        
                var expectedUp = new List<double>()
                {
                    100,80,60,40,20,0,0,0, 0,0,40,20,0,100,100,100,100,80, 60,100,80,60,40,100,100
                };
        
                var expectedDown = new List<double>
                {
                    20,0,0,100,100,80,100,100,100,100,80,60,40,20,0,0,40,20,0,0,40,20,0,40,20
                };
        
                Assert.IsTrue( result.Up.SequenceEqual(expectedUp));
                Assert.IsTrue( result.Down.SequenceEqual(expectedDown));
        
            }
        

答案 1 :(得分:0)

只需从代码中添加方法HighestBarNum和LowestBarnum的实现

 public class Aroon 
{  
    public bool AroonDown
    {
        get;
        set;
    }
    public double Period
    {
        get;
        set;
    }
    public Aroon()
    {
    }
    public IList<double> Execute(IList<double> src)
    {
        if (!this.AroonDown)
        {
            return this.ExecuteUp(src);
        }
        return this.ExecuteDown(src);
    }
    public IList<double> ExecuteDown(IList<double> src)
    {
        double[] period = new double[src.Count];
        for (int i = 1; i < src.Count; i++)
        {
            double num = LowestBarNum(src, i, Period);
            period[i] = 100 * (Period - num) / Period;
        }
        return period;
    }
    public IList<double> ExecuteUp(IList<double> src)
    {
        double[] period = new double[src.Count];
        for (int i = 1; i < src.Count; i++)
        {
            double num = HighestBarNum(src, i, Period);
            period[i] = 100 * ((Period - num) / Period;
        }
        return period;
    }}

答案 2 :(得分:0)

class AroonData
{
    public double AroonUp;

    public double AroonDown;
}

计算类:

class AroonCalculationData
{
    public double PeriodHigh;

    public double PeriodLow;

    public double SetAroonUp(List<MarketData> period, double lastHigh)
    {

        /*reverse the set so we can look at it from the current tick
        on back, and ticksSinceHigh will set correctly*/
        period.Reverse();

        int ticksSinceHigh = 0;
        double high = 0.0;//Set 0 so anything will be higher

        for (int i = 0; i < period.Count; i++)
        {
            if (period[i].high > high)
            {
                high = period[i].high;
                ticksSinceHigh = i;
            }
        }

        /*This bit if for if the high just ticked out
        of List<MarketData>.
        Including the current tick (i = 0), List<MarketData> period
        only looks back (period - 1) days. 
        This Checks to see if the last high is still in the set. if it's 
        not, and is still the high for the period, then ticksSinceHigh
        is set to (period)*/
        PeriodHigh = high;
        if (PeriodHigh < lastHigh)
        {
            ticksSinceHigh = period.Count;
        }

        /*Aroon-Up Formula*/
        return (double)(period.Count - ticksSinceHigh ) / (double)period.Count * 100.0;
    }

    //ASIDE FROM LOOKING FOR LOWS INSTEAD OF HIGHS, SAME AS AROON-UP
    public double SetAroonDown(List<MarketData> period, double lastLow)
    {

        period.Reverse();

        int daysSinceLow = 0;
        double low = double.MaxValue;//Set max so anything will be lower

        for (int i = 0; i < period.Count; i++)
        {
            if (period[i].low < low)
            {
                low = period[i].low;
                daysSinceLow = i;
            }
        }

        PeriodLow = low;
        if (PeriodLow > lastLow)
        {
            daysSinceLow = period.Count;
        }

        return (double)(period.Count - daysSinceLow) / (double)period.Count * 100.0;
    }
}

致电代码:

public AroonData[] Aroon(List<MarketData> marketData, int period)
{
    AroonCalculationData[] calculationData = new AroonCalculationData[marketData.Count]
    AroonData[] aroon= new AroonData[marketData.Count]

    for (int i = period; i < marketData.Count; i++)
    {
        /*GetRange(i - period + 1, period) add 1 so that the current tick is 
        included in look back.
        For example, if (period = 10) the first loop (i = 10) then (i - 
        period + 1) = 1 the set will be marketData 1 - 10.*/

        /*calculationData[i - 1].PeriodHigh and calculationData[i - 1].PeriodLow
        are for looking back at the last tick's look back period high and 
        low*/

        data[i].AroonUp = calculationData[i].SetAroonUp(marketData.GetRange(i - period + 1, period), calculationData[i - 1].PeriodHigh);
        data[i].AroonDown = calculationData[i].SetAroonDown(marketData.GetRange(i - period + 1, period), calculationData[i - 1].PeriodLow);
    }
}

旁注: 我遇到的一个问题是将我的数据与TD Ameritrades Aroon进行比较,直到我发现它们的周期确实是1期,所以如果你要与TD比较,请记住这一点。