feat: add new indicators (Decay, Edecay, MinusDi, MinusDm, PlusDi, PlusDm, Maxindex, Minindex, Sarext) and update pine scripts, core libs, validation tests, and python bindings

This commit is contained in:
Miha Kralj
2026-03-09 13:45:46 -07:00
parent 8e43d62cbb
commit 031f1b5fe6
491 changed files with 6156 additions and 5590 deletions
+121
View File
@@ -0,0 +1,121 @@
using System.Runtime.CompilerServices;
namespace QuanTAlib;
/// <summary>
/// PLUS_DI: Plus Directional Indicator (Wilder, 1978)
/// </summary>
/// <remarks>
/// Measures upward directional movement as a percentage of true range.
/// Extracted from the DX calculation: +DI = Smoothed(+DM) / Smoothed(TR) × 100.
/// Range: 0 to 100. Higher values indicate stronger upward movement.
/// </remarks>
[SkipLocalsInit]
public sealed class PlusDi : ITValuePublisher
{
private readonly Dx _dx;
/// <summary>Display name for the indicator.</summary>
public string Name { get; }
public event TValuePublishedHandler? Pub;
/// <summary>Current +DI value.</summary>
public TValue Last { get; private set; }
/// <summary>True when the indicator has warmed up.</summary>
public bool IsHot => _dx.IsHot;
/// <summary>Bars required for warmup.</summary>
public int WarmupPeriod => _dx.WarmupPeriod;
/// <summary>The period parameter.</summary>
public int Period => _dx.Period;
/// <summary>
/// Creates PlusDi with specified period.
/// </summary>
/// <param name="period">Wilder smoothing period (must be &gt; 0)</param>
public PlusDi(int period = 14)
{
if (period <= 0)
{
throw new ArgumentException("Period must be greater than 0", nameof(period));
}
_dx = new Dx(period);
Name = $"PlusDi({period})";
}
/// <summary>
/// Creates PlusDi and immediately processes the bar series.
/// </summary>
public PlusDi(TBarSeries source, int period = 14) : this(period)
{
var result = Batch(source, period);
Last = result[^1];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(TBar input, bool isNew = true)
{
_dx.Update(input, isNew);
Last = _dx.DiPlus;
if (isNew)
{
Pub?.Invoke(this, new TValueEventArgs { Value = Last, IsNew = isNew });
}
return Last;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(TValue input, bool isNew = true)
{
// DI requires OHLC data — scalar update not meaningful
return Last;
}
public TSeries Update(TBarSeries source)
{
var result = new TSeries(source.Count);
foreach (var bar in source)
{
result.Add(Update(bar));
}
return result;
}
/// <summary>
/// Initializes the indicator state using the provided bar series history.
/// </summary>
public void Prime(TBarSeries source)
{
foreach (var bar in source)
{
Update(bar);
}
}
public void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
// Not applicable — DI requires OHLC bar data, not scalar values
}
public static TSeries Batch(TBarSeries source, int period = 14)
{
var indicator = new PlusDi(period);
return indicator.Update(source);
}
public static (TSeries Results, PlusDi Indicator) Calculate(TBarSeries source, int period = 14)
{
var indicator = new PlusDi(period);
return (indicator.Update(source), indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
_dx.Reset();
Last = default;
}
}
+31
View File
@@ -0,0 +1,31 @@
# PLUS_DI: Plus Directional Indicator
### TL;DR
Measures upward directional movement strength as a percentage (0-100).
## Introduction
The Plus Directional Indicator (+DI) measures the strength of upward price movement relative to the true range. It is one of the components of the Directional Movement System developed by J. Welles Wilder Jr.
When +DI is rising, upward price pressure is increasing. When +DI crosses above -DI, it signals a potential bullish trend. The +DI line is commonly plotted alongside -DI to visualize directional balance.
## Calculation
+DI = Smoothed(+DM) / Smoothed(TR) × 100
Where:
- +DM (Plus Directional Movement) = max(High - PrevHigh, 0) when High - PrevHigh > PrevLow - Low, else 0
- TR (True Range) = max(High - Low, |High - PrevClose|, |Low - PrevClose|)
- Smoothing uses Wilder's method: Smooth = Smooth - Smooth/N + Input
## Parameters
| Parameter | Default | Range | Description |
| :--- | :--- | :--- | :--- |
| Period | 14 | 2-∞ | Wilder smoothing period |
## Interpretation
- **Rising +DI:** Strengthening upward movement
- **+DI > -DI:** Bulls dominate; potential uptrend
- **+DI crossover above -DI:** Bullish signal
- **High +DI (>40):** Strong upward momentum
## References
- Wilder, J. Welles Jr. "New Concepts in Technical Trading Systems" (1978)