mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-23 13:08:04 +00:00
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:
@@ -14,10 +14,14 @@ Oscillators fluctuate above and below a centerline or within bounded ranges. Use
|
||||
| [CFO](cfo/Cfo.md) | Chande Forecast Oscillator | Percentage difference between price and linear regression forecast. |
|
||||
| [DECO](deco/Deco.md) | Ehlers Decycler Oscillator | Dual HP bandpass isolating intermediate-frequency market cycles. |
|
||||
| [DPO](dpo/Dpo.md) | Detrended Price Oscillator | Removes trend via displaced SMA. Reveals cycles. |
|
||||
| [ER](er/Er.md) | Efficiency Ratio | Measures directional efficiency. Net movement / total path length. |
|
||||
| [ERI](eri/Eri.md) | Elder Ray Index | Separates bull and bear power relative to EMA. |
|
||||
| [FISHER](fisher/Fisher.md) | Ehlers Fisher Transform | Converts prices to Gaussian distribution. Sharp reversals. |
|
||||
| [INERTIA](inertia/Inertia.md) | Inertia | Linear regression residual. Raw deviation from trend forecast. |
|
||||
| [KDJ](kdj/Kdj.md) | KDJ Indicator | Enhanced Stochastic. J = 3K - 2D provides leading signal. |
|
||||
| [KRI](kri/Kri.md) | Kairi Relative Index | Percentage deviation of price from SMA. Overbought/oversold. |
|
||||
| [PGO](pgo/Pgo.md) | Pretty Good Oscillator | Distance from SMA normalized by ATR. Units: ATR multiples. |
|
||||
| [PSL](psl/Psl.md) | Psychological Line | Ratio of up periods to total periods. Crowd sentiment gauge. |
|
||||
| [SMI](smi/Smi.md) | Stochastic Momentum Index | Distance from range midpoint. More sensitive than classic Stochastic. |
|
||||
| [STOCH](stoch/Stoch.md) | Stochastic Oscillator | Close position within N-period high-low range. Classic overbought/oversold. |
|
||||
| [STOCHF](stochf/Stochf.md) | Stochastic Fast | Unsmoothed Stochastic. Faster but noisier. |
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# BRAR: Atmosphere and Buying Ratio Indicator
|
||||
|
||||
BRAR is a dual-output sentiment oscillator from East Asian technical analysis that decomposes intrabar price dynamics into two independent ratios: AR (Atmosphere Ratio) measuring the relationship between opening price and intrabar range, and BR (Buying Ratio) measuring buying pressure relative to the previous close. The indicator produces two lines oscillating around 100, where AR above 100 indicates bullish intrabar sentiment and BR above 100 indicates net buying pressure over the lookback window.
|
||||
|
||||
## Historical Context
|
||||
|
||||
BRAR originated in Japanese and Taiwanese equity analysis during the 1980s, where it became a standard feature of domestic charting software before gaining broader recognition in quantitative trading. The indicator belongs to a class of OHLC decomposition oscillators that extract directional information from the relationship between open, high, low, and close prices rather than from close-only series. Unlike Western momentum oscillators that typically operate on a single price input, BRAR requires full OHLC bars, making it structurally similar to Williams %R or Stochastic but with fundamentally different decomposition logic. The "atmosphere" terminology reflects the Japanese market philosophy that open-to-range dynamics capture collective market mood, while the "buying ratio" component captures institutional accumulation pressure relative to settlement prices.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Dual-Component Design
|
||||
|
||||
BRAR separates intrabar dynamics into two independent measurements:
|
||||
|
||||
1. **AR (Atmosphere Ratio):** Measures the open's position within the intrabar range. Numerator accumulates $(H_i - O_i)$ over $n$ bars (upside from open), denominator accumulates $(O_i - L_i)$ (downside from open). The ratio, scaled by 100, indicates whether prices tend to rally or decline from the opening price.
|
||||
|
||||
2. **BR (Buying Ratio):** Measures buying pressure relative to the previous close. Numerator accumulates $\max(0, H_i - C_{i-1})$ (gains above prior close), denominator accumulates $\max(0, C_{i-1} - L_i)$ (drops below prior close). The ratio captures net accumulation vs distribution.
|
||||
|
||||
### Running Sum Architecture
|
||||
|
||||
Both ratios maintain four independent circular buffers with running sums for O(1) streaming updates. When buffer is full, the oldest bar's contribution is subtracted before the new bar's contribution is added. The first close comparison uses open as a fallback when no previous close exists.
|
||||
|
||||
### Defensive Division
|
||||
|
||||
Both AR and BR return 0.0 when their respective denominators are zero, preventing division-by-zero in flat markets where open equals low (AR) or prior close equals low with no upside (BR).
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
Given OHLC bars $(O_i, H_i, L_i, C_i)$ and lookback period $n$:
|
||||
|
||||
**AR (Atmosphere Ratio):**
|
||||
|
||||
$$AR = \frac{\sum_{i=1}^{n} (H_i - O_i)}{\sum_{i=1}^{n} (O_i - L_i)} \times 100$$
|
||||
|
||||
**BR (Buying Ratio):**
|
||||
|
||||
$$BR = \frac{\sum_{i=1}^{n} \max(0,\; H_i - C_{i-1})}{\sum_{i=1}^{n} \max(0,\; C_{i-1} - L_i)} \times 100$$
|
||||
|
||||
**Streaming update** (per bar, O(1)):
|
||||
|
||||
```text
|
||||
arNum_new = arNum_old - oldest_arNum + (H - O)
|
||||
arDen_new = arDen_old - oldest_arDen + (O - L)
|
||||
brNum_new = brNum_old - oldest_brNum + max(0, H - prevClose)
|
||||
brDen_new = brDen_old - oldest_brDen + max(0, prevClose - L)
|
||||
|
||||
AR = (arDen ≠ 0) ? (arNum / arDen) × 100 : 0
|
||||
BR = (brDen ≠ 0) ? (brNum / brDen) × 100 : 0
|
||||
```
|
||||
|
||||
**Interpretation reference levels:**
|
||||
|
||||
- AR > 100, BR > 100: Strong bullish sentiment
|
||||
- AR < 100, BR < 100: Strong bearish sentiment
|
||||
- AR and BR divergence: Potential trend reversal signal
|
||||
|
||||
**Default parameters:** period = 26 (approximately one trading month).
|
||||
|
||||
## Resources
|
||||
|
||||
- Japanese Technical Analysis references on AR/BR sentiment indicators
|
||||
- Taiwan Stock Exchange historical charting methodology
|
||||
- PineScript reference: [`brar.pine`](brar.pine)
|
||||
@@ -0,0 +1,59 @@
|
||||
# COPPOCK: Coppock Curve
|
||||
|
||||
The Coppock Curve is a long-term momentum oscillator that applies a Weighted Moving Average to the sum of two Rate of Change calculations at different lookback periods. Originally designed for monthly charts to identify major market bottoms, it produces a single oscillating line where zero-line crossovers from below signal long-term buying opportunities. The dual-ROC architecture captures both intermediate and longer-term momentum dynamics in a single smoothed output.
|
||||
|
||||
## Historical Context
|
||||
|
||||
Edwin Sedgwick Coppock introduced this indicator in 1962 in *Barron's* magazine, originally calling it the "Trendex Model." Coppock, an economist by training, reportedly derived the 11-month and 14-month ROC periods from Episcopal clergy who told him the average mourning period for a bereavement was 11 to 14 months. He reasoned that market bottoms represented a similar psychological recovery period. The indicator was designed exclusively as a buy signal generator on monthly S&P 500 data, with zero-line crossovers from negative territory signaling major market lows. Later practitioners adapted it to weekly and daily timeframes with scaled parameters, though Coppock himself considered only the monthly application valid. The 10-period WMA smoothing was chosen to filter out intermediate noise while preserving the timing of major turning points.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Three-Stage Pipeline
|
||||
|
||||
The Coppock Curve processes data through a sequential pipeline:
|
||||
|
||||
1. **ROC Stage:** Two independent Rate of Change calculations at different lookback periods extract momentum at two time horizons. Each ROC measures the percentage price change over its respective window: $\text{ROC}(n) = \frac{C_t - C_{t-n}}{C_{t-n}} \times 100$.
|
||||
|
||||
2. **Summation Stage:** The two ROC values are added directly, creating a composite momentum measure that captures both intermediate and long-term price velocity.
|
||||
|
||||
3. **WMA Stage:** A Weighted Moving Average smooths the combined ROC, using linearly increasing weights that emphasize recent composite momentum while suppressing noise. The WMA implementation uses the dual running sum technique for O(1) per-bar updates.
|
||||
|
||||
### Circular Buffer Design
|
||||
|
||||
The ROC stage stores historical prices in a circular buffer sized to the maximum of the two ROC periods. The WMA stage maintains its own circular buffer with running weighted and unweighted sums, enabling constant-time updates without recomputation.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
Given source series $x_t$, long ROC period $L$, short ROC period $S$, and WMA period $W$:
|
||||
|
||||
**Rate of Change:**
|
||||
|
||||
$$ROC_L(t) = \frac{x_t - x_{t-L}}{x_{t-L}} \times 100, \quad ROC_S(t) = \frac{x_t - x_{t-S}}{x_{t-S}} \times 100$$
|
||||
|
||||
**Combined ROC:**
|
||||
|
||||
$$R_t = ROC_L(t) + ROC_S(t)$$
|
||||
|
||||
**Weighted Moving Average of combined ROC:**
|
||||
|
||||
$$\text{Coppock}(t) = \frac{\sum_{i=0}^{W-1} (W - i) \cdot R_{t-i}}{\sum_{i=0}^{W-1} (W - i)}$$
|
||||
|
||||
The denominator equals $\frac{W(W+1)}{2}$.
|
||||
|
||||
**O(1) WMA streaming update** using dual running sums:
|
||||
|
||||
```text
|
||||
On new value R entering buffer (oldest R_old exits):
|
||||
plainSum = plainSum - R_old + R
|
||||
weightedSum = weightedSum - plainSum_old + W × R
|
||||
norm = W × (W + 1) / 2
|
||||
Coppock = weightedSum / norm
|
||||
```
|
||||
|
||||
**Default parameters:** longRoc = 14, shortRoc = 11, wmaPeriod = 10 (original monthly values).
|
||||
|
||||
## Resources
|
||||
|
||||
- Coppock, E.S.C. (1962). "A Guide to the Use of Coppock Curve." *Barron's*
|
||||
- Kirkpatrick, C. & Dahlquist, J. (2010). *Technical Analysis*, Chapter 15: Momentum
|
||||
- PineScript reference: [`coppock.pine`](coppock.pine)
|
||||
@@ -0,0 +1,63 @@
|
||||
# CRSI: Connors RSI
|
||||
|
||||
Connors RSI is a composite momentum oscillator that combines three independent measurements of price behavior into a single bounded (0-100) output: a short-term RSI of price, an RSI of the consecutive up/down streak length, and a percentile rank of the current rate of change within its recent history. The equal-weighted average of these three components produces a mean-reverting oscillator where extreme readings (above 90 or below 10) identify statistically overbought or oversold conditions with higher reliability than single-component RSI alone.
|
||||
|
||||
## Historical Context
|
||||
|
||||
Larry Connors and Cesar Alvarez introduced Connors RSI in their 2012 publication, building on Connors' earlier research into short-term mean reversion strategies. The indicator addressed a recognized weakness of standard RSI: its tendency to remain in overbought or oversold territory during strong trends without providing actionable reversal signals. By combining three orthogonal measurements of price behavior, each capturing a different aspect of momentum, CRSI reduces the false signal rate inherent in any single oscillator. The streak RSI component was particularly novel, converting the categorical information of consecutive up/down days into a continuous oscillator via a second RSI application. The percent rank component adds a non-parametric statistical dimension that is robust to distribution assumptions. Connors' backtesting showed the composite outperformed standard RSI for mean-reversion entry timing on equity indices and ETFs.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Three-Component Pipeline
|
||||
|
||||
CRSI combines three independent calculations with equal weighting:
|
||||
|
||||
1. **Price RSI** (Component 1): Standard Wilder RSI with exponential smoothing ($\alpha = 1/\text{rsiPeriod}$) applied to the source series. Uses warmup compensation via the decaying exponential $e = \beta^n$ to correct for initial bias, producing valid output from bar 1.
|
||||
|
||||
2. **Streak RSI** (Component 2): First computes a consecutive streak counter (positive for up-closes, negative for down-closes, zero for unchanged), then applies the same Wilder RSI to the streak series. This converts run-length information into a bounded oscillator.
|
||||
|
||||
3. **Percent Rank** (Component 3): Computes 1-bar ROC, stores in a circular buffer, then counts what percentage of historical ROC values are less than or equal to the current ROC. This is a non-parametric ranking that is distribution-free.
|
||||
|
||||
### Warmup Compensation
|
||||
|
||||
Both RSI stages use the "section 2" warmup pattern: track $e = \beta^n$ and apply correction factor $c = 1/(1 - e)$ to the raw exponential averages until $e$ drops below $10^{-10}$. This eliminates the startup bias that plagues naive EMA initialization.
|
||||
|
||||
### Final Composition
|
||||
|
||||
The three components are averaged and clamped to $[0, 100]$:
|
||||
|
||||
$$\text{CRSI} = \text{clamp}\!\left(\frac{\text{PriceRSI} + \text{StreakRSI} + \text{PctRank}}{3}, 0, 100\right)$$
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
**Component 1: Price RSI** with Wilder smoothing ($\alpha = 1/p_1$):
|
||||
|
||||
$$\overline{G}_t = \alpha \cdot \max(\Delta x_t, 0) + (1-\alpha) \cdot \overline{G}_{t-1}$$
|
||||
|
||||
$$\overline{L}_t = \alpha \cdot \max(-\Delta x_t, 0) + (1-\alpha) \cdot \overline{L}_{t-1}$$
|
||||
|
||||
$$RSI_1 = \frac{100 \cdot \overline{G}_t}{\overline{G}_t + \overline{L}_t}$$
|
||||
|
||||
**Component 2: Streak counter** then RSI:
|
||||
|
||||
$$\text{streak}_t = \begin{cases} \text{streak}_{t-1} + 1 & \text{if } x_t > x_{t-1} \text{ and streak}_{t-1} \geq 0 \\ 1 & \text{if } x_t > x_{t-1} \text{ and streak}_{t-1} < 0 \\ \text{streak}_{t-1} - 1 & \text{if } x_t < x_{t-1} \text{ and streak}_{t-1} \leq 0 \\ -1 & \text{if } x_t < x_{t-1} \text{ and streak}_{t-1} > 0 \\ 0 & \text{otherwise} \end{cases}$$
|
||||
|
||||
$$RSI_2 = \text{Wilder\_RSI}(\text{streak}_t, p_2)$$
|
||||
|
||||
**Component 3: Percent Rank** of 1-bar ROC over window $p_3$:
|
||||
|
||||
$$ROC_t = \frac{x_t - x_{t-1}}{x_{t-1}} \times 100$$
|
||||
|
||||
$$PctRank_t = \frac{|\{ROC_i : ROC_i \leq ROC_t,\; i \in \text{window}\}|}{|\text{window}|} \times 100$$
|
||||
|
||||
**Composite:**
|
||||
|
||||
$$CRSI_t = \frac{RSI_1 + RSI_2 + PctRank}{3}$$
|
||||
|
||||
**Default parameters:** rsiPeriod = 3, streakPeriod = 2, rankPeriod = 100.
|
||||
|
||||
## Resources
|
||||
|
||||
- Connors, L. & Alvarez, C. (2012). *An Introduction to ConnorsRSI*. TradingMarkets
|
||||
- Connors, L. (2009). *Short-Term Trading Strategies That Work*. TradingMarkets
|
||||
- PineScript reference: [`crsi.pine`](crsi.pine)
|
||||
@@ -0,0 +1,60 @@
|
||||
# CTI: Correlation Trend Indicator
|
||||
|
||||
The Correlation Trend Indicator computes the Pearson correlation coefficient between the price series and a linear time index over a rolling window, producing a bounded oscillator in the range $[-1, +1]$. Values near $+1$ indicate a strong linear uptrend, values near $-1$ indicate a strong linear downtrend, and values near zero indicate no linear trend relationship. The implementation achieves O(1) complexity per bar through incremental running sums that avoid recomputing the full correlation on each update.
|
||||
|
||||
## Historical Context
|
||||
|
||||
The concept of measuring trend strength via linear correlation has roots in classical statistics, where Pearson's $r$ between an ordinal time index and a dependent variable quantifies how well a linear model fits the observed data. John Ehlers popularized this approach in trading contexts, noting that correlation-based trend detection is mathematically equivalent to the R-squared goodness-of-fit measure used in linear regression. CTI differs from slope-based indicators (like TSF or LSMA) by normalizing the result to a fixed $[-1, +1]$ range regardless of price scale or volatility, making it directly comparable across instruments and timeframes. This normalization property makes CTI particularly useful as a regime filter: values above a threshold (typically $\pm 0.5$) indicate trending conditions where trend-following strategies perform well, while values near zero suggest mean-reverting or choppy conditions.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Incremental Pearson Correlation
|
||||
|
||||
The standard Pearson correlation formula requires $\Sigma x$, $\Sigma y$, $\Sigma x^2$, $\Sigma y^2$, and $\Sigma xy$ over $n$ observations. For CTI, the $x$ values are sequential integers (time indices), which means $\Sigma x$ and $\Sigma x^2$ are deterministic closed-form functions of $n$ and do not require running sums. Only the $y$-dependent sums ($\Sigma y$, $\Sigma y^2$, $\Sigma xy$) need incremental maintenance.
|
||||
|
||||
### Running Sum Trick for $\Sigma xy$
|
||||
|
||||
The key optimization is the incremental update of $\Sigma xy$. When the window slides forward by one bar:
|
||||
- The oldest value exits at what was position 0 and all remaining values shift down by one position.
|
||||
- Rather than recomputing all $x_i \cdot y_i$ products, the implementation subtracts $\Sigma y$ (which shifts all position indices down by 1) and adds $(n-1) \times y_{\text{new}}$ for the new value entering at the highest position.
|
||||
|
||||
This reduces the $O(n)$ recomputation to $O(1)$ per bar.
|
||||
|
||||
### Clamping and Edge Cases
|
||||
|
||||
The output is clamped to $[-1, +1]$ to guard against floating-point drift. When the count is less than 2, the output is `NaN` (insufficient data). When either variance term is non-positive (constant price or constant time, which cannot happen for time), the output is 0.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
Given source values $y_t$ over a window of $n$ observations with time indices $x_i = 0, 1, \ldots, n-1$:
|
||||
|
||||
**Closed-form sums for time indices:**
|
||||
|
||||
$$\Sigma_x = \frac{n(n-1)}{2}, \quad \Sigma_{x^2} = \frac{n(n-1)(2n-1)}{6}$$
|
||||
|
||||
**Running sums for price:**
|
||||
|
||||
$$\Sigma_y = \sum_{i=0}^{n-1} y_i, \quad \Sigma_{y^2} = \sum_{i=0}^{n-1} y_i^2, \quad \Sigma_{xy} = \sum_{i=0}^{n-1} i \cdot y_i$$
|
||||
|
||||
**Pearson correlation:**
|
||||
|
||||
$$r = \frac{n \cdot \Sigma_{xy} - \Sigma_x \cdot \Sigma_y}{\sqrt{(n \cdot \Sigma_{x^2} - \Sigma_x^2)(n \cdot \Sigma_{y^2} - \Sigma_y^2)}}$$
|
||||
|
||||
**O(1) incremental update** (when buffer is full, oldest value $y_{\text{old}}$ exits):
|
||||
|
||||
```text
|
||||
Σy -= y_old; Σy += y_new
|
||||
Σy² -= y_old²; Σy² += y_new²
|
||||
Σxy -= Σy_before_removal // shift all positions down by 1
|
||||
Σxy += (n-1) × y_new // new value enters at position n-1
|
||||
|
||||
CTI = clamp(r, -1, +1)
|
||||
```
|
||||
|
||||
**Default parameters:** period = 20.
|
||||
|
||||
## Resources
|
||||
|
||||
- Ehlers, J.F. (2001). *Rocket Science for Traders*. Wiley
|
||||
- Pearson, K. (1895). "Notes on Regression and Inheritance in the Case of Two Parents." *Proceedings of the Royal Society of London*
|
||||
- PineScript reference: [`cti.pine`](cti.pine)
|
||||
@@ -0,0 +1,59 @@
|
||||
# DOSC: Derivative Oscillator
|
||||
|
||||
The Derivative Oscillator applies a four-stage signal processing pipeline to extract momentum inflection points: RSI via Wilder's smoothing, double EMA smoothing of the RSI, an SMA signal line of the double-smoothed result, and finally the difference between the smoothed RSI and its signal. The histogram output crosses zero at momentum turning points, offering earlier signals than raw RSI by isolating the rate of change of the smoothed momentum rather than the momentum level itself.
|
||||
|
||||
## Historical Context
|
||||
|
||||
Constance Brown introduced the Derivative Oscillator in her 1994 work on advanced oscillator techniques, positioning it as a refinement of standard RSI analysis. The core insight was that RSI levels alone provide trend information but not inflection information: a rising RSI at 60 tells you momentum is bullish, but not whether it is accelerating or decelerating. By taking what amounts to the "derivative" of RSI (via the difference between the double-smoothed RSI and its moving average), the oscillator isolates the acceleration component. The double-EMA smoothing stage was borrowed from MACD-style signal extraction, while the final SMA subtraction mirrors the MACD histogram concept. Brown's original parameters (RSI 14, EMA1 5, EMA2 3, Signal 9) were calibrated for daily equity charts and remain the standard defaults. The indicator found adoption among fixed-income and commodity traders where RSI divergence analysis is common but requires confirmation of momentum turning points.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Four-Stage Pipeline
|
||||
|
||||
1. **Stage 1: Wilder RSI.** Standard RSI using Wilder's RMA smoothing ($\alpha = 1/\text{rsiPeriod}$) for average gain and average loss. Output range: 0-100.
|
||||
|
||||
2. **Stage 2: First EMA.** Exponential moving average of the RSI output with $\alpha_1 = 2/(\text{ema1Period} + 1)$. This removes high-frequency RSI noise while preserving the momentum signal.
|
||||
|
||||
3. **Stage 3: Second EMA (double smoothing).** A second EMA with $\alpha_2 = 2/(\text{ema2Period} + 1)$ applied to the Stage 2 output. The double smoothing creates a zero-lag-adjusted smoother that tracks RSI trends with minimal overshoot.
|
||||
|
||||
4. **Stage 4: SMA signal line.** A simple moving average of the double-smoothed RSI, implemented via circular buffer with running sum for O(1) updates. The SMA period controls the signal line's responsiveness.
|
||||
|
||||
### Output
|
||||
|
||||
The Derivative Oscillator is the difference: $\text{DOSC} = \text{EMA2}(\text{EMA1}(\text{RSI})) - \text{SMA}(\text{EMA2}(\text{EMA1}(\text{RSI})))$. Zero crossings mark momentum inflection points. Positive values indicate accelerating RSI; negative values indicate decelerating RSI.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
**Stage 1: Wilder RSI** ($\alpha_r = 1/p_r$):
|
||||
|
||||
$$\overline{G}_t = \alpha_r \cdot \max(\Delta x_t, 0) + (1-\alpha_r) \cdot \overline{G}_{t-1}$$
|
||||
|
||||
$$\overline{L}_t = \alpha_r \cdot \max(-\Delta x_t, 0) + (1-\alpha_r) \cdot \overline{L}_{t-1}$$
|
||||
|
||||
$$RSI_t = 100 - \frac{100}{1 + \overline{G}_t / \overline{L}_t}$$
|
||||
|
||||
**Stage 2: First EMA** ($\alpha_1 = 2/(p_1 + 1)$):
|
||||
|
||||
$$E_1(t) = \alpha_1 \cdot RSI_t + (1-\alpha_1) \cdot E_1(t-1)$$
|
||||
|
||||
**Stage 3: Second EMA** ($\alpha_2 = 2/(p_2 + 1)$):
|
||||
|
||||
$$E_2(t) = \alpha_2 \cdot E_1(t) + (1-\alpha_2) \cdot E_2(t-1)$$
|
||||
|
||||
**Stage 4: SMA signal line** (period $p_s$):
|
||||
|
||||
$$S(t) = \frac{1}{\min(k, p_s)} \sum_{i=0}^{\min(k, p_s)-1} E_2(t-i)$$
|
||||
|
||||
where $k$ is the count of available values (warmup-aware).
|
||||
|
||||
**Derivative Oscillator:**
|
||||
|
||||
$$DOSC_t = E_2(t) - S(t)$$
|
||||
|
||||
**Default parameters:** rsiPeriod = 14, ema1Period = 5, ema2Period = 3, signalPeriod = 9.
|
||||
|
||||
## Resources
|
||||
|
||||
- Brown, C. (1994). *Technical Analysis for the Trading Professional*. McGraw-Hill
|
||||
- Brown, C. (1999). *Technical Analysis for the Trading Professional*, 2nd ed. McGraw-Hill
|
||||
- PineScript reference: [`dosc.pine`](dosc.pine)
|
||||
@@ -0,0 +1,82 @@
|
||||
// The MIT License (MIT)
|
||||
// © mihakralj
|
||||
//@version=6
|
||||
indicator("Derivative Oscillator (DOSC)", "DOSC", overlay=false, precision=4)
|
||||
|
||||
//@function Calculates the Derivative Oscillator: double-smoothed RSI minus its SMA signal line
|
||||
//@param source Series to calculate from
|
||||
//@param rsiPeriod RSI lookback period
|
||||
//@param ema1Period First EMA smoothing period applied to RSI
|
||||
//@param ema2Period Second EMA smoothing period (double smoothing)
|
||||
//@param sigPeriod SMA signal line period applied to double-smoothed RSI
|
||||
//@returns DOSC value (histogram: double-smoothed RSI minus signal)
|
||||
//@optimized O(1) per bar after warmup for all EMA/SMA stages
|
||||
dosc(series float source, simple int rsiPeriod, simple int ema1Period, simple int ema2Period, simple int sigPeriod) =>
|
||||
if rsiPeriod <= 0 or ema1Period <= 0 or ema2Period <= 0 or sigPeriod <= 0
|
||||
runtime.error("All periods must be greater than 0")
|
||||
|
||||
// --- Stage 1: RSI via Wilder's smoothing ---
|
||||
float change_up = math.max(source - nz(source[1]), 0.0)
|
||||
float change_down = math.max(nz(source[1]) - source, 0.0)
|
||||
|
||||
var float avgGain = 0.0
|
||||
var float avgLoss = 0.0
|
||||
|
||||
float rsiAlpha = 1.0 / rsiPeriod
|
||||
if bar_index < rsiPeriod
|
||||
avgGain := change_up
|
||||
avgLoss := change_down
|
||||
else
|
||||
avgGain := nz(avgGain[1]) * (1.0 - rsiAlpha) + change_up * rsiAlpha
|
||||
avgLoss := nz(avgLoss[1]) * (1.0 - rsiAlpha) + change_down * rsiAlpha
|
||||
|
||||
float rsiVal = avgLoss == 0.0 ? 100.0 : 100.0 - (100.0 / (1.0 + avgGain / avgLoss))
|
||||
|
||||
// --- Stage 2: EMA1 of RSI ---
|
||||
var float ema1 = na
|
||||
float alpha1 = 2.0 / (ema1Period + 1.0)
|
||||
ema1 := na(ema1[1]) ? rsiVal : nz(ema1[1]) * (1.0 - alpha1) + rsiVal * alpha1
|
||||
|
||||
// --- Stage 3: EMA2 of EMA1 (double smoothing) ---
|
||||
var float ema2 = na
|
||||
float alpha2 = 2.0 / (ema2Period + 1.0)
|
||||
ema2 := na(ema2[1]) ? ema1 : nz(ema2[1]) * (1.0 - alpha2) + ema1 * alpha2
|
||||
|
||||
// --- Stage 4: SMA signal line of EMA2 ---
|
||||
var array<float> sigBuf = array.new_float(sigPeriod, na)
|
||||
var int sigHead = 0
|
||||
var int sigCount = 0
|
||||
var float sigSum = 0.0
|
||||
|
||||
float oldest = array.get(sigBuf, sigHead)
|
||||
if not na(oldest)
|
||||
sigSum -= oldest
|
||||
sigSum += ema2
|
||||
else
|
||||
sigCount += 1
|
||||
sigSum += ema2
|
||||
|
||||
array.set(sigBuf, sigHead, ema2)
|
||||
sigHead := (sigHead + 1) % sigPeriod
|
||||
|
||||
float signal = sigCount > 0 ? sigSum / sigCount : 0.0
|
||||
|
||||
// DOSC = double-smoothed RSI minus signal
|
||||
float result = ema2 - signal
|
||||
result
|
||||
|
||||
// ---------- Main loop ----------
|
||||
|
||||
// Inputs
|
||||
i_source = input.source(close, "Source")
|
||||
i_rsiPeriod = input.int(14, "RSI Period", minval=1, maxval=500)
|
||||
i_ema1 = input.int(5, "EMA1 Period", minval=1, maxval=500, tooltip="First EMA smoothing of RSI")
|
||||
i_ema2 = input.int(3, "EMA2 Period", minval=1, maxval=500, tooltip="Second EMA smoothing (double smooth)")
|
||||
i_sigPeriod = input.int(9, "Signal Period", minval=1, maxval=500, tooltip="SMA signal line period")
|
||||
|
||||
// Calculation
|
||||
dosc_value = dosc(i_source, i_rsiPeriod, i_ema1, i_ema2, i_sigPeriod)
|
||||
|
||||
// Plot
|
||||
plot(dosc_value, "DOSC", color=color.yellow, linewidth=2)
|
||||
hline(0, "Zero", color=color.gray, linestyle=hline.style_dotted)
|
||||
@@ -0,0 +1,68 @@
|
||||
# FOSC: Forecast Oscillator
|
||||
|
||||
The Forecast Oscillator measures the percentage deviation of the current price from its linear regression forecast value, producing a zero-centered oscillator that quantifies how far price has moved beyond what a least-squares trend projection would predict. Positive values indicate price is above the regression forecast (bullish divergence from trend), negative values indicate price is below (bearish divergence), and zero crossings mark the points where price meets its statistically expected value. The implementation achieves O(1) per-bar complexity through incremental running sums for the linear regression calculation.
|
||||
|
||||
## Historical Context
|
||||
|
||||
The Forecast Oscillator was introduced by Tushar Chande in his exploration of regression-based indicators during the 1990s, published in *Technical Analysis of Stocks & Commodities* magazine and later in his book on technical analysis. The indicator builds on the Time Series Forecast (TSF) concept but reframes it as an oscillator by expressing the relationship as a percentage deviation rather than an absolute price level. This normalization makes FOSC comparable across instruments of different price scales. Chande positioned FOSC as a complementary tool to his other regression-based indicators (R-Squared, Linear Regression Slope), where R-Squared measures trend quality, slope measures trend direction, and FOSC measures the current price's position relative to trend extrapolation. The percentage formulation also makes FOSC functionally similar to a detrended price series, connecting it to the broader family of detrending oscillators used in cycle analysis.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Linear Regression via Running Sums
|
||||
|
||||
FOSC requires computing a linear regression forecast at each bar. The standard OLS formula needs $\Sigma x$, $\Sigma x^2$, $\Sigma y$, and $\Sigma xy$. Since the $x$ values are sequential integers, $\Sigma x$ and $\Sigma x^2$ are closed-form functions of $n$. Only $\Sigma y$ and $\Sigma xy$ require incremental maintenance via circular buffer.
|
||||
|
||||
The key optimization for $\Sigma xy$ is identical to CTI: when the window slides, subtracting $\Sigma y$ (before removal) shifts all position indices down by one, and adding $(n-1) \times y_{\text{new}}$ places the new value at the highest position. This avoids recomputing $n$ products per bar.
|
||||
|
||||
### Forecast Point
|
||||
|
||||
The linear regression yields slope $m$ and intercept $b$. The forecast value is evaluated at the endpoint of the window: $\hat{y} = m \cdot (n-1) + b$. This represents the trend-projected value for the current bar.
|
||||
|
||||
### Percentage Deviation
|
||||
|
||||
The oscillator output is $\frac{x_t - \hat{y}}{x_t} \times 100$, which normalizes the deviation by the current price. Division by zero is guarded when source equals zero.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
Given source values $y_t$ over a window of $n$ observations with indices $x_i = 0, 1, \ldots, n-1$:
|
||||
|
||||
**Closed-form time sums:**
|
||||
|
||||
$$\Sigma_x = \frac{n(n-1)}{2}, \quad \Sigma_{x^2} = \frac{n(n-1)(2n-1)}{6}$$
|
||||
|
||||
**Running sums (O(1) incremental):**
|
||||
|
||||
$$\Sigma_y = \sum y_i, \quad \Sigma_{xy} = \sum i \cdot y_i$$
|
||||
|
||||
**OLS linear regression:**
|
||||
|
||||
$$m = \frac{n \cdot \Sigma_{xy} - \Sigma_x \cdot \Sigma_y}{n \cdot \Sigma_{x^2} - \Sigma_x^2}, \quad b = \frac{\Sigma_y - m \cdot \Sigma_x}{n}$$
|
||||
|
||||
**Forecast at endpoint:**
|
||||
|
||||
$$\hat{y}_t = m \cdot (n - 1) + b$$
|
||||
|
||||
**Forecast Oscillator:**
|
||||
|
||||
$$FOSC_t = \frac{y_t - \hat{y}_t}{y_t} \times 100$$
|
||||
|
||||
**Streaming update pseudo-code:**
|
||||
|
||||
```text
|
||||
// When buffer full, oldest y_old exits:
|
||||
Σy -= y_old; Σxy -= Σy_before
|
||||
Σy += y_new; Σxy += (n-1) × y_new
|
||||
|
||||
m = (n×Σxy - Σx×Σy) / (n×Σx² - Σx²)
|
||||
b = (Σy - m×Σx) / n
|
||||
forecast = m×(n-1) + b
|
||||
FOSC = (y_new ≠ 0) ? (y_new - forecast) / y_new × 100 : 0
|
||||
```
|
||||
|
||||
**Default parameters:** period = 14.
|
||||
|
||||
## Resources
|
||||
|
||||
- Chande, T.S. (1997). *Beyond Technical Analysis*. Wiley
|
||||
- Chande, T.S. & Kroll, S. (1994). *The New Technical Trader*. Wiley
|
||||
- PineScript reference: [`fosc.pine`](fosc.pine)
|
||||
@@ -0,0 +1,59 @@
|
||||
# KST: Know Sure Thing Oscillator
|
||||
|
||||
The Know Sure Thing is a multi-timeframe momentum oscillator that computes four Rate of Change values at progressively longer lookback periods, smooths each with an independent SMA, then combines them using linearly increasing weights (1, 2, 3, 4) to produce a single composite momentum line. A signal line (SMA of the KST) provides crossover triggers. The weighted summation ensures longer-term momentum dominates the output while shorter-term components contribute responsiveness, creating a momentum indicator that reflects multiple cycle lengths simultaneously.
|
||||
|
||||
## Historical Context
|
||||
|
||||
Martin Pring developed the KST oscillator in the early 1990s, publishing it in *Technical Analysis of Stocks & Commodities* and later in his comprehensive work on technical analysis. Pring's motivation was to create a single indicator that captured momentum across multiple timeframes, eliminating the need to monitor four separate ROC charts. The name "Know Sure Thing" was somewhat tongue-in-cheek, acknowledging that no indicator provides certainty, but reflecting Pring's confidence that multi-timeframe momentum confirmation produces more reliable signals than any single timeframe. The original design used monthly data with ROC periods of 9, 12, 18, 24 months and SMA periods of 6, 6, 6, 9 months, later adapted to daily timeframes using proportionally scaled periods. The linearly increasing weights (1:2:3:4) were chosen to give progressively more influence to longer-term momentum, reflecting the principle that major market trends are driven by longer-term forces while shorter-term momentum primarily adds noise.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Parallel ROC + SMA Pipeline
|
||||
|
||||
KST maintains four independent processing channels, each consisting of:
|
||||
|
||||
1. **ROC calculation:** $ROC_k = \frac{x_t - x_{t-r_k}}{x_{t-r_k}} \times 100$ for lookback periods $r_1 < r_2 < r_3 < r_4$.
|
||||
|
||||
2. **SMA smoothing:** Each ROC is smoothed by an independent SMA with its own circular buffer and running sum, achieving O(1) per bar. The SMA helper function encapsulates buffer management, head pointer, count, and running sum.
|
||||
|
||||
### Weighted Combination
|
||||
|
||||
The four smoothed ROC values are combined with fixed linear weights:
|
||||
|
||||
$$KST = 1 \times SMA(ROC_1) + 2 \times SMA(ROC_2) + 3 \times SMA(ROC_3) + 4 \times SMA(ROC_4)$$
|
||||
|
||||
### Signal Line
|
||||
|
||||
A fifth SMA is applied to the KST output, using its own circular buffer. Crossovers between KST and signal indicate momentum shifts.
|
||||
|
||||
### Total Buffer Count
|
||||
|
||||
The implementation maintains 5 independent SMA circular buffers (4 ROC smoothers + 1 signal), each with its own metadata arrays. No ROC circular buffer is needed because PineScript's `source[n]` lookback provides direct access to historical prices.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
Given source $x_t$, ROC periods $(r_1, r_2, r_3, r_4)$, SMA periods $(s_1, s_2, s_3, s_4)$, signal period $p_s$:
|
||||
|
||||
**Rate of Change for each channel:**
|
||||
|
||||
$$ROC_k(t) = \frac{x_t - x_{t-r_k}}{x_{t-r_k}} \times 100, \quad k \in \{1,2,3,4\}$$
|
||||
|
||||
**SMA smoothing** (O(1) circular buffer per channel):
|
||||
|
||||
$$SM_k(t) = \frac{1}{s_k} \sum_{i=0}^{s_k-1} ROC_k(t-i)$$
|
||||
|
||||
**KST composite:**
|
||||
|
||||
$$KST(t) = 1 \cdot SM_1(t) + 2 \cdot SM_2(t) + 3 \cdot SM_3(t) + 4 \cdot SM_4(t)$$
|
||||
|
||||
**Signal line:**
|
||||
|
||||
$$Signal(t) = \frac{1}{p_s} \sum_{i=0}^{p_s-1} KST(t-i)$$
|
||||
|
||||
**Default parameters:** $r = (10, 15, 20, 30)$, $s = (10, 10, 10, 15)$, $p_s = 9$.
|
||||
|
||||
## Resources
|
||||
|
||||
- Pring, M.J. (1992). "The KST System." *Technical Analysis of Stocks & Commodities*
|
||||
- Pring, M.J. (2002). *Technical Analysis Explained*, 4th ed. McGraw-Hill
|
||||
- PineScript reference: [`kst.pine`](kst.pine)
|
||||
@@ -0,0 +1,60 @@
|
||||
# MSTOCH: Ehlers MESA Stochastic
|
||||
|
||||
The MESA Stochastic applies John Ehlers' Roofing Filter as a preprocessing stage before computing a stochastic oscillator, then smooths the stochastic output with a Super Smoother. The Roofing Filter removes both low-frequency trend components (via highpass) and high-frequency noise (via Super Smoother), isolating the dominant cycle. The stochastic calculation on this filtered data produces a clean 0-to-1 oscillator that responds to cycle turning points rather than trend or noise, with substantially reduced whipsaw compared to conventional stochastic indicators.
|
||||
|
||||
## Historical Context
|
||||
|
||||
John Ehlers introduced the MESA Stochastic in his 2013 book *Cycle Analytics for Traders*, as part of his systematic framework for applying digital signal processing to market data. The "MESA" prefix references Maximum Entropy Spectral Analysis, Ehlers' preferred technique for estimating dominant cycle periods. The key innovation is the Roofing Filter preprocessing: by bandpass-filtering the data before applying the stochastic calculation, the oscillator responds to cycle extremes rather than trend extremes. Conventional stochastic indicators on raw price tend to saturate at 0 or 100 during trends (the "stochastic pop" failure mode), but the Roofing Filter removes the trend component entirely, so the stochastic operates on stationary cycle data. Ehlers demonstrated that this produces fewer false signals in trending markets while maintaining responsiveness at genuine cycle turning points. The Super Smoother stages use 2-pole Butterworth-derived coefficients that provide superior smoothing characteristics compared to simple or exponential moving averages.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Three-Stage Pipeline
|
||||
|
||||
1. **Stage 1: Roofing Filter** (Highpass + Super Smoother). The highpass is a 2-pole Butterworth filter that removes cycles longer than `hpLength`, eliminating trend. The Super Smoother is a 2-pole lowpass filter that removes cycles shorter than `ssLength`, eliminating noise. Together they form a bandpass that isolates the dominant cycle band.
|
||||
|
||||
2. **Stage 2: Stochastic on filtered data.** A standard highest-high / lowest-low stochastic over `stochLength` bars of the roofing-filtered output. Because the input is zero-mean (trend removed), the stochastic operates on cycle oscillations rather than trending prices.
|
||||
|
||||
3. **Stage 3: Super Smoother of stochastic.** The same 2-pole smoothing filter applied to the raw stochastic, removing stochastic noise while preserving the timing of overbought/oversold transitions. Output is clamped to $[0, 1]$.
|
||||
|
||||
### IIR Filter Coefficients
|
||||
|
||||
Both the highpass and Super Smoother stages use coefficients derived from 2-pole Butterworth prototypes:
|
||||
|
||||
$$\text{arg} = \frac{\sqrt{2}\pi}{P}, \quad e^{-\text{arg}}, \quad c_2 = 2 e^{-\text{arg}} \cos(\text{arg}), \quad c_3 = -e^{-2\text{arg}}$$
|
||||
|
||||
The highpass uses $c_1 = (1 + c_2 - c_3)/4$ with a second-difference input $(x - 2x_{-1} + x_{-2})$.
|
||||
The Super Smoother uses $c_1 = 1 - c_2 - c_3$ with an averaged input $(x + x_{-1})/2$.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
**Roofing Filter highpass** (removes trend, cutoff period $P_{hp}$):
|
||||
|
||||
$$HP_t = c_1^{hp}(x_t - 2x_{t-1} + x_{t-2}) + c_2^{hp} \cdot HP_{t-1} + c_3^{hp} \cdot HP_{t-2}$$
|
||||
|
||||
where $c_1^{hp} = \frac{1 + c_2^{hp} - c_3^{hp}}{4}$
|
||||
|
||||
**Super Smoother** (removes noise, cutoff period $P_{ss}$):
|
||||
|
||||
$$F_t = c_1^{ss} \cdot \frac{HP_t + HP_{t-1}}{2} + c_2^{ss} \cdot F_{t-1} + c_3^{ss} \cdot F_{t-2}$$
|
||||
|
||||
where $c_1^{ss} = 1 - c_2^{ss} - c_3^{ss}$
|
||||
|
||||
**Stochastic on filtered data:**
|
||||
|
||||
$$S_t = \frac{F_t - \min(F_{t-k}, \ldots, F_t)}{\max(F_{t-k}, \ldots, F_t) - \min(F_{t-k}, \ldots, F_t)}$$
|
||||
|
||||
where $k = \text{stochLength} - 1$. If range is zero, $S_t = 0.5$.
|
||||
|
||||
**Final smoothing:**
|
||||
|
||||
$$MSTOCH_t = c_1^{ss} \cdot \frac{S_t + S_{t-1}}{2} + c_2^{ss} \cdot MSTOCH_{t-1} + c_3^{ss} \cdot MSTOCH_{t-2}$$
|
||||
|
||||
$$\text{Output} = \text{clamp}(MSTOCH_t, 0, 1)$$
|
||||
|
||||
**Default parameters:** stochLength = 20, hpLength = 48, ssLength = 10.
|
||||
|
||||
## Resources
|
||||
|
||||
- Ehlers, J.F. (2013). *Cycle Analytics for Traders*. Wiley, Chapter 6
|
||||
- Ehlers, J.F. (2004). *Cybernetic Analysis for Stocks and Futures*. Wiley
|
||||
- PineScript reference: [`mstoch.pine`](mstoch.pine)
|
||||
@@ -0,0 +1,65 @@
|
||||
# QQE: Quantitative Qualitative Estimation
|
||||
|
||||
Quantitative Qualitative Estimation applies a multi-stage smoothing pipeline to RSI and then constructs dynamic volatility-based trailing bands around the smoothed result. The output is a dual-line system: the QQE line (smoothed RSI) and a trailing level that follows price directionally, similar to Parabolic SAR logic. Crossovers between the QQE line and its trailing level signal momentum shifts, while crossovers of the QQE line above and below 50 indicate trend direction. The trailing level adapts to volatility through a double-EMA of RSI absolute changes, making band width contract in quiet markets and expand during volatile conditions.
|
||||
|
||||
## Historical Context
|
||||
|
||||
QQE emerged from the forex trading community in the mid-2000s, attributed to an anonymous developer and popularized through MetaTrader forums. The indicator extends Wilder's RSI concept by addressing two of its primary limitations: noise in the RSI signal and fixed overbought/oversold thresholds. The first problem is solved by EMA smoothing of the RSI output; the second by replacing static thresholds with adaptive trailing bands derived from RSI volatility. The "Quantitative Qualitative" name reflects the dual nature of the system: the quantitative RSI measurement combined with qualitative trend-following logic in the trailing level. The trailing level mechanism borrows from Welles Wilder's Parabolic SAR: it follows the smoothed RSI directionally, only reversing when the RSI breaks through. The default QQE factor of 4.236 (the square of the golden ratio $\phi^2 = 2.618... \times 1.618...$) has no documented mathematical justification but has become canonical through widespread adoption.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Four-Stage Pipeline
|
||||
|
||||
1. **Stage 1: Wilder RSI** via RMA ($\alpha = 1/\text{rsiPeriod}$) with warmup compensation. The exponential decay factor $e = \beta^n$ tracks convergence, applying correction $c = 1/(1-e)$ until $e < 10^{-10}$.
|
||||
|
||||
2. **Stage 2: EMA smoothing** of RSI ($\alpha = 2/(\text{SF}+1)$) with the same warmup compensation. Produces `rsiMA`, the primary QQE line.
|
||||
|
||||
3. **Stage 3: Dynamic Average Range (DAR).** Computes $|\Delta \text{rsiMA}|$ bar-to-bar, then applies two consecutive EMAs with period $2 \times \text{SF} - 1$. Both EMAs use warmup compensation. The double smoothing produces a stable volatility estimate analogous to ATR but operating on the RSI domain.
|
||||
|
||||
4. **Stage 4: Trailing level.** Constructs upper/lower bands at $\text{rsiMA} \pm \text{qqeFactor} \times \text{DAR}$. The trailing logic follows directionally:
|
||||
- If rsiMA is above the trail and was above previously: trail = max(trail, lowerBand) (ratchets up)
|
||||
- If rsiMA is below the trail and was below previously: trail = min(trail, upperBand) (ratchets down)
|
||||
- On crossover: trail flips to the opposite band
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
**Stage 1: RSI** ($\alpha_r = 1/p_r$, $\beta_r = 1 - \alpha_r$):
|
||||
|
||||
$$\hat{G}_t = \beta_r \hat{G}_{t-1} + \alpha_r \max(\Delta x_t, 0), \quad e_r = \beta_r^t$$
|
||||
|
||||
$$RSI_t = \frac{100 \cdot \hat{G}_t / (1-e_r)}{\hat{G}_t/(1-e_r) + \hat{L}_t/(1-e_r)}$$
|
||||
|
||||
**Stage 2: EMA of RSI** ($\alpha_s = 2/(SF+1)$):
|
||||
|
||||
$$\hat{M}_t = \beta_s \hat{M}_{t-1} + \alpha_s \cdot RSI_t, \quad rsiMA_t = \hat{M}_t / (1 - \beta_s^t)$$
|
||||
|
||||
**Stage 3: Double EMA of |delta|** ($\alpha_d = 2/(2 \cdot SF)$):
|
||||
|
||||
$$D_t = |rsiMA_t - rsiMA_{t-1}|$$
|
||||
|
||||
$$\hat{d}_1 = \beta_d \hat{d}_1 + \alpha_d D_t, \quad dar_1 = \hat{d}_1 / (1 - \beta_d^t)$$
|
||||
|
||||
$$\hat{d}_2 = \beta_d \hat{d}_2 + \alpha_d \cdot dar_1, \quad DAR_t = \hat{d}_2 / (1 - \beta_d^t)$$
|
||||
|
||||
**Stage 4: Trailing level:**
|
||||
|
||||
```text
|
||||
band = qqeFactor × DAR
|
||||
upper = rsiMA + band
|
||||
lower = rsiMA - band
|
||||
|
||||
if rsiMA > trail AND prev_rsiMA > trail:
|
||||
trail = max(trail, lower)
|
||||
elif rsiMA < trail AND prev_rsiMA < trail:
|
||||
trail = min(trail, upper)
|
||||
else:
|
||||
trail = (rsiMA > trail) ? lower : upper
|
||||
```
|
||||
|
||||
**Default parameters:** rsiPeriod = 14, smoothFactor = 5, qqeFactor = 4.236.
|
||||
|
||||
## Resources
|
||||
|
||||
- Wilder, J.W. (1978). *New Concepts in Technical Trading Systems*. Trend Research (RSI foundation)
|
||||
- MetaTrader community documentation on QQE implementation
|
||||
- PineScript reference: [`qqe.pine`](qqe.pine)
|
||||
@@ -0,0 +1,59 @@
|
||||
# RVGI: Relative Vigor Index
|
||||
|
||||
The Relative Vigor Index measures the conviction of a price move by comparing closing strength (close minus open) to the total intrabar range (high minus low), smoothed through a symmetrically weighted moving average and then averaged over a lookback period. The premise is that in bullish markets, closes tend to occur near highs and opens near lows, producing positive RVGI values, while bearish markets show the opposite pattern. A 4-bar SWMA signal line provides crossover triggers. The indicator oscillates around zero with no fixed bounds.
|
||||
|
||||
## Historical Context
|
||||
|
||||
John Ehlers introduced the Relative Vigor Index in his 2002 book *Rocket Science for Traders*, drawing on the concept that price vigor (the difference between open and close) relative to the bar's range captures directional conviction more effectively than close-only momentum measures. The design reflects Ehlers' signal processing background: the SWMA (Symmetrically Weighted Moving Average) with weights $[1, 2, 2, 1]/6$ is a 4-tap FIR filter with symmetric coefficients, which guarantees zero phase shift at the cost of minimal lag. This choice was deliberate, as asymmetric weights would introduce phase distortion that corrupts the relationship between the indicator and its signal line. The SMA averaging stage serves as a secondary smoothing filter that reduces noise without further phase impact. The signal line reuses the same SWMA kernel, maintaining phase consistency throughout the entire processing chain.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Four-Stage Pipeline
|
||||
|
||||
1. **SWMA of (Close - Open):** A fixed 4-bar kernel with weights $[1, 2, 2, 1]/6$ applied to the close-minus-open series. This captures the directional conviction of each bar, smoothed symmetrically.
|
||||
|
||||
2. **SWMA of (High - Low):** The same 4-bar kernel applied to the high-minus-low (range) series. This normalizes by volatility.
|
||||
|
||||
3. **SMA of numerator and denominator:** Independent SMAs over the specified period, each using a circular buffer with O(1) running sum updates. The ratio $\text{SMA(numerator)} / \text{SMA(denominator)}$ produces the RVGI line.
|
||||
|
||||
4. **Signal line:** A 4-bar SWMA of the RVGI output, using three history variables to store the previous three RVGI values. The SWMA kernel is hardcoded: $(rv_3 + 2 \cdot rv_2 + 2 \cdot rv_1 + rv_0) / 6$.
|
||||
|
||||
### Defensive Division
|
||||
|
||||
When the denominator SMA equals zero (all bars in the window have zero range, i.e., doji sequences), RVGI returns 0 rather than propagating division by zero.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
Given OHLC bars and lookback period $n$:
|
||||
|
||||
**SWMA kernel** (4-tap symmetric FIR):
|
||||
|
||||
$$w = \left[\frac{1}{6}, \frac{2}{6}, \frac{2}{6}, \frac{1}{6}\right]$$
|
||||
|
||||
**Numerator (closing strength):**
|
||||
|
||||
$$N_t = \frac{(C_{t-3} - O_{t-3}) + 2(C_{t-2} - O_{t-2}) + 2(C_{t-1} - O_{t-1}) + (C_t - O_t)}{6}$$
|
||||
|
||||
**Denominator (bar range):**
|
||||
|
||||
$$D_t = \frac{(H_{t-3} - L_{t-3}) + 2(H_{t-2} - L_{t-2}) + 2(H_{t-1} - L_{t-1}) + (H_t - L_t)}{6}$$
|
||||
|
||||
**SMA smoothing** (O(1) circular buffer):
|
||||
|
||||
$$\overline{N}_t = \frac{1}{n}\sum_{i=0}^{n-1} N_{t-i}, \quad \overline{D}_t = \frac{1}{n}\sum_{i=0}^{n-1} D_{t-i}$$
|
||||
|
||||
**RVGI:**
|
||||
|
||||
$$RVGI_t = \begin{cases} \overline{N}_t / \overline{D}_t & \text{if } \overline{D}_t \neq 0 \\ 0 & \text{otherwise} \end{cases}$$
|
||||
|
||||
**Signal line:**
|
||||
|
||||
$$Signal_t = \frac{RVGI_{t-3} + 2 \cdot RVGI_{t-2} + 2 \cdot RVGI_{t-1} + RVGI_t}{6}$$
|
||||
|
||||
**Default parameters:** period = 10.
|
||||
|
||||
## Resources
|
||||
|
||||
- Ehlers, J.F. (2002). *Rocket Science for Traders*. Wiley, Chapter 12
|
||||
- Ehlers, J.F. (2001). "The Relative Vigor Index." *Technical Analysis of Stocks & Commodities*
|
||||
- PineScript reference: [`rvgi.pine`](rvgi.pine)
|
||||
@@ -0,0 +1,63 @@
|
||||
# SQUEEZE: Squeeze Momentum
|
||||
|
||||
Squeeze Momentum combines Bollinger Band and Keltner Channel width analysis to detect low-volatility compression ("squeeze") states, while simultaneously measuring directional momentum via linear regression of a detrended price series. The dual output consists of a momentum histogram and a binary squeeze state indicator. When Bollinger Bands contract inside the Keltner Channel, the market is in a squeeze (coiling volatility); when the squeeze releases, the momentum histogram direction signals the likely breakout direction. The implementation combines five distinct computational stages, each using O(1) streaming techniques.
|
||||
|
||||
## Historical Context
|
||||
|
||||
John Carter popularized the Squeeze indicator in his 2005 book *Mastering the Trade*, though the core concept of BB-inside-KC squeeze detection predates his work. The underlying principle is that volatility is mean-reverting: periods of unusually low volatility (measured by BB width falling below KC width) tend to precede large directional moves. Carter combined this squeeze detection with a momentum component derived from linear regression to provide directional bias. The specific construction uses the midpoint of a Donchian Channel averaged with SMA as a center line, computes the deviation of price from this averaged midpoint, and applies linear regression to this deviation series. The regression endpoint value serves as the momentum measure. This construction effectively measures detrended momentum, isolating the directional force from the trend component. The color-coded histogram (traditionally four colors based on momentum direction and acceleration) provides visual distinction between momentum increasing and decreasing in both directions.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Five Computational Stages
|
||||
|
||||
1. **SMA + Standard Deviation** (Bollinger Bands): Circular buffer with running sum and sum-of-squares for O(1) variance computation. BB upper/lower = SMA $\pm$ bbMult $\times$ StdDev.
|
||||
|
||||
2. **EMA + ATR via RMA** (Keltner Channel): EMA uses warmup-compensated exponential smoothing. ATR uses Wilder's RMA (also warmup-compensated) of True Range. KC upper/lower = EMA $\pm$ kcMult $\times$ ATR.
|
||||
|
||||
3. **Squeeze detection:** Binary comparison: if BB upper < KC upper AND BB lower > KC lower, squeeze is on. This means BB has contracted inside KC.
|
||||
|
||||
4. **Donchian midline + delta:** Circular buffers for highest-high and lowest-low over the period, with full O(n) scan per bar for max/min (no O(1) trick for running max). Delta = close $-$ (donchianMid + SMA) / 2.
|
||||
|
||||
5. **Linear regression of delta:** Incremental running sums ($\Sigma y$, $\Sigma xy$) for O(1) regression per bar. The momentum output is the regression line evaluated at the most recent point: $\text{slope} \times (n-1) + \text{intercept}$.
|
||||
|
||||
### Warmup Compensation
|
||||
|
||||
EMA and RMA stages use the $e = \beta^n$ warmup tracking with correction factor $c = 1/(1-e)$ to eliminate initial bias.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
**Bollinger Bands** (SMA + StdDev via running sums):
|
||||
|
||||
$$\mu = \frac{\Sigma x}{n}, \quad \sigma = \sqrt{\frac{\Sigma x^2}{n} - \mu^2}$$
|
||||
|
||||
$$BB_{upper} = \mu + m_{bb} \cdot \sigma, \quad BB_{lower} = \mu - m_{bb} \cdot \sigma$$
|
||||
|
||||
**Keltner Channel** (EMA + ATR):
|
||||
|
||||
$$EMA_t = \frac{\hat{E}_t}{1 - \beta^t}, \quad ATR_t = \frac{\hat{R}_t}{1 - \beta_r^t}$$
|
||||
|
||||
$$KC_{upper} = EMA + m_{kc} \cdot ATR, \quad KC_{lower} = EMA - m_{kc} \cdot ATR$$
|
||||
|
||||
**Squeeze state:**
|
||||
|
||||
$$Squeeze = \begin{cases} 1 & \text{if } BB_{upper} < KC_{upper} \text{ and } BB_{lower} > KC_{lower} \\ 0 & \text{otherwise} \end{cases}$$
|
||||
|
||||
**Detrended price (delta):**
|
||||
|
||||
$$\delta_t = x_t - \frac{(\text{DonchianMid}_t + \text{SMA}_t)}{2}$$
|
||||
|
||||
where $\text{DonchianMid} = \frac{\max(H_{t-n+1..t}) + \min(L_{t-n+1..t})}{2}$
|
||||
|
||||
**Momentum (linear regression endpoint of delta):**
|
||||
|
||||
$$m = \frac{n \cdot \Sigma_{xy} - \Sigma_x \cdot \Sigma_y}{n \cdot \Sigma_{x^2} - \Sigma_x^2}, \quad b = \frac{\Sigma_y - m \cdot \Sigma_x}{n}$$
|
||||
|
||||
$$Momentum_t = m \cdot (t_{\text{last}}) + b$$
|
||||
|
||||
**Default parameters:** period = 20, bbMult = 2.0, kcMult = 1.5.
|
||||
|
||||
## Resources
|
||||
|
||||
- Carter, J. (2005). *Mastering the Trade*. McGraw-Hill, Chapter 11
|
||||
- Bollinger, J. (2001). *Bollinger on Bollinger Bands*. McGraw-Hill
|
||||
- PineScript reference: [`squeeze.pine`](squeeze.pine)
|
||||
@@ -0,0 +1,60 @@
|
||||
# TD_SEQ: TD Sequential
|
||||
|
||||
TD Sequential is Tom DeMark's exhaustion counting system that identifies potential trend reversals through two phases: a 9-count Setup phase that detects overextended trends, and a 13-count Countdown phase that pinpoints probable reversal timing. Unlike oscillators that measure momentum magnitude, TD Sequential counts consecutive qualifying bars, producing integer outputs (Setup: $\pm 1$ to $\pm 9$; Countdown: $\pm 1$ to $\pm 13$) that represent the progression toward exhaustion. A completed 9-count Setup followed by a completed 13-count Countdown signals high-probability trend exhaustion. All state is maintained in O(1) scalar variables with no buffers required.
|
||||
|
||||
## Historical Context
|
||||
|
||||
Thomas DeMark developed TD Sequential during the 1970s-1990s as part of his comprehensive market timing framework, published in *The New Science of Technical Analysis* (1994) and *New Market Timing Techniques* (1997). The indicator was conceived as a structural alternative to momentum oscillators: rather than measuring how overbought or oversold a market is, it counts how long a directional condition has persisted and identifies specific exhaustion points. DeMark's key insight was that trends exhaust at predictable counting thresholds (9 for Setup, 13 for Countdown), a pattern he validated across equity, fixed-income, commodity, and currency markets. The indicator found significant institutional adoption, with Bloomberg terminals providing native DeMark indicators and firms like Tudor Investment Corporation licensing the methodology. The compare period (typically 4 bars) determines the lookback for the close comparison: each Setup bar requires close above/below close[4], creating a structural requirement that the trend has been sustained for at least 4 additional bars beyond the count itself. The Countdown phase adds a higher bar: the close must exceed the high or low of 2 bars ago, a condition that doesn't occur on every bar, making the Countdown non-consecutive.
|
||||
|
||||
## Architecture & Physics
|
||||
|
||||
### Two-Phase State Machine
|
||||
|
||||
**Phase 1: Setup ($\pm 1$ to $\pm 9$)**
|
||||
|
||||
The Setup counter compares the current close to the close `comparePeriod` bars ago. If close > close[comparePeriod], the sell setup count increments (positive); if close < close[comparePeriod], the buy setup count decrements (negative). The count resets to zero when the condition breaks or reverses direction. Counts are clamped to $\pm 9$.
|
||||
|
||||
When the count reaches exactly $\pm 9$ for the first time (without having been reset), the setup is "complete" and Phase 2 begins. The setupComplete flag prevents re-triggering until a reset occurs.
|
||||
|
||||
**Phase 2: Countdown ($\pm 1$ to $\pm 13$)**
|
||||
|
||||
After a completed 9-count Setup, the Countdown phase begins. Unlike Setup, Countdown is non-consecutive: a sell countdown bar requires close > high[2]; a buy countdown bar requires close < low[2]. Only qualifying bars increment the countdown. The count progresses toward $\pm 13$, at which point the countdown completes and the directional signal resets.
|
||||
|
||||
An opposite 9-count Setup during an active Countdown resets and restarts the Countdown in the new direction.
|
||||
|
||||
### Zero-Buffer Design
|
||||
|
||||
The entire indicator state consists of four scalar variables: `setupCount`, `countdownCount`, `countdownDir`, and `setupComplete`. No circular buffers, arrays, or sliding windows are needed. The only historical lookback dependency is PineScript's `close[comparePeriod]`, `low[2]`, and `high[2]`.
|
||||
|
||||
## Mathematical Foundation
|
||||
|
||||
**Setup counting** (comparePeriod = $p$):
|
||||
|
||||
$$S_t = \begin{cases} S_{t-1} - 1 & \text{if } C_t < C_{t-p} \text{ and } S_{t-1} \leq 0 \\ -1 & \text{if } C_t < C_{t-p} \text{ and } S_{t-1} > 0 \\ S_{t-1} + 1 & \text{if } C_t > C_{t-p} \text{ and } S_{t-1} \geq 0 \\ +1 & \text{if } C_t > C_{t-p} \text{ and } S_{t-1} < 0 \\ 0 & \text{if } C_t = C_{t-p} \end{cases}$$
|
||||
|
||||
$$S_t = \text{clamp}(S_t, -9, +9)$$
|
||||
|
||||
**Setup completion trigger:**
|
||||
|
||||
$$\text{if } |S_t| = 9 \text{ and not previously complete} \Rightarrow \text{begin Countdown, dir} = \text{sign}(S_t)$$
|
||||
|
||||
**Countdown** (non-consecutive):
|
||||
|
||||
$$CD_t = \begin{cases} CD_{t-1} - 1 & \text{if dir} = -1 \text{ and } C_t < L_{t-2} \\ CD_{t-1} + 1 & \text{if dir} = +1 \text{ and } C_t > H_{t-2} \\ CD_{t-1} & \text{otherwise (no qualifying bar)} \end{cases}$$
|
||||
|
||||
**Countdown completion:**
|
||||
|
||||
$$\text{if } |CD_t| \geq 13 \Rightarrow CD_t = \text{sign}(dir) \times 13, \text{ reset dir}$$
|
||||
|
||||
**Countdown reset on opposite Setup:**
|
||||
|
||||
$$\text{if dir} = +1 \text{ and } S_t = -9, \text{ or dir} = -1 \text{ and } S_t = +9 \Rightarrow \text{reset CD, new dir}$$
|
||||
|
||||
**Default parameters:** comparePeriod = 4.
|
||||
|
||||
## Resources
|
||||
|
||||
- DeMark, T.R. (1994). *The New Science of Technical Analysis*. Wiley
|
||||
- DeMark, T.R. (1997). *New Market Timing Techniques*. Wiley
|
||||
- Bloomberg Terminal: DeMark Indicators (DMRK) implementation reference
|
||||
- PineScript reference: [`td_seq.pine`](td_seq.pine)
|
||||
Reference in New Issue
Block a user