изменена синхронизация портфеля
test / deploy_trader_prod (push) Successful in 1m39s
Details
test / deploy_trader_prod (push) Successful in 1m39s
Details
parent
80221648f7
commit
d0ec2af488
|
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using MathNet.Numerics;
|
using KLHZ.Trader.Core.Math.Declisions.Dtos;
|
||||||
|
using MathNet.Numerics;
|
||||||
using MathNet.Numerics.IntegralTransforms;
|
using MathNet.Numerics.IntegralTransforms;
|
||||||
|
|
||||||
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
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>();
|
var arrv = data.Select(d => new Complex32((float)d, 0)).ToArray();
|
||||||
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();
|
|
||||||
Fourier.Forward(arrv);
|
Fourier.Forward(arrv);
|
||||||
|
var res = new List<Harmonic>();
|
||||||
Fourier.Inverse(arrv);
|
var times = new TimeSpan[arrv.Length];
|
||||||
var res = arrv.Select(a => a.Real).ToArray();
|
var mags = arrv.Select(a => a.Magnitude).ToArray();
|
||||||
|
var phases = arrv.Select(a => a.Phase).ToArray();
|
||||||
for (int i = 0; i < 1000; i++)
|
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)
|
public static TimeSpan CaclHarmonycPeriod(TimeSpan signalLength, int signalLengthItems, int harmonyNumber)
|
||||||
|
|
|
@ -10,16 +10,28 @@ namespace KLHZ.Trader.Core.Tests
|
||||||
[Test]
|
[Test]
|
||||||
public static void Test()
|
public static void Test()
|
||||||
{
|
{
|
||||||
//var da = new List<float>();
|
var da = new List<float>();
|
||||||
//for (int i = 0; i < 100; i++)
|
var da2 = new List<float>();
|
||||||
//{
|
var dates = new List<DateTime>();
|
||||||
// da.Add((float)System.Math.Sin(0.5 * i)+(float)System.Math.Cos(0.5 * i));
|
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 start = da.ToArray();
|
||||||
//var arrv = da.Select(d => new Complex32(d, 0)).ToArray();
|
var arrv = da.Select(d => new Complex32(d, 0)).ToArray();
|
||||||
//Fourier.Forward(arrv);
|
Fourier.Forward(arrv);
|
||||||
//var tem = arrv.Select(a => Complex32.Abs(a)).ToArray();
|
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();
|
//var s = tem.Sum();
|
||||||
//Fourier.Inverse(arrv);
|
//Fourier.Inverse(arrv);
|
||||||
//var res = arrv.Select(a => a.Real).ToArray();
|
//var res = arrv.Select(a => a.Real).ToArray();
|
||||||
|
|
|
@ -192,6 +192,7 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ = SyncPortfolioWorker();
|
||||||
_ = WritePricesTask();
|
_ = WritePricesTask();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -241,8 +242,12 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
|
|
||||||
if (trade != null)
|
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);
|
trades.Remove(trade);
|
||||||
price = trade.Price;
|
price = trade.Price;
|
||||||
|
context.Trades.Update(trade);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -351,40 +356,8 @@ namespace KLHZ.Trader.Core.Exchange.Services
|
||||||
{
|
{
|
||||||
trade.Price = (oldAmount + newAmount) / trade.Count;
|
trade.Price = (oldAmount + newAmount) / trade.Count;
|
||||||
}
|
}
|
||||||
}
|
context.Trades.Update(trade);
|
||||||
|
await context.SaveChangesAsync();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
private async Task WritePricesTask()
|
||||||
{
|
{
|
||||||
var buffer1 = new List<ProcessedPrice>();
|
var buffer1 = new List<ProcessedPrice>();
|
||||||
|
|
|
@ -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]
|
//[HttpGet]
|
||||||
//public async Task GetBalance(string figi)
|
//public async Task GetBalance(string figi)
|
||||||
//{
|
//{
|
||||||
|
|
Loading…
Reference in New Issue