diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs index 1301c70..ab480b5 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs @@ -15,14 +15,10 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils { return ValueAmplitudePosition.UpperThen30Decil; } - else if (value < fftData.Mediana && System.Math.Sign(value2) >= 0) + else if (value < fftData.Mediana) { return ValueAmplitudePosition.LowerThenMedianaGrowing; } - else if (value < fftData.Mediana && System.Math.Sign(value2) < 0) - { - return ValueAmplitudePosition.LowerThenMedianaFalling; - } else { return ValueAmplitudePosition.Middle; @@ -65,6 +61,58 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils } } + public static (DateTime[] timestamps, decimal[] values) TrimValues(DateTime[] timestamps, decimal[] values, TimeSpan period) + { + int i = 0; + var lastTime = timestamps[timestamps.Length - 1]; + for (i=0;i< timestamps.Length; i++) + { + if ((lastTime - timestamps[timestamps.Length - i-1]) > period) + { + break; + } + } + + var resDt = new DateTime[i]; + var resVs = new decimal[i]; + + Array.Copy(timestamps, timestamps.Length - i, resDt, 0, i); + Array.Copy(values, values.Length - i, resVs, 0, i); + + return (resDt, resVs); + } + + public static FFTAnalyzeResult GetMainHarmonic(DateTime[] timestamps, decimal[] values, string key, TimeSpan minPeriod) + { + var startPeriod = timestamps[timestamps.Length - 1] - timestamps[0]; + var results = new List<(float, Harmonic[], TimeSpan, Harmonic)>(); + var max = 0f; + while (startPeriod> minPeriod) + { + var data = TrimValues(timestamps, values, startPeriod); + var harmonics = GetHarmonics(values, startPeriod, TimeSpan.FromSeconds(5), startPeriod); + var summMagn = harmonics.Sum(h => h.Magnitude); + (float, Harmonic[], TimeSpan, Harmonic)? res = null; + for (int i=2;i< harmonics.Length; i++) + { + var currentMagn = harmonics[i].Magnitude / summMagn/ harmonics.Length; + if (currentMagn> max) + { + res = (currentMagn, harmonics, startPeriod, harmonics[i]); + } + } + if (res != null) + { + results.Add(res.Value); + } + startPeriod = startPeriod - TimeSpan.FromSeconds(30); + } + + var t = results.MaxBy(r => r.Item1); + + return FFTAnalyzeResult.Empty; + } + public static FFTAnalyzeResult Analyze(DateTime[] timestamps, decimal[] values, string key, TimeSpan minPeriod, TimeSpan maxPeriod) { var harmonics = GetHarmonics(values, timestamps[timestamps.Length - 1] - timestamps[0], minPeriod, maxPeriod); diff --git a/KLHZ.Trader.Core.Tests/FFTTests.cs b/KLHZ.Trader.Core.Tests/FFTTests.cs index f0e77e9..19ba7d5 100644 --- a/KLHZ.Trader.Core.Tests/FFTTests.cs +++ b/KLHZ.Trader.Core.Tests/FFTTests.cs @@ -219,5 +219,26 @@ namespace KLHZ.Trader.Core.Tests Assert.IsTrue(res.max > System.Math.PI / 2); Assert.IsTrue(res.max < System.Math.PI / 2 * 1.1); } + + [Test] + public static void TrimValues_Test1() + { + var da = new List(); + var dates = new List(); + var dt = DateTime.UtcNow; + var dt1 = dt; + var dt2 = dt.AddSeconds(3600); + var i = 0; + while (dt < dt2) + { + da.Add(i); + dates.Add(dt); + dt = dt.AddSeconds(1); + i++; + } + + var res = FFT.TrimValues(dates.ToArray(), da.ToArray(), TimeSpan.FromSeconds(30)); + var res2 = FFT.TrimValues(dates.ToArray(), da.ToArray(), TimeSpan.FromSeconds(4011)); + } } } diff --git a/KLHZ.Trader.Core/Exchange/Constants.cs b/KLHZ.Trader.Core/Exchange/Constants.cs index 2b10187..9561705 100644 --- a/KLHZ.Trader.Core/Exchange/Constants.cs +++ b/KLHZ.Trader.Core/Exchange/Constants.cs @@ -3,8 +3,10 @@ internal static class Constants { internal const string _1minCacheKey = "1min"; + internal const string _15minSellCacheKey = "5min_sell"; internal const string _5minSellCacheKey = "5min_sell"; internal const string _5minBuyCacheKey = "5min_buy"; + internal const string _15minBuyCacheKey = "5min_buy"; internal const string _1minSellCacheKey = "1min_sell"; internal const string _1minBuyCacheKey = "1min_buy"; diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs index badd7a2..40df5b9 100644 --- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs @@ -95,15 +95,11 @@ namespace KLHZ.Trader.Core.Exchange.Services public async ValueTask<(DateTime[] timestamps, decimal[] prices, bool isFullIntervalExists)> GetData(INewPrice message, TimeSpan? windowSize = null) { - var data2 = await _tradeDataProvider.GetData(message.Figi, windowSize??TimeSpan.FromHours(1.5)); - if (!data2.isFullIntervalExists) - { - data2 = await _tradeDataProvider.GetData(message.Figi, TimeSpan.FromHours(1)); - } - if (!data2.isFullIntervalExists) - { - data2 = await _tradeDataProvider.GetData(message.Figi, TimeSpan.FromHours(0.75)); - } + var data2 = await _tradeDataProvider.GetData(message.Figi, windowSize??TimeSpan.FromHours(1)); + //if (!data2.isFullIntervalExists) + //{ + // data2 = await _tradeDataProvider.GetData(message.Figi, TimeSpan.FromHours(0.75)); + //} return data2; } @@ -141,13 +137,13 @@ namespace KLHZ.Trader.Core.Exchange.Services if (data.isFullIntervalExists) { var interpolatedData = SignalProcessing.InterpolateData(data.timestamps, data.prices, TimeSpan.FromSeconds(5)); - fftFull = FFT.Analyze(interpolatedData.timestamps, interpolatedData.values, message.Figi+"_full", TimeSpan.FromSeconds(30), TimeSpan.FromHours(24)); + fftFull = FFT.Analyze(interpolatedData.timestamps, interpolatedData.values, message.Figi+"_full", TimeSpan.FromMinutes(2), TimeSpan.FromMinutes(30)); - fft = FFT.ReAnalyze(fftFull, message.Figi, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(60)); + //fft = FFT.ReAnalyze(fftFull, message.Figi, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(60)); //highFreq = FFT.ReAnalyze(fftFull, message.Figi + "_low_freq", TimeSpan.FromMinutes(20), TimeSpan.FromMinutes(60)); //lowFreq = FFT.ReAnalyze(fftFull, message.Figi + "_high_freq", TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(20)); - - await _tradeDataProvider.SetFFtResult(fft); + //var tmp = FFT.GetMainHarmonic(interpolatedData.timestamps, interpolatedData.values, "mainHarm", TimeSpan.FromMinutes(20)); + //await _tradeDataProvider.SetFFtResult(fft); await _tradeDataProvider.SetFFtResult(fftFull); //await _tradeDataProvider.SetFFtResult(lowFreq); //await _tradeDataProvider.SetFFtResult(highFreq); @@ -166,7 +162,7 @@ namespace KLHZ.Trader.Core.Exchange.Services - position = FFT.Check(fft, message.Time); + position = FFT.Check(fftFull, message.Time); if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil) { await LogPrice(message, "upper30percent", message.Value); @@ -176,6 +172,8 @@ namespace KLHZ.Trader.Core.Exchange.Services await LogPrice(message, "lower30percent", message.Value); } + + //var hposition = FFT.CheckExtremums(highFreq, message.Time); //if (hposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil) //{ @@ -340,6 +338,11 @@ namespace KLHZ.Trader.Core.Exchange.Services Time = message.Time, Value = (decimal)message.Count }); + await _tradeDataProvider.AddDataTo15MinuteWindowCache(message.Figi, Constants._15minBuyCacheKey, new Contracts.Declisions.Dtos.CachedValue() + { + Time = message.Time, + Value = (decimal)message.Count + }); await _tradeDataProvider.AddDataTo1MinuteWindowCache(message.Figi, Constants._1minBuyCacheKey, new Contracts.Declisions.Dtos.CachedValue() { Time = message.Time, @@ -353,6 +356,11 @@ namespace KLHZ.Trader.Core.Exchange.Services Time = message.Time, Value = (decimal)message.Count }); + await _tradeDataProvider.AddDataTo15MinuteWindowCache(message.Figi, Constants._15minSellCacheKey, new Contracts.Declisions.Dtos.CachedValue() + { + Time = message.Time, + Value = (decimal)message.Count + }); await _tradeDataProvider.AddDataTo1MinuteWindowCache(message.Figi, Constants._1minSellCacheKey, new Contracts.Declisions.Dtos.CachedValue() { Time = message.Time, @@ -533,12 +541,12 @@ namespace KLHZ.Trader.Core.Exchange.Services private async Task> GetSpeedResultantMods(INewPrice message) { var res = GetInitDict(1); - var buys5min = await _tradeDataProvider.GetDataFrom5MinuteWindowCache(message.Figi, Constants._5minBuyCacheKey); - var sells5min = await _tradeDataProvider.GetDataFrom5MinuteWindowCache(message.Figi, Constants._5minSellCacheKey); + var buys5min = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, Constants._15minBuyCacheKey); + var sells5min = await _tradeDataProvider.GetDataFrom15MinuteWindowCache(message.Figi, Constants._15minSellCacheKey); var buysSpeed5min = buys5min.Sum(p => p.Value) / 300; var sellsSpeed5min = sells5min.Sum(p => p.Value) / 300; var diff5min = buysSpeed5min - sellsSpeed5min; - await LogPrice(message, "speed_diff_5min", diff5min); + await LogPrice(message, "speed_diff_15min", diff5min); if (diff5min < 0) { @@ -699,7 +707,7 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt var windows = await GetWindowsSizes(message); //var resTask1 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, -2m, 2m,3); - var resTask1 = GetWindowAverageStartData(data, (int)windows.smallWindow, (int)windows.bigWindow, message, windowMaxSize, -0.5m, 0.5m); + var resTask1 = GetWindowAverageStartData(data, (int)windows.smallWindow, (int)windows.bigWindow, message, windowMaxSize, -1m, 1m); ////var resTask3 = GetWindowAverageStartData(data, 30, 180, message, windowMaxSize, 0, 0,0.7m); var getFFTModsTask = GetFFTMods(message); var getLocalTrendsModsTask = GetLocalTrendsMods(data, message); @@ -969,7 +977,7 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt } if (mode == TradingMode.SlowDropping && type == PositionType.Short) { - takeProfitShift = 4m; + } if (mode == TradingMode.SlowDropping && type == PositionType.Long) { diff --git a/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs b/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs index 69a437c..eea3fa3 100644 --- a/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs +++ b/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs @@ -146,6 +146,16 @@ namespace KLHZ.Trader.Core.Exchange.Services await _historyCash[figi].AddDataToTimeWindowCache(key, data, TimeWindowCacheType._5_Minutes); } + public async ValueTask AddDataTo15MinuteWindowCache(string figi, string key, CachedValue data) + { + if (!_historyCash.TryGetValue(figi, out var unit)) + { + unit = new PriceHistoryCacheUnit2(figi); + _historyCash.TryAdd(figi, unit); + } + await _historyCash[figi].AddDataToTimeWindowCache(key, data, TimeWindowCacheType._15_Minutes); + } + public ValueTask GetDataFrom20SecondsWindowCache(string figi, string key) { if (_historyCash.TryGetValue(figi, out var cahcheItem)) @@ -173,6 +183,15 @@ namespace KLHZ.Trader.Core.Exchange.Services return ValueTask.FromResult(Array.Empty()); } + public ValueTask GetDataFrom15MinuteWindowCache(string figi, string key) + { + if (_historyCash.TryGetValue(figi, out var cahcheItem)) + { + return cahcheItem.GetDataFromTimeWindowCache(key, TimeWindowCacheType._15_Minutes); + } + return ValueTask.FromResult(Array.Empty()); + } + public async ValueTask AddOrderbook(IOrderbook orderbook) { if (!_historyCash.TryGetValue(orderbook.Figi, out var unit)) diff --git a/KLHZ.Trader.Service/Controllers/PlayController.cs b/KLHZ.Trader.Service/Controllers/PlayController.cs index 12d54df..bf493e8 100644 --- a/KLHZ.Trader.Service/Controllers/PlayController.cs +++ b/KLHZ.Trader.Service/Controllers/PlayController.cs @@ -46,7 +46,7 @@ namespace KLHZ.Trader.Service.Controllers context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; - while (time1 < DateTime.UtcNow) + while (time1 < DateTime.UtcNow.Date) { var data = new List(); var data2 = new List();