From 022cee9a1982a55a3b95fa26d302686943b4257f Mon Sep 17 00:00:00 2001 From: vlad zverzhkhovskiy Date: Tue, 14 Oct 2025 14:05:15 +0300 Subject: [PATCH] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=D1=8B=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=B5=D0=B3?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Declisions/Utils/Statistics.cs | 4 +- KLHZ.Trader.Core/Exchange/Constants.cs | 3 +- .../Models/Trading/DeferredDeclision.cs | 14 ++ .../Models/Trading/PirsonCalculatingResult.cs | 1 + .../Exchange/Models/Trading/SupportLevel.cs | 1 + KLHZ.Trader.Core/Exchange/Services/Trader.cs | 236 ++++++++++++++---- .../Exchange/Services/TraderDataProvider.cs | 7 +- .../Exchange/Utils/ExchangeScheduler.cs | 5 +- KLHZ.Trader.Service/appsettings.json | 2 +- 9 files changed, 219 insertions(+), 54 deletions(-) create mode 100644 KLHZ.Trader.Core/Exchange/Models/Trading/DeferredDeclision.cs diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/Statistics.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/Statistics.cs index 333dc3e..2642dc0 100644 --- a/KLHZ.Trader.Core.Math/Declisions/Utils/Statistics.cs +++ b/KLHZ.Trader.Core.Math/Declisions/Utils/Statistics.cs @@ -56,9 +56,10 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils } public static bool TryCalcTimeWindowsDiff(this ITradeDataItem[] values, TimeSpan boundLeft, TimeSpan boundRight, - Func fieldSelector, bool calcMean, out decimal result) + Func fieldSelector, bool calcMean, out decimal result, out decimal resultRelative) { result = default; + resultRelative = default; if (values.Length > 1) { var shiftTimeR = values.Last().Time - boundRight; @@ -78,6 +79,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils valOld = valOld / valuesOld.Length; } result = valNew - valOld; + resultRelative = (valNew - valOld) / valOld; return true; } } diff --git a/KLHZ.Trader.Core/Exchange/Constants.cs b/KLHZ.Trader.Core/Exchange/Constants.cs index 9561705..d98f92b 100644 --- a/KLHZ.Trader.Core/Exchange/Constants.cs +++ b/KLHZ.Trader.Core/Exchange/Constants.cs @@ -15,10 +15,11 @@ internal const string AreasRelationProcessor = "balancescalc30min"; internal readonly static TimeSpan AreasRelationWindow = TimeSpan.FromMinutes(15); + internal const decimal ForceExecuteCoefficient = 500000m; internal const decimal PowerUppingCoefficient = 1.69m; internal const decimal UppingCoefficient = 1.3m; internal const decimal LowingCoefficient = .76m; internal const decimal PowerLowingCoefficient = .59m; - internal const decimal BlockingCoefficient = 0m; + internal const decimal BlockingCoefficient = 0.01m; } } diff --git a/KLHZ.Trader.Core/Exchange/Models/Trading/DeferredDeclision.cs b/KLHZ.Trader.Core/Exchange/Models/Trading/DeferredDeclision.cs new file mode 100644 index 0000000..dddc365 --- /dev/null +++ b/KLHZ.Trader.Core/Exchange/Models/Trading/DeferredDeclision.cs @@ -0,0 +1,14 @@ +using KLHZ.Trader.Core.Contracts.Declisions.Dtos.Enums; +using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces; +using System.Collections.Immutable; + +namespace KLHZ.Trader.Core.Exchange.Models.Trading +{ + internal class DeferredDeclision + { + public ImmutableDictionary Events { get; init; } = ImmutableDictionary.Empty; + public Stops Stops { get; init; } + public DateTime ExpirationTime { get; init; } + public required ITradeDataItem Message { get; init; } + } +} diff --git a/KLHZ.Trader.Core/Exchange/Models/Trading/PirsonCalculatingResult.cs b/KLHZ.Trader.Core/Exchange/Models/Trading/PirsonCalculatingResult.cs index f844dd8..fe2123c 100644 --- a/KLHZ.Trader.Core/Exchange/Models/Trading/PirsonCalculatingResult.cs +++ b/KLHZ.Trader.Core/Exchange/Models/Trading/PirsonCalculatingResult.cs @@ -6,5 +6,6 @@ public decimal Pirson { get; init; } public decimal PriceDiff { get; init; } public decimal TradesDiff { get; init; } + public decimal TradesDiffRelative { get; init; } } } diff --git a/KLHZ.Trader.Core/Exchange/Models/Trading/SupportLevel.cs b/KLHZ.Trader.Core/Exchange/Models/Trading/SupportLevel.cs index a2806de..5de1ff6 100644 --- a/KLHZ.Trader.Core/Exchange/Models/Trading/SupportLevel.cs +++ b/KLHZ.Trader.Core/Exchange/Models/Trading/SupportLevel.cs @@ -6,5 +6,6 @@ public decimal LowValue { get; init; } public decimal HighValue { get; init; } public DateTime? LastLevelTime { get; init; } + public DateTime CalculatedAt { get; init; } } } diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs index a37f5e9..5f998cf 100644 --- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs +++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs @@ -34,9 +34,14 @@ namespace KLHZ.Trader.Core.Exchange.Services private readonly ConcurrentDictionary TradingModes = new(); + private readonly ConcurrentDictionary DeferredDeclisions = new(); private readonly ConcurrentDictionary SupportLevels = new(); - private readonly ConcurrentDictionary DPirsonValues = new(); + private readonly ConcurrentDictionary _pirsonValues = new(); + private readonly ConcurrentDictionary _dpirsonValues = new(); private readonly ConcurrentDictionary _supportLevelsCalculationTimes = new(); + private readonly ConcurrentDictionary _usedSupportLevels = new(); + private readonly ConcurrentDictionary _usedSupportLevelsForClosing = new(); + private readonly ConcurrentDictionary _oldItems = new(); private readonly Channel _pricesChannel = Channel.CreateUnbounded(); private readonly Channel _commands = Channel.CreateUnbounded(); @@ -161,44 +166,109 @@ namespace KLHZ.Trader.Core.Exchange.Services { if (message.Figi == "FUTIMOEXF000") { + if (DeferredDeclisions.TryGetValue(message.Figi, out var dec)) + { + if (dec.ExpirationTime < message.Time) + { + if (dec.Events[TradingEvent.OpenShort] > Constants.BlockingCoefficient) + { + if (dec.Message.Price < message.Price) + { + var stops2 = GetStops(message); + var declisionsStops2 = ProcessStops(stops2, 2m); + var e = TraderUtils.MergeResultsMult(dec.Events, declisionsStops2); + await ExecuteDeclisions(e.ToImmutableDictionary(), message, stops2, 1); + } + } + else if (dec.Events[TradingEvent.OpenLong] > Constants.BlockingCoefficient) + { + if (dec.Message.Price > message.Price) + { + var stops2 = GetStops(message); + var declisionsStops2 = ProcessStops(stops2, 2m); + var e = TraderUtils.MergeResultsMult(dec.Events, declisionsStops2); + await ExecuteDeclisions(e.ToImmutableDictionary(), message, stops2, 1); + } + } + else if (dec.Events[TradingEvent.CloseLong] > Constants.BlockingCoefficient + || dec.Events[TradingEvent.CloseShort] > Constants.BlockingCoefficient) + { + await ExecuteDeclisions(dec.Events, dec.Message, dec.Stops, 1); + } + + DeferredDeclisions.TryRemove(message.Figi, out _); + } + } + await CalcSupportLevels(message, 3, 5); var stops = GetStops(message); var pirson = await CalcPirson(message); var declisionPirson = await ProcessPirson(pirson, message); var declisionsSupportLevels = await ProcessSupportLevels(message); - var declisionsStops = ProcessStops(stops, 1.5m); + var declisionsStops = ProcessStops(stops, 2m); var res = TraderUtils.MergeResultsMult(declisionPirson, declisionsSupportLevels); res = TraderUtils.MergeResultsMult(res, declisionsStops); await ExecuteDeclisions(res.ToImmutableDictionary(), message, stops, 1); + + var declision = new DeferredDeclision() + { + Message = message, + Stops = stops, + Events = res.ToImmutableDictionary(), + ExpirationTime = message.Time.AddSeconds(5) + }; + + if (declision.Events.Values.Any(v => v > Constants.BlockingCoefficient)) + { + //DeferredDeclisions.TryAdd(message.Figi, declision); + } + + _oldItems[message.Figi] = message; } } private async Task> ProcessPirson(PirsonCalculatingResult pirson, ITradeDataItem message) { - var res = TraderUtils.GetInitDict(0); - if (pirson.Success && DPirsonValues.TryGetValue(message.Figi, out var olddpirs)) + var res = TraderUtils.GetInitDict(Constants.BlockingCoefficient); + if (pirson.Success && _pirsonValues.TryGetValue(message.Figi, out var olddpirs)) { - if (olddpirs < -0.3m && pirson.Pirson > -0.3m && pirson.PriceDiff > 0 && (pirson.TradesDiff > 0)) + var dpirson = pirson.Pirson - olddpirs; + if (olddpirs < 0 && pirson.Pirson > 0 && pirson.PriceDiff > 0 && (pirson.TradesDiffRelative > 0.2m)) { res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient; - await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_long_in", message.Price); } - if (olddpirs > 0.3m && pirson.Pirson < 0.3m && pirson.PriceDiff < 0 && (pirson.TradesDiff > 0)) + //if (olddpirs < -0.7m && pirson.Pirson > -0.7m && pirson.PriceDiff > 0 && (pirson.TradesDiffRelative < -0.1m)) + //{ + // res[TradingEvent.OpenLong] = Constants.PowerUppingCoefficient; + //} + + if (olddpirs > 0 && pirson.Pirson < 0 && pirson.PriceDiff < 0 && (pirson.TradesDiffRelative > 0.2m)) { res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient; - await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_short_in", message.Price); } - if (olddpirs > 0.7m && pirson.Pirson < 0.7m) + //if (olddpirs > 0.3m && pirson.Pirson < 0.3m && pirson.PriceDiff < 0 && (pirson.TradesDiffRelative > 0.3m)) + //{ + // res[TradingEvent.OpenShort] = Constants.PowerUppingCoefficient; + //} + + if (_dpirsonValues.TryGetValue(message.Figi, out var oldDprison)) { - // await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_long_out", message.Price); - } - if (olddpirs < -0.7m && pirson.Pirson > -0.7m) - { - // await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_short_out", message.Price); + if (oldDprison > 0.02m && dpirson < -0.02m && pirson.Pirson > 0.7m && pirson.TradesDiffRelative < -0.2m) + { + res[TradingEvent.CloseLong] = Constants.PowerUppingCoefficient; + //await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_long_out", message.Price); + } + if (oldDprison < 0 && dpirson > 0 && pirson.Pirson < -0.6m && pirson.TradesDiffRelative < -0.1m) + { + res[TradingEvent.CloseShort] = Constants.PowerUppingCoefficient; + // await _tradeDataProvider.LogPrice(message, "diffs_pirson_diff_point_short_out", message.Price); + } } + + _dpirsonValues[message.Figi] = dpirson; } - DPirsonValues[message.Figi] = pirson.Pirson; + _pirsonValues[message.Figi] = pirson.Pirson; return res.ToImmutableDictionary(); } @@ -212,7 +282,7 @@ namespace KLHZ.Trader.Core.Exchange.Services var buys = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, cacheSize, selector: (i) => i.Direction == 1); var trades = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, cacheSize); - if (trades.TryCalcTimeWindowsDiff(bigWindow, smallWindow, v => v.Count, false, out var tradesDiff) + if (trades.TryCalcTimeWindowsDiff(bigWindow, smallWindow, v => v.Count, false, out var tradesDiff, out var tradesDiffRelative) && buys.TryCalcTimeDiff(bigWindow, smallWindow, v => v.Price, true, out var pricesDiff)) { await _tradeDataProvider.LogPrice(message, "privcesDiff", pricesDiff); @@ -243,6 +313,7 @@ namespace KLHZ.Trader.Core.Exchange.Services Pirson = res, PriceDiff = pricesDiff, TradesDiff = tradesDiff, + TradesDiffRelative = tradesDiffRelative, Success = true, }; } @@ -276,10 +347,10 @@ namespace KLHZ.Trader.Core.Exchange.Services var data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, TimeSpan.FromHours(depthHours)); if (data.Length > 0) { - if (data[^1].Time - data[0].Time < TimeSpan.FromHours(depthHours - 1)) + if (data[^1].Time - data[0].Time < TimeSpan.FromHours(0.5)) { data = await _tradeDataProvider.GetDataForTimeWindow(message.Figi, TimeSpan.FromHours(depthHours + 12)); - if (data[^1].Time - data[0].Time < TimeSpan.FromHours(depthHours - 1)) + if (data[^1].Time - data[0].Time < TimeSpan.FromHours(0.5)) { return; } @@ -305,6 +376,7 @@ namespace KLHZ.Trader.Core.Exchange.Services HighValue = high, LowValue = low, Value = c.Value, + CalculatedAt = message.Time, }); } else if (last.HighValue >= low && last.HighValue < high) @@ -313,7 +385,8 @@ namespace KLHZ.Trader.Core.Exchange.Services { LowValue = last.LowValue, HighValue = high, - Value = last.LowValue + (high - last.LowValue) / 2 + Value = last.LowValue + (high - last.LowValue) / 2, + CalculatedAt = message.Time, }; } } @@ -324,6 +397,7 @@ namespace KLHZ.Trader.Core.Exchange.Services HighValue = high, LowValue = low, Value = c.Value, + CalculatedAt = message.Time, }); } } @@ -346,6 +420,7 @@ namespace KLHZ.Trader.Core.Exchange.Services LowValue = level.LowValue, Value = level.Value, LastLevelTime = time, + CalculatedAt = message.Time, }; i++; } @@ -426,7 +501,7 @@ namespace KLHZ.Trader.Core.Exchange.Services var sign = positionType == PositionType.Long ? 1 : 1; foreach (var acc in accounts) { - if (TraderUtils.IsOperationAllowed(acc, message.Price, 1, _exchangeConfig.AccountCashPartFutures, _exchangeConfig.AccountCashPart)) + if (TraderUtils.IsOperationAllowed(acc, message.Price, count, _exchangeConfig.AccountCashPartFutures, _exchangeConfig.AccountCashPart)) { await acc.OpenPosition(message.Figi, positionType, stopLossShift, takeProfitShift, count); await _dataBus.Broadcast(new MessageForAdmin() @@ -448,7 +523,7 @@ namespace KLHZ.Trader.Core.Exchange.Services private async Task ExecuteDeclisions(ImmutableDictionary result, ITradeDataItem message, Stops st, int accountsForOpening = 1) { - var state = ExchangeScheduler.GetCurrentState(); + var state = ExchangeScheduler.GetCurrentState(message.Time); if (result[TradingEvent.OpenLong] >= Constants.UppingCoefficient && state == ExchangeState.Open ) @@ -464,15 +539,18 @@ namespace KLHZ.Trader.Core.Exchange.Services .ToArray(); await OpenPositions(accounts, message, PositionType.Long, stops.stopLoss, stops.takeProfit, 1); } - await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenLong, message.Price, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message); - await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, message.Price + stops.takeProfit, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message); - await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, message.Price - stops.stopLoss, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message); + var val = message.Price; + var valLow = message.Price - stops.stopLoss; + var valHigh = message.Price + stops.takeProfit; + await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenLong, val, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message); + //await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valHigh, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message); + await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsLong, valLow, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message); } if (result[TradingEvent.OpenShort] >= Constants.UppingCoefficient && state == ExchangeState.Open ) { - var stops = st.GetStops(PositionType.Long); + var stops = st.GetStops(PositionType.Short); if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase()) { var accounts = _portfolioWrapper.Accounts @@ -482,12 +560,14 @@ namespace KLHZ.Trader.Core.Exchange.Services .ToArray(); await OpenPositions(accounts, message, PositionType.Short, stops.stopLoss, stops.takeProfit, 1); } - - await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenShort, message.Price, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message); - await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, message.Price - stops.takeProfit, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message); - await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, message.Price + stops.stopLoss, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message); + var val = message.Price; + var valLow = message.Price - stops.takeProfit; + var valHigh = message.Price + stops.stopLoss; + await _tradeDataProvider.LogDeclision(DeclisionTradeAction.OpenShort, val, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(-100, 100)), message); + //await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, valLow, message.Time.AddMilliseconds(-RandomNumberGenerator.GetInt32(300, 1000)), message); + await _tradeDataProvider.LogDeclision(DeclisionTradeAction.ResetStopsShort, valHigh, message.Time.AddMilliseconds(RandomNumberGenerator.GetInt32(300, 1000)), message); } - if (result[TradingEvent.CloseLong] >= Constants.UppingCoefficient * 10) + if (result[TradingEvent.CloseLong] >= Constants.UppingCoefficient) { if (!message.IsHistoricalData && BotModeSwitcher.CanSell()) { @@ -501,7 +581,7 @@ namespace KLHZ.Trader.Core.Exchange.Services } - if (result[TradingEvent.CloseShort] >= Constants.UppingCoefficient * 10) + if (result[TradingEvent.CloseShort] >= Constants.UppingCoefficient) { if (!message.IsHistoricalData && BotModeSwitcher.CanPurchase()) { @@ -550,10 +630,11 @@ namespace KLHZ.Trader.Core.Exchange.Services private Stops GetStops(ITradeDataItem message) { - decimal longStopLossShift = message.Value * 0.99m; - decimal longTakeProfitShift = message.Value * 1.03m; - decimal shortStopLossShift = message.Value * 0.99m; - decimal shortTakeProfitShift = message.Value * 1.03m; + var additionalShift = message.Price * 0.001m; + var longStopLossShift = message.Price * 0.0025m; + var longTakeProfitShift = message.Price * 0.02m; + var shortStopLossShift = message.Price * 0.0025m; + var shortTakeProfitShift = message.Price * 0.02m; if (SupportLevels.TryGetValue(message.Figi, out var levels)) { if (levels.Length > 0) @@ -564,16 +645,29 @@ namespace KLHZ.Trader.Core.Exchange.Services if (message.Price >= levelsByTime[0].LowValue && message.Price < levelsByTime[0].HighValue) { longStopLossShift = message.Price - levelsByTime[0].LowValue; - shortStopLossShift = message.Price + levelsByTime[0].HighValue; + shortStopLossShift = levelsByTime[0].HighValue - message.Price; } else { - var levelsByDiff = levels.Where(l => l.LastLevelTime.HasValue) - .OrderBy(l => System.Math.Abs(l.Value - message.Price)) + var levelsByDiffForLong = levels.Where(l => l.LastLevelTime.HasValue) + .OrderBy(l => l.Value - message.Price) .ToArray(); - var nearestLevel = levelsByDiff[0]; - longStopLossShift = message.Price - nearestLevel.HighValue; - shortStopLossShift = nearestLevel.LowValue - message.Price; + + var levelsByDiffForShort = levels.Where(l => l.LastLevelTime.HasValue) + .OrderByDescending(l => l.Value - message.Price) + .ToArray(); + + var nearestLevel = levelsByDiffForLong[0]; + if (message.Price > nearestLevel.HighValue) + { + longStopLossShift = message.Price - nearestLevel.HighValue + additionalShift; + } + + nearestLevel = levelsByDiffForShort[0]; + if (message.Price < nearestLevel.LowValue) + { + shortStopLossShift = nearestLevel.LowValue - message.Price + additionalShift; + } } } } @@ -613,17 +707,69 @@ namespace KLHZ.Trader.Core.Exchange.Services var levelsByTime = levels.Where(l => l.LastLevelTime.HasValue) .OrderByDescending(l => l.LastLevelTime) .ToArray(); - - if (message.Price >= levelsByTime[0].LowValue && message.Price < levelsByTime[0].HighValue) + var levelByTime = levelsByTime[0]; + if (message.Price >= levelByTime.LowValue && message.Price < levelByTime.HighValue) { - if (message.Price > levelsByTime[0].Value) + if (message.Price > levelByTime.Value) { res[TradingEvent.OpenLong] = Constants.BlockingCoefficient; } - if (message.Price < levelsByTime[0].Value) + if (message.Price < levelByTime.Value) { res[TradingEvent.OpenShort] = Constants.BlockingCoefficient; } + if (_oldItems.TryGetValue(message.Figi, out var old1)) + { + var islevelUsed = false; + if (_usedSupportLevelsForClosing.TryGetValue(message.Figi, out var time)) + { + if (time == levelByTime.CalculatedAt) + { + islevelUsed = true; + } + } + if (!islevelUsed) + { + if (old1.Price < levelByTime.LowValue || levelByTime.CalculatedAt == message.Time) + { + res[TradingEvent.CloseLong] = Constants.ForceExecuteCoefficient; + _usedSupportLevelsForClosing[message.Figi] = levelByTime.CalculatedAt; + } + if (old1.Price > levelByTime.HighValue || levelByTime.CalculatedAt == message.Time) + { + res[TradingEvent.CloseShort] = Constants.ForceExecuteCoefficient; + _usedSupportLevelsForClosing[message.Figi] = levelByTime.CalculatedAt; + } + } + + } + } + else if (_oldItems.TryGetValue(message.Figi, out var old)) + { + if (old.Price >= levelByTime.LowValue && old.Price < levelByTime.HighValue) + { + var islevelUsed = false; + if (_usedSupportLevels.TryGetValue(message.Figi, out var time)) + { + if (time == levelByTime.CalculatedAt) + { + islevelUsed = true; + } + } + if (!islevelUsed) + { + if (message.Price < levelByTime.LowValue) + { + res[TradingEvent.OpenShort] = Constants.ForceExecuteCoefficient; + _usedSupportLevels[message.Figi] = levelByTime.CalculatedAt; + } + else if (message.Price > levelByTime.HighValue) + { + res[TradingEvent.OpenLong] = Constants.ForceExecuteCoefficient; + _usedSupportLevels[message.Figi] = levelByTime.CalculatedAt; + } + } + } } } } diff --git a/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs b/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs index 1d79dcc..d3f8f2b 100644 --- a/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs +++ b/KLHZ.Trader.Core/Exchange/Services/TraderDataProvider.cs @@ -24,6 +24,7 @@ namespace KLHZ.Trader.Core.Exchange.Services private readonly IDbContextFactory _dbContextFactory; private readonly ILogger _logger; private readonly string[] _instrumentsFigis = []; + private readonly string[] _tradingInstrumentsFigis = []; public readonly ConcurrentDictionary Orderbooks = new(); private readonly ConcurrentDictionary _tickersCache = new(); @@ -40,6 +41,7 @@ namespace KLHZ.Trader.Core.Exchange.Services _dbContextFactory = dbContextFactory; _logger = logger; _instrumentsFigis = options.Value.DataRecievingInstrumentsFigis.ToArray(); + _tradingInstrumentsFigis = options.Value.TradingInstrumentsFigis.ToArray(); _isDataRecievingAllowed = options.Value.ExchangeDataRecievingEnabled; } @@ -142,11 +144,11 @@ namespace KLHZ.Trader.Core.Exchange.Services if (_isDataRecievingAllowed) { - var time = DateTime.UtcNow.AddHours(-5); + var time = DateTime.UtcNow.AddHours(-20); using var context1 = await _dbContextFactory.CreateDbContextAsync(); context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var data = await context1.PriceChanges - .Where(c => _instrumentsFigis.Contains(c.Figi) && c.Time >= time) + .Where(c => _tradingInstrumentsFigis.Contains(c.Figi) && c.Time >= time) .OrderBy(c => c.Time) .Select(c => new TradeDataItem() { @@ -262,6 +264,7 @@ namespace KLHZ.Trader.Core.Exchange.Services Action = action, }, false); } + private async Task WritePricesTask() { var buffer1 = new List(); diff --git a/KLHZ.Trader.Core/Exchange/Utils/ExchangeScheduler.cs b/KLHZ.Trader.Core/Exchange/Utils/ExchangeScheduler.cs index 3da9f71..311bbfa 100644 --- a/KLHZ.Trader.Core/Exchange/Utils/ExchangeScheduler.cs +++ b/KLHZ.Trader.Core/Exchange/Utils/ExchangeScheduler.cs @@ -23,10 +23,7 @@ namespace KLHZ.Trader.Core.Exchange.Utils var time = TimeOnly.FromDateTime(dt); if (day == DayOfWeek.Sunday || day == DayOfWeek.Saturday) { - if (time > _openTimeHoliday && time < _closeTimeHoliday) - { - return ExchangeState.Open; - } + return ExchangeState.Close; } else { diff --git a/KLHZ.Trader.Service/appsettings.json b/KLHZ.Trader.Service/appsettings.json index 89e4b01..ea712f5 100644 --- a/KLHZ.Trader.Service/appsettings.json +++ b/KLHZ.Trader.Service/appsettings.json @@ -12,7 +12,7 @@ "Token": "", "ManagingAccountNamePatterns": [ "автотрейд" ], "DataRecievingInstrumentsFigis": [ "BBG004730N88", "FUTIMOEXF000", "FUTGMKN09250", "FUTBR1025000", "FUTNG0925000", "FUTNASD09250" ], - "TradingInstrumentsFigis": [ "FUTIMOEXF000", "BBG004730N88" ], + "TradingInstrumentsFigis": [ "FUTIMOEXF000"], "FutureComission": 0.0025, "ShareComission": 0.0004, "AccountCashPart": 0.05,