From 152031815b0425d9e56bd018caeb64867de51c1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:44:39 +0000 Subject: [PATCH 1/3] Bump System.Text.Json Bumps the nuget group with 1 update in the /archive/Tests directory: [System.Text.Json](https://github.com/dotnet/runtime). Updates `System.Text.Json` from 8.0.0-preview.3.23174.8 to 8.0.4 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.0-preview.3.23174.8...v8.0.4) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production dependency-group: nuget ... Signed-off-by: dependabot[bot] --- archive/Tests/Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archive/Tests/Tests.csproj b/archive/Tests/Tests.csproj index 41673a8b..13369b4e 100644 --- a/archive/Tests/Tests.csproj +++ b/archive/Tests/Tests.csproj @@ -28,7 +28,7 @@ - + From 014625afc593c94c39b37f9554172ed3adc08bcc Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Fri, 25 Oct 2024 22:21:02 -0700 Subject: [PATCH 2/3] Cleanup of indicators --- docs/indicators/indicators.md | 213 +++++++++++++------------ docs/styles.css | 2 +- lib/{volatility => oscillators}/Cmo.cs | 3 - 3 files changed, 115 insertions(+), 103 deletions(-) rename lib/{volatility => oscillators}/Cmo.cs (96%) diff --git a/docs/indicators/indicators.md b/docs/indicators/indicators.md index 4ef85e51..e68c12a9 100644 --- a/docs/indicators/indicators.md +++ b/docs/indicators/indicators.md @@ -4,39 +4,107 @@ ✔️= Validation tests passed
❌= Issue -|**VOLATILITY INDICATORS**|QuanTALib|Skender.Stock|TALib.NETCore| + +|**MOMENTUM INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore| |--|:--:|:--:|:--:| +|*DMI - Directional Movement Index|`?`|GetDmi|| +|*DMX - Jurik Directional Movement Index|`?`||| +|*MOM - Momentum|`?`||| +|*VEL - Jurik Signal Velocity|`?`||| +|ADX - Average Directional Movement Index|`?`|GetAdx|Adx| +|ADXR - Average Directional Movement Index|`?`|Rating|Adxr| +|APO - Absolute Price Oscillator|`?`|Apo|| +|DPO - Detrended Price Oscillator|`?`|GetDpo|| +|MACD - Movign Average Convergence/Divergence|`?`||| +|PO - Price Oscillator|`?`||| +|PPO - Percentage Price Oscillator|`?`||| +|PMO - Price Momentum Oscillator|`?`|GetPmo|| +|PRS - Price Relative Strength|`?`|GetPrs|| +|ROC - Rate of Change|`?`|GetRoc|| +|TRIX - 1-day ROC of TEMA|`?`|GetTrix|| +|VORTEX - Vortex Indicator|`?`||| +
+|**VOLATILITY INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore| +|ADR - Average Daily Range|||| +|ANDREW - Andrew's Pitchfork|||| +|ATR - Average True Range|`Atr`|GetAtr|Atr| +|ATRP - Average True Range Percent|||| +|ATRSTOP - ATR Trailing Stop ||GetAtrStop|| +|BBANDS - Bollinger Bands®||BollingerBands|| +|CHAND - Chandelier Exit||GetChandelier|| +|CVI - Chaikins Volatility|||| +|DON - Donchian Channels||GetDonchian|| +|FCB - Fractal Chaos Bands||GetFcb|| +|HV - Historical Volatility|||| +|ICH - Ichimoku Cloud||GetIchimoku|| +|KEL - Keltner Channels||GetKeltner|| +|NATR - Normalized Average True Range||GetAtr|| +|CHN - Price Channel Indicator|||| +|SAR - Parabolic Stop and Reverse||GetParabolicSar|| +|STARC - Starc Bands||GetStarcBands|| +|TR - True Range|||| +|UI - Ulcer Index||GetUlcerIndex|| +|VSTOP - Volatility Stop||GetVolatilityStop|| +
+|**OSCILLATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore| +|RSI - Relative Strength Index|`Rsi`|GetRsi|| +|RSX - Jurik Trend Strength Index|`Rsx`||| +|AC - Acceleration Oscillator||||| +|AO - Awesome Oscillator||GetAwesome||| +|AROON - Aroon oscillator||GetAroon|Aroon|| +|BOP - Balance of Power||GetBop|Bop|| +|CCI - Commodity Channel Index||GetCci|Cci|| +|CFO - Chande Forcast Oscillator||||| +|CMO - Chande Momentum Oscillator||GetCmo|Cmo|| +|CHOP - Choppiness Index||GetChop||| +|COG - Ehler's Center of Gravity||||| +|COPPOCK - Coppock Curve||||| +|CRSI - Connor RSI||GetConnorsRsi||| +|CTI - Ehler's Correlation Trend Indicator||||| +|DOSC - Derivative Oscillator||||| +|EFI - Elder Ray's Force Index||GetElderRay||| +|FISHER - Fisher Transform||||| +|FOSC - Forecast Oscillator|||||| +|GATOR - Williams Alliator Oscillator||GetGator||| +|KDJ - KDJ Indicator (trend reversal)||||| +|KRI - Kairi Relative Index||||| +|RVGI - Relative Vigor Index||||| +|SMI - Stochastic Momentum Index||GetSmi||| +|SRSI - Stochastic RSI||GetStochRsi||| +|STC - Schaff Trend Cycle||GetStc||| +|STOCH - Stochastic Oscillator||`GetStoch||| +|TSI - True Strength Index||GetTsi||| +|UO - Ultimate Oscillator||GetUltimate||| +|WILLR - Larry Williams' %R||GetWilliamsR||| +
+|**VOLUME INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore| |ADL - Chaikin Accumulation Distribution Line||GetAdl|Ad|| |ADOSC - Chaikin Accumulation Distribution Oscillator||GetChaikinOsc|AdOsc|| -|ATR - Average True Range|`Atr`|GetAtr|Atr|| -|ATRP - Average True Range Percent||||| -|ATRSTOP - ATR Trailing Stop ||GetAtrStop||| -|BBANDS - Bollinger Bands®||BollingerBands||| -|CHAND - Chandelier Exit||GetChandelier||| -|CRSI - Connor RSI||GetConnorsRsi||| -|CVI - Chaikins Volatility||||| -|DON - Donchian Channels||GetDonchian||| -|FCB - Fractal Chaos Bands||GetFcb||| -|FISHER - Fisher Transform||||| -|HV - Historical Volatility||||| -|ICH - Ichimoku Cloud||GetIchimoku||| -|KEL - Keltner Channels||GetKeltner||| -|NATR - Normalized Average True Range||GetAtr||| -|CHN - Price Channel Indicator||||| -|RSI - Relative Strength Index|`Rsi`|GetRsi||| -|SAR - Parabolic Stop and Reverse||GetParabolicSar||| -|SRSI - Stochastic RSI||GetStochRsi||| -|STARC - Starc Bands||GetStarcBands||| -|TR - True Range||||| -|UI - Ulcer Index||GetUlcerIndex||| -|VSTOP - Volatility Stop||GetVolatilityStop||| -|**NUMERICAL ANALYSIS**|QuanTALib|Skender.Stock|TALib.NETCore| +|AOBV - Archer On-Balance Volume||||| +|CMF - Chaikin Money Flow||GetCmf||| +|EOM - Ease of Movement||||| +|KVO - Klinger Volume Oscillator||GetKvo|||| +|MFI - Money Flow Index||GetMfi||| +|NVI - Negative Volume Index||||| +|OBV - On-Balance Volume||GetObv||| +|PVI - Positive Volume Index||||| +|PVOL - Price-Volume||||| +|PVO - Percentage Volume Oscillator||GetPvo||| +|PVR - Price Volume Rank||||| +|PVT - Price Volume Trend||||| +|TVI - Trade Volume Index||||| +|VP - Volume Profile||||| +|VWAP - Volume Weighted Average Price||GetVwap||| +|VWMA - Volume Weighted Moving Average||GetVwma|||| +
+|**NUMERICAL ANALYSIS**|**QuanTALib**|Skender.Stock|TALib.NETCore| |BETA - Beta coefficient||||| |CORR - Correlation Coefficient||||| |CURVATURE - Rate of Change in Direction or Slope|`Curvature`|||| |ENTROPY - Measure of Uncertainty or Disorder|`Entropy`|||| |KURTOSIS - Measure of Tails/Peakedness|`Kurtosis`|||| |HUBER - Huber Loss|`Huberloss`|||| +|HURST - Hurst Exponent||GetHurst||| |MAX - Maximum with exponential decay|`Max`|||| |MEDIAN - Middle value|`Median`|||| |MIN - Minimum with exponential decay|`Min`|||| @@ -47,9 +115,11 @@ |SLOPE - Rate of Change, Linear Regression|`Slope`|||| |STDDEV - Standard Deviation, Measure of Spread|`Stddev`|||| |THEIL - Theil's U Statistics||||| +|TSF - Time Series Forecast|||`✔️`|`✔️`| |VARIANCE - Average of Squared Deviations|`Variance`|||| |ZSCORE - Standardized Score|`Zscore`|||| -|**ERRORS**|QuanTALib|Skender.Stock|TALib.NETCore| +
+|**ERRORS**|**QuanTALib**|Skender.Stock|TALib.NETCore| |MAE - Mean Absolute Error|`Mae`|||| |MAPD - Mean Absolute Percentage Deviation|`Mapd`|||| |MAPE - Mean Absolute Percentage Error|`Mape`|||| @@ -64,13 +134,14 @@ |RSE - Relateive Squared Error|`Rse`|||| |RMSLE - Root Mean Squared Logarithmic Error|`Rmsle`|||| |SMAPE - Symmetric Mean Absolute Percentage Error|`Smape`|||| -|**AVERAGES & TRENDS**QuanTALib|Skender.Stock|TALib.NETCore| +
+|**AVERAGES & TRENDS**|**QuanTALib**|Skender.Stock|TALib.NETCore| |AFIRMA - Autoregressive Finite Impulse Response Moving Average|`Afirma`|||| -|ALMA - Arnaud Legoux Moving Average|`Alma`|`✔️`||| -|⭐DEMA - Double EMA Average|`Dema`|`⭐`|`⭐`|`⭐`|| +|ALMA - Arnaud Legoux Moving Average|`Alma`|`✔️`|| +|DEMA - Double EMA Average|`Dema`|`✔️`|`✔️`| |DSMA - Deviation Scaled Moving Average|`Dsma`|||| |DWMA - Double WMA Average|`Dwma`|||| -|⭐EMA - Exponential Moving Average|`Ema`|`⭐`|`⭐`|`⭐`|`⭐`| +|EMA - Exponential Moving Average|`Ema`|`⭐`|`⭐`|`⭐`|`⭐`| |EPMA - Endpoint Moving Average|`Epma`|`✔️`||| |FRAMA - Fractal Adaptive Moving Average|`Frama`|||| |FWMA - Fibonacci Weighted Moving Average|`Fwma`|||| @@ -80,87 +151,31 @@ |HMA - Hull Moving Average|`Hma`|`✔️`||`✔️`| |HWMA - Holt-Winter Moving Average|`Hwma`|||| |JMA - Jurik Moving Average|`Jma`|||| +|JORDAN - Jordan Moving Average||||| |KAMA - Kaufman's Adaptive Moving Average|`Kama`|`✔️`|`✔️`|`✔️`| -|KDJ - KDJ Indicator (trend reversal)||||| |LTMA - Laguerre Transform Moving Average|`Ltma`|||| |MAAF - Median-Average Adaptive Filter|`Maaf`|||| |MAMA - MESA Adaptive Moving Average|`Mama`|`✔️`|`✔️`|| |MGDI - McGinley Dynamic Indicator|`Mgdi`|`✔️`||| +|MLMA - Minimal Lag Moving Average||||| |MMA - Modified Moving Average|`Mma`|||| |PPMA - Pivot Point Moving Average||||| |PWMA - Pascal's Weighted Moving Average|`Pwma`|||| |QEMA - Quad Exponential Moving Average|`Qema`|||| |RMA - WildeR's Moving Average|`Rma`|||| |SINEMA - Sine Weighted Moving Average|`Sinema`|||| -|⭐SMA - Simple Moving Average|`Sma`|`⭐`|`⭐`|`⭐`|`⭐`| -|SMMA - Smoothed Moving Average|`Smma`|`✔️`||| -|SSF - Ehler's Super Smoother Filter||||| -|SUPERTREND - Supertrend||`✔️`||| -|T3 - Tillson T3 Moving Average|`T3`|`✔️`|`✔️`|| -|TEMA - Triple EMA Average|`Tema`|`✔️`|`✔️`|`✔️`| -|TRIMA - Triangular Moving Average|`Trima`|`✔️`||`✔️`| -|TSF - Time Series Forecast|||`✔️`|`✔️`| -|VIDYA - Variable Index Dynamic Average|`Vidya`|||`✔️`| -|VORTEX - Vortex Indicator||`✔️`||| -|WMA - Weighted Moving Average|`Wma`|`✔️`||`✔️`| -|ZLEMA - Zero Lag EMA Average|`Zlema`|||`✔️`| - -|**MOMENTUM INDICATORS & OSCILLATORS**|QuanTALib|Skender.Stock|TALib.NETCore| -|AC - Acceleration Oscillator||||| -|ADX - Average Directional Movement Index||GetAdx|Adx|| -|ADXR - Average Directional Movement Index||Rating|Adxr|| -|AO - Awesome Oscillator||GetAwesome||| -|APO - Absolute Price Oscillator||Apo||| -|AROON - Aroon oscillator||GetAroon|Aroon|| -|BOP - Balance of Power||GetBop|Bop|| -|CCI - Commodity Channel Index||GetCci|Cci|| -|CFO - Chande Forcast Oscillator||||| -|CMO - Chande Momentum Oscillator||GetCmo|Cmo|| -|CHOP - Choppiness Index||GetChop||| -|COG - Center of Gravity||||| -|COPPOCK - Coppock Curve||||| -|CTI - Ehler's Correlation Trend Indicator||||| -|DPO - Detrended Price Oscillator||GetDpo||| -|DMI - Directional Movement Index||GetDmi||| -|EFI - Elder Ray's Force Index||GetElderRay||| -|FOSC - Forecast oscillator|||||| -|GATOR - Gator oscillator||GetGator||| -|HURST - Hurst Exponent||GetHurst||| -|KRI - Kairi Relative Index||||| -|KVO - Klinger Volume Oscillator||GetKvo|||| -|MACD - Movign Average Convergence/Divergence||`✔️`|`✔️`|| -|MFI - Money Flow Index||GetMfi||| -|MOM - Momentum||||| -|NVI - Negative Volume Index||||| -|PO - Price Oscillator||||| -|PPO - Percentage Price Oscillator||||| -|PMO - Price Momentum Oscillator||GetPmo||| -|PVI - Positive Volume Index||||| -|ROC - Rate of Change||GetRoc||| -|RVGI - Relative Vigor Index||||| -|SMI - Stochastic Momentum Index||GetSmi||| -|STC - Schaff Trend Cycle||GetStc||| -|STOCH - Stochastic Oscillator||`GetStoch||| -|TRIX - 1-day ROC of TEMA||GetTrix||trix.Run| -|TSI - True Strength Index||GetTsi||| -|UO - Ultimate Oscillator||GetUltimate||| -|WILLR - Larry Williams' %R||GetWilliamsR||| -|WGAT - Williams Alligator||GetAlligator||| -|**VOLUME INDICATORS**|QuanTALib|Skender.Stock|TALib.NETCore| -|AOBV - Archer On-Balance Volume||||| -|CMF - Chaikin Money Flow||GetCmf||| -|EOM - Ease of Movement||||| -|KVO - Klinger Volume Oscilaltor||||| -|OBV - On-Balance Volume||GetObv||| -|PRS - Price Relative Strength||`GetPrs||| -|PVOL - Price-Volume||||| -|PVO - Percentage Volume Oscillator||GetPvo||| -|PVR - Price Volume Rank||||| -|PVT - Price Volume Trend||||| -|VP - Volume Profile||||| -|VWAP - Volume Weighted Average Price||GetVwap||| -|VWMA - Volume Weighted Moving Average||GetVwma|||| -|**BASIC TRANSFORMS**|QuanTALib|Skender.Stock|TALib.NETCore| +|SMA - Simple Moving Average|`Sma`||| +|SMMA - Smoothed Moving Average|`Smma`|`✔️`|| +|SSF - Ehler's Super Smoother Filter|||| +|SUPERTREND - Supertrend||`✔️`|| +|T3 - Tillson T3 Moving Average|`T3`|`✔️`|`✔️`| +|TEMA - Triple EMA Average|`Tema`|`✔️`|`✔️`| +|TRIMA - Triangular Moving Average|`Trima`|`✔️`|| +|VIDYA - Variable Index Dynamic Average|`Vidya`||| +|WMA - Weighted Moving Average|`Wma`|`✔️`|| +|ZLEMA - Zero Lag EMA Average|`Zlema`||| +
+|**BASIC TRANSFORMS**|**QuanTALib**|Skender.Stock|TALib.NETCore| |OC2 - Midpoint price|️`.OC2`|CandlePart.OC2|MidPoint| |HL2 - Median Price|️`.HL2`|CandlePart.HL2|MedPrice| |HLC3 - Typical Price|️`.HLC3`|CandlePart.HLC3|TypPrice| diff --git a/docs/styles.css b/docs/styles.css index 143773fa..5f30ab96 100644 --- a/docs/styles.css +++ b/docs/styles.css @@ -97,7 +97,7 @@ --table-row-odd-background: var(--mono-shade2); /* Layout */ - --content-max-width: 100em; + --content-max-width: 75em; /* Cover */ --cover-margin: 0 auto; diff --git a/lib/volatility/Cmo.cs b/lib/oscillators/Cmo.cs similarity index 96% rename from lib/volatility/Cmo.cs rename to lib/oscillators/Cmo.cs index df64d3a9..0b8d92c5 100644 --- a/lib/volatility/Cmo.cs +++ b/lib/oscillators/Cmo.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; - namespace QuanTAlib; /// From f55f630ac60b98f1edec8914cf006412348eec01 Mon Sep 17 00:00:00 2001 From: Miha Kralj <31756078+mihakralj@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:19:40 -0700 Subject: [PATCH 3/3] Add CVI - Chaikin's Volatility class and tests Add implementation of CVI - Chaikin's Volatility class and related tests. * **Cvi Class Implementation:** - Add `Cvi` class in `lib/volatility/Cvi.cs` to calculate Chaikin's Volatility. - Use high and low prices for calculation. - Include a constructor with `period` parameter. - Add a method to calculate Chaikin's Volatility. * **Quantower Indicator:** - Add `CviIndicator` class in `quantower/Volatility/CviIndicator.cs`. - Use `Cvi` class for calculation. - Add input parameters for `period` and `showColdValues`. - Implement `OnInit` and `OnUpdate` methods. * **Tests:** - Add a test method for `Cvi` class in `Tests/test_updates_volatility.cs`. - Use random updates to test `Cvi`. - Ensure initial and final values are equal. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/mihakralj/QuanTAlib?shareId=XXXX-XXXX-XXXX-XXXX). --- Tests/test_updates_volatility.cs | 16 ++++ lib/volatility/Cvi.cs | 109 +++++++++++++++++++++++++++ quantower/Volatility/CviIndicator.cs | 54 +++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 lib/volatility/Cvi.cs create mode 100644 quantower/Volatility/CviIndicator.cs diff --git a/Tests/test_updates_volatility.cs b/Tests/test_updates_volatility.cs index f8877a8e..05d43c60 100644 --- a/Tests/test_updates_volatility.cs +++ b/Tests/test_updates_volatility.cs @@ -101,4 +101,20 @@ public class VolatilityUpdateTests Assert.Equal(initialValue, finalValue, precision); } + + [Fact] + public void Cvi_Update() + { + var indicator = new Cvi(period: 14); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } } diff --git a/lib/volatility/Cvi.cs b/lib/volatility/Cvi.cs new file mode 100644 index 00000000..a6895321 --- /dev/null +++ b/lib/volatility/Cvi.cs @@ -0,0 +1,109 @@ +using System.Runtime.CompilerServices; +namespace QuanTAlib; + +/// +/// CVI: Chaikin's Volatility +/// A technical indicator developed by Marc Chaikin that measures the volatility of a financial instrument by comparing the spread between the high and low prices. +/// +/// +/// The CVI calculation process: +/// 1. Calculates the difference between the high and low prices. +/// 2. Applies an exponential moving average (EMA) to the differences. +/// 3. Computes the percentage change in the EMA over a specified period. +/// +/// Key characteristics: +/// - Measures volatility +/// - Uses high and low prices +/// - Percentage-based +/// - EMA smoothing +/// +/// Formula: +/// CVI = (EMA(high - low, period) - EMA(high - low, period, offset)) / EMA(high - low, period, offset) * 100 +/// +/// Market Applications: +/// - Volatility assessment +/// - Trend confirmation +/// - Risk management +/// - Entry/exit timing +/// +/// Sources: +/// Marc Chaikin - Original development +/// https://www.investopedia.com/terms/c/chaikins-volatility.asp +/// +/// Note: Higher CVI values indicate higher volatility +/// + +[SkipLocalsInit] +public sealed class Cvi : AbstractBase +{ + private readonly int _period; + private readonly Ema _ema; + private readonly CircularBuffer _buffer; + private double _prevEma; + + /// The number of periods for CVI calculation. + /// Thrown when period is less than 1. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Cvi(int period) + { + if (period < 1) + { + throw new ArgumentOutOfRangeException(nameof(period), + "Period must be greater than or equal to 1."); + } + _period = period; + _ema = new Ema(period); + _buffer = new CircularBuffer(period); + WarmupPeriod = period; + Name = $"CVI({period})"; + } + + /// The data source object that publishes updates. + /// The number of periods for CVI calculation. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Cvi(object source, int period) : this(period) + { + var pubEvent = source.GetType().GetEvent("Pub"); + pubEvent?.AddEventHandler(source, new BarSignal(Sub)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override void Init() + { + base.Init(); + _ema.Init(); + _buffer.Clear(); + _prevEma = 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void ManageState(bool isNew) + { + if (isNew) + { + _index++; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + protected override double Calculation() + { + ManageState(BarInput.IsNew); + + double highLowDiff = BarInput.High - BarInput.Low; + _buffer.Add(highLowDiff, BarInput.IsNew); + + double ema = _ema.Calc(new TValue(Input.Time, highLowDiff, BarInput.IsNew)).Value; + + double cvi = 0; + if (_index >= _period) + { + double prevEma = _buffer[_buffer.Count - _period]; + cvi = (ema - prevEma) / prevEma * 100; + } + + _prevEma = ema; + IsHot = _index >= WarmupPeriod; + return cvi; + } +} diff --git a/quantower/Volatility/CviIndicator.cs b/quantower/Volatility/CviIndicator.cs new file mode 100644 index 00000000..7a43523f --- /dev/null +++ b/quantower/Volatility/CviIndicator.cs @@ -0,0 +1,54 @@ +using System.Drawing; +using TradingPlatform.BusinessLayer; + +namespace QuanTAlib; + +public class CviIndicator : Indicator, IWatchlistIndicator +{ + [InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)] + public int Periods { get; set; } = 20; + + [InputParameter("Show cold values", sortIndex: 21)] + public bool ShowColdValues { get; set; } = true; + + private Cvi? cvi; + protected LineSeries? CviSeries; + public int MinHistoryDepths => Math.Max(5, Periods * 2); + int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths; + + public CviIndicator() + { + Name = "CVI - Chaikin's Volatility"; + Description = "Measures the volatility of a financial instrument by comparing the spread between the high and low prices."; + SeparateWindow = true; + + CviSeries = new($"CVI {Periods}", Color.Blue, 2, LineStyle.Solid); + AddLineSeries(CviSeries); + } + + protected override void OnInit() + { + cvi = new Cvi(Periods); + base.OnInit(); + } + + protected override void OnUpdate(UpdateArgs args) + { + TBar input = IndicatorExtensions.GetInputBar(this, args); + TValue result = cvi!.Calc(input); + + CviSeries!.SetValue(result.Value); + CviSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here + } + +#pragma warning disable CA1416 // Validate platform compatibility + + public override string ShortName => $"CVI ({Periods})"; + + public override void OnPaintChart(PaintChartEventArgs args) + { + base.OnPaintChart(args); + this.PaintHLine(args, 0.05, new Pen(Color.DarkRed, width: 2)); + this.PaintSmoothCurve(args, CviSeries!, cvi!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2); + } +}