399 lines
16 KiB
C#
399 lines
16 KiB
C#
using KLHZ.Trader.Core.Contracts.Messaging.Dtos;
|
|
using KLHZ.Trader.Core.Contracts.Messaging.Interfaces;
|
|
using KLHZ.Trader.Core.DataLayer;
|
|
using KLHZ.Trader.Core.DataLayer.Entities.Orders;
|
|
using KLHZ.Trader.Core.DataLayer.Entities.Prices;
|
|
using KLHZ.Trader.Core.Exchange.Services;
|
|
using KLHZ.Trader.Core.Math.Declisions.Utils;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace KLHZ.Trader.Service.Controllers
|
|
{
|
|
[ApiController]
|
|
[Route("[controller]/[action]")]
|
|
public class PlayController : ControllerBase
|
|
{
|
|
private readonly TraderDataProvider _traderDataProvider;
|
|
private readonly IDataBus _dataBus;
|
|
private readonly IDbContextFactory<TraderDbContext> _dbContextFactory;
|
|
|
|
public PlayController(IDataBus dataBus, IDbContextFactory<TraderDbContext> dbContextFactory, TraderDataProvider traderDataProvider)
|
|
{
|
|
_dbContextFactory = dbContextFactory;
|
|
_dataBus = dataBus;
|
|
_traderDataProvider = traderDataProvider;
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task Run(double? shift = null)
|
|
{
|
|
try
|
|
{
|
|
var figi1 = "FUTIMOEXF000";
|
|
//var figi1 = "BBG004730N88";
|
|
var figi2 = "BBG004730N88";
|
|
//var figi2 = "FUTIMOEXF000";
|
|
var time1 = DateTime.UtcNow.AddDays(-shift ?? -7).Date;
|
|
//var time1 = new DateTime(2025, 9, 24, 7, 00, 0, DateTimeKind.Utc);
|
|
//var time2 = DateTime.UtcNow.AddMinutes(18);
|
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
var data = await context1.PriceChanges
|
|
.Where(c => (c.Figi == figi1 || c.Figi == figi2) && c.Time >= time1)
|
|
.OrderBy(c => c.Time)
|
|
.Select(c => new NewPriceMessage()
|
|
{
|
|
Figi = c.Figi,
|
|
Ticker = c.Ticker,
|
|
Time = c.Time,
|
|
Value = c.Value,
|
|
IsHistoricalData = true,
|
|
Direction = c.Direction,
|
|
Count = c.Count,
|
|
})
|
|
.ToArrayAsync();
|
|
|
|
foreach (var mess in data)
|
|
{
|
|
await _dataBus.Broadcast(mess);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task CalcOrderbookMeanav(string figi)
|
|
{
|
|
try
|
|
{
|
|
var t = DateTime.UtcNow.AddHours(-4);
|
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
var data = await context1.OrderbookItems
|
|
.Where(i => i.Time > t && i.Figi == figi && (i.ItemType == Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.BidsSummary4 || i.ItemType == Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.AsksSummary4))
|
|
.OrderBy(i => i.Time)
|
|
.ToArrayAsync();
|
|
var bids = new LinkedList<OrderbookItem>();
|
|
var asks = new LinkedList<OrderbookItem>();
|
|
var buffer = new List<OrderbookItem>();
|
|
var dt = TimeSpan.FromMinutes(1);
|
|
var q = data.ToLookup(d => d.Time);
|
|
foreach (var d in q)
|
|
{
|
|
var pair = d.DistinctBy(www => www.ItemType).OrderBy(www => www.ItemType).ToArray();
|
|
if (pair.Length == 2)
|
|
{
|
|
bids.AddLast(pair[1]);
|
|
if (bids.Last().Time - bids.First().Time > dt)
|
|
{
|
|
bids.RemoveFirst();
|
|
}
|
|
if (pair[0].Count != 0)
|
|
{
|
|
pair[1].Price = ((decimal)pair[1].Count) / ((decimal)pair[0].Count);
|
|
buffer.Add(new OrderbookItem()
|
|
{
|
|
Figi = pair[1].Figi,
|
|
Ticker = pair[1].Ticker,
|
|
Count = 1,
|
|
ItemType = Core.DataLayer.Entities.Orders.Enums.OrderbookItemType.BidsAsksSummary4_2min,
|
|
Price = bids.Sum(b => b.Price) / bids.Count,
|
|
Time = pair[1].Time,
|
|
});
|
|
}
|
|
if (buffer.Count > 10000)
|
|
{
|
|
await context1.OrderbookItems.AddRangeAsync(buffer);
|
|
await context1.SaveChangesAsync();
|
|
buffer.Clear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
}
|
|
if (buffer.Count > 0)
|
|
{
|
|
await context1.OrderbookItems.AddRangeAsync(buffer);
|
|
await context1.SaveChangesAsync();
|
|
buffer.Clear();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task CalcTradesMeanav(string figi)
|
|
{
|
|
try
|
|
{
|
|
var t = DateTime.UtcNow.AddHours(-4);
|
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
var data = await context1.PriceChanges
|
|
.Where(i => i.Time > t && i.Figi == figi)
|
|
.OrderBy(i => i.Time)
|
|
.ToArrayAsync();
|
|
var sells = new LinkedList<PriceChange>();
|
|
var buys = new LinkedList<PriceChange>();
|
|
var buffer = new List<ProcessedPrice>();
|
|
var dt = TimeSpan.FromMinutes(1);
|
|
foreach (var d in data)
|
|
{
|
|
if (d.Direction == 1)
|
|
{
|
|
if (buys.Last().Time - buys.First().Time > dt)
|
|
{
|
|
buys.RemoveFirst();
|
|
}
|
|
buys.AddLast(d);
|
|
}
|
|
if (d.Direction == 2)
|
|
{
|
|
sells.AddLast(d);
|
|
if (sells.Last().Time - sells.First().Time > dt)
|
|
{
|
|
sells.RemoveFirst();
|
|
}
|
|
sells.AddLast(d);
|
|
}
|
|
|
|
if (sells.Count > 0 && buys.Count > 0)
|
|
{
|
|
var meanS = ((decimal)sells.Sum(s => s.Count)) / sells.Count;
|
|
var meanB = ((decimal)buys.Sum(s => s.Count)) / buys.Count;
|
|
if (meanS != 0)
|
|
{
|
|
buffer.Add(new ProcessedPrice()
|
|
{
|
|
Figi = d.Figi,
|
|
Processor = "tradesbalance",
|
|
Ticker = d.Ticker,
|
|
Count = 1,
|
|
Direction = 0,
|
|
Time = d.Time,
|
|
Value = meanB / meanS
|
|
});
|
|
}
|
|
}
|
|
|
|
if (buffer.Count > 10000)
|
|
{
|
|
await context1.ProcessedPrices.AddRangeAsync(buffer);
|
|
await context1.SaveChangesAsync();
|
|
buffer.Clear();
|
|
}
|
|
}
|
|
if (buffer.Count > 0)
|
|
{
|
|
await context1.ProcessedPrices.AddRangeAsync(buffer);
|
|
await context1.SaveChangesAsync();
|
|
buffer.Clear();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
|
|
[HttpGet]
|
|
public async Task TestInmterpolate(string figi)
|
|
{
|
|
try
|
|
{
|
|
var t1 = DateTime.UtcNow.AddHours(-4);
|
|
var t2 = DateTime.UtcNow.AddHours(1);
|
|
|
|
//t1 = new DateTime(2025, 9, 15, 10, 1, 0, DateTimeKind.Utc);
|
|
//t2 = new DateTime(2025, 9, 15, 10, 1, 50, DateTimeKind.Utc);
|
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
var data = await context1.PriceChanges
|
|
.Where(i => i.Time >= t1 && i.Time <= t2 && i.Figi == figi)
|
|
.OrderBy(i => i.Time)
|
|
.ToArrayAsync();
|
|
|
|
var buffer = new List<ProcessedPrice>();
|
|
var res = SignalProcessing.InterpolateData(data.Select(d => d.Time).ToArray(), data.Select(d => d.Value).ToArray(),
|
|
TimeSpan.FromSeconds(1));
|
|
|
|
|
|
for (int i = 0; i < res.Item1.Length; i++)
|
|
{
|
|
buffer.Add(new ProcessedPrice()
|
|
{
|
|
Figi = figi,
|
|
Processor = "1secinterpol",
|
|
Ticker = data[0].Ticker,
|
|
Count = 1,
|
|
Direction = 0,
|
|
Time = res.Item1[i],
|
|
Value = (decimal)res.Item2[i]
|
|
});
|
|
}
|
|
await context1.ProcessedPrices.AddRangeAsync(buffer);
|
|
await context1.SaveChangesAsync();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
[HttpGet]
|
|
public async Task TestFFT(string figi)
|
|
{
|
|
try
|
|
{
|
|
var t1 = new DateTime(2025, 9, 15, 6, 30, 0, DateTimeKind.Utc);
|
|
var t2 = new DateTime(2025, 9, 15, 7, 50, 50, DateTimeKind.Utc);
|
|
|
|
using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
var data = await context1.PriceChanges
|
|
.Where(i => i.Time >= t1 && i.Time <= t2 && i.Figi == figi)
|
|
.OrderBy(i => i.Time)
|
|
.ToArrayAsync();
|
|
|
|
var buffer = new List<ProcessedPrice>();
|
|
var values = data.Select(d => d.Value).ToArray();
|
|
var times = data.Select(d => d.Time).ToArray();
|
|
var res = SignalProcessing.InterpolateData(times, values,
|
|
TimeSpan.FromSeconds(10));
|
|
|
|
//FFT.GetMainHarmonictPeriod(res.Item2, res.Item1.Last() - res.Item1.First());
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
}
|
|
}
|
|
//[HttpGet]
|
|
//public async Task GetBalance(string figi)
|
|
//{
|
|
// try
|
|
// {
|
|
// var time1 = DateTime.UtcNow.AddDays(-7);
|
|
// using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
// context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
// var data = await context1.PriceChanges
|
|
// .Where(c => c.Figi == figi && c.Time >= time1)
|
|
// .OrderBy(c => c.Time)
|
|
// .Select(c => new NewPriceMessage()
|
|
// {
|
|
// Figi = figi,
|
|
// Ticker = c.Ticker,
|
|
// Time = c.Time,
|
|
// Value = c.Value,
|
|
// IsHistoricalData = true
|
|
// })
|
|
// .ToArrayAsync();
|
|
// var buffer = new List<ProcessedPrice>();
|
|
// var list = new LinkedList<(DateTime time, double value)>();
|
|
// var previous = -1000d;
|
|
// foreach (var mess in data)
|
|
// {
|
|
// await _traderDataProvider.AddData(mess, TimeSpan.FromHours(6));
|
|
// var dataFromCache = await _traderDataProvider.GetData(figi, TimeSpan.FromMinutes(15));
|
|
// if (dataFromCache.isFullIntervalExists)
|
|
// {
|
|
// if (ShapeAreaCalculator.TryGetAreasRelation(dataFromCache.timestamps, dataFromCache.prices,mess.Value,out var res))
|
|
// {
|
|
// if (list.Count > 0 && mess.Time - list.Last().time > TimeSpan.FromMinutes(5))
|
|
// {
|
|
// list.Clear();
|
|
// }
|
|
// list.AddLast((mess.Time, res));
|
|
// if (list.Last().time - list.First().time > TimeSpan.FromMinutes(1))
|
|
// {
|
|
// list.RemoveFirst();
|
|
// }
|
|
// var newRes = (decimal)(list.Sum(i => i.value) / list.Count);
|
|
// if (list.Count > 0)
|
|
// {
|
|
// try
|
|
// {
|
|
// buffer.Add(new ProcessedPrice()
|
|
// {
|
|
// Figi = figi,
|
|
// Processor = "balancescalc30min",
|
|
// Ticker = mess.Ticker,
|
|
// Time = mess.Time,
|
|
// Value = newRes,
|
|
// //Value = (decimal)res,
|
|
// });
|
|
// }
|
|
// catch(Exception ex)
|
|
// {
|
|
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// previous = -1d;
|
|
// }
|
|
// if (buffer.Count > 10000)
|
|
// {
|
|
// await context1.ProcessedPrices.AddRangeAsync(buffer);
|
|
// await context1.SaveChangesAsync();
|
|
// buffer.Clear();
|
|
// }
|
|
// }
|
|
// if (buffer.Count > 0)
|
|
// {
|
|
// await context1.ProcessedPrices.AddRangeAsync(buffer);
|
|
// await context1.SaveChangesAsync();
|
|
// buffer.Clear();
|
|
// }
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
|
|
// }
|
|
//}
|
|
|
|
////[HttpGet]
|
|
//public async Task LoadTradesToHistory(string figi)
|
|
//{
|
|
// try
|
|
// {
|
|
// using var context1 = await _dbContextFactory.CreateDbContextAsync();
|
|
// context1.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
|
|
// var data = await context1.InstrumentTrades
|
|
// .Where(c => c.Figi == figi)
|
|
// .OrderBy(c => c.BoughtAt)
|
|
// .Select(c => new PriceChange()
|
|
// {
|
|
// Figi = figi,
|
|
// Ticker = c.Ticker,
|
|
// Time = c.BoughtAt,
|
|
// Value = c.Price,
|
|
// IsHistoricalData = true
|
|
// })
|
|
// .ToArrayAsync();
|
|
// await context1.PriceChanges.Where(p => p.Figi == figi).ExecuteDeleteAsync();
|
|
// await context1.PriceChanges.AddRangeAsync(data);
|
|
// await context1.SaveChangesAsync();
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
|
|
// }
|
|
//}
|
|
}
|
|
}
|