Пример #1
0
        private static List <ConnorsRsiResult> CalcConnorsRsiBaseline(
            List <BasicData> bdList, int rsiPeriod, int rankPeriod)
        {
            // initialize
            List <RsiResult> rsiResults = CalcRsi(bdList, rsiPeriod).ToList();

            int size = bdList.Count;
            List <ConnorsRsiResult> results = new List <ConnorsRsiResult>(size);

            decimal?[] gain = new decimal?[size];

            decimal?lastClose = null;
            decimal streak    = 0;

            // compose interim results
            for (int i = 0; i < size; i++)
            {
                BasicData h     = bdList[i];
                int       index = i + 1;

                ConnorsRsiResult result = new ConnorsRsiResult
                {
                    Date     = h.Date,
                    RsiClose = rsiResults[i].Rsi
                };

                // bypass for first record
                if (lastClose == null)
                {
                    lastClose = h.Value;
                    results.Add(result);
                    continue;
                }

                // streak of up or down
                if (h.Value == lastClose)
                {
                    streak = 0;
                }
                else if (h.Value > lastClose)
                {
                    if (streak >= 0)
                    {
                        streak++;
                    }
                    else
                    {
                        streak = 1;
                    }
                }
                else // h.Value < lastClose
                {
                    if (streak <= 0)
                    {
                        streak--;
                    }
                    else
                    {
                        streak = -1;
                    }
                }

                result.Streak = streak;

                // percentile rank
                gain[i] = (lastClose == 0) ? null
                    : (decimal)((lastClose <= 0) ? null : (h.Value - lastClose) / lastClose);

                results.Add(result);

                if (index > rankPeriod)
                {
                    int qty = 0;
                    for (int p = index - rankPeriod - 1; p < index; p++)
                    {
                        if (gain[p] < gain[i])
                        {
                            qty++;
                        }
                    }

                    result.PercentRank = 100m * qty / rankPeriod;
                }


                lastClose = h.Value;
            }

            return(results);
        }
Пример #2
0
        private static IEnumerable <RsiResult> CalcRsi(IEnumerable <BasicData> basicData, int lookbackPeriod = 14)
        {
            // clean data
            List <BasicData> bdList = Cleaners.PrepareBasicData(basicData).ToList();

            // check parameters
            ValidateRsi(basicData, lookbackPeriod);

            // initialize
            decimal          lastValue = bdList[0].Value;
            List <RsiResult> results   = new List <RsiResult>();

            // load gain data
            for (int i = 0; i < bdList.Count; i++)
            {
                BasicData h = bdList[i];

                RsiResult result = new RsiResult
                {
                    Index = (int)h.Index,
                    Date  = h.Date,
                    Gain  = (h.Value > lastValue) ? h.Value - lastValue : 0,
                    Loss  = (h.Value < lastValue) ? lastValue - h.Value : 0
                };
                results.Add(result);

                lastValue = h.Value;
            }

            // initialize average gain
            decimal avgGain = results.Where(x => x.Index <= lookbackPeriod).Select(g => g.Gain).Average();
            decimal avgLoss = results.Where(x => x.Index <= lookbackPeriod).Select(g => g.Loss).Average();

            // initial first record
            decimal lastRSI = (avgLoss > 0) ? 100 - (100 / (1 + (avgGain / avgLoss))) : 100;

            RsiResult first = results.Where(x => x.Index == lookbackPeriod + 1).FirstOrDefault();

            first.Rsi = lastRSI;

            // calculate RSI
            foreach (RsiResult r in results.Where(x => x.Index > (lookbackPeriod + 1)))
            {
                avgGain = (avgGain * (lookbackPeriod - 1) + r.Gain) / lookbackPeriod;
                avgLoss = (avgLoss * (lookbackPeriod - 1) + r.Loss) / lookbackPeriod;

                if (avgLoss > 0)
                {
                    decimal rs = avgGain / avgLoss;
                    r.Rsi = 100 - (100 / (1 + rs));
                }
                else
                {
                    r.Rsi = 100;
                }

                lastRSI = (decimal)r.Rsi;
            }

            return(results);
        }
Пример #3
0
        // PRICE VOLUME OSCILLATOR (PVO)
        /// <include file='./info.xml' path='indicator/*' />
        ///
        public static IEnumerable <PvoResult> GetPvo <TQuote>(
            IEnumerable <TQuote> history,
            int fastPeriod   = 12,
            int slowPeriod   = 26,
            int signalPeriod = 9)
            where TQuote : IQuote
        {
            // convert history to basic format
            List <BasicData> bdList = history.ConvertToBasic("V");

            // check parameter arguments
            ValidatePvo(history, fastPeriod, slowPeriod, signalPeriod);

            // initialize
            List <EmaResult> emaFast = CalcEma(bdList, fastPeriod).ToList();
            List <EmaResult> emaSlow = CalcEma(bdList, slowPeriod).ToList();

            int size = bdList.Count;
            List <BasicData> emaDiff = new List <BasicData>();
            List <PvoResult> results = new List <PvoResult>(size);

            // roll through history
            for (int i = 0; i < size; i++)
            {
                BasicData h  = bdList[i];
                EmaResult df = emaFast[i];
                EmaResult ds = emaSlow[i];

                PvoResult result = new PvoResult
                {
                    Date = h.Date
                };

                if (df?.Ema != null && ds?.Ema != null)
                {
                    decimal?pvo = (ds.Ema != 0) ?
                                  100 * (df.Ema - ds.Ema) / ds.Ema : null;

                    result.Pvo = pvo;

                    // temp data for interim EMA of PVO
                    BasicData diff = new BasicData
                    {
                        Date  = h.Date,
                        Value = (decimal)pvo
                    };

                    emaDiff.Add(diff);
                }

                results.Add(result);
            }

            // add signal and histogram to result
            List <EmaResult> emaSignal = CalcEma(emaDiff, signalPeriod).ToList();

            for (int d = slowPeriod - 1; d < size; d++)
            {
                PvoResult r  = results[d];
                EmaResult ds = emaSignal[d + 1 - slowPeriod];

                r.Signal    = ds.Ema;
                r.Histogram = r.Pvo - r.Signal;
            }

            return(results);
        }
Пример #4
0
        private static IEnumerable <RsiResult> CalcRsi(List <BasicData> bdList, int lookbackPeriod)
        {
            // check parameter arguments
            ValidateRsi(bdList, lookbackPeriod);

            // initialize
            decimal lastValue = bdList[0].Value;
            decimal avgGain   = 0m;
            decimal avgLoss   = 0m;

            int size = bdList.Count;
            List <RsiResult> results = new(size);

            decimal[] gain = new decimal[size]; // gain
            decimal[] loss = new decimal[size]; // loss

            // roll through history
            for (int i = 0; i < bdList.Count; i++)
            {
                BasicData h     = bdList[i];
                int       index = i + 1;

                RsiResult r = new()
                {
                    Date = h.Date
                };
                results.Add(r);

                gain[i]   = (h.Value > lastValue) ? h.Value - lastValue : 0;
                loss[i]   = (h.Value < lastValue) ? lastValue - h.Value : 0;
                lastValue = h.Value;

                // calculate RSI
                if (index > lookbackPeriod + 1)
                {
                    avgGain = (avgGain * (lookbackPeriod - 1) + gain[i]) / lookbackPeriod;
                    avgLoss = (avgLoss * (lookbackPeriod - 1) + loss[i]) / lookbackPeriod;

                    if (avgLoss > 0)
                    {
                        decimal rs = avgGain / avgLoss;
                        r.Rsi = 100 - (100 / (1 + rs));
                    }
                    else
                    {
                        r.Rsi = 100;
                    }
                }

                // initialize average gain
                else if (index == lookbackPeriod + 1)
                {
                    decimal sumGain = 0;
                    decimal sumLoss = 0;

                    for (int p = 1; p <= lookbackPeriod; p++)
                    {
                        sumGain += gain[p];
                        sumLoss += loss[p];
                    }
                    avgGain = sumGain / lookbackPeriod;
                    avgLoss = sumLoss / lookbackPeriod;

                    r.Rsi = (avgLoss > 0) ? 100 - (100 / (1 + (avgGain / avgLoss))) : 100;
                }
            }

            return(results);
        }
Пример #5
0
        // MOVING AVERAGE CONVERGENCE/DIVERGENCE (MACD) OSCILLATOR
        /// <include file='./info.xml' path='indicator/*' />
        ///
        public static IEnumerable <MacdResult> GetMacd <TQuote>(
            this IEnumerable <TQuote> history,
            int fastPeriod   = 12,
            int slowPeriod   = 26,
            int signalPeriod = 9)
            where TQuote : IQuote
        {
            // convert history to basic format
            List <BasicData> bdList = history.ConvertToBasic("C");

            // check parameter arguments
            ValidateMacd(history, fastPeriod, slowPeriod, signalPeriod);

            // initialize
            List <EmaResult> emaFast = CalcEma(bdList, fastPeriod).ToList();
            List <EmaResult> emaSlow = CalcEma(bdList, slowPeriod).ToList();

            int size = bdList.Count;
            List <BasicData>  emaDiff = new();
            List <MacdResult> results = new(size);

            // roll through history
            for (int i = 0; i < size; i++)
            {
                BasicData h  = bdList[i];
                EmaResult df = emaFast[i];
                EmaResult ds = emaSlow[i];

                MacdResult result = new()
                {
                    Date = h.Date
                };

                if (df?.Ema != null && ds?.Ema != null)
                {
                    decimal macd = (decimal)df.Ema - (decimal)ds.Ema;
                    result.Macd = macd;

                    // temp data for interim EMA of macd
                    BasicData diff = new()
                    {
                        Date  = h.Date,
                        Value = macd
                    };

                    emaDiff.Add(diff);
                }

                results.Add(result);
            }

            // add signal and histogram to result
            List <EmaResult> emaSignal = CalcEma(emaDiff, signalPeriod).ToList();

            for (int d = slowPeriod - 1; d < size; d++)
            {
                MacdResult r  = results[d];
                EmaResult  ds = emaSignal[d + 1 - slowPeriod];

                r.Signal    = ds.Ema;
                r.Histogram = r.Macd - r.Signal;
            }

            return(results);
        }