feat: Enhance volume indicators with ADOSC and SSF implementation and validation

This commit is contained in:
Miha Kralj
2025-12-20 15:08:07 -08:00
parent 5549c7329a
commit d21fea3c18
85 changed files with 5144 additions and 3954 deletions
+24 -9
View File
@@ -66,20 +66,19 @@ public sealed class Vidya : AbstractBase
{
if (isNew)
{
_p_state = _state;
_state.BarCount++;
if (_state.IsInitialized)
{
_state.PrevClose = _state.CurrentClose;
_state.LastVidya = _state.CurrentVidya;
}
_p_state = _state;
}
else
{
_state = _p_state;
}
if (_state.IsInitialized)
{
_state.PrevClose = _state.CurrentClose;
_state.LastVidya = _state.CurrentVidya;
}
double price = input.Value;
if (!double.IsFinite(price))
{
@@ -143,9 +142,25 @@ public sealed class Vidya : AbstractBase
Batch(source.Values, vSpan, _period);
source.Times.CopyTo(tSpan);
Prime(source.Values);
// Replay only the last _period bars to restore internal state
Reset();
int start = 0;
if (len > _period)
{
start = len - _period;
_state.BarCount = start;
_state.IsInitialized = true;
_state.PrevClose = source.Values[start - 1];
_state.LastVidya = vSpan[start - 1];
_state.CurrentClose = _state.PrevClose;
_state.CurrentVidya = _state.LastVidya;
}
for (int i = start; i < len; i++)
{
Update(new TValue(source.Times[i], source.Values[i]));
}
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
+33 -106
View File
@@ -1,132 +1,59 @@
# VIDYA: Variable Index Dynamic Average
## What It Does
> "Tushar Chande asked: 'Why should I trust a moving average that treats a market crash the same as a lunch break?' VIDYA is the answer."
The Variable Index Dynamic Average (VIDYA) is an adaptive moving average that automatically adjusts its smoothing speed based on market volatility. When the market is volatile and trending, VIDYA speeds up to capture the move. When the market is quiet or consolidating, VIDYA slows down to filter out noise. It uses the Chande Momentum Oscillator (CMO) as its volatility index.
The Variable Index Dynamic Average (VIDYA) is an adaptive moving average that automatically adjusts its smoothing speed based on market volatility. When the market is trending (high volatility), VIDYA speeds up to capture the move. When the market is ranging (low volatility), it slows down to filter out the noise.
## Historical Context
Developed by Tushar Chande and introduced in his 1994 book *"The New Technical Trader"*, VIDYA was one of the first "intelligent" moving averages. Chande recognized that a fixed-period moving average is always a compromise. VIDYA solves this by dynamically varying its effective period bar-by-bar.
Developed by Tushar Chande and introduced in *Technical Analysis of Stocks & Commodities* (March 1992). It was one of the first "intelligent" moving averages, using Chande's own Momentum Oscillator (CMO) as the volatility index.
## How It Works
## Architecture & Physics
### The Core Idea
VIDYA is essentially an EMA where the alpha ($\alpha$) is not constant.
$$ \alpha_{dynamic} = \alpha_{static} \times |CMO| $$
VIDYA is essentially an Exponential Moving Average (EMA) where the smoothing factor ($\alpha$) is not constant. Instead, $\alpha$ is scaled by a "Volatility Index" (VI).
Since $|CMO|$ ranges from 0 to 1:
- **High Volatility:** VI is high $\rightarrow$ $\alpha$ increases $\rightarrow$ VIDYA reacts faster.
- **Low Volatility:** VI is low $\rightarrow$ $\alpha$ decreases $\rightarrow$ VIDYA reacts slower.
* **CMO = 0 (No Trend)**: $\alpha = 0$. VIDYA becomes a flat line.
* **CMO = 1 (Strong Trend)**: $\alpha = \alpha_{static}$. VIDYA acts like a standard EMA.
### Mathematical Foundation
## Mathematical Foundation
1. **Volatility Index (VI):**
We use the absolute value of the Chande Momentum Oscillator (CMO) over period $N$.
$$ VI = |CMO(N)| = \left| \frac{\sum Up - \sum Down}{\sum Up + \sum Down} \right| $$
$VI$ ranges from 0 (no trend) to 1 (strong trend).
### 1. Chande Momentum Oscillator (CMO)
2. **Smoothing Factor ($\alpha$):**
$$ \alpha_{base} = \frac{2}{N+1} $$
$$ \alpha_{dynamic} = \alpha_{base} \times VI $$
$$ CMO = \frac{\sum Up - \sum Down}{\sum Up + \sum Down} $$
3. **Update Formula:**
$$ VIDYA_{today} = \alpha_{dynamic} \times Price_{today} + (1 - \alpha_{dynamic}) \times VIDYA_{yesterday} $$
### 2. Dynamic Alpha
### Implementation Details
$$ \alpha_{static} = \frac{2}{N+1} $$
$$ \alpha_{dynamic} = \alpha_{static} \times |CMO| $$
Our implementation calculates CMO and VIDYA in a single pass.
### 3. The Update
- **Complexity:** O(1) per update (CMO is O(1) via running sums).
- **Efficiency:** Uses the same optimized structure as our standard EMA.
## Configuration
| Parameter | Default | Purpose | Adjustment Guidelines |
|-----------|---------|---------|----------------------|
| Period | 14 | Lookback window | Standard lookback for both CMO and the base EMA. |
$$ VIDYA_t = (\alpha_{dynamic} \times Price_t) + ((1 - \alpha_{dynamic}) \times VIDYA_{t-1}) $$
## Performance Profile
| Operation | Complexity | Description |
|-----------|------------|-------------------|
| Streaming update | O(1) | CMO update + EMA update |
| Bar correction | O(1) | Efficient state rollback |
| Batch processing | O(N) | Single pass through data |
| Memory footprint | O(period) | RingBuffer for CMO calculation |
### Zero-Allocation Design
## Interpretation
The implementation uses two `RingBuffer`s to track the sum of up-moves and down-moves for the CMO calculation. This allows O(1) updates of the volatility index without re-iterating history.
### Trading Signals
| Metric | Score | Notes |
| :--- | :--- | :--- |
| **Throughput** | High | CMO + EMA |
| **Complexity** | O(1) | Constant time update |
| **Accuracy** | 8/10 | Adapts to volatility, tracking trends |
| **Timeliness** | 8/10 | Speeds up in volatile markets |
| **Overshoot** | 7/10 | Can overshoot if volatility spikes |
| **Smoothness** | 7/10 | Smoother than EMA in quiet markets |
#### Trend Following
## Validation
- **Support/Resistance:** VIDYA is excellent at identifying dynamic support and resistance levels because it flattens out during consolidations (providing a clear "shelf" of support) and slopes steeply during trends.
Validated against the original formula and reference implementations.
#### Crossovers
### Common Pitfalls
- **Price Crossover:** Price crossing VIDYA is a standard trend entry signal. Because VIDYA adapts to volatility, these signals are often more reliable than SMA crossovers in choppy markets.
### When It Works Best
- **Breakouts:** VIDYA excels at catching breakouts from low-volatility consolidations because its effective period shortens (speeds up) as soon as volatility expands.
### When It Struggles
- **Grinding Trends:** In a slow, low-volatility grind upwards, VIDYA might lag more than a standard EMA because the low volatility keeps the smoothing factor small.
## Architecture Notes
This implementation makes specific trade-offs:
### Choice: CMO as Volatility Index
- **Implementation:** Uses Chande Momentum Oscillator.
- **Rationale:** This is the original definition by Chande. Other variants (like using Efficiency Ratio) exist but are technically different indicators (e.g., KAMA).
## References
- Chande, Tushar. "The New Technical Trader." Wiley, 1994.
- Chande, Tushar. "Adapting Moving Averages To Market Volatility." *Technical Analysis of Stocks & Commodities*, Mar 1992.
## C# Usage
### Streaming Updates (Single Instance)
```csharp
using QuanTAlib;
var vidya = new Vidya(period: 14);
// Process each new bar
TValue result = vidya.Update(new TValue(timestamp, closePrice));
Console.WriteLine($"VIDYA: {result.Value:F2}");
// Check if buffer is full
if (vidya.IsHot)
{
// Indicator is fully initialized
}
```
### Batch Processing (Historical Data)
```csharp
// TSeries API
TSeries prices = ...;
TSeries vidyaValues = Vidya.Batch(prices, period: 14);
// Span API (High Performance)
double[] prices = new double[1000];
double[] output = new double[1000];
Vidya.Calculate(prices.AsSpan(), output.AsSpan(), period: 14);
```
### Bar Correction (isNew Parameter)
```csharp
var vidya = new Vidya(14);
// New bar
vidya.Update(new TValue(time, 100), isNew: true);
// Intra-bar update
vidya.Update(new TValue(time, 101), isNew: false); // Replaces 100 with 101
1. **Flatlining**: In extremely choppy, sideways markets, CMO can approach 0, causing VIDYA to flatline completely. This is a feature, not a bug.
2. **Sensitivity**: VIDYA is highly sensitive to the period chosen for the CMO. A short period makes it jittery; a long period makes it sluggish.
3. **Comparison**: Often compared to KAMA (Kaufman). KAMA uses Efficiency Ratio (ER); VIDYA uses CMO. They are conceptually similar but mathematically distinct.