diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs b/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs
index 3ebc7a7..ed4ab8d 100644
--- a/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs
+++ b/KLHZ.Trader.Core.Contracts/Declisions/Dtos/Enums/TradingEvent.cs
@@ -9,5 +9,7 @@
ShortClose = 4,
LongClose = 8,
ShortOpen = 16,
+ UptrendEnd = 32,
+ UptrendStart = 64,
}
}
diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs
similarity index 93%
rename from KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs
rename to KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs
index 7d33f3d..def5810 100644
--- a/KLHZ.Trader.Core.Math/Declisions/Utils/TwoPeriods.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Utils/LocalTrends.cs
@@ -9,7 +9,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
///
/// Обработка последних интервалов истории изменения цен.
///
- public static class TwoPeriods
+ public static class LocalTrends
{
internal static PeriodPricesInfoDto GetPriceDiffForTimeSpan(this IPriceHistoryCacheUnit unit, TimeSpan timeShift, TimeSpan timeSpan, int? pointsShift = null)
{
@@ -302,42 +302,14 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
var data = unit.GetData().Result;
var periodStat = data.GetTwoPeriodsProcessingData(secondPeriod, pointsStart, pointsEnd, firstPeriod, meanfullDiff);
- var trendRelation = CalcTrendRelationAbs(periodStat);
var isStartOk = periodStat.Success && periodStat.DiffStart < -meanfullDiff;
var isEndOk = periodStat.Success && periodStat.DiffEnd >= meanfullDiff;
-
- if (isEndOk)
- {
-
- }
-
- if (isStartOk)
- {
-
- }
-
- if (isEndOk && isStartOk)
- {
-
- }
return isStartOk && isEndOk && data.prices[periodStat.Start] - data.prices[periodStat.End] >= meanfullDiff;
}
public static TradingEvent Detect(IPriceHistoryCacheUnit data)
{
- decimal meanfullDiff;
- if (data.Figi == "BBG004730N88")
- {
- meanfullDiff = 0.05m;
- }
- else if (data.Figi == "FUTIMOEXF000")
- {
- meanfullDiff = 1m;
- }
- else
- {
- return TradingEvent.None;
- }
+ decimal meanfullDiff = 1m;
var res = TradingEvent.None;
//var downtrendStarts = data.CheckDowntrendStarting(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(7), meanfullDiff);
diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs
index 20045a2..74b1351 100644
--- a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs
@@ -77,10 +77,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
if (pricesForFinalComparison[i2 + 1] - pricesForFinalComparison[size - 1] >= meanfullStep)
{
- res |= TradingEvent.LongOpen;
- res |= TradingEvent.ShortClose;
- break;
+ res |= TradingEvent.UptrendStart;
}
+ break;
}
// если фильтрация окном 15 наползает на окно 120 сверху, потенциальное время закрытия лонга и возможно открытия шорта
@@ -88,10 +87,9 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
if (pricesForFinalComparison[i2 + 1] - pricesForFinalComparison[size - 1] <= -meanfullStep)
{
- res |= TradingEvent.LongClose;
- res |= TradingEvent.ShortOpen;
- break;
+ res |= TradingEvent.UptrendEnd;
}
+ break;
}
}
}
diff --git a/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs b/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs
index 4b4b195..f2d6a6c 100644
--- a/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs
+++ b/KLHZ.Trader.Core.Tests/HistoryProcessingInstrumentsTests.cs
@@ -45,7 +45,7 @@ namespace KLHZ.Trader.Core.Tests
var periodLength = 4;
var shift = 0;
- var result = TwoPeriods.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
@@ -79,7 +79,7 @@ namespace KLHZ.Trader.Core.Tests
var periodLength = 4;
var shift = 0;
- var result = TwoPeriods.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
@@ -114,7 +114,7 @@ namespace KLHZ.Trader.Core.Tests
var periodLength = 4;
var shift = 1;
- var result = TwoPeriods.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
@@ -149,7 +149,7 @@ namespace KLHZ.Trader.Core.Tests
var periodLength = 4;
var shift = 0;
- var result = TwoPeriods.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
@@ -184,7 +184,7 @@ namespace KLHZ.Trader.Core.Tests
var periodLength = 4;
var shift = 3;
- var result = TwoPeriods.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
var minValue = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
@@ -219,7 +219,7 @@ namespace KLHZ.Trader.Core.Tests
var periodLength = 4;
var shift = 3;
- var result = TwoPeriods.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result = LocalTrends.GetPriceDiffForTimeSpan(unit, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue1 = startValue + (step > 0 ? (step * count) - step * shift : (step * count) - (step * (shift + periodLength)));
var minValue1 = startValue + (step > 0 ? (step * count) - (step * (shift + periodLength)) : (step * count) - step * shift);
@@ -260,7 +260,7 @@ namespace KLHZ.Trader.Core.Tests
}
- var result2 = TwoPeriods.GetPriceDiffForTimeSpan(unit2, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
+ var result2 = LocalTrends.GetPriceDiffForTimeSpan(unit2, TimeSpan.FromSeconds(shift), TimeSpan.FromSeconds(periodLength));
var maxValue2 = 100;
var minValue2 = -100;
diff --git a/KLHZ.Trader.Core/DataLayer/Entities/Declisions/Enums/DeclisionTradeAction.cs b/KLHZ.Trader.Core/DataLayer/Entities/Declisions/Enums/DeclisionTradeAction.cs
index 8aab2f2..49255be 100644
--- a/KLHZ.Trader.Core/DataLayer/Entities/Declisions/Enums/DeclisionTradeAction.cs
+++ b/KLHZ.Trader.Core/DataLayer/Entities/Declisions/Enums/DeclisionTradeAction.cs
@@ -4,6 +4,7 @@
{
Unknown = 0,
StopBuy = 1,
+ StopBuyShortTime = 2,
OpenLong = 100,
CloseLong = 200,
OpenShort = 300,
diff --git a/KLHZ.Trader.Core/DataLayer/Entities/Orders/Enums/OrderbookItemType.cs b/KLHZ.Trader.Core/DataLayer/Entities/Orders/Enums/OrderbookItemType.cs
index 16ce2bf..dac689c 100644
--- a/KLHZ.Trader.Core/DataLayer/Entities/Orders/Enums/OrderbookItemType.cs
+++ b/KLHZ.Trader.Core/DataLayer/Entities/Orders/Enums/OrderbookItemType.cs
@@ -5,7 +5,9 @@
Unknown = 0,
Ask = 1,
Bid = 2,
- AsksSummary = 3,
- BidsSummary = 4
+ AsksSummary10 = 3,
+ BidsSummary10 = 4,
+ AsksSummary4 = 5,
+ BidsSummary4 = 6,
}
}
diff --git a/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs b/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs
index 038c827..bf48882 100644
--- a/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs
+++ b/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs
@@ -178,34 +178,54 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
if (response.Orderbook != null)
{
- var asksSummary = new OrderbookItem()
+ var asksSummary10 = new OrderbookItem()
{
Figi = response.Orderbook.Figi,
Ticker = GetTickerByFigi(response.Orderbook.Figi),
Count = response.Orderbook.Asks.Sum(a => (int)a.Quantity),
- ItemType = DataLayer.Entities.Orders.Enums.OrderbookItemType.AsksSummary,
+ ItemType = DataLayer.Entities.Orders.Enums.OrderbookItemType.AsksSummary10,
Time = response.Orderbook.Time.ToDateTime().ToUniversalTime(),
};
- var bidsSummary = new OrderbookItem()
+ var asksSummary4 = new OrderbookItem()
+ {
+ Figi = response.Orderbook.Figi,
+ Ticker = GetTickerByFigi(response.Orderbook.Figi),
+ Count = response.Orderbook.Asks.Take(4).Sum(a => (int)a.Quantity),
+ ItemType = DataLayer.Entities.Orders.Enums.OrderbookItemType.AsksSummary4,
+ Time = response.Orderbook.Time.ToDateTime().ToUniversalTime(),
+ };
+
+ var bidsSummary10 = new OrderbookItem()
{
Figi = response.Orderbook.Figi,
Ticker = GetTickerByFigi(response.Orderbook.Figi),
Count = response.Orderbook.Bids.Sum(a => (int)a.Quantity),
- ItemType = DataLayer.Entities.Orders.Enums.OrderbookItemType.BidsSummary,
+ ItemType = DataLayer.Entities.Orders.Enums.OrderbookItemType.BidsSummary10,
Time = response.Orderbook.Time.ToDateTime().ToUniversalTime(),
};
- orderbookItemsBuffer.Add(asksSummary);
- orderbookItemsBuffer.Add(bidsSummary);
+ var bidsSummary4 = new OrderbookItem()
+ {
+ Figi = response.Orderbook.Figi,
+ Ticker = GetTickerByFigi(response.Orderbook.Figi),
+ Count = response.Orderbook.Bids.Take(4).Sum(a => (int)a.Quantity),
+ ItemType = DataLayer.Entities.Orders.Enums.OrderbookItemType.BidsSummary4,
+ Time = response.Orderbook.Time.ToDateTime().ToUniversalTime(),
+ };
+
+ orderbookItemsBuffer.Add(asksSummary4);
+ orderbookItemsBuffer.Add(asksSummary10);
+ orderbookItemsBuffer.Add(bidsSummary4);
+ orderbookItemsBuffer.Add(bidsSummary10);
var message = new NewOrderbookMessage()
{
Ticker = GetTickerByFigi(response.Orderbook.Figi),
Figi = response.Orderbook.Figi,
Time = response.Orderbook.Time.ToDateTime().ToUniversalTime(),
- AsksCount = asksSummary.Count,
- BidsCount = bidsSummary.Count,
+ AsksCount = asksSummary10.Count,
+ BidsCount = bidsSummary10.Count,
};
await _eventBus.Broadcast(message);
}
diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs
index 8d452b3..49dea9b 100644
--- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs
+++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs
@@ -101,25 +101,14 @@ namespace KLHZ.Trader.Core.Exchange.Services
_ = ProcessOrdersbooks();
}
- private async Task InitStops()
- {
- using var context = await _dbContextFactory.CreateDbContextAsync();
- context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
- var dt = DateTime.UtcNow.AddMinutes(-_buyStopLength);
- var stops = await context.Declisions.Where(d => d.Time > dt && d.Action == DeclisionTradeAction.StopBuy).ToArrayAsync();
- foreach (var stop in stops)
- {
- var time = stop.Time.AddMinutes(_buyStopLength);
- OpeningStops.TryAdd(stop.Figi, time);
- }
- }
-
private async Task ProcessPrices()
{
var declisionsForSave = new List();
var processedPrices = new List();
while (await _pricesChannel.Reader.WaitToReadAsync())
{
+ var bigWindowProcessor = nameof(Trader) + "_big";
+ var smallWindowProcessor = nameof(Trader) + "_small";
var message = await _pricesChannel.Reader.ReadAsync();
if (_tradingInstrumentsFigis.Contains(message.Figi))
{
@@ -149,112 +138,45 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(3);
OpeningStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
- declisionsForSave.Add(new Declision()
- {
- AccountId = string.Empty,
- Figi = message.Figi,
- Ticker = message.Ticker,
- Price = message.Value,
- Value = 3,
- Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
- Action = DeclisionTradeAction.StopBuy,
- });
+ LogDeclision(declisionsForSave, DeclisionTradeAction.StopBuyShortTime, message);
}
- var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 15, 120);
- if (result.bigWindowAv != 0)
+ var resultLongOpen = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 45, 180, 2.5m);
+ var resultLongClose = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 15, 120, 2.5m);
+
+ if (resultLongOpen.bigWindowAv != 0)
{
- var priceb = new ProcessedPrice()
- {
- Figi = message.Figi,
- Ticker = message.Ticker,
- Processor = nameof(Trader) + "_big",
- Time = message.Time,
- Value = result.bigWindowAv,
- };
-
- var prices = new ProcessedPrice()
- {
- Figi = message.Figi,
- Ticker = message.Ticker,
- Processor = nameof(Trader) + "_small",
- Time = message.Time,
- Value = result.smallWindowAv,
- };
- processedPrices.Add(priceb);
- processedPrices.Add(prices);
+ LogPrice(processedPrices, message, bigWindowProcessor, resultLongOpen.bigWindowAv);
+ LogPrice(processedPrices, message, smallWindowProcessor, resultLongOpen.smallWindowAv);
}
- if ((result.events & TradingEvent.StopBuy) == TradingEvent.StopBuy)
+ if ((resultLongClose.events & TradingEvent.StopBuy) == TradingEvent.StopBuy)
{
var stopTo = (message.IsHistoricalData ? message.Time : DateTime.UtcNow).AddMinutes(_buyStopLength);
OpeningStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
- declisionsForSave.Add(new Declision()
- {
- AccountId = string.Empty,
- Figi = message.Figi,
- Ticker = message.Ticker,
- Price = message.Value,
- Value = (decimal)_buyStopLength,
- Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
- Action = DeclisionTradeAction.StopBuy,
- });
+ //LogDeclision(declisionsForSave, DeclisionTradeAction.StopBuy, message);
}
- if ((result.events & TradingEvent.LongOpen) == TradingEvent.LongOpen
- && !OpeningStops.TryGetValue(message.Figi, out _)
- && ((unit.BidsCount / unit.AsksCount) > 0.5m))
+ if ((resultLongOpen.events & TradingEvent.UptrendStart) == TradingEvent.UptrendStart
+ && !OpeningStops.TryGetValue(message.Figi, out _))
{
- declisionsForSave.Add(new Declision()
- {
- AccountId = string.Empty,
- Figi = message.Figi,
- Ticker = message.Ticker,
- Price = message.Value,
- Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
- Action = DeclisionTradeAction.OpenLong,
- });
+ LogDeclision(declisionsForSave, DeclisionTradeAction.OpenLong, message);
}
- if ((result.events & TradingEvent.LongClose) == TradingEvent.LongClose)
+ if ((resultLongClose.events & TradingEvent.UptrendEnd) == TradingEvent.UptrendEnd)
{
- declisionsForSave.Add(new Declision()
- {
- AccountId = string.Empty,
- Figi = message.Figi,
- Ticker = message.Ticker,
- Price = message.Value,
- Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
- Action = DeclisionTradeAction.CloseLong,
- });
+ LogDeclision(declisionsForSave, DeclisionTradeAction.CloseLong, message);
}
- if ((result.events & TradingEvent.ShortOpen) == TradingEvent.ShortOpen
- && !OpeningStops.TryGetValue(message.Figi, out _)
- && (unit.BidsCount / unit.AsksCount < 2))
- {
- declisionsForSave.Add(new Declision()
- {
- AccountId = string.Empty,
- Figi = message.Figi,
- Ticker = message.Ticker,
- Price = message.Value,
- Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
- Action = DeclisionTradeAction.OpenShort,
- });
- }
+ //if ((resultLongOpen.events & TradingEvent.ShortOpen) == TradingEvent.ShortOpen
+ // && !OpeningStops.TryGetValue(message.Figi, out _))
+ //{
+ // LogDeclision(declisionsForSave, DeclisionTradeAction.OpenShort, message);
+ //}
- if ((result.events & TradingEvent.ShortClose) == TradingEvent.ShortClose)
- {
- declisionsForSave.Add(new Declision()
- {
- AccountId = string.Empty,
- Figi = message.Figi,
- Ticker = message.Ticker,
- Price = message.Value,
- Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
- Action = DeclisionTradeAction.CloseShort,
- });
- }
+ //if ((resultLongOpen.events & TradingEvent.ShortClose) == TradingEvent.ShortClose)
+ //{
+ // LogDeclision(declisionsForSave, DeclisionTradeAction.CloseShort, message);
+ //}
if ((!message.IsHistoricalData && (processedPrices.Count > 0 || declisionsForSave.Count > 0))
|| (message.IsHistoricalData && ((processedPrices.Count + declisionsForSave.Count > 10000) || _pricesChannel.Reader.Count == 0)))
@@ -284,6 +206,31 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
}
+ private static void LogPrice(List prices, INewPrice message, string processor, decimal value)
+ {
+ prices.Add(new ProcessedPrice()
+ {
+ Figi = message.Figi,
+ Ticker = message.Ticker,
+ Processor = processor,
+ Time = message.Time,
+ Value = value,
+ });
+ }
+
+ private static void LogDeclision(List declisions, DeclisionTradeAction action, INewPrice message)
+ {
+ declisions.Add(new Declision()
+ {
+ AccountId = string.Empty,
+ Figi = message.Figi,
+ Ticker = message.Ticker,
+ Price = message.Value,
+ Time = message.IsHistoricalData ? message.Time : DateTime.UtcNow,
+ Action = action,
+ });
+ }
+
private async Task ProcessOrdersbooks()
{
while (await _ordersbookChannel.Reader.WaitToReadAsync())
diff --git a/KLHZ.Trader.Service/Controllers/PlayController.cs b/KLHZ.Trader.Service/Controllers/PlayController.cs
index 7c7a670..0bb45d5 100644
--- a/KLHZ.Trader.Service/Controllers/PlayController.cs
+++ b/KLHZ.Trader.Service/Controllers/PlayController.cs
@@ -24,6 +24,7 @@ namespace KLHZ.Trader.Service.Controllers
{
try
{
+ var time = new DateTime(2025, 9, 3, 13, 5, 0, DateTimeKind.Utc);
using var context1 = await _dbContextFactory.CreateDbContextAsync();
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var data = await context1.PriceChanges
@@ -38,7 +39,7 @@ namespace KLHZ.Trader.Service.Controllers
IsHistoricalData = true
})
.ToArrayAsync();
-
+ //data = data.Where(d=>d.Time> time).ToArray();
foreach (var mess in data)
{
await _dataBus.Broadcast(mess);
diff --git a/KLHZ.Trader.Service/appsettings.json b/KLHZ.Trader.Service/appsettings.json
index 3894cfb..58199d7 100644
--- a/KLHZ.Trader.Service/appsettings.json
+++ b/KLHZ.Trader.Service/appsettings.json
@@ -8,7 +8,7 @@
},
"LokiUrl": "",
"ExchangeConfig": {
- "StopBuyLengthMinuts": 20,
+ "StopBuyLengthMinuts": 15,
"ExchangeDataRecievingEnabled": true,
"Token": "",
"ManagingAccountNamePatterns": [ "автотрейд 1" ],