diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs b/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs
index ed4ab8d..4f8d20e 100644
--- a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs
+++ b/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs
@@ -11,5 +11,6 @@
ShortOpen = 16,
UptrendEnd = 32,
UptrendStart = 64,
+ HorisontTrend = 128,
}
}
diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs b/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs
index 446767c..2826943 100644
--- a/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs
+++ b/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs
@@ -7,7 +7,7 @@ namespace KLHZ.Trader.Core.Contracts.Declisions.Interfaces
public string Figi { get; }
public int Length { get; }
public ValueTask AddData(INewPrice priceChange);
- public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData();
+ public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData(int? length = null);
public ValueTask AddOrderbook(IOrderbook orderbook);
///
diff --git a/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs b/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs
deleted file mode 100644
index b1d7e58..0000000
--- a/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace KLHZ.Trader.Core.Math.Declisions.Dtos
-{
- internal readonly struct PeriodPricesInfoDto
- {
- public readonly int Start;
- public readonly int End;
- public readonly decimal LastPrice;
- public readonly decimal FirstPrice;
- public readonly decimal PeriodDiff;
- public readonly decimal PeriodMax;
- public readonly decimal PeriodMin;
- public readonly bool Success;
- public readonly TimeSpan Period;
-
- public PeriodPricesInfoDto(bool success, decimal firstPrice, decimal lastPrice, decimal periodDiff, decimal periodMin, decimal periodMax, TimeSpan period, int start, int end)
- {
- Success = success;
- LastPrice = lastPrice;
- FirstPrice = firstPrice;
- PeriodDiff = periodDiff;
- PeriodMax = periodMax;
- PeriodMin = periodMin;
- Period = period;
- Start = start;
- End = end;
- }
- }
-}
diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs b/KLHZ.Trader.Core.Math/Declisions/Dtos/TwoLocalTrendsResultDto.cs
similarity index 72%
rename from KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs
rename to KLHZ.Trader.Core.Math/Declisions/Dtos/TwoLocalTrendsResultDto.cs
index d16f12f..0d3b251 100644
--- a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Dtos/TwoLocalTrendsResultDto.cs
@@ -1,6 +1,6 @@
-namespace KLHZ.Trader.Core.Contracts.Declisions.Dtos
+namespace KLHZ.Trader.Core.Math.Declisions.Dtos
{
- public readonly struct TwoPeriodsResultDto
+ internal readonly struct TwoLocalTrendsResultDto
{
public readonly int Start;
public readonly int Bound;
@@ -11,7 +11,7 @@
public readonly TimeSpan PeriodStart;
public readonly TimeSpan PeriodEnd;
- public TwoPeriodsResultDto(bool success, decimal diffStart, decimal diffEnd, int start, int bound, int end,
+ public TwoLocalTrendsResultDto(bool success, decimal diffStart, decimal diffEnd, int start, int bound, int end,
TimeSpan periodStart, TimeSpan periodEnd)
{
Success = success;
diff --git a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs
index 6d222da..de90df6 100644
--- a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs
@@ -47,7 +47,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
return ValueTask.CompletedTask;
}
- public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData()
+ public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData(int? length = null)
{
lock (_locker)
{
diff --git a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs
index 1fcb33f..dcad0f0 100644
--- a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs
@@ -76,7 +76,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
return ValueTask.CompletedTask;
}
- public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData()
+ public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData(int? length = null)
{
lock (_locker)
{
@@ -86,10 +86,12 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache
}
else
{
- var prices = new decimal[_length];
- var timestamps = new DateTime[_length];
- Array.Copy(Prices, 1 + _pointer - _length, prices, 0, prices.Length);
- Array.Copy(Timestamps, 1 + _pointer - _length, timestamps, 0, timestamps.Length);
+ var dataLength = length.HasValue ? System.Math.Min(length.Value, _length) : _length;
+ var prices = new decimal[dataLength];
+ var timestamps = new DateTime[dataLength];
+ var index = 1 + _pointer - dataLength;
+ Array.Copy(Prices, index, prices, 0, prices.Length);
+ Array.Copy(Timestamps, index, timestamps, 0, timestamps.Length);
return ValueTask.FromResult((timestamps, prices));
}
}
diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs
index def5810..3d3aecd 100644
--- a/KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs
@@ -1,8 +1,6 @@
-using KLHZ.Trader.Core.Contracts.Declisions.Dtos;
-using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
+using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums;
using KLHZ.Trader.Core.Contracts.Declisions.Interfaces;
using KLHZ.Trader.Core.Math.Declisions.Dtos;
-using KLHZ.Trader.Core.Math.Declisions.Services.Cache;
namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
@@ -11,199 +9,48 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
///
public static class LocalTrends
{
- internal static PeriodPricesInfoDto GetPriceDiffForTimeSpan(this IPriceHistoryCacheUnit unit, TimeSpan timeShift, TimeSpan timeSpan, int? pointsShift = null)
+ public static TradingEvent CheckByLocalTrends(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
{
- var res = new PeriodPricesInfoDto(false, 0, 0, 0, 0, 0, timeSpan, 0, 0);
- var data = unit.GetData().Result;
- var times = data.timestamps;
- var prices = data.prices;
- if (times.Length < 2) return res;
- var lastPriceTime = times[times.Length - 1];
- var intervalEnd = lastPriceTime - timeShift;
- var intervalStart = intervalEnd - timeSpan;
- var max = decimal.MinValue;
- var min = decimal.MaxValue;
-
- var intervaEndIndex = -1;
- var intervaStartIndex = -1;
-
- int count = 0;
- for (int i = times.Length - 1; i > -1; i--)
- {
- if ((times[i] <= intervalEnd || pointsShift.HasValue && count < pointsShift.Value) && intervaEndIndex < 0)
- {
- intervaEndIndex = i;
- }
-
- if (prices[i] > max && intervaEndIndex >= 0)
- {
- max = prices[i];
- }
- if (prices[i] < min && intervaEndIndex >= 0)
- {
- min = prices[i];
- }
- if (times[i] <= intervalStart && intervaStartIndex < 0)
- {
- intervaStartIndex = i;
- if (intervaStartIndex != intervaEndIndex && intervaEndIndex >= 0)
- break;
- }
- count++;
- }
-
- if (intervaStartIndex >= 0 && intervaEndIndex >= 0)
- {
- res = new PeriodPricesInfoDto(
- true,
- prices[intervaStartIndex],
- prices[intervaEndIndex],
- prices[intervaEndIndex] - prices[intervaStartIndex],
- min,
- max,
- timeSpan,
- intervaStartIndex,
- intervaEndIndex);
- }
+ var res = TradingEvent.None;
+ res |= CheckUptrendStart(times, prices, firstPeriod, secondPeriod, meanfullDiff, boundIndex);
+ res |= CheckUptrendEnd(times, prices, firstPeriod, secondPeriod, meanfullDiff, boundIndex);
return res;
}
- internal static bool CheckStable(this PeriodPricesInfoDto data, decimal meanfullDiff)
+ internal static TradingEvent CheckUptrendStart(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
{
- meanfullDiff = System.Math.Abs(meanfullDiff);
- return data.Success && System.Math.Abs(data.PeriodDiff) < 1.5m * meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 2 * meanfullDiff;
+ 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 bool CheckGrowing(this PeriodPricesInfoDto data, decimal meanfullDiff)
+ internal static TradingEvent CheckUptrendEnd(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
{
- return meanfullDiff > 0 && data.Success && data.PeriodDiff > meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 3 * System.Math.Abs(data.PeriodDiff);
+ 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 bool CheckFalling(this PeriodPricesInfoDto data, decimal meanfullDiff)
+ internal static TwoLocalTrendsResultDto GetTwoPeriodsProcessingData(DateTime[] times, decimal[] prices, TimeSpan firstPeriod, TimeSpan lastPeriod, int boundIndex, decimal meanfullDiff)
{
- meanfullDiff = -meanfullDiff;
- return meanfullDiff < 0 && data.Success && data.PeriodDiff < meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 3 * System.Math.Abs(data.PeriodDiff);
- }
-
- internal static float CalcTrendRelationAbs(PeriodPricesInfoDto first, PeriodPricesInfoDto second)
- {
- var k1 = System.Math.Abs(first.PeriodDiff) / System.Math.Abs((decimal)first.Period.TotalSeconds);
- var k2 = System.Math.Abs(second.PeriodDiff) / System.Math.Abs((decimal)second.Period.TotalSeconds);
- if (k2 == 0 && k1 != 0) return 1000;
- return (float)(k1 / k2);
- }
- internal static float CalcTrendRelationAbs(TwoPeriodsResultDto data)
- {
- var k1 = System.Math.Abs(data.DiffStart) / System.Math.Abs((decimal)data.PeriodStart.TotalSeconds);
- var k2 = System.Math.Abs(data.DiffEnd) / System.Math.Abs((decimal)data.PeriodEnd.TotalSeconds);
- if (k2 == 0 && k1 != 0) return 1000;
- return (float)(k1 / k2);
- }
-
- internal static bool CheckDowntrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
- {
- var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
- var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
- var endDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, secondPeriod);
- var isEndStable = endDiff.CheckStable(meanfullDiff);
- var isEndGrown = endDiff.CheckGrowing(meanfullDiff);
- var isStartFalls = startDiff.CheckFalling(meanfullDiff);
- var isTotalFalls = totalDiff.CheckFalling(meanfullDiff);
-
- var trendRelation = CalcTrendRelationAbs(startDiff, endDiff);
- var res = totalDiff.Success && isStartFalls && (isEndStable || isEndGrown) && trendRelation >= 2;
-
- if (startDiff.Success)
- {
-
- }
- return res;
- }
-
- internal static bool CheckUptrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
- {
- var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
- var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
- var endDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, secondPeriod);
- var isEndStable = endDiff.CheckStable(meanfullDiff);
- var isEndFalls = endDiff.CheckFalling(meanfullDiff);
- var isStartGrows = startDiff.CheckGrowing(meanfullDiff);
-
- var trendRelation = CalcTrendRelationAbs(startDiff, endDiff);
- var isEndLocal = endDiff.PeriodDiff == 0;
- var res = totalDiff.Success && isStartGrows && (isEndStable || isEndFalls) && trendRelation >= 2 && !isEndLocal;
-
- if (res)
- {
-
- }
- return res;
- }
-
- internal static bool CheckDowntrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
- {
- var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
- var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
- var endDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, secondPeriod);
-
-
- var isEndFalls = endDiff.CheckFalling(meanfullDiff);
- var isStartStable = startDiff.CheckStable(meanfullDiff);
- var isStartGrows = startDiff.CheckGrowing(meanfullDiff);
-
- var trendRelation = CalcTrendRelationAbs(endDiff, startDiff);
- return totalDiff.Success && (isStartStable || isStartGrows) && isEndFalls && trendRelation >= 2;
- }
-
- internal static bool CheckUptrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
- {
- var totalDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, firstPeriod + secondPeriod);
- var startDiff = unit.GetPriceDiffForTimeSpan(secondPeriod, firstPeriod);
- var endDiff = unit.GetPriceDiffForTimeSpan(TimeSpan.Zero, secondPeriod);
-
-
- var isEndGrows = endDiff.CheckGrowing(meanfullDiff);
- var isStartStable = startDiff.CheckStable(meanfullDiff);
- var isStartFalls = startDiff.CheckStable(meanfullDiff);
-
- var trendRelation = CalcTrendRelationAbs(endDiff, startDiff);
- var res = totalDiff.Success && (isStartStable || isStartFalls) && isEndGrows && endDiff.PeriodDiff > meanfullDiff;
-
- if (isStartStable)
- {
- res &= trendRelation >= 2;
- }
- else
- {
-
- }
- if (res)
- {
-
- }
- return res;
- }
-
- internal static TwoPeriodsResultDto GetTwoPeriodsProcessingData(this (DateTime[] timestamps, decimal[] prices) data, TimeSpan shift, int shiftPointsStart, int shiftPointsEnd, TimeSpan firstPeriod, decimal meanfullDiff)
- {
- var res = new TwoPeriodsResultDto(success: false, 0, 0, 0, 0, 0, TimeSpan.Zero, TimeSpan.Zero);
- var time = data.timestamps;
- var prices = data.prices;
+ var res = new TwoLocalTrendsResultDto(success: false, 0, 0, 0, 0, 0, TimeSpan.Zero, TimeSpan.Zero);
int count = -1;
- var lastTime = time[time.Length - 1];
+ var lastTime = times[times.Length - 1];
var bound = -1;
var start = -1;
- var end = time.Length - 1;
+ var end = times.Length - 1;
- for (int i = time.Length - 1; i > -1; i--)
+ for (int i = times.Length - 1; i > -1; i--)
{
- if (count > 0 && bound < 0 && (count == shiftPointsEnd || lastTime - time[i] >= shift))
+ if (count > 0 && bound < 0 && (count == boundIndex || lastTime - times[i] >= lastPeriod))
{
bound = i;
- shift = lastTime - time[i];
+ lastPeriod = lastTime - times[i];
}
- if (lastTime - time[i] >= shift + firstPeriod)
+ if (lastTime - times[i] >= lastPeriod + firstPeriod)
{
start = i;
@@ -217,105 +64,37 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
var diff1 = prices[bound] - prices[start];
var diff2 = prices[end] - prices[bound];
- res = new TwoPeriodsResultDto(true, diff1, diff2, start, bound, end, time[bound] - time[start], time[end] - time[bound]);
+ res = new TwoLocalTrendsResultDto(true, diff1, diff2, start, bound, end, times[bound] - times[start], times[end] - times[bound]);
}
return res;
}
-
- public static bool CheckLongClose(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int pointsStart, int pointsEnd)
+ internal static bool CheckLongOpen(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int boundIndex)
{
var data = unit.GetData().Result;
- var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, pointsStart, pointsEnd, firstPeriod, meanfullDiff);
- var trendRelation = CalcTrendRelationAbs(periodStat);
- var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5m * meanfullDiff;
- var isEndOk = periodStat.Success && periodStat.DiffEnd < meanfullDiff;
-
- if (isEndOk)
- {
-
- }
-
- if (isStartOk)
- {
-
- }
-
- if (isEndOk && isStartOk)
- {
-
- }
- return isStartOk && isEndOk && data.prices[periodStat.End] - data.prices[periodStat.Start] >= meanfullDiff;
- }
-
- internal static bool CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
- {
- var data = unit.GetData().Result;
- var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, 15, 2, firstPeriod, meanfullDiff);
- var trendRelation = CalcTrendRelationAbs(periodStat);
- var isStartOk = periodStat.Success && periodStat.DiffStart < -meanfullDiff;
- var isEndOk = periodStat.Success && periodStat.DiffEnd >= meanfullDiff;
-
- if (isEndOk)
- {
-
- }
-
- if (isStartOk)
- {
-
- }
-
- if (isEndOk && isStartOk)
- {
-
- }
- return isStartOk && isEndOk;
- }
-
- internal static bool _CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff)
- {
- var data = unit.GetData().Result;
- var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, 15, 1, firstPeriod, meanfullDiff);
- var trendRelation = CalcTrendRelationAbs(periodStat);
- var isStartOk = periodStat.Success && periodStat.DiffStart < -meanfullDiff;
- var isEndOk = periodStat.Success && periodStat.DiffEnd >= meanfullDiff;
-
- if (isEndOk)
- {
-
- }
-
- if (isStartOk)
- {
-
- }
-
- if (isEndOk && isStartOk)
- {
-
- }
- return isStartOk && isEndOk;
- }
-
-
- public static bool CheckLongOpen(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, decimal meanfullDiff, int pointsStart, int pointsEnd)
- {
- var data = unit.GetData().Result;
- var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, pointsStart, pointsEnd, firstPeriod, meanfullDiff);
+ 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;
}
- public static TradingEvent Detect(IPriceHistoryCacheUnit data)
+ 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, 8, 3);
- var uptrendStarts2 = data.CheckLongOpen(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(3), meanfullDiff, 15, 2);
- var downtrendEnds = data.CheckLongOpen(TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(10), meanfullDiff, 15, 5);
+ 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)
@@ -324,8 +103,8 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
}
//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, 8);
- var uptrendEnds2 = data.CheckLongClose(TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(30), meanfullDiff, 15, 8);
+ 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)
{
diff --git a/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs b/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs
index 64906df..3049e0a 100644
--- a/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs
+++ b/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs
@@ -219,5 +219,28 @@ namespace KLHZ.Trader.Core.Tests
}
}
}
+
+ [Test]
+ public void Test10()
+ {
+ var length = 77;
+ var shift = 334;
+ var count = PriceHistoryCacheUnit.CacheMaxLength + shift;
+ var figi = "figi";
+ var hist = GetHistory(count, figi);
+ var cacheUnit = new PriceHistoryCacheUnit2(figi, hist);
+ var data = cacheUnit.GetData(length).Result;
+
+ Assert.That(data.prices.Length == length);
+ Assert.That(data.timestamps.Length == length);
+
+ Assert.That(data.prices.Last() == hist.Last().Value);
+ Assert.That(data.timestamps.Last() == hist.Last().Time);
+ for (var i = 1; i <= length; i++)
+ {
+ Assert.That(hist[hist.Length - i].Value, Is.EqualTo(data.prices[data.prices.Length - i]));
+ Assert.That(hist[hist.Length - i].Time, Is.EqualTo(data.timestamps[data.prices.Length - i]));
+ }
+ }
}
}
\ No newline at end of file
diff --git a/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs b/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs
deleted file mode 100644
index f2d6a6c..0000000
--- a/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs
+++ /dev/null
@@ -1,275 +0,0 @@
-using KLHZ.Trader.Core.DataLayer.Entities.Prices;
-using KLHZ.Trader.Core.Math.Declisions.Services.Cache;
-using KLHZ.Trader.Core.Math.Declisions.Utils;
-
-namespace KLHZ.Trader.Core.Tests
-{
- public class HistoryProcessingInstrumentsTests
- {
- private static PriceChange[] GetHistory(int count, string figi, DateTime startDt, decimal startValue, decimal step)
- {
- var res = new PriceChange[count];
- if (count != 0)
- {
- for (int i = 0; i < count; i++)
- {
- startValue += step;
- startDt = startDt.AddSeconds(1);
- res[i] = new PriceChange()
- {
- Figi = figi,
- Ticker = figi + "_ticker",
- Id = i,
- Time = startDt,
- Value = startValue,
- };
- }
- }
- return res;
- }
-
- [Test]
- public void Test0()
- {
- var figi = "figi";
- var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
- var count = 100;
- var step = 0;
- var startValue = 10;
- var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
-
- var data = unit.GetData().Result;
- var endDate = startDate.AddSeconds(count);
- Assert.IsTrue(data.timestamps.Last() == endDate);
- Assert.IsTrue(data.prices.Last() == startValue + step * count);
-
- var periodLength = 4;
- var shift = 0;
- var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
- var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
- var firstPrice = startValue + (step * count) - (step * (shift + periodLength));
- var lastPrice = startValue + (step * count) - step * shift;
-
- var diff = firstPrice - lastPrice;
-
-
- Assert.IsTrue(result.LastPrice == lastPrice);
- Assert.IsTrue(result.FirstPrice == firstPrice);
- Assert.IsTrue(result.PeriodMax == maxValue);
- Assert.IsTrue(result.PeriodMin == minValue);
- Assert.IsTrue(result.PeriodDiff == diff);
- }
-
- [Test]
- public void Test1()
- {
- var figi = "figi";
- var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
- var count = 100;
- var step = 0.5m;
- var startValue = 10;
- var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
-
- var data = unit.GetData().Result;
- var endDate = startDate.AddSeconds(count);
- Assert.IsTrue(data.timestamps.Last() == endDate);
- Assert.IsTrue(data.prices.Last() == startValue + step * count);
-
- var periodLength = 4;
- var shift = 0;
- var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
- var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
- var firstPrice = startValue + (step * count) - (step * (shift + periodLength));
- var lastPrice = startValue + (step * count) - step * shift;
-
- var diff = lastPrice - firstPrice;
-
-
- Assert.IsTrue(result.LastPrice == lastPrice);
- Assert.IsTrue(result.FirstPrice == firstPrice);
- Assert.IsTrue(result.PeriodMax == maxValue);
- Assert.IsTrue(result.PeriodMin == minValue);
- Assert.IsTrue(result.PeriodDiff == diff);
- }
-
- [Test]
- public void Test2()
- {
- var figi = "figi";
- var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
- var count = 100;
- var step = 0.5m;
- var startValue = 10;
-
- var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
-
- var data = unit.GetData().Result;
- var endDate = startDate.AddSeconds(count);
- Assert.IsTrue(data.timestamps.Last() == endDate);
- Assert.IsTrue(data.prices.Last() == startValue + step * count);
-
- var periodLength = 4;
- var shift = 1;
- var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
- var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
- var firstPrice = startValue + (step * count) - (step * (shift + periodLength));
- var lastPrice = startValue + (step * count) - step * shift;
-
- var diff = lastPrice - firstPrice;
-
-
- Assert.IsTrue(result.LastPrice == lastPrice);
- Assert.IsTrue(result.FirstPrice == firstPrice);
- Assert.IsTrue(result.PeriodMax == maxValue);
- Assert.IsTrue(result.PeriodMin == minValue);
- Assert.IsTrue(result.PeriodDiff == diff);
- }
-
- [Test]
- public void Test3()
- {
- var figi = "figi";
- var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
- var count = 100;
- var step = -0.5m;
- var startValue = 10;
-
- var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
-
- var data = unit.GetData().Result;
- var endDate = startDate.AddSeconds(count);
- Assert.IsTrue(data.timestamps.Last() == endDate);
- Assert.IsTrue(data.prices.Last() == startValue + step * count);
-
- var periodLength = 4;
- var shift = 0;
- var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
- var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
- var firstPrice = startValue + (step * count) - (step * (shift + periodLength));
- var lastPrice = startValue + (step * count) - step * shift;
-
- var diff = lastPrice - firstPrice;
-
-
- Assert.IsTrue(result.LastPrice == lastPrice);
- Assert.IsTrue(result.FirstPrice == firstPrice);
- Assert.IsTrue(result.PeriodMax == maxValue);
- Assert.IsTrue(result.PeriodMin == minValue);
- Assert.IsTrue(result.PeriodDiff == diff);
- }
-
- [Test]
- public void Test4()
- {
- var figi = "figi";
- var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
- var count = 100;
- var step = -0.5m;
- var startValue = 10;
-
- var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
-
- var data = unit.GetData().Result;
- var endDate = startDate.AddSeconds(count);
- Assert.IsTrue(data.timestamps.Last() == endDate);
- Assert.IsTrue(data.prices.Last() == startValue + step * count);
-
- var periodLength = 4;
- var shift = 3;
- var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
- var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
- var firstPrice = startValue + (step * count) - (step * (shift + periodLength));
- var lastPrice = startValue + (step * count) - step * shift;
-
- var diff = lastPrice - firstPrice;
-
-
- Assert.IsTrue(result.LastPrice == lastPrice);
- Assert.IsTrue(result.FirstPrice == firstPrice);
- Assert.IsTrue(result.PeriodMax == maxValue);
- Assert.IsTrue(result.PeriodMin == minValue);
- Assert.IsTrue(result.PeriodDiff == diff);
- }
-
- [Test]
- public void Test5()
- {
- var figi = "figi";
- var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc);
- var count = 100;
- var step = -0.5m;
- var startValue = 10;
-
- var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step));
-
- var data = unit.GetData().Result;
- var endDate = startDate.AddSeconds(count);
- Assert.IsTrue(data.timestamps.Last() == endDate);
- Assert.IsTrue(data.prices.Last() == startValue + step * count);
-
- var periodLength = 4;
- var shift = 3;
- var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue1 = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
- var minValue1 = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
- var firstPrice1 = startValue + (step * count) - (step * (shift + periodLength));
- var lastPrice1 = startValue + (step * count) - step * shift;
-
- var diff1 = lastPrice1 - firstPrice1;
-
-
- Assert.IsTrue(result.LastPrice == lastPrice1);
- Assert.IsTrue(result.FirstPrice == firstPrice1);
- Assert.IsTrue(result.PeriodMax == maxValue1);
- Assert.IsTrue(result.PeriodMin == minValue1);
- Assert.IsTrue(result.PeriodDiff == diff1);
-
-
-
- var unit2 = new PriceHistoryCacheUnit(figi);
- var data2 = unit.GetData().Result;
- for (int i = 0; i < data2.prices.Length; i++)
- {
- var value = (decimal)data2.prices[i];
- if (i == data2.prices.Length - 5)
- {
- value = 100;
- }
- else if (i == data2.prices.Length - 6)
- {
- value = -100;
- }
- unit2.AddData(new PriceChange()
- {
- Figi = figi,
- Ticker = figi,
- Time = data2.timestamps[i],
- Value = value
- });
-
- }
-
- var result2 = LocalTrends.GetPriceDiffForTimeSpan(unit2, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
-
- var maxValue2 = 100;
- var minValue2 = -100;
-
- Assert.IsTrue(result2.LastPrice == result.LastPrice);
- Assert.IsTrue(result2.FirstPrice == result.FirstPrice);
- Assert.IsTrue(result2.PeriodMax == maxValue2);
- Assert.IsTrue(result2.PeriodMin == minValue2);
- Assert.IsTrue(result2.PeriodDiff == result.PeriodDiff);
- }
- }
-}
diff --git a/KLHZ.Trader.Core/Exchange/Extentions/StringExtensions.cs b/KLHZ.Trader.Core/Exchange/Extentions/StringExtensions.cs
index a0bcda0..625ce00 100644
--- a/KLHZ.Trader.Core/Exchange/Extentions/StringExtensions.cs
+++ b/KLHZ.Trader.Core/Exchange/Extentions/StringExtensions.cs
@@ -1,4 +1,4 @@
-using KLHZ.Trader.Core.Exchange.Models;
+using KLHZ.Trader.Core.Exchange.Models.Assets;
namespace KLHZ.Trader.Core.Exchange.Extentions
{
diff --git a/KLHZ.Trader.Core/Exchange/Models/Asset.cs b/KLHZ.Trader.Core/Exchange/Models/Assets/Asset.cs
similarity index 88%
rename from KLHZ.Trader.Core/Exchange/Models/Asset.cs
rename to KLHZ.Trader.Core/Exchange/Models/Assets/Asset.cs
index fec382d..e42f69a 100644
--- a/KLHZ.Trader.Core/Exchange/Models/Asset.cs
+++ b/KLHZ.Trader.Core/Exchange/Models/Assets/Asset.cs
@@ -1,4 +1,4 @@
-namespace KLHZ.Trader.Core.Exchange.Models
+namespace KLHZ.Trader.Core.Exchange.Models.Assets
{
public class Asset
{
diff --git a/KLHZ.Trader.Core/Exchange/Models/AssetType.cs b/KLHZ.Trader.Core/Exchange/Models/Assets/AssetType.cs
similarity index 66%
rename from KLHZ.Trader.Core/Exchange/Models/AssetType.cs
rename to KLHZ.Trader.Core/Exchange/Models/Assets/AssetType.cs
index 1a58b9d..9000294 100644
--- a/KLHZ.Trader.Core/Exchange/Models/AssetType.cs
+++ b/KLHZ.Trader.Core/Exchange/Models/Assets/AssetType.cs
@@ -1,4 +1,4 @@
-namespace KLHZ.Trader.Core.Exchange.Models
+namespace KLHZ.Trader.Core.Exchange.Models.Assets
{
public enum AssetType
{
diff --git a/KLHZ.Trader.Core/Exchange/Models/PositionType.cs b/KLHZ.Trader.Core/Exchange/Models/Assets/PositionType.cs
similarity index 62%
rename from KLHZ.Trader.Core/Exchange/Models/PositionType.cs
rename to KLHZ.Trader.Core/Exchange/Models/Assets/PositionType.cs
index 1f68c6f..549c1e0 100644
--- a/KLHZ.Trader.Core/Exchange/Models/PositionType.cs
+++ b/KLHZ.Trader.Core/Exchange/Models/Assets/PositionType.cs
@@ -1,4 +1,4 @@
-namespace KLHZ.Trader.Core.Exchange.Models
+namespace KLHZ.Trader.Core.Exchange.Models.Assets
{
public enum PositionType
{
diff --git a/KLHZ.Trader.Core/Exchange/Models/DeferredTrade.cs b/KLHZ.Trader.Core/Exchange/Models/DeferredTrade.cs
new file mode 100644
index 0000000..15aabb5
--- /dev/null
+++ b/KLHZ.Trader.Core/Exchange/Models/DeferredTrade.cs
@@ -0,0 +1,9 @@
+namespace KLHZ.Trader.Core.Exchange.Models
+{
+ internal class DeferredTrade
+ {
+ public required string Figi { get; set; }
+ public decimal Price { get; set; }
+ public DateTime Time { get; set; }
+ }
+}
diff --git a/KLHZ.Trader.Core/Exchange/Services/ManagedAccount.cs b/KLHZ.Trader.Core/Exchange/Services/ManagedAccount.cs
index 5afcdb8..38b1f9f 100644
--- a/KLHZ.Trader.Core/Exchange/Services/ManagedAccount.cs
+++ b/KLHZ.Trader.Core/Exchange/Services/ManagedAccount.cs
@@ -10,7 +10,7 @@ using System.Collections.Concurrent;
using System.Threading.Channels;
using Tinkoff.InvestApi;
using Tinkoff.InvestApi.V1;
-using PositionType = KLHZ.Trader.Core.Exchange.Models.PositionType;
+using PositionType = KLHZ.Trader.Core.Exchange.Models.Assets.PositionType;
namespace KLHZ.Trader.Core.Exchange.Services
{
@@ -58,7 +58,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
}
- internal readonly ConcurrentDictionary Assets = new();
+ internal readonly ConcurrentDictionary Assets = new();
#endregion
@@ -126,7 +126,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
price = position.AveragePositionPrice;
}
#pragma warning disable CS0612 // Тип или член устарел
- var asset = new Models.Asset()
+ var asset = new Models.Assets.Asset()
{
AccountId = AccountId,
Figi = position.Figi,
diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs
index 49dea9b..f3dc518 100644
--- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs
+++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs
@@ -10,6 +10,7 @@ using KLHZ.Trader.Core.DataLayer.Entities.Declisions.Enums;
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
using KLHZ.Trader.Core.Exchange.Extentions;
using KLHZ.Trader.Core.Exchange.Models;
+using KLHZ.Trader.Core.Exchange.Models.Assets;
using KLHZ.Trader.Core.Math.Declisions.Services.Cache;
using KLHZ.Trader.Core.Math.Declisions.Utils;
using Microsoft.EntityFrameworkCore;
@@ -20,7 +21,7 @@ using Microsoft.Extensions.Options;
using System.Collections.Concurrent;
using System.Threading.Channels;
using Tinkoff.InvestApi;
-using AssetType = KLHZ.Trader.Core.Exchange.Models.AssetType;
+using AssetType = KLHZ.Trader.Core.Exchange.Models.Assets.AssetType;
namespace KLHZ.Trader.Core.Exchange.Services
{
@@ -31,6 +32,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
private readonly IDataBus _dataBus;
private readonly BotModeSwitcher _botModeSwitcher;
private readonly IDbContextFactory _dbContextFactory;
+ private readonly ConcurrentDictionary DeferredLongOpens = new();
+ private readonly ConcurrentDictionary DeferredLongCloses = new();
private readonly ConcurrentDictionary OpeningStops = new();
private readonly ConcurrentDictionary Accounts = new();
private readonly ConcurrentDictionary _historyCash = new();
@@ -125,7 +128,37 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
if (message.Figi == "FUTIMOEXF000")
{
- var data = await unit.GetData();
+
+ DeferredTrade? longOpen;
+ DeferredLongOpens.TryGetValue(message.Figi, out longOpen);
+ if (longOpen != null)
+ {
+ if (longOpen.Time <= (message.IsHistoricalData ? message.Time : DateTime.UtcNow))
+ {
+ DeferredLongOpens.TryRemove(message.Figi, out _);
+ if (message.Value - longOpen.Price < 1)
+ {
+ LogDeclision(declisionsForSave, DeclisionTradeAction.OpenLong, message);
+ }
+ }
+ }
+
+ DeferredTrade? longClose;
+ DeferredLongCloses.TryGetValue(message.Figi, out longClose);
+ if (longClose != null)
+ {
+ if (longClose.Time <= (message.IsHistoricalData ? message.Time : DateTime.UtcNow))
+ {
+ DeferredLongCloses.TryRemove(message.Figi, out _);
+ if (longClose.Price - message.Value < 1)
+ {
+ LogDeclision(declisionsForSave, DeclisionTradeAction.CloseLong, message);
+ }
+ }
+ }
+
+ var windowMaxSize = 100;
+ var data = await unit.GetData(windowMaxSize);
if (OpeningStops.TryGetValue(message.Figi, out var dt))
{
if (dt < (message.IsHistoricalData ? message.Time : DateTime.UtcNow))
@@ -137,34 +170,59 @@ namespace KLHZ.Trader.Core.Exchange.Services
if ((unit.BidsCount / unit.AsksCount) < 0.5m || (unit.BidsCount / unit.AsksCount) > 2m)
{
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(3);
- OpeningStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
- LogDeclision(declisionsForSave, DeclisionTradeAction.StopBuyShortTime, message);
+ //OpeningStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
+ //LogDeclision(declisionsForSave, DeclisionTradeAction.StopBuyShortTime, message);
}
- var resultLongOpen = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 45, 180, 2.5m);
- var resultLongClose = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 15, 120, 2.5m);
+ var res = TradingEvent.None;
+ var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, windowMaxSize, 45, 180, 2.5m);
+ var resultLongClose = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, windowMaxSize, 15, 120, 2.5m).events;
- if (resultLongOpen.bigWindowAv != 0)
+ var uptrendStarts = LocalTrends.CheckByLocalTrends(data.timestamps, data.prices, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(7), 1.5m, 3);
+ var uptrendStarts2 = LocalTrends.CheckByLocalTrends(data.timestamps, data.prices, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(3), 1.5m, 2);
+ var downtrendEnds = LocalTrends.CheckByLocalTrends(data.timestamps, data.prices, TimeSpan.FromSeconds(120), TimeSpan.FromSeconds(10), 1.5m, 5);
+
+
+ res |= uptrendStarts;
+ res |= uptrendStarts2;
+ //res |= downtrendEnds;
+ res |= resultLongClose;
+ res |= resultMoveAvFull.events;
+ if (resultMoveAvFull.bigWindowAv != 0)
{
- LogPrice(processedPrices, message, bigWindowProcessor, resultLongOpen.bigWindowAv);
- LogPrice(processedPrices, message, smallWindowProcessor, resultLongOpen.smallWindowAv);
+ LogPrice(processedPrices, message, bigWindowProcessor, resultMoveAvFull.bigWindowAv);
+ LogPrice(processedPrices, message, smallWindowProcessor, resultMoveAvFull.smallWindowAv);
}
- if ((resultLongClose.events & TradingEvent.StopBuy) == TradingEvent.StopBuy)
+ if ((resultLongClose & TradingEvent.StopBuy) == TradingEvent.StopBuy)
{
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(_buyStopLength);
OpeningStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
//LogDeclision(declisionsForSave, DeclisionTradeAction.StopBuy, message);
}
- if ((resultLongOpen.events & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
- && !OpeningStops.TryGetValue(message.Figi, out _))
+ if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
+ && !OpeningStops.TryGetValue(message.Figi, out _)
+ && data.timestamps.Length > 1
+ && (data.timestamps[data.timestamps.Length - 1] - data.timestamps[data.timestamps.Length - 2] < TimeSpan.FromMinutes(1)))
{
- LogDeclision(declisionsForSave, DeclisionTradeAction.OpenLong, message);
+ var trade = new DeferredTrade()
+ {
+ Figi = message.Figi,
+ Price = message.Value,
+ Time = message.Time.AddSeconds(15)
+ };
+ DeferredLongOpens[message.Figi] = trade;
}
- if ((resultLongClose.events & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
+ if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
{
- LogDeclision(declisionsForSave, DeclisionTradeAction.CloseLong, message);
+ var trade = new DeferredTrade()
+ {
+ Figi = message.Figi,
+ Price = message.Value,
+ Time = message.Time.AddSeconds(15)
+ };
+ DeferredLongCloses[message.Figi] = trade;
}
//if ((resultLongOpen.events & TradingEvent.ShortOpen) == TradingEvent.ShortOpen