From fbd3da2b8d320fb02fc7fa1b9d12e3d369128573 Mon Sep 17 00:00:00 2001 From: vlad zverzhkhovskiy Date: Tue, 2 Sep 2025 21:54:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D1=88=D0=B5=D0=BB=20?= =?UTF-8?q?=D1=81=20float=20=D0=BD=D0=B0=20decimal=20=D0=B2=20=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=87=D1=91=D1=82=D0=B0=D0=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Declisions/Dtos/TwoPeriodsResultDto.cs | 6 +-- .../Interfaces/IPriceHistoryCacheUnit.cs | 2 +- KLHZ.Trader.Core.Math/Common/Lines.cs | 8 ++-- .../Declisions/Dtos/PeriodPricesInfoDto.cs | 12 ++--- .../Services/Cache/PriceHistoryCacheUnit.cs | 10 ++-- .../Services/Cache/PriceHistoryCacheUnit2.cs | 12 ++--- .../Declisions/Utils/MovingAverage.cs | 22 +++++---- .../Declisions/Utils/TwoPeriods.cs | 48 +++++++++---------- .../HistoryCacheUnit2Tests.cs | 18 +++---- .../HistoryCacheUnitTests.cs | 4 +- .../HistoryProcessingInstrumentsTests.cs | 14 +++--- KLHZ.Trader.Core.Tests/LinesProcessingTest.cs | 16 +++---- KLHZ.Trader.Core/Exchange/Services/Trader.cs | 6 ++- 13 files changed, 94 insertions(+), 84 deletions(-) diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs b/KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs index 83c07a1..d16f12f 100644 --- a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs +++ b/KLHZ.Trader.Core.Contracts/Declisions/Dtos/TwoPeriodsResultDto.cs @@ -5,13 +5,13 @@ public readonly int Start; public readonly int Bound; public readonly int End; - public readonly float DiffStart; - public readonly float DiffEnd; + public readonly decimal DiffStart; + public readonly decimal DiffEnd; public readonly bool Success; public readonly TimeSpan PeriodStart; public readonly TimeSpan PeriodEnd; - public TwoPeriodsResultDto(bool success, float diffStart, float diffEnd, int start, int bound, int end, + public TwoPeriodsResultDto(bool success, decimal diffStart, decimal diffEnd, int start, int bound, int end, TimeSpan periodStart, TimeSpan periodEnd) { Success = success; diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs b/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs index baaba9d..446767c 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, float[] prices)> GetData(); + public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData(); public ValueTask AddOrderbook(IOrderbook orderbook); /// diff --git a/KLHZ.Trader.Core.Math/Common/Lines.cs b/KLHZ.Trader.Core.Math/Common/Lines.cs index 5736969..b116f8a 100644 --- a/KLHZ.Trader.Core.Math/Common/Lines.cs +++ b/KLHZ.Trader.Core.Math/Common/Lines.cs @@ -2,7 +2,7 @@ { public static class Lines { - public static (float x, float y) LinesCrossing(float k1, float b1, float k2, float b2) + public static (decimal x, decimal y) LinesCrossing(decimal k1, decimal b1, decimal k2, decimal b2) { var x = (b2 - b1) / (k1 - k2); var y = k1 * x + b1; @@ -10,9 +10,9 @@ return (x, y); } - public static bool IsLinesCrossing(DateTime time1, DateTime time2, float val1_1, float val1_2, float val2_1, float val2_2) + public static bool IsLinesCrossing(DateTime time1, DateTime time2, decimal val1_1, decimal val1_2, decimal val2_1, decimal val2_2) { - var dtime = (float)(time2 - time1).TotalSeconds; + var dtime = (decimal)(time2 - time1).TotalSeconds; var dval1 = val1_2 - val1_1; var k1 = dval1 / dtime; @@ -25,7 +25,7 @@ if (k1 != k2) { var cross = LinesCrossing(k1, b1, k2, b2); - var crossingTimestamp = time1.AddSeconds(cross.x); + var crossingTimestamp = time1.AddSeconds((double)cross.x); return crossingTimestamp >= time1 && crossingTimestamp <= time2; } return false; diff --git a/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs b/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs index 399d83b..b1d7e58 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Dtos/PeriodPricesInfoDto.cs @@ -4,15 +4,15 @@ { public readonly int Start; public readonly int End; - public readonly float LastPrice; - public readonly float FirstPrice; - public readonly float PeriodDiff; - public readonly float PeriodMax; - public readonly float PeriodMin; + 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, float firstPrice, float lastPrice, float periodDiff, float periodMin, float periodMax, TimeSpan period, int start, int end) + public PeriodPricesInfoDto(bool success, decimal firstPrice, decimal lastPrice, decimal periodDiff, decimal periodMin, decimal periodMax, TimeSpan period, int start, int end) { Success = success; LastPrice = lastPrice; diff --git a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs index 52a30e8..6d222da 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit.cs @@ -24,7 +24,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache public decimal BidsCount => 1; private readonly object _locker = new(); - private readonly float[] Prices = new float[CacheMaxLength]; + private readonly decimal[] Prices = new decimal[CacheMaxLength]; private readonly DateTime[] Timestamps = new DateTime[CacheMaxLength]; private int _length = 0; @@ -36,7 +36,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache Array.Copy(Prices, 1, Prices, 0, Prices.Length - 1); Array.Copy(Timestamps, 1, Timestamps, 0, Timestamps.Length - 1); - Prices[Prices.Length - 1] = (float)priceChange.Value; + Prices[Prices.Length - 1] = priceChange.Value; Timestamps[Timestamps.Length - 1] = priceChange.Time; if (_length < CacheMaxLength) @@ -47,11 +47,11 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache return ValueTask.CompletedTask; } - public ValueTask<(DateTime[] timestamps, float[] prices)> GetData() + public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData() { lock (_locker) { - var prices = new float[_length]; + var prices = new decimal[_length]; var timestamps = new DateTime[_length]; Array.Copy(Prices, Prices.Length - _length, prices, 0, prices.Length); Array.Copy(Timestamps, Prices.Length - _length, timestamps, 0, timestamps.Length); @@ -79,7 +79,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache .Skip(priceChanges.Length - CacheMaxLength) .ToArray(); var prices = selectedPriceChanges - .Select(pc => (float)pc.Value) + .Select(pc => pc.Value) .ToArray(); var times = selectedPriceChanges .Select(pc => pc.Time) diff --git a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs index baf5a74..1fcb33f 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Services/Cache/PriceHistoryCacheUnit2.cs @@ -44,7 +44,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache } private readonly object _locker = new(); - private readonly float[] Prices = new float[_arrayMaxLength]; + private readonly decimal[] Prices = new decimal[_arrayMaxLength]; private readonly DateTime[] Timestamps = new DateTime[_arrayMaxLength]; private int _length = 0; @@ -59,7 +59,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache lock (_locker) { _pointer++; - Prices[_pointer] = (float)priceChange.Value; + Prices[_pointer] = priceChange.Value; Timestamps[_pointer] = priceChange.Time; if (_length < CacheMaxLength) { @@ -76,17 +76,17 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache return ValueTask.CompletedTask; } - public ValueTask<(DateTime[] timestamps, float[] prices)> GetData() + public ValueTask<(DateTime[] timestamps, decimal[] prices)> GetData() { lock (_locker) { if (_pointer < 0) { - return ValueTask.FromResult((Array.Empty(), Array.Empty())); + return ValueTask.FromResult((Array.Empty(), Array.Empty())); } else { - var prices = new float[_length]; + 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); @@ -123,7 +123,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Services.Cache foreach (var pc in selectedPriceChanges) { - AddData(pc); + AddData(pc).AsTask().Wait(); } } } diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs index 5831302..aa33551 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs @@ -5,10 +5,10 @@ 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) + 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 = 1; + var count = 1m; var startTime = timestamps[timestamps.Length - 1 - shift]; for (int i = 2; i < values.Length && startTime - timestamps[values.Length - i - shift] < TimeSpan.FromSeconds(window); i++) { @@ -18,12 +18,18 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return (startTime, sum / count); } - public static TradingEvent CheckByWindowAverageMean(DateTime[] timestamps, float[] prices, int size, float meanfullStep = 3f) + public static TradingEvent CheckByWindowAverageMean(DateTime[] timestamps, decimal[] prices, int size, decimal meanfullStep = 3m) { - var twav15s = new float[size]; - var twav120s = new float[size]; - var times = new DateTime[size]; var res = TradingEvent.None; + if (timestamps.Length < size) + { + return res; + } + var twav15s = new decimal[size]; + var twav120s = new decimal[size]; + var times = new DateTime[size]; + + for (int shift = 0; shift < size; shift++) { var twav15 = CalcTimeWindowAverageValue(timestamps, prices, 15, shift); @@ -38,8 +44,8 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils } if (shift > 0) { - var i1 = size - 1 - shift; - var i2 = size - 2 - shift; + var i1 = size - shift; + var i2 = size - 1 - shift; var isCrossing = Lines.IsLinesCrossing( times[i1], times[i2], diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs index 947070b..7d33f3d 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs @@ -21,8 +21,8 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils var lastPriceTime = times[times.Length - 1]; var intervalEnd = lastPriceTime - timeShift; var intervalStart = intervalEnd - timeSpan; - var max = float.MinValue; - var min = float.MaxValue; + var max = decimal.MinValue; + var min = decimal.MaxValue; var intervaEndIndex = -1; var intervaStartIndex = -1; @@ -69,18 +69,18 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return res; } - internal static bool CheckStable(this PeriodPricesInfoDto data, float meanfullDiff) + internal static bool CheckStable(this PeriodPricesInfoDto data, decimal meanfullDiff) { meanfullDiff = System.Math.Abs(meanfullDiff); - return data.Success && System.Math.Abs(data.PeriodDiff) < 1.5 * meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 2 * meanfullDiff; + return data.Success && System.Math.Abs(data.PeriodDiff) < 1.5m * meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 2 * meanfullDiff; } - internal static bool CheckGrowing(this PeriodPricesInfoDto data, float meanfullDiff) + internal static bool CheckGrowing(this PeriodPricesInfoDto data, decimal meanfullDiff) { return meanfullDiff > 0 && data.Success && data.PeriodDiff > meanfullDiff && System.Math.Abs(data.PeriodMax - data.PeriodMin) < 3 * System.Math.Abs(data.PeriodDiff); } - internal static bool CheckFalling(this PeriodPricesInfoDto data, float meanfullDiff) + internal static bool CheckFalling(this PeriodPricesInfoDto data, 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); @@ -88,20 +88,20 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils internal static float CalcTrendRelationAbs(PeriodPricesInfoDto first, PeriodPricesInfoDto second) { - var k1 = System.Math.Abs(first.PeriodDiff) / System.Math.Abs(first.Period.TotalSeconds); - var k2 = System.Math.Abs(second.PeriodDiff) / System.Math.Abs(second.Period.TotalSeconds); + 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(data.PeriodStart.TotalSeconds); - var k2 = System.Math.Abs(data.DiffEnd) / System.Math.Abs(data.PeriodEnd.TotalSeconds); + 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, float meanfullDiff) + 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); @@ -121,7 +121,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return res; } - internal static bool CheckUptrendEnding(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff) + 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); @@ -141,7 +141,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return res; } - internal static bool CheckDowntrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff) + 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); @@ -156,7 +156,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return totalDiff.Success && (isStartStable || isStartGrows) && isEndFalls && trendRelation >= 2; } - internal static bool CheckUptrendStarting(this PriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff) + 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); @@ -185,7 +185,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return res; } - internal static TwoPeriodsResultDto GetTwoPeriodsProcessingData(this (DateTime[] timestamps, float[] prices) data, TimeSpan shift, int shiftPointsStart, int shiftPointsEnd, TimeSpan firstPeriod, float meanfullDiff) + 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; @@ -222,12 +222,12 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return res; } - public static bool CheckLongClose(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff, int pointsStart, int pointsEnd) + public static bool CheckLongClose(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 trendRelation = CalcTrendRelationAbs(periodStat); - var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5 * meanfullDiff; + var isStartOk = periodStat.Success && periodStat.DiffStart > 0 && periodStat.DiffStart > 1.5m * meanfullDiff; var isEndOk = periodStat.Success && periodStat.DiffEnd < meanfullDiff; if (isEndOk) @@ -247,7 +247,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return isStartOk && isEndOk && data.prices[periodStat.End] - data.prices[periodStat.Start] >= meanfullDiff; } - internal static bool CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float 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); @@ -272,7 +272,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils return isStartOk && isEndOk; } - internal static bool _CheckUptrendStarting2(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float 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, 1, firstPeriod, meanfullDiff); @@ -298,7 +298,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils } - public static bool CheckLongOpen(this IPriceHistoryCacheUnit unit, TimeSpan firstPeriod, TimeSpan secondPeriod, float meanfullDiff, int pointsStart, int pointsEnd) + 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); @@ -325,14 +325,14 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils public static TradingEvent Detect(IPriceHistoryCacheUnit data) { - float meanfullDiff; + decimal meanfullDiff; if (data.Figi == "BBG004730N88") { - meanfullDiff = 0.05f; + meanfullDiff = 0.05m; } else if (data.Figi == "FUTIMOEXF000") { - meanfullDiff = 1f; + meanfullDiff = 1m; } else { @@ -352,7 +352,7 @@ 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.5f, 8, 8); + 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); uptrendEnds |= uptrendEnds2; if (uptrendEnds) diff --git a/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs b/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs index edb1c33..64906df 100644 --- a/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs +++ b/KLHZ.Trader.Core.Tests/HistoryCacheUnit2Tests.cs @@ -46,7 +46,7 @@ namespace KLHZ.Trader.Core.Tests var count = 1; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count); @@ -64,7 +64,7 @@ namespace KLHZ.Trader.Core.Tests var count = 20; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count); @@ -83,7 +83,7 @@ namespace KLHZ.Trader.Core.Tests var count = PriceHistoryCacheUnit.CacheMaxLength; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count); @@ -103,7 +103,7 @@ namespace KLHZ.Trader.Core.Tests var count = PriceHistoryCacheUnit.CacheMaxLength + shift; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count - shift); @@ -127,7 +127,7 @@ namespace KLHZ.Trader.Core.Tests var count = PriceHistoryCacheUnit.CacheMaxLength + shift; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count - shift); @@ -151,7 +151,7 @@ namespace KLHZ.Trader.Core.Tests var count = PriceHistoryCacheUnit.CacheMaxLength + shift; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count - shift); @@ -175,7 +175,7 @@ namespace KLHZ.Trader.Core.Tests var count = PriceHistoryCacheUnit.CacheMaxLength; var figi = "figi"; var hist = GetHistory(count, figi); - var cacheUnit = new PriceHistoryCacheUnit2("", hist); + var cacheUnit = new PriceHistoryCacheUnit2(figi, hist); var data = cacheUnit.GetData().Result; Assert.That(data.prices.Length == count); @@ -192,7 +192,7 @@ namespace KLHZ.Trader.Core.Tests cacheUnit.AddData(newData1); var data2 = cacheUnit.GetData().Result; - Assert.IsTrue(data2.prices[data2.prices.Length - 1] == (float)newData1.Value); + Assert.IsTrue(data2.prices[data2.prices.Length - 1] == newData1.Value); Assert.IsTrue(data2.timestamps[data2.timestamps.Length - 1] == newData1.Time); var newData2 = new PriceChange() { Figi = figi, Ticker = figi, Value = 100501, Time = DateTime.UtcNow }; @@ -200,7 +200,7 @@ namespace KLHZ.Trader.Core.Tests cacheUnit.AddData(newData2); var data3 = cacheUnit.GetData().Result; - Assert.IsTrue(data3.prices[data3.prices.Length - 1] == (float)newData2.Value); + Assert.IsTrue(data3.prices[data3.prices.Length - 1] == newData2.Value); Assert.IsTrue(data3.timestamps[data3.timestamps.Length - 1] == newData2.Time); } diff --git a/KLHZ.Trader.Core.Tests/HistoryCacheUnitTests.cs b/KLHZ.Trader.Core.Tests/HistoryCacheUnitTests.cs index d721f91..9406c0f 100644 --- a/KLHZ.Trader.Core.Tests/HistoryCacheUnitTests.cs +++ b/KLHZ.Trader.Core.Tests/HistoryCacheUnitTests.cs @@ -192,7 +192,7 @@ namespace KLHZ.Trader.Core.Tests cacheUnit.AddData(newData1); var data2 = cacheUnit.GetData().Result; - Assert.IsTrue(data2.prices[data2.prices.Length - 1] == (float)newData1.Value); + Assert.IsTrue(data2.prices[data2.prices.Length - 1] == newData1.Value); Assert.IsTrue(data2.timestamps[data2.timestamps.Length - 1] == newData1.Time); var newData2 = new PriceChange() { Figi = figi, Ticker = figi, Value = 100501, Time = DateTime.UtcNow }; @@ -200,7 +200,7 @@ namespace KLHZ.Trader.Core.Tests cacheUnit.AddData(newData2); var data3 = cacheUnit.GetData().Result; - Assert.IsTrue(data3.prices[data3.prices.Length - 1] == (float)newData2.Value); + Assert.IsTrue(data3.prices[data3.prices.Length - 1] == newData2.Value); Assert.IsTrue(data3.timestamps[data3.timestamps.Length - 1] == newData2.Time); } } diff --git a/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs b/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs index fb32831..4b4b195 100644 --- a/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs +++ b/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs @@ -6,7 +6,7 @@ namespace KLHZ.Trader.Core.Tests { public class HistoryProcessingInstrumentsTests { - private static PriceChange[] GetHistory(int count, string figi, DateTime startDt, float startValue, float step) + private static PriceChange[] GetHistory(int count, string figi, DateTime startDt, decimal startValue, decimal step) { var res = new PriceChange[count]; if (count != 0) @@ -21,7 +21,7 @@ namespace KLHZ.Trader.Core.Tests Ticker = figi + "_ticker", Id = i, Time = startDt, - Value = (decimal)startValue, + Value = startValue, }; } } @@ -68,7 +68,7 @@ namespace KLHZ.Trader.Core.Tests var figi = "figi"; var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc); var count = 100; - var step = 0.5f; + var step = 0.5m; var startValue = 10; var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step)); @@ -102,7 +102,7 @@ namespace KLHZ.Trader.Core.Tests var figi = "figi"; var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc); var count = 100; - var step = 0.5f; + var step = 0.5m; var startValue = 10; var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step)); @@ -137,7 +137,7 @@ namespace KLHZ.Trader.Core.Tests var figi = "figi"; var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc); var count = 100; - var step = -0.5f; + var step = -0.5m; var startValue = 10; var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step)); @@ -172,7 +172,7 @@ namespace KLHZ.Trader.Core.Tests var figi = "figi"; var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc); var count = 100; - var step = -0.5f; + var step = -0.5m; var startValue = 10; var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step)); @@ -207,7 +207,7 @@ namespace KLHZ.Trader.Core.Tests var figi = "figi"; var startDate = new DateTime(2020, 1, 1, 1, 0, 0, DateTimeKind.Utc); var count = 100; - var step = -0.5f; + var step = -0.5m; var startValue = 10; var unit = new PriceHistoryCacheUnit(figi, GetHistory(count, figi, startDate, startValue, step)); diff --git a/KLHZ.Trader.Core.Tests/LinesProcessingTest.cs b/KLHZ.Trader.Core.Tests/LinesProcessingTest.cs index fc475b6..888e5d3 100644 --- a/KLHZ.Trader.Core.Tests/LinesProcessingTest.cs +++ b/KLHZ.Trader.Core.Tests/LinesProcessingTest.cs @@ -10,11 +10,11 @@ namespace KLHZ.Trader.Core.Tests var time2 = DateTime.UtcNow; var time1 = time2.AddSeconds(-20); - var val1_1 = 0.5f; - var val1_2 = -0.5f; + var val1_1 = 0.5m; + var val1_2 = -0.5m; - var val2_1 = -0.5f; - var val2_2 = 0.5f; + var val2_1 = -0.5m; + var val2_2 = 0.5m; Assert.IsTrue(Lines.IsLinesCrossing(time1, time2, val1_1, val1_2, val2_1, val2_2)); } @@ -25,11 +25,11 @@ namespace KLHZ.Trader.Core.Tests var time2 = DateTime.UtcNow; var time1 = time2.AddSeconds(-20); - var val1_1 = 0.5f; - var val1_2 = -0.5f; + var val1_1 = 0.5m; + var val1_2 = -0.5m; - var val2_1 = 0.5f; - var val2_2 = -0.5f; + var val2_1 = 0.5m; + var val2_2 = -0.5m; Assert.IsFalse(Lines.IsLinesCrossing(time1, time2, val1_1, val1_2, val2_1, val2_2)); } diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs index 4629f8b..3f06c09 100644 --- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs @@ -135,7 +135,11 @@ namespace KLHZ.Trader.Core.Exchange.Services var declisionsForSave = new List(); if (message.Figi == "FUTIMOEXF000") { - var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 3f); + if (unit.Length < 100) + { + continue; + } + var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 2m); if ((result & TradingEvent.StopBuy) == TradingEvent.StopBuy) { var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);