diff --git a/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs b/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs
index fdd930e..baaba9d 100644
--- a/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs
+++ b/KLHZ.Trader.Core.Contracts/Declisions/Interfaces/IPriceHistoryCacheUnit.cs
@@ -9,7 +9,15 @@ namespace KLHZ.Trader.Core.Contracts.Declisions.Interfaces
public ValueTask AddData(INewPrice priceChange);
public ValueTask<(DateTime[] timestamps, float[] prices)> GetData();
public ValueTask AddOrderbook(IOrderbook orderbook);
+
+ ///
+ /// Число заявок на продаже в стакане.
+ ///
public decimal AsksCount { get; }
+
+ ///
+ /// Число заявок на покупку в стакане.
+ ///
public decimal BidsCount { get; }
}
}
diff --git a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs
index 61c21ed..5831302 100644
--- a/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs
+++ b/KLHZ.Trader.Core.Math/Declisions/Utils/MovingAverage.cs
@@ -38,13 +38,15 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
}
if (shift > 0)
{
+ var i1 = size - 1 - shift;
+ var i2 = size - 2 - shift;
var isCrossing = Lines.IsLinesCrossing(
- times[size - 1 - shift],
- times[size - 2 - shift],
- twav15s[size - 1 - shift],
- twav15s[size - 2 - shift],
- twav120s[size - 1 - shift],
- twav120s[size - 2 - shift]);
+ times[i1],
+ times[i2],
+ twav15s[i1],
+ twav15s[i2],
+ twav120s[i1],
+ twav120s[i2]);
if (shift == 1 && !isCrossing) //если нет пересечения скользящих средний с окном 120 и 15 секунд между
//текущей и предыдущей точкой - можно не продолжать выполнение.
{
diff --git a/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs b/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs
index 54039b4..038c827 100644
--- a/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs
+++ b/KLHZ.Trader.Core/Exchange/Services/ExchangeDataReader.cs
@@ -142,14 +142,10 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
SubscribeOrderBookRequest = bookRequest
});
- using var context = await _dbContextFactory.CreateDbContextAsync();
- context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+
var pricesBuffer = new List();
var orderbookItemsBuffer = new List();
var tradesBuffer = new List();
- var lastWriteOrderbooks = DateTime.UtcNow;
- var lastWriteTrades = DateTime.UtcNow;
- var lastWritePrices = DateTime.UtcNow;
var lastWrite = DateTime.UtcNow;
await foreach (var response in stream.ResponseStream.ReadAllAsync())
{
@@ -214,25 +210,34 @@ namespace KLHZ.Trader.Core.Exchange.Services
await _eventBus.Broadcast(message);
}
- if (orderbookItemsBuffer.Count + pricesBuffer.Count + tradesBuffer.Count > 1000 || (DateTime.UtcNow - lastWrite).TotalSeconds > 10)
+ if (orderbookItemsBuffer.Count + pricesBuffer.Count + tradesBuffer.Count > 0 || (DateTime.UtcNow - lastWrite).TotalSeconds > 10)
{
- lastWrite = DateTime.UtcNow;
- if (orderbookItemsBuffer.Count > 0)
+ try
{
- await context.OrderbookItems.AddRangeAsync(orderbookItemsBuffer);
- orderbookItemsBuffer.Clear();
+ using var context = await _dbContextFactory.CreateDbContextAsync();
+ context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ lastWrite = DateTime.UtcNow;
+ if (orderbookItemsBuffer.Count > 0)
+ {
+ await context.OrderbookItems.AddRangeAsync(orderbookItemsBuffer);
+ orderbookItemsBuffer.Clear();
+ }
+ if (pricesBuffer.Count > 0)
+ {
+ await context.PriceChanges.AddRangeAsync(pricesBuffer);
+ pricesBuffer.Clear();
+ }
+ if (tradesBuffer.Count > 0)
+ {
+ await context.InstrumentTrades.AddRangeAsync(tradesBuffer);
+ tradesBuffer.Clear();
+ }
+ await context.SaveChangesAsync();
}
- if (pricesBuffer.Count > 0)
+ catch (Exception ex)
{
- await context.PriceChanges.AddRangeAsync(pricesBuffer);
- pricesBuffer.Clear();
+ _logger.LogError(ex, "Ошибка при сохранении данных биржи.");
}
- if (tradesBuffer.Count > 0)
- {
- await context.InstrumentTrades.AddRangeAsync(tradesBuffer);
- tradesBuffer.Clear();
- }
- await context.SaveChangesAsync();
}
}
}
diff --git a/KLHZ.Trader.Core/Exchange/Services/Trader.cs b/KLHZ.Trader.Core/Exchange/Services/Trader.cs
index 076da5e..4629f8b 100644
--- a/KLHZ.Trader.Core/Exchange/Services/Trader.cs
+++ b/KLHZ.Trader.Core/Exchange/Services/Trader.cs
@@ -98,7 +98,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
_dataBus.AddChannel(nameof(Trader), _ordersbookChannel);
_ = ProcessPrices();
_ = ProcessOrdersbooks();
- _ = BackgroundWorker();
}
private async Task InitStops()
@@ -119,86 +118,121 @@ namespace KLHZ.Trader.Core.Exchange.Services
while (await _pricesChannel.Reader.WaitToReadAsync())
{
var message = await _pricesChannel.Reader.ReadAsync();
- //if (_tradingInstrumentsFigis.Contains(message.Figi))
- //{
- // if (_historyCash.TryGetValue(message.Figi, out var unit))
- // {
- // await unit.AddData(message);
- // }
- // else
- // {
- // unit = new PriceHistoryCacheUnit2(message.Figi, message);
- // _historyCash.TryAdd(message.Figi, unit);
- // }
- // var data = await unit.GetData();
- // var declisionsForSave = new List();
- // if (message.Figi == "FUTIMOEXF000")
- // {
- // var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 3f);
- // if ((result & TradingEvent.StopBuy) == TradingEvent.StopBuy)
- // {
- // var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);
- // BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
- // 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.StopBuy,
- // });
- // }
+ if (_tradingInstrumentsFigis.Contains(message.Figi))
+ {
+ if (_historyCash.TryGetValue(message.Figi, out var unit))
+ {
+ await unit.AddData(message);
+ }
+ else
+ {
+ unit = new PriceHistoryCacheUnit2(message.Figi, message);
+ _historyCash.TryAdd(message.Figi, unit);
+ }
+ try
+ {
+ var data = await unit.GetData();
+ var declisionsForSave = new List();
+ if (message.Figi == "FUTIMOEXF000")
+ {
+ var result = MovingAverage.CheckByWindowAverageMean(data.timestamps, data.prices, 100, 3f);
+ if ((result & TradingEvent.StopBuy) == TradingEvent.StopBuy)
+ {
+ var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);
+ BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
+ 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.StopBuy,
+ });
+ }
- // if ((result & TradingEvent.LongOpen) == TradingEvent.LongOpen
- // && !BuyStops.TryGetValue(message.Figi, out _))
- // {
- // var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);
- // BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
- // 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,
- // });
- // }
+ if ((result & TradingEvent.LongOpen) == TradingEvent.LongOpen
+ && ((unit.BidsCount / unit.AsksCount) > 0.5m))
+ {
+ if (BuyStops.TryGetValue(message.Figi, out var dt))
+ {
+ if (dt > DateTime.UtcNow)
+ {
+ continue;
+ }
+ else
+ {
+ BuyStops.TryRemove(message.Figi, out _);
+ }
+ }
+ var stopTo = DateTime.UtcNow.AddMinutes(_buyStopLength);
+ BuyStops.AddOrUpdate(message.Figi, stopTo, (k, v) => stopTo);
+ 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,
+ });
+ }
- // if ((result & TradingEvent.LongClose) == TradingEvent.LongClose)
- // {
- // 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,
- // });
- // }
+ if ((result & TradingEvent.LongClose) == TradingEvent.LongClose)
+ {
+ 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,
+ });
+ }
- // if ((result & TradingEvent.ShortOpen) == TradingEvent.ShortOpen && (unit.AsksCount/ unit.BidsCount>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 ((result & TradingEvent.ShortOpen) == TradingEvent.ShortOpen && (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,
+ });
+ }
- // using var context = await _dbContextFactory.CreateDbContextAsync();
- // context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ if ((result & 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,
+ });
+ }
- // await context.AddRangeAsync(declisionsForSave);
- // await context.SaveChangesAsync();
- // }
- //}
+ if (declisionsForSave.Count > 0)
+ {
+ using var context = await _dbContextFactory.CreateDbContextAsync();
+ context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+
+ await context.AddRangeAsync(declisionsForSave);
+ await context.SaveChangesAsync();
+ declisionsForSave.Clear();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
}
}
@@ -216,27 +250,6 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
}
- private async Task BackgroundWorker()
- {
- var keysForRemove = new List();
- while (!_cts.IsCancellationRequested)
- {
- var time = DateTime.UtcNow;
- foreach (var kvp in BuyStops)
- {
- if (kvp.Value > time)
- {
- keysForRemove.Add(kvp.Key);
- }
- }
- foreach (var key in keysForRemove)
- {
- BuyStops.TryRemove(key, out _);
- }
- await Task.Delay(10000);
- }
- }
-
public Task StopAsync(CancellationToken cancellationToken)
{
_cts.Cancel();