From c2105ad0199c76abb4a339a73714410fb290ac33 Mon Sep 17 00:00:00 2001 From: vlad zverzhkhovskiy Date: Tue, 9 Sep 2025 11:57:43 +0300 Subject: [PATCH] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D0=B8=D1=81=D0=B8=20=D0=B2=20=D0=B1=D0=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Declisions/Utils/MovingAverage.cs | 143 +++++++++--------- .../Exchange/Services/ExchangeDataReader.cs | 20 ++- KLHZ.Trader.Core/Exchange/Services/Trader.cs | 6 +- 3 files changed, 87 insertions(+), 82 deletions(-) diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs index 43fdb75..029c80d 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs @@ -26,107 +26,100 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils var bigWindowAv = 0m; var smallWindowAv = 0m; var s = 0; - try + var pricesForFinalComparison = new decimal[size]; + var twavss = new decimal[size]; + var twavbs = new decimal[size]; + var times = new DateTime[size]; + var crossings = new List(); + for (int shift = 0; shift < size - 1 && shift < prices.Length - 1; shift++) { - var pricesForFinalComparison = new decimal[size]; - var twavss = new decimal[size]; - var twavbs = new decimal[size]; - var times = new DateTime[size]; - var crossings = new List(); - for (int shift = 0; shift < size - 1 && shift < prices.Length - 1; shift++) + s = shift; + var i2 = size - 1 - shift; + var i1 = size - 2 - shift; + + var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift); + var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift); + pricesForFinalComparison[i2] = prices[prices.Length - 1 - shift]; + + if (shift == 0) { - s = shift; - var i2 = size - 1 - shift; - var i1 = size - 2 - shift; + bigWindowAv = twavb.value; + smallWindowAv = twavs.value; + } + twavss[i2] = twavs.value; + twavbs[i2] = twavb.value; + times[i2] = twavb.time; - var twavs = CalcTimeWindowAverageValue(timestamps, prices, smallWindow, shift); - var twavb = CalcTimeWindowAverageValue(timestamps, prices, bigWindow, shift); - pricesForFinalComparison[i2] = prices[prices.Length - 1 - shift]; + if (shift > 0) + { + var isCrossing = Lines.IsLinesCrossing( + times[i1 + 1], + times[i2 + 1], + twavss[i1 + 1], + twavss[i2 + 1], + twavbs[i1 + 1], + twavbs[i2 + 1]); - if (shift == 0) + if (shift == 1 && !isCrossing.res) //если нет пересечения скользящих средний с окном 120 и 15 секунд между + //текущей и предыдущей точкой - можно не продолжать выполнение. { - bigWindowAv = twavb.value; - smallWindowAv = twavs.value; + break; } - twavss[i2] = twavs.value; - twavbs[i2] = twavb.value; - times[i2] = twavb.time; - if (shift > 0) + if (isCrossing.res) { - var isCrossing = Lines.IsLinesCrossing( - times[i1 + 1], - times[i2 + 1], - twavss[i1 + 1], - twavss[i2 + 1], - twavbs[i1 + 1], - twavbs[i2 + 1]); - - if (shift == 1 && !isCrossing.res) //если нет пересечения скользящих средний с окном 120 и 15 секунд между - //текущей и предыдущей точкой - можно не продолжать выполнение. + crossings.Add(i2); + if (crossings.Count == 4 || (shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) { - break; - } - - if (isCrossing.res) - { - crossings.Add(i2); - if (crossings.Count == 4 || (shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) + if ((shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) { - if ((shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) + crossings.Add(shift); + } + var diffTotal = pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]]; + for (int crossingShift = 1; crossingShift < crossings.Count - 2; crossingShift++) + { + var diff = pricesForFinalComparison[crossings[crossingShift]] - pricesForFinalComparison[crossings[crossingShift + 1]]; + if (diff >= 0) { - crossings.Add(shift); + diffTotal += diff; } - var diffTotal = pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]]; - for (int crossingShift = 1; crossingShift < crossings.Count - 2; crossingShift++) + else { - var diff = pricesForFinalComparison[crossings[crossingShift]] - pricesForFinalComparison[crossings[crossingShift + 1]]; - if (diff >= 0) - { - diffTotal += diff; - } - else - { - break; - } - } - - // если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта - if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2]) - { - if (diffTotal >= uptrendEndingDetectionMeanfullStep - && times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart) - { - res |= TradingEvent.UptrendEnd; - } break; } } - if (crossings.Count == 2 || (shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) + // если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта + if (twavss[size - 1] <= twavbs[size - 1] && twavss[size - 2] > twavbs[size - 2]) { - if ((shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) + if (diffTotal >= uptrendEndingDetectionMeanfullStep + && times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart) { - crossings.Add(shift); + res |= TradingEvent.UptrendEnd; } - // если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта - if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2]) + break; + } + } + + if (crossings.Count == 2 || (shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) + { + if ((shift + 1 == size - 1 || shift + 1 == prices.Length - 1)) + { + crossings.Add(shift); + } + // если фильтрация окном 120 наползает на окно 15 сверху, потенциальное время открытия лонга и закрытия шорта + if (twavss[size - 1] >= twavbs[size - 1] && twavss[size - 2] < twavbs[size - 2]) + { + if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] <= -downtrendStartingDetectionMeanfullStep + && times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart) { - if (pricesForFinalComparison[crossings[0]] - pricesForFinalComparison[crossings[1]] <= -downtrendStartingDetectionMeanfullStep - && times[crossings[0]] - times[crossings[1]] >= timeForUptreandStart) - { - res |= TradingEvent.UptrendStart; - } - break; + res |= TradingEvent.UptrendStart; } + break; } } } } - } - catch (Exception ex) - { - } return (res, bigWindowAv, smallWindowAv); } diff --git a/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs b/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs index 384a156..7bf1860 100644 --- a/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Tinkoff.InvestApi; using Tinkoff.InvestApi.V1; +using static Google.Rpc.Context.AttributeContext.Types; namespace KLHZ.Trader.Core.Exchange.Services { @@ -55,7 +56,7 @@ namespace KLHZ.Trader.Core.Exchange.Services { try { - //_ = SubscribeUpdates(); + _ = SubscribeMyTrades(); if (_exchangeDataRecievingEnabled) { _ = SubscribePrices(); @@ -69,7 +70,7 @@ namespace KLHZ.Trader.Core.Exchange.Services } } - private async Task SubscribeUpdates() + private async Task SubscribeMyTrades() { var req = new TradesStreamRequest(); foreach (var a in _tradeDataProvider.Accounts) @@ -81,7 +82,18 @@ namespace KLHZ.Trader.Core.Exchange.Services { if (response.OrderTrades != null) { - + foreach(var t in response.OrderTrades.Trades) + { + //await _tradeDataProvider.LogDeal(new Models.AssetsAccounting.DealResult() + //{ + // AccountId = response.OrderTrades.AccountId, + // Figi = response.OrderTrades.Figi, + // Count = t.Quantity, + // Price = t.Price, + // Direction = Models.AssetsAccounting.DealDirection + //}) + } + } } } @@ -210,7 +222,7 @@ namespace KLHZ.Trader.Core.Exchange.Services await _eventBus.Broadcast(message); } - if (orderbookItemsBuffer.Count + pricesBuffer.Count + tradesBuffer.Count > 0 || (DateTime.UtcNow - lastWrite).TotalSeconds > 10) + if (orderbookItemsBuffer.Count + pricesBuffer.Count + tradesBuffer.Count > 100 || (DateTime.UtcNow - lastWrite).TotalSeconds > 5) { try { diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs index 9410407..ea9291f 100644 --- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs @@ -210,7 +210,7 @@ namespace KLHZ.Trader.Core.Exchange.Services { var assetType = _tradeDataProvider.GetAssetTypeByFigi(message.Figi); var loggedDeclisions = 0; - if (BotModeSwitcher.CanSell()) + if (!message.IsHistoricalData && BotModeSwitcher.CanSell()) { var assetsForClose = _tradeDataProvider.Accounts .SelectMany(a => a.Value.Assets.Values) @@ -283,7 +283,7 @@ namespace KLHZ.Trader.Core.Exchange.Services Processor = processor, Time = message.Time, Value = value, - }, !message.IsHistoricalData); + }, false); } private async Task LogDeclision(DeclisionTradeAction action, INewPrice message, decimal? profit = null) @@ -297,7 +297,7 @@ namespace KLHZ.Trader.Core.Exchange.Services Price = message.Value, Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow, Action = action, - }, !message.IsHistoricalData); + }, false); } public Task StopAsync(CancellationToken cancellationToken)