using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums; using KLHZ.Trader.Core.Math.Common; namespace KLHZ.Trader.Core.Math.Declisions.Utils { public static class MovingAverage { private static (DateTime time, float value) CalcTimeWindowAverageValue(DateTime[] timestamps, float[] values, int window, int shift = 0) { var sum = values[values.Length - 1 - shift]; var count = 1; var startTime = timestamps[timestamps.Length - 1 - shift]; for (int i = 2; i < values.Length && startTime - timestamps[values.Length - i - shift] < TimeSpan.FromSeconds(window); i++) { sum += values[values.Length - i - shift]; count++; } return (startTime, sum / count); } public static TradingEvent CheckByWindowAverageMean(DateTime[] timestamps, float[] prices, int size, float meanfullStep = 3f) { var twav15s = new float[size]; var twav120s = new float[size]; var times = new DateTime[size]; var res = TradingEvent.None; for (int shift = 0; shift < size; shift++) { var twav15 = CalcTimeWindowAverageValue(timestamps, prices, 15, shift); var twav120 = CalcTimeWindowAverageValue(timestamps, prices, 120, shift); twav15s[size - 1 - shift] = twav15.value; twav120s[size - 1 - shift] = twav120.value; times[size - 1 - shift] = twav120.time; if (System.Math.Abs(twav120.value - prices[prices.Length - 1]) > 3 * meanfullStep) { res |= TradingEvent.StopBuy; return res; } if (shift > 0) { var isCrossing = Lines.IsLinesCrossing( times[size - 1 - shift], times[size - 2 - shift], twav15s[size - 1 - shift], twav15s[size - 2 - shift], twav120s[size - 1 - shift], twav120s[size - 2 - shift]); if (shift == 1 && !isCrossing) //если нет пересечения скользящих средний с окном 120 и 15 секунд между //текущей и предыдущей точкой - можно не продолжать выполнение. { break; } if (shift > 1 && isCrossing) { // если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта if (twav120s[size - 1] <= twav15s[size - 1] && twav120s[size - 2] > twav15s[size - 2]) { if (twav15s[size - 1 - shift] - twav15s[size - 1] >= meanfullStep) { res |= TradingEvent.LongOpen; res |= TradingEvent.ShortClose; break; } } // если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта if (twav15s[size - 1] <= twav120s[size - 1] && twav15s[size - 2] > twav120s[size - 2]) { if (twav15s[size - 1 - shift] - twav15s[size - 1] <= -meanfullStep) { res |= TradingEvent.LongClose; res |= TradingEvent.ShortOpen; break; } } } } } return res; } } }