Add new moving average implementations: LTMA, MCNMA, NLMA, NMA, NYQMA, RAIN, and TRAMA

- LTMA (Linear Trend Moving Average): Introduces a predictive moving average using dual cascaded EMAs for trend estimation.
- MCNMA (McNicholl EMA): Implements a zero-lag TEMA using a cascaded EMA structure for enhanced responsiveness.
- NLMA (Non-Lag Moving Average): Utilizes a damped cosine kernel to achieve reduced lag in moving averages.
- NMA (Natural Moving Average): Adapts smoothing based on volatility profiles using a square-root kernel.
- NYQMA (Nyquist Moving Average): Applies the Nyquist-Shannon theorem to prevent aliasing in cascaded moving averages.
- RAIN (Rainbow Moving Average): Combines multiple SMA layers with weighted averages for multi-scale smoothing.
- TRAMA (Trend Regularity Adaptive Moving Average): Adapts smoothing based on the frequency of new highs and lows in price data.
This commit is contained in:
Miha Kralj
2026-02-20 21:40:32 -08:00
parent cbeefc9d64
commit 90d5638008
121 changed files with 9595 additions and 6315 deletions
+60 -111
View File
@@ -2,142 +2,91 @@
> "The average candlestick body reveals the market's true conviction."
Developed by Tushar Chande, the Qstick indicator measures the average difference between closing and opening prices over a lookback period. It quantifies whether bars are predominantly bullish (closing above opens) or bearish (closing below opens), providing a smoothed view of candlestick body direction and magnitude.
The Qstick indicator, developed by Tushar Chande, computes a moving average of the close-minus-open difference over a lookback period, quantifying whether bars are predominantly bullish or bearish. Positive values indicate closes above opens (buying pressure); negative values indicate closes below opens (selling pressure). It supports both SMA (O(N) space via ring buffer) and EMA (O(1) space) smoothing modes and requires TBar input for open/close access.
## Historical Context
Tushar Chande introduced the Qstick as part of his work on candlestick pattern quantification in the early 1990s. While traditional candlestick analysis relies on visual pattern recognition, Qstick provides a numerical measure that can be systematically tracked and used for algorithmic trading.
Tushar Chande introduced Qstick as part of his candlestick quantification work in *The New Technical Trader* (1994, co-authored with Stanley Kroll). Traditional candlestick analysis relies on visual pattern recognition; Qstick reduces bar body direction and magnitude to a single continuous number suitable for systematic tracking. The indicator addresses a specific gap: close-to-close momentum indicators miss intrabar dynamics captured by the open-to-close differential. The name "Qstick" reflects the "quick stick" reading of candlestick conviction.
The indicator addresses a fundamental question: "On average, are prices closing higher or lower than they open?" This simple metric captures intrabar momentum that other indicators measuring close-to-close changes may miss.
## Architecture & Physics
## Architecture
### 1. Body Difference
### 1. Body Difference Calculation
$$d_t = \text{Close}_t - \text{Open}_t$$
The core input is the difference between close and open:
```
diff = Close - Open
```
- **Positive diff**: Bullish bar (white/green candle)
- **Negative diff**: Bearish bar (black/red candle)
- **Zero diff**: Doji (open equals close)
Positive $d_t$ represents a bullish bar (close above open), negative represents bearish, zero represents a doji.
### 2. Moving Average Smoothing
The raw differences are smoothed using either SMA or EMA:
**SMA mode:** Maintains a ring buffer of $N$ differences and a running sum for O(1) incremental updates:
**SMA Mode:**
$$\text{Qstick} = \frac{1}{n} \sum_{i=0}^{n-1} (Close_i - Open_i)$$
$$\text{Qstick}_t = \frac{1}{N} \sum_{i=0}^{N-1} d_{t-i}$$
**EMA Mode:**
$$\text{Qstick}_t = \alpha \cdot diff_t + (1 - \alpha) \cdot \text{Qstick}_{t-1}$$
**EMA mode:** Standard recursive filter with decay $\alpha = 2/(N+1)$:
where $\alpha = \frac{2}{period + 1}$
$$\text{Qstick}_t = \alpha \cdot d_t + (1 - \alpha) \cdot \text{Qstick}_{t-1}$$
### 3. State Management
EMA mode uses O(1) space but weights recent bars more heavily than SMA.
For real-time bar correction (isNew=false), the indicator maintains:
- `_sum` / `_savedSum`: Running sum for SMA
- `_emaValue` / `_savedEmaValue`: Current EMA value
- `_count` / `_savedCount`: Bar count for warmup
### 3. Complexity
## Parameters
| Parameter | Type | Default | Valid Range | Description |
|-----------|------|---------|-------------|-------------|
| `period` | int | 14 | ≥ 1 | Lookback period for moving average |
| `useEma` | bool | false | true/false | Use EMA (true) or SMA (false) |
| Metric | SMA Mode | EMA Mode |
|:-------|:---------|:---------|
| Time | O(1) per bar | O(1) per bar |
| Space | O(N) ring buffer | O(1) |
| Ops | 1 add, 1 sub, 1 div | 1 sub, 1 mul, 1 FMA |
## Mathematical Foundation
### Formula
### Parameters
| Parameter | Type | Default | Constraint | Description |
|:----------|:-----|:--------|:-----------|:------------|
| period | int | 14 | > 0 | Lookback period for moving average |
| useEma | bool | false | — | Use EMA (true) or SMA (false) |
### Pseudo-code
```
Qstick = MA(Close - Open, period)
QSTICK(bar, period=14, useEma=false):
diff = bar.Close - bar.Open
if useEma:
// EMA mode
alpha = 2.0 / (period + 1)
if count == 0:
ema_val = diff
else:
ema_val = FMA(alpha, diff - ema_val, ema_val) // alpha*(diff-ema)+ema
result = ema_val
else:
// SMA mode with ring buffer
if buffer is full:
running_sum -= buffer.oldest
buffer.add(diff)
running_sum += diff
result = running_sum / min(count, period)
return result
```
### Interpretation
### Zero-Crossing Interpretation
| Qstick Value | Market Condition |
|--------------|------------------|
| > 0 | Bullish momentum (closes above opens) |
| < 0 | Bearish momentum (closes below opens) |
| = 0 | Neutral (balanced open/close) |
| Rising | Increasing bullish pressure |
| Falling | Increasing bearish pressure |
| Condition | Meaning |
|:----------|:--------|
| Qstick > 0 | Closes above opens dominate (net buying pressure) |
| Qstick < 0 | Closes below opens dominate (net selling pressure) |
| Qstick crosses zero | Shift in intrabar momentum direction |
| Qstick rising | Increasing bullish pressure regardless of sign |
| Qstick falling | Increasing bearish pressure regardless of sign |
### Signal Generation
### Scale Dependence
- **Buy Signal**: Qstick crosses above zero
- **Sell Signal**: Qstick crosses below zero
- **Divergence**: Price making new highs while Qstick making lower highs suggests weakening momentum
Qstick values are in absolute price units, not normalized. Cross-instrument comparison requires normalization (e.g., divide by ATR or price level). Short periods (5-8) suit trading signals; longer periods (20+) suit trend identification.
## Performance Profile
## Resources
### Operation Count (Streaming Mode)
| Operation | SMA Mode | EMA Mode |
|-----------|----------|----------|
| ADD/SUB | 3 | 2 |
| MUL | 0 | 1 |
| DIV | 1 | 0 |
| FMA | 0 | 1 |
| Memory | O(period) | O(1) |
### Complexity
- **Time**: O(1) per bar for both modes
- **Space**: O(period) for SMA, O(1) for EMA
### Quality Metrics
| Metric | Score | Notes |
|--------|-------|-------|
| Accuracy | 10/10 | Exact calculation |
| Timeliness | 8/10 | Lag proportional to period |
| Overshoot | 2/10 | Smooth, no overshoot |
| Smoothness | 8/10 | SMA smoother than EMA |
## Validation
| Library | Status | Notes |
|---------|--------|-------|
| TA-Lib | ✓ | Not available (implement locally) |
| Skender | ✓ | Validated against Qstick |
| OoplesFinance | ✓ | Validated |
## Common Pitfalls
1. **Ignoring Volume**: Qstick weights all bars equally; consider volume-weighted variants for more accuracy
2. **Range Dependence**: Absolute values depend on price scale; normalize for comparison across instruments
3. **Period Selection**: Short periods (5-8) for trading signals; long periods (20+) for trend identification
4. **Gap Sensitivity**: Large gaps (open ≠ previous close) can distort readings
5. **Flat Markets**: Near-zero readings indicate indecision, not necessarily reversal
## Usage Example
```csharp
// Create Qstick with 14-period SMA
var qstick = new Qstick(14);
// Update with bar data
foreach (var bar in bars)
{
var result = qstick.Update(bar);
if (qstick.IsHot)
{
Console.WriteLine($"Qstick: {result.Value:F4}");
}
}
// Or use EMA mode
var qstickEma = new Qstick(14, useEma: true);
```
## References
1. Chande, T. S. (1994). *The New Technical Trader*. John Wiley & Sons.
2. Chande, T. S., & Kroll, S. (1994). *Beyond Technical Analysis*. John Wiley & Sons.
3. Kirkpatrick, C. D., & Dahlquist, J. R. (2015). *Technical Analysis: The Complete Resource for Financial Market Technicians*. FT Press.
- Chande, T. S. & Kroll, S. (1994). *The New Technical Trader*. John Wiley and Sons.
- Kirkpatrick, C. D. & Dahlquist, J. R. (2015). *Technical Analysis: The Complete Resource for Financial Market Technicians*. FT Press.