149 lines
4.8 KiB
C#
149 lines
4.8 KiB
C#
using MathNet.Numerics;
|
||
using MathNet.Numerics.IntegralTransforms;
|
||
|
||
namespace KLHZ.Trader.Core.Math.Declisions.Utils
|
||
{
|
||
public static class FFT
|
||
{
|
||
public static void Test()
|
||
{
|
||
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();
|
||
Fourier.Forward(arrv);
|
||
|
||
Fourier.Inverse(arrv);
|
||
var res = arrv.Select(a => a.Real).ToArray();
|
||
|
||
for (int i = 0; i < 1000; i++)
|
||
{
|
||
var d = res[i] - start[i];
|
||
}
|
||
}
|
||
|
||
public static void А()
|
||
{
|
||
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();
|
||
Fourier.Forward(arrv);
|
||
|
||
Fourier.Inverse(arrv);
|
||
var res = arrv.Select(a => a.Real).ToArray();
|
||
|
||
for (int i = 0; i < 1000; i++)
|
||
{
|
||
var d = res[i] - start[i];
|
||
}
|
||
}
|
||
|
||
public static TimeSpan CaclHarmonycPeriod(TimeSpan signalLength, int signalLengthItems, int harmonyNumber)
|
||
{
|
||
var fdiscretisation = signalLengthItems / signalLength.TotalSeconds;
|
||
var fharm = harmonyNumber * fdiscretisation / signalLengthItems;
|
||
return TimeSpan.FromSeconds(1 / fharm);
|
||
}
|
||
|
||
public static double CalcCurrentPhase(Complex32[] spectr, int harmonyNumber)
|
||
{
|
||
var item = spectr[harmonyNumber];
|
||
return System.Math.Atan(item.Imaginary / item.Real);
|
||
}
|
||
|
||
public static (double min, double max) CalcPhaseRangeFoxMax(double aSin, double aCos, double initPhase, double level)
|
||
{
|
||
return CalcPhaseRange(aSin, aCos,initPhase, level, CheckMaxValue);
|
||
}
|
||
|
||
public static (double min, double max) CalcPhaseRangeFoxMin(double aSin, double aCos, double initPhase, double level)
|
||
{
|
||
return CalcPhaseRange(aSin, aCos, initPhase, level, CheckMinValue);
|
||
}
|
||
|
||
internal static (double min, double max) CalcPhaseRange(double aSin, double aCos, double initPhase, double level, Func<double, double, double, double,bool> comparer)
|
||
{
|
||
var x = new List<double>();
|
||
var xIndexes = new List<int>();
|
||
var y = new List<double>();
|
||
var max = double.MinValue;
|
||
var min = double.MaxValue;
|
||
var _2pi = 2 * System.Math.PI;
|
||
for (double i = 0; i <= 10 * System.Math.PI; i += 0.01)
|
||
{
|
||
var df = (((i) / _2pi) % 1) * _2pi;
|
||
var val = aSin * System.Math.Sin(i + initPhase) + aCos * System.Math.Cos(i + initPhase);
|
||
if (val > max)
|
||
{
|
||
max = val;
|
||
}
|
||
if (val < min)
|
||
{
|
||
min = val;
|
||
}
|
||
x.Add(df);
|
||
y.Add(val);
|
||
}
|
||
|
||
int start = -2;
|
||
int prevI = -2;
|
||
int end = -2;
|
||
|
||
var drange = -2;
|
||
|
||
var minPhaseTmp = 0d;
|
||
var maxPhaseTmp = 0d;
|
||
|
||
var minPhase = 0d;
|
||
var maxPhase = 0d;
|
||
for (int i = 0; i < y.Count; i++)
|
||
{
|
||
if (comparer(y[i],min,max,level))
|
||
{
|
||
if (start < 0)
|
||
{
|
||
minPhaseTmp = x[i];
|
||
start = i;
|
||
}
|
||
}
|
||
else if (start >= 0 && i - prevI == 1)
|
||
{
|
||
end = prevI;
|
||
maxPhaseTmp = x[end];
|
||
var drangeTmp = end - start;
|
||
if (drangeTmp > drange)
|
||
{
|
||
drange = drangeTmp;
|
||
minPhase = minPhaseTmp;
|
||
maxPhase = maxPhaseTmp;
|
||
}
|
||
start = -2;
|
||
}
|
||
prevI = i;
|
||
}
|
||
|
||
|
||
return (minPhase, maxPhase);
|
||
}
|
||
|
||
internal static bool CheckMaxValue(double val, double min, double max, double relativeValue)
|
||
{
|
||
return (val > (1 - relativeValue) * max);
|
||
}
|
||
|
||
internal static bool CheckMinValue(double val, double min, double max, double relativeValue)
|
||
{
|
||
return (val < (1 - relativeValue) * min);
|
||
}
|
||
}
|
||
}
|