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_DM: Plus Directional Movement (Wilder, 1978)
/// </summary>
/// <remarks>
/// Wilder-smoothed upward directional movement in price units.
/// Extracted from the DX calculation: Smoothed(+DM) using Wilder's method.
/// Values ≥ 0 in price units. Higher values indicate stronger upward movement magnitude.
/// </remarks>
[SkipLocalsInit]
public sealed class PlusDm : ITValuePublisher
{
private readonly Dx _dx;
/// <summary>Display name for the indicator.</summary>
public string Name { get; }
public event TValuePublishedHandler? Pub;
/// <summary>Current smoothed +DM 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 PlusDm with specified period.
/// </summary>
/// <param name="period">Wilder smoothing period (must be &gt; 0)</param>
public PlusDm(int period = 14)
{
if (period <= 0)
{
throw new ArgumentException("Period must be greater than 0", nameof(period));
}
_dx = new Dx(period);
Name = $"PlusDm({period})";
}
/// <summary>
/// Creates PlusDm and immediately processes the bar series.
/// </summary>
public PlusDm(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.DmPlus;
if (isNew)
{
Pub?.Invoke(this, new TValueEventArgs { Value = Last, IsNew = isNew });
}
return Last;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TValue Update(TValue input, bool isNew = true)
{
// DM 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 — DM requires OHLC bar data, not scalar values
}
public static TSeries Batch(TBarSeries source, int period = 14)
{
var indicator = new PlusDm(period);
return indicator.Update(source);
}
public static (TSeries Results, PlusDm Indicator) Calculate(TBarSeries source, int period = 14)
{
var indicator = new PlusDm(period);
return (indicator.Update(source), indicator);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Reset()
{
_dx.Reset();
Last = default;
}
}
+28
View File
@@ -0,0 +1,28 @@
# PLUS_DM: Plus Directional Movement
### TL;DR
Wilder-smoothed upward directional movement in price units (≥0).
## Introduction
Plus Directional Movement (+DM) measures the magnitude of upward price movement, smoothed using Wilder's method. Unlike +DI which normalizes by true range to produce a percentage, +DM outputs raw smoothed values in price units.
+DM captures when the current bar's high exceeds the previous bar's high by more than the previous bar's low exceeds the current bar's low. It is the raw building block of the Directional Movement System.
## Calculation
+DM = max(High - PrevHigh, 0) when High - PrevHigh > PrevLow - Low, else 0
Smoothed using Wilder's method: Smooth = Smooth - Smooth/N + Input
## Parameters
| Parameter | Default | Range | Description |
| :--- | :--- | :--- | :--- |
| Period | 14 | 2-∞ | Wilder smoothing period |
## Interpretation
- **Rising +DM:** Increasing upward price extension
- **+DM > -DM:** Upward movement exceeds downward movement
- **Zero +DM:** No upward directional movement on the bar
- Values are in price units and scale with the instrument
## References
- Wilder, J. Welles Jr. "New Concepts in Technical Trading Systems" (1978)