переход на секционированную таблицу
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 KLHZ.Trader.Core.Contracts.Messaging.Dtos.Interfaces;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace KLHZ.Trader.Core.DataLayer.Entities.Prices
|
||||
{
|
||||
[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 DbSet<Declision> Declisions { get; set; }
|
||||
public DbSet<Trade> Trades { get; set; }
|
||||
public DbSet<PriceChange> PriceChanges { get; set; }
|
||||
public DbSet<ProcessedPrice> ProcessedPrices { get; set; }
|
||||
public DbSet<ExperimentsResult> ExperimentsResults { get; set; }
|
||||
public DbSet<OrderbookItem> OrderbookItems { get; set; }
|
||||
public DbSet<OrderbookElement> OrderbookElements { get; set; }
|
||||
public TraderDbContext(DbContextOptions<TraderDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
|
@ -40,6 +43,26 @@ namespace KLHZ.Trader.Core.DataLayer
|
|||
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 =>
|
||||
{
|
||||
entity.HasKey(e1 => e1.Id);
|
||||
|
@ -49,6 +72,15 @@ namespace KLHZ.Trader.Core.DataLayer
|
|||
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 =>
|
||||
{
|
||||
entity.HasKey(e1 => e1.Id);
|
||||
|
|
|
@ -13,6 +13,7 @@ using Microsoft.Extensions.Options;
|
|||
using System.Collections.Concurrent;
|
||||
using Tinkoff.InvestApi;
|
||||
using Tinkoff.InvestApi.V1;
|
||||
using Trade = KLHZ.Trader.Core.DataLayer.Entities.Prices.Trade;
|
||||
|
||||
namespace KLHZ.Trader.Core.Exchange.Services
|
||||
{
|
||||
|
@ -137,14 +138,14 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
});
|
||||
|
||||
var lastUpdateDict = new Dictionary<string, PriceChange>();
|
||||
var pricesBuffer = new List<PriceChange>();
|
||||
var pricesBuffer = new List<Trade>();
|
||||
var orderbookItemsBuffer = new List<OrderbookItem>();
|
||||
var lastWrite = DateTime.UtcNow;
|
||||
await foreach (var response in stream.ResponseStream.ReadAllAsync())
|
||||
{
|
||||
if (response.Trade != null)
|
||||
{
|
||||
var message = new PriceChange()
|
||||
var message = new Trade()
|
||||
{
|
||||
Figi = response.Trade.Figi,
|
||||
Ticker = _tradeDataProvider.GetTickerByFigi(response.Trade.Figi),
|
||||
|
@ -212,7 +213,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
|||
}
|
||||
if (pricesBuffer.Count > 0)
|
||||
{
|
||||
await context.PriceChanges.AddRangeAsync(pricesBuffer);
|
||||
await context.Trades.AddRangeAsync(pricesBuffer);
|
||||
pricesBuffer.Clear();
|
||||
}
|
||||
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