Files
QuanTAlib/lib/numerics/exptrans/tests/Exptrans.Validation.Tests.cs
Miha Kralj 060649192f docs: remove C# Implementation Considerations sections, clean up temp scripts, reorganize test files
- Remove 'C# Implementation Considerations' sections from 34 indicator .md files
- Delete 29 temp PowerShell scripts (_fix_mojibake.ps1, _hex_scan.ps1, etc.)
- Move test files into tests/ subdirectories for consistent project structure
- Add trader-focused bullet points to indicator documentation
2026-03-12 12:34:16 -07:00

174 lines
4.9 KiB
C#

using Xunit;
namespace QuanTAlib.Tests;
/// <summary>
/// EXPTRANS validation tests - validates against Math.Exp (standard library)
/// </summary>
public class ExptransValidationTests
{
private const double Tolerance = 1e-14;
[Fact]
public void Exptrans_Batch_MatchesMathExp()
{
int count = 100;
// Use log-transformed prices to keep exp in reasonable range
var gbm = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 50000);
var bars = gbm.Fetch(count, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
var logSource = Logtrans.Batch(bars.Close);
var result = Exptrans.Batch(logSource);
for (int i = 0; i < logSource.Count; i++)
{
double expected = Math.Exp(logSource[i].Value);
Assert.Equal(expected, result[i].Value, Tolerance);
}
}
[Fact]
public void Exptrans_Streaming_MatchesMathExp()
{
int count = 100;
var gbm = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 50001);
var bars = gbm.Fetch(count, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
var logSource = Logtrans.Batch(bars.Close);
var indicator = new Exptrans();
for (int i = 0; i < logSource.Count; i++)
{
indicator.Update(logSource[i]);
double expected = Math.Exp(logSource[i].Value);
Assert.Equal(expected, indicator.Last.Value, Tolerance);
}
}
[Fact]
public void Exptrans_Span_MatchesMathExp()
{
int count = 100;
var gbm = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 50002);
var bars = gbm.Fetch(count, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
var logSource = Logtrans.Batch(bars.Close);
var values = logSource.Values.ToArray();
var output = new double[count];
Exptrans.Batch(values, output);
for (int i = 0; i < count; i++)
{
double expected = Math.Exp(values[i]);
Assert.Equal(expected, output[i], Tolerance);
}
}
[Fact]
public void Exptrans_KnownIdentities()
{
var indicator = new Exptrans();
var time = DateTime.UtcNow;
// exp(0) = 1
indicator.Update(new TValue(time, 0.0));
Assert.Equal(1.0, indicator.Last.Value, Tolerance);
// exp(1) = e
indicator.Update(new TValue(time.AddMinutes(1), 1.0));
Assert.Equal(Math.E, indicator.Last.Value, Tolerance);
// exp(n) = e^n
for (int n = 2; n <= 5; n++)
{
indicator.Update(new TValue(time.AddMinutes(n), n));
Assert.Equal(Math.Exp(n), indicator.Last.Value, Tolerance);
}
}
[Fact]
public void Exptrans_InverseOfLog()
{
// exp(ln(x)) = x for all x > 0
var gbm = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 50003);
var bars = gbm.Fetch(50, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
var source = bars.Close;
var logResult = Logtrans.Batch(source);
var expResult = Exptrans.Batch(logResult);
for (int i = 0; i < source.Count; i++)
{
Assert.Equal(source[i].Value, expResult[i].Value, 1e-10);
}
}
[Fact]
public void Exptrans_ProductRule()
{
// exp(a + b) = exp(a) * exp(b)
double a = 1.5;
double b = 2.3;
var indicator = new Exptrans();
var time = DateTime.UtcNow;
indicator.Update(new TValue(time, a));
double expA = indicator.Last.Value;
indicator.Reset();
indicator.Update(new TValue(time, b));
double expB = indicator.Last.Value;
indicator.Reset();
indicator.Update(new TValue(time, a + b));
double expAB = indicator.Last.Value;
Assert.Equal(expA * expB, expAB, Tolerance);
}
[Fact]
public void Exptrans_QuotientRule()
{
// exp(a - b) = exp(a) / exp(b)
double a = 3.0;
double b = 1.5;
var indicator = new Exptrans();
var time = DateTime.UtcNow;
indicator.Update(new TValue(time, a));
double expA = indicator.Last.Value;
indicator.Reset();
indicator.Update(new TValue(time, b));
double expB = indicator.Last.Value;
indicator.Reset();
indicator.Update(new TValue(time, a - b));
double expAMinusB = indicator.Last.Value;
Assert.Equal(expA / expB, expAMinusB, Tolerance);
}
[Fact]
public void Exptrans_PowerRule()
{
// exp(n * a) = exp(a)^n
double a = 1.2;
int n = 3;
var indicator = new Exptrans();
var time = DateTime.UtcNow;
indicator.Update(new TValue(time, a));
double expA = indicator.Last.Value;
indicator.Reset();
indicator.Update(new TValue(time, n * a));
double expNA = indicator.Last.Value;
Assert.Equal(Math.Pow(expA, n), expNA, 1e-12);
}
}