mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-06 13:07:44 +00:00
0.5.1 (#41)
This commit is contained in:
+12
-8
@@ -13,7 +13,7 @@
|
||||
<PackageReference Include="xunit.runner.console" Version="2.9.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
|
||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||
@@ -25,15 +25,19 @@
|
||||
<PackageReference Include="TALib.NETCore" Version="0.4.4" />
|
||||
<PackageReference Include="Tulip.NETCore" Version="0.8.0.1" />
|
||||
<PackageReference Include="Trady.Analysis" Version="3.2.8" />
|
||||
<!--
|
||||
<PackageReference Include="quantconnect.indicators" Version="2.5.16573" />
|
||||
<PackageReference Include="stocksharp.algo" Version="5.0.193" />
|
||||
<PackageReference Include="OoplesFinance.StockIndicators" Version="1.0.53" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\lib\quantalib.csproj" />
|
||||
<Reference Include="TradingPlatform.BusinessLayer">
|
||||
<HintPath>..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
</Reference>
|
||||
<None Include="..\.github\TradingPlatform.BusinessLayer.xml">
|
||||
<Link>TradingPlatform.BusinessLayer.xml</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\quantower\**\*.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
+21
-3
@@ -8,7 +8,7 @@ namespace QuanTAlib;
|
||||
public class EventingTests
|
||||
{
|
||||
[Fact]
|
||||
public void VerifyEventBasedCalculations()
|
||||
public void EventBasedCalculations()
|
||||
{
|
||||
// Create a cryptographically secure random number generator
|
||||
using var rng = RandomNumberGenerator.Create();
|
||||
@@ -28,6 +28,7 @@ public class EventingTests
|
||||
("Dwma", new Dwma(p), new Dwma(input, p)),
|
||||
("Ema", new Ema(p), new Ema(input, p)),
|
||||
("Epma", new Epma(p), new Epma(input, p)),
|
||||
("Pwma", new Pwma(p), new Pwma(input, p)),
|
||||
("Frama", new Frama(p), new Frama(input, p)),
|
||||
("Fwma", new Fwma(p), new Fwma(input, p)),
|
||||
("Gma", new Gma(p), new Gma(input, p)),
|
||||
@@ -49,7 +50,24 @@ public class EventingTests
|
||||
("Rma", new Rma(p), new Rma(input, p)),
|
||||
("Tema", new Tema(p), new Tema(input, p)),
|
||||
("Kama", new Kama(2, 30, 6), new Kama(input, 2, 30, 6)),
|
||||
("Zlema", new Zlema(p), new Zlema(input, p))
|
||||
("Zlema", new Zlema(p), new Zlema(input, p)),
|
||||
// error classes
|
||||
("Mae", new Mae(p), new Mae(input, p)),
|
||||
("Mapd", new Mapd(p), new Mapd(input, p)),
|
||||
("Mape", new Mape(p), new Mape(input, p)),
|
||||
("Mase", new Mase(p), new Mase(input, p)),
|
||||
("Mda", new Mda(p), new Mda(input, p)),
|
||||
("Me", new Me(p), new Me(input, p)),
|
||||
("Mpe", new Mpe(p), new Mpe(input, p)),
|
||||
("Mse", new Mse(p), new Mse(input, p)),
|
||||
("Msle", new Msle(p), new Msle(input, p)),
|
||||
("Rae", new Rae(p), new Rae(input, p)),
|
||||
("Rmse", new Rmse(p), new Rmse(input, p)),
|
||||
("Rmsle", new Rmsle(p), new Rmsle(input, p)),
|
||||
("Rse", new Rse(p), new Rse(input, p)),
|
||||
("Smape", new Smape(p), new Smape(input, p)),
|
||||
("Rsquared", new Rsquared(p), new Rsquared(input, p)),
|
||||
("Huberloss", new Huberloss(p), new Huberloss(input, p))
|
||||
};
|
||||
|
||||
// Generate 200 random values and feed them to both direct and event-based indicators
|
||||
@@ -81,4 +99,4 @@ public class EventingTests
|
||||
rng.GetBytes(bytes);
|
||||
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
using Xunit;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class IndicatorTests
|
||||
{
|
||||
private readonly RandomNumberGenerator rng;
|
||||
private const int SeriesLen = 1000;
|
||||
private const int Corrections = 100;
|
||||
|
||||
public IndicatorTests()
|
||||
{
|
||||
rng = RandomNumberGenerator.Create();
|
||||
}
|
||||
|
||||
private int GetRandomNumber(int minValue, int maxValue)
|
||||
{
|
||||
byte[] randomBytes = new byte[4];
|
||||
rng.GetBytes(randomBytes);
|
||||
int randomInt = BitConverter.ToInt32(randomBytes, 0);
|
||||
return Math.Abs(randomInt % (maxValue - minValue)) + minValue;
|
||||
}
|
||||
|
||||
// skipcq: CS-R1055
|
||||
private static readonly ITValue[] indicators =
|
||||
{
|
||||
new Ema(period: 10, useSma: true),
|
||||
new Alma(period: 14, offset: 0.85, sigma: 6),
|
||||
new Afirma(periods: 4, taps: 4, window: Afirma.WindowType.Blackman),
|
||||
new Convolution(new[] { 1.0, 2, 3, 2, 1 }),
|
||||
new Dema(period: 14),
|
||||
new Dsma(period: 14),
|
||||
new Dwma(period: 14),
|
||||
new Epma(period: 14),
|
||||
new Frama(period: 14),
|
||||
new Fwma(period: 14),
|
||||
new Gma(period: 14),
|
||||
new Hma(period: 14),
|
||||
new Hwma(period: 14),
|
||||
new Kama(period: 14),
|
||||
new Mama(fastLimit: 0.5, slowLimit: 0.05),
|
||||
new Mgdi(period: 14),
|
||||
new Mma(period: 14),
|
||||
new Qema(),
|
||||
new Rema(period: 14),
|
||||
new Rma(period: 14),
|
||||
new Sinema(period: 14),
|
||||
new Sma(period: 14),
|
||||
new Smma(period: 14),
|
||||
new T3(period: 14),
|
||||
new Tema(period: 14),
|
||||
new Trima(period: 14),
|
||||
new Vidya(shortPeriod: 14, longPeriod: 30, alpha: 0.2),
|
||||
new Wma(period: 14),
|
||||
new Zlema(period: 14),
|
||||
|
||||
new Curvature(period: 14),
|
||||
new Entropy(period: 14),
|
||||
new Kurtosis(period: 14),
|
||||
new Max(period: 14, decay: 0.01),
|
||||
new Median(period: 14),
|
||||
new Min(period: 14, decay: 0.01),
|
||||
new Median(period: 14),
|
||||
new Mode(period: 14),
|
||||
new Percentile(period: 14, percent: 50),
|
||||
new Skew(period: 14),
|
||||
new Slope(period: 14),
|
||||
new Stddev(period: 14),
|
||||
new Variance(period: 14),
|
||||
new Zscore(period: 14),
|
||||
|
||||
new Historical(period: 14),
|
||||
new Realized(period: 14)
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetIndicators))]
|
||||
public void IndicatorIsNew(ITValue indicator)
|
||||
{
|
||||
var indicator1 = indicator;
|
||||
var indicator2 = indicator;
|
||||
|
||||
MethodInfo calcMethod = FindCalcMethod(indicator.GetType());
|
||||
if (calcMethod == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Calc method not found for indicator type: {indicator.GetType().Name}");
|
||||
}
|
||||
|
||||
for (int i = 0; i < SeriesLen; i++)
|
||||
{
|
||||
TValue item1 = new(Time: DateTime.Now, Value: GetRandomNumber(-100, 100), IsNew: true);
|
||||
InvokeCalc(indicator1, calcMethod, item1);
|
||||
|
||||
for (int j = 0; j < Corrections; j++)
|
||||
{
|
||||
item1 = new(Time: DateTime.Now, Value: GetRandomNumber(-100, 100), IsNew: false);
|
||||
InvokeCalc(indicator1, calcMethod, item1);
|
||||
}
|
||||
|
||||
var item2 = new TValue(item1.Time, item1.Value, IsNew: true);
|
||||
InvokeCalc(indicator2, calcMethod, item2);
|
||||
|
||||
Assert.Equal(indicator1.Value, indicator2.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodInfo FindCalcMethod(Type type)
|
||||
{
|
||||
while (type != null && type != typeof(object))
|
||||
{
|
||||
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
|
||||
.Where(m => m.Name == "Calc")
|
||||
.ToList();
|
||||
|
||||
if (methods.Count > 0)
|
||||
{
|
||||
// Prefer the method with TValue parameter
|
||||
var method = methods.FirstOrDefault(m =>
|
||||
{
|
||||
var parameters = m.GetParameters();
|
||||
return parameters.Length == 1 && parameters[0].ParameterType == typeof(TValue);
|
||||
});
|
||||
|
||||
// If not found, return the first method
|
||||
return method ?? methods.First();
|
||||
}
|
||||
|
||||
type = type.BaseType!;
|
||||
}
|
||||
return null!;
|
||||
}
|
||||
|
||||
private static void InvokeCalc(ITValue indicator, MethodInfo calcMethod, TValue input)
|
||||
{
|
||||
var parameters = calcMethod.GetParameters();
|
||||
if (parameters.Length == 1)
|
||||
{
|
||||
calcMethod.Invoke(indicator, new object[] { input });
|
||||
}
|
||||
else if (parameters.Length == 2)
|
||||
{
|
||||
calcMethod.Invoke(indicator, new object[] { input, double.NaN });
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid number of parameters for Calc method in indicator type: {indicator.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetIndicators()
|
||||
{
|
||||
return indicators.Select(indicator => new object[] { indicator });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib
|
||||
{
|
||||
public class QuantowerTests
|
||||
{
|
||||
private void TestIndicator<T>(string fieldName = "ma") where T : Indicator, new()
|
||||
{
|
||||
var indicator = new T();
|
||||
try
|
||||
{
|
||||
var onInitMethod = typeof(T).GetMethod("OnInit", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Assert.NotNull(onInitMethod);
|
||||
onInitMethod.Invoke(indicator, null);
|
||||
|
||||
var field = typeof(T).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Assert.NotNull(field);
|
||||
var fieldValue = field.GetValue(indicator);
|
||||
Assert.NotNull(fieldValue);
|
||||
|
||||
Assert.NotNull(indicator.ShortName);
|
||||
Assert.NotEmpty(indicator.ShortName);
|
||||
Assert.NotNull(indicator.Name);
|
||||
Assert.NotEmpty(indicator.Name);
|
||||
Assert.NotNull(indicator.Description);
|
||||
Assert.NotEmpty(indicator.Description);
|
||||
Assert.IsAssignableFrom<Indicator>(indicator);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Xunit.Sdk.XunitException($"Test failed for {typeof(T).Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Averages Indicators
|
||||
[Fact] public void Afirma() => TestIndicator<AfirmaIndicator>();
|
||||
[Fact] public void Alma() => TestIndicator<AlmaIndicator>();
|
||||
[Fact] public void Dema() => TestIndicator<DemaIndicator>();
|
||||
[Fact] public void Dsma() => TestIndicator<DsmaIndicator>();
|
||||
[Fact] public void Dwma() => TestIndicator<DwmaIndicator>();
|
||||
[Fact] public void Ema() => TestIndicator<EmaIndicator>();
|
||||
[Fact] public void Epma() => TestIndicator<EpmaIndicator>();
|
||||
[Fact] public void Frama() => TestIndicator<FramaIndicator>();
|
||||
[Fact] public void Fwma() => TestIndicator<FwmaIndicator>();
|
||||
[Fact] public void Gma() => TestIndicator<GmaIndicator>();
|
||||
[Fact] public void Hma() => TestIndicator<HmaIndicator>();
|
||||
[Fact] public void Htit() => TestIndicator<HtitIndicator>();
|
||||
[Fact] public void Hwma() => TestIndicator<HwmaIndicator>();
|
||||
[Fact] public void Jma() => TestIndicator<JmaIndicator>();
|
||||
[Fact] public void Kama() => TestIndicator<KamaIndicator>();
|
||||
[Fact] public void Ltma() => TestIndicator<LtmaIndicator>();
|
||||
[Fact] public void Maaf() => TestIndicator<MaafIndicator>();
|
||||
[Fact] public void Mama() => TestIndicator<MamaIndicator>();
|
||||
[Fact] public void Mgdi() => TestIndicator<MgdiIndicator>();
|
||||
[Fact] public void Mma() => TestIndicator<MmaIndicator>();
|
||||
[Fact] public void Pwma() => TestIndicator<PwmaIndicator>();
|
||||
[Fact] public void Qema() => TestIndicator<QemaIndicator>();
|
||||
[Fact] public void Rema() => TestIndicator<RemaIndicator>();
|
||||
[Fact] public void Rma() => TestIndicator<RmaIndicator>();
|
||||
[Fact] public void Sinema() => TestIndicator<SinemaIndicator>();
|
||||
[Fact] public void Sma() => TestIndicator<SmaIndicator>();
|
||||
[Fact] public void Smma() => TestIndicator<SmmaIndicator>();
|
||||
[Fact] public void T3() => TestIndicator<T3Indicator>();
|
||||
[Fact] public void Tema() => TestIndicator<TemaIndicator>();
|
||||
[Fact] public void Trima() => TestIndicator<TrimaIndicator>();
|
||||
[Fact] public void Vidya() => TestIndicator<VidyaIndicator>();
|
||||
[Fact] public void Wma() => TestIndicator<WmaIndicator>();
|
||||
[Fact] public void Zlema() => TestIndicator<ZlemaIndicator>();
|
||||
|
||||
// Statistics Indicators
|
||||
[Fact] public void Curvature() => TestIndicator<CurvatureIndicator>("curvature");
|
||||
[Fact] public void Entropy() => TestIndicator<EntropyIndicator>("entropy");
|
||||
[Fact] public void Kurtosis() => TestIndicator<KurtosisIndicator>("kurtosis");
|
||||
[Fact] public void Max() => TestIndicator<MaxIndicator>("ma");
|
||||
[Fact] public void Median() => TestIndicator<MedianIndicator>("med");
|
||||
[Fact] public void Min() => TestIndicator<MinIndicator>("mi");
|
||||
[Fact] public void Mode() => TestIndicator<ModeIndicator>("mode");
|
||||
[Fact] public void Percentile() => TestIndicator<PercentileIndicator>("percentile");
|
||||
[Fact] public void Skew() => TestIndicator<SkewIndicator>("skew");
|
||||
[Fact] public void Slope() => TestIndicator<SlopeIndicator>("slope");
|
||||
[Fact] public void Stddev() => TestIndicator<StddevIndicator>("stddev");
|
||||
[Fact] public void Variance() => TestIndicator<VarianceIndicator>("variance");
|
||||
[Fact] public void Zscore() => TestIndicator<ZScoreIndicator>("zScore");
|
||||
|
||||
// Volatility Indicators
|
||||
[Fact] public void Atr() => TestIndicator<AtrIndicator>("atr");
|
||||
[Fact] public void Historical() => TestIndicator<HistoricalIndicator>("historical");
|
||||
[Fact] public void Realized() => TestIndicator<RealizedIndicator>("realized");
|
||||
[Fact] public void Rvi() => TestIndicator<RviIndicator>("rvi");
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ using System.Security.Cryptography;
|
||||
|
||||
#pragma warning disable S1944, S2053, S2222, S2259, S2583, S2589, S3329, S3655, S3900, S3949, S3966, S4158, S4347, S5773, S6781
|
||||
|
||||
namespace QuanTAlib;
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class SkenderTests
|
||||
{
|
||||
|
||||
@@ -109,26 +109,6 @@ public class TAlibTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WMA()
|
||||
{
|
||||
for (int run = 0; run < iterations; run++)
|
||||
{
|
||||
int period = GetRandomNumber(5, 55);
|
||||
Wma ma = new(period);
|
||||
TSeries QL = new();
|
||||
foreach (TBar item in feed)
|
||||
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
|
||||
Core.Wma(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period);
|
||||
Assert.Equal(QL.Length, TALIB.Count());
|
||||
for (int i = QL.Length - 1; i > 2000; i--)
|
||||
{
|
||||
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void T3()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,529 @@
|
||||
using Xunit;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class AveragesUpdateTests
|
||||
{
|
||||
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
||||
private const int RandomUpdates = 100;
|
||||
private const double ReferenceValue = 100.0;
|
||||
private const int precision = 8;
|
||||
|
||||
private double GetRandomDouble()
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
rng.GetBytes(bytes);
|
||||
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200 - 100; // Range: -100 to 100
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Afirma_Update()
|
||||
{
|
||||
var indicator = new Afirma(periods: 14, taps: 4, window: Afirma.WindowType.Blackman);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alma_Update()
|
||||
{
|
||||
var indicator = new Alma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Convolution_Update()
|
||||
{
|
||||
var indicator = new Convolution(new double[] { 1, 2, 3, 2, 1 });
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dema_Update()
|
||||
{
|
||||
var indicator = new Dema(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dsma_Update()
|
||||
{
|
||||
var indicator = new Dsma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dwma_Update()
|
||||
{
|
||||
var indicator = new Dwma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ema_Update()
|
||||
{
|
||||
var indicator = new Ema(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Epma_Update()
|
||||
{
|
||||
var indicator = new Epma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Frama_Update()
|
||||
{
|
||||
var indicator = new Frama(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fwma_Update()
|
||||
{
|
||||
var indicator = new Fwma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gma_Update()
|
||||
{
|
||||
var indicator = new Gma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Hma_Update()
|
||||
{
|
||||
var indicator = new Hma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Htit_Update()
|
||||
{
|
||||
var indicator = new Htit();
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Hwma_Update()
|
||||
{
|
||||
var indicator = new Hwma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Jma_Update()
|
||||
{
|
||||
var indicator = new Jma(period: 14, phase: 0);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kama_Update()
|
||||
{
|
||||
var indicator = new Kama(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ltma_Update()
|
||||
{
|
||||
var indicator = new Ltma(gamma: 0.2);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Maaf_Update()
|
||||
{
|
||||
var indicator = new Maaf(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mama_Update()
|
||||
{
|
||||
var indicator = new Mama(fastLimit: 0.5, slowLimit: 0.05);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mgdi_Update()
|
||||
{
|
||||
var indicator = new Mgdi(period: 14, kFactor: 0.6);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mma_Update()
|
||||
{
|
||||
var indicator = new Mma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Pwma_Update()
|
||||
{
|
||||
var indicator = new Pwma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Qema_Update()
|
||||
{
|
||||
var indicator = new Qema(k1: 0.2, k2: 0.2, k3: 0.2, k4: 0.2);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rema_Update()
|
||||
{
|
||||
var indicator = new Rema(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rma_Update()
|
||||
{
|
||||
var indicator = new Rma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sinema_Update()
|
||||
{
|
||||
var indicator = new Sinema(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sma_Update()
|
||||
{
|
||||
var indicator = new Sma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Smma_Update()
|
||||
{
|
||||
var indicator = new Smma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void T3_Update()
|
||||
{
|
||||
var indicator = new T3(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tema_Update()
|
||||
{
|
||||
var indicator = new Tema(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Trima_Update()
|
||||
{
|
||||
var indicator = new Trima(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Vidya_Update()
|
||||
{
|
||||
var indicator = new Vidya(shortPeriod: 14, longPeriod: 30, alpha: 0.2);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Wma_Update()
|
||||
{
|
||||
var indicator = new Wma(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Zlema_Update()
|
||||
{
|
||||
var indicator = new Zlema(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
using Xunit;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class UpdateTests
|
||||
{
|
||||
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
||||
private const int RandomUpdates = 100;
|
||||
private const double ReferenceValue = 100.0;
|
||||
private const int precision = 8;
|
||||
|
||||
private double GetRandomDouble()
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
rng.GetBytes(bytes);
|
||||
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200 - 100; // Range: -100 to 100
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Huberloss_Update()
|
||||
{
|
||||
var indicator = new Huberloss(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mae_Update()
|
||||
{
|
||||
var indicator = new Mae(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mapd_Update()
|
||||
{
|
||||
var indicator = new Mapd(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mape_Update()
|
||||
{
|
||||
var indicator = new Mape(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mase_Update()
|
||||
{
|
||||
var indicator = new Mase(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mda_Update()
|
||||
{
|
||||
var indicator = new Mda(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Me_Update()
|
||||
{
|
||||
var indicator = new Me(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mpe_Update()
|
||||
{
|
||||
var indicator = new Mpe(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mse_Update()
|
||||
{
|
||||
var indicator = new Mse(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Msle_Update()
|
||||
{
|
||||
var indicator = new Msle(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rae_Update()
|
||||
{
|
||||
var indicator = new Rae(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rmse_Update()
|
||||
{
|
||||
var indicator = new Rmse(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rmsle_Update()
|
||||
{
|
||||
var indicator = new Rmsle(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rse_Update()
|
||||
{
|
||||
var indicator = new Rse(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Smape_Update()
|
||||
{
|
||||
var indicator = new Smape(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rsquared_Update()
|
||||
{
|
||||
var indicator = new Rsquared(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
using Xunit;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace QuanTAlib.Tests;
|
||||
|
||||
public class StatisticsUpdateTests
|
||||
{
|
||||
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
||||
private const int RandomUpdates = 100;
|
||||
private const double ReferenceValue = 100.0;
|
||||
private const int precision = 8;
|
||||
|
||||
private double GetRandomDouble()
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
rng.GetBytes(bytes);
|
||||
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200 - 100; // Range: -100 to 100
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Curvature_Update()
|
||||
{
|
||||
var indicator = new Curvature(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Entropy_Update()
|
||||
{
|
||||
var indicator = new Entropy(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Kurtosis_Update()
|
||||
{
|
||||
var indicator = new Kurtosis(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Max_Update()
|
||||
{
|
||||
var indicator = new Max(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Median_Update()
|
||||
{
|
||||
var indicator = new Median(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Min_Update()
|
||||
{
|
||||
var indicator = new Min(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mode_Update()
|
||||
{
|
||||
var indicator = new Mode(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Percentile_Update()
|
||||
{
|
||||
var indicator = new Percentile(period: 14, percent: 50);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skew_Update()
|
||||
{
|
||||
var indicator = new Skew(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slope_Update()
|
||||
{
|
||||
var indicator = new Slope(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stddev_Update()
|
||||
{
|
||||
var indicator = new Stddev(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Variance_Update()
|
||||
{
|
||||
var indicator = new Variance(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Zscore_Update()
|
||||
{
|
||||
var indicator = new Zscore(period: 14);
|
||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
|OHLC4 - Average Price|`️.OHLC4`|CandlePart.OHLC4|AvgPrice||
|
||||
|HLCC4 - Weighted Price|`️.HLCC4`||WclPrice||
|
||||
|<br>||||
|
||||
|**STATISTICS AND NUMERICAL ANALYSIS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|**STATISTICS, ERRORS AND NUMERICAL ANALYSIS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|BETA - Beta coefficient|||||
|
||||
|CORR - Correlation Coefficient|||||
|
||||
|CURVATURE - Rate of Change in Direction or Slope|`Curvature`||||
|
||||
@@ -21,28 +21,28 @@
|
||||
|KURTOSIS - Measure of Tails/Peakedness|`Kurtosis`||||
|
||||
|HUBER - Huber Loss|||||
|
||||
|MAX - Maximum with exponential decay|`Max`||||
|
||||
|MAE - Mean Absolute Error|||||
|
||||
|MAPD - Mean Absolute Percentage Deviation|||||
|
||||
|MAPE - Mean Absolute Percentage Error|||||
|
||||
|MASE - Mean Absolute Scaled Error|||||
|
||||
|MAE - Mean Absolute Error|`Mae`||||
|
||||
|MAPD - Mean Absolute Percentage Deviation|`Mapd`||||
|
||||
|MAPE - Mean Absolute Percentage Error|`Mape`||||
|
||||
|MASE - Mean Absolute Scaled Error|`Mase`||||
|
||||
|MDA - Mean Directional Accuracy|||||
|
||||
|ME - Mean Error|||||
|
||||
|ME - Mean Error|`Me`||||
|
||||
|MEDIAN - Middle value|`Median`||||
|
||||
|MIN - Minimum with exponential decay|`Min`||||
|
||||
|MODE - Most Frequent Value|`Mode`||||
|
||||
|MPE - Pean Percentage Error|||||
|
||||
|MSE - Mean Squared Error|||||
|
||||
|MSLE - Mean Squared Logarithmic Error|||||
|
||||
|MPE - Pean Percentage Error|`Mpe`||||
|
||||
|MSE - Mean Squared Error|`Mse`||||
|
||||
|MSLE - Mean Squared Logarithmic Error|`Msle`||||
|
||||
|PERCENTILE - Rank Order|`Percentile`||||
|
||||
|RSQUARED - Coefficient of Determination R-Squared|||||
|
||||
|RAE - Relative Absolute Error|||||
|
||||
|RMSE - Root Mean Squared Error|||||
|
||||
|RSE - Relateive Squared Error|||||
|
||||
|RMSLE - Root Mean Squared Logarithmic Error|||||
|
||||
|RAE - Relative Absolute Error|`Rae`||||
|
||||
|RMSE - Root Mean Squared Error|`Rmse`||||
|
||||
|RSE - Relateive Squared Error|`Rse`||||
|
||||
|RMSLE - Root Mean Squared Logarithmic Error|`Rmsle`||||
|
||||
|SKEW - Skewness, asymmetry of distribution|`Skew`||||
|
||||
|SLOPE - Rate of Change, Linear Regression|`Slope`||||
|
||||
|SMAPE - Symmetric Mean Absolute Percentage Error|||||
|
||||
|STDDEV - Standard Deviation, Measure of Spread|||||
|
||||
|SMAPE - Symmetric Mean Absolute Percentage Error|`Smape`||||
|
||||
|STDDEV - Standard Deviation, Measure of Spread|`Stddev`||||
|
||||
|THEIL - Theil's U Statistics|||||
|
||||
|VARIANCE - Average of Squared Deviations|`Variance`||||
|
||||
|ZSCORE - Standardized Score|`Zscore`||||
|
||||
@@ -72,7 +72,7 @@
|
||||
|MGDI - McGinley Dynamic Indicator|`Mgdi`|`✔️`|||
|
||||
|MMA - Modified Moving Average|`Mma`||||
|
||||
|PPMA - Pivot Point Moving Average|||||
|
||||
|PWMA - Pascal's Weighted Moving Average|||||
|
||||
|PWMA - Pascal's Weighted Moving Average|`Pwma`||||
|
||||
|QEMA - Quad Exponential Moving Average|`Qema`||||
|
||||
|RMA - WildeR's Moving Average|`Rma`||||
|
||||
|SINEMA - Sine Weighted Moving Average|`Sinema`||||
|
||||
@@ -87,7 +87,7 @@
|
||||
|TSF - Time Series Forecast|||`✔️`|`✔️`|
|
||||
|VIDYA - Variable Index Dynamic Average|`Vidya`|||`✔️`|
|
||||
|VORTEX - Vortex Indicator||`✔️`|||
|
||||
|WMA - Weighted Moving Average|`Wma`|`✔️`|`✔️`|`✔️`|
|
||||
|WMA - Weighted Moving Average|`Wma`|`✔️`||`✔️`|
|
||||
|ZLEMA - Zero Lag EMA Average|`Zlema`|||`✔️`|
|
||||
|<br>||||
|
||||
|**VOLATILITY INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|
||||
@@ -14,18 +14,18 @@ public class Maaf : AbstractBase
|
||||
|
||||
private readonly int _period;
|
||||
|
||||
public Maaf(int Period = 39, double Threshold = 0.002)
|
||||
public Maaf(int period = 39, double threshold = 0.002)
|
||||
{
|
||||
_period = Period;
|
||||
_threshold = Threshold;
|
||||
_period = period;
|
||||
_threshold = threshold;
|
||||
_priceBuffer = new CircularBuffer(4);
|
||||
_smoothBuffer = new CircularBuffer(Period);
|
||||
_smoothBuffer = new CircularBuffer(period);
|
||||
Name = "MAAF";
|
||||
WarmupPeriod = Period;
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Maaf(object source, int Period = 39, double Threshold = 0.002) : this(Period, Threshold)
|
||||
public Maaf(object source, int period = 39, double threshold = 0.002) : this(period, threshold)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class Pwma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Convolution _convolution;
|
||||
|
||||
public Pwma(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 = "Pwma";
|
||||
WarmupPeriod = period;
|
||||
Init();
|
||||
}
|
||||
|
||||
public Pwma(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];
|
||||
kernel[0] = 1;
|
||||
|
||||
for (int i = 1; i < period; i++)
|
||||
{
|
||||
for (int j = i; j > 0; j--)
|
||||
{
|
||||
kernel[j] += kernel[j - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
double weightSum = kernel.Sum();
|
||||
for (int i = 0; i < period; i++)
|
||||
{
|
||||
kernel[i] /= weightSum;
|
||||
}
|
||||
|
||||
return kernel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Huber Loss calculator that combines the best properties of L2 squared loss for normal data
|
||||
/// and L1 absolute loss for outliers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Huberloss class calculates the Huber Loss using circular buffers
|
||||
/// to efficiently manage the actual and predicted data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Huberloss : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
private readonly double _delta;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Huberloss class with the specified period and delta.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Huber Loss.</param>
|
||||
/// <param name="delta">The threshold at which to switch from squared to linear loss.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1 or delta is less than or equal to 0.
|
||||
/// </exception>
|
||||
public Huberloss(int period, double delta = 1.0)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
if (delta <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(delta), "Delta must be greater than 0.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
_delta = delta;
|
||||
Name = $"Huberloss(period={period}, delta={delta})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Huberloss(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Huberloss instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Huberloss instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Huber Loss calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Huber Loss value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Huber Loss using the formula:
|
||||
/// L(a, p) = 0.5 * (a - p)^2 for |a - p| <= delta
|
||||
/// L(a, p) = delta * |a - p| - 0.5 * delta^2 for |a - p| > delta
|
||||
/// where a is the actual value, p is the predicted value, and delta is the threshold.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double huberLoss = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumLoss = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double error = Math.Abs(actualValues[i] - predictedValues[i]);
|
||||
if (error <= _delta)
|
||||
{
|
||||
sumLoss += 0.5 * error * error;
|
||||
}
|
||||
else
|
||||
{
|
||||
sumLoss += _delta * error - 0.5 * _delta * _delta;
|
||||
}
|
||||
}
|
||||
|
||||
huberLoss = sumLoss / _actualBuffer.Count;
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return huberLoss;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Huber Loss for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Huber Loss.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Absolute Error calculator that measures the average absolute difference
|
||||
/// between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mae class calculates the Mean Absolute Error using circular buffers
|
||||
/// to efficiently manage the actual and predicted data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Mae : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mae class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Mae(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Mae(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mae class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Error.</param>
|
||||
public Mae(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mae instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mae instance based on whether a new value is being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current input is a new value.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Absolute Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Absolute Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Absolute Error using the formula:
|
||||
/// MAE = sum(|actual - predicted|) / n
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// If Input2.Value is NaN, it uses the average of actual values as the predicted value.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double mae = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumOfAbsoluteDifferences = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
sumOfAbsoluteDifferences += Math.Abs(actualValues[i] - predictedValues[i]);
|
||||
}
|
||||
|
||||
mae = sumOfAbsoluteDifferences / _actualBuffer.Count;
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return mae;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Absolute Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Absolute Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Absolute Percentage Deviation calculator that measures the average absolute percentage difference
|
||||
/// between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mapd class calculates the Mean Absolute Percentage Deviation using circular buffers
|
||||
/// to efficiently manage the actual and predicted data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Mapd : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mapd class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Deviation.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Mapd(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Mapd(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mapd class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Deviation.</param>
|
||||
public Mapd(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mapd instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mapd instance based on whether a new value is being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current input is a new value.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Absolute Percentage Deviation calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Absolute Percentage Deviation value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Absolute Percentage Deviation using the formula:
|
||||
/// MAPD = (sum(|actual - predicted| / |actual|) / n) * 100
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// If there's only one value in the buffer or if any actual value is zero, those values are excluded from the calculation.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double mapd = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumOfAbsolutePercentageDeviations = 0;
|
||||
int validCount = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
if (actualValues[i] != 0)
|
||||
{
|
||||
sumOfAbsolutePercentageDeviations += Math.Abs((actualValues[i] - predictedValues[i]) / actualValues[i]);
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validCount > 0)
|
||||
{
|
||||
mapd = (sumOfAbsolutePercentageDeviations / validCount) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return mapd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Absolute Percentage Deviation for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Absolute Percentage Deviation.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Absolute Percentage Error calculator that measures the average absolute percentage difference
|
||||
/// between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mape class calculates the Mean Absolute Percentage Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Mape : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Mape(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Mape(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Mape(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mape instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mape instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Absolute Percentage Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Absolute Percentage Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Absolute Percentage Error using the formula:
|
||||
/// MAPE = (sum(|actual - predicted| / |actual|) / n) * 100
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// If any actual value is zero, it is excluded from the calculation to avoid division by zero.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double mape = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumAbsolutePercentageError = 0;
|
||||
int validCount = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
if (actualValues[i] != 0)
|
||||
{
|
||||
sumAbsolutePercentageError += Math.Abs((actualValues[i] - predictedValues[i]) / actualValues[i]);
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validCount > 0)
|
||||
{
|
||||
mape = (sumAbsolutePercentageError / validCount) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return mape;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Absolute Percentage Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Absolute Percentage Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Absolute Scaled Error calculator that measures the ratio of the mean absolute error
|
||||
/// of the forecast values to the mean absolute error of the naive forecast.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mase class calculates the Mean Absolute Scaled Error using circular buffers
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Mase : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _forecastBuffer;
|
||||
private readonly int _period;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mase class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Scaled Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 3.
|
||||
/// </exception>
|
||||
public Mase(int period)
|
||||
{
|
||||
if (period < 3)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 3.");
|
||||
}
|
||||
_period = period;
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_forecastBuffer = new CircularBuffer(period);
|
||||
Name = $"Mase(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mase class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Scaled Error.</param>
|
||||
public Mase(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mase instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_forecastBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mase instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Absolute Scaled Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Absolute Scaled Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Absolute Scaled Error using the formula:
|
||||
/// MASE = mean(|actual - forecast|) / mean(|actual[t] - actual[t-1]|)
|
||||
/// where actual is each actual value and forecast is each forecast value.
|
||||
/// If there are fewer than 3 values in the buffers, the method returns 0.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double forecast = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_forecastBuffer.Add(forecast, Input.IsNew);
|
||||
|
||||
double mase = 0;
|
||||
if (_actualBuffer.Count >= 3)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var forecastValues = _forecastBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumAbsoluteError = 0;
|
||||
double sumAbsoluteNaiveError = 0;
|
||||
|
||||
int count = Math.Min(_actualBuffer.Count, _period);
|
||||
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
sumAbsoluteError += Math.Abs(actualValues[i] - forecastValues[i]);
|
||||
sumAbsoluteNaiveError += Math.Abs(actualValues[i] - actualValues[i - 1]);
|
||||
}
|
||||
|
||||
double meanAbsoluteError = sumAbsoluteError / (count - 1);
|
||||
double meanAbsoluteNaiveError = sumAbsoluteNaiveError / (count - 1);
|
||||
|
||||
if (meanAbsoluteNaiveError != 0)
|
||||
{
|
||||
mase = meanAbsoluteError / meanAbsoluteNaiveError;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return mase;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Absolute Scaled Error for the given actual and forecast values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="forecast">The forecast value.</param>
|
||||
/// <returns>The calculated Mean Absolute Scaled Error.</returns>
|
||||
public double Calc(double actual, double forecast)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, forecast);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Directional Accuracy calculator that measures the average accuracy
|
||||
/// of predicted directional changes compared to actual directional changes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mda class calculates the Mean Directional Accuracy using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// Mean Directional Accuracy is useful in financial analysis for evaluating the performance
|
||||
/// of forecasting models in predicting the direction of price movements.
|
||||
/// </remarks>
|
||||
public class Mda : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _forecastBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mda class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Directional Accuracy.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 2.
|
||||
/// </exception>
|
||||
public Mda(int period)
|
||||
{
|
||||
if (period < 2)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
|
||||
}
|
||||
WarmupPeriod = 1;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_forecastBuffer = new CircularBuffer(period);
|
||||
Name = $"Mda(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mda class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Directional Accuracy.</param>
|
||||
public Mda(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mda instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_forecastBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mda instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Directional Accuracy calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Directional Accuracy value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Directional Accuracy using the formula:
|
||||
/// MDA = (number of correct directional predictions / total number of predictions) * 100
|
||||
/// A correct directional prediction is when the sign of the actual change matches
|
||||
/// the sign of the predicted change.
|
||||
/// The result is expressed as a percentage, where 100% indicates perfect directional accuracy
|
||||
/// and 50% indicates performance no better than random guessing.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double forecast = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_forecastBuffer.Add(forecast, Input.IsNew);
|
||||
|
||||
double mda = 0;
|
||||
if (_actualBuffer.Count > 1)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var forecastValues = _forecastBuffer.GetSpan().ToArray();
|
||||
|
||||
int correctPredictions = 0;
|
||||
int totalPredictions = actualValues.Length - 1;
|
||||
|
||||
for (int i = 1; i < actualValues.Length; i++)
|
||||
{
|
||||
double actualChange = actualValues[i] - actualValues[i - 1];
|
||||
double forecastChange = forecastValues[i] - actualValues[i - 1];
|
||||
|
||||
if ((actualChange >= 0 && forecastChange >= 0) || (actualChange < 0 && forecastChange < 0))
|
||||
{
|
||||
correctPredictions++;
|
||||
}
|
||||
}
|
||||
|
||||
mda = (double)correctPredictions / totalPredictions * 100;
|
||||
}
|
||||
|
||||
IsHot = _actualBuffer.Count > 1; // MDA calc is valid from bar 2
|
||||
return mda;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Directional Accuracy for the given actual and forecast values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="forecast">The forecast value.</param>
|
||||
/// <returns>The calculated Mean Directional Accuracy.</returns>
|
||||
public double Calc(double actual, double forecast)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, forecast);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Error calculator that measures the average difference
|
||||
/// between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Me class calculates the Mean Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Me : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Me class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Me(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Me(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Me(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Me instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Me instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Error using the formula:
|
||||
/// ME = sum(actual - predicted) / n
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double me = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumError = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
sumError += actualValues[i] - predictedValues[i];
|
||||
}
|
||||
|
||||
me = sumError / _actualBuffer.Count;
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return me;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Percentage Error calculator that measures the average percentage difference
|
||||
/// between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mpe class calculates the Mean Percentage Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Mpe : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mpe class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Percentage Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Mpe(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Mpe(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Mpe(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mpe instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mpe instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Percentage Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Percentage Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Percentage Error using the formula:
|
||||
/// MPE = (sum((actual - predicted) / actual) / n) * 100
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// If any actual value is zero, it is excluded from the calculation to avoid division by zero.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double mpe = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumPercentageError = 0;
|
||||
int validCount = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
if (actualValues[i] != 0)
|
||||
{
|
||||
sumPercentageError += (actualValues[i] - predictedValues[i]) / actualValues[i];
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validCount > 0)
|
||||
{
|
||||
mpe = (sumPercentageError / validCount) * 100;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return mpe;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Percentage Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Percentage Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Squared Error calculator that measures the average of the squares
|
||||
/// of the differences between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Mse class calculates the Mean Squared Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Mse : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mse class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Squared Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Mse(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Mse(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Mse(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Mse instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mse instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Squared Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Squared Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Squared Error using the formula:
|
||||
/// MSE = sum((actual - predicted)^2) / n
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double mse = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumSquaredError = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double error = actualValues[i] - predictedValues[i];
|
||||
sumSquaredError += error * error;
|
||||
}
|
||||
|
||||
mse = sumSquaredError / _actualBuffer.Count;
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return mse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Squared Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Squared Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
_lastValidValue = predicted;
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Mean Squared Logarithmic Error calculator that measures the average of the squares
|
||||
/// of the differences between the logarithms of actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Msle class calculates the Mean Squared Logarithmic Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Msle : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Msle class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Mean Squared Logarithmic Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Msle(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Msle(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Msle(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Msle instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Msle instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Mean Squared Logarithmic Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Mean Squared Logarithmic Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Mean Squared Logarithmic Error using the formula:
|
||||
/// MSLE = sum((log(actual + 1) - log(predicted + 1))^2) / n
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// We add 1 to both actual and predicted values to avoid taking the log of zero.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double msle = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumSquaredLogError = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double logActual = Math.Log(actualValues[i] + 1);
|
||||
double logPredicted = Math.Log(predictedValues[i] + 1);
|
||||
double logError = logActual - logPredicted;
|
||||
sumSquaredLogError += logError * logError;
|
||||
}
|
||||
|
||||
msle = sumSquaredLogError / _actualBuffer.Count;
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return msle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Mean Squared Logarithmic Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Mean Squared Logarithmic Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Relative Absolute Error calculator that measures the ratio of the sum of absolute errors
|
||||
/// to the sum of absolute differences between actual values and the mean of actual values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Rae class calculates the Relative Absolute Error using circular buffers
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Rae : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rae class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Relative Absolute Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 2.
|
||||
/// </exception>
|
||||
public Rae(int period)
|
||||
{
|
||||
if (period < 2)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Rae(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Rae(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Rae instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Rae instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Relative Absolute Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Relative Absolute Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Relative Absolute Error using the formula:
|
||||
/// RAE = sum(|actual - predicted|) / sum(|actual - mean(actual)|)
|
||||
/// where actual is each actual value, predicted is each predicted value, and mean(actual) is the average of actual values.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double rae = 0;
|
||||
if (_actualBuffer.Count >= 2)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double actualMean = actualValues.Average();
|
||||
double sumAbsoluteError = 0;
|
||||
double sumAbsoluteDifferenceFromMean = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
sumAbsoluteError += Math.Abs(actualValues[i] - predictedValues[i]);
|
||||
sumAbsoluteDifferenceFromMean += Math.Abs(actualValues[i] - actualMean);
|
||||
}
|
||||
|
||||
if (sumAbsoluteDifferenceFromMean != 0)
|
||||
{
|
||||
rae = sumAbsoluteError / sumAbsoluteDifferenceFromMean;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return rae;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Relative Absolute Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Relative Absolute Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Root Mean Squared Error calculator that measures the square root of the average
|
||||
/// of the squares of the differences between actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Rmse class calculates the Root Mean Squared Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Rmse : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rmse class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Root Mean Squared Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Rmse(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Rmse(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Rmse(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes the Rmse instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Rmse instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Root Mean Squared Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Root Mean Squared Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Root Mean Squared Error using the formula:
|
||||
/// RMSE = sqrt(sum((actual - predicted)^2) / n)
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double rmse = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumSquaredError = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double error = actualValues[i] - predictedValues[i];
|
||||
sumSquaredError += error * error;
|
||||
}
|
||||
|
||||
rmse = Math.Sqrt(sumSquaredError / _actualBuffer.Count);
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return rmse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Root Mean Squared Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Root Mean Squared Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Root Mean Squared Logarithmic Error calculator that measures the square root of the average
|
||||
/// of the squares of the differences between the logarithms of actual values and predicted values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Rmsle class calculates the Root Mean Squared Logarithmic Error using a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Rmsle : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rmsle class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Root Mean Squared Logarithmic Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Rmsle(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Rmsle(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Rmsle(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Rmsle instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Rmsle instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Root Mean Squared Logarithmic Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Root Mean Squared Logarithmic Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Root Mean Squared Logarithmic Error using the formula:
|
||||
/// RMSLE = sqrt(sum((log(actual + 1) - log(predicted + 1))^2) / n)
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// We add 1 to both actual and predicted values to avoid taking the log of zero.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double rmsle = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumSquaredLogError = 0;
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double logActual = Math.Log(actualValues[i] + 1);
|
||||
double logPredicted = Math.Log(predictedValues[i] + 1);
|
||||
double logError = logActual - logPredicted;
|
||||
sumSquaredLogError += logError * logError;
|
||||
}
|
||||
|
||||
rmsle = Math.Sqrt(sumSquaredLogError / _actualBuffer.Count);
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return rmsle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Root Mean Squared Logarithmic Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Root Mean Squared Logarithmic Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Relative Squared Error calculator that measures the ratio of the sum of squared errors
|
||||
/// to the sum of squared differences between actual values and the mean of actual values.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Rse class calculates the Relative Squared Error using circular buffers
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Rse : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rse class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Relative Squared Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 2.
|
||||
/// </exception>
|
||||
public Rse(int period)
|
||||
{
|
||||
if (period < 2)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Rse(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Rse(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Rse instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Rse instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Relative Squared Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Relative Squared Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Relative Squared Error using the formula:
|
||||
/// RSE = sum((actual - predicted)^2) / sum((actual - mean(actual))^2)
|
||||
/// where actual is each actual value, predicted is each predicted value, and mean(actual) is the average of actual values.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double rse = 0;
|
||||
if (_actualBuffer.Count >= 2)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double actualMean = actualValues.Average();
|
||||
double sumSquaredError = 0;
|
||||
double sumSquaredDifferenceFromMean = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double error = actualValues[i] - predictedValues[i];
|
||||
sumSquaredError += error * error;
|
||||
|
||||
double differenceFromMean = actualValues[i] - actualMean;
|
||||
sumSquaredDifferenceFromMean += differenceFromMean * differenceFromMean;
|
||||
}
|
||||
|
||||
if (sumSquaredDifferenceFromMean != 0)
|
||||
{
|
||||
rse = sumSquaredError / sumSquaredDifferenceFromMean;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return rse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Relative Squared Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Relative Squared Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Coefficient of Determination (R-squared) calculator that measures the proportion of
|
||||
/// the variance in the dependent variable that is predictable from the independent variable(s).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Rsquared class calculates the Coefficient of Determination using circular buffers
|
||||
/// to efficiently manage the actual and predicted data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Rsquared : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rsquared class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Coefficient of Determination.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 2.
|
||||
/// </exception>
|
||||
public Rsquared(int period)
|
||||
{
|
||||
if (period < 2)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Rsquared(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Rsquared(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Rsquared instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Rsquared instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Coefficient of Determination calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Coefficient of Determination value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Coefficient of Determination using the formula:
|
||||
/// R^2 = 1 - (SSres / SStot)
|
||||
/// where SSres is the sum of squared residuals and SStot is the total sum of squares.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double rsquared = 0;
|
||||
if (_actualBuffer.Count >= 2)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double actualMean = actualValues.Average();
|
||||
double ssRes = 0;
|
||||
double ssTot = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double residual = actualValues[i] - predictedValues[i];
|
||||
ssRes += residual * residual;
|
||||
|
||||
double deviation = actualValues[i] - actualMean;
|
||||
ssTot += deviation * deviation;
|
||||
}
|
||||
|
||||
if (ssTot != 0)
|
||||
{
|
||||
rsquared = 1 - (ssRes / ssTot);
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return rsquared;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Coefficient of Determination for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Coefficient of Determination.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Symmetric Mean Absolute Percentage Error calculator that measures the percentage difference
|
||||
/// between actual and predicted values, using a symmetric formula to handle both positive and negative errors equally.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Smape class calculates the Symmetric Mean Absolute Percentage Error using circular buffers
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
/// </remarks>
|
||||
public class Smape : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _actualBuffer;
|
||||
private readonly CircularBuffer _predictedBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Smape class with the specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Symmetric Mean Absolute Percentage Error.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Smape(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
WarmupPeriod = period;
|
||||
_actualBuffer = new CircularBuffer(period);
|
||||
_predictedBuffer = new CircularBuffer(period);
|
||||
Name = $"Smape(period={period})";
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Mape class with the specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Mean Absolute Percentage Error.</param>
|
||||
public Smape(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Smape instance by clearing the buffers.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_actualBuffer.Clear();
|
||||
_predictedBuffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Smape instance based on whether new values are being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current inputs are new values.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Symmetric Mean Absolute Percentage Error calculation for the current period.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Symmetric Mean Absolute Percentage Error value for the current period.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the Symmetric Mean Absolute Percentage Error using the formula:
|
||||
/// SMAPE = (100% / n) * sum(2 * |actual - predicted| / (|actual| + |predicted|))
|
||||
/// where actual is each actual value, predicted is each predicted value, and n is the number of values.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double actual = Input.Value;
|
||||
_actualBuffer.Add(actual, Input.IsNew);
|
||||
|
||||
double predicted = double.IsNaN(Input2.Value) ? _actualBuffer.Average() : Input2.Value;
|
||||
_predictedBuffer.Add(predicted, Input.IsNew);
|
||||
|
||||
double smape = 0;
|
||||
if (_actualBuffer.Count > 0)
|
||||
{
|
||||
var actualValues = _actualBuffer.GetSpan().ToArray();
|
||||
var predictedValues = _predictedBuffer.GetSpan().ToArray();
|
||||
|
||||
double sumSymmetricPercentageError = 0;
|
||||
int validCount = 0;
|
||||
|
||||
for (int i = 0; i < _actualBuffer.Count; i++)
|
||||
{
|
||||
double denominator = Math.Abs(actualValues[i]) + Math.Abs(predictedValues[i]);
|
||||
if (denominator != 0)
|
||||
{
|
||||
sumSymmetricPercentageError += 2 * Math.Abs(actualValues[i] - predictedValues[i]) / denominator;
|
||||
validCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validCount > 0)
|
||||
{
|
||||
smape = (100.0 / validCount) * sumSymmetricPercentageError;
|
||||
}
|
||||
}
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return smape;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the Symmetric Mean Absolute Percentage Error for the given actual and predicted values.
|
||||
/// </summary>
|
||||
/// <param name="actual">The actual value.</param>
|
||||
/// <param name="predicted">The predicted value.</param>
|
||||
/// <returns>The calculated Symmetric Mean Absolute Percentage Error.</returns>
|
||||
public double Calc(double actual, double predicted)
|
||||
{
|
||||
Input = new TValue(DateTime.Now, actual);
|
||||
Input2 = new TValue(DateTime.Now, predicted);
|
||||
return Calculation();
|
||||
}
|
||||
}
|
||||
+13
-8
@@ -1,9 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Title>QuanTAlib</Title>
|
||||
<Product>Library of TA Calculations, Charts and Strategies for Quantower</Product>
|
||||
<Description>Quantitative Technical Analysis Library in C# for Quantower</Description>
|
||||
<Title>QuanTAlib</Title>
|
||||
<Product>Library of TA Calculations, Charts and Strategies for Quantower</Product>
|
||||
<Description>Quantitative Technical Analysis Library in C# for Quantower</Description>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/mihakralj/QuanTAlib</RepositoryUrl>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
@@ -14,7 +14,7 @@
|
||||
<AssemblyName>QuanTAlib</AssemblyName>
|
||||
<IsPublishable>True</IsPublishable>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
|
||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
@@ -27,10 +27,15 @@
|
||||
Quantitative;Historical;Quotes;
|
||||
</PackageTags>
|
||||
<PackageIcon>QuanTAlib2.png</PackageIcon>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="**\*.cs" Exclude="obj\**\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\docs\readme.md" Pack="true" PackagePath=""/>
|
||||
<None Include="..\.github\QuanTAlib2.png" Pack="true" Visible="false" PackagePath=""/>
|
||||
@@ -38,11 +43,11 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="TradingPlatform.BusinessLayer">
|
||||
<HintPath>..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
<HintPath>..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
</Reference>
|
||||
<None Include="..\.github\TradingPlatform.BusinessLayer.xml">
|
||||
<Link>TradingPlatform.BusinessLayer.xml</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -4,15 +4,36 @@ namespace QuanTAlib;
|
||||
/// Calculates the rate of change of the slope over a specified period.
|
||||
/// Provides insights into trend acceleration or deceleration.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Curvature is a second-order derivative that measures how quickly the slope (first-order derivative) is changing.
|
||||
/// Positive curvature indicates accelerating uptrends or decelerating downtrends.
|
||||
/// Negative curvature indicates decelerating uptrends or accelerating downtrends.
|
||||
/// This indicator can be useful for identifying potential trend reversals or confirming trend strength.
|
||||
/// </remarks>
|
||||
public class Curvature : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly Slope _slopeCalculator;
|
||||
private readonly CircularBuffer _slopeBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y-intercept of the curvature line.
|
||||
/// </summary>
|
||||
public double? Intercept { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the standard deviation of the slope values used in the curvature calculation.
|
||||
/// </summary>
|
||||
public double? StdDev { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the R-squared value, indicating the goodness of fit of the curvature line.
|
||||
/// </summary>
|
||||
public double? RSquared { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last calculated point on the curvature line.
|
||||
/// </summary>
|
||||
public double? Line { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -153,4 +174,4 @@ public class Curvature : AbstractBase
|
||||
IsHot = _slopeBuffer.Count == _period;
|
||||
return curvature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,20 @@ namespace QuanTAlib;
|
||||
/// Measures the unpredictability of data using Shannon's Entropy.
|
||||
/// Provides insights into the randomness or information content of the time series.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Shannon's Entropy quantifies the average amount of information contained in a message.
|
||||
/// In the context of time series analysis, it can be used to:
|
||||
/// - Detect regime changes or structural breaks in the data.
|
||||
/// - Assess the complexity or predictability of price movements.
|
||||
/// - Identify periods of high uncertainty or information flow in the market.
|
||||
/// The entropy value is normalized between 0 and 1, where 1 indicates maximum randomness
|
||||
/// and 0 indicates perfect predictability.
|
||||
/// </remarks>
|
||||
public class Entropy : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the entropy calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
@@ -24,7 +36,7 @@ public class Entropy : AbstractBase
|
||||
"Period must be greater than or equal to 2 for entropy calculation.");
|
||||
}
|
||||
Period = period;
|
||||
WarmupPeriod = 2;
|
||||
WarmupPeriod = 2; // Minimum number of points needed for entropy calculation
|
||||
_buffer = new CircularBuffer(period);
|
||||
Name = $"Entropy(period={period})";
|
||||
Init();
|
||||
@@ -110,4 +122,4 @@ public class Entropy : AbstractBase
|
||||
IsHot = _buffer.Count >= Period;
|
||||
return entropy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,25 @@ namespace QuanTAlib;
|
||||
/// Calculates excess kurtosis using the Sheskin Algorithm.
|
||||
/// Measures the "tailedness" of the probability distribution of a real-valued random variable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Kurtosis is a measure of the combined weight of a distribution's tails relative to the center of the distribution.
|
||||
/// In financial time series analysis, kurtosis can provide insights into:
|
||||
/// - The frequency and magnitude of extreme returns.
|
||||
/// - The potential for outliers or "black swan" events.
|
||||
/// - The shape of the return distribution compared to a normal distribution.
|
||||
///
|
||||
/// Interpretation:
|
||||
/// - Excess kurtosis > 0: Heavy-tailed distribution (more extreme values than a normal distribution)
|
||||
/// - Excess kurtosis = 0: Normal distribution
|
||||
/// - Excess kurtosis < 0: Light-tailed distribution (fewer extreme values than a normal distribution)
|
||||
///
|
||||
/// High kurtosis in financial returns may indicate a higher risk of extreme events.
|
||||
/// </remarks>
|
||||
public class Kurtosis : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the kurtosis calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
@@ -73,6 +90,11 @@ public class Kurtosis : AbstractBase
|
||||
/// <remarks>
|
||||
/// Uses the Sheskin Algorithm for kurtosis calculation.
|
||||
/// Requires at least 4 data points for a valid calculation.
|
||||
///
|
||||
/// Interpretation of results:
|
||||
/// - Positive values indicate a distribution with heavier tails and a higher peak compared to a normal distribution.
|
||||
/// - Negative values indicate a distribution with lighter tails and a lower peak compared to a normal distribution.
|
||||
/// - A value close to 0 suggests a distribution similar to a normal distribution in terms of tailedness.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
|
||||
+41
-3
@@ -4,19 +4,57 @@ namespace QuanTAlib;
|
||||
/// Calculates the maximum value over a specified period, with an optional decay factor.
|
||||
/// Useful for tracking the highest point in a time series with the ability to gradually forget old peaks.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Max indicator is particularly useful in financial analysis for:
|
||||
/// - Identifying resistance levels in price charts.
|
||||
/// - Tracking the highest price over a given period.
|
||||
/// - Implementing trailing stop-loss strategies.
|
||||
///
|
||||
/// The decay factor allows the indicator to adapt to changing market conditions by
|
||||
/// gradually reducing the influence of older maximum values.
|
||||
/// </remarks>
|
||||
public class Max : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the maximum calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer to store the most recent data points.
|
||||
/// </summary>
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The half-life decay factor used to gradually forget old peaks.
|
||||
/// </summary>
|
||||
private readonly double _halfLife;
|
||||
private double _currentMax, _p_currentMax;
|
||||
private int _timeSinceNewMax, _p_timeSinceNewMax;
|
||||
|
||||
/// <summary>
|
||||
/// The current maximum value.
|
||||
/// </summary>
|
||||
private double _currentMax;
|
||||
|
||||
/// <summary>
|
||||
/// The previous maximum value.
|
||||
/// </summary>
|
||||
private double _p_currentMax;
|
||||
|
||||
/// <summary>
|
||||
/// The number of periods since a new maximum was set.
|
||||
/// </summary>
|
||||
private int _timeSinceNewMax;
|
||||
|
||||
/// <summary>
|
||||
/// The previous value of _timeSinceNewMax.
|
||||
/// </summary>
|
||||
private int _p_timeSinceNewMax;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Max class.
|
||||
/// </summary>
|
||||
/// <param name="period">The number of data points to consider. Must be at least 1.</param>
|
||||
/// <param name="decay">Half-life decay factor. Set to 0 for no decay, higher for faster forgetting. Default is 0.</param>
|
||||
/// <param name="decay">Half-life decay factor. Set to 0 for no decay, higher for faster forgetting of old peaks. Default is 0.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when the period is less than 1 or decay is negative.
|
||||
/// </exception>
|
||||
|
||||
@@ -4,8 +4,20 @@ namespace QuanTAlib;
|
||||
/// Calculates the median value over a specified period.
|
||||
/// Provides a measure of central tendency that is robust to outliers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Median indicator is particularly useful in financial analysis for:
|
||||
/// - Providing a robust measure of central tendency that is less affected by extreme values than the mean.
|
||||
/// - Identifying the middle value in a dataset, which can be helpful in understanding price distributions.
|
||||
/// - Serving as a basis for other indicators or trading strategies that require a stable reference point.
|
||||
///
|
||||
/// Unlike the mean, the median is not influenced by extreme outliers, making it valuable
|
||||
/// in markets with occasional large price swings or in the presence of data anomalies.
|
||||
/// </remarks>
|
||||
public class Median : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the median calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
@@ -41,6 +53,15 @@ public class Median : AbstractBase
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the Median indicator to its initial state.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_buffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the indicator.
|
||||
/// </summary>
|
||||
|
||||
+36
-4
@@ -9,20 +9,52 @@ namespace QuanTAlib;
|
||||
/// The Min class uses a circular buffer to store values and calculates the minimum
|
||||
/// efficiently. It also implements a decay mechanism to adjust the minimum value over
|
||||
/// time, allowing for a more responsive indicator in changing market conditions.
|
||||
///
|
||||
/// The decay factor allows the indicator to "forget" old minimum values gradually,
|
||||
/// which can be useful in adapting to new price trends or market regimes.
|
||||
/// </remarks>
|
||||
public class Min : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the minimum calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer to store the most recent data points.
|
||||
/// </summary>
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
/// <summary>
|
||||
/// The half-life decay factor used to gradually forget old minimums.
|
||||
/// </summary>
|
||||
private readonly double _halfLife;
|
||||
private double _currentMin, _p_currentMin;
|
||||
private int _timeSinceNewMin, _p_timeSinceNewMin;
|
||||
|
||||
/// <summary>
|
||||
/// The current minimum value.
|
||||
/// </summary>
|
||||
private double _currentMin;
|
||||
|
||||
/// <summary>
|
||||
/// The previous minimum value.
|
||||
/// </summary>
|
||||
private double _p_currentMin;
|
||||
|
||||
/// <summary>
|
||||
/// The number of periods since a new minimum was set.
|
||||
/// </summary>
|
||||
private int _timeSinceNewMin;
|
||||
|
||||
/// <summary>
|
||||
/// The previous value of _timeSinceNewMin.
|
||||
/// </summary>
|
||||
private int _p_timeSinceNewMin;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Min class with the specified period and decay.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the minimum value.</param>
|
||||
/// <param name="decay">The decay factor to apply to older values (default is 0).</param>
|
||||
/// <param name="decay">The decay factor to apply to older values. Higher values cause faster forgetting of old minimums. Default is 0 (no decay).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1 or decay is negative.
|
||||
/// </exception>
|
||||
@@ -49,7 +81,7 @@ public class Min : AbstractBase
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the minimum value.</param>
|
||||
/// <param name="decay">The decay factor to apply to older values (default is 0).</param>
|
||||
/// <param name="decay">The decay factor to apply to older values. Higher values cause faster forgetting of old minimums. Default is 0 (no decay).</param>
|
||||
public Min(object source, int period, double decay = 0) : this(period, decay)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
|
||||
@@ -8,9 +8,17 @@ namespace QuanTAlib;
|
||||
/// The Mode class uses a circular buffer to store values and calculates the mode
|
||||
/// efficiently. Before the specified period is reached, it returns the average of
|
||||
/// the available values as an approximation.
|
||||
///
|
||||
/// In financial analysis, the mode can be useful for:
|
||||
/// - Identifying the most common price levels, which could indicate support or resistance.
|
||||
/// - Analyzing the distribution of returns or other financial metrics.
|
||||
/// - Detecting patterns in trading volume or other discrete financial data.
|
||||
/// </remarks>
|
||||
public class Mode : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the mode calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
@@ -45,6 +53,15 @@ public class Mode : AbstractBase
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the Mode indicator to its initial state.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_buffer.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Mode instance based on whether a new value is being processed.
|
||||
/// </summary>
|
||||
|
||||
@@ -9,11 +9,25 @@ namespace QuanTAlib;
|
||||
/// percentile efficiently. It uses linear interpolation when the percentile falls
|
||||
/// between two data points. Before the specified period is reached, it returns the
|
||||
/// average of the available values as an approximation.
|
||||
///
|
||||
/// In financial analysis, percentiles are useful for:
|
||||
/// - Assessing the relative standing of a value within a distribution.
|
||||
/// - Identifying outliers or extreme values in financial data.
|
||||
/// - Creating risk measures, such as Value at Risk (VaR) calculations.
|
||||
/// - Analyzing the distribution of returns, trading volumes, or other financial metrics.
|
||||
/// </remarks>
|
||||
public class Percentile : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the percentile calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
|
||||
/// <summary>
|
||||
/// The percentile to calculate (between 0 and 100).
|
||||
/// </summary>
|
||||
private readonly double Percent;
|
||||
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
/// <summary>
|
||||
@@ -36,7 +50,7 @@ public class Percentile : AbstractBase
|
||||
}
|
||||
Period = period;
|
||||
Percent = percent;
|
||||
WarmupPeriod = 2;
|
||||
WarmupPeriod = 2; // Minimum number of points needed for percentile calculation
|
||||
_buffer = new CircularBuffer(period);
|
||||
Name = $"Percentile(period={period}, percent={percent})";
|
||||
Init();
|
||||
@@ -125,4 +139,4 @@ public class Percentile : AbstractBase
|
||||
IsHot = _buffer.Count >= Period;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-1
@@ -9,9 +9,21 @@ namespace QuanTAlib;
|
||||
/// efficiently. It uses the adjusted Fisher-Pearson standardized moment coefficient
|
||||
/// for sample skewness calculation. A minimum of 3 data points is required for the
|
||||
/// calculation.
|
||||
///
|
||||
/// In financial analysis, skewness is important for:
|
||||
/// - Assessing the asymmetry of returns distribution.
|
||||
/// - Evaluating the risk of extreme events in either direction.
|
||||
/// - Complementing other risk measures like standard deviation.
|
||||
/// - Informing investment decisions and risk management strategies.
|
||||
///
|
||||
/// Positive skewness indicates a longer tail on the right side of the distribution,
|
||||
/// while negative skewness indicates a longer tail on the left side.
|
||||
/// </remarks>
|
||||
public class Skew : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the skewness calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
@@ -79,6 +91,11 @@ public class Skew : AbstractBase
|
||||
/// to calculate the sample skewness. It requires at least 3 data points for the
|
||||
/// calculation. If there are fewer than 3 data points, or if the standard
|
||||
/// deviation is zero, the method returns 0.
|
||||
///
|
||||
/// Interpretation of results:
|
||||
/// - Positive values indicate right-skewed distribution (longer tail on the right side).
|
||||
/// - Negative values indicate left-skewed distribution (longer tail on the left side).
|
||||
/// - Values close to 0 suggest a relatively symmetric distribution.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
@@ -117,4 +134,4 @@ public class Skew : AbstractBase
|
||||
IsHot = _buffer.Count >= Period;
|
||||
return skew;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,15 +7,37 @@ namespace QuanTAlib;
|
||||
/// The Slope class calculates the slope of a linear regression line, along with other
|
||||
/// statistical measures such as intercept, standard deviation, R-squared, and the last
|
||||
/// point on the regression line. It uses the least squares method for calculation.
|
||||
///
|
||||
/// In financial analysis, slope is important for:
|
||||
/// - Identifying trends in price movements or other financial metrics.
|
||||
/// - Measuring the rate of change in a financial time series.
|
||||
/// - Assessing the strength and direction of relationships between variables.
|
||||
/// - Supporting technical analysis indicators and trading strategies.
|
||||
/// </remarks>
|
||||
public class Slope : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly CircularBuffer _buffer;
|
||||
private readonly CircularBuffer _timeBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y-intercept of the regression line.
|
||||
/// </summary>
|
||||
public double? Intercept { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the standard deviation of the y-values.
|
||||
/// </summary>
|
||||
public double? StdDev { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the R-squared value, indicating the goodness of fit of the regression line.
|
||||
/// </summary>
|
||||
public double? RSquared { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the y-value of the last point on the regression line.
|
||||
/// </summary>
|
||||
public double? Line { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -90,6 +112,13 @@ public class Slope : AbstractBase
|
||||
/// It also calculates and updates the Intercept, StdDev, RSquared, and Line properties.
|
||||
/// If there are fewer than 2 data points, or if the sum of squared x deviations is 0,
|
||||
/// the method returns 0 and sets the additional properties to null.
|
||||
///
|
||||
/// Interpretation of results:
|
||||
/// - Positive slope: Indicates an upward trend in the data.
|
||||
/// - Negative slope: Indicates a downward trend in the data.
|
||||
/// - Slope close to 0: Indicates a relatively flat or no clear trend in the data.
|
||||
/// The magnitude of the slope represents the rate of change in the dependent variable
|
||||
/// (y) for each unit change in the independent variable (x).
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
|
||||
@@ -8,10 +8,23 @@ namespace QuanTAlib;
|
||||
/// The Stddev class calculates either the population standard deviation or the sample
|
||||
/// standard deviation based on the isPopulation parameter. It uses a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
///
|
||||
/// In financial analysis, standard deviation is important for:
|
||||
/// - Measuring volatility of financial instruments or portfolios.
|
||||
/// - Assessing risk in investments.
|
||||
/// - Calculating Sharpe ratios and other risk-adjusted performance measures.
|
||||
/// - Identifying potential outliers or unusual market behavior.
|
||||
/// </remarks>
|
||||
public class Stddev : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether to calculate population (true) or sample (false) standard deviation.
|
||||
/// </summary>
|
||||
private readonly bool IsPopulation;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer to store the most recent data points.
|
||||
/// </summary>
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
/// <summary>
|
||||
@@ -87,6 +100,11 @@ public class Stddev : AbstractBase
|
||||
/// sqrt(sum((x - mean)^2) / (n - 1)) for sample,
|
||||
/// where x is each value, mean is the average of all values, and n is the number of values.
|
||||
/// If there's only one value in the buffer, the method returns 0.
|
||||
///
|
||||
/// Interpretation of results:
|
||||
/// - A low standard deviation indicates that the values tend to be close to the mean.
|
||||
/// - A high standard deviation indicates that the values are spread out over a wider range.
|
||||
/// - In financial contexts, higher standard deviation often implies higher volatility or risk.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
|
||||
@@ -8,10 +8,23 @@ namespace QuanTAlib;
|
||||
/// The Variance class calculates either the population variance or the sample
|
||||
/// variance based on the isPopulation parameter. It uses a circular buffer
|
||||
/// to efficiently manage the data points within the specified period.
|
||||
///
|
||||
/// In financial analysis, variance is important for:
|
||||
/// - Measuring the dispersion of returns around the mean.
|
||||
/// - Assessing risk and volatility in financial instruments or portfolios.
|
||||
/// - Serving as a basis for other risk measures like standard deviation and beta.
|
||||
/// - Contributing to portfolio optimization techniques, such as Modern Portfolio Theory.
|
||||
/// </remarks>
|
||||
public class Variance : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether to calculate population (true) or sample (false) variance.
|
||||
/// </summary>
|
||||
private readonly bool IsPopulation;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer to store the most recent data points.
|
||||
/// </summary>
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
/// <summary>
|
||||
@@ -87,6 +100,12 @@ public class Variance : AbstractBase
|
||||
/// sum((x - mean)^2) / (n - 1) for sample,
|
||||
/// where x is each value, mean is the average of all values, and n is the number of values.
|
||||
/// If there's only one value in the buffer, the method returns 0.
|
||||
///
|
||||
/// Interpretation of results:
|
||||
/// - A low variance indicates that the values tend to be close to the mean and to each other.
|
||||
/// - A high variance indicates that the values are spread out over a wider range.
|
||||
/// - In financial contexts, higher variance often implies higher volatility or risk.
|
||||
/// - Variance is always non-negative, and its units are squared units of the original data.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
|
||||
@@ -8,10 +8,23 @@ namespace QuanTAlib;
|
||||
/// The Zscore class calculates the Z-score (also known as standard score) for
|
||||
/// the most recent value in a given period. It uses a circular buffer to
|
||||
/// efficiently manage the data points within the specified period.
|
||||
///
|
||||
/// In financial analysis, Z-score is important for:
|
||||
/// - Identifying outliers or unusual price movements.
|
||||
/// - Normalizing data across different scales or time periods.
|
||||
/// - Assessing the relative position of a value within its historical distribution.
|
||||
/// - Supporting trading strategies based on mean reversion or momentum.
|
||||
/// </remarks>
|
||||
public class Zscore : AbstractBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The number of data points to consider for the Z-score calculation.
|
||||
/// </summary>
|
||||
private readonly int Period;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer to store the most recent data points.
|
||||
/// </summary>
|
||||
private readonly CircularBuffer _buffer;
|
||||
|
||||
/// <summary>
|
||||
@@ -78,6 +91,14 @@ public class Zscore : AbstractBase
|
||||
/// Z = (x - μ) / σ
|
||||
/// where x is the input value, μ is the mean of the period, and σ is the sample standard deviation.
|
||||
/// If there are fewer than 2 data points or if the standard deviation is 0, the method returns 0.
|
||||
///
|
||||
/// Interpretation of results:
|
||||
/// - A Z-score of 0 indicates that the data point is exactly on the mean.
|
||||
/// - A positive Z-score indicates the data point is above the mean.
|
||||
/// - A negative Z-score indicates the data point is below the mean.
|
||||
/// - The magnitude of the Z-score represents how many standard deviations away from the mean the data point is.
|
||||
/// - In a normal distribution, about 68% of the values have a Z-score between -1 and 1,
|
||||
/// 95% between -2 and 2, and 99.7% between -3 and 3.
|
||||
/// </remarks>
|
||||
protected override double Calculation()
|
||||
{
|
||||
@@ -104,4 +125,4 @@ public class Zscore : AbstractBase
|
||||
IsHot = _buffer.Count >= Period;
|
||||
return zScore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ QuanTAlib.Formatters.Initialize();
|
||||
#!csharp
|
||||
|
||||
TSeries input = new();
|
||||
Sma ma1 = new (6);
|
||||
Sma ma2 = new (input, 6);
|
||||
Beta ma1 = new (6);
|
||||
Beta ma2 = new (input, 6);
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ public class AfirmaIndicator : IndicatorBase
|
||||
[InputParameter("Periods for lowpass cutoff", sortIndex: 2, 1, 2000, 1, 0)]
|
||||
public int Periods { get; set; } = 6;
|
||||
|
||||
|
||||
|
||||
[InputParameter("Window Type", sortIndex: 3, variants: [
|
||||
"Rectangular", Afirma.WindowType.Rectangular,
|
||||
"Hanning", Afirma.WindowType.Hanning1,
|
||||
@@ -32,6 +30,8 @@ public class AfirmaIndicator : IndicatorBase
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Afirma(periods: Periods, taps: Taps, window: Window);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class AlmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -7,10 +7,10 @@ public class AlmaIndicator : IndicatorBase
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
[InputParameter("Offset", sortIndex: 5)]
|
||||
public double Offset = 0.85;
|
||||
public double Offset { get; set; } = 0.85;
|
||||
|
||||
[InputParameter("Sigma", sortIndex: 6)]
|
||||
public double Sigma = 6.0;
|
||||
public double Sigma { get; set; } = 6.0;
|
||||
private Alma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"ALMA {Period} : {Offset:F2} : {Sigma:F0} : {SourceName}";
|
||||
@@ -18,6 +18,8 @@ public class AlmaIndicator : IndicatorBase
|
||||
public AlmaIndicator() : base()
|
||||
{
|
||||
Name = "ALMA - Arnaud Legoux Moving Average";
|
||||
Description = "Arnaud Legoux Moving Average";
|
||||
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -5,28 +5,26 @@
|
||||
<IsLocalBuild Condition="'$(GITHUB_ACTIONS)' == ''">true</IsLocalBuild>
|
||||
<UpdateAssemblyInfo>true</UpdateAssemblyInfo>
|
||||
<GenerateGitVersionInformation>true</GenerateGitVersionInformation>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<Compile Include="..\..\lib\**\*.cs" Exclude="..\..\lib\obj\**">
|
||||
<Link>lib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild" Condition="'$(IsLocalBuild)' == 'true'">
|
||||
<Copy SourceFiles="$(OutputPath)\Averages.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Averages" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\*.cs">
|
||||
<Link>%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\*.cs" />
|
||||
<Compile Include="*.cs" />
|
||||
<ProjectReference Include="..\..\lib\quantalib.csproj" Private="true" IncludeAssets="all" />
|
||||
<Reference Include="TradingPlatform.BusinessLayer">
|
||||
<HintPath>..\..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
<HintPath>..\..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
</Reference>
|
||||
<None Include="..\..\.github\TradingPlatform.BusinessLayer.xml">
|
||||
<Link>TradingPlatform.BusinessLayer.xml</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild" Condition="'$(IsLocalBuild)' == 'true'">
|
||||
<Copy SourceFiles="$(OutputPath)\Averages.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Averages" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class DemaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -12,6 +12,7 @@ public class DemaIndicator : IndicatorBase
|
||||
public DemaIndicator() : base()
|
||||
{
|
||||
Name = "DEMA - Double Exponential Moving Average";
|
||||
Description = "A faster-responding moving average that reduces lag by applying the EMA twice.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class DsmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -15,6 +15,7 @@ public class DsmaIndicator : IndicatorBase
|
||||
public DsmaIndicator() : base()
|
||||
{
|
||||
Name = "DSMA - Deviation Scaled Moving Average";
|
||||
Description = "A moving average that adjusts its responsiveness based on price deviations from the mean.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class DwmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -10,10 +10,10 @@ public class DwmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"DWMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public DwmaIndicator() : base()
|
||||
{
|
||||
Name = "DWMA - Double Weighted Moving Average";
|
||||
Description = "A moving average that applies double weighting to recent prices for increased responsiveness.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class EmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -16,7 +16,7 @@ public class EmaIndicator : IndicatorBase
|
||||
public EmaIndicator() : base()
|
||||
{
|
||||
Name = "EMA - Exponential Moving Average";
|
||||
Description = "Exponential Moving Average";
|
||||
Description = "Moving average that gives more weight to recent prices, reducing lag in trend following.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class EpmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -13,6 +13,7 @@ public class EpmaIndicator : IndicatorBase
|
||||
public EpmaIndicator() : base()
|
||||
{
|
||||
Name = "EPMA - Endpoint Moving Average";
|
||||
Description = "Moving average that emphasizes the most recent data point, useful for identifying trend changes.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class FramaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -10,10 +10,10 @@ public class FramaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"FRAMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public FramaIndicator() : base()
|
||||
{
|
||||
Name = "FRAMA - Fractal Adaptive Moving Average";
|
||||
Description = "Adaptive moving average that adjusts its smoothing based on market fractal dimension.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class FwmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -10,10 +10,10 @@ public class FwmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"FWMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public FwmaIndicator() : base()
|
||||
{
|
||||
Name = "FWMA - Fibonacci-Weighted Moving Average";
|
||||
Description = "Moving average that uses Fibonacci sequence for weighting, emphasizing recent and key historical prices.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
using QuanTAlib;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class GmaIndicator : IndicatorBase
|
||||
{
|
||||
@@ -10,10 +10,10 @@ public class GmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"GMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public GmaIndicator() : base()
|
||||
{
|
||||
Name = "GMA - Gaussian-Weighted Moving Average";
|
||||
Description = "Moving average using Gaussian distribution for weighting, balancing recent and historical data.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class HmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"HMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public HmaIndicator() : base()
|
||||
{
|
||||
Name = "HMA - Hull Moving Average";
|
||||
Description = "Responsive moving average that reduces lag while maintaining smoothness in price action.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,6 +10,7 @@ public class HtitIndicator : IndicatorBase
|
||||
public HtitIndicator() : base()
|
||||
{
|
||||
Name = "HTIT - Hilbert Transform Instantaneous Trendline";
|
||||
Description = "Uses Hilbert Transform to identify the dominant cycle and generate a smooth, lag-free trendline.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -16,17 +16,14 @@ public class HwmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"HWMA {nA:F2} : {nB:F2} : {nC:F2} : {SourceName}";
|
||||
|
||||
|
||||
public HwmaIndicator() : base()
|
||||
{
|
||||
Name = "HWMA - Holt-Winter Moving Average";
|
||||
Description = "Triple exponential moving average that accounts for level, trend, and seasonal components.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
//nA = 2 / (1 + (double)Period);
|
||||
//nB = 1 / (double)Period;
|
||||
//nC = 1 / (double)Period;
|
||||
ma = new Hwma(nA: nA, nB: nB, nC: nC);
|
||||
base.InitIndicator();
|
||||
}
|
||||
|
||||
@@ -12,10 +12,10 @@ public class JmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"JMA {Period} : {Phase} : {SourceName}";
|
||||
|
||||
|
||||
public JmaIndicator() : base()
|
||||
{
|
||||
Name = "JMA - Jurik Moving Average";
|
||||
Description = "Adaptive moving average with reduced lag and noise, adjustable smoothness and phase shift.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -14,10 +14,10 @@ public class KamaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"KAMA {Period} : {Fast} : {Slow} : {SourceName}";
|
||||
|
||||
|
||||
public KamaIndicator() : base()
|
||||
{
|
||||
Name = "KAMA - Kaufman's Adaptive Moving Average";
|
||||
Description = "Adaptive moving average that adjusts to market volatility, reducing lag in trending markets.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -13,6 +13,7 @@ public class LtmaIndicator : IndicatorBase
|
||||
public LtmaIndicator() : base()
|
||||
{
|
||||
Name = "LTMA - Laguerre Transform Moving Average";
|
||||
Description = "Moving average using Laguerre polynomials, offering adjustable smoothing and lag reduction.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -7,7 +7,7 @@ public class MaafIndicator : IndicatorBase
|
||||
public int Period { get; set; } = 39;
|
||||
|
||||
[InputParameter("Threshold", sortIndex: 5, minimum: 0, maximum: 1, increment: 0.001, decimalPlaces: 3)]
|
||||
public double Threshold = 0.002;
|
||||
private double Threshold { get; set; } = 0.002;
|
||||
|
||||
private Maaf? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
@@ -16,11 +16,12 @@ public class MaafIndicator : IndicatorBase
|
||||
public MaafIndicator() : base()
|
||||
{
|
||||
Name = "MAAF - Median-Average Adaptive Filter";
|
||||
Description = "Adaptive filter combining median and average, reducing noise while preserving trend responsiveness.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Maaf(Period: Period, Threshold: Threshold);
|
||||
ma = new Maaf(period: Period, threshold: Threshold);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ public class MamaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MAMA : {Fast} : {Slow} : {SourceName}";
|
||||
|
||||
|
||||
public MamaIndicator() : base()
|
||||
{
|
||||
Name = "MAMA - MESA Adaptive Moving Average";
|
||||
Description = "Adaptive moving average using MESA algorithm to adjust to market cycles and reduce lag.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -9,15 +9,14 @@ public class MgdiIndicator : IndicatorBase
|
||||
[InputParameter("k Factor", sortIndex: 2, minimum: 0.0, maximum: 1.0, increment: 0.1, decimalPlaces: 2)]
|
||||
public double kfactor { get; set; } = 0.6;
|
||||
|
||||
|
||||
private Mgdi? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"MGDI {Period} : {kfactor:F2} : {SourceName}";
|
||||
|
||||
|
||||
public MgdiIndicator() : base()
|
||||
{
|
||||
Name = "MGDI - McGinley Dynamic Index";
|
||||
Description = "Adaptive moving average that adjusts to market speed, reducing whipsaws in trending markets.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -13,6 +13,7 @@ public class MmaIndicator : IndicatorBase
|
||||
public MmaIndicator() : base()
|
||||
{
|
||||
Name = "MMA - Modified Moving Average";
|
||||
Description = "Variation of EMA that reduces lag and smooths price action, balancing responsiveness and stability.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using TradingPlatform.BusinessLayer;
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class PwmaIndicator : IndicatorBase
|
||||
{
|
||||
[InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 10;
|
||||
|
||||
private Pwma? ma;
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"PWMA {Period} : {SourceName}";
|
||||
|
||||
public PwmaIndicator() : base()
|
||||
{
|
||||
Name = "PWMA - Pascal's Weighted Moving Average";
|
||||
Description = "Moving average using Pascal's triangle coefficients, emphasizing recent data with smooth transitions.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
base.InitIndicator();
|
||||
ma = new Pwma(period: Period);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class QemaIndicator : IndicatorBase
|
||||
public QemaIndicator() : base()
|
||||
{
|
||||
Name = "QEMA - Quad Exponential Moving Average";
|
||||
Description = "Quad Exponential Moving Average";
|
||||
Description = "Combines four EMAs with different smoothing factors to reduce lag and improve trend following.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -16,6 +16,7 @@ public class RemaIndicator : IndicatorBase
|
||||
public RemaIndicator() : base()
|
||||
{
|
||||
Name = "REMA - Regularized Exponential Moving Average";
|
||||
Description = "EMA variant with regularization to reduce noise and improve stability in volatile markets.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class RmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"RMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public RmaIndicator() : base()
|
||||
{
|
||||
Name = "RMA - wildeR Moving Average";
|
||||
Name = "RMA - Wilder's Moving Average";
|
||||
Description = "Smoothed moving average that reduces whipsaws, commonly used in RSI calculations.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -13,6 +13,7 @@ public class SinemaIndicator : IndicatorBase
|
||||
public SinemaIndicator() : base()
|
||||
{
|
||||
Name = "SINEMA - Sine-Weighted Moving Average";
|
||||
Description = "Moving average using sine function for weighting, balancing recent and historical price data.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class SmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"SMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public SmaIndicator() : base()
|
||||
{
|
||||
Name = "SMA - Simple Moving Average";
|
||||
Description = "Basic moving average that calculates the arithmetic mean of prices over a specified period.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class SmmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"SMMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public SmmaIndicator() : base()
|
||||
{
|
||||
Name = "SMMA - Smoothed Moving Average";
|
||||
Description = "Moving average that gives more weight to recent data while retaining all historical data.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -19,6 +19,7 @@ public class T3Indicator : IndicatorBase
|
||||
public T3Indicator() : base()
|
||||
{
|
||||
Name = "T3 - Tillson T3 Moving Average";
|
||||
Description = "Triple exponential moving average with reduced lag and smoothing, adjustable via volume factor.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -13,6 +13,7 @@ public class TemaIndicator : IndicatorBase
|
||||
public TemaIndicator() : base()
|
||||
{
|
||||
Name = "TEMA - Triple Exponential Moving Average";
|
||||
Description = "Moving average that applies EMA three times to reduce lag and improve responsiveness to trends.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class TrimaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"TRIMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public TrimaIndicator() : base()
|
||||
{
|
||||
Name = "TRIMA - Triangular Moving Average";
|
||||
Description = "Weighted moving average giving more importance to the middle of the period for smoother output.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -14,10 +14,10 @@ public class VidyaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"VIDYA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public VidyaIndicator() : base()
|
||||
{
|
||||
Name = "VIDYA - Variable Index Dynamic Average";
|
||||
Description = "Adaptive moving average that adjusts based on market volatility for improved trend following.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class WmaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"WMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public WmaIndicator() : base()
|
||||
{
|
||||
Name = "WMA - Weighted Moving Average";
|
||||
Description = "Moving average that assigns higher weights to recent data points for improved responsiveness.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -10,10 +10,10 @@ public class ZlemaIndicator : IndicatorBase
|
||||
protected override AbstractBase QuanTAlib => ma!;
|
||||
public override string ShortName => $"ZLEMA {Period} : {SourceName}";
|
||||
|
||||
|
||||
public ZlemaIndicator() : base()
|
||||
{
|
||||
Name = "ZLEMA - Weighted Moving Average";
|
||||
Name = "ZLEMA - Zero-Lag Exponential Moving Average";
|
||||
Description = "EMA variant that reduces lag by using linear extrapolation, providing faster response to price changes.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -13,6 +13,7 @@ public class CurvatureIndicator : IndicatorBase
|
||||
public CurvatureIndicator()
|
||||
{
|
||||
Name = "CURVATURE - Rate of Change of Slope";
|
||||
Description = "Measures the rate of change of the slope, indicating acceleration or deceleration in price movement.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -21,4 +22,4 @@ public class CurvatureIndicator : IndicatorBase
|
||||
curvature = new(Period);
|
||||
MinHistoryDepths = curvature.WarmupPeriod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public class EntropyIndicator : IndicatorBase
|
||||
public EntropyIndicator() : base()
|
||||
{
|
||||
Name = "ENTROPY - Entropy";
|
||||
Description = "Measures the randomness or uncertainty in price movements, useful for identifying market phases.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -22,4 +23,4 @@ public class EntropyIndicator : IndicatorBase
|
||||
MinHistoryDepths = entropy.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public class KurtosisIndicator : IndicatorBase
|
||||
public KurtosisIndicator() : base()
|
||||
{
|
||||
Name = "KURTOSIS - Relative Flatness";
|
||||
Description = "Measures the 'tailedness' of price distribution, indicating potential for extreme market movements.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -22,4 +23,4 @@ public class KurtosisIndicator : IndicatorBase
|
||||
MinHistoryDepths = kurtosis.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ public class MaxIndicator : IndicatorBase
|
||||
|
||||
public MaxIndicator() : base()
|
||||
{
|
||||
Name = "MAX - Maximum value (with decay) ";
|
||||
Name = "MAX - Maximum value (with decay)";
|
||||
Description = "Tracks the maximum value over a period, with a decay factor to gradually adjust to new highs.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
|
||||
@@ -12,6 +12,7 @@ public class MedianIndicator : IndicatorBase
|
||||
public MedianIndicator() : base()
|
||||
{
|
||||
Name = "MEDIAN - Median historical value";
|
||||
Description = "Calculates the middle value of price data over a specified period, less affected by outliers than mean.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
@@ -20,4 +21,4 @@ public class MedianIndicator : IndicatorBase
|
||||
MinHistoryDepths = med.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public class MinIndicator : IndicatorBase
|
||||
public MinIndicator() : base()
|
||||
{
|
||||
Name = "MIN - Minimum value (with decay)";
|
||||
Description = "Tracks the minimum value over a period, with a decay factor to gradually adjust to new lows.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
@@ -24,4 +25,4 @@ public class MinIndicator : IndicatorBase
|
||||
Source = 3;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public class ModeIndicator : IndicatorBase
|
||||
public ModeIndicator() : base()
|
||||
{
|
||||
Name = "MODE - Most frequent historical value";
|
||||
Description = "Identifies the most frequently occurring price value over a specified period, indicating price clusters.";
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
@@ -20,4 +21,4 @@ public class ModeIndicator : IndicatorBase
|
||||
MinHistoryDepths = mode.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ public class PercentileIndicator : IndicatorBase
|
||||
|
||||
public PercentileIndicator() : base()
|
||||
{
|
||||
Name = "PERCENTILE - n-th Percentile ";
|
||||
Name = "PERCENTILE - n-th Percentile";
|
||||
Description = "Calculates the value below which a given percentage of observations falls within a specified period.";
|
||||
SeparateWindow = false;
|
||||
}
|
||||
|
||||
@@ -24,5 +25,4 @@ public class PercentileIndicator : IndicatorBase
|
||||
MinHistoryDepths = percentile.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
using TradingPlatform.BusinessLayer;
|
||||
namespace QuanTAlib;
|
||||
|
||||
@@ -14,6 +13,7 @@ public class SkewIndicator : IndicatorBase
|
||||
public SkewIndicator() : base()
|
||||
{
|
||||
Name = "SKEW - Skewness";
|
||||
Description = "Measures the asymmetry of price distribution, indicating potential trend direction or reversal.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -23,4 +23,4 @@ public class SkewIndicator : IndicatorBase
|
||||
MinHistoryDepths = skew.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ public class SlopeIndicator : IndicatorBase
|
||||
public SlopeIndicator()
|
||||
{
|
||||
Name = "SLOPE - Trend Slope";
|
||||
Description = "Measures the rate of change in price over a specified period, indicating trend strength and direction.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -21,4 +22,4 @@ public class SlopeIndicator : IndicatorBase
|
||||
slope = new(Period);
|
||||
MinHistoryDepths = slope.WarmupPeriod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,28 +5,26 @@
|
||||
<IsLocalBuild Condition="'$(GITHUB_ACTIONS)' == ''">true</IsLocalBuild>
|
||||
<UpdateAssemblyInfo>true</UpdateAssemblyInfo>
|
||||
<GenerateGitVersionInformation>true</GenerateGitVersionInformation>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<Compile Include="..\..\lib\**\*.cs" Exclude="..\..\lib\obj\**">
|
||||
<Link>lib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild" Condition="'$(IsLocalBuild)' == 'true'">
|
||||
<Copy SourceFiles="$(OutputPath)\Statistics.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Statistics" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\*.cs">
|
||||
<Link>%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\*.cs" />
|
||||
<Compile Include="*.cs" />
|
||||
<ProjectReference Include="..\..\lib\quantalib.csproj" Private="true" IncludeAssets="all" />
|
||||
<Reference Include="TradingPlatform.BusinessLayer">
|
||||
<HintPath>..\..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
<HintPath>..\..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
</Reference>
|
||||
<None Include="..\..\.github\TradingPlatform.BusinessLayer.xml">
|
||||
<Link>TradingPlatform.BusinessLayer.xml</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild" Condition="'$(IsLocalBuild)' == 'true'">
|
||||
<Copy SourceFiles="$(OutputPath)\Statistics.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Statistics" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -15,6 +15,7 @@ public class StddevIndicator : IndicatorBase
|
||||
public StddevIndicator() : base()
|
||||
{
|
||||
Name = "STDDEV - Standard Deviation";
|
||||
Description = "Measures price volatility by calculating the dispersion of prices from their average over a period.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -24,4 +25,4 @@ public class StddevIndicator : IndicatorBase
|
||||
MinHistoryDepths = stddev.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ public class VarianceIndicator : IndicatorBase
|
||||
public VarianceIndicator() : base()
|
||||
{
|
||||
Name = "VAR - Variance";
|
||||
Description = "Measures the spread of price data around its mean, indicating volatility and potential trend changes.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -25,4 +26,4 @@ public class VarianceIndicator : IndicatorBase
|
||||
MinHistoryDepths = variance.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ public class ZScoreIndicator : IndicatorBase
|
||||
public ZScoreIndicator() : base()
|
||||
{
|
||||
Name = "ZSCORE - Standard Score";
|
||||
Description = "Measures how many standard deviations a price is from the mean, indicating overbought/oversold levels.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -22,5 +23,4 @@ public class ZScoreIndicator : IndicatorBase
|
||||
MinHistoryDepths = zScore.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public class AtrIndicator : IndicatorBarBase
|
||||
public AtrIndicator()
|
||||
{
|
||||
Name = "ATR - Average True Range";
|
||||
Description = "Measures market volatility by calculating the average range between high and low prices.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -20,4 +21,4 @@ public class AtrIndicator : IndicatorBarBase
|
||||
atr = new(Period);
|
||||
MinHistoryDepths = atr!.WarmupPeriod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public class HistoricalIndicator : IndicatorBase
|
||||
public HistoricalIndicator() : base()
|
||||
{
|
||||
Name = "HV - Historical Volatility";
|
||||
Description = "Measures price fluctuations over time, indicating market volatility based on past price movements.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -25,4 +26,4 @@ public class HistoricalIndicator : IndicatorBase
|
||||
MinHistoryDepths = historical.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ public class RealizedIndicator : IndicatorBase
|
||||
public RealizedIndicator() : base()
|
||||
{
|
||||
Name = "RV - Realized Volatility";
|
||||
Description = "Measures actual price volatility over a specific period, useful for risk assessment and forecasting.";
|
||||
SeparateWindow = true;
|
||||
}
|
||||
|
||||
@@ -25,4 +26,4 @@ public class RealizedIndicator : IndicatorBase
|
||||
MinHistoryDepths = realized.WarmupPeriod;
|
||||
base.InitIndicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,12 +13,9 @@ public class RviIndicator : IndicatorBase
|
||||
public RviIndicator() : base()
|
||||
{
|
||||
Name = "RVI - Relative Volatility Index";
|
||||
Description = "Measures the direction of volatility, helping to identify overbought or oversold conditions in price.";
|
||||
SeparateWindow = true;
|
||||
|
||||
// Adding upper and lower reference lines
|
||||
//AddLineSeries("UpperLevel", 80, System.Drawing.Color.Gray, 1, LineStyle.Dot);
|
||||
//AddLineSeries("LowerLevel", 20, System.Drawing.Color.Gray, 1, LineStyle.Dot);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InitIndicator()
|
||||
{
|
||||
|
||||
@@ -5,28 +5,26 @@
|
||||
<IsLocalBuild Condition="'$(GITHUB_ACTIONS)' == ''">true</IsLocalBuild>
|
||||
<UpdateAssemblyInfo>true</UpdateAssemblyInfo>
|
||||
<GenerateGitVersionInformation>true</GenerateGitVersionInformation>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Drawing.Common" Version="8.0.0" />
|
||||
<Compile Include="..\..\lib\**\*.cs" Exclude="..\..\lib\obj\**">
|
||||
<Link>lib\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild" Condition="'$(IsLocalBuild)' == 'true'">
|
||||
<Copy SourceFiles="$(OutputPath)\Volatility.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Volatility" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\*.cs">
|
||||
<Link>%(Filename)%(Extension)</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\*.cs" />
|
||||
<Compile Include="*.cs" />
|
||||
<ProjectReference Include="..\..\lib\quantalib.csproj" Private="true" IncludeAssets="all" />
|
||||
<Reference Include="TradingPlatform.BusinessLayer">
|
||||
<HintPath>..\..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
<HintPath>..\..\.github\TradingPlatform.BusinessLayer.dll</HintPath>
|
||||
</Reference>
|
||||
<None Include="..\..\.github\TradingPlatform.BusinessLayer.xml">
|
||||
<Link>TradingPlatform.BusinessLayer.xml</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Target Name="CopyCustomContent" AfterTargets="AfterBuild" Condition="'$(IsLocalBuild)' == 'true'">
|
||||
<Copy SourceFiles="$(OutputPath)\Volatility.dll" DestinationFolder="$(QuantowerRoot)\Settings\Scripts\Indicators\QuanTAlib\Volatility" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -3,10 +3,11 @@ using TradingPlatform.BusinessLayer;
|
||||
using TradingPlatform.BusinessLayer.Chart;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Drawing.Drawing2D;
|
||||
using QuanTAlib;
|
||||
using System.Collections;
|
||||
using TradingPlatform.BusinessLayer.TimeSync;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public abstract class IndicatorBase : Indicator, IWatchlistIndicator
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user