фиксация экспериментов с FFT

dev
vlad zverzhkhovskiy 2025-09-25 10:03:04 +03:00
parent 56a8b2534a
commit cdc179b3a5
5 changed files with 168 additions and 21 deletions

View File

@ -5,6 +5,10 @@
None = 0,
Middle = 1,
UpperThen30Decil = 10,
LowerThenMediana = -50,
LowerThen30Decil = -0,
LowerThenMedianaGrowing = -50,
LowerThenMedianaFalling = -51,
Growing = -512,
Falling = -513,
}
}

View File

@ -8,7 +8,7 @@
public decimal Min { get; init; }
public decimal Mediana { get; init; }
public decimal Upper30Decil { get; init; }
public decimal Lower20Decil { get; init; }
public decimal Lower30Decil { get; init; }
public int Length { get; init; }
public DateTime LastTime { get; init; }
public DateTime StartTime { get; init; }

View File

@ -2,7 +2,6 @@
using KLHZ.Trader.Core.Math.Declisions.Dtos.FFT.Enums;
using MathNet.Numerics;
using MathNet.Numerics.IntegralTransforms;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace KLHZ.Trader.Core.Math.Declisions.Utils
{
@ -18,7 +17,47 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
}
else if (value < fftData.Mediana && System.Math.Sign(value2) >= 0)
{
return ValueAmplitudePosition.LowerThenMediana;
return ValueAmplitudePosition.LowerThenMedianaGrowing;
}
else if (value < fftData.Mediana && System.Math.Sign(value2) < 0)
{
return ValueAmplitudePosition.LowerThenMedianaFalling;
}
else
{
return ValueAmplitudePosition.Middle;
}
}
public static ValueAmplitudePosition CheckExtremums(FFTAnalyzeResult fftData, DateTime timestamp)
{
var value = (decimal)CalcAmplitude(fftData.Harmonics, fftData.StartTime, timestamp);
var value2 = (decimal)CalcExtremum(fftData.Harmonics, fftData.StartTime, timestamp);
if (value > fftData.Upper30Decil && System.Math.Sign(value2) <= 0)
{
return ValueAmplitudePosition.UpperThen30Decil;
}
else if (value < fftData.Lower30Decil && System.Math.Sign(value2) >= 0)
{
return ValueAmplitudePosition.LowerThen30Decil;
}
else
{
return ValueAmplitudePosition.Middle;
}
}
public static ValueAmplitudePosition CheckSign(FFTAnalyzeResult fftData, DateTime timestamp)
{
var value = (decimal)CalcAmplitude(fftData.Harmonics, fftData.StartTime, timestamp);
var value2 = (decimal)CalcExtremum(fftData.Harmonics, fftData.StartTime, timestamp);
if (System.Math.Sign(value2) <= 0)
{
return ValueAmplitudePosition.Falling;
}
else if (System.Math.Sign(value2) >= 0)
{
return ValueAmplitudePosition.Growing;
}
else
{
@ -49,7 +88,7 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
StartTime = startTime,
Mediana = newValues[newValues.Length / 2],
Upper30Decil = newValues[(int)(newValues.Length * 0.7)],
Lower20Decil = newValues[(int)(newValues.Length * 0.2)],
Lower30Decil = newValues[(int)(newValues.Length * 0.3)],
Max = newValues.Max(),
Min = newValues.Min(),
Length = values.Length,
@ -91,7 +130,60 @@ namespace KLHZ.Trader.Core.Math.Declisions.Utils
StartTime = result.StartTime,
Mediana = newValues[newValues.Length / 2],
Upper30Decil = newValues[(int)(newValues.Length * 0.7)],
Lower20Decil = newValues[(int)(newValues.Length * 0.2)],
Lower30Decil = newValues[(int)(newValues.Length * 0.3)],
Max = newValues.Max(),
Min = newValues.Min(),
};
}
public static FFTAnalyzeResult ReAnalyze(FFTAnalyzeResult result, string key, float energyPart, bool include)
{
var tmp = new List<Harmonic>();
var symmEnergy = result.Harmonics.Sum(h => h.Magnitude);
var tmpSumEnergy = 0f;
for (int i = 0; i < result.Harmonics.Length; i++)
{
tmpSumEnergy += result.Harmonics[i].Magnitude;
if (include)
{
if (tmpSumEnergy/ symmEnergy < energyPart)
{
tmp.Add(result.Harmonics[i]);
}
}
else
{
if (tmpSumEnergy / symmEnergy >= energyPart)
{
tmp.Add(result.Harmonics[i]);
}
}
}
var harms = tmp.ToArray();
var newValues = new decimal[result.Length];
var newValues2 = new decimal[result.Length];
var time = result.StartTime;
var dt = (result.LastTime - result.StartTime).TotalSeconds / result.Length;
for (int i = 0; i < result.Length; i++)
{
var currentTime = time.AddSeconds(i * dt);
newValues[i] = (decimal)CalcAmplitude(harms, result.StartTime, currentTime);
newValues2[i] = (decimal)CalcExtremum(harms, result.StartTime, currentTime);
}
newValues = newValues.Order().ToArray();
var ma = newValues2.Max();
var mi = newValues2.Min();
return new FFTAnalyzeResult()
{
Key = key,
Harmonics = harms,
LastTime = result.LastTime,
StartTime = result.StartTime,
Mediana = newValues[newValues.Length / 2],
Upper30Decil = newValues[(int)(newValues.Length * 0.7)],
Lower30Decil = newValues[(int)(newValues.Length * 0.3)],
Max = newValues.Max(),
Min = newValues.Min(),
};

View File

@ -92,9 +92,9 @@ namespace KLHZ.Trader.Core.Exchange.Services
return Task.CompletedTask;
}
public async ValueTask<(DateTime[] timestamps, decimal[] prices, bool isFullIntervalExists)> GetData(INewPrice message)
public async ValueTask<(DateTime[] timestamps, decimal[] prices, bool isFullIntervalExists)> GetData(INewPrice message, TimeSpan? windowSize = null)
{
var data2 = await _tradeDataProvider.GetData(message.Figi, TimeSpan.FromHours(1.5));
var data2 = await _tradeDataProvider.GetData(message.Figi, windowSize??TimeSpan.FromHours(1.5));
if (!data2.isFullIntervalExists)
{
data2 = await _tradeDataProvider.GetData(message.Figi, TimeSpan.FromHours(1));
@ -111,30 +111,80 @@ namespace KLHZ.Trader.Core.Exchange.Services
var currentTime = message.IsHistoricalData ? message.Time : DateTime.UtcNow;
var position = ValueAmplitudePosition.None;
var fft = await _tradeDataProvider.GetFFtResult(message.Figi);
var fftFull = await _tradeDataProvider.GetFFtResult(message.Figi + "_full");
//var highFreq = await _tradeDataProvider.GetFFtResult(message.Figi + "_high_freq");
//var lowFreq = await _tradeDataProvider.GetFFtResult(message.Figi + "_low_freq");
var step = message.IsHistoricalData ? 5 : 5;
if (fft.IsEmpty || (currentTime - fft.LastTime).TotalSeconds > step)
{
if (data.isFullIntervalExists)
{
var interpolatedData = SignalProcessing.InterpolateData(data.timestamps, data.prices, TimeSpan.FromSeconds(5));
var fftFull = FFT.Analyze(interpolatedData.timestamps, interpolatedData.values, message.Figi+"_full", TimeSpan.FromSeconds(15), TimeSpan.FromHours(24));
fftFull = FFT.Analyze(interpolatedData.timestamps, interpolatedData.values, message.Figi+"_full", TimeSpan.FromSeconds(120), TimeSpan.FromHours(24));
fft = FFT.ReAnalyze(fftFull, message.Figi, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(40));
//highFreq = FFT.ReAnalyze(fftFull, message.Figi + "_low_freq", TimeSpan.FromMinutes(20), TimeSpan.FromMinutes(60));
//lowFreq = FFT.ReAnalyze(fftFull, message.Figi + "_high_freq", TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(20));
await _tradeDataProvider.SetFFtResult(fft);
await _tradeDataProvider.SetFFtResult(fftFull);
//await _tradeDataProvider.SetFFtResult(fftFull);
//await _tradeDataProvider.SetFFtResult(lowFreq);
//await _tradeDataProvider.SetFFtResult(highFreq);
}
//var highFreqData = await GetData(message, TimeSpan.FromMinutes(120));
//if (highFreqData.isFullIntervalExists)
//{
// var interpolatehighFreqData = SignalProcessing.InterpolateData(data.timestamps, data.prices, TimeSpan.FromSeconds(5));
// highFreq = FFT.Analyze(interpolatehighFreqData.timestamps, interpolatehighFreqData.values, message.Figi + "_high_freq", TimeSpan.FromSeconds(20), TimeSpan.FromMinutes(120));
// await _tradeDataProvider.SetFFtResult(highFreq);
//}
}
else
position = FFT.Check(fft, message.Time);
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil)
{
position = FFT.Check(fft, message.Time);
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil)
{
await LogPrice(message, "upper30percent", message.Value);
}
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.LowerThenMediana)
{
await LogPrice(message, "lower30percent", message.Value);
}
await LogPrice(message, "upper30percent", message.Value);
}
if (position == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.LowerThenMedianaGrowing)
{
await LogPrice(message, "lower30percent", message.Value);
}
//var hposition = FFT.CheckExtremums(highFreq, message.Time);
//if (hposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil)
//{
// await LogPrice(message, "high_freq_high", message.Value);
//}
//if (hposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.LowerThen30Decil)
//{
// await LogPrice(message, "high_freq_low", message.Value);
//}
//var gposition = FFT.CheckSign(highFreq, message.Time);
//if (gposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.Growing)
//{
// await LogPrice(message, "growing", message.Value);
//}
//if (gposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.Falling)
//{
// await LogPrice(message, "falling", message.Value);
//}
//var lposition = FFT.CheckExtremums(lowFreq, message.Time);
//if (lposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.UpperThen30Decil)
//{
// await LogPrice(message, "low_freq_high", message.Value);
//}
//if (lposition == Math.Declisions.Dtos.FFT.Enums.ValueAmplitudePosition.LowerThen30Decil)
//{
// await LogPrice(message, "low_freq_low", message.Value);
//}
return position;
}
@ -821,7 +871,7 @@ INewPrice message, int windowMaxSize, decimal uptrendStartingDetectionMeanfullSt
var res = GetInitDict(1);
var position = await CheckHarmonicPosition(message);
if (position == ValueAmplitudePosition.LowerThenMediana)
if (position == ValueAmplitudePosition.LowerThenMedianaGrowing)
{
//res[TradingEvent.UptrendStart] = Constants.UppingCoefficient;
res[TradingEvent.DowntrendEnd] = Constants.UppingCoefficient;

View File

@ -54,6 +54,7 @@ namespace KLHZ.Trader.Service.Controllers
})
.ToArrayAsync();
foreach (var mess in data)
{
await _dataBus.Broadcast(mess);