public static void UpdateEma(Guid eventActionId) { using (var db = new PoloniexContext()) { var eventAction = db.EventActions.Include(x => x.MovingAverageEventAction).Single(x => x.EventActionId == eventActionId); var closingValue = db.CurrencyDataPoints .Where(x => x.CurrencyPair == eventAction.MovingAverageEventAction.CurrencyPair) .OrderByDescending(x => x.ClosingDateTime) .First(); var prevEma = db.MovingAverages .Where(x => x.MovingAverageType == eventAction.MovingAverageEventAction.MovingAverageType && x.CurrencyPair == eventAction.MovingAverageEventAction.CurrencyPair && x.Interval == eventAction.MovingAverageEventAction.Interval && x.MinutesPerInterval == eventAction.MovingAverageEventAction.MinutesPerInterval) .OrderByDescending(x => x.ClosingDateTime) .First(); // -15 seconds to account for timer skew if (closingValue.ClosingDateTime >= prevEma.ClosingDateTime.AddSeconds(-15).AddMinutes(prevEma.MinutesPerInterval)) { var curEma = new MovingAverage() { MovingAverageType = MovingAverageType.ExponentialMovingAverage, CurrencyPair = eventAction.MovingAverageEventAction.CurrencyPair, Interval = eventAction.MovingAverageEventAction.Interval, MinutesPerInterval = eventAction.MovingAverageEventAction.MinutesPerInterval, ClosingDateTime = DateTime.UtcNow, MovingAverageValue = MovingAverageCalculations.CalculateEma(closingValue.ClosingValue, prevEma.MovingAverageValue, eventAction.MovingAverageEventAction.Interval), LastClosingValue = closingValue.ClosingValue }; db.MovingAverages.Add(curEma); db.SaveChanges(); } } }
/* additional helpers */ public static void BackFillEma(string currencyPair, int interval, int minutesPerInterval, DateTime beginDateTime, DateTime endDateTime, decimal?prevEmaSeed = null) { // add time buffer to guarantee beginDate inclusive / endDate exclusive var delEndDateTime = endDateTime.AddSeconds(30); var delBeginDateTime = beginDateTime.AddSeconds(30); List <CurrencyDataPoint> dataPoints; List <decimal> smaInput; decimal prevEma; using (var db = new PoloniexContext()) { var delMovingAverages = db.MovingAverages .Where(x => x.CurrencyPair == currencyPair && x.Interval == interval && x.MinutesPerInterval == minutesPerInterval && x.ClosingDateTime <= delBeginDateTime && x.ClosingDateTime >= delEndDateTime); db.MovingAverages.RemoveRange(delMovingAverages); db.SaveChanges(); dataPoints = db.CurrencyDataPoints .Where(x => x.CurrencyPair == currencyPair && x.ClosingDateTime <= beginDateTime && x.ClosingDateTime >= endDateTime) .ToList(); if (prevEmaSeed == null) { smaInput = db.CurrencyDataPoints .Where(x => x.CurrencyPair == currencyPair && x.ClosingDateTime < endDateTime) .OrderBy(x => x.ClosingDateTime) .Select(x => x.ClosingValue) .Take(interval) .ToList(); prevEma = MovingAverageCalculations.CalculateSma(smaInput); } else { prevEma = prevEmaSeed.Value; } } // Begin calculating List <MovingAverage> movingAveragesData = new List <MovingAverage>(); for (int i = 0; i < dataPoints.Count; i++) { if (i % minutesPerInterval == 0) { var newMovingAverage = new MovingAverage() { MovingAverageType = MovingAverageType.ExponentialMovingAverage, CurrencyPair = currencyPair, Interval = interval, MinutesPerInterval = minutesPerInterval, ClosingDateTime = dataPoints[i].ClosingDateTime, MovingAverageValue = MovingAverageCalculations.CalculateEma(dataPoints[i].ClosingValue, prevEma, interval), LastClosingValue = dataPoints[i].ClosingValue }; movingAveragesData.Add(newMovingAverage); prevEma = newMovingAverage.MovingAverageValue; } } BulkInsertMovingAverages(movingAveragesData); }