переход на секционированную таблицу
test / deploy_trader_prod (push) Successful in 5m43s
Details
test / deploy_trader_prod (push) Successful in 5m43s
Details
parent
ecd9a70e2e
commit
61b98e88f7
|
@ -0,0 +1,45 @@
|
||||||
|
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
|
||||||
|
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
||||||
|
{
|
||||||
|
[Table("experiment_results")]
|
||||||
|
public class ExperimentsResult : IProcessedPrice
|
||||||
|
{
|
||||||
|
[Column("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
[Column("time")]
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
|
||||||
|
[Column("value")]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[Column("figi")]
|
||||||
|
public required string Figi { get; set; }
|
||||||
|
|
||||||
|
[Column("ticker")]
|
||||||
|
public required string Ticker { get; set; }
|
||||||
|
|
||||||
|
public bool IsHistoricalData { get; set; }
|
||||||
|
|
||||||
|
[Column("processor")]
|
||||||
|
public required string Processor { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public long Count { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public int Direction { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public decimal Value { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public decimal Value2 { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public AttachedInfo? AttachedInfo { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||||
|
using KLHZ.Trader.Core.DataLayer.Entities.Orders.Enums;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace KLHZ.Trader.Core.DataLayer.Entities.Orders
|
||||||
|
{
|
||||||
|
[Table("orderbook_elements")]
|
||||||
|
public class OrderbookElement : IOrderbookItem
|
||||||
|
{
|
||||||
|
[Column("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
[Column("time")]
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
|
||||||
|
[Column("price")]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[Column("count")]
|
||||||
|
public long Count { get; set; }
|
||||||
|
|
||||||
|
[Column("figi")]
|
||||||
|
public required string Figi { get; set; }
|
||||||
|
|
||||||
|
[Column("ticker")]
|
||||||
|
public required string Ticker { get; set; }
|
||||||
|
|
||||||
|
[Column("item_type")]
|
||||||
|
public OrderbookItemType ItemType { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,62 +1,10 @@
|
||||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
||||||
{
|
{
|
||||||
[Table("price_changes")]
|
[Table("price_changes")]
|
||||||
public class PriceChange : ITradeDataItem
|
public class PriceChange : Trade
|
||||||
{
|
{
|
||||||
[Column("id")]
|
|
||||||
public long Id { get; set; }
|
|
||||||
|
|
||||||
[Column("time")]
|
|
||||||
public DateTime Time { get; set; }
|
|
||||||
|
|
||||||
[Column("value")]
|
|
||||||
public decimal Price { get; set; }
|
|
||||||
|
|
||||||
[Column("figi")]
|
|
||||||
public required string Figi { get; set; }
|
|
||||||
|
|
||||||
[Column("ticker")]
|
|
||||||
public required string Ticker { get; set; }
|
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public bool IsHistoricalData { get; set; }
|
|
||||||
[Column("count")]
|
|
||||||
public long Count { get; set; }
|
|
||||||
|
|
||||||
[Column("direction")]
|
|
||||||
public int Direction { get; set; }
|
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public decimal Value { get; set; }
|
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public decimal Value2 { get; set; }
|
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public AttachedInfo? AttachedInfo
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock (_locker)
|
|
||||||
{
|
|
||||||
return _attachedInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetAttachedInfo(AttachedInfo? attachedInfo)
|
|
||||||
{
|
|
||||||
lock (_locker)
|
|
||||||
{
|
|
||||||
_attachedInfo = attachedInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private AttachedInfo? _attachedInfo;
|
|
||||||
private readonly object _locker = new();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
|
||||||
|
using KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
||||||
|
{
|
||||||
|
[Table("trades")]
|
||||||
|
public class Trade : ITradeDataItem
|
||||||
|
{
|
||||||
|
[Column("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
[Column("time")]
|
||||||
|
public DateTime Time { get; set; }
|
||||||
|
|
||||||
|
[Column("value")]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[Column("figi")]
|
||||||
|
public required string Figi { get; set; }
|
||||||
|
|
||||||
|
[Column("ticker")]
|
||||||
|
public required string Ticker { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public bool IsHistoricalData { get; set; }
|
||||||
|
[Column("count")]
|
||||||
|
public long Count { get; set; }
|
||||||
|
|
||||||
|
[Column("direction")]
|
||||||
|
public int Direction { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public decimal Value { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public decimal Value2 { get; set; }
|
||||||
|
|
||||||
|
[NotMapped]
|
||||||
|
public AttachedInfo? AttachedInfo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
return _attachedInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAttachedInfo(AttachedInfo? attachedInfo)
|
||||||
|
{
|
||||||
|
lock (_locker)
|
||||||
|
{
|
||||||
|
_attachedInfo = attachedInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AttachedInfo? _attachedInfo;
|
||||||
|
private readonly object _locker = new();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,9 +9,12 @@ namespace KLHZ.Trader.Core.DataLayer
|
||||||
public class TraderDbContext : DbContext
|
public class TraderDbContext : DbContext
|
||||||
{
|
{
|
||||||
public DbSet<Declision> Declisions { get; set; }
|
public DbSet<Declision> Declisions { get; set; }
|
||||||
|
public DbSet<Trade> Trades { get; set; }
|
||||||
public DbSet<PriceChange> PriceChanges { get; set; }
|
public DbSet<PriceChange> PriceChanges { get; set; }
|
||||||
public DbSet<ProcessedPrice> ProcessedPrices { get; set; }
|
public DbSet<ProcessedPrice> ProcessedPrices { get; set; }
|
||||||
|
public DbSet<ExperimentsResult> ExperimentsResults { get; set; }
|
||||||
public DbSet<OrderbookItem> OrderbookItems { get; set; }
|
public DbSet<OrderbookItem> OrderbookItems { get; set; }
|
||||||
|
public DbSet<OrderbookElement> OrderbookElements { get; set; }
|
||||||
public TraderDbContext(DbContextOptions<TraderDbContext> options)
|
public TraderDbContext(DbContextOptions<TraderDbContext> options)
|
||||||
: base(options)
|
: base(options)
|
||||||
{
|
{
|
||||||
|
@ -40,6 +43,26 @@ namespace KLHZ.Trader.Core.DataLayer
|
||||||
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<Trade>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e1 => new { e1.Time, e1.Id });
|
||||||
|
entity.Ignore(e1 => e1.IsHistoricalData);
|
||||||
|
entity.Property(e => e.Time)
|
||||||
|
.HasConversion(
|
||||||
|
v => v.ToUniversalTime(),
|
||||||
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<ExperimentsResult>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e1 => new { e1.Time, e1.Id });
|
||||||
|
entity.Ignore(e1 => e1.IsHistoricalData);
|
||||||
|
entity.Property(e => e.Time)
|
||||||
|
.HasConversion(
|
||||||
|
v => v.ToUniversalTime(),
|
||||||
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity<OrderbookItem>(entity =>
|
modelBuilder.Entity<OrderbookItem>(entity =>
|
||||||
{
|
{
|
||||||
entity.HasKey(e1 => e1.Id);
|
entity.HasKey(e1 => e1.Id);
|
||||||
|
@ -49,6 +72,15 @@ namespace KLHZ.Trader.Core.DataLayer
|
||||||
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<OrderbookElement>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasKey(e1 => new { e1.Time, e1.Id });
|
||||||
|
entity.Property(e => e.Time)
|
||||||
|
.HasConversion(
|
||||||
|
v => v.ToUniversalTime(),
|
||||||
|
v => DateTime.SpecifyKind(v, DateTimeKind.Utc));
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity<ProcessedPrice>(entity =>
|
modelBuilder.Entity<ProcessedPrice>(entity =>
|
||||||
{
|
{
|
||||||
entity.HasKey(e1 => e1.Id);
|
entity.HasKey(e1 => e1.Id);
|
||||||
|
|
|
@ -13,6 +13,7 @@ using Microsoft.Extensions.Options;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using Tinkoff.InvestApi;
|
using Tinkoff.InvestApi;
|
||||||
using Tinkoff.InvestApi.V1;
|
using Tinkoff.InvestApi.V1;
|
||||||
|
using Trade = KLHZ.Trader.Core.DataLayer.Entities.Prices.Trade;
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.Exchange.Services
|
namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
{
|
{
|
||||||
|
@ -137,14 +138,14 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
});
|
});
|
||||||
|
|
||||||
var lastUpdateDict = new Dictionary<string, PriceChange>();
|
var lastUpdateDict = new Dictionary<string, PriceChange>();
|
||||||
var pricesBuffer = new List<PriceChange>();
|
var pricesBuffer = new List<Trade>();
|
||||||
var orderbookItemsBuffer = new List<OrderbookItem>();
|
var orderbookItemsBuffer = new List<OrderbookItem>();
|
||||||
var lastWrite = DateTime.UtcNow;
|
var lastWrite = DateTime.UtcNow;
|
||||||
await foreach (var response in stream.ResponseStream.ReadAllAsync())
|
await foreach (var response in stream.ResponseStream.ReadAllAsync())
|
||||||
{
|
{
|
||||||
if (response.Trade != null)
|
if (response.Trade != null)
|
||||||
{
|
{
|
||||||
var message = new PriceChange()
|
var message = new Trade()
|
||||||
{
|
{
|
||||||
Figi = response.Trade.Figi,
|
Figi = response.Trade.Figi,
|
||||||
Ticker = _tradeDataProvider.GetTickerByFigi(response.Trade.Figi),
|
Ticker = _tradeDataProvider.GetTickerByFigi(response.Trade.Figi),
|
||||||
|
@ -212,7 +213,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
}
|
}
|
||||||
if (pricesBuffer.Count > 0)
|
if (pricesBuffer.Count > 0)
|
||||||
{
|
{
|
||||||
await context.PriceChanges.AddRangeAsync(pricesBuffer);
|
await context.Trades.AddRangeAsync(pricesBuffer);
|
||||||
pricesBuffer.Clear();
|
pricesBuffer.Clear();
|
||||||
}
|
}
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
|
|
|
@ -351,5 +351,52 @@ namespace KLHZ.Trader.Service.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task MigrateData()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
||||||
|
var figis = context1.PriceChanges.Select(p => p.Figi).Distinct().ToArray();
|
||||||
|
|
||||||
|
foreach (var f in figis)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var time1 = new DateTime(2025, 8, 25, 0, 0, 0, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
while (time1 < DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
var time2 = time1.AddDays(7);
|
||||||
|
var prices = await context1.PriceChanges
|
||||||
|
.Where(c => (c.Figi == f) && c.Time >= time1 && c.Time < time2)
|
||||||
|
.OrderBy(c => c.Time)
|
||||||
|
.ToArrayAsync();
|
||||||
|
await context1.Trades.AddRangeAsync(prices);
|
||||||
|
await context1.SaveChangesAsync();
|
||||||
|
time1 = time2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue