mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-22 12:38:06 +00:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Convolution : AbstractBase
|
||||
{
|
||||
private readonly double[] _kernel;
|
||||
private readonly int _kernelSize;
|
||||
private CircularBuffer _buffer;
|
||||
private double[] _normalizedKernel;
|
||||
|
||||
public Convolution(double[] kernel)
|
||||
{
|
||||
if (kernel == null || kernel.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("Kernel must not be null or empty.", nameof(kernel));
|
||||
}
|
||||
_kernel = kernel;
|
||||
_kernelSize = kernel.Length;
|
||||
_buffer = new CircularBuffer(_kernelSize);
|
||||
_normalizedKernel = new double[_kernelSize];
|
||||
Init();
|
||||
}
|
||||
|
||||
public Convolution(object source, double[] kernel) : this(kernel)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_buffer.Clear();
|
||||
Array.Copy(_kernel, _normalizedKernel, _kernelSize);
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double GetLastValid()
|
||||
{
|
||||
return _lastValidValue;
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
_buffer.Add(Input.Value, Input.IsNew);
|
||||
|
||||
// Normalize kernel on each calculation until buffer is full
|
||||
if (_index <= _kernelSize)
|
||||
{
|
||||
NormalizeKernel();
|
||||
}
|
||||
|
||||
double result = ConvolveBuffer();
|
||||
IsHot = _index >= _kernelSize;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void NormalizeKernel()
|
||||
{
|
||||
int activeLength = Math.Min(_index, _kernelSize);
|
||||
double sum = 0;
|
||||
|
||||
// Calculate the sum of the active kernel elements
|
||||
for (int i = 0; i < activeLength; i++)
|
||||
{
|
||||
sum += _kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel or set equal weights if the sum is zero
|
||||
double normalizationFactor = (sum != 0) ? sum : activeLength;
|
||||
for (int i = 0; i < activeLength; i++)
|
||||
{
|
||||
_normalizedKernel[i] = _kernel[i] / normalizationFactor;
|
||||
}
|
||||
|
||||
// Set the rest of the normalized kernel to zero
|
||||
Array.Clear(_normalizedKernel, activeLength, _kernelSize - activeLength);
|
||||
}
|
||||
|
||||
private double ConvolveBuffer()
|
||||
{
|
||||
double sum = 0;
|
||||
var bufferSpan = _buffer.GetSpan();
|
||||
int activeLength = Math.Min(_index, _kernelSize);
|
||||
|
||||
for (int i = 0; i < activeLength; i++)
|
||||
{
|
||||
sum += bufferSpan[activeLength - 1 - i] * _normalizedKernel[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// DWMA: Double Weighted Moving Average
|
||||
/// DWMA is a technical indicator that applies a Weighted Moving Average (WMA) twice to the input data.
|
||||
/// The weights are decreasing over the period with p^2 decay, and the most recent data has the heaviest weight.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Smoothness: ★★★★★ (5/5)
|
||||
/// Sensitivity: ★★★☆☆ (3/5)
|
||||
/// Overshooting: ★★★★☆ (4/5)
|
||||
/// Lag: ★★☆☆☆ (2/5)
|
||||
///
|
||||
/// The DWMA is calculated by applying two WMAs in sequence:
|
||||
/// 1. An inner WMA is applied to the input data.
|
||||
/// 2. An outer WMA is then applied to the result of the inner WMA.
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - The weight distribution follows a p^2 decay, where p is the position of the data point.
|
||||
/// - More recent data points receive higher weights, emphasizing recent price movements.
|
||||
/// - The double application of WMA results in a smoother indicator compared to a single WMA.
|
||||
///
|
||||
/// The formula for DWMA can be expressed as:
|
||||
/// DWMA = WMA(WMA(price, period), period)
|
||||
///
|
||||
/// Where WMA is the Weighted Moving Average function and 'period' is the number of data points used in each WMA calculation.
|
||||
/// </remarks>
|
||||
|
||||
public class Dwma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Wma _innerWma;
|
||||
private readonly Wma _outerWma;
|
||||
|
||||
public Dwma(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_innerWma = new Wma(period);
|
||||
_outerWma = new Wma(period);
|
||||
Name = "Wma";
|
||||
WarmupPeriod = 2 * _period - 1;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Dwma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_innerWma.Init();
|
||||
_outerWma.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Calculate inner WMA
|
||||
TValue innerResult = _innerWma.Calc(Input);
|
||||
|
||||
// Calculate outer WMA using the result of inner WMA
|
||||
TValue outerResult = _outerWma.Calc(innerResult);
|
||||
|
||||
double result = outerResult.Value;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Epma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Epma(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_convolution = new Convolution(GenerateKernel(_period));
|
||||
Name = "Epma";
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Epma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_convolution.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Use Convolution for calculation
|
||||
TValue convolutionResult = _convolution.Calc(Input);
|
||||
|
||||
double result = convolutionResult.Value;
|
||||
|
||||
// Adjust for partial periods during warmup
|
||||
if (_index < _period)
|
||||
{
|
||||
double[] partialKernel = GenerateKernel(_index);
|
||||
result /= partialKernel.Sum();
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double[] GenerateKernel(int period)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
double weightSum = 0;
|
||||
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] = (2 * period - 1) - 3 * i;
|
||||
weightSum += kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] /= weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Fwma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Fwma(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_convolution = new Convolution(GenerateKernel(_period));
|
||||
Name = "Fwma";
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Fwma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
public static double[] GenerateKernel(int period)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
double[] fibSeries = new double[period];
|
||||
double weightSum = 0;
|
||||
|
||||
// Generate Fibonacci series
|
||||
fibSeries[0] = fibSeries[1] = 1;
|
||||
for (int i = 2; i < period; i++)
|
||||
{
|
||||
fibSeries[i] = fibSeries[i - 1] + fibSeries[i - 2];
|
||||
}
|
||||
|
||||
// Reverse the series to give more weight to recent prices
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] = fibSeries[period - 1 - i];
|
||||
weightSum += kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] /= weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_convolution.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Use Convolution for calculation
|
||||
TValue convolutionResult = _convolution.Calc(Input);
|
||||
|
||||
double result = convolutionResult.Value;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Gma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Gma(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_convolution = new Convolution(GenerateKernel(_period));
|
||||
Name = "Gma";
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Gma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
public static double[] GenerateKernel(int period, double sigma = 1.0)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
double weightSum = 0;
|
||||
int center = period / 2;
|
||||
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
double x = (i - center) / (double)center;
|
||||
kernel[i] = Math.Exp(-(x * x) / (2 * sigma * sigma));
|
||||
weightSum += kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] /= weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_convolution.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Use Convolution for calculation
|
||||
TValue convolutionResult = _convolution.Calc(Input);
|
||||
|
||||
double result = convolutionResult.Value;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Hma : AbstractBase
|
||||
{
|
||||
private readonly int _period, _sqrtPeriod;
|
||||
private readonly Convolution _wmaHalf, _wmaFull, _wmaFinal;
|
||||
|
||||
public Hma(int period)
|
||||
{
|
||||
if (period < 2)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 2.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_sqrtPeriod = (int)Math.Sqrt(period);
|
||||
_wmaHalf = new Convolution(GenerateWmaKernel(period / 2));
|
||||
_wmaFull = new Convolution(GenerateWmaKernel(period));
|
||||
_wmaFinal = new Convolution(GenerateWmaKernel(_sqrtPeriod));
|
||||
Name = "Hma";
|
||||
WarmupPeriod = _period + _sqrtPeriod - 1;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Hma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
private static double[] GenerateWmaKernel(int period)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
double weightSum = period * (period + 1) / 2.0;
|
||||
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] = (period - i) / weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_wmaHalf.Init();
|
||||
_wmaFull.Init();
|
||||
_wmaFinal.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Calculate WMA(n/2) and WMA(n)
|
||||
double wmaHalfResult = _wmaHalf.Calc(Input).Value;
|
||||
double wmaFullResult = _wmaFull.Calc(Input).Value;
|
||||
|
||||
// Calculate 2*WMA(n/2) - WMA(n)
|
||||
double intermediateResult = 2 * wmaHalfResult - wmaFullResult;
|
||||
|
||||
// Calculate final WMA
|
||||
double result = _wmaFinal.Calc(new TValue(Input.Time, intermediateResult, Input.IsNew)).Value;
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Sinema : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Sinema(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_convolution = new Convolution(GenerateKernel(_period));
|
||||
Name = "Sinema";
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Sinema(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_convolution.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Use Convolution for calculation
|
||||
TValue convolutionResult = _convolution.Calc(Input);
|
||||
|
||||
double result = convolutionResult.Value;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static double[] GenerateKernel(int period)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
double weightSum = 0;
|
||||
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
// Use sine function to generate weights
|
||||
kernel[i] = Math.Sin((i + 1) * Math.PI / (period + 1));
|
||||
weightSum += kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] /= weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Trima : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Trima(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_convolution = new Convolution(GenerateKernel(_period));
|
||||
Name = "Trima";
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Trima(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
private static double[] GenerateKernel(int period)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
int halfPeriod = (period + 1) / 2;
|
||||
double weightSum = 0;
|
||||
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
if (i < halfPeriod)
|
||||
{
|
||||
kernel[i] = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
kernel[i] = period - i;
|
||||
}
|
||||
weightSum += kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] /= weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_convolution.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Use Convolution for calculation
|
||||
TValue convolutionResult = _convolution.Calc(Input);
|
||||
|
||||
double result = convolutionResult.Value;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Wma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Wma(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
}
|
||||
_period = period;
|
||||
_convolution = new Convolution(GenerateWmaKernel(_period));
|
||||
Name = "Wma";
|
||||
WarmupPeriod = _period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Wma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
private static double[] GenerateWmaKernel(int period)
|
||||
{
|
||||
double[] kernel = new double[period];
|
||||
double weightSum = period * (period + 1) / 2.0;
|
||||
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] = (period - i) / weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
|
||||
private new void Init()
|
||||
{
|
||||
base.Init();
|
||||
_convolution.Init();
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
// Use Convolution for calculation
|
||||
TValue convolutionResult = _convolution.Calc(Input);
|
||||
|
||||
double result = convolutionResult.Value;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user