klhztrader/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs

219 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
{
internal static (DateTime time, decimal value) CalcTimeWindowAverageValue(DateTime[] timestamps, decimal[] values, int window, int shift = 0)
{
var sum = values[values.Length - 1 - shift];
var count = 1m;
var startTime = timestamps[timestamps.Length - 1 - shift];
for (int i = 2; i + shift < values.Length
&& startTime - timestamps[values.Length - i - shift] < TimeSpan.FromSeconds(window); i++)
{
var k = values.Length - i - shift;
sum += values[values.Length - i - shift];
count++;
}
return (startTime, sum / count);
}
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean(DateTime[] timestamps,
decimal[] prices, int size, int smallWindow, int bigWindow, TimeSpan timeForUptreandStart,
decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m)
{
var res = TradingEvent.None;
var bigWindowAv = 0m;
var smallWindowAv = 0m;
var s = 0;
var pricesForFinalComparison = new decimal[size];
var twavss = new decimal[size];
var twavbs = new decimal[size];
var times = new DateTime[size];
var crossings = new List<int>();
for (int shift = 0; shift < size - 1 && shift < prices.Length - 1; shift++)
{
s = shift;
var i2 = size - 1 - shift;
var i1 = size - 2 - shift;
var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift);
var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift);
pricesForFinalComparison[i2] = prices[prices.Length - 1 - shift];
if (shift == 0)
{
bigWindowAv = twavb.value;
smallWindowAv = twavs.value;
}
twavss[i2] = twavs.value;
twavbs[i2] = twavb.value;
times[i2] = twavb.time;
if (shift > 0)
{
var isCrossing = Lines.IsLinesCrossing(
times[i1 + 1],
times[i2 + 1],
twavss[i1 + 1],
twavss[i2 + 1],
twavbs[i1 + 1],
twavbs[i2 + 1]);
if (shift == 1 && !isCrossing.res) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
//текущей и предыдущей точкой - можно не продолжать выполнение.
{
break;
}
if (isCrossing.res)
{
crossings.Add(i2);
if (crossings.Count == 6 || (shift + 1 == size - 1 || shift + 1 == prices.Length - 1))
{
if ((shift + 1 == size - 1 || shift + 1 == prices.Length - 1))
{
crossings.Add(shift);
}
var diffTotal = pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]];
for (int crossingShift = 1; crossingShift < crossings.Count - 2; crossingShift++)
{
var diff = pricesForFinalComparison[crossings[crossingShift]] - pricesForFinalComparison[crossings[crossingShift + 1]];
if (diff >= -0.5m)
{
diffTotal += diff;
}
else
{
break;
}
}
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
{
if (diffTotal >= uptrendEndingDetectionMeanfullStep
&& times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart)
{
res |= TradingEvent.CloseLong;
}
break;
}
}
if (crossings.Count == 2 || (shift + 1 == size - 1 || shift + 1 == prices.Length - 1))
{
if ((shift + 1 == size - 1 || shift + 1 == prices.Length - 1))
{
crossings.Add(shift);
}
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2])
{
if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] <= uptrendStartingDetectionMeanfullStep
&& times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart)
{
res |= TradingEvent.OpenLong;
}
break;
}
}
}
}
}
return (res, bigWindowAv, smallWindowAv);
}
public static (TradingEvent events, decimal bigWindowAv, decimal smallWindowAv) CheckByWindowAverageMean2(DateTime[] timestamps,
decimal[] prices, int size, int smallWindow, int bigWindow,
decimal? uptrendStartingDetectionMeanfullStep = null, decimal? uptrendEndingDetectionMeanfullStep = null)
{
var res = TradingEvent.None;
var bigWindowAv = 0m;
var smallWindowAv = 0m;
var s = 0;
var pricesForFinalComparison = new decimal[size];
var timesForFinalComparison = new DateTime[size];
var twavss = new decimal[size];
var twavbs = new decimal[size];
var times = new DateTime[size];
var crossings = new List<int>();
var crossingValues = new List<decimal>();
for (int shift = 0; shift < size - 1 && shift < prices.Length - 1; shift++)
{
s = shift;
var i2 = size - 1 - shift;
var i1 = size - 2 - shift;
var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift);
var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift);
pricesForFinalComparison[i2] = prices[prices.Length - 1 - shift];
timesForFinalComparison[i2] = timestamps[prices.Length - 1 - shift];
if (shift == 0)
{
bigWindowAv = twavb.value;
smallWindowAv = twavs.value;
}
twavss[i2] = twavs.value;
twavbs[i2] = twavb.value;
times[i2] = twavb.time;
if (shift > 0)
{
var isCrossing = Lines.IsLinesCrossing(
times[i1 + 1],
times[i2 + 1],
twavss[i1 + 1],
twavss[i2 + 1],
twavbs[i1 + 1],
twavbs[i2 + 1]);
if (shift == 1 && !isCrossing.res) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
//текущей и предыдущей точкой - можно не продолжать выполнение.
{
break;
}
if (isCrossing.res)
{
crossings.Add(i2);
crossingValues.Add(isCrossing.y);
if (crossings.Count == 2)
{
var dt = timesForFinalComparison[crossings[0]] - timesForFinalComparison[crossings[1]];
var d1 = pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]];
var d2 = crossingValues[0] - crossingValues[1];
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2])
{
if (!uptrendEndingDetectionMeanfullStep.HasValue || ((d1 >= uptrendEndingDetectionMeanfullStep
//|| d2 >= uptrendEndingDetectionMeanfullStep
)
&& dt > TimeSpan.FromSeconds(10)))
{
res |= TradingEvent.CloseLong;
}
break;
}
// если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта
if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2])
{
if (!uptrendStartingDetectionMeanfullStep.HasValue || ((d1 <= uptrendStartingDetectionMeanfullStep
// || d2 <= uptrendStartingDetectionMeanfullStep
) && dt > TimeSpan.FromSeconds(10)))
{
res |= TradingEvent.OpenLong;
}
break;
}
}
}
}
}
return (res, bigWindowAv, smallWindowAv);
}
}
}