public void Removed() { int lookbackPeriods = 14; List <MfiResult> results = quotes.GetMfi(lookbackPeriods) .RemoveWarmupPeriods() .ToList(); // assertions Assert.AreEqual(502 - 14, results.Count); MfiResult last = results.LastOrDefault(); Assert.AreEqual(39.9494m, Math.Round((decimal)last.Mfi, 4)); }
public void Standard() { int lookbackPeriods = 14; List <MfiResult> results = quotes.GetMfi(lookbackPeriods).ToList(); // assertions // proper quantities // should always be the same number of results as there is quotes Assert.AreEqual(502, results.Count); Assert.AreEqual(488, results.Where(x => x.Mfi != null).Count()); // sample values MfiResult r1 = results[439]; Assert.AreEqual(69.0622m, Math.Round((decimal)r1.Mfi, 4)); MfiResult r2 = results[501]; Assert.AreEqual(39.9494m, Math.Round((decimal)r2.Mfi, 4)); }
public void GetMfiTest() { int lookbackPeriod = 14; IEnumerable <MfiResult> results = Indicator.GetMfi(history, lookbackPeriod); // assertions // proper quantities // should always be the same number of results as there is history Assert.AreEqual(502, results.Count()); Assert.AreEqual(502 - lookbackPeriod, results.Where(x => x.Mfi != null).Count()); // sample values MfiResult r1 = results.Where(x => x.Index == 502).FirstOrDefault(); Assert.AreEqual(39.9494m, Math.Round((decimal)r1.Mfi, 4)); MfiResult r2 = results.Where(x => x.Index == 440).FirstOrDefault(); Assert.AreEqual(69.0622m, Math.Round((decimal)r2.Mfi, 4)); }
public void GetMfiSmall() { int lookbackPeriod = 4; List <MfiResult> results = Indicator.GetMfi(history, lookbackPeriod).ToList(); // assertions // proper quantities // should always be the same number of results as there is history Assert.AreEqual(502, results.Count); Assert.AreEqual(502 - lookbackPeriod, results.Where(x => x.Mfi != null).Count()); // sample values MfiResult r1 = results[31]; Assert.AreEqual(100m, Math.Round((decimal)r1.Mfi, 4)); MfiResult r2 = results[43]; Assert.AreEqual(0m, Math.Round((decimal)r2.Mfi, 4)); }
// MONEY FLOW INDEX /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <MfiResult> GetMfi <TQuote>( this IEnumerable <TQuote> quotes, int lookbackPeriods = 14) where TQuote : IQuote { // convert quotes List <QuoteD> quotesList = quotes.ConvertToList(); // check parameter arguments ValidateMfi(lookbackPeriods); // initialize int length = quotesList.Count; List <MfiResult> results = new(length); double[] tp = new double[length]; // true price double[] mf = new double[length]; // raw MF value int[] direction = new int[length]; // direction double?prevTP = null; // roll through quotes, to get preliminary data for (int i = 0; i < quotesList.Count; i++) { QuoteD q = quotesList[i]; MfiResult result = new() { Date = q.Date }; // true price tp[i] = (q.High + q.Low + q.Close) / 3; // raw money flow mf[i] = tp[i] * q.Volume; // direction if (prevTP == null || tp[i] == prevTP) { direction[i] = 0; } else if (tp[i] > prevTP) { direction[i] = 1; } else if (tp[i] < prevTP) { direction[i] = -1; } results.Add(result); prevTP = tp[i]; } // add money flow index for (int i = lookbackPeriods; i < results.Count; i++) { MfiResult r = results[i]; int index = i + 1; double sumPosMFs = 0; double sumNegMFs = 0; for (int p = index - lookbackPeriods; p < index; p++) { if (direction[p] == 1) { sumPosMFs += mf[p]; } else if (direction[p] == -1) { sumNegMFs += mf[p]; } } // handle no negative case if (sumNegMFs == 0) { r.Mfi = 100; continue; } // calculate MFI normally decimal mfRatio = (decimal)(sumPosMFs / sumNegMFs); r.Mfi = 100 - (100 / (1 + mfRatio)); } return(results); }