private static void CalcPmoSignal( List <PmoResult> results, int timePeriod, int smoothingPeriod, int signalPeriod) { decimal signalConstant = 2m / (signalPeriod + 1); decimal?lastSignal = null; int startIndex = timePeriod + smoothingPeriod + signalPeriod - 1; for (int i = startIndex - 1; i < results.Count; i++) { PmoResult pr = results[i]; int index = i + 1; if (index > startIndex) { pr.Signal = (pr.Pmo - lastSignal) * signalConstant + lastSignal; } else if (index == startIndex) { decimal sumPmo = 0; for (int p = index - signalPeriod; p < index; p++) { PmoResult d = results[p]; sumPmo += (decimal)d.Pmo; } pr.Signal = sumPmo / signalPeriod; } lastSignal = pr.Signal; } }
// PRICE MOMENTUM OSCILLATOR (PMO) public static IEnumerable <PmoResult> GetPmo( IEnumerable <Quote> history, int timePeriod = 35, int smoothingPeriod = 20, int signalPeriod = 10) { // clean quotes history = Cleaners.PrepareHistory(history); // check parameters ValidatePmo(history, timePeriod, smoothingPeriod, signalPeriod); // initialize List <PmoResult> results = CalcPmoRocEma(history, timePeriod); decimal smoothingConstant = 2m / smoothingPeriod; decimal? lastPmo = null; // calculate PMO int startIndex = timePeriod + smoothingPeriod; for (int i = startIndex - 1; i < results.Count; i++) { PmoResult pr = results[i]; if (pr.Index > startIndex) { pr.Pmo = (pr.RocEma - lastPmo) * smoothingConstant + lastPmo; } else if (pr.Index == startIndex) { decimal sumRocEma = 0; for (int p = pr.Index - smoothingPeriod; p < pr.Index; p++) { PmoResult d = results[p]; sumRocEma += (decimal)d.RocEma; } pr.Pmo = sumRocEma / smoothingPeriod; } lastPmo = pr.Pmo; } // add Signal CalcPmoSignal(results, timePeriod, smoothingPeriod, signalPeriod); return(results); }
private static List <PmoResult> CalcPmoRocEma <TQuote>( IEnumerable <TQuote> history, int timePeriod) where TQuote : IQuote { // initialize decimal smoothingMultiplier = 2m / timePeriod; decimal? lastRocEma = null; List <RocResult> roc = GetRoc(history, 1).ToList(); List <PmoResult> results = new List <PmoResult>(); int startIndex = timePeriod + 1; for (int i = 0; i < roc.Count; i++) { RocResult r = roc[i]; int index = i + 1; PmoResult result = new PmoResult { Date = r.Date }; if (index > startIndex) { result.RocEma = r.Roc * smoothingMultiplier + lastRocEma * (1 - smoothingMultiplier); } else if (index == startIndex) { decimal sumRoc = 0; for (int p = index - timePeriod; p < index; p++) { RocResult d = roc[p]; sumRoc += (decimal)d.Roc; } result.RocEma = sumRoc / timePeriod; } lastRocEma = result.RocEma; result.RocEma *= 10; results.Add(result); } return(results); }
// RATE OF CHANGE (PMO) public static IEnumerable <PmoResult> GetPmo( IEnumerable <Quote> history, int timePeriod = 35, int smoothingPeriod = 20, int signalPeriod = 10) { // clean quotes Cleaners.PrepareHistory(history); // check parameters ValidatePmo(history, timePeriod, smoothingPeriod, signalPeriod); // initialize List <PmoResult> results = new List <PmoResult>(); List <RocResult> roc = GetRoc(history, 1).ToList(); int startIndex = 0; decimal smoothingMultiplier = 2m / timePeriod; decimal smoothingConstant = 2m / smoothingPeriod; decimal signalConstant = 2m / (signalPeriod + 1); decimal?lastRocEma = null; decimal?lastPmo = null; decimal?lastSignal = null; // get ROC EMA variant startIndex = timePeriod + 1; for (int i = 0; i < roc.Count; i++) { RocResult r = roc[i]; PmoResult result = new PmoResult { Index = r.Index, Date = r.Date }; if (r.Index > startIndex) { result.RocEma = r.Roc * smoothingMultiplier + lastRocEma * (1 - smoothingMultiplier); } else if (r.Index == startIndex) { result.RocEma = roc .Where(x => x.Index > r.Index - timePeriod && x.Index <= r.Index) .ToList() .Select(x => x.Roc) .Average(); } lastRocEma = result.RocEma; result.RocEma *= 10; results.Add(result); } // calculate PMO startIndex = timePeriod + smoothingPeriod; for (int i = startIndex - 1; i < results.Count; i++) { PmoResult p = results[i]; if (p.Index > startIndex) { p.Pmo = (p.RocEma - lastPmo) * smoothingConstant + lastPmo; } else if (p.Index == startIndex) { p.Pmo = results .Where(x => x.Index > p.Index - smoothingPeriod && x.Index <= p.Index) .ToList() .Select(x => x.RocEma) .Average(); } lastPmo = p.Pmo; } // add Signal startIndex = timePeriod + smoothingPeriod + signalPeriod - 1; for (int i = startIndex - 1; i < results.Count; i++) { PmoResult p = results[i]; if (p.Index > startIndex) { p.Signal = (p.Pmo - lastSignal) * signalConstant + lastSignal; } else if (p.Index == startIndex) { p.Signal = results .Where(x => x.Index > p.Index - signalPeriod && x.Index <= p.Index) .ToList() .Select(x => x.Pmo) .Average(); } lastSignal = p.Signal; } return(results); }