mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-17 18:18:04 +00:00
new indicators
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// DCHN: Donchian Channels
|
||||
/// A volatility indicator that identifies the highest high and lowest low
|
||||
/// over a specified period, creating a channel that contains price movement.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The DCHN calculation process:
|
||||
/// 1. Track highest high over period
|
||||
/// 2. Track lowest low over period
|
||||
/// 3. Calculate midline as average of high and low
|
||||
/// 4. Updates with each new price bar
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Trend following indicator
|
||||
/// - Support/resistance identification
|
||||
/// - Breakout detection
|
||||
/// - Volatility measurement
|
||||
/// - Range-based analysis
|
||||
///
|
||||
/// Formula:
|
||||
/// Upper = Highest High over period
|
||||
/// Lower = Lowest Low over period
|
||||
/// Middle = (Upper + Lower) / 2
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Trend identification
|
||||
/// - Support/resistance levels
|
||||
/// - Breakout trading
|
||||
/// - Volatility analysis
|
||||
/// - Range-bound trading
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Dchn : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _highs;
|
||||
private readonly CircularBuffer _lows;
|
||||
private const int DefaultPeriod = 20;
|
||||
|
||||
/// <param name="period">The number of periods for DCHN calculation (default 20).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Dchn(int period = DefaultPeriod)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
|
||||
_highs = new(period);
|
||||
_lows = new(period);
|
||||
WarmupPeriod = period;
|
||||
Name = $"DCHN({period})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for DCHN calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Dchn(object source, int period = DefaultPeriod) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_highs.Add(BarInput.High);
|
||||
_lows.Add(BarInput.Low);
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(BarInput.IsNew);
|
||||
|
||||
// Calculate channel boundaries
|
||||
double upper = _highs.Max();
|
||||
double lower = _lows.Min();
|
||||
|
||||
// Return midline
|
||||
return (upper + lower) / 2.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the upper channel value (highest high)
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public double Upper() => _highs.Max();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lower channel value (lowest low)
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public double Lower() => _lows.Min();
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// NATR: Normalized Average True Range
|
||||
/// A volatility indicator that expresses ATR as a percentage of closing price,
|
||||
/// making it more comparable across different price levels.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The NATR calculation process:
|
||||
/// 1. Calculate True Range (TR):
|
||||
/// TR = max(high-low, abs(high-prevClose), abs(low-prevClose))
|
||||
/// 2. Calculate ATR using SMA of TR
|
||||
/// 3. Normalize by dividing ATR by close price and multiply by 100
|
||||
/// 4. Updates with each new price bar
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Normalized volatility measure
|
||||
/// - Period-based average
|
||||
/// - Trend independent
|
||||
/// - Percentage-based measure
|
||||
/// - Comparable across instruments
|
||||
///
|
||||
/// Formula:
|
||||
/// TR = max(high-low, abs(high-prevClose), abs(low-prevClose))
|
||||
/// ATR = SMA(TR, period)
|
||||
/// NATR = (ATR / Close) * 100
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Cross-market comparison
|
||||
/// - Position sizing
|
||||
/// - Volatility analysis
|
||||
/// - Risk assessment
|
||||
/// - Market regime identification
|
||||
///
|
||||
/// Note: More suitable for comparing volatility across different instruments than ATR
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Natr : AbstractBase
|
||||
{
|
||||
private readonly Sma _ma;
|
||||
private double _prevClose;
|
||||
private const int DefaultPeriod = 14;
|
||||
|
||||
/// <param name="period">The number of periods for NATR calculation (default 14).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Natr(int period = DefaultPeriod)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
|
||||
_ma = new(period);
|
||||
WarmupPeriod = period;
|
||||
Name = $"NATR({period})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for NATR calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Natr(object source, int period = DefaultPeriod) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_prevClose = BarInput.Close;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(BarInput.IsNew);
|
||||
|
||||
// Calculate True Range
|
||||
double hl = BarInput.High - BarInput.Low;
|
||||
double hc = Math.Abs(BarInput.High - _prevClose);
|
||||
double lc = Math.Abs(BarInput.Low - _prevClose);
|
||||
double tr = Math.Max(hl, Math.Max(hc, lc));
|
||||
|
||||
// Calculate ATR
|
||||
double atr = _ma.Calc(tr, BarInput.IsNew);
|
||||
|
||||
// Normalize ATR
|
||||
return (atr / BarInput.Close) * 100.0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// PCH: Price Channel
|
||||
/// A volatility indicator that identifies the highest high and lowest low
|
||||
/// over a specified period, creating a channel that contains price movement.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The PCH calculation process:
|
||||
/// 1. Track highest high over period
|
||||
/// 2. Track lowest low over period
|
||||
/// 3. Calculate midline as average of high and low
|
||||
/// 4. Updates with each new price bar
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Trend following indicator
|
||||
/// - Support/resistance identification
|
||||
/// - Breakout detection
|
||||
/// - Volatility measurement
|
||||
/// - Range-based analysis
|
||||
///
|
||||
/// Formula:
|
||||
/// Upper = Highest High over period
|
||||
/// Lower = Lowest Low over period
|
||||
/// Middle = (Upper + Lower) / 2
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Trend identification
|
||||
/// - Support/resistance levels
|
||||
/// - Breakout trading
|
||||
/// - Volatility analysis
|
||||
/// - Range-bound trading
|
||||
///
|
||||
/// Note: Also known as Donchian Channels
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Pch : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _highs;
|
||||
private readonly CircularBuffer _lows;
|
||||
private const int DefaultPeriod = 20;
|
||||
|
||||
/// <param name="period">The number of periods for PCH calculation (default 20).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Pch(int period = DefaultPeriod)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
|
||||
_highs = new(period);
|
||||
_lows = new(period);
|
||||
WarmupPeriod = period;
|
||||
Name = $"PCH({period})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for PCH calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Pch(object source, int period = DefaultPeriod) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_highs.Add(BarInput.High);
|
||||
_lows.Add(BarInput.Low);
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(BarInput.IsNew);
|
||||
|
||||
// Calculate channel boundaries
|
||||
double upper = _highs.Max();
|
||||
double lower = _lows.Min();
|
||||
|
||||
// Return midline
|
||||
return (upper + lower) / 2.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the upper channel value (highest high)
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public double Upper() => _highs.Max();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the lower channel value (lowest low)
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public double Lower() => _lows.Min();
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// PV: Parkinson Volatility
|
||||
/// A volatility measure that uses the high and low prices to estimate
|
||||
/// volatility, assuming continuous trading and log-normal price distribution.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The PV calculation process:
|
||||
/// 1. Calculate squared log range for each period
|
||||
/// 2. Apply scaling factor (1/4ln2)
|
||||
/// 3. Average over specified period
|
||||
/// 4. Take square root for final volatility
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Range-based volatility
|
||||
/// - More efficient than close-to-close
|
||||
/// - Assumes continuous trading
|
||||
/// - No gap consideration
|
||||
/// - Log-normal distribution
|
||||
///
|
||||
/// Formula:
|
||||
/// PV = sqrt(1/(4*ln(2)*n) * Σ(ln(High/Low))²)
|
||||
/// where n is the number of periods
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Volatility estimation
|
||||
/// - Risk assessment
|
||||
/// - Option pricing
|
||||
/// - Trading system development
|
||||
/// - Market regime identification
|
||||
///
|
||||
/// Note: More efficient than traditional volatility measures but sensitive to gaps
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Pv : AbstractBase
|
||||
{
|
||||
private readonly Sma _ma;
|
||||
private readonly double _scaleFactor;
|
||||
private const int DefaultPeriod = 10;
|
||||
private double _prevValue;
|
||||
|
||||
/// <param name="period">The number of periods for PV calculation (default 10).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Pv(int period = DefaultPeriod)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
|
||||
_ma = new(period);
|
||||
_scaleFactor = 1.0 / (4.0 * Math.Log(2.0));
|
||||
WarmupPeriod = period;
|
||||
Name = $"PV({period})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for PV calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Pv(object source, int period = DefaultPeriod) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
_index++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
if (!BarInput.IsNew)
|
||||
return _prevValue;
|
||||
|
||||
ManageState(true);
|
||||
|
||||
// Calculate log range squared
|
||||
double logRange = Math.Log(BarInput.High / BarInput.Low);
|
||||
double logRangeSquared = logRange * logRange;
|
||||
|
||||
// Apply moving average and scaling
|
||||
double meanLogRangeSquared = _ma.Calc(logRangeSquared, true);
|
||||
|
||||
// Calculate final volatility
|
||||
_prevValue = Math.Sqrt(_scaleFactor * meanLogRangeSquared);
|
||||
return _prevValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// RSV: Rogers-Satchell Volatility
|
||||
/// A volatility measure that accounts for drift in the price process and
|
||||
/// is independent of the mean return level.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The RSV calculation process:
|
||||
/// 1. Calculate log differences between prices
|
||||
/// 2. Combine log differences in specific way
|
||||
/// 3. Average over specified period
|
||||
/// 4. Take square root for final volatility
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Drift-independent
|
||||
/// - Uses all price data (HLOC)
|
||||
/// - More efficient estimator
|
||||
/// - Handles trending markets
|
||||
/// - Non-zero mean returns
|
||||
///
|
||||
/// Formula:
|
||||
/// RSV = sqrt(mean(ln(H/C) * ln(H/O) + ln(L/C) * ln(L/O)))
|
||||
/// where H=High, L=Low, O=Open, C=Close
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Volatility estimation
|
||||
/// - Risk measurement
|
||||
/// - Option pricing
|
||||
/// - Trading system development
|
||||
/// - Market regime identification
|
||||
///
|
||||
/// Note: More robust than simple volatility measures in trending markets
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Rsv : AbstractBase
|
||||
{
|
||||
private readonly Sma _ma;
|
||||
private const int DefaultPeriod = 10;
|
||||
private double _prevValue;
|
||||
|
||||
/// <param name="period">The number of periods for RSV calculation (default 10).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Rsv(int period = DefaultPeriod)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
|
||||
_ma = new(period);
|
||||
WarmupPeriod = period;
|
||||
Name = $"RSV({period})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for RSV calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Rsv(object source, int period = DefaultPeriod) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
_index++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
if (!BarInput.IsNew)
|
||||
return _prevValue;
|
||||
|
||||
ManageState(true);
|
||||
|
||||
// Calculate log ratios
|
||||
double lnHC = Math.Log(BarInput.High / BarInput.Close);
|
||||
double lnHO = Math.Log(BarInput.High / BarInput.Open);
|
||||
double lnLC = Math.Log(BarInput.Low / BarInput.Close);
|
||||
double lnLO = Math.Log(BarInput.Low / BarInput.Open);
|
||||
|
||||
// Calculate Rogers-Satchell term
|
||||
double rs = lnHC * lnHO + lnLC * lnLO;
|
||||
|
||||
// Apply moving average and take square root
|
||||
_prevValue = Math.Sqrt(_ma.Calc(rs, true));
|
||||
return _prevValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// SV: Stochastic Volatility
|
||||
/// A volatility measure that models price volatility as a random process,
|
||||
/// capturing both the magnitude and the rate of change in price movements.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The SV calculation process:
|
||||
/// 1. Calculate log returns
|
||||
/// 2. Compute exponentially weighted variance
|
||||
/// 3. Apply smoothing to variance estimate
|
||||
/// 4. Take square root for volatility
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Time-varying volatility
|
||||
/// - Mean-reverting process
|
||||
/// - Captures volatility clustering
|
||||
/// - Handles leverage effects
|
||||
/// - Accounts for fat tails
|
||||
///
|
||||
/// Formula:
|
||||
/// Returns = ln(Close/PrevClose)
|
||||
/// Variance = λ * PrevVariance + (1-λ) * Returns²
|
||||
/// SV = sqrt(Variance)
|
||||
/// where λ is the decay factor
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Option pricing
|
||||
/// - Risk management
|
||||
/// - Trading strategies
|
||||
/// - Portfolio optimization
|
||||
/// - Market regime detection
|
||||
///
|
||||
/// Note: More sophisticated than simple volatility measures, better captures market dynamics
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Sv : AbstractBase
|
||||
{
|
||||
private readonly double _lambda;
|
||||
private readonly Sma _ma;
|
||||
private double _prevClose;
|
||||
private double _prevVariance;
|
||||
private double _prevValue;
|
||||
private const int DefaultPeriod = 20;
|
||||
private const double DefaultLambda = 0.94;
|
||||
|
||||
/// <param name="period">The number of periods for smoothing (default 20).</param>
|
||||
/// <param name="lambda">The decay factor for variance calculation (default 0.94).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1 or lambda is not between 0 and 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Sv(int period = DefaultPeriod, double lambda = DefaultLambda)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
if (lambda <= 0 || lambda >= 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(lambda));
|
||||
|
||||
_lambda = lambda;
|
||||
_ma = new(period);
|
||||
WarmupPeriod = period;
|
||||
Name = $"SV({period},{lambda:F2})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for smoothing.</param>
|
||||
/// <param name="lambda">The decay factor for variance calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Sv(object source, int period = DefaultPeriod, double lambda = DefaultLambda) : this(period, lambda)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_prevClose = BarInput.Close;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
if (!BarInput.IsNew)
|
||||
return _prevValue;
|
||||
|
||||
ManageState(true);
|
||||
|
||||
// Calculate log return
|
||||
double logReturn = Math.Log(BarInput.Close / _prevClose);
|
||||
double squaredReturn = logReturn * logReturn;
|
||||
|
||||
// Update variance estimate
|
||||
_prevVariance = _lambda * _prevVariance + (1.0 - _lambda) * squaredReturn;
|
||||
|
||||
// Apply smoothing and take square root
|
||||
_prevValue = Math.Sqrt(_ma.Calc(_prevVariance, true));
|
||||
return _prevValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// YZV: Yang-Zhang Volatility
|
||||
/// A volatility estimator that combines overnight and trading volatilities,
|
||||
/// providing a more complete picture of price variation while being drift-independent.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The YZV calculation process:
|
||||
/// 1. Calculate overnight (close-to-open) volatility
|
||||
/// 2. Calculate open-to-close volatility
|
||||
/// 3. Calculate Rogers-Satchell volatility
|
||||
/// 4. Combine components with optimal weights
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Drift independence
|
||||
/// - Minimum variance
|
||||
/// - Handles overnight gaps
|
||||
/// - Uses all HLOC prices
|
||||
/// - Optimal weighting
|
||||
///
|
||||
/// Formula:
|
||||
/// YZV = sqrt(Vo + k*Vc + (1-k)*Vrs)
|
||||
/// where:
|
||||
/// Vo = overnight volatility
|
||||
/// Vc = open-to-close volatility
|
||||
/// Vrs = Rogers-Satchell volatility
|
||||
/// k ≈ 0.34 (optimal weight)
|
||||
///
|
||||
/// Market Applications:
|
||||
/// - Option pricing
|
||||
/// - Risk measurement
|
||||
/// - Trading systems
|
||||
/// - Portfolio management
|
||||
/// - Market analysis
|
||||
///
|
||||
/// Note: Most efficient unbiased estimator among drift-independent estimators
|
||||
/// </remarks>
|
||||
[SkipLocalsInit]
|
||||
public sealed class Yzv : AbstractBase
|
||||
{
|
||||
private readonly Sma _maCo; // Close-to-Open
|
||||
private readonly Sma _maOc; // Open-to-Close
|
||||
private readonly Sma _maRs; // Rogers-Satchell
|
||||
private double _prevClose;
|
||||
private double _prevValue;
|
||||
private const double K = 0.34; // Optimal weight
|
||||
private const int DefaultPeriod = 20;
|
||||
|
||||
/// <param name="period">The number of periods for volatility calculation (default 20).</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Yzv(int period = DefaultPeriod)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
|
||||
_maCo = new(period);
|
||||
_maOc = new(period);
|
||||
_maRs = new(period);
|
||||
WarmupPeriod = period;
|
||||
Name = $"YZV({period})";
|
||||
}
|
||||
|
||||
/// <param name="source">The data source object that publishes updates.</param>
|
||||
/// <param name="period">The number of periods for volatility calculation.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Yzv(object source, int period = DefaultPeriod) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_prevClose = BarInput.Close;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
protected override double Calculation()
|
||||
{
|
||||
if (!BarInput.IsNew)
|
||||
return _prevValue;
|
||||
|
||||
ManageState(true);
|
||||
|
||||
// Calculate overnight volatility (close-to-open)
|
||||
double co = Math.Log(BarInput.Open / _prevClose);
|
||||
double vo = _maCo.Calc(co * co, true);
|
||||
|
||||
// Calculate open-to-close volatility
|
||||
double oc = Math.Log(BarInput.Close / BarInput.Open);
|
||||
double vc = _maOc.Calc(oc * oc, true);
|
||||
|
||||
// Calculate Rogers-Satchell volatility component
|
||||
double lnHC = Math.Log(BarInput.High / BarInput.Close);
|
||||
double lnHO = Math.Log(BarInput.High / BarInput.Open);
|
||||
double lnLC = Math.Log(BarInput.Low / BarInput.Close);
|
||||
double lnLO = Math.Log(BarInput.Low / BarInput.Open);
|
||||
double rs = lnHC * lnHO + lnLC * lnLO;
|
||||
double vrs = _maRs.Calc(rs, true);
|
||||
|
||||
// Combine components with optimal weights
|
||||
_prevValue = Math.Sqrt(vo + K * vc + (1.0 - K) * vrs);
|
||||
return _prevValue;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# Volatility indicators
|
||||
Done: 24, Todo: 11
|
||||
Done: 25, Todo: 10
|
||||
|
||||
✔️ ADR - Average Daily Range
|
||||
✔️ AP - Andrew's Pitchfork
|
||||
@@ -11,28 +11,28 @@ Done: 24, Todo: 11
|
||||
✔️ CE - Chandelier Exit
|
||||
✔️ CV - Conditional Volatility (ARCH/GARCH)
|
||||
✔️ CVI - Chaikin's Volatility
|
||||
*DC - Donchian Channels (Upper, Middle, Lower)
|
||||
✔️ DCHN - Donchian Channels (Upper, Middle, Lower)
|
||||
✔️ EWMA - Exponential Weighted Moving Average Volatility
|
||||
✔️ FCB - Fractal Chaos Bands
|
||||
✔️ GKV - Garman-Klass Volatility
|
||||
✔️ HLV - High-Low Volatility
|
||||
✔️ HV - Historical Volatility
|
||||
*ICH - Ichimoku Cloud (Conversion, Base, Leading Span A, Leading Span B, Lagging Span)
|
||||
✔️ JVOLTY - Jurik Volatility
|
||||
✔️ *JVOLTY - Jurik Volatility (Jvolty, Upper band, Lower band)
|
||||
*KC - Keltner Channels (Upper, Middle, Lower)
|
||||
NATR - Normalized Average True Range
|
||||
PCH - Price Channel Indicator
|
||||
✔️ NATR - Normalized Average True Range
|
||||
✔️ PCH - Price Channel Indicator
|
||||
*PSAR - Parabolic Stop and Reverse (Value, Trend)
|
||||
PV - Parkinson Volatility
|
||||
RSV - Rogers-Satchell Volatility
|
||||
✔️ PV - Parkinson Volatility
|
||||
✔️ RSV - Rogers-Satchell Volatility
|
||||
✔️ RV - Realized Volatility
|
||||
✔️ RVI - Relative Volatility Index
|
||||
*STARC - Starc Bands (Upper, Middle, Lower)
|
||||
SV - Stochastic Volatility
|
||||
✔️ SV - Stochastic Volatility
|
||||
✔️ TR - True Range
|
||||
✔️ UI - Ulcer Index
|
||||
✔️ *VC - Volatility Cone (Mean, Upper Bound, Lower Bound)
|
||||
✔️ VOV - Volatility of Volatility
|
||||
✔️ VR - Volatility Ratio
|
||||
✔️ *VS - Volatility Stop (Long Stop, Short Stop)
|
||||
YZV - Yang-Zhang Volatility
|
||||
✔️ YZV - Yang-Zhang Volatility
|
||||
|
||||
Reference in New Issue
Block a user