mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-22 20:48:04 +00:00
feat: Enhance volume indicators with ADOSC and SSF implementation and validation
This commit is contained in:
+31
-103
@@ -1,128 +1,56 @@
|
||||
# TRIMA: Triangular Moving Average
|
||||
|
||||
## What It Does
|
||||
> "The weighted blanket of moving averages. It doesn't care where the price is going right now; it cares where the price feels most comfortable."
|
||||
|
||||
The Triangular Moving Average (TRIMA) is a weighted moving average where the weights are assigned in a triangular pattern. The most recent data and the oldest data carry the least weight, while the data in the middle of the period carries the most weight. This creates a double-smoothing effect that produces a line much smoother than a Simple Moving Average (SMA) or Exponential Moving Average (EMA), making it ideal for identifying the primary trend without the distraction of short-term noise.
|
||||
The Triangular Moving Average (TRIMA) places the majority of its weight on the middle of the data window, tapering off linearly towards the ends. This creates a triangular weight distribution (hence the name). It is mathematically equivalent to a double-smoothed SMA.
|
||||
|
||||
## Historical Context
|
||||
|
||||
While the concept of triangular weighting has roots in statistical signal processing, it was popularized in technical analysis as a way to solve the "whipsaw" problem of SMAs. By de-emphasizing the most recent data (which is often noisy), TRIMA focuses on the "consensus" of value over the period.
|
||||
TRIMA has been a staple in cycle analysis. By double-smoothing the data, it effectively removes high-frequency noise, making it ideal for identifying dominant market cycles. However, this smoothness comes at the cost of significant lag.
|
||||
|
||||
## How It Works
|
||||
## Architecture & Physics
|
||||
|
||||
### The Core Idea
|
||||
TRIMA is implemented as a cascade of two Simple Moving Averages.
|
||||
$$ TRIMA = SMA(SMA(Price, P_1), P_2) $$
|
||||
|
||||
TRIMA is mathematically equivalent to a "double SMA."
|
||||
Where $P_1$ and $P_2$ are roughly half the total period.
|
||||
|
||||
- **SMA:** Average of $N$ prices.
|
||||
- **TRIMA:** Average of an Average. Specifically, an SMA of period $X$ applied to an SMA of period $X$.
|
||||
### The Weight Distribution
|
||||
|
||||
Because it averages an average, it is extremely smooth. However, this double smoothing comes at the cost of increased lag. It will turn significantly later than an EMA or SMA.
|
||||
An SMA has a rectangular weight distribution (all weights equal). A WMA has a linear distribution (heaviest at the end). TRIMA has a triangular distribution (heaviest in the center).
|
||||
|
||||
### Mathematical Foundation
|
||||
## Mathematical Foundation
|
||||
|
||||
The weights form a triangle. For a period of 5:
|
||||
### 1. Period Splitting
|
||||
|
||||
- Weights: 1, 2, 3, 2, 1
|
||||
- Sum of weights: $1+2+3+2+1 = 9$
|
||||
$$ P_1 = \lfloor \frac{N}{2} \rfloor + 1 $$
|
||||
$$ P_2 = \lceil \frac{N+1}{2} \rceil $$
|
||||
|
||||
Formula:
|
||||
$$ TRIMA = \frac{\sum (Price_i \times Weight_i)}{\sum Weights} $$
|
||||
### 2. The Cascade
|
||||
|
||||
Equivalent Calculation (Double SMA):
|
||||
$$ TRIMA(N) \approx SMA(SMA(Price, \lceil N/2 \rceil), \lfloor N/2 \rfloor + 1) $$
|
||||
|
||||
### Implementation Details
|
||||
|
||||
Our implementation uses the Double SMA method for O(1) efficiency.
|
||||
|
||||
- **Complexity:** O(1) per update (two sliding window sums).
|
||||
- **Stability:** Inherits the stability of SMA.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Default | Purpose | Adjustment Guidelines |
|
||||
|-----------|---------|---------|----------------------|
|
||||
| Period | 14 | Lookback window | Standard lookback. |
|
||||
$$ TRIMA = SMA(SMA(Price, P_1), P_2) $$
|
||||
|
||||
## Performance Profile
|
||||
|
||||
| Operation | Complexity | Description |
|
||||
|-----------|------------|-------------------|
|
||||
| Streaming update | O(1) | Two sliding window sums |
|
||||
| Bar correction | O(1) | Efficient state rollback |
|
||||
| Batch processing | O(N) | Single pass through data |
|
||||
| Memory footprint | O(period) | RingBuffers for the two internal SMAs |
|
||||
### Zero-Allocation Design
|
||||
|
||||
## Interpretation
|
||||
TRIMA relies on two internal `Sma` instances, which use pre-allocated `RingBuffer`s. The chaining of updates is done via value passing, ensuring no intermediate objects are created on the heap.
|
||||
|
||||
### Trading Signals
|
||||
| Metric | Score | Notes |
|
||||
| :--- | :--- | :--- |
|
||||
| **Throughput** | High | 2 SMAs |
|
||||
| **Complexity** | O(1) | Constant time update |
|
||||
| **Accuracy** | 6/10 | Heavily smoothed, loses detail |
|
||||
| **Timeliness** | 4/10 | Significant lag (Lag ≈ N/2 + N/2) |
|
||||
| **Overshoot** | 9/10 | Very stable, minimal overshoot |
|
||||
| **Smoothness** | 9/10 | Triangular weighting removes high freq noise |
|
||||
|
||||
#### Trend Identification
|
||||
## Validation
|
||||
|
||||
- **Primary Trend:** TRIMA is excellent for visualizing the "major" trend. If TRIMA is rising, the long-term direction is up, regardless of short-term chops.
|
||||
Validated against TA-Lib (`TA_TRIMA`) and Skender.Stock.Indicators.
|
||||
|
||||
### When It Works Best
|
||||
### Common Pitfalls
|
||||
|
||||
- **Visual Clarity:** Traders often use TRIMA not for signals, but to declutter charts and see the underlying market structure.
|
||||
|
||||
### When It Struggles
|
||||
|
||||
- **Timing Entries:** Due to its significant lag, TRIMA is poor for timing entries or exits. It is a lagging indicator, not a leading one.
|
||||
|
||||
## Architecture Notes
|
||||
|
||||
This implementation makes specific trade-offs:
|
||||
|
||||
### Choice: Double SMA Composition
|
||||
|
||||
- **Implementation:** Composed of two `Sma` objects.
|
||||
- **Rationale:** This is mathematically equivalent to the weighted sum method but allows us to reuse the O(1) optimization of the `Sma` class.
|
||||
|
||||
## References
|
||||
|
||||
- Merrill, Arthur A. "Filtered Waves." *Technical Analysis of Stocks & Commodities*.
|
||||
|
||||
## C# Usage
|
||||
|
||||
### Streaming Updates (Single Instance)
|
||||
|
||||
```csharp
|
||||
using QuanTAlib;
|
||||
|
||||
var trima = new Trima(period: 14);
|
||||
|
||||
// Process each new bar
|
||||
TValue result = trima.Update(new TValue(timestamp, closePrice));
|
||||
Console.WriteLine($"TRIMA: {result.Value:F2}");
|
||||
|
||||
// Check if buffer is full
|
||||
if (trima.IsHot)
|
||||
{
|
||||
// Indicator is fully initialized
|
||||
}
|
||||
```
|
||||
|
||||
### Batch Processing (Historical Data)
|
||||
|
||||
```csharp
|
||||
// TSeries API
|
||||
TSeries prices = ...;
|
||||
TSeries trimaValues = Trima.Batch(prices, period: 14);
|
||||
|
||||
// Span API (High Performance)
|
||||
double[] prices = new double[1000];
|
||||
double[] output = new double[1000];
|
||||
Trima.Calculate(prices.AsSpan(), output.AsSpan(), period: 14);
|
||||
```
|
||||
|
||||
### Bar Correction (isNew Parameter)
|
||||
|
||||
```csharp
|
||||
var trima = new Trima(14);
|
||||
|
||||
// New bar
|
||||
trima.Update(new TValue(time, 100), isNew: true);
|
||||
|
||||
// Intra-bar update
|
||||
trima.Update(new TValue(time, 101), isNew: false); // Replaces 100 with 101
|
||||
1. **Lag**: TRIMA has more lag than SMA, EMA, or WMA. It is a lagging indicator, not a leading one.
|
||||
2. **Signal Generation**: Due to its lag, TRIMA is poor for crossover signals. It is best used for visual trend identification or as a baseline for envelopes (e.g., TMA Bands).
|
||||
3. **Even/Odd Periods**: The exact calculation of $P_1$ and $P_2$ differs slightly between implementations for even periods. QuanTAlib matches the standard definition used by TA-Lib.
|
||||
|
||||
Reference in New Issue
Block a user