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

121 lines
4.6 KiB
C#

using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
using MathNet.Numerics;
namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
/// <summary>
/// Обработка последних интервалов истории изменения цен.
/// </summary>
public static class LocalTrends
{
public static bool TryGetLocalTrends(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan lastPeriod,
double meanfullDiff, out TradingEvent res)
{
res = TradingEvent.None;
var success = false;
if (times.Length == 0)
{
return success;
}
var x1 = new List<double>();
var y1 = new List<double>();
var x1d = new List<DateTime>();
var x2 = new List<double>();
var y2 = new List<double>();
var x2d = new List<DateTime>();
var y1_approximated = new List<double>();
var y2_approximated = new List<double>();
var lastTime = times[times.Length - 1];
var firstTime = times[0];
var fullPeriod = firstPeriod + lastPeriod;
if (lastTime - firstTime > fullPeriod)
{
for (int i = 1; i < times.Length - 1; i++)
{
var dt1 = lastTime - times[times.Length - i];
if (dt1 <= lastPeriod)
{
x2.Add((times[times.Length - i] - firstTime).TotalSeconds);
x2d.Add(times[times.Length - i]);
y2.Add((double)prices[times.Length - i]);
}
else if (dt1 <= fullPeriod)
{
x1.Add((times[times.Length - i] - firstTime).TotalSeconds);
x1d.Add(times[times.Length - i]);
y1.Add((double)prices[times.Length - i]);
}
else
{
success = true;
break;
}
}
if (x1.Count > 1 && x2.Count > 1)
{
var line1 = Fit.Line(x1.ToArray(), y1.ToArray());
var line2 = Fit.Line(x2.ToArray(), y2.ToArray());
foreach (var x in x1)
{
y1_approximated.Add(line1.A + x * line1.B);
}
foreach (var x in x2)
{
y2_approximated.Add(line2.A + x * line2.B);
}
var diff1 = y1_approximated[0] - y1_approximated[y1_approximated.Count - 1];
var diff2 = y2_approximated[0] - y2_approximated[y2_approximated.Count - 1];
if (diff1 <= -meanfullDiff && diff2 >= meanfullDiff)
{
res |= TradingEvent.DowntrendEnd;
}
else if (diff1 >= meanfullDiff && diff2 <= -meanfullDiff)
{
res |= TradingEvent.UptrendEnd;
}
else if (diff1 <= -meanfullDiff && diff2 >= meanfullDiff)
{
res |= TradingEvent.DowntrendEnd;
}
else if (diff1 >= 0 && diff2 <= -meanfullDiff)
{
res |= TradingEvent.DowntrendStart;
}
success = true;
}
}
return success;
}
public static bool TryCalcTrendDiff(DateTime[] times, decimal[] prices, out decimal diff)
{
diff = 0;
if (times.Length <= 1 || times.Length != prices.Length)
{
return false;
}
else
{
var startTime = times[0];
var x = new double[times.Length];
for (int i = 0; i < times.Length - 1; i++)
{
x[i] = (times[i] - startTime).TotalSeconds;
}
var line = Fit.Line(x.ToArray(), prices.Select(p => (double)p).ToArray());
var p1 = line.A + line.B * 0;
var p2 = line.A + line.B * (times[times.Length - 1] - times[0]).TotalSeconds;
diff = (decimal)(p2 - p1);
return true;
}
}
}
}