изменена синхронизация портфеля
test / deploy_trader_prod (push) Successful in 1m39s Details

dev
vlad zverzhkhovskiy 2025-09-15 16:30:21 +03:00
parent 80221648f7
commit d0ec2af488
5 changed files with 167 additions and 59 deletions

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KLHZ.Trader.Core.Math.Declisions.Dtos
{
public class Harmonic
{
public TimeSpan Period { get; set; }
public float Magnitude { get; set; }
public float Real { get; set; }
public float Imaginary { get; set; }
public float Phase { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using MathNet.Numerics;
using KLHZ.Trader.Core.Math.Declisions.Dtos;
using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;
namespace KLHZ.Trader.Core.Math.Declisions.Utils
@ -26,25 +27,81 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
}
}
public static void А()
public static TimeSpan GetMainHarmonictPeriod(double[] data, TimeSpan period)
{
var da = new List<float>();
for (int i = 0; i < 1000; i++)
{
da.Add((float)System.Math.Sin(0.01 * i) + (float)System.Math.Cos(0.01 * i));
}
var start = da.ToArray();
var arrv = da.Select(d => new Complex32(d, 0)).ToArray();
var arrv = data.Select(d => new Complex32((float)d, 0)).ToArray();
Fourier.Forward(arrv);
Fourier.Inverse(arrv);
var res = arrv.Select(a => a.Real).ToArray();
for (int i = 0; i < 1000; i++)
var res = new List<Harmonic>();
var times = new TimeSpan[arrv.Length];
var mags = arrv.Select(a => a.Magnitude).ToArray();
var phases = arrv.Select(a => a.Phase).ToArray();
var max = 0f;
var kmax = 1;
var sum = 0f;
for (int i=0;i< arrv.Length / 2; i++)
{
var d = res[i] - start[i];
if (i == 0)
{
res.Add(new Harmonic()
{
Magnitude = arrv[i].Magnitude,
Period = TimeSpan.MaxValue,
Phase = arrv[i].Phase,
});
}
else
{
times[i] = CaclHarmonycPeriod(period, data.Length, i);
res.Add(new Harmonic()
{
Magnitude = arrv[i].Magnitude,
Period = times[i],
Phase = arrv[i].Phase,
});
var mag = arrv[i].Magnitude;
sum += mag;
if (mag > max)
{
max = mag;
kmax = i;
}
}
}
return CaclHarmonycPeriod(period, data.Length, kmax);
}
public static Harmonic[] GetHarmonics(double[] data, TimeSpan period, int count)
{
var arrv = data.Select(d => new Complex32((float)d, 0)).ToArray();
Fourier.Forward(arrv);
var res = new List<Harmonic>();
for (int i = 1; i < count; i++)
{
res.Add(new Harmonic()
{
Imaginary = arrv[i].Imaginary,
Real = arrv[i].Real,
Magnitude = arrv[i].Magnitude,
Period = CaclHarmonycPeriod(period, data.Length, i),
Phase = arrv[i].Phase,
});
}
return res.ToArray();
}
public static double Calc(Harmonic[] harmonics, DateTime startTime, DateTime endTime, DateTime currentTime)
{
var sum = 0d;
var timeSpan = currentTime - startTime;
for (int i = 0; i < harmonics.Length; i++)
{
var currentPhase = System.Math.PI * 2 * timeSpan.TotalSeconds * (endTime - startTime).TotalSeconds / harmonics[i].Period.TotalSeconds / harmonics[i].Period.TotalSeconds + harmonics[i].Phase;
var value = harmonics[i].Real * System.Math.Cos(currentPhase) + harmonics[i].Imaginary * System.Math.Sign(currentPhase);
sum += value;
}
return sum;
}
public static TimeSpan CaclHarmonycPeriod(TimeSpan signalLength, int signalLengthItems, int harmonyNumber)

View File

@ -10,16 +10,28 @@ namespace KLHZ.Trader.Core.Tests
[Test]
public static void Test()
{
//var da = new List<float>();
//for (int i = 0; i < 100; i++)
//{
// da.Add((float)System.Math.Sin(0.5 * i)+(float)System.Math.Cos(0.5 * i));
//}
var da = new List<float>();
var da2 = new List<float>();
var dates = new List<DateTime>();
var dt = DateTime.UtcNow;
for (int i = 0; i < 1000; i++)
{
dt = dt.AddSeconds(1);
da.Add((float)System.Math.Sin(0.01 * i) + (float)System.Math.Cos(0.02 * i));
dates.Add(dt);
}
//var start = da.ToArray();
//var arrv = da.Select(d => new Complex32(d, 0)).ToArray();
//Fourier.Forward(arrv);
//var tem = arrv.Select(a => Complex32.Abs(a)).ToArray();
var start = da.ToArray();
var arrv = da.Select(d => new Complex32(d, 0)).ToArray();
Fourier.Forward(arrv);
var harms = FFT.GetHarmonics(da.Select(d => (double)d).ToArray(), dates.Last() - dates.First(), 20);
foreach(var d in dates)
{
da2.Add((float)FFT.Calc(harms, dates.First(), dates.Last(), d));
}
//var tem = arrv.Select(a => Complex32.Abs(a)).ToArray();
//var s = tem.Sum();
//Fourier.Inverse(arrv);
//var res = arrv.Select(a => a.Real).ToArray();

View File

@ -192,6 +192,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
}
_ = SyncPortfolioWorker();
_ = WritePricesTask();
}
catch (Exception ex)
@ -241,8 +242,12 @@ namespace KLHZ.Trader.Core.Exchange.Services
if (trade != null)
{
trade.Count = position.Quantity;
trade.Position = position.Quantity > 0 ? DataLayer.Entities.Trades.Enums.PositionType.Long : DataLayer.Entities.Trades.Enums.PositionType.Short;
trades.Remove(trade);
price = trade.Price;
context.Trades.Update(trade);
await context.SaveChangesAsync();
}
else
{
@ -351,40 +356,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
{
trade.Price = (oldAmount + newAmount) / trade.Count;
}
}
if (Accounts.TryGetValue(dealResult.AccountId, out var account))
{
if (account.Assets.TryGetValue(dealResult.Figi, out var asset))
{
if (trade.Count == 0)
{
await context.Trades.Where(t => t.Id == trade.Id && t.ArchiveStatus == 0)
.ExecuteUpdateAsync(t => t.SetProperty(tr => tr.ArchiveStatus, 1));
account.Assets.TryRemove(dealResult.Figi, out _);
return;
}
else
{
context.Trades.Update(trade);
await context.SaveChangesAsync();
var newAsset = new Asset()
{
AccountId = asset.AccountId,
Figi = asset.Figi,
Ticker = asset.Ticker,
BlockedItems = asset.BlockedItems,
BoughtAt = DateTime.UtcNow,
BoughtPrice = trade.Price,
Count = sign * trade.Count,
Position = trade.Count > 0 ? PositionType.Long : PositionType.Short,
Type = asset.Type,
TradeId = asset.TradeId,
};
account.Assets[dealResult.Figi] = newAsset;
return;
}
}
context.Trades.Update(trade);
await context.SaveChangesAsync();
}
}
}
@ -419,6 +392,25 @@ namespace KLHZ.Trader.Core.Exchange.Services
}
}
private async Task SyncPortfolioWorker()
{
while (true)
{
try
{
await Task.Delay(20000);
foreach (var acc in Accounts)
{
await SyncPortfolio(acc.Value);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка при цикличном обновлении портфеля");
}
}
}
private async Task WritePricesTask()
{
var buffer1 = new List<ProcessedPrice>();

View File

@ -245,6 +245,36 @@ namespace KLHZ.Trader.Service.Controllers
}
}
[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 => (double)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)
//{