doc headers

This commit is contained in:
Miha Kralj
2026-02-27 07:48:12 -08:00
parent 8a1ba95173
commit 4ab3a7fb53
389 changed files with 6682 additions and 468 deletions
+5 -5
View File
@@ -114,11 +114,11 @@ public class AcfValidationTests
// For white noise, ACF at any lag > 0 should be close to zero
var acf = new Acf(100, 5);
// Generate pseudo-random values with zero mean
var random = new Random(42);
// Generate pseudo-random values with zero mean via GBM log-returns
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
for (int i = 0; i < 500; i++)
{
double val = random.NextDouble() * 2 - 1; // Uniform [-1, 1]
double val = Math.Log(random.Next().Close / 100.0); // ~N(0, vol²*dt) centered near 0
acf.Update(new TValue(DateTime.UtcNow.AddSeconds(i), val));
}
@@ -215,12 +215,12 @@ public class AcfValidationTests
double[] ar1Data = new double[n];
ar1Data[0] = 0;
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
// Generate AR(1) process
for (int i = 1; i < n; i++)
{
double epsilon = (random.NextDouble() * 2 - 1) * 0.1; // Small noise
double epsilon = Math.Log(random.Next().Close / 100.0) * 0.1; // Small noise
ar1Data[i] = phi * ar1Data[i - 1] + epsilon;
}
+18 -1
View File
@@ -1,5 +1,22 @@
# ACF: Autocorrelation Function
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `lag` (default 1) |
| **Outputs** | Single series (Acf) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Autocorrelation Function (ACF) measures the correlation of a time series with a lagged copy of itself.
- Parameterized by `period`, `lag` (default 1).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The past doesn't predict the future, but it whispers patterns to those who listen."
The Autocorrelation Function (ACF) measures the correlation of a time series with a lagged copy of itself. It is fundamental for identifying repeating patterns, seasonal effects, and determining the order of time series models like ARMA/ARIMA.
@@ -159,4 +176,4 @@ A random walk should have ACF ≈ 0 at all lags. Significant ACF values indicate
- Box, G.E.P., Jenkins, G.M. (1970). *Time Series Analysis: Forecasting and Control*. Holden-Day.
- Hamilton, J.D. (1994). *Time Series Analysis*. Princeton University Press.
- Yule, G.U. (1927). "On a Method of Investigating Periodicities in Disturbed Series." *Philosophical Transactions of the Royal Society*.
- Yule, G.U. (1927). "On a Method of Investigating Periodicities in Disturbed Series." *Philosophical Transactions of the Royal Society*.
+17
View File
@@ -1,5 +1,22 @@
# Beta: Beta Coefficient
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Beta) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period + 1` bars |
### TL;DR
- Beta measures the volatility of an asset in relation to the overall market.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period + 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Volatility is not risk. It's the price of admission."
Beta measures the volatility of an asset in relation to the overall market. It's the slope of the regression line between the asset's returns and the market's returns. A beta of 1.0 means the asset moves in lockstep with the market. A beta of 2.0 means the asset is twice as volatile as the market.
+17
View File
@@ -1,5 +1,22 @@
# CMA: Cumulative Moving Average
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `source` |
| **Outputs** | Single series (CMA) |
| **Output range** | Varies (see docs) |
| **Warmup** | `1` bars |
### TL;DR
- The Cumulative Moving Average (CMA) calculates the arithmetic mean of ALL data points seen so far, not just a fixed window.
- Parameterized by `source`.
- Output range: Varies (see docs).
- Requires `1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The running average that never forgets. Every single tick you've ever fed it? Still in there, affecting the result. It's like the elephant of technical indicators."
The Cumulative Moving Average (CMA) calculates the arithmetic mean of ALL data points seen so far, not just a fixed window. Unlike SMA or EMA which use a sliding window, CMA treats every historical value with equal weight. As the sample size grows, each new value has diminishing impact on the average.
@@ -581,12 +581,12 @@ public class CointegrationTests
{
// Create two cointegrated series: B = A + noise
var indicator = new Cointegration(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
for (int i = 0; i < 100; i++)
{
double a = 100.0 + i * 0.1;
double b = a + random.NextDouble() * 0.1 - 0.05; // Highly correlated
double b = a + Math.Log(random.Next().Close / 100.0) * 0.1; // Highly correlated
indicator.Update(a, b);
}
@@ -601,7 +601,7 @@ public class CointegrationTests
// Create two non-cointegrated series (random walks)
var indicatorCointegrated = new Cointegration(20);
var indicatorRandom = new Cointegration(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
double walkA = 100.0;
double walkB = 100.0;
@@ -610,12 +610,13 @@ public class CointegrationTests
{
// Cointegrated pair
double a1 = 100.0 + i * 0.1;
double b1 = a1 + random.NextDouble() * 0.1;
double noise1 = Math.Log(random.Next().Close / 100.0);
double b1 = a1 + noise1 * 0.1;
indicatorCointegrated.Update(a1, b1);
// Random walks
walkA += random.NextDouble() - 0.5;
walkB += random.NextDouble() - 0.5;
walkA += Math.Log(random.Next().Close / 100.0);
walkB += Math.Log(random.Next().Close / 100.0);
indicatorRandom.Update(walkA, walkB);
}
@@ -10,6 +10,9 @@ public class CointegrationValidationTests
{
private const double Tolerance = 1e-6;
// GBM-based noise helper: log-return from seeded GBM price stream as centered noise.
private static double GbmNoise(GBM gbm) => Math.Log(gbm.Next().Close / 100.0);
#region Statistical Property Validation
[Fact]
@@ -18,12 +21,12 @@ public class CointegrationValidationTests
// Two series with near-perfect linear relationship should show strong cointegration
// Adding small noise to avoid zero-variance residuals
var indicator = new Cointegration(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
for (int i = 0; i < 100; i++)
{
double a = 100.0 + i * 0.5 + (random.NextDouble() - 0.5) * 0.1;
double b = 2.0 * a + 10.0 + (random.NextDouble() - 0.5) * 0.1;
double a = 100.0 + i * 0.5 + GbmNoise(random) * 0.1;
double b = 2.0 * a + 10.0 + GbmNoise(random) * 0.1;
indicator.Update(a, b);
}
@@ -55,12 +58,12 @@ public class CointegrationValidationTests
{
// B = k * A + small noise (near-proportional relationship)
var indicator = new Cointegration(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 43);
for (int i = 0; i < 100; i++)
{
double a = 50.0 + i * 0.3 + Math.Sin(i * 0.2) * 5.0;
double noise = (random.NextDouble() - 0.5) * 0.5;
double noise = GbmNoise(random) * 0.5;
double b = 1.5 * a + noise;
indicator.Update(a, b);
}
@@ -73,12 +76,12 @@ public class CointegrationValidationTests
{
// B = α + β*A + small_noise
var indicator = new Cointegration(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 44);
for (int i = 0; i < 100; i++)
{
double a = 100.0 + i * 0.2;
double noise = (random.NextDouble() - 0.5) * 0.5; // Small noise
double noise = GbmNoise(random) * 0.5; // Small noise
double b = 25.0 + 0.8 * a + noise;
indicator.Update(a, b);
}
@@ -245,12 +248,12 @@ public class CointegrationValidationTests
public void Cointegration_SmallPeriod_WorksCorrectly()
{
var indicator = new Cointegration(3); // Minimum practical period
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 45);
for (int i = 0; i < 20; i++)
{
double a = 100.0 + i + (random.NextDouble() - 0.5) * 0.1;
double b = 50.0 + 0.5 * a + (random.NextDouble() - 0.5) * 0.1;
double a = 100.0 + i + GbmNoise(random) * 0.1;
double b = 50.0 + 0.5 * a + GbmNoise(random) * 0.1;
indicator.Update(a, b);
}
@@ -263,12 +266,12 @@ public class CointegrationValidationTests
public void Cointegration_LargePeriod_WorksCorrectly()
{
var indicator = new Cointegration(100);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 46);
for (int i = 0; i < 150; i++)
{
double a = 100.0 + i * 0.1 + (random.NextDouble() - 0.5) * 0.1;
double b = 30.0 + 0.8 * a + (random.NextDouble() - 0.5) * 0.1;
double a = 100.0 + i * 0.1 + GbmNoise(random) * 0.1;
double b = 30.0 + 0.8 * a + GbmNoise(random) * 0.1;
indicator.Update(a, b);
}
+18 -1
View File
@@ -1,5 +1,22 @@
# Cointegration: Engle-Granger Two-Step Cointegration Test
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` (default 20) |
| **Outputs** | Single series (Cointegration) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period + 1` bars |
### TL;DR
- The Cointegration indicator measures the long-run equilibrium relationship between two price series using the Engle-Granger two-step method with an...
- Parameterized by `period` (default 20).
- Output range: Varies (see docs).
- Requires `period + 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Correlation tells you they move together. Cointegration tells you they're bound together. Two stocks can be uncorrelated yet cointegrated, or perfectly correlated yet destined to drift apart forever. The difference between 'similar direction' and 'shared destiny' is the difference between a tourist attraction and a gravitational orbit."
The Cointegration indicator measures the long-run equilibrium relationship between two price series using the Engle-Granger two-step method with an Augmented Dickey-Fuller (ADF) test. Unlike correlation, which measures short-term co-movement, cointegration tests whether two non-stationary series share a common stochastic trend—meaning they may diverge temporarily but are statistically bound to revert to their equilibrium relationship.
@@ -270,4 +287,4 @@ coint.Update(101.0, 51.0, isNew: false); // Recalculates without advancing state
- Engle, R.F. and Granger, C.W.J. (1987). "Co-integration and Error Correction: Representation, Estimation, and Testing." *Econometrica*, 55(2), 251-276.
- Dickey, D.A. and Fuller, W.A. (1979). "Distribution of the Estimators for Autoregressive Time Series with a Unit Root." *Journal of the American Statistical Association*, 74(366), 427-431.
- TradingView. "Cointegration Indicator (PineScript)." *TradingView Community Scripts*.
- Vidyamurthy, G. (2004). "Pairs Trading: Quantitative Methods and Analysis." *Wiley Finance*.
- Vidyamurthy, G. (2004). "Pairs Trading: Quantitative Methods and Analysis." *Wiley Finance*.
@@ -594,12 +594,12 @@ public sealed class CorrelationValidationTests : IDisposable
{
// Create two series with negative correlation
var indicator = new Correlation(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
for (int i = 0; i < 100; i++)
{
double x = 100.0 + i + (random.NextDouble() - 0.5) * 2;
double y = 200.0 - 0.8 * i + (random.NextDouble() - 0.5) * 2; // Negative relationship
double x = 100.0 + i + Math.Log(random.Next().Close / 100.0) * 2;
double y = 200.0 - 0.8 * i + Math.Log(random.Next().Close / 100.0) * 2; // Negative relationship
indicator.Update(x, y);
}
@@ -611,12 +611,12 @@ public sealed class CorrelationValidationTests : IDisposable
{
// Create two series with weak correlation (lots of noise)
var indicator = new Correlation(20);
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 43);
for (int i = 0; i < 100; i++)
{
double x = 100.0 + i + (random.NextDouble() - 0.5) * 50;
double y = 100.0 + 0.1 * i + (random.NextDouble() - 0.5) * 50; // Weak relationship
double x = 100.0 + i + Math.Log(random.Next().Close / 100.0) * 50;
double y = 100.0 + 0.1 * i + Math.Log(random.Next().Close / 100.0) * 50; // Weak relationship
indicator.Update(x, y);
}
+18 -1
View File
@@ -1,5 +1,22 @@
# CORR: Pearson Correlation Coefficient
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` (default 20) |
| **Outputs** | Single series (Correlation) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Pearson Correlation Coefficient measures the linear relationship between two variables, returning a value from -1 (perfect negative correlation...
- Parameterized by `period` (default 20).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Correlation is not causation, but it sure is a hint. The market doesn't care why two instruments move together—only that they do, and whether that relationship will persist long enough for you to profit from it."
The Pearson Correlation Coefficient measures the linear relationship between two variables, returning a value from -1 (perfect negative correlation) to +1 (perfect positive correlation). Zero indicates no linear relationship. This implementation uses running sums for O(1) streaming updates, making it suitable for real-time analysis of price relationships.
@@ -265,4 +282,4 @@ corr.Update(101.0, 51.0, isNew: false); // Recalculates without advancing state
- Pearson, K. (1895). "Notes on regression and inheritance in the case of two parents." *Proceedings of the Royal Society of London*, 58, 240-242.
- TradingView. "ta.correlation() function." *Pine Script Language Reference Manual*.
- Vidyamurthy, G. (2004). "Pairs Trading: Quantitative Methods and Analysis." *Wiley Finance*. Chapter on correlation analysis.
- Embrechts, P., McNeil, A., & Straumann, D. (2002). "Correlation and dependence in risk management: properties and pitfalls." *Risk Management: Value at Risk and Beyond*, Cambridge University Press.
- Embrechts, P., McNeil, A., & Straumann, D. (2002). "Correlation and dependence in risk management: properties and pitfalls." *Risk Management: Value at Risk and Beyond*, Cambridge University Press.
+17
View File
@@ -1,5 +1,22 @@
# Covariance: Covariance
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `isPopulation` (default false) |
| **Outputs** | Single series (Cov) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Covariance measures the joint variability of two random variables.
- Parameterized by `period`, `ispopulation` (default false).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Correlation is just covariance normalized by standard deviation. But sometimes you want the raw, unadulterated relationship."
Covariance measures the joint variability of two random variables. It indicates the direction of the linear relationship between variables.
+17
View File
@@ -1,5 +1,22 @@
# ENTROPY: Shannon Entropy
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Entropy) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Shannon Entropy measures the unpredictability or randomness of a time series over a sliding window.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Information is the resolution of uncertainty." — Claude Shannon
Shannon Entropy measures the unpredictability or randomness of a time series over a sliding window. A low entropy value indicates the series is highly predictable (clustered values), while a high entropy value indicates the data is spread uniformly across its range — maximum randomness.
+17
View File
@@ -1,5 +1,22 @@
# GEOMEAN: Geometric Mean
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Geomean) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Geometric Mean computes the nth root of the product of n positive values over a sliding window.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The geometric mean is never greater than the arithmetic mean." - Mathematical inequality since antiquity
The Geometric Mean computes the nth root of the product of n positive values over a sliding window. Unlike the arithmetic mean, it captures multiplicative relationships and is the correct average for growth rates, ratios, and log-normally distributed data. For financial time series, this means it properly accounts for compounding.
@@ -7,13 +7,17 @@ namespace QuanTAlib.Tests;
/// </summary>
public class GrangerValidationTests
{
// GBM-based noise helper: extracts log-return from a seeded GBM price stream as centered noise.
// Using sigma=1.0 gives log-returns ~N(0, vol²*dt); scale to required magnitude.
private static double GbmNoise(GBM gbm) => Math.Log(gbm.Next().Close / 100.0);
[Fact]
public void Granger_CausalRelationship_ProducesHighFStatistic()
{
// X causes Y: Y_t = 0.5*Y_{t-1} + 0.3*X_{t-1} + noise
// Adding X_lag should significantly improve prediction
var indicator = new Granger(20);
var rng = new Random(42);
var rng = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
double y = 100.0;
double x = 100.0;
@@ -22,8 +26,8 @@ public class GrangerValidationTests
for (int i = 0; i < 200; i++)
{
x = 100.0 + Math.Sin(i * 0.1) * 10.0 + (rng.NextDouble() - 0.5) * 2.0;
y = 50.0 + 0.5 * prevY + 0.3 * prevX + (rng.NextDouble() - 0.5) * 0.5;
x = 100.0 + Math.Sin(i * 0.1) * 10.0 + GbmNoise(rng) * 2.0;
y = 50.0 + 0.5 * prevY + 0.3 * prevX + GbmNoise(rng) * 0.5;
indicator.Update(y, x, isNew: true);
@@ -68,7 +72,7 @@ public class GrangerValidationTests
// Compare strong causal vs weak causal relationship
var strongIndicator = new Granger(20);
var weakIndicator = new Granger(20);
var rng = new Random(42);
var rng = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
double yStrong = 100.0, yWeak = 100.0;
double x = 100.0;
@@ -76,12 +80,12 @@ public class GrangerValidationTests
for (int i = 0; i < 200; i++)
{
x = 100.0 + Math.Sin(i * 0.1) * 10.0 + (rng.NextDouble() - 0.5) * 2.0;
x = 100.0 + Math.Sin(i * 0.1) * 10.0 + GbmNoise(rng) * 2.0;
// Strong: Y depends heavily on X_lag
yStrong = 50.0 + 0.3 * prevYStrong + 0.6 * prevX + (rng.NextDouble() - 0.5) * 0.5;
yStrong = 50.0 + 0.3 * prevYStrong + 0.6 * prevX + GbmNoise(rng) * 0.5;
// Weak: Y barely depends on X_lag
yWeak = 50.0 + 0.8 * prevYWeak + 0.05 * prevX + (rng.NextDouble() - 0.5) * 5.0;
yWeak = 50.0 + 0.8 * prevYWeak + 0.05 * prevX + GbmNoise(rng) * 5.0;
strongIndicator.Update(yStrong, x, isNew: true);
weakIndicator.Update(yWeak, x, isNew: true);
@@ -199,7 +203,7 @@ public class GrangerValidationTests
// when causality is asymmetric
var indicatorYX = new Granger(15);
var indicatorXY = new Granger(15);
var rng = new Random(42);
var rng = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
double y = 100.0, x = 100.0;
double prevY = y, prevX = x;
@@ -207,9 +211,9 @@ public class GrangerValidationTests
for (int i = 0; i < 200; i++)
{
// X is exogenous (just random walk with drift)
x = prevX + (rng.NextDouble() - 0.5) * 2.0;
x = prevX + GbmNoise(rng) * 2.0;
// Y depends on X_lag (X Granger-causes Y, but Y does NOT Granger-cause X)
y = 50.0 + 0.3 * prevY + 0.4 * prevX + (rng.NextDouble() - 0.5) * 0.5;
y = 50.0 + 0.3 * prevY + 0.4 * prevX + GbmNoise(rng) * 0.5;
indicatorYX.Update(y, x, isNew: true); // Testing: does X cause Y?
indicatorXY.Update(x, y, isNew: true); // Testing: does Y cause X?
+17
View File
@@ -1,5 +1,22 @@
# GRANGER: Granger Causality F-Statistic
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` (default 20) |
| **Outputs** | Single series (Granger) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period + 1` bars |
### TL;DR
- The Granger Causality test asks a precise, falsifiable question: does knowing the history of series X improve your ability to predict series Y, bey...
- Parameterized by `period` (default 20).
- Output range: Varies (see docs).
- Requires `period + 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Correlation is not causation, but Granger causality is not causation either. It is prediction." -- Clive Granger
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# HARMEAN: Harmonic Mean
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Harmean) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Harmonic Mean computes the reciprocal of the arithmetic mean of reciprocals over a sliding window.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The harmonic mean is never greater than the geometric mean, which is never greater than the arithmetic mean." - The Mean Inequality, a mathematical fact older than calculus
The Harmonic Mean computes the reciprocal of the arithmetic mean of reciprocals over a sliding window. It is the correct average for quantities defined in terms of rates or ratios (speed, P/E ratios, yield). For financial time series, the harmonic mean gives the largest discount to outliers, making it the most conservative of the three Pythagorean means.
@@ -1,6 +1,4 @@
using OoplesFinance.StockIndicators;
using OoplesFinance.StockIndicators.Models;
// HURST Validation Tests - Hurst Exponent via Rescaled Range (R/S) Analysis
// Validated against self-consistency and known mathematical properties
// No external library provides a direct R/S-based Hurst exponent equivalent
@@ -183,23 +181,4 @@ public sealed class HurstValidationTests
Assert.Equal(h1.Last.Value, h2.Last.Value, 1e-15);
}
[Fact(Skip = "CalculateEhlersHurstCoefficient produces 0 finite values on 500-bar dataset — requires an extremely long warmup (1000+ bars). Not comparable with synthetic GBM input.")]
public void Hurst_MatchesOoples_Structural()
{
var gbm = new GBM(startPrice: 100.0, mu: 0.02, sigma: 0.15, seed: 42);
var bars = gbm.Fetch(500, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
var ooplesData = bars.Select(b => new TickerData
{
Date = new DateTime(b.Time, DateTimeKind.Utc),
Open = b.Open,
High = b.High,
Low = b.Low,
Close = b.Close,
Volume = b.Volume
}).ToList();
var result = new StockData(ooplesData).CalculateEhlersHurstCoefficient();
var values = result.OutputValues.Values.First();
int finiteCount = values.Count(v => double.IsFinite(v));
Assert.True(finiteCount > 100, $"Expected >100 finite values, got {finiteCount}");
}
}
+17
View File
@@ -1,5 +1,22 @@
# HURST: Hurst Exponent
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Hurst) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period + 1` bars |
### TL;DR
- The Hurst Exponent ($H$) quantifies long-range dependence in a time series through Rescaled Range (R/S) analysis.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period + 1` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The past is not dead. In fact, it's not even past." — William Faulkner, and also every mean-reverting time series that refuses to forget.
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# IQR: Interquartile Range
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Iqr) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Interquartile Range measures the spread of the middle 50% of a sorted dataset within a rolling window.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The median is the most important statistic, and the interquartile range is the second most important." — John Tukey
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# JB: Jarque-Bera Test
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Jb) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Jarque-Bera test quantifies departure from normality by combining skewness and excess kurtosis into a single chi-squared statistic.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The assumption of normality is the most dangerous assumption in all of statistics." — George Box (paraphrased)
The Jarque-Bera test quantifies departure from normality by combining skewness and excess kurtosis into a single chi-squared statistic. A rolling JB value near zero means the window looks Gaussian. Values exceeding 5.991 (5% significance) reject normality. Financial returns almost always fail this test, which is precisely why the test matters.
+17
View File
@@ -1,5 +1,22 @@
# KURTOSIS: Excess Kurtosis
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `isPopulation` (default false) |
| **Outputs** | Single series (Kurtosis) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Kurtosis measures the **tailedness** of a probability distribution.
- Parameterized by `period`, `ispopulation` (default false).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car." The fourth moment measures how far your returns deviate from that comforting fiction.
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# LinReg: Linear Regression Curve
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `offset` (default 0) |
| **Outputs** | Single series (LinReg) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Linear Regression Curve plots the end point of the linear regression line for each bar.
- Parameterized by `period`, `offset` (default 0).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The trend is your friend, until it bends."
The Linear Regression Curve plots the end point of the linear regression line for each bar. It fits a straight line $y = mx + b$ to the data points using the least squares method, providing a smoothed representation of the price trend that is more responsive than a Simple Moving Average (SMA).
+17 -1
View File
@@ -1,6 +1,22 @@
````markdown
# MeanDev: Mean Deviation (Average Absolute Deviation)
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (MeanDev) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- ````markdown
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Not all dispersion is created equal — some prefer robustness over elegance."
Mean Deviation (also known as Mean Absolute Deviation or Average Absolute Deviation) measures the average of the absolute deviations from the mean. Unlike Standard Deviation, it does not square the deviations, making it more robust to outliers and more intuitive to interpret.
+17
View File
@@ -1,5 +1,22 @@
# MEDIAN: Rolling Median
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Median) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Rolling Median is a robust statistic that represents the middle value of a dataset within a moving window.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The average is easily influenced by outliers; the median stands its ground."
The Rolling Median is a robust statistic that represents the middle value of a dataset within a moving window. Unlike the Simple Moving Average (SMA), which can be skewed by extreme values, the Median provides a more stable measure of central tendency, making it particularly useful for filtering noise in volatile markets.
+17
View File
@@ -1,5 +1,22 @@
# MODE: Statistical Mode (Most Frequent Value)
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Mode) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The **Mode** is a rolling statistical indicator that identifies the most frequently occurring value within a sliding window of recent observations.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The mode is the value that appears most frequently in a data set — the only measure of central tendency that tells you what's actually popular, not what's average."
## Introduction
+2 -2
View File
@@ -105,13 +105,13 @@ public class PacfValidationTests
// For AR(1) process: x_t = φ*x_{t-1} + ε_t
// PACF should be significant at lag 1 and cut off (near zero) after
double phi = 0.7; // AR(1) coefficient
var random = new Random(42);
var random = new GBM(startPrice: 100.0, sigma: 1.0, seed: 42);
var arProcess = new List<double> { 100.0 };
// Generate AR(1) process
for (int i = 1; i < 500; i++)
{
double noise = random.NextDouble() * 2 - 1; // Small noise
double noise = Math.Log(random.Next().Close / 100.0); // ~N(0, vol²*dt) noise
double newValue = phi * arProcess[^1] + noise;
arProcess.Add(newValue);
}
+18 -1
View File
@@ -1,5 +1,22 @@
# PACF: Partial Autocorrelation Function
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `lag` (default 1) |
| **Outputs** | Single series (Pacf) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Partial Autocorrelation Function (PACF) measures the correlation between a time series and its lagged values, after removing the effects of all...
- Parameterized by `period`, `lag` (default 1).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Strip away the intermediaries, and you'll see the true direct relationship."
The Partial Autocorrelation Function (PACF) measures the correlation between a time series and its lagged values, after removing the effects of all intermediate lags. While ACF shows total correlation at each lag, PACF isolates the direct correlation, making it essential for AR model identification.
@@ -194,4 +211,4 @@ PACF is used in linear prediction and filter design, where the partial correlati
- Box, G.E.P., Jenkins, G.M. (1970). *Time Series Analysis: Forecasting and Control*. Holden-Day.
- Durbin, J. (1960). "The fitting of time series models." *Review of the International Statistical Institute*, 28, 233-243.
- Levinson, N. (1946). "The Wiener RMS error criterion in filter design and prediction." *Journal of Mathematics and Physics*, 25, 261-278.
- Hamilton, J.D. (1994). *Time Series Analysis*. Princeton University Press.
- Hamilton, J.D. (1994). *Time Series Analysis*. Princeton University Press.
+18
View File
@@ -1,6 +1,24 @@
# PERCENTILE: Rolling Percentile
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `percent` (default 50.0) |
| **Outputs** | Single series (Percentile) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Rolling Percentile computes the value below which a given percentage of observations fall within a sliding window.
- Parameterized by `period`, `percent` (default 50.0).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "There are three kinds of lies: lies, damned lies, and statistics." — Mark Twain.
> But percentiles, at least, tell you exactly where you stand.
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# POLYFIT: Polynomial Fitting
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `degree` (default 2) |
| **Outputs** | Single series (Polyfit) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Polynomial Fitting computes a rolling polynomial regression of configurable degree over a lookback window, returning the fitted value at the curren...
- Parameterized by `period`, `degree` (default 2).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
Polynomial Fitting computes a rolling polynomial regression of configurable degree over a lookback window, returning the fitted value at the current bar. Degree 1 produces a linear regression endpoint (identical to LSQR), degree 2 produces a quadratic fit that captures curvature, and degree 3 produces a cubic fit that captures inflection points. The implementation solves the normal equations $\mathbf{X}^T\mathbf{X}\mathbf{a} = \mathbf{X}^T\mathbf{y}$ via Gauss-Jordan elimination with partial pivoting, evaluating the resulting polynomial at $x = 1$ (the current bar position). With $O(Nd + d^3)$ complexity per bar where $N$ is the period and $d$ is the degree, POLYFIT provides a general-purpose curve-fitting tool that subsumes linear regression and extends it to arbitrary polynomial order.
## Historical Context
+17
View File
@@ -1,5 +1,22 @@
# QUANTILE: Rolling Quantile
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `quantileLevel` (default 0.25) |
| **Outputs** | Single series (Quantile) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Rolling Quantile computes the value below which a given fraction of observations fall within a sliding window.
- Parameterized by `period`, `quantilelevel` (default 0.25).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The quantile function is the inverse of the distribution function." — Every probability textbook ever written, and yet somehow it still surprises people.
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# SKEW: Skewness
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `isPopulation` (default false) |
| **Outputs** | Single series (Skew) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Skewness measures the asymmetry of the probability distribution of a real-valued random variable about its mean.
- Parameterized by `period`, `ispopulation` (default false).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "In the land of the blind, the one-eyed man is king. In the land of the normal distribution, the skewed man is profitable."
Skewness measures the asymmetry of the probability distribution of a real-valued random variable about its mean. It tells you where the "tail" of the distribution is.
+17
View File
@@ -1,5 +1,22 @@
# SPEARMAN: Spearman Rank Correlation Coefficient
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` (default 20) |
| **Outputs** | Single series (Spearman) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Spearman's ρ (rho) measures the strength and direction of monotonic association between two variables.
- Parameterized by `period` (default 20).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The person who asks whether rank correlation exists is not asking a wholly foolish question." — Maurice Kendall (1970)
Spearman's ρ (rho) measures the strength and direction of monotonic association between two variables. Unlike Pearson's correlation, which measures linear relationship, Spearman captures any monotonic relationship. A portfolio of stocks whose returns move monotonically together has different risk than one whose components merely share a linear trend. Spearman detects both.
+17
View File
@@ -1,5 +1,22 @@
# STDDEV: Standard Deviation
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `isPopulation` (default false) |
| **Outputs** | Single series (StdDev) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Standard Deviation measures the amount of variation or dispersion of a set of values.
- Parameterized by `period`, `ispopulation` (default false).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Volatility is not risk, but it's the only thing we can measure."
Standard Deviation measures the amount of variation or dispersion of a set of values. A low standard deviation indicates that the values tend to be close to the mean (also called the expected value) of the set, while a high standard deviation indicates that the values are spread out over a wider range.
@@ -196,18 +196,9 @@ public class StderrValidationTests
}
}
// ── Tulip Structural Note ─────────────────────────────────────────────────
//
// Tulip `stderr` is NOT the standard error of linear regression.
// Note: Tulip `stderr` is NOT the standard error of linear regression.
// Tulip formula: stddev(x, n) / sqrt(n) = standard error of the mean.
// QuanTAlib Stderr: sqrt(SSR / (n-2)) = standard error of OLS regression.
// These are different statistics — no cross-validation is possible.
// QuanTAlib is validated against its own brute-force OLS reference above.
[Fact(Skip = "Tulip stderr = StdDev/sqrt(n) (SE of mean); QuanTAlib Stderr = sqrt(SSR/(n-2)) (SE of OLS regression). Different statistics — intentional divergence.")]
public void Stderr_Structural_Note_TulipFormulaDiffers()
{
// Intentionally empty: test is always skipped via [Fact(Skip=...)].
// The Skip message documents the formula incompatibility with Tulip.
}
}
+17 -1
View File
@@ -1,6 +1,22 @@
````markdown
# Stderr: Standard Error of Regression
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Stderr) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- ````markdown
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "How confident are you in your line of best fit?"
Standard Error of Regression (also called the Standard Error of the Estimate) measures the average distance that the observed values fall from the regression line. It quantifies the typical size of the residuals, providing a direct measure of how well a linear regression model fits the data.
+17
View File
@@ -1,5 +1,22 @@
# Sum: Summation with Kahan-Babuška Algorithm
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Sum) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Sum indicator calculates a rolling window summation using the Kahan-Babuška algorithm (also known as "improved Kahan" or "second-order compensa...
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The naive approach to summation assumes all digits matter equally. They don't. When you add 1e-10 to 1e10, that small value vanishes into the rounding noise. Kahan-Babuška tracks what got lost and adds it back later. It's bookkeeping for bits that would otherwise slip through the cracks."
The Sum indicator calculates a rolling window summation using the Kahan-Babuška algorithm (also known as "improved Kahan" or "second-order compensated summation") for maximum numerical precision. This approach captures rounding errors that even classic Kahan summation misses, making it suitable for numerical libraries, statistics, and trading applications where precision matters.
+17
View File
@@ -1,5 +1,22 @@
# THEIL: Theil's T Index
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Theil) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Theil T Index is an information-theoretic measure of inequality (or concentration) within a distribution of positive values.
- Parameterized by `period`.
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The only useful measure of inequality is one that tells you how much redistribution would make everyone equally well off." — Henri Theil
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# TRIM: Trimmed Mean Moving Average
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `trimPct` (default 10.0) |
| **Outputs** | Single series (Trim) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Trimmed Mean Moving Average computes a rolling average after discarding a configurable percentage of the most extreme values from each tail of ...
- Parameterized by `period`, `trimpct` (default 10.0).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
The Trimmed Mean Moving Average computes a rolling average after discarding a configurable percentage of the most extreme values from each tail of the sorted lookback window. By removing the lowest and highest `trimPct%` of observations, TRIM eliminates the influence of outliers while retaining more information than a pure median. At `trimPct = 0` it degenerates to the SMA; at `trimPct = 50` it becomes the median. The default 10% trim provides a robust central tendency estimator that resists spike contamination with minimal loss of responsiveness, requiring $O(N \log N)$ for the sort plus $O(N)$ for the summation per bar.
## Historical Context
+17
View File
@@ -1,5 +1,22 @@
# Variance (VAR)
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `isPopulation` (default false) |
| **Outputs** | Single series (Variance) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- Variance measures how far a set of numbers is spread out from their average value.
- Parameterized by `period`, `ispopulation` (default false).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "Volatility is the price of admission for high returns."
Variance measures how far a set of numbers is spread out from their average value. In finance, it is a key measure of volatility and risk.
+17
View File
@@ -1,5 +1,22 @@
# WAVG: Weighted Average
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` |
| **Outputs** | Single series (Wavg) |
| **Output range** | $0$ to $1$ |
| **Warmup** | `period` bars |
### TL;DR
- The Weighted Average computes a rolling linearly-weighted mean where the most recent observation receives weight $N$ and the oldest receives weight...
- Parameterized by `period`.
- Output range: $0$ to $1$.
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
The Weighted Average computes a rolling linearly-weighted mean where the most recent observation receives weight $N$ and the oldest receives weight 1, making it mathematically identical to the Weighted Moving Average (WMA) but categorized as a statistical measure. The implementation uses a circular buffer with an $O(1)$ incremental update scheme: rather than recomputing the full weighted sum each bar, it maintains running sums and adjusts them through add/subtract operations as values enter and exit the window. This makes WAVG one of the most efficient weighted estimators available, with constant per-bar cost regardless of the lookback period.
## Historical Context
+17
View File
@@ -1,5 +1,22 @@
# WINS: Winsorized Mean Moving Average
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period`, `winPct` (default 10.0) |
| **Outputs** | Single series (Wins) |
| **Output range** | Varies (see docs) |
| **Warmup** | `period` bars |
### TL;DR
- The Winsorized Mean Moving Average computes a rolling average after replacing (not discarding) the most extreme values in each tail with the bounda...
- Parameterized by `period`, `winpct` (default 10.0).
- Output range: Varies (see docs).
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
The Winsorized Mean Moving Average computes a rolling average after replacing (not discarding) the most extreme values in each tail with the boundary values at the trim point. Unlike the trimmed mean (TRIM) which removes outliers entirely, Winsorization preserves the full sample size by clamping extreme values to the nearest non-extreme observation. At `winPct = 0` it degenerates to the SMA; at `winPct = 50` all values equal the median pair. The default 10% Winsorization provides a robust central tendency estimator that dampens outlier impact while maintaining the statistical efficiency advantages of the full sample size.
## Historical Context
+17
View File
@@ -1,5 +1,22 @@
# ZSCORE: Z-Score (Population Standard Score, also known as STANDARDIZE)
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` (default 14) |
| **Outputs** | Single series (Zscore) |
| **Output range** | Unbounded |
| **Warmup** | `period` bars |
### TL;DR
- The Z-Score measures how many population standard deviations a value lies from the rolling mean over a lookback window.
- Parameterized by `period` (default 14).
- Output range: Unbounded.
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "How far from normal is this?" — Every risk manager, every day.
## Introduction
+17
View File
@@ -1,5 +1,22 @@
# ZTEST: One-Sample t-Test Statistic
| Property | Value |
| ---------------- | -------------------------------- |
| **Category** | Statistic |
| **Inputs** | Source (close) |
| **Parameters** | `period` (default 30), `mu0` (default 0.0) |
| **Outputs** | Single series (Ztest) |
| **Output range** | Unbounded |
| **Warmup** | `period` bars |
### TL;DR
- ZTEST computes the **one-sample t-statistic**, measuring how many standard errors the rolling sample mean deviates from a hypothesized population m...
- Parameterized by `period` (default 30), `mu0` (default 0.0).
- Output range: Unbounded.
- Requires `period` bars of warmup before first valid output (IsHot = true).
- Validated against TA-Lib, Skender, and Tulip reference implementations where available.
> "The purpose of hypothesis testing is not to prove what we believe, but to measure what we observe." — Adapted from R.A. Fisher
## Introduction