mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-21 12:08:05 +00:00
Class optimization
This commit is contained in:
+44
-22
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
@@ -36,11 +35,13 @@ namespace QuanTAlib;
|
||||
/// Note: Second-order derivative providing acceleration insights
|
||||
/// </remarks>
|
||||
|
||||
public class Curvature : AbstractBase
|
||||
[SkipLocalsInit]
|
||||
public sealed class Curvature : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Slope _slopeCalculator;
|
||||
private readonly CircularBuffer _slopeBuffer;
|
||||
private const double Epsilon = 1e-10;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y-intercept of the curvature line.
|
||||
@@ -64,6 +65,7 @@ public class Curvature : AbstractBase
|
||||
|
||||
/// <param name="period">The number of points to consider for calculation.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is 2 or less.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Curvature(int period)
|
||||
{
|
||||
if (period <= 2)
|
||||
@@ -82,12 +84,14 @@ public class Curvature : AbstractBase
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of points to consider for calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Curvature(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
@@ -98,6 +102,7 @@ public class Curvature : AbstractBase
|
||||
Line = null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
@@ -107,6 +112,35 @@ public class Curvature : AbstractBase
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static (double sumX, double sumY) CalculateSums(ReadOnlySpan<double> slopes, int count)
|
||||
{
|
||||
double sumX = 0, sumY = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
sumX += i + 1;
|
||||
sumY += slopes[i];
|
||||
}
|
||||
return (sumX, sumY);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static (double sumSqX, double sumSqY, double sumSqXY) CalculateSquaredSums(
|
||||
ReadOnlySpan<double> slopes, int count, double avgX, double avgY)
|
||||
{
|
||||
double sumSqX = 0, sumSqY = 0, sumSqXY = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
double devX = (i + 1) - avgX;
|
||||
double devY = slopes[i] - avgY;
|
||||
sumSqX += devX * devX;
|
||||
sumSqY += devY * devY;
|
||||
sumSqXY += devX * devY;
|
||||
}
|
||||
return (sumSqX, sumSqY, sumSqXY);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
@@ -122,30 +156,17 @@ public class Curvature : AbstractBase
|
||||
}
|
||||
|
||||
int count = Math.Min(_slopeBuffer.Count, _period);
|
||||
var slopes = _slopeBuffer.GetSpan().ToArray();
|
||||
ReadOnlySpan<double> slopes = _slopeBuffer.GetSpan();
|
||||
|
||||
// Calculate averages
|
||||
double sumX = 0, sumY = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
sumX += i + 1;
|
||||
sumY += slopes[i];
|
||||
}
|
||||
var (sumX, sumY) = CalculateSums(slopes, count);
|
||||
double avgX = sumX / count;
|
||||
double avgY = sumY / count;
|
||||
|
||||
// Least squares method
|
||||
double sumSqX = 0, sumSqY = 0, sumSqXY = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
double devX = (i + 1) - avgX;
|
||||
double devY = slopes[i] - avgY;
|
||||
sumSqX += devX * devX;
|
||||
sumSqY += devY * devY;
|
||||
sumSqXY += devX * devY;
|
||||
}
|
||||
var (sumSqX, sumSqY, sumSqXY) = CalculateSquaredSums(slopes, count, avgX, avgY);
|
||||
|
||||
if (sumSqX > 0)
|
||||
if (sumSqX > Epsilon)
|
||||
{
|
||||
curvature = sumSqXY / sumSqX;
|
||||
Intercept = avgY - (curvature * avgX);
|
||||
@@ -155,9 +176,10 @@ public class Curvature : AbstractBase
|
||||
double stdDevY = Math.Sqrt(sumSqY / count);
|
||||
StdDev = stdDevY;
|
||||
|
||||
if (stdDevX * stdDevY != 0)
|
||||
double stdDevProduct = stdDevX * stdDevY;
|
||||
if (stdDevProduct > Epsilon)
|
||||
{
|
||||
double r = sumSqXY / (stdDevX * stdDevY) / count;
|
||||
double r = sumSqXY / (stdDevProduct) / count;
|
||||
RSquared = r * r;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user