mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-24 05:28:05 +00:00
feat: Enhance volume indicators with ADOSC and SSF implementation and validation
This commit is contained in:
+35
-126
@@ -1,152 +1,61 @@
|
||||
# DWMA: Double Weighted Moving Average
|
||||
|
||||
## What It Does
|
||||
> "If one WMA is good, two must be better. DWMA is for when you want your signal so smooth it looks like it's been sanded, polished, and waxed."
|
||||
|
||||
The Double Weighted Moving Average (DWMA) is a smoothing indicator that applies a Weighted Moving Average (WMA) twice. By smoothing the data once and then smoothing the result again, DWMA produces an exceptionally clean curve that filters out significant market noise. The trade-off is increased lag compared to a single WMA, making it more suitable for identifying major trends rather than short-term scalping.
|
||||
DWMA (Double Weighted Moving Average) is exactly what it says on the tin: a Weighted Moving Average of a Weighted Moving Average. Unlike DEMA, which tries to *remove* lag, DWMA accepts lag as the price of admission for superior noise reduction. It produces a curve that is incredibly smooth, ideal for identifying long-term trends without getting faked out by market chop.
|
||||
|
||||
## Historical Context
|
||||
|
||||
While the concept of double smoothing dates back to the early days of technical analysis (with the Triangular Moving Average being a close cousin), the DWMA gained utility as computing power allowed traders to easily chain indicators. It represents a logical extension of the WMA for traders who found the standard WMA too jittery but appreciated its linear weighting scheme.
|
||||
There is no single "inventor" of DWMA; it's a natural extension of linear filtering. It represents a higher-order filter that prioritizes recent data (via WMA) but applies a second pass to iron out any remaining wrinkles. It's the heavy artillery of smoothing.
|
||||
|
||||
## How It Works
|
||||
## Architecture & Physics
|
||||
|
||||
### The Core Idea
|
||||
DWMA applies a linear weight kernel (triangle window) twice.
|
||||
|
||||
Think of DWMA as a "filter of a filter."
|
||||
1. **Pass 1**: Calculate WMA of the price.
|
||||
2. **Pass 2**: Calculate WMA of the result from Pass 1.
|
||||
|
||||
1. First, you calculate a standard WMA of the price. This removes high-frequency noise but leaves some jaggedness.
|
||||
2. Then, you calculate a WMA of that *first* WMA. This polishes the curve, resulting in a very smooth line that clearly defines the underlying trend direction.
|
||||
The effective window size is roughly $2 \times \text{Period}$, and the lag is cumulative. This is not for high-frequency scalping; this is for determining if the market is actually bullish or just having a manic episode.
|
||||
|
||||
### Mathematical Foundation
|
||||
### Zero-Allocation Design
|
||||
|
||||
1. Calculate the first WMA: $WMA_1 = WMA(Price, n)$
|
||||
2. Calculate the second WMA: $DWMA = WMA(WMA_1, n)$
|
||||
Our implementation composes two `Wma` instances.
|
||||
|
||||
Where $n$ is the period length.
|
||||
- **Composition**: We wrap two `Wma` objects.
|
||||
- **Efficiency**: Since `Wma` is O(1) (using a running sum algorithm), DWMA is also O(1).
|
||||
- **Memory**: No massive arrays are allocated; just the internal buffers of the two WMAs.
|
||||
|
||||
Because WMA uses linear weighting (triangle weights), applying it twice creates a weighting structure that resembles a bell curve (Gaussian-like), giving the most weight to the center of the lookback window and tapering off smoothly at both ends.
|
||||
## Mathematical Foundation
|
||||
|
||||
### Implementation Details
|
||||
$$ \text{WMA}_1 = \text{WMA}(P, N) $$
|
||||
|
||||
Our implementation wraps two instances of the `Wma` class.
|
||||
$$ \text{DWMA} = \text{WMA}(\text{WMA}_1, N) $$
|
||||
|
||||
- **Complexity:** O(1) per update (since WMA is O(1)).
|
||||
- **Memory:** O(period) to store the buffers for both internal WMAs.
|
||||
- **Warmup:** Requires roughly $2 \times period$ bars to fully stabilize.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Default | Purpose | Adjustment Guidelines |
|
||||
|-----------|---------|---------|----------------------|
|
||||
| Period | 14 | Lookback window | Shorter = Faster trend detection; Longer = Major trend identification |
|
||||
|
||||
**Configuration note:** A DWMA(10) will have roughly the same lag as a WMA(15-20) but will be significantly smoother.
|
||||
The weight profile of a single WMA is triangular. The weight profile of a DWMA approaches a Gaussian-like shape (central limit theorem in action), but heavily skewed towards recent data due to the WMA's linear weighting.
|
||||
|
||||
## Performance Profile
|
||||
|
||||
| Operation | Complexity | Description |
|
||||
|-----------|------------|-------------------|
|
||||
| Streaming update | O(1) | Two O(1) WMA updates |
|
||||
| Bar correction | O(1) | Efficient state rollback |
|
||||
| Batch processing | O(N) | Two passes over the data |
|
||||
| Memory footprint | O(period) | Two RingBuffers |
|
||||
Despite the double pass, it remains O(1) thanks to the optimized WMA implementation.
|
||||
|
||||
## Interpretation
|
||||
| Metric | Complexity | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **Throughput** | High | 2x cost of WMA |
|
||||
| **Complexity** | O(1) | Constant time update |
|
||||
| **Accuracy** | 8/10 | Very smooth trend representation |
|
||||
| **Timeliness** | 4/10 | Double smoothing adds significant lag |
|
||||
| **Overshoot** | 10/10 | No overshoot (series of WMAs) |
|
||||
| **Smoothness** | 9/10 | Very smooth, ideal for noise reduction |
|
||||
|
||||
### Trading Signals
|
||||
## Validation
|
||||
|
||||
#### Trend Identification
|
||||
Validated against custom reference implementations (Excel/Python).
|
||||
|
||||
- **Major Trend:** DWMA is excellent for defining the "background" trend. If price is above DWMA, the bias is bullish.
|
||||
- **Support/Resistance:** Due to its smoothness, DWMA often acts as dynamic support in uptrends and resistance in downtrends.
|
||||
| Provider | Error Tolerance | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **Manual Calc** | $10^{-9}$ | Verified against recursive WMA calculation |
|
||||
|
||||
#### Crossovers
|
||||
### Common Pitfalls
|
||||
|
||||
- **Price Crossover:** Price crossing DWMA signals a major trend change.
|
||||
- **DWMA/WMA Crossover:** Using a WMA(14) crossing a DWMA(14) creates a signal similar to MACD but directly on the price chart.
|
||||
|
||||
### When It Works Best
|
||||
|
||||
- **Long-Term Trends:** DWMA filters out the "noise" of daily volatility, letting you stay in a trade during minor pullbacks.
|
||||
- **Visual Clarity:** It produces a very clean line on the chart, reducing visual clutter.
|
||||
|
||||
### When It Struggles
|
||||
|
||||
- **Scalping:** The double smoothing introduces too much lag for very short-term trading.
|
||||
- **Reversals:** DWMA will be slow to recognize a sharp V-bottom or V-top reversal.
|
||||
|
||||
## Comparison: DWMA vs WMA vs SMA
|
||||
|
||||
| Aspect | WMA | DWMA | SMA |
|
||||
|--------|-----|------|-----|
|
||||
| **Lag** | Moderate | High | High |
|
||||
| **Smoothness** | Moderate | Very High | High |
|
||||
| **Responsiveness** | Moderate | Low | Low |
|
||||
| **Weighting** | Linear | Bell-curve-like | Equal |
|
||||
|
||||
**Summary:** Use DWMA when smoothness is your priority and you are willing to accept some lag to avoid false signals.
|
||||
|
||||
## Architecture Notes
|
||||
|
||||
This implementation makes specific trade-offs:
|
||||
|
||||
### Choice: Composition
|
||||
|
||||
- **Alternative:** Implement a single "Double Weighted" formula.
|
||||
- **Trade-off:** Slight function call overhead.
|
||||
- **Rationale:** Reusing the optimized `Wma` class ensures correctness and benefits from any future optimizations to the base WMA (like SIMD).
|
||||
|
||||
### Choice: Temporary Buffer for Batch
|
||||
|
||||
- **Alternative:** Single pass calculation.
|
||||
- **Trade-off:** Memory allocation for intermediate results.
|
||||
- **Rationale:** Calculating DWMA in a single pass is mathematically complex and hard to vectorize. Two optimized WMA passes are faster and easier to maintain.
|
||||
|
||||
## References
|
||||
|
||||
- Kaufman, Perry J. "Trading Systems and Methods." Wiley, 2013.
|
||||
|
||||
## C# Usage
|
||||
|
||||
### Streaming Updates (Single Instance)
|
||||
|
||||
```csharp
|
||||
using QuanTAlib;
|
||||
|
||||
var dwma = new Dwma(period: 14);
|
||||
|
||||
// Process each new bar
|
||||
TValue result = dwma.Update(new TValue(timestamp, closePrice));
|
||||
Console.WriteLine($"DWMA: {result.Value:F2}");
|
||||
|
||||
// Check if buffer is full
|
||||
if (dwma.IsHot)
|
||||
{
|
||||
// Indicator is fully initialized
|
||||
}
|
||||
```
|
||||
|
||||
### Batch Processing (Historical Data)
|
||||
|
||||
```csharp
|
||||
// TSeries API
|
||||
TSeries prices = ...;
|
||||
TSeries dwmaValues = Dwma.Batch(prices, period: 14);
|
||||
|
||||
// Span API (High Performance)
|
||||
double[] prices = new double[1000];
|
||||
double[] output = new double[1000];
|
||||
Dwma.Calculate(prices.AsSpan(), output.AsSpan(), period: 14);
|
||||
```
|
||||
|
||||
### Bar Correction (isNew Parameter)
|
||||
|
||||
```csharp
|
||||
var dwma = new Dwma(14);
|
||||
|
||||
// New bar
|
||||
dwma.Update(new TValue(time, 100), isNew: true);
|
||||
|
||||
// Intra-bar update
|
||||
dwma.Update(new TValue(time, 101), isNew: false); // Replaces 100 with 101
|
||||
```
|
||||
1. **Lag**: This indicator lags. A lot. Do not use it for entry signals on tight timeframes. Use it for trend filtering (e.g., "only buy if price > DWMA").
|
||||
2. **Warmup**: It takes roughly $2 \times N$ bars to produce valid data.
|
||||
3. **Confusion with DEMA**: DEMA = Fast, DWMA = Smooth. Do not mix them up.
|
||||
|
||||
Reference in New Issue
Block a user