117 lines
6.3 KiB
C#
117 lines
6.3 KiB
C#
using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
|
|
using KLHZ.Trader.Core.Contracts.Declisions.Interfaces;
|
|
using KLHZ.Trader.Core.Math.Declisions.Dtos;
|
|
|
|
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
|
{
|
|
/// <summary>
|
|
/// Обработка последних интервалов истории изменения цен.
|
|
/// </summary>
|
|
public static class LocalTrends
|
|
{
|
|
public static TradingEvent CheckByLocalTrends(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
|
|
{
|
|
var res = TradingEvent.None;
|
|
res |= CheckUptrendStart(times, prices, firstPeriod, secondPeriod, meanfullDiff, boundIndex);
|
|
res |= CheckUptrendEnd(times, prices, firstPeriod, secondPeriod, meanfullDiff, boundIndex);
|
|
|
|
return res;
|
|
}
|
|
|
|
internal static TradingEvent CheckUptrendStart(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
|
|
{
|
|
var periodStat = GetTwoPeriodsProcessingData(times, prices, firstPeriod, secondPeriod, boundIndex, meanfullDiff);
|
|
var isStartOk = periodStat.Success && periodStat.DiffStart < -meanfullDiff;
|
|
var isEndOk = periodStat.Success && periodStat.DiffEnd >= meanfullDiff;
|
|
return isStartOk && isEndOk && prices[periodStat.Start] - prices[periodStat.End] >= meanfullDiff ? TradingEvent.UptrendStart : TradingEvent.None;
|
|
}
|
|
|
|
internal static TradingEvent CheckUptrendEnd(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
|
|
{
|
|
var periodStat = GetTwoPeriodsProcessingData(times, prices, firstPeriod, secondPeriod, boundIndex, meanfullDiff);
|
|
var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5m * meanfullDiff;
|
|
var isEndOk = periodStat.Success && periodStat.DiffEnd < meanfullDiff;
|
|
return isStartOk && isEndOk && prices[periodStat.End] - prices[periodStat.Start] >= meanfullDiff ? TradingEvent.UptrendEnd : TradingEvent.None; ;
|
|
}
|
|
|
|
internal static TwoLocalTrendsResultDto GetTwoPeriodsProcessingData(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan lastPeriod, int boundIndex, decimal meanfullDiff)
|
|
{
|
|
var res = new TwoLocalTrendsResultDto(success: false, 0, 0, 0, 0, 0, TimeSpan.Zero, TimeSpan.Zero);
|
|
int count = -1;
|
|
var lastTime = times[times.Length - 1];
|
|
var bound = -1;
|
|
var start = -1;
|
|
var end = times.Length - 1;
|
|
|
|
for (int i = times.Length - 1; i > -1; i--)
|
|
{
|
|
if (count > 0 && bound < 0 && (count == boundIndex || lastTime - times[i] >= lastPeriod))
|
|
{
|
|
bound = i;
|
|
lastPeriod = lastTime - times[i];
|
|
}
|
|
if (lastTime - times[i] >= lastPeriod + firstPeriod)
|
|
{
|
|
start = i;
|
|
|
|
break;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
if (start < bound && start >= 0 && bound > 0)
|
|
{
|
|
var diff1 = prices[bound] - prices[start];
|
|
var diff2 = prices[end] - prices[bound];
|
|
res = new TwoLocalTrendsResultDto(true, diff1, diff2, start, bound, end, times[bound] - times[start], times[end] - times[bound]);
|
|
}
|
|
return res;
|
|
}
|
|
internal static bool CheckLongOpen(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
|
|
{
|
|
var data = unit.GetData().Result;
|
|
var periodStat = GetTwoPeriodsProcessingData(data.timestamps, data.prices, firstPeriod, secondPeriod, boundIndex, meanfullDiff);
|
|
var isStartOk = periodStat.Success && periodStat.DiffStart < -meanfullDiff;
|
|
var isEndOk = periodStat.Success && periodStat.DiffEnd >= meanfullDiff;
|
|
return isStartOk && isEndOk && data.prices[periodStat.Start] - data.prices[periodStat.End] >= meanfullDiff;
|
|
}
|
|
|
|
internal static bool CheckLongClose(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
|
|
{
|
|
var data = unit.GetData().Result;
|
|
var periodStat = GetTwoPeriodsProcessingData(data.timestamps, data.prices, firstPeriod, secondPeriod, boundIndex, meanfullDiff);
|
|
var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5m * meanfullDiff;
|
|
var isEndOk = periodStat.Success && periodStat.DiffEnd < meanfullDiff;
|
|
return isStartOk && isEndOk && data.prices[periodStat.End] - data.prices[periodStat.Start] >= meanfullDiff;
|
|
}
|
|
|
|
internal static TradingEvent Detect(IPriceHistoryCacheUnit data)
|
|
{
|
|
decimal meanfullDiff = 1m;
|
|
|
|
var res = TradingEvent.None;
|
|
//var downtrendStarts = data.CheckDowntrendStarting(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(7), meanfullDiff);
|
|
var uptrendStarts = data.CheckLongOpen(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(7), meanfullDiff, 3);
|
|
var uptrendStarts2 = data.CheckLongOpen(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(3), meanfullDiff, 2);
|
|
var downtrendEnds = data.CheckLongOpen(TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(10), meanfullDiff, 5);
|
|
uptrendStarts |= downtrendEnds;
|
|
uptrendStarts |= uptrendStarts2;
|
|
if (uptrendStarts)
|
|
{
|
|
res |= TradingEvent.LongClose;
|
|
}
|
|
//var downtrendEnds = data.CheckDowntrendEnding(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(15), meanfullDiff);
|
|
|
|
var uptrendEnds = data.CheckLongClose(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(20), meanfullDiff * 1.5m, 8);
|
|
var uptrendEnds2 = data.CheckLongClose(TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(30), meanfullDiff, 8);
|
|
uptrendEnds |= uptrendEnds2;
|
|
if (uptrendEnds)
|
|
{
|
|
res |= TradingEvent.LongOpen;
|
|
}
|
|
return res;
|
|
}
|
|
}
|
|
}
|