// Stochastic RSI public static void CalculateStochasticRSI(out string key, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period, out int offset, bool leverage = true) { key = string.Format("StocRSI({0})", period.ToString("00")); ExponentialMovingAverage gains = new ExponentialMovingAverage(period); ExponentialMovingAverage losses = new ExponentialMovingAverage(period); offset = period * 2; double rsi; double stochRSI; double highestRSI; double lowestRSI; Queue<double> rsiQueue = new Queue<double>(); StockPoint previousPoint = data[0]; int i = 0; foreach (StockPoint point in data.Skip(1)) { if (previousPoint.Close > point.Close) { losses.AddValue(previousPoint.Close - point.Close); gains.AddValue(0); } else if (previousPoint.Close < point.Close) { gains.AddValue(point.Close - previousPoint.Close); losses.AddValue(0); } if (i < period - 1) { i++; } else { rsi = 100 - (100 / (1 + (gains.MovingAverage / losses.MovingAverage))); rsiQueue.Enqueue(rsi); if (rsiQueue.Count > period) { rsiQueue.Dequeue(); } if (rsiQueue.Count == period) { highestRSI = rsiQueue.Max(); lowestRSI = rsiQueue.Min(); stochRSI = (rsi - lowestRSI) / (highestRSI - lowestRSI) * (leverage ? 100 : 1); AddValue(point.PointDateTime, key, stochRSI, indicators); } } previousPoint = point; } }
// RSI /// <summary> /// Calculates the Relative Strength Index and fills indicators with the data needed to graph it. /// </summary> /// <param name="key">Name of the set to put in the graph key</param> /// <param name="data">StockPoints to calculate the Relative Strength Index with.</param> /// <param name="indicators">The mfvvalues needed to graph the RSI.</param> /// <param name="period">The number of days gained/lost to consider.</param> /// <param name="offset">Where to start the graph.</param> public static void CalculateRsi(out string key, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period, out int offset) { key = "RSI(" + period.ToString("00") + ")"; ExponentialMovingAverage gains = new ExponentialMovingAverage(period); ExponentialMovingAverage losses = new ExponentialMovingAverage(period); offset = period; int i = 0; StockPoint previousPoint = data[0]; foreach (StockPoint point in data.Skip(1)) { if (previousPoint.Close > point.Close) { losses.AddValue(previousPoint.Close - point.Close); gains.AddValue(0); } else if (previousPoint.Close < point.Close) { gains.AddValue(point.Close - previousPoint.Close); losses.AddValue(0); } if (i < period - 1) { i++; } else { double rsi = 100 - (100 / (1 + (gains.MovingAverage / losses.MovingAverage))); AddValue(point.PointDateTime, key, rsi, indicators); } previousPoint = point; } }
// Full Stochastic /// <summary> /// Calculates the Full Stochastic Oscillator and fills indicators with the data needed to graph it. /// </summary> /// <param name="key">Name of the first set to put in the graph key</param> /// <param name="key2">Name of the second set to put in the graph key</param> /// <param name="data">StockPoints to calculate the Full Stochastic with.</param> /// <param name="indicators">The mfvvalues needed to graph the Full Stochastic.</param> /// <param name="period1">The number of period to calculate Fast Stochastic.</param> /// <param name="period2">The number of period to calculate SMA of Fast Stochastic.</param> /// <param name="period3">The number of period to calculate SMA of calculated SMA of Fast Stochastic.</param> /// <param name="offset">Where to start the graph.</param> public static void CalculateStochastic(out string key, out string key2, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period1, int period2, int period3, out int offset) { key = string.Format("Full STO %K({0}:{1})", period1.ToString("00"), period2.ToString("00")); key2 = string.Format("Full STO %D({0})", period3.ToString("00")); offset = period1 - 1; SimpleMovingAverage ksma = new SimpleMovingAverage(period2); SimpleMovingAverage dsma = new SimpleMovingAverage(period3); // lowest among the lowest for the chosen period double lowestLow; // highest among the highest for the chosen period double highestHigh; // Lowest Low = lowest low for the look-back period // Highest High = highest high for the look-back period // fastk = (Current Close - Lowest Low)/(Highest High - Lowest Low) * 100 double fastk; // fullk smoothed with X-period SMA double fullk; // X-period SMA of Full fullk double fulld; int i = 0; // loop through each stockpoint skipping the foreach (StockPoint point in data) { lowestLow = data.Skip(data.IndexOf(point) - (period1 - 1)).Take(period1).OrderBy(sp => sp.Low).FirstOrDefault().Low; highestHigh = data.Skip(data.IndexOf(point) - (period1 - 1)).Take(period1).OrderByDescending(sp => sp.High).FirstOrDefault().High; fastk = (point.Close - lowestLow) / (highestHigh - lowestLow == 0 ? 1 : highestHigh - lowestLow) * 100; ksma.AddValue(fastk); fullk = ksma.MovingAverage(); dsma.AddValue(fullk); fulld = dsma.MovingAverage(); if (i < period1 - 1) { i++; } else { AddValue(point.PointDateTime, key, fullk, indicators); AddValue(point.PointDateTime, key2, fulld, indicators); } } }
// Money Flow Index public static void CalculateMFI(out string key, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period, out int offset) { key = string.Format("MFI({0})", period.ToString("00")); offset = period; // Typical Price = (High + Low + Close)/3 double typicalPrice; // Raw Money Flow = Typical Price x Volume double rawMoneyFlow; // Money Flow Ratio = (x-period Positive Money Flow)/(x-period Negative Money Flow) double moneyFlowRatio; // Money Flow Index = 100 - 100/(1 + Money Flow Ratio) double moneyFlowIndex; double positiveMoneyFlow = 0D; double negativeMoneyFLow = 0D; Queue<double> moneyFlow = new Queue<double>(); double previousTipycalPrice = (data[0].Low + data[0].High + data[0].Close) / 3; int i = 0; foreach (StockPoint point in data.Skip(1)) { typicalPrice = (point.Low + point.High + point.Close) / 3; rawMoneyFlow = typicalPrice * point.Volume; moneyFlow.Enqueue(rawMoneyFlow * (typicalPrice >= previousTipycalPrice ? 1 : -1)); if(moneyFlow.Count > period) { moneyFlow.Dequeue(); } if (i < period - 1) { i++; } else { positiveMoneyFlow = moneyFlow.Where(v => v >= 0).Sum(); negativeMoneyFLow = Math.Abs(moneyFlow.Where(v => v < 0).Sum()); moneyFlowRatio = positiveMoneyFlow / negativeMoneyFLow; moneyFlowIndex = 100 - (100 / (1 + moneyFlowRatio)); AddValue(point.PointDateTime, key, moneyFlowIndex, indicators); } previousTipycalPrice = typicalPrice; } }