From bcc084c49c0b07a019f44c212b8bbf336e72ca62 Mon Sep 17 00:00:00 2001 From: vlad zverzhkhovskiy Date: Wed, 17 Sep 2025 09:53:56 +0300 Subject: [PATCH] =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20=D0=B2=D1=80=D0=B5=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=B1=D1=80?= =?UTF-8?q?=D0=BE=D1=81=D0=B0=20=D0=B0=D0=BA=D1=82=D0=B8=D0=B2=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs | 2 +- KLHZ.Trader.Core/Exchange/Services/Trader.cs | 106 ++++++++++-------- .../Controllers/PlayController.cs | 2 +- 3 files changed, 59 insertions(+), 51 deletions(-) diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs index f3acfc0..e1024df 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Utils/FFT.cs @@ -15,7 +15,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils { return ValueAmplitudePosition.UpperThen30Decil; } - else if (value < fftData.Mediana) + else if (value < fftData.Mediana && System.Math.Sign(value2)>=0) { return ValueAmplitudePosition.LowerThenMediana; } diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs index 7ba5c91..0ea1a82 100644 --- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs @@ -92,7 +92,7 @@ namespace KLHZ.Trader.Core.Exchange.Services var currentTime = message.IsHistoricalData ? message.Time : DateTime.UtcNow; var position = ValueAmplitudePosition.None; var fft = await _tradeDataProvider.GetFFtResult(message.Figi); - var step = message.IsHistoricalData ? 90 : 10; + var step = message.IsHistoricalData ? 5 : 5; if (fft.IsEmpty || (currentTime - fft.LastTime).TotalSeconds > step) { if (data.isFullIntervalExists) @@ -190,7 +190,7 @@ namespace KLHZ.Trader.Core.Exchange.Services try { - if (message.Figi == "FUTIMOEXF000") + if (message.Figi == "FUTIMOEXF000" && message.Direction==1) { ProcessStops(message, currentTime); var windowMaxSize = 2000; @@ -227,7 +227,7 @@ namespace KLHZ.Trader.Core.Exchange.Services var profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value, GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0); var stoppingKey = message.Figi + asset.AccountId; - if (message.Time - asset.BoughtAt > TimeSpan.FromMinutes(4) && profit < -66m) + if (profit < -66m) { var command = new TradeCommand() { @@ -250,10 +250,10 @@ namespace KLHZ.Trader.Core.Exchange.Services } private async Task CheckByWindowAverageMean((DateTime[] timestamps, decimal[] prices) data, - INewPrice message, int windowMaxSize) + INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m) { var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, - windowMaxSize, 30, 180, TimeSpan.FromSeconds(20), -1m, 2m); + windowMaxSize, 30, 180, TimeSpan.FromSeconds(20), uptrendStartingDetectionMeanfullStep, uptrendEndingDetectionMeanfullStep); if (resultMoveAvFull.bigWindowAv != 0) { await LogPrice(message, Constants.BigWindowCrossingAverageProcessor, resultMoveAvFull.bigWindowAv); @@ -262,8 +262,16 @@ namespace KLHZ.Trader.Core.Exchange.Services return resultMoveAvFull.events; } + private async Task CheckByWindowAverageMeanNolog((DateTime[] timestamps, decimal[] prices) data, + INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullStep = 0m, decimal uptrendEndingDetectionMeanfullStep = 3m) + { + var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, + windowMaxSize, 30, 180, TimeSpan.FromSeconds(20), uptrendStartingDetectionMeanfullStep, uptrendEndingDetectionMeanfullStep); + return resultMoveAvFull.events; + } + private async Task CheckByWindowAverageMeanForShotrs((DateTime[] timestamps, decimal[] prices) data, - INewPrice message, int windowMaxSize) + INewPrice message, int windowMaxSize) { var resultMoveAvFull = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, windowMaxSize, 30, 240, TimeSpan.FromSeconds(20), -1m, 1m); @@ -351,17 +359,21 @@ namespace KLHZ.Trader.Core.Exchange.Services var dsell = (sells / su - 0.5m) * 2; - var mavTask = CheckByWindowAverageMean(data, message, windowMaxSize); + var mavTask = CheckByWindowAverageMean(data, message, windowMaxSize, -1, 2m); + var mavTaskEnds = CheckByWindowAverageMeanNolog(data, message, windowMaxSize, -1, 1m); + var mavTaskShorts = CheckByWindowAverageMeanForShotrs(data, message, windowMaxSize); var ltTask = CheckByLocalTrends(data, message, windowMaxSize); var areasTask = GetAreasRelation(data, message); var positionTask = CheckPosition(message); var trendTask = CalcTrendDiff(message); - await Task.WhenAll(mavTask, ltTask, areasTask, positionTask, trendTask, mavTaskShorts); + var ends = mavTaskEnds.Result & TradingEvent.UptrendEnd; + + await Task.WhenAll(mavTask, ltTask, areasTask, positionTask, trendTask, mavTaskShorts, mavTaskEnds); var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi); var res = mavTask.Result | ltTask.Result; - + res |= ends; if ((res & TradingEvent.UptrendStart) == TradingEvent.UptrendStart && !LongOpeningStops.ContainsKey(message.Figi) && trendTask.Result.HasValue @@ -410,56 +422,52 @@ namespace KLHZ.Trader.Core.Exchange.Services } if ((res & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd) { - //if (dsell < 0.1m) + if (!message.IsHistoricalData && BotModeSwitcher.CanSell()) { - if (!message.IsHistoricalData && BotModeSwitcher.CanSell()) + var loggedDeclisions = 0; + var assetsForClose = _tradeDataProvider.Accounts + .SelectMany(a => a.Value.Assets.Values) + .Where(a => a.Figi == message.Figi && a.Count > 0) + .ToArray(); + foreach (var asset in assetsForClose) { - var loggedDeclisions = 0; - var assetsForClose = _tradeDataProvider.Accounts - .SelectMany(a => a.Value.Assets.Values) - .Where(a => a.Figi == message.Figi && a.Count > 0) - .ToArray(); - foreach (var asset in assetsForClose) + var profit = 0m; + + if (assetType == AssetType.Common && asset.Count > 0) { - var profit = 0m; + profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value, + GetComission(assetType), 1, false); + } + if (assetType == AssetType.Futures) + { + profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value, + GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0); + } - if (assetType == AssetType.Common && asset.Count > 0) + if (profit > 0) + { + LongClosingStops[message.Figi] = message.Time.AddSeconds(30); + var command = new TradeCommand() { - profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value, - GetComission(assetType), 1, false); - } - if (assetType == AssetType.Futures) + AccountId = asset.AccountId, + Figi = message.Figi, + CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell, + Count = (long)asset.Count, + RecomendPrice = null, + EnableMargin = false, + }; + await _dataBus.Broadcast(command); + _logger.LogWarning("Продажа актива {figi}! id команды {commandId}. Направление сделки: {dir}; Количество активов: {count}; Разрешена ли маржиналка: {margin}", + message.Figi, command.CommandId, command.CommandType, command.Count, command.EnableMargin); + if (loggedDeclisions == 0) { - profit = TradingCalculator.CaclProfit(asset.BoughtPrice, message.Value, - GetComission(assetType), GetLeverage(message.Figi, asset.Count < 0), asset.Count < 0); - } - - if (profit > 0) - { - LongClosingStops[message.Figi] = message.Time.AddSeconds(30); - var command = new TradeCommand() - { - AccountId = asset.AccountId, - Figi = message.Figi, - CommandType = Contracts.Messaging.Dtos.Enums.TradeCommandType.MarketSell, - Count = (long)asset.Count, - RecomendPrice = null, - EnableMargin = false, - }; - await _dataBus.Broadcast(command); - _logger.LogWarning("Продажа актива {figi}! id команды {commandId}. Направление сделки: {dir}; Количество активов: {count}; Разрешена ли маржиналка: {margin}", - message.Figi, command.CommandId, command.CommandType, command.Count, command.EnableMargin); - if (loggedDeclisions == 0) - { - loggedDeclisions++; - await LogDeclision(DeclisionTradeAction.CloseLongReal, message, profit); - } + loggedDeclisions++; + await LogDeclision(DeclisionTradeAction.CloseLongReal, message, profit); } } } - await LogDeclision(DeclisionTradeAction.CloseLong, message); } - + await LogDeclision(DeclisionTradeAction.CloseLong, message); } if ((mavTaskShorts.Result & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd) diff --git a/KLHZ.Trader.Service/Controllers/PlayController.cs b/KLHZ.Trader.Service/Controllers/PlayController.cs index 3a2713b..595a509 100644 --- a/KLHZ.Trader.Service/Controllers/PlayController.cs +++ b/KLHZ.Trader.Service/Controllers/PlayController.cs @@ -34,7 +34,7 @@ namespace KLHZ.Trader.Service.Controllers //var figi1 = "BBG004730N88"; var figi2 = "BBG004730N88"; //var figi2 = "FUTIMOEXF000"; - var time1 = DateTime.UtcNow.AddDays(-16.5); + var time1 = DateTime.UtcNow.AddDays(-17); //var time2 = DateTime.UtcNow.AddMinutes(18); using var context1 = await _dbContextFactory.CreateDbContextAsync(); context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;