// TRIX public static void CalculateTRIX(out string key, out string key2, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period, int period2, out int offset, out int min, out int max, bool leverage = false) { min = int.MaxValue; max = int.MinValue; key = string.Format("TRIX({0}-{1})", period.ToString("00"), period2.ToString("00")); key2 = string.Format("TRIX-Smooth-({0}-{1})", period.ToString("00"), period2.ToString("00")); offset = 3 * (period > period2 ? period : period2); ExponentialMovingAverage ema1 = new ExponentialMovingAverage(period); ExponentialMovingAverage ema2 = new ExponentialMovingAverage(period); ExponentialMovingAverage ema3 = new ExponentialMovingAverage(period); ExponentialMovingAverage ema4 = new ExponentialMovingAverage(period2); double singleSmooth; double doubleSmooth; double tripleSmooth; double prevTriplesmooth = -1; double trix; int i = 0; foreach (StockPoint point in data) { ema1.AddValue(point.Close); if (i < period) { i++; } else { singleSmooth = ema1.MovingAverage; ema2.AddValue(singleSmooth); if (i < 2 * period) { i++; } else { doubleSmooth = ema2.MovingAverage; ema3.AddValue(doubleSmooth); if (i < 3 * period) { i++; } else { tripleSmooth = ema3.MovingAverage; if (prevTriplesmooth != -1) { trix = (double)decimal.Round((((decimal)tripleSmooth - (decimal)prevTriplesmooth) / (decimal)tripleSmooth) * 100 * (leverage ? 100 : 1), 4); ema4.AddValue(trix); AddValue(point.PointDateTime, key, trix, indicators); AddValue(point.PointDateTime, key2, ema4.MovingAverage, indicators); if (min > trix) min = (int)Math.Floor(trix); if (max < trix) max = (int)Math.Ceiling(trix); } prevTriplesmooth = tripleSmooth; } } } } }
// 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; } }
// MACD public static void CalculateMACD(out string key, out string key2, out double[] key3, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period1, int period2, int period3, out int offset, out int min, out int max) { min = int.MaxValue; max = int.MinValue; key = string.Format("MACD({0}-{1}-{2})", period1.ToString("00"), period2.ToString("00"), period3.ToString("00")); key2 = string.Format("MACD-SignalLine({0}-{1}-{2})", period1.ToString("00"), period2.ToString("00"), period3.ToString("00")); List<double> hist = new List<double>(); offset = (new List<int>(){period1, period2}.Max()) - 1; ExponentialMovingAverage ema1 = new ExponentialMovingAverage(period1); ExponentialMovingAverage ema2 = new ExponentialMovingAverage(period2); ExponentialMovingAverage ema3 = new ExponentialMovingAverage(period3); int i = 0; foreach(StockPoint point in data) { ema1.AddValue(point.Close); ema2.AddValue(point.Close); double EMA1 = ema1.MovingAverage; double EMA2 = ema2.MovingAverage; double MACDLine = EMA1 - EMA2; ema3.AddValue(MACDLine); if (i < offset) { i++; hist.Add(0); } else { double SignalLine = ema3.MovingAverage; if (min > MACDLine || min > SignalLine) { min = (int)(Math.Floor(MACDLine < SignalLine ? MACDLine : SignalLine)); } if (max < MACDLine || max < SignalLine) { max = (int)(Math.Ceiling(MACDLine > SignalLine ? MACDLine : SignalLine)); } AddValue(point.PointDateTime, key, MACDLine, indicators); AddValue(point.PointDateTime, key2, SignalLine, indicators); hist.Add(MACDLine - SignalLine); } } key3 = hist.ToArray(); }
// EMA /// <summary> /// Calculates the Exponential Moving Average 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 EMA with.</param> /// <param name="indicators">The mfvvalues needed to graph the EMA.</param> /// <param name="period">The number of days to average.</param> /// <param name="offset">Where to start the graph.</param> public static void CalculateEma(out string key, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period, out int offset) { key = "EMA(" + period.ToString("00") + ")"; ExponentialMovingAverage ema = new ExponentialMovingAverage(period); offset = period - 1; int i = 0; foreach (StockPoint point in data) { ema.AddValue(point.Close); if (i < offset) { i++; } else { AddValue(point.PointDateTime, key, ema.MovingAverage, indicators); } } }
// Chaikin Oscillator public static void CalculateChaikinOscillator(out string key, StockPoints data, Dictionary<DateTime, Dictionary<string, double>> indicators, int period1, int period2, out int offset, out int min, out int max) { key = string.Format("ChiOsc({0}:{1})", period1.ToString("00"), period2.ToString("00")); offset = (period2 > period1 ? period2 : period1) - 1; min = int.MaxValue; max = int.MinValue; // Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low) double mfm; // Money Flow Volume = Money Flow Multiplier x Volume for the Period double mfv; // ADL = Previous ADL + Current Period's Money Flow Volume double adl = 0D; // CHaikin Oscillator double co; ExponentialMovingAverage ema1 = new ExponentialMovingAverage(period1); ExponentialMovingAverage ema2 = new ExponentialMovingAverage(period2); int i = 0; foreach (StockPoint point in data) { mfm = ((point.Close - point.Low) - (point.High - point.Close)) / (point.High - point.Low == 0 ? 1 : point.High - point.Low); mfv = mfm * point.Volume; adl = adl + mfv; ema1.AddValue(adl); ema2.AddValue(adl); if (i < period2 - 1) { i++; } else { co = ema1.MovingAverage - ema2.MovingAverage; if (min > co) min = (int)Math.Floor(co); if (max < co) max = (int)Math.Ceiling(co); AddValue(point.PointDateTime, key, co, indicators); } } }