mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-03 03:47:42 +00:00
+semver: feature Cmo, Macd, Rsi, Rsx
This commit is contained in:
+3
-3
@@ -25,7 +25,7 @@ public class BarIndicatorTests
|
||||
private static readonly ITValue[] indicators = new ITValue[]
|
||||
{
|
||||
new Atr(period: 14),
|
||||
new Jvolty(period: 14)
|
||||
|
||||
// Add other TBar-based indicators here
|
||||
};
|
||||
|
||||
@@ -80,14 +80,14 @@ public class BarIndicatorTests
|
||||
if (methods.Count > 0)
|
||||
{
|
||||
// Prefer the method with TBar parameter
|
||||
var method = methods.FirstOrDefault(m =>
|
||||
var method = methods.Find(m =>
|
||||
{
|
||||
var parameters = m.GetParameters();
|
||||
return parameters.Length == 1 && parameters[0].ParameterType == typeof(TBar);
|
||||
});
|
||||
|
||||
// If not found, return the first method
|
||||
return method ?? methods.First();
|
||||
return method ?? methods[0];
|
||||
}
|
||||
|
||||
type = type.BaseType!;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace QuanTAlib
|
||||
{
|
||||
public class QuantowerTests
|
||||
{
|
||||
private void TestIndicator<T>(string fieldName = "ma") where T : Indicator, new()
|
||||
private static void TestIndicator<T>(string fieldName = "ma") where T : Indicator, new()
|
||||
{
|
||||
var indicator = new T();
|
||||
try
|
||||
@@ -95,7 +95,6 @@ namespace QuanTAlib
|
||||
|
||||
// Volatility Indicators
|
||||
[Fact] public void Atr() => TestIndicator<AtrIndicator>("atr");
|
||||
[Fact] public void Jvolty() => TestIndicator<JvoltyIndicator>("jvolty");
|
||||
|
||||
[Fact] public void Historical() => TestIndicator<HistoricalIndicator>("historical");
|
||||
[Fact] public void Realized() => TestIndicator<RealizedIndicator>("realized");
|
||||
|
||||
@@ -345,7 +345,7 @@ public class SkenderTests
|
||||
var atrValues = quotes.GetAtr(lookbackPeriods: period).Select(i => i.Atr.Null2NaN()!);
|
||||
const int AdditionalPeriods = 500;
|
||||
|
||||
for (int i = QL.Length - 1; i > period + AdditionalPeriods; i--)
|
||||
for (int i = QL.Length - 1; i > 1000 + AdditionalPeriods; i--)
|
||||
{
|
||||
Assert.InRange(atrValues.ElementAt(i) - QL[i].Value, -range, range);
|
||||
}
|
||||
|
||||
@@ -57,21 +57,6 @@ public class VolatilityUpdateTests
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Jvolty_Update()
|
||||
{
|
||||
var indicator = new Jvolty(period: 14);
|
||||
double initialValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: true));
|
||||
|
||||
for (int i = 0; i < RandomUpdates; i++)
|
||||
{
|
||||
indicator.Calc(GetRandomBar(false));
|
||||
}
|
||||
double finalValue = indicator.Calc(new TBar(DateTime.Now, ReferenceValue, ReferenceValue, ReferenceValue, ReferenceValue, 1000, IsNew: false));
|
||||
|
||||
Assert.Equal(initialValue, finalValue, precision);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Realized_Update()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
AC,Acceleration Oscillator
|
||||
AD,Chaikin A/D Line
|
||||
ADOSC,Chaikin A/D Oscillator
|
||||
ADL,Accumulation / Distribution Line
|
||||
ADX,Average Directional Movement Index
|
||||
ADXR,Average Directional Movement Index Rating
|
||||
Alligator,Alligator Indicator
|
||||
ALMA,Arnaud Legoux Moving Average
|
||||
AO,Awesome Oscillator
|
||||
APO,Absolute Price Oscillator
|
||||
AROON,Aroon Indicator
|
||||
AROONOSC,Aroon Oscillator
|
||||
ATS,ATR Trailing Stop
|
||||
ATR,Average True Range
|
||||
AVGPRICE,Average Price
|
||||
BB,Bollinger Bands
|
||||
BBF,Bollinger Bands Flat
|
||||
BBP,Bull and Bear Power
|
||||
BC,Beta Coefficient
|
||||
BETA,Beta
|
||||
BOP,Balance of Power
|
||||
CCI,Commodity Channel Index
|
||||
CE,Chandelier Exit
|
||||
Channel,Price Channel
|
||||
CI,Choppiness Index
|
||||
CMF,Chaikin Money Flow
|
||||
CMO,Chande Momentum Oscillator
|
||||
CORREL,Pearson's Correlation Coefficient
|
||||
CRSI,ConnorsRSI
|
||||
DC,Donchian Channels
|
||||
DCP,Dominant Cycle Periods
|
||||
DEMA,Double Exponential Moving Average
|
||||
DMI,Directional Movement Index
|
||||
DPO,Detrended Price Oscillator
|
||||
DX,Directional Movement Index
|
||||
EMA,Exponential Moving Average
|
||||
EPMA,Endpoint Moving Average
|
||||
ERI,Elder-ray Index
|
||||
FCB,Fractal Chaos Bands
|
||||
FI,Force Index
|
||||
GO,Gator Oscillator
|
||||
HE,Hurst Exponent
|
||||
HMA,Hull Moving Average
|
||||
HT_TRENDLINE,Hilbert Transform - Instantaneous Trendline
|
||||
HT_TRENDMODE,Hilbert Transform - Trend vs Cycle Mode
|
||||
HV,Historical Volatility
|
||||
IC,Ichimoku Cloud
|
||||
KAMA,Kaufman Adaptive Moving Average
|
||||
KDJ,KDJ Index
|
||||
Keltner,Keltner Channel
|
||||
KVO,Klinger Volume Oscillator
|
||||
LINEARREG,Linear Regression
|
||||
LINEARREG_ANGLE,Linear Regression Angle
|
||||
LINEARREG_INTERCEPT,Linear Regression Intercept
|
||||
LINEARREG_SLOPE,Linear Regression Slope
|
||||
LSMA,Least Squares Moving Average
|
||||
LWMA,Linearly Weighted Moving Average
|
||||
MACDEXT,MACD with controllable MA type
|
||||
MACDFIX,Moving Average Convergence Divergence Fix 12/26
|
||||
MAD,Mean absolute deviation
|
||||
MAE,Moving Average Envelope
|
||||
MAMA,MESA Adaptive Moving Average
|
||||
MAPE,Mean absolute percentage error
|
||||
MAX,Highest value over a specified period
|
||||
MAXINDEX,Index of highest value over a specified period
|
||||
MD,McGinley Dynamic
|
||||
MEDPRICE,Median Price
|
||||
MFI,Money Flow Index
|
||||
MIN,Lowest value over a specified period
|
||||
MININDEX,Index of lowest value over a specified period
|
||||
MINMAX,Lowest and highest values over a specified period
|
||||
MINMAXINDEX,Indexes of lowest and highest values over a period
|
||||
MMA,Modified Moving Average
|
||||
MOM,Momentum
|
||||
MSE,Mean square error
|
||||
NATR,Normalized Average True Range
|
||||
OBV,On Balance Volume
|
||||
OsMA,Moving Average of Oscillator
|
||||
PAZ,Price Action Zones
|
||||
Pivots,Pivots
|
||||
PMO,Price Momentum Oscillator
|
||||
PP,Pivot Points
|
||||
PPO,Percentage Price Oscillator
|
||||
PPMA,Pivot Point Moving Average
|
||||
PRS,Price Relative Strength
|
||||
PVI,Positive Volume Index
|
||||
PVO,Percentage Volume Oscillator
|
||||
Qstick,Qstick Indicator
|
||||
R2,R-Squared (Coefficient of Determination)
|
||||
Regression,Regression Line Indicator
|
||||
RLW,%R Larry Williams
|
||||
RMA,Running Moving Average
|
||||
ROC,Rate of Change
|
||||
ROCB,ROC with Bands
|
||||
RPP,Rolling Pivot Points
|
||||
RRA,Rescaled Range Analysis
|
||||
RSI,Relative Strength Index
|
||||
SAR,Parabolic SAR
|
||||
SAREXT,Parabolic SAR - Extended
|
||||
SDC,Standard Deviation Channels
|
||||
SI,Swing Index
|
||||
SLR,Slope and Linear Regression
|
||||
SMA,Simple Moving Average
|
||||
SMI,Stochastic Momentum Index
|
||||
SMMA,Smoothed Moving Average
|
||||
ST,SuperTrend
|
||||
STARC,STARC Bands
|
||||
STC,Schaff Trend Cycle
|
||||
STDDEV,Standard Deviation
|
||||
STOCH,Stochastic
|
||||
STOCHF,Stochastic Fast
|
||||
STOCHRSI,Stochastic Relative Strength Index
|
||||
SUM,Summation
|
||||
T3,Triple Exponential Moving Average (T3)
|
||||
TEMA,Triple Exponential Moving Average
|
||||
TRANGE,True Range
|
||||
TRIMA,Triangular Moving Average
|
||||
TRIX,1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
|
||||
TSI,True Strength Index
|
||||
TYPPRICE,Typical Price
|
||||
UI,Ulcer Index
|
||||
ULTOSC,Ultimate Oscillator
|
||||
VAR,Variance
|
||||
VI,Vortex Indicator
|
||||
Volume,Volume Indicator
|
||||
VS,Volatility Stop
|
||||
VWAP,Volume Weighted Average Price
|
||||
VWMA,Volume Weighted Moving Average
|
||||
WA,Williams Alligator
|
||||
WCLPRICE,Weighted Close Price
|
||||
WF,Williams Fractal
|
||||
WMA,Weighted Moving Average
|
||||
ZS,Z-Score
|
||||
ZZ,ZigZag Indicator
|
||||
|
+313
-5
@@ -1,5 +1,313 @@
|
||||
# Backlog and done
|
||||
|
||||
|**QT**|**Chart**|Cmnt|Docs|isNew|Validation|
|
||||
|--|:--:|:--:|:--:|:--:|:--:|
|
||||
|AFIRMA|✔️|||||
|
||||
| AD | Chaikin A/D Line |
|
||||
| AROON | Aroon Indicator |
|
||||
| ADX | Average Directional Movement Index |
|
||||
| ADXR | Average Directional Movement Index Rating |
|
||||
| DX | Directional Movement Index |
|
||||
| SAR | Parabolic SAR |
|
||||
| SAREXT | Parabolic SAR - Extended |
|
||||
| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline |
|
||||
| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode |
|
||||
| ZZ | ZigZag Indicator |
|
||||
| DMI | Directional Movement Index |
|
||||
| Alligator | Alligator Indicator |
|
||||
| Regression | Regression Line Indicator |
|
||||
| SI | Swing Index |
|
||||
| ATS | ATR Trailing Stop |
|
||||
| ERI | Elder-ray Index |
|
||||
| GO | Gator Oscillator |
|
||||
| HE | Hurst Exponent |
|
||||
| IC | Ichimoku Cloud |
|
||||
| ST | SuperTrend |
|
||||
| VI | Vortex Indicator |
|
||||
| WA | Williams Alligator |
|
||||
| RSI | Relative Strength Index |
|
||||
| CCI | Commodity Channel Index |
|
||||
| MOM | Momentum |
|
||||
| ROC | Rate of Change |
|
||||
| PPO | Percentage Price Oscillator |
|
||||
| AO | Awesome Oscillator |
|
||||
| CMO | Chande Momentum Oscillator |
|
||||
| TRIX | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA |
|
||||
| ULTOSC | Ultimate Oscillator |
|
||||
| AROONOSC | Aroon Oscillator |
|
||||
| ADOSC | Chaikin A/D Oscillator |
|
||||
| APO | Absolute Price Oscillator |
|
||||
| STOCH | Stochastic |
|
||||
| STOCHF | Stochastic Fast |
|
||||
| STOCHRSI | Stochastic Relative Strength Index |
|
||||
| Qstick | Qstick Indicator |
|
||||
| RLW | %R Larry Williams |
|
||||
| AC | Acceleration Oscillator |
|
||||
| TSI | True Strength Index |
|
||||
| CRSI | ConnorsRSI |
|
||||
| DPO | Detrended Price Oscillator |
|
||||
| KDJ | KDJ Index |
|
||||
| STC | Schaff Trend Cycle |
|
||||
| SMI | Stochastic Momentum Index |
|
||||
| BB | Bollinger Bands |
|
||||
| Keltner | Keltner Channel |
|
||||
| BBF | Bollinger Bands Flat |
|
||||
| Channel | Price Channel |
|
||||
| MAE | Moving Average Envelope |
|
||||
| PAZ | Price Action Zones |
|
||||
| DC | Donchian Channels |
|
||||
| FCB | Fractal Chaos Bands |
|
||||
| PP | Pivot Points |
|
||||
| RPP | Rolling Pivot Points |
|
||||
| STARC | STARC Bands |
|
||||
| SDC | Standard Deviation Channels |
|
||||
| OBV | On Balance Volume |
|
||||
| PVI | Positive Volume Index |
|
||||
| Volume | Volume Indicator |
|
||||
| MFI | Money Flow Index |
|
||||
| ADL | Accumulation / Distribution Line |
|
||||
| CMF | Chaikin Money Flow |
|
||||
| FI | Force Index |
|
||||
| KVO | Klinger Volume Oscillator |
|
||||
| PVO | Percentage Volume Oscillator |
|
||||
| ATS | ATR Trailing Stop |
|
||||
| CE | Chandelier Exit |
|
||||
| SAR | Parabolic SAR |
|
||||
| ST | SuperTrend |
|
||||
| VS | Volatility Stop |
|
||||
| Pivots | Pivots |
|
||||
| WF | Williams Fractal |
|
||||
| EMA | Exponential Moving Average |
|
||||
| SMA | Simple Moving Average |
|
||||
| LWMA | Linearly Weighted Moving Average |
|
||||
| SMMA | Smoothed Moving Average |
|
||||
| MMA | Modified Moving Average |
|
||||
| KAMA | Kaufman Adaptive Moving Average |
|
||||
| DEMA | Double Exponential Moving Average |
|
||||
| TEMA | Triple Exponential Moving Average |
|
||||
| MAMA | MESA Adaptive Moving Average |
|
||||
| TRIMA | Triangular Moving Average |
|
||||
| T3 | Triple Exponential Moving Average (T3) |
|
||||
| PPMA | Pivot Point Moving Average |
|
||||
| WMA | Weighted Moving Average |
|
||||
| ALMA | Arnaud Legoux Moving Average |
|
||||
| EPMA | Endpoint Moving Average |
|
||||
| HMA | Hull Moving Average |
|
||||
| LSMA | Least Squares Moving Average |
|
||||
| MD | McGinley Dynamic |
|
||||
| RMA | Running Moving Average |
|
||||
| VWAP | Volume Weighted Average Price |
|
||||
| VWMA | Volume Weighted Moving Average |
|
||||
| ATR | Average True Range |
|
||||
| NATR | Normalized Average True Range |
|
||||
| TRANGE | True Range |
|
||||
| STDDEV | Standard Deviation |
|
||||
| HV | Historical Volatility |
|
||||
| BOP | Balance of Power |
|
||||
| BBP | Bull and Bear Power |
|
||||
| CI | Choppiness Index |
|
||||
| DCP | Dominant Cycle Periods |
|
||||
| PMO | Price Momentum Oscillator |
|
||||
| PRS | Price Relative Strength |
|
||||
| ROCB | ROC with Bands |
|
||||
| RRA | Rescaled Range Analysis |
|
||||
| UI | Ulcer Index |
|
||||
| CORREL | Pearson's Correlation Coefficient |
|
||||
| BETA | Beta |
|
||||
| VAR | Variance |
|
||||
| AVGPRICE | Average Price |
|
||||
| MEDPRICE | Median Price |
|
||||
| TYPPRICE | Typical Price |
|
||||
| WCLPRICE | Weighted Close Price |
|
||||
| SUM | Summation |
|
||||
| MAX | Highest value over a specified period |
|
||||
| MIN | Lowest value over a specified period |
|
||||
| MAXINDEX | Index of highest value over a specified period |
|
||||
| MININDEX | Index of lowest value over a specified period |
|
||||
| MINMAX | Lowest and highest values over a specified period |
|
||||
| MINMAXINDEX | Indexes of lowest and highest values over a period |
|
||||
| BC | Beta Coefficient |
|
||||
| MAD | Mean absolute deviation |
|
||||
| MAPE | Mean absolute percentage error |
|
||||
| MSE | Mean square error |
|
||||
| R2 | R-Squared (Coefficient of Determination) |
|
||||
| SLR | Slope and Linear Regression |
|
||||
| ZS | Z-Score |
|
||||
| AD | Chaikin A/D Line |
|
||||
| AROON | Aroon Indicator |
|
||||
| ADX | Average Directional Movement Index |
|
||||
| ADXR | Average Directional Movement Index Rating |
|
||||
| DX | Directional Movement Index |
|
||||
| SAR | Parabolic SAR |
|
||||
| SAREXT | Parabolic SAR - Extended |
|
||||
| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline |
|
||||
| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode |
|
||||
| ZZ | ZigZag Indicator |
|
||||
| DMI | Directional Movement Index |
|
||||
| Alligator | Alligator Indicator |
|
||||
| Regression | Regression Line Indicator |
|
||||
| SI | Swing Index |
|
||||
| ATS | ATR Trailing Stop |
|
||||
| ERI | Elder-ray Index |
|
||||
| GO | Gator Oscillator |
|
||||
| HE | Hurst Exponent |
|
||||
| IC | Ichimoku Cloud |
|
||||
| ST | SuperTrend |
|
||||
| VI | Vortex Indicator |
|
||||
| WA | Williams Alligator |
|
||||
| RSI | Relative Strength Index |
|
||||
| CCI | Commodity Channel Index |
|
||||
| MOM | Momentum |
|
||||
| ROC | Rate of Change |
|
||||
| PPO | Percentage Price Oscillator |
|
||||
| AO | Awesome Oscillator |
|
||||
| CMO | Chande Momentum Oscillator |
|
||||
| TRIX | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA |
|
||||
| ULTOSC | Ultimate Oscillator |
|
||||
| AROONOSC | Aroon Oscillator |
|
||||
| ADOSC | Chaikin A/D Oscillator |
|
||||
| APO | Absolute Price Oscillator |
|
||||
| STOCH | Stochastic |
|
||||
| STOCHF | Stochastic Fast |
|
||||
| STOCHRSI | Stochastic Relative Strength Index |
|
||||
| Qstick | Qstick Indicator |
|
||||
| RLW | %R Larry Williams |
|
||||
| AC | Acceleration Oscillator |
|
||||
| TSI | True Strength Index |
|
||||
| CRSI | ConnorsRSI |
|
||||
| DPO | Detrended Price Oscillator |
|
||||
| KDJ | KDJ Index |
|
||||
| STC | Schaff Trend Cycle |
|
||||
| SMI | Stochastic Momentum Index |
|
||||
| BB | Bollinger Bands |
|
||||
| Keltner | Keltner Channel |
|
||||
| BBF | Bollinger Bands Flat |
|
||||
| Channel | Price Channel |
|
||||
| MAE | Moving Average Envelope |
|
||||
| PAZ | Price Action Zones |
|
||||
| DC | Donchian Channels |
|
||||
| FCB | Fractal Chaos Bands |
|
||||
| PP | Pivot Points |
|
||||
| RPP | Rolling Pivot Points |
|
||||
| STARC | STARC Bands |
|
||||
| SDC | Standard Deviation Channels |
|
||||
| OBV | On Balance Volume |
|
||||
| PVI | Positive Volume Index |
|
||||
| Volume | Volume Indicator |
|
||||
| MFI | Money Flow Index |
|
||||
| ADL | Accumulation / Distribution Line |
|
||||
| CMF | Chaikin Money Flow |
|
||||
| FI | Force Index |
|
||||
| KVO | Klinger Volume Oscillator |
|
||||
| PVO | Percentage Volume Oscillator |
|
||||
| ATS | ATR Trailing Stop |
|
||||
| CE | Chandelier Exit |
|
||||
| SAR | Parabolic SAR |
|
||||
| ST | SuperTrend |
|
||||
| VS | Volatility Stop |
|
||||
| Pivots | Pivots |
|
||||
| WF | Williams Fractal |
|
||||
| ALMA | Arnaud Legoux Moving Average |
|
||||
| EPMA | Endpoint Moving Average |
|
||||
| HMA | Hull Moving Average |
|
||||
| LSMA | Least Squares Moving Average |
|
||||
| MD | McGinley Dynamic |
|
||||
| RMA | Running Moving Average |
|
||||
| T3 | Tillson T3 Moving Average |
|
||||
| VWAP | Volume Weighted Average Price |
|
||||
| VWMA | Volume Weighted Moving Average |
|
||||
| BOP | Balance of Power |
|
||||
| BBP | Bull and Bear Power |
|
||||
| CI | Choppiness Index |
|
||||
| DCP | Dominant Cycle Periods |
|
||||
| PMO | Price Momentum Oscillator |
|
||||
| PRS | Price Relative Strength |
|
||||
| ROCB | ROC with Bands |
|
||||
| RRA | Rescaled Range Analysis |
|
||||
| UI | Ulcer Index |
|
||||
| BC | Beta Coefficient |
|
||||
| MAD | Mean absolute deviation |
|
||||
| MAPE | Mean absolute percentage error |
|
||||
| MSE | Mean square error |
|
||||
| R2 | R-Squared (Coefficient of Determination) |
|
||||
| SLR | Slope and Linear Regression |
|
||||
| ZS | Z-Score |
|
||||
| EMA | Exponential Moving Average |
|
||||
| SMA | Simple Moving Average |
|
||||
| LWMA | Linearly Weighted Moving Average |
|
||||
| SMMA | Smoothed Moving Average |
|
||||
| MMA | Modified Moving Average |
|
||||
| KAMA | Kaufman Adaptive Moving Average |
|
||||
| DEMA | Double Exponential Moving Average |
|
||||
| TEMA | Triple Exponential Moving Average |
|
||||
| MAMA | MESA Adaptive Moving Average |
|
||||
| TRIMA | Triangular Moving Average |
|
||||
| T3 | Triple Exponential Moving Average (T3) |
|
||||
| PPMA | Pivot Point Moving Average |
|
||||
| MAE | Moving Average Envelope |
|
||||
| MACD | Moving Average Convergence Divergence |
|
||||
| MACDEXT | MACD with controllable MA type |
|
||||
| MACDFIX | Moving Average Convergence Divergence Fix 12/26 |
|
||||
| OsMA | Moving Average of Oscillator |
|
||||
| Regression | Regression Indicator |
|
||||
| LINEARREG | Linear Regression |
|
||||
| LINEARREG_ANGLE | Linear Regression Angle |
|
||||
| LINEARREG_INTERCEPT | Linear Regression Intercept |
|
||||
| LINEARREG_SLOPE | Linear Regression Slope |
|
||||
| RSI | Relative Strength Index |
|
||||
| CCI | Commodity Channel Index |
|
||||
| MOM | Momentum |
|
||||
| ROC | Rate of Change |
|
||||
| PPO | Percentage Price Oscillator |
|
||||
| AO | Awesome Oscillator |
|
||||
| CMO | Chande Momentum Oscillator |
|
||||
| TRIX | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA |
|
||||
| ULTOSC | Ultimate Oscillator |
|
||||
| AROONOSC | Aroon Oscillator |
|
||||
| ADOSC | Chaikin A/D Oscillator |
|
||||
| APO | Absolute Price Oscillator |
|
||||
| STOCH | Stochastic |
|
||||
| STOCHF | Stochastic Fast |
|
||||
| STOCHRSI | Stochastic Relative Strength Index |
|
||||
| Qstick | Qstick Indicator |
|
||||
| RLW | %R Larry Williams |
|
||||
| AC | Acceleration Oscillator |
|
||||
| TSI | True Strength Index |
|
||||
| AD | Chaikin A/D Line |
|
||||
| AROON | Aroon Indicator |
|
||||
| ADX | Average Directional Movement Index |
|
||||
| ADXR | Average Directional Movement Index Rating |
|
||||
| DX | Directional Movement Index |
|
||||
| SAR | Parabolic SAR |
|
||||
| SAREXT | Parabolic SAR - Extended |
|
||||
| HT_TRENDLINE | Hilbert Transform - Instantaneous Trendline |
|
||||
| HT_TRENDMODE | Hilbert Transform - Trend vs Cycle Mode |
|
||||
| ZZ | ZigZag Indicator |
|
||||
| DMI | Directional Movement Index |
|
||||
| Alligator | Alligator Indicator |
|
||||
| Regression | Regression Line Indicator |
|
||||
| SI | Swing Index |
|
||||
| ATR | Average True Range |
|
||||
| NATR | Normalized Average True Range |
|
||||
| TRANGE | True Range |
|
||||
| STDDEV | Standard Deviation |
|
||||
| HV | Historical Volatility |
|
||||
| BB | Bollinger Bands |
|
||||
| Keltner | Keltner Channel |
|
||||
| BBF | Bollinger Bands Flat |
|
||||
| Channel | Price Channel |
|
||||
| MAE | Moving Average Envelope |
|
||||
| PAZ | Price Action Zones |
|
||||
| OBV | On Balance Volume |
|
||||
| PVI | Positive Volume Index |
|
||||
| Volume | Volume Indicator |
|
||||
| MFI | Money Flow Index |
|
||||
| CORREL | Pearson's Correlation Coefficient |
|
||||
| BETA | Beta |
|
||||
| VAR | Variance |
|
||||
| AVGPRICE | Average Price |
|
||||
| MEDPRICE | Median Price |
|
||||
| TYPPRICE | Typical Price |
|
||||
| WCLPRICE | Weighted Close Price |
|
||||
| SUM | Summation |
|
||||
| MAX | Highest value over a specified period |
|
||||
| MIN | Lowest value over a specified period |
|
||||
| MAXINDEX | Index of highest value over a specified period |
|
||||
| MININDEX | Index of lowest value over a specified period |
|
||||
| MINMAX | Lowest and highest values over a specified period |
|
||||
| MINMAXINDEX | Indexes of lowest and highest values over a period |
|
||||
|
||||
+34
-10
@@ -1,7 +1,34 @@
|
||||
* [QuanTAlib](/)
|
||||
|
||||
* [Home](/)
|
||||
* Introduction
|
||||
* [Overview]()
|
||||
* [Features]()
|
||||
* [Historical vs Real-time analysis](essays/realtime.md)
|
||||
* [Indicators](indicators/indicators.md)
|
||||
* Averages & Trends
|
||||
|
||||
* Core Concepts
|
||||
* [Time Series Data Handling]()
|
||||
* [Calculation classes]()
|
||||
* [Presentation Classes]()
|
||||
|
||||
* QuanTAlib C# Library
|
||||
* [Installation]()
|
||||
* [Quick Start Guide]()
|
||||
* [Usage Examples]()
|
||||
* [Tests and Validation]()
|
||||
|
||||
* Quantower Charts
|
||||
* [Installation]()
|
||||
* [Quick Start Guide]()
|
||||
* [Using VS Code for QuanTower coding](setup/vscode.md)
|
||||
* [Using DotPeek](setup/dotpeek.md)
|
||||
* [Creating Custom Indicators]()
|
||||
* [Inspecting Quantower Internals]()
|
||||
|
||||
* [Available Indicators](indicators/indicators.md)
|
||||
* Basic Transforms
|
||||
* Numerical Analysis
|
||||
* Errors
|
||||
* Moving Averages
|
||||
* [AFIRMA - Adaptive Filtering Integrated Recursive Moving Average](indicators/averages/afirma/afirma.md)
|
||||
* [Calculation](indicators/averages/afirma/calc.md)
|
||||
* [Analysis](indicators/averages/afirma/analysis.md)
|
||||
@@ -14,7 +41,6 @@
|
||||
* [Calculation](indicators/averages/ama/calc.md)
|
||||
* [Analysis](indicators/averages/ama/analysis.md)
|
||||
* [Charts](indicators/averages/ama/charts.md)
|
||||
* [Convolutiuon]
|
||||
* [DEMA - Double Exponential Moving Average](indicators/averages/dema/dema.md)
|
||||
* [Calculation](indicators/averages/dema/calc.md)
|
||||
* [Analysis](indicators/averages/dema/analysis.md)
|
||||
@@ -61,11 +87,9 @@
|
||||
* VIDYA - Variable Index Dynamic Average
|
||||
* WMA - Weighted Moving Average
|
||||
* ZLEMA - Weighted Moving Average
|
||||
* Basic Data Transforms
|
||||
* [Statistics & Numerical Analysis](indicators/statistics/list.md)
|
||||
* Trends
|
||||
* Momentum
|
||||
* Oscillators
|
||||
* Volatility
|
||||
* Volume
|
||||
* Momentum & Oscillators
|
||||
* Development
|
||||
* [VS Code](setup/vscode.md)
|
||||
* [DotPeek](setup/dotpeek.md)
|
||||
|
||||
|
||||
+46
-69
@@ -2,76 +2,38 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Document</title>
|
||||
<title>QuanTAlib Documentation</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="description" content="Description">
|
||||
<meta name="description" content="Documentation for QuanTAlib, a quantitative technical analysis library">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple-dark.css" integrity="sha384-G+RAlt+LEfAH/nY+DZh3+XIhRboypMI32hiJ9BwnmjF41May5BWQKyrDrEkNdV/i" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.css" integrity="sha384-3UiQGuEI4TTMaFmGIZumfRPtfKQ3trwQE2JgosJxCnGmQpL/lJdjpcHkaaFwHlcI" crossorigin="anonymous">
|
||||
|
||||
<style>
|
||||
.markdown-section {
|
||||
max-width: none !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.sidebar-nav {
|
||||
line-height: 1.5;
|
||||
font-size: 12px;
|
||||
}
|
||||
.markdown-section table tbody td {
|
||||
padding: 4px 1px;
|
||||
}
|
||||
:root {
|
||||
--sidebar-width: 350px;
|
||||
--sidebar-nav-link-padding: 2px 0;
|
||||
--sidebar-nav-pagelink-padding: 2px 0 2px 12px;
|
||||
--sidebar-nav-indent: 12px;
|
||||
}
|
||||
.content {
|
||||
left: var(--sidebar-width);
|
||||
}
|
||||
.sidebar-toggle {
|
||||
width: var(--sidebar-width);
|
||||
}
|
||||
/* Updated styles for partially expandable sidebar */
|
||||
.sidebar-nav ul ul ul ul {
|
||||
overflow: hidden;
|
||||
max-height: 0;
|
||||
transition: max-height 0.3s ease-out;
|
||||
}
|
||||
.sidebar-nav ul ul ul li:hover > ul {
|
||||
max-height: 1000px;
|
||||
transition: max-height 0.3s ease-in;
|
||||
}
|
||||
.sidebar-nav .collapse.level-4 > ul {
|
||||
max-height: 0 !important;
|
||||
}
|
||||
.sidebar-nav .collapse.level-4:hover > ul {
|
||||
max-height: 1000px !important;
|
||||
}
|
||||
.sidebar-nav .folder > .app-sub-sidebar {
|
||||
display: block !important;
|
||||
}
|
||||
/* Ensure levels 1, 2, and 3 are always visible */
|
||||
.sidebar-nav > ul,
|
||||
.sidebar-nav > ul > li > ul,
|
||||
.sidebar-nav > ul > li > ul > li > ul {
|
||||
max-height: none !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
name: 'QuanTAlib',
|
||||
repo: 'https://github.com/mihakralj/quantalib',
|
||||
homepage: 'readme.md',
|
||||
loadSidebar: true,
|
||||
subMaxLevel: 4, // Increased to allow for level 4+ items
|
||||
name: '',
|
||||
repo: '',
|
||||
sidebarDisplayLevel: 3, // Changed to keep levels 1, 2, and 3 expanded
|
||||
auto2top: true,
|
||||
mergeNavbar: true,
|
||||
sidebarDisplayLevel: 0, // Add this line to collapse all sidebar items initially
|
||||
search: {
|
||||
maxAge: 86400000,
|
||||
paths: 'auto',
|
||||
placeholder: 'Type to search',
|
||||
noData: 'No Results!',
|
||||
depth: 6,
|
||||
hideOtherSidebarContent: false,
|
||||
},
|
||||
pagination: {
|
||||
previousText: 'Previous',
|
||||
nextText: 'Next',
|
||||
crossChapter: true,
|
||||
crossChapterText: true,
|
||||
},
|
||||
themeable: {
|
||||
readyTransition: true,
|
||||
responsiveTables: true
|
||||
@@ -79,18 +41,33 @@
|
||||
latex: {
|
||||
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
||||
displayMath: [['$$', '$$']],
|
||||
}
|
||||
},
|
||||
executeScript: true,
|
||||
externalLinkTarget: '_blank',
|
||||
cornerExternalLinkTarget: '_blank',
|
||||
relativePath: false,
|
||||
toc: {
|
||||
scope: '.markdown-section',
|
||||
headings: 'h1, h2, h3, h4, h5, h6',
|
||||
title: 'Table of Contents',
|
||||
},
|
||||
copyCode: {
|
||||
buttonText: 'Copy to clipboard',
|
||||
errorText: 'Error',
|
||||
successText: 'Copied'
|
||||
},
|
||||
plugins: [
|
||||
]
|
||||
};
|
||||
</script>
|
||||
<!-- plugins -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js" integrity="sha384-lMHOyuqf3B/T/BgfYxUKprN0bdRf8KhVTE11w76Tvtze86XHVSDYzxqNGDGgIi9I" crossorigin="anonymous"></script>
|
||||
<!-- Docsify v4 -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js" integrity="sha384-KaHhgnx/OTLoJ4J33SSJsF4x1pk4I7q3s5ZOfIDHJYl6IG7Oyn2vNDsHiWJe46fD" crossorigin="anonymous"></script>
|
||||
<!-- docsify-themeable -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/js/docsify-themeable.min.js" integrity="sha384-ibjVZCUwWPrRrNc9BNkbbJvtYmTh8GYDNQgj+2jQVNDudOFgSQWs+Es6JhdoTIvf" crossorigin="anonymous"></script>
|
||||
<!-- KaTeX -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.7/dist/katex.min.js" integrity="sha384-G0zcxDFp5LWZtDuRMnBkk3EphCK1lhEf4UEyEM693ka574TZGwo4IWwS6QLzM/2t" crossorigin="anonymous"></script>
|
||||
<!-- docsify-katex plugin -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-sidebar-collapse/dist/docsify-sidebar-collapse.min.js" integrity="sha384-lMHOyuqf3B/T/BgfYxUKprN0bdRf8KhVTE11w76Tvtze86XHVSDYzxqNGDGgIi9I" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-pagination/dist/docsify-pagination.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-tabs/dist/docsify-tabs.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsify-katex@1.4.3/dist/docsify-katex.js" integrity="sha384-M76M/x5vGyeoej1covQQifl7T945mY+qgzNVrM/urHMCYjP8tnMsx5WCdeLZ74UE" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -4,50 +4,67 @@
|
||||
✔️= Validation tests passed<br>
|
||||
❌= Issue
|
||||
|
||||
|**BASIC TRANSFORMS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|--|:--:|:--:|:--:|:--:|:--:|
|
||||
|OC2 - Midpoint price|️`.OC2`|CandlePart.OC2|MidPoint||
|
||||
|HL2 - Median Price|️`.HL2`|CandlePart.HL2|MedPrice||
|
||||
|HLC3 - Typical Price|️`.HLC3`|CandlePart.HLC3|TypPrice||
|
||||
|OHL3 - Mean Price|`️.OHL3`|CandlePart.OHL3`|||
|
||||
|OHLC4 - Average Price|`️.OHLC4`|CandlePart.OHLC4|AvgPrice||
|
||||
|HLCC4 - Weighted Price|`️.HLCC4`||WclPrice||
|
||||
|<br>||||
|
||||
|**STATISTICS, ERRORS AND NUMERICAL ANALYSIS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|**VOLATILITY 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|
|
||||
|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|||||
|
||||
|HUBER - Huber Loss|`Huberloss`||||
|
||||
|MAX - Maximum with exponential decay|`Max`||||
|
||||
|MEDIAN - Middle value|`Median`||||
|
||||
|MIN - Minimum with exponential decay|`Min`||||
|
||||
|MODE - Most Frequent Value|`Mode`||||
|
||||
|PERCENTILE - Rank Order|`Percentile`||||
|
||||
|RSQUARED - Coefficient of Determination R-Squared|||||
|
||||
|SKEW - Skewness, asymmetry of distribution|`Skew`||||
|
||||
|SLOPE - Rate of Change, Linear Regression|`Slope`||||
|
||||
|STDDEV - Standard Deviation, Measure of Spread|`Stddev`||||
|
||||
|THEIL - Theil's U Statistics|||||
|
||||
|VARIANCE - Average of Squared Deviations|`Variance`||||
|
||||
|ZSCORE - Standardized Score|`Zscore`||||
|
||||
|**ERRORS**|QuanTALib|Skender.Stock|TALib.NETCore|
|
||||
|MAE - Mean Absolute Error|`Mae`||||
|
||||
|MAPD - Mean Absolute Percentage Deviation|`Mapd`||||
|
||||
|MAPE - Mean Absolute Percentage Error|`Mape`||||
|
||||
|MASE - Mean Absolute Scaled Error|`Mase`||||
|
||||
|MDA - Mean Directional Accuracy|||||
|
||||
|ME - Mean Error|`Me`||||
|
||||
|MEDIAN - Middle value|`Median`||||
|
||||
|MIN - Minimum with exponential decay|`Min`||||
|
||||
|MODE - Most Frequent Value|`Mode`||||
|
||||
|MPE - Pean Percentage Error|`Mpe`||||
|
||||
|MSE - Mean Squared Error|`Mse`||||
|
||||
|MSLE - Mean Squared Logarithmic Error|`Msle`||||
|
||||
|PERCENTILE - Rank Order|`Percentile`||||
|
||||
|RSQUARED - Coefficient of Determination R-Squared|||||
|
||||
|RAE - Relative Absolute Error|`Rae`||||
|
||||
|RMSE - Root Mean Squared Error|`Rmse`||||
|
||||
|RSE - Relateive Squared Error|`Rse`||||
|
||||
|RMSLE - Root Mean Squared Logarithmic Error|`Rmsle`||||
|
||||
|SKEW - Skewness, asymmetry of distribution|`Skew`||||
|
||||
|SLOPE - Rate of Change, Linear Regression|`Slope`||||
|
||||
|SMAPE - Symmetric Mean Absolute Percentage Error|`Smape`||||
|
||||
|STDDEV - Standard Deviation, Measure of Spread|`Stddev`||||
|
||||
|THEIL - Theil's U Statistics|||||
|
||||
|VARIANCE - Average of Squared Deviations|`Variance`||||
|
||||
|ZSCORE - Standardized Score|`Zscore`||||
|
||||
|<br>|||||
|
||||
|**AVERAGES & TRENDS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|**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`|`⭐`|`⭐`|`⭐`||
|
||||
@@ -67,7 +84,6 @@
|
||||
|KDJ - KDJ Indicator (trend reversal)|||||
|
||||
|LTMA - Laguerre Transform Moving Average|`Ltma`||||
|
||||
|MAAF - Median-Average Adaptive Filter|`Maaf`||||
|
||||
|MACD - Movign Average Convergence/Divergence||`✔️`|`✔️`||
|
||||
|MAMA - MESA Adaptive Moving Average|`Mama`|`✔️`|`✔️`||
|
||||
|MGDI - McGinley Dynamic Indicator|`Mgdi`|`✔️`|||
|
||||
|MMA - Modified Moving Average|`Mma`||||
|
||||
@@ -80,7 +96,6 @@
|
||||
|SMMA - Smoothed Moving Average|`Smma`|`✔️`|||
|
||||
|SSF - Ehler's Super Smoother Filter|||||
|
||||
|SUPERTREND - Supertrend||`✔️`|||
|
||||
|SWMA - Symmetric Weighted Moving Average|||||
|
||||
|T3 - Tillson T3 Moving Average|`T3`|`✔️`|`✔️`||
|
||||
|TEMA - Triple EMA Average|`Tema`|`✔️`|`✔️`|`✔️`|
|
||||
|TRIMA - Triangular Moving Average|`Trima`|`✔️`||`✔️`|
|
||||
@@ -89,34 +104,8 @@
|
||||
|VORTEX - Vortex Indicator||`✔️`|||
|
||||
|WMA - Weighted Moving Average|`Wma`|`✔️`||`✔️`|
|
||||
|ZLEMA - Zero Lag EMA Average|`Zlema`|||`✔️`|
|
||||
|<br>||||
|
||||
|**VOLATILITY INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|ADL - Chaikin Accumulation Distribution Line||GetAdl|Ad||
|
||||
|ADOSC - Chaikin Accumulation Distribution Oscillator||GetChaikinOsc|AdOsc||
|
||||
|ATR - Average True Range||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||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|||
|
||||
|<br>||||
|
||||
|**MOMENTUM INDICATORS & OSCILLATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|
||||
|**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||
|
||||
@@ -139,6 +128,7 @@
|
||||
|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|||||
|
||||
@@ -156,8 +146,7 @@
|
||||
|UO - Ultimate Oscillator||GetUltimate|||
|
||||
|WILLR - Larry Williams' %R||GetWilliamsR|||
|
||||
|WGAT - Williams Alligator||GetAlligator|||
|
||||
|<br>||||
|
||||
|**VOLUME INDICATORS**|**QuanTALib**|Skender.Stock|TALib.NETCore|Tulip.NETCore|Trady|
|
||||
|**VOLUME INDICATORS**|QuanTALib|Skender.Stock|TALib.NETCore|
|
||||
|AOBV - Archer On-Balance Volume|||||
|
||||
|CMF - Chaikin Money Flow||GetCmf|||
|
||||
|EOM - Ease of Movement|||||
|
||||
@@ -171,3 +160,10 @@
|
||||
|VP - Volume Profile|||||
|
||||
|VWAP - Volume Weighted Average Price||GetVwap|||
|
||||
|VWMA - Volume Weighted Moving Average||GetVwma||||
|
||||
|**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|
|
||||
|OHL3 - Mean Price|`️.OHL3`|CandlePart.OHL3|
|
||||
|OHLC4 - Average Price|`️.OHLC4`|CandlePart.OHLC4|AvgPrice|
|
||||
|HLCC4 - Weighted Price|`️.HLCC4`||WclPrice|
|
||||
+1617
File diff suppressed because it is too large
Load Diff
+58
-6
@@ -2,10 +2,11 @@ namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// EMA: Exponential Moving Average
|
||||
/// EMA needs very short history buffer and calculates the EMA value using just the
|
||||
/// previous EMA value. The weight of the new datapoint (alpha) is alpha = 2 / (period + 1)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// EMA needs very short history buffer and calculates the EMA value using just the
|
||||
/// previous EMA value. The weight of the new datapoint (alpha) is alpha = 2 / (period + 1)
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Uses no buffer, relying only on the previous EMA value.
|
||||
/// - The weight of new data points is calculated as alpha = 2 / (period + 1).
|
||||
@@ -19,19 +20,52 @@ namespace QuanTAlib;
|
||||
/// - https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
|
||||
/// - https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
|
||||
/// </remarks>
|
||||
|
||||
public class Ema : AbstractBase
|
||||
{
|
||||
// inherited _index
|
||||
// inherited _value
|
||||
|
||||
/// <summary>
|
||||
/// The period for the EMA calculation.
|
||||
/// </summary>
|
||||
private readonly int _period;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer for SMA calculation.
|
||||
/// </summary>
|
||||
private CircularBuffer _sma;
|
||||
|
||||
/// <summary>
|
||||
/// The last calculated EMA value.
|
||||
/// </summary>
|
||||
private double _lastEma, _p_lastEma;
|
||||
|
||||
/// <summary>
|
||||
/// Compensator for early EMA values.
|
||||
/// </summary>
|
||||
private double _e, _p_e;
|
||||
|
||||
/// <summary>
|
||||
/// The smoothing factor for EMA calculation.
|
||||
/// </summary>
|
||||
private readonly double _k;
|
||||
|
||||
/// <summary>
|
||||
/// Flags to track initialization status.
|
||||
/// </summary>
|
||||
private bool _isInit, _p_isInit;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to determine whether to use SMA for initial values.
|
||||
/// </summary>
|
||||
private readonly bool _useSma;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Ema class with a specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period for EMA calculation.</param>
|
||||
/// <param name="useSma">Whether to use SMA for initial values. Default is true.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
public Ema(int period, bool useSma = true)
|
||||
{
|
||||
if (period < 1)
|
||||
@@ -47,23 +81,36 @@ public class Ema : AbstractBase
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Ema class with a specified alpha value.
|
||||
/// </summary>
|
||||
/// <param name="alpha">The smoothing factor for EMA calculation.</param>
|
||||
public Ema(double alpha)
|
||||
{
|
||||
_k = alpha;
|
||||
_useSma = false;
|
||||
_sma = new(1);
|
||||
Name = "Ema";
|
||||
_period = 1;
|
||||
WarmupPeriod = (int)Math.Ceiling(Math.Log(0.05) / Math.Log(1 - _k)); //95th percentile
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Ema class with a specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object for event subscription.</param>
|
||||
/// <param name="period">The period for EMA calculation.</param>
|
||||
/// <param name="useSma">Whether to use SMA for initial values. Default is true.</param>
|
||||
public Ema(object source, int period, bool useSma = true) : this(period, useSma)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
//inhereted public void Sub(object source, in ValueEventArgs args)
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Ema instance.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
@@ -74,6 +121,10 @@ public class Ema : AbstractBase
|
||||
_sma = new(_period);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Ema instance.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the input is new.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
@@ -92,8 +143,9 @@ public class Ema : AbstractBase
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Core EMA calculation
|
||||
/// Performs the EMA calculation.
|
||||
/// </summary>
|
||||
/// <returns>The calculated EMA value.</returns>
|
||||
protected override double Calculation()
|
||||
{
|
||||
double result, _ema;
|
||||
@@ -118,7 +170,7 @@ public class Ema : AbstractBase
|
||||
_ema = _k * (Input.Value - _lastEma) + _lastEma;
|
||||
|
||||
// _useSma decides if we use compensator or not
|
||||
result = (_useSma || _e == 0) ? _ema : _ema / (1 - _e);
|
||||
result = (_useSma || _e <= double.Epsilon) ? _ema : _ema / (1 - _e);
|
||||
}
|
||||
_lastEma = _ema;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
+91
-64
@@ -1,68 +1,93 @@
|
||||
/// <summary>
|
||||
/// Represents a Jurik Moving Average, based on known and reverse-engineered insights
|
||||
/// </summary>
|
||||
|
||||
namespace QuanTAlib;
|
||||
//TODO fails consistency test
|
||||
|
||||
public class Jma : AbstractBase
|
||||
{
|
||||
public readonly int Period;
|
||||
private readonly double _period;
|
||||
private readonly double _phase;
|
||||
private readonly int _vshort, _vlong;
|
||||
private readonly CircularBuffer _values;
|
||||
private readonly CircularBuffer _voltyShort;
|
||||
private readonly CircularBuffer _vsumBuff;
|
||||
private readonly CircularBuffer _avoltyBuff;
|
||||
|
||||
private double _beta, _len1, _pow1;
|
||||
private double _upperBand, _lowerBand, _prevMa1, _prevDet0, _prevDet1, _prevJma;
|
||||
private double _p_UpperBand, _p_LowerBand, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma;
|
||||
private double _len1;
|
||||
private double _pow1;
|
||||
private readonly double _beta;
|
||||
private double _upperBand, _lowerBand, _p_upperBand, _p_lowerBand;
|
||||
private double _prevMa1, _prevDet0, _prevDet1, _prevJma, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma;
|
||||
private double _vSum, _p_vSum;
|
||||
|
||||
public Jma(int period, double phase = 0, int vshort = 10)
|
||||
|
||||
public double UpperBand { get; set; }
|
||||
public double LowerBand { get; set; }
|
||||
public double Volty { get; set; }
|
||||
public double Factor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Jma class with the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Jvolty.</param>
|
||||
/// <param name="phase">The phase parameter for the JMA-style calculation.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Jma(int period, int phase = 0, double factor = 0.45, int buffer = 10)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
Period = period;
|
||||
_vshort = vshort;
|
||||
_vlong = 65;
|
||||
Factor = factor;
|
||||
_period = period;
|
||||
_phase = Math.Clamp((phase * 0.01) + 1.5, 0.5, 2.5);
|
||||
|
||||
_values = new CircularBuffer(period);
|
||||
_voltyShort = new CircularBuffer(vshort);
|
||||
_vsumBuff = new CircularBuffer(_vlong);
|
||||
_avoltyBuff = new CircularBuffer(2);
|
||||
_vsumBuff = new CircularBuffer(buffer);
|
||||
_avoltyBuff = new CircularBuffer(65);
|
||||
_beta = factor * (_period - 1) / (factor * (_period - 1) + 2);
|
||||
|
||||
Name = "JMA";
|
||||
WarmupPeriod = period * 2;
|
||||
Init();
|
||||
Name = $"JMA({period})";
|
||||
}
|
||||
|
||||
public Jma(object source, int period, double phase = 0, int vshort = 10) : this(period, phase, vshort)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Jvolty class with the specified source and parameters.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for value updates.</param>
|
||||
/// <param name="period">The period over which to calculate the Jvolty.</param>
|
||||
/// <param name="phase">The phase parameter for the JMA-style calculation.</param>
|
||||
public Jma(object source, int period, int phase = 0, double factor = 0.45, int buffer = 10) : this(period, phase, factor, buffer)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Jma instance by setting up the initial state.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
_upperBand = _lowerBand = _prevMa1 = _prevDet0 = _prevDet1 = _prevJma = 0.0;
|
||||
_p_UpperBand = _p_LowerBand = _p_prevMa1 = _p_prevDet0 = _p_prevDet1 = _p_prevJma = 0.0;
|
||||
_beta = 0.45 * (Period - 1) / (0.45 * (Period - 1) + 2);
|
||||
_len1 = Math.Max((Math.Log(Math.Sqrt(Period - 1)) / Math.Log(2.0)) + 2.0, 0);
|
||||
base.Init();
|
||||
_upperBand = _lowerBand = 0.0;
|
||||
_p_upperBand = _p_lowerBand = 0.0;
|
||||
_len1 = Math.Max((Math.Log(Math.Sqrt(_period - 1)) / Math.Log(2.0)) + 2.0, 0);
|
||||
_pow1 = Math.Max(_len1 - 2.0, 0.5);
|
||||
_avoltyBuff.Clear();
|
||||
_avoltyBuff.Add(0, true);
|
||||
_avoltyBuff.Add(0, true);
|
||||
base.Init();
|
||||
_vsumBuff.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Jma instance based on whether a new value is being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current input is a new value.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
// Save current state
|
||||
_p_UpperBand = _upperBand;
|
||||
_p_LowerBand = _lowerBand;
|
||||
_p_upperBand = _upperBand;
|
||||
_p_lowerBand = _lowerBand;
|
||||
_p_vSum = _vSum;
|
||||
_p_prevMa1 = _prevMa1;
|
||||
_p_prevDet0 = _prevDet0;
|
||||
_p_prevDet1 = _prevDet1;
|
||||
@@ -70,67 +95,69 @@ public class Jma : AbstractBase
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore previous state
|
||||
_upperBand = _p_UpperBand;
|
||||
_lowerBand = _p_LowerBand;
|
||||
_upperBand = _p_upperBand;
|
||||
_lowerBand = _p_lowerBand;
|
||||
_vSum = _p_vSum;
|
||||
_prevMa1 = _p_prevMa1;
|
||||
_prevDet0 = _p_prevDet0;
|
||||
_prevDet1 = _p_prevDet1;
|
||||
_prevJma = _p_prevJma;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Jma calculation for the current value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Jma value for the current input.
|
||||
/// </returns>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
_values.Add(Input.Value, Input.IsNew);
|
||||
|
||||
if (_index == 1)
|
||||
double price = Input.Value;
|
||||
if (_index <= 1)
|
||||
{
|
||||
_prevMa1 = _prevJma = Input.Value;
|
||||
return Input.Value;
|
||||
_upperBand = _lowerBand = price;
|
||||
_prevMa1 = _prevJma = price;
|
||||
}
|
||||
|
||||
double hprice = _values.Max();
|
||||
double lprice = _values.Min();
|
||||
|
||||
double del1 = hprice - _upperBand;
|
||||
double del2 = lprice - _lowerBand;
|
||||
double del1 = price - _upperBand;
|
||||
double del2 = price - _lowerBand;
|
||||
double volty = Math.Max(Math.Abs(del1), Math.Abs(del2));
|
||||
|
||||
_voltyShort.Add(volty, Input.IsNew);
|
||||
double vsum = _vsumBuff.Newest() + 0.1 * (volty - _voltyShort.Oldest());
|
||||
_vsumBuff.Add(vsum, Input.IsNew);
|
||||
_vsumBuff.Add(volty, Input.IsNew);
|
||||
_vSum += (_vsumBuff[^1] - _vsumBuff[0]) / _vsumBuff.Count;
|
||||
_avoltyBuff.Add(_vSum, Input.IsNew);
|
||||
double avgvolty = _avoltyBuff.Average();
|
||||
|
||||
double prevAvolty = _avoltyBuff.Newest();
|
||||
double avolty = prevAvolty + 2.0 / (Math.Max(4.0 * Period, 30) + 1.0) * (vsum - prevAvolty);
|
||||
_avoltyBuff.Add(avolty, Input.IsNew);
|
||||
double rvolty = (avgvolty > 0) ? volty / avgvolty : 1;
|
||||
rvolty = Math.Min(Math.Max(rvolty, 1.0), Math.Pow(_len1, 1.0 / _pow1));
|
||||
|
||||
double dVolty = (avolty > 0) ? volty / avolty : 0;
|
||||
dVolty = Math.Min(Math.Max(dVolty, 1.0), Math.Pow(_len1, 1.0 / _pow1));
|
||||
double pow2 = Math.Pow(rvolty, _pow1);
|
||||
double Kv = Math.Pow(_beta, Math.Sqrt(pow2));
|
||||
|
||||
double pow2 = Math.Pow(dVolty, _pow1);
|
||||
double len2 = Math.Sqrt(0.5 * (Period - 1)) * _len1;
|
||||
double _Kv = Math.Pow(len2 / (len2 + 1), Math.Sqrt(pow2));
|
||||
_upperBand = (del1 >= 0) ? price : price - (Kv * del1);
|
||||
_lowerBand = (del2 <= 0) ? price : price - (Kv * del2);
|
||||
|
||||
_upperBand = (del1 > 0) ? hprice : hprice - (_Kv * del1);
|
||||
_lowerBand = (del2 < 0) ? lprice : lprice - (_Kv * del2);
|
||||
|
||||
double alpha = Math.Pow(_beta, pow2);
|
||||
double ma1 = (1 - alpha) * Input.Value + alpha * _prevMa1;
|
||||
double _alpha = Math.Pow(_beta, pow2);
|
||||
double ma1 = Input.Value + _alpha * (_prevMa1 - Input.Value); //original: (1 - _alpha) * Input.Value + _alpha * _prevMa1;
|
||||
_prevMa1 = ma1;
|
||||
|
||||
double det0 = (1 - _beta) * (Input.Value - ma1) + _beta * _prevDet0;
|
||||
double det0 = price + _beta * (_prevDet0 - price + ma1) - ma1; //original: (price - ma1) * (1 - _beta) + _beta * _prevDet0;
|
||||
_prevDet0 = det0;
|
||||
double ma2 = ma1 + (_phase + 1) * det0;
|
||||
double ma2 = ma1 + _phase * det0;
|
||||
|
||||
double det1 = ((1 - alpha) * (1 - alpha) * (ma2 - _prevJma)) + (alpha * alpha * _prevDet1);
|
||||
double det1 = ((ma2 - _prevJma) * (1 - _alpha) * (1 - _alpha)) + (_alpha * _alpha * _prevDet1);
|
||||
_prevDet1 = det1;
|
||||
double jma = _prevJma + det1;
|
||||
_prevJma = jma;
|
||||
|
||||
UpperBand = _upperBand;
|
||||
LowerBand = _lowerBand;
|
||||
Volty = volty;
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return jma;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+101
-33
@@ -1,18 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// RMA: Relative Moving Average (also known as Wilder's Moving Average)
|
||||
/// RMA is similar to EMA but uses a different smoothing factor.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// RMA is similar to EMA but uses a different smoothing factor.
|
||||
///
|
||||
/// Key characteristics:
|
||||
/// - Uses no buffer, relying only on the previous RMA value.
|
||||
/// - The weight of new data points (alpha) is calculated as 1 / period.
|
||||
/// - Provides a smoother curve compared to SMA and EMA, reacting more slowly to price changes.
|
||||
///
|
||||
/// Calculation method:
|
||||
/// RMA = (Previous RMA * (period - 1) + New Data) / period
|
||||
/// This implementation can use SMA for the first Period bars as a seeding value for RMA when useSma is true.
|
||||
///
|
||||
/// Sources:
|
||||
/// - https://www.tradingview.com/pine-script-reference/v5/#fun_ta{dot}rma
|
||||
@@ -20,75 +20,143 @@ namespace QuanTAlib;
|
||||
/// </remarks>
|
||||
public class Rma : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private double _lastRma;
|
||||
private readonly double _alpha;
|
||||
private double _savedLastRma;
|
||||
// inherited _index
|
||||
// inherited _value
|
||||
|
||||
public Rma(int period)
|
||||
/// <summary>
|
||||
/// The period for the RMA calculation.
|
||||
/// </summary>
|
||||
private readonly int _period;
|
||||
|
||||
/// <summary>
|
||||
/// Circular buffer for SMA calculation.
|
||||
/// </summary>
|
||||
private CircularBuffer _sma;
|
||||
|
||||
/// <summary>
|
||||
/// The last calculated RMA value.
|
||||
/// </summary>
|
||||
private double _lastRma, _p_lastRma;
|
||||
|
||||
/// <summary>
|
||||
/// Compensator for early RMA values.
|
||||
/// </summary>
|
||||
private double _e, _p_e;
|
||||
|
||||
/// <summary>
|
||||
/// The smoothing factor for RMA calculation.
|
||||
/// </summary>
|
||||
private readonly double _k;
|
||||
|
||||
/// <summary>
|
||||
/// Flags to track initialization status.
|
||||
/// </summary>
|
||||
private bool _isInit, _p_isInit;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to determine whether to use SMA for initial values.
|
||||
/// </summary>
|
||||
private readonly bool _useSma;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rma class with a specified period.
|
||||
/// </summary>
|
||||
/// <param name="period">The period for RMA calculation.</param>
|
||||
/// <param name="useSma">Whether to use SMA for initial values. Default is true.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Thrown when period is less than 1.</exception>
|
||||
public Rma(int period, bool useSma = true)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
_period = period;
|
||||
WarmupPeriod = period * 2;
|
||||
_alpha = 1.0 / _period; // Wilder's smoothing factor
|
||||
Name = $"Rma({_period})";
|
||||
_k = 1.0 / _period; // Wilder's smoothing factor
|
||||
_useSma = useSma;
|
||||
_sma = new(period);
|
||||
Name = "Rma";
|
||||
WarmupPeriod = _period * 2; // RMA typically needs more warmup periods
|
||||
Init();
|
||||
}
|
||||
|
||||
public Rma(object source, int period) : this(period)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Rma class with a specified source and period.
|
||||
/// </summary>
|
||||
/// <param name="source">The source object for event subscription.</param>
|
||||
/// <param name="period">The period for RMA calculation.</param>
|
||||
/// <param name="useSma">Whether to use SMA for initial values. Default is true.</param>
|
||||
public Rma(object source, int period, bool useSma = true) : this(period, useSma)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Rma instance.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_e = 1.0;
|
||||
_lastRma = 0;
|
||||
_savedLastRma = 0;
|
||||
_isInit = false;
|
||||
_p_isInit = false;
|
||||
_sma = new(_period);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Rma instance.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the input is new.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_savedLastRma = _lastRma;
|
||||
_lastValidValue = Input.Value;
|
||||
_p_lastRma = _lastRma;
|
||||
_p_isInit = _isInit;
|
||||
_p_e = _e;
|
||||
_index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lastRma = _savedLastRma;
|
||||
_lastRma = _p_lastRma;
|
||||
_isInit = _p_isInit;
|
||||
_e = _p_e;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the RMA calculation.
|
||||
/// </summary>
|
||||
/// <returns>The calculated RMA value.</returns>
|
||||
protected override double Calculation()
|
||||
{
|
||||
double result, _rma;
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double rma;
|
||||
|
||||
if (_index == 1)
|
||||
// when _UseSma == true, use SMA calculation until we have enough data points
|
||||
if (!_isInit && _useSma)
|
||||
{
|
||||
rma = Input.Value;
|
||||
}
|
||||
else if (_index <= _period)
|
||||
{
|
||||
// Simple average during initial period
|
||||
rma = (_lastRma * (_index - 1) + Input.Value) / _index;
|
||||
_sma.Add(Input.Value, Input.IsNew);
|
||||
_rma = _sma.Average();
|
||||
result = _rma;
|
||||
if (_index >= _period)
|
||||
{
|
||||
_isInit = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wilder's smoothing method
|
||||
rma = _alpha * (_lastRma - Input.Value) + _lastRma;
|
||||
// compensator for early rma values
|
||||
_e = (_e > 1e-10) ? (1 - _k) * _e : 0;
|
||||
|
||||
_rma = _k * Input.Value + (1 - _k) * _lastRma;
|
||||
|
||||
// _useSma decides if we use compensator or not
|
||||
result = (_useSma || _e <= double.Epsilon) ? _rma : _rma / (1 - _e);
|
||||
}
|
||||
|
||||
_lastRma = rma;
|
||||
_lastRma = _rma;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return rma;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,12 @@ public abstract class AbstractBase : ITValue
|
||||
Input2 = new(Time: Input.Time, Value: double.NaN, IsNew: Input.IsNew, IsHot: Input.IsHot);
|
||||
return Process(input.Value, input.Time, input.IsNew);
|
||||
}
|
||||
public virtual TValue Calc(double value, bool IsNew)
|
||||
{
|
||||
Input = new(this.Time, Value: value, IsNew: IsNew, IsHot: false);
|
||||
Input2 = new(this.Time, double.NaN, false, false);
|
||||
return Process(Input.Value, Input.Time, Input.IsNew);
|
||||
}
|
||||
|
||||
public virtual TValue Calc(TBar barInput)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,8 @@ public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { }
|
||||
public TBar(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : this(DateTime.UtcNow, Open, High, Low, Close, Volume, IsNew) { }
|
||||
public TBar(double value) : this(Time: DateTime.UtcNow, Open: value, High: value, Low: value, Close: value, Volume: value, IsNew: true) { }
|
||||
public TBar(TValue value) : this(Time: value.Time, Open: value.Value, High: value.Value, Low: value.Value, Close: value.Value, Volume: value.Value, IsNew: value.IsNew) { }
|
||||
public TBar(TBar v) : this(Time: v.Time, Open: v.Open, High: v.High, Low: v.Low, Close: v.Close, Volume: v.Volume, IsNew: true) { }
|
||||
|
||||
|
||||
public static implicit operator double(TBar bar) => bar.Close;
|
||||
public static implicit operator DateTime(TBar tv) => tv.Time;
|
||||
|
||||
+2
-2
@@ -52,13 +52,13 @@ public class TSeries : List<TValue>
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
if (pubEvent != null)
|
||||
{
|
||||
|
||||
/*
|
||||
var nameProperty = source.GetType().GetProperty("Name");
|
||||
if (nameProperty != null)
|
||||
{
|
||||
Name = nameProperty.GetValue(nameProperty)?.ToString()!;
|
||||
}
|
||||
|
||||
*/
|
||||
pubEvent.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
}
|
||||
|
||||
+19
-19
@@ -6,11 +6,11 @@ public class GbmFeed : TBarSeries
|
||||
{
|
||||
private readonly double _mu, _sigma;
|
||||
private readonly RandomNumberGenerator _rng;
|
||||
private double _lastClose, _lastHigh, _lastLow;
|
||||
private double _lastClose;
|
||||
|
||||
public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2)
|
||||
{
|
||||
_lastClose = _lastHigh = _lastLow = initialPrice;
|
||||
_lastClose = initialPrice;
|
||||
_mu = mu;
|
||||
_sigma = sigma;
|
||||
_rng = RandomNumberGenerator.Create();
|
||||
@@ -24,9 +24,7 @@ public class GbmFeed : TBarSeries
|
||||
DateTime startTime = DateTime.UtcNow - TimeSpan.FromHours(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Add(startTime, true);
|
||||
Add(startTime, false);
|
||||
Add(startTime, false);
|
||||
Add(startTime, isNew: true);
|
||||
startTime = startTime.AddHours(1);
|
||||
}
|
||||
}
|
||||
@@ -36,27 +34,29 @@ public class GbmFeed : TBarSeries
|
||||
double dt = 1.0 / 252;
|
||||
double drift = (_mu - 0.5 * _sigma * _sigma) * dt;
|
||||
double diffusion = _sigma * Math.Sqrt(dt) * GenerateNormalRandom();
|
||||
double newClose = _lastClose * Math.Exp(drift + diffusion);
|
||||
|
||||
double open = _lastClose;
|
||||
double high = Math.Max(_lastHigh, Math.Max(open, newClose) * (1 + GenerateRandomDouble() * 0.01));
|
||||
double low = Math.Min(_lastLow, Math.Min(open, newClose) * (1 - GenerateRandomDouble() * 0.01));
|
||||
double close = open * Math.Exp(drift + diffusion);
|
||||
|
||||
// Generate intra-bar price movements
|
||||
double maxMove = Math.Abs(close - open) * 1.5; // Allow for some extra movement within the bar
|
||||
double high = Math.Max(open, close) + maxMove * GenerateRandomDouble();
|
||||
double low = Math.Min(open, close) - maxMove * GenerateRandomDouble();
|
||||
|
||||
// Ensure high is always greater than or equal to both open and close
|
||||
high = Math.Max(high, Math.Max(open, close));
|
||||
|
||||
// Ensure low is always less than or equal to both open and close
|
||||
low = Math.Min(low, Math.Min(open, close));
|
||||
|
||||
double volume = 1000 + GenerateRandomDouble() * 1000;
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
_lastClose = newClose;
|
||||
_lastClose = close;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = Math.Max(_lastHigh, high);
|
||||
low = Math.Min(_lastLow, low);
|
||||
}
|
||||
_lastHigh = high;
|
||||
_lastLow = low;
|
||||
|
||||
TBar bar = new(time, open, high, low, newClose, volume, isNew);
|
||||
return bar;
|
||||
return new TBar(time, open, high, low, close, volume, isNew);
|
||||
}
|
||||
|
||||
private double GenerateNormalRandom()
|
||||
@@ -73,4 +73,4 @@ public class GbmFeed : TBarSeries
|
||||
_rng.GetBytes(bytes);
|
||||
return (double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
<NoWarn>$(NoWarn);NU1903;NU5104</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
+21
-16
@@ -4,13 +4,14 @@ namespace QuanTAlib;
|
||||
/// Represents an Average True Range (ATR) calculator, a measure of market volatility.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ATR class calculates the average true range using an Exponential Moving Average (EMA)
|
||||
/// The ATR class calculates the average true range using a Relative Moving Average (RMA)
|
||||
/// of the true range. The true range is the greatest of: current high - current low,
|
||||
/// absolute value of current high - previous close, or absolute value of current low - previous close.
|
||||
/// </remarks>
|
||||
public class Atr : AbstractBase
|
||||
{
|
||||
private readonly Ema _ma;
|
||||
public double Tr { get; private set; }
|
||||
private readonly Rma _ma;
|
||||
private double _prevClose, _p_prevClose;
|
||||
|
||||
/// <summary>
|
||||
@@ -26,7 +27,7 @@ public class Atr : AbstractBase
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
_ma = new(1.0 / period);
|
||||
_ma = new(period, useSma: true);
|
||||
WarmupPeriod = _ma.WarmupPeriod;
|
||||
Name = $"ATR({period})";
|
||||
}
|
||||
@@ -50,6 +51,7 @@ public class Atr : AbstractBase
|
||||
base.Init();
|
||||
_ma.Init();
|
||||
_prevClose = double.NaN;
|
||||
Tr = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,7 +78,7 @@ public class Atr : AbstractBase
|
||||
/// The calculated ATR value for the current bar.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This method calculates the true range for the current bar and then uses an EMA
|
||||
/// This method calculates the true range for the current bar and then uses an RMA
|
||||
/// to smooth the true range values. For the first bar, it uses the high-low range
|
||||
/// as the true range.
|
||||
/// </remarks>
|
||||
@@ -84,22 +86,25 @@ public class Atr : AbstractBase
|
||||
{
|
||||
ManageState(BarInput.IsNew);
|
||||
|
||||
double trueRange = Math.Max(
|
||||
Math.Max(
|
||||
BarInput.High - BarInput.Low,
|
||||
Math.Abs(BarInput.High - _prevClose)
|
||||
),
|
||||
Math.Abs(BarInput.Low - _prevClose)
|
||||
);
|
||||
if (_index < 2)
|
||||
if (_index == 1)
|
||||
{
|
||||
trueRange = BarInput.High - BarInput.Low;
|
||||
Tr = BarInput.High - BarInput.Low;
|
||||
_prevClose = BarInput.Close;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tr = Math.Max(
|
||||
BarInput.High - BarInput.Low,
|
||||
Math.Max(
|
||||
Math.Abs(BarInput.High - _prevClose),
|
||||
Math.Abs(BarInput.Low - _prevClose)
|
||||
)
|
||||
);
|
||||
}
|
||||
_ma.Calc(new TValue(Input.Time, Tr, BarInput.IsNew));
|
||||
|
||||
TValue emaTrueRange = _ma.Calc(new TValue(Input.Time, trueRange, Input.IsNew));
|
||||
IsHot = _ma.IsHot;
|
||||
_prevClose = BarInput.Close;
|
||||
|
||||
return emaTrueRange.Value;
|
||||
return _ma.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Chande Momentum Oscillator (CMO) calculator.
|
||||
/// </summary>
|
||||
public class Cmo : AbstractBase
|
||||
{
|
||||
private readonly CircularBuffer _sumH;
|
||||
private readonly CircularBuffer _sumL;
|
||||
private double _prevValue, _p_prevValue;
|
||||
|
||||
public Cmo(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
_sumH = new(period);
|
||||
_sumL = new(period);
|
||||
|
||||
WarmupPeriod = period+1;
|
||||
Name = $"CMO({period})";
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_index++;
|
||||
_p_prevValue = _prevValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_prevValue = _p_prevValue;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
if (_index == 0)
|
||||
{
|
||||
_prevValue = Input.Value;
|
||||
}
|
||||
|
||||
double diff = Input.Value - _prevValue;
|
||||
_prevValue = Input.Value;
|
||||
|
||||
if (diff > 0)
|
||||
{
|
||||
_sumH.Add(diff, Input.IsNew);
|
||||
_sumL.Add(0, Input.IsNew);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sumH.Add(0, Input.IsNew);
|
||||
_sumL.Add(-diff, Input.IsNew);
|
||||
|
||||
}
|
||||
|
||||
// Calculate sums for the specified period only
|
||||
double sumH = _sumH.Sum();
|
||||
double sumL = _sumL.Sum();
|
||||
double divisor = sumH + sumL;
|
||||
|
||||
return (Math.Abs(divisor) > double.Epsilon) ?
|
||||
100.0 * ((sumH - sumL) / divisor) :
|
||||
0.0;
|
||||
}
|
||||
}
|
||||
|
||||
+70
-38
@@ -7,17 +7,25 @@ namespace QuanTAlib;
|
||||
public class Jvolty : AbstractBase
|
||||
{
|
||||
private readonly int _period;
|
||||
private readonly CircularBuffer _values;
|
||||
private readonly CircularBuffer _voltyShort;
|
||||
private readonly double _phase;
|
||||
private readonly CircularBuffer _vsumBuff;
|
||||
private readonly CircularBuffer _avoltyBuff;
|
||||
|
||||
private double _len1;
|
||||
private double _pow1;
|
||||
private double _upperBand;
|
||||
private double _lowerBand;
|
||||
private double _p_upperBand;
|
||||
private double _p_lowerBand;
|
||||
private readonly double _beta;
|
||||
private double _upperBand, _lowerBand, _p_upperBand, _p_lowerBand;
|
||||
private double _prevMa1, _prevDet0, _prevDet1, _prevJma, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma;
|
||||
private double _vSum, _p_vSum;
|
||||
|
||||
|
||||
public double UpperBand { get; set; }
|
||||
public double LowerBand { get; set; }
|
||||
public double Volty { get; set; }
|
||||
public double VSum { get; set; }
|
||||
public double Jma { get; set; }
|
||||
public double AvgVolty { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Jvolty class with the specified parameters.
|
||||
@@ -28,22 +36,21 @@ public class Jvolty : AbstractBase
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Jvolty(int period, int vshort = 10)
|
||||
public Jvolty(int period, int phase = 0)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
_period = period;
|
||||
int _vlong = 65;
|
||||
_phase = Math.Clamp((phase * 0.01) + 1.5, 0.5, 2.5);
|
||||
|
||||
_values = new CircularBuffer(period);
|
||||
_voltyShort = new CircularBuffer(vshort);
|
||||
_vsumBuff = new CircularBuffer(_vlong);
|
||||
_avoltyBuff = new CircularBuffer(2);
|
||||
_vsumBuff = new CircularBuffer(10);
|
||||
_avoltyBuff = new CircularBuffer(65);
|
||||
_beta = 0.45 * (period - 1) / (0.45 * (period - 1) + 2);
|
||||
|
||||
WarmupPeriod = period * 2;
|
||||
Name = $"JVOLTY({period},{vshort})";
|
||||
Name = $"JVOLTY({period})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -53,7 +60,7 @@ public class Jvolty : AbstractBase
|
||||
/// <param name="period">The period over which to calculate the Jvolty.</param>
|
||||
/// <param name="phase">The phase parameter for the JMA-style calculation.</param>
|
||||
/// <param name="vshort">The short-term volatility period.</param>
|
||||
public Jvolty(object source, int period, int vshort = 10) : this(period, vshort)
|
||||
public Jvolty(object source, int period, int phase = 0) : this(period, phase)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
@@ -70,8 +77,7 @@ public class Jvolty : AbstractBase
|
||||
_len1 = Math.Max((Math.Log(Math.Sqrt(_period - 1)) / Math.Log(2.0)) + 2.0, 0);
|
||||
_pow1 = Math.Max(_len1 - 2.0, 0.5);
|
||||
_avoltyBuff.Clear();
|
||||
_avoltyBuff.Add(0, true);
|
||||
_avoltyBuff.Add(0, true);
|
||||
_vsumBuff.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -85,11 +91,21 @@ public class Jvolty : AbstractBase
|
||||
_index++;
|
||||
_p_upperBand = _upperBand;
|
||||
_p_lowerBand = _lowerBand;
|
||||
_p_vSum = _vSum;
|
||||
_p_prevMa1 = _prevMa1;
|
||||
_p_prevDet0 = _prevDet0;
|
||||
_p_prevDet1 = _prevDet1;
|
||||
_p_prevJma = _prevJma;
|
||||
}
|
||||
else
|
||||
{
|
||||
_upperBand = _p_upperBand;
|
||||
_lowerBand = _p_lowerBand;
|
||||
_vSum = _p_vSum;
|
||||
_prevMa1 = _p_prevMa1;
|
||||
_prevDet0 = _p_prevDet0;
|
||||
_prevDet1 = _p_prevDet1;
|
||||
_prevJma = _p_prevJma;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,41 +117,57 @@ public class Jvolty : AbstractBase
|
||||
/// </returns>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(BarInput.IsNew);
|
||||
|
||||
_values.Add(BarInput.Close, BarInput.IsNew);
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double price = Input.Value;
|
||||
if (_index == 1)
|
||||
{
|
||||
return 0;
|
||||
_upperBand = _lowerBand = price;
|
||||
}
|
||||
|
||||
double hprice = _values.Max();
|
||||
double lprice = _values.Min();
|
||||
|
||||
double del1 = hprice - _upperBand;
|
||||
double del2 = lprice - _lowerBand;
|
||||
double del1 = price - _upperBand;
|
||||
double del2 = price - _lowerBand;
|
||||
double volty = Math.Max(Math.Abs(del1), Math.Abs(del2));
|
||||
|
||||
_voltyShort.Add(volty, BarInput.IsNew);
|
||||
double vsum = _vsumBuff.Newest() + 0.1 * (volty - _voltyShort.Oldest());
|
||||
_vsumBuff.Add(vsum, BarInput.IsNew);
|
||||
_vsumBuff.Add(volty, Input.IsNew);
|
||||
_vSum += (_vsumBuff[^1] - _vsumBuff[0]) / 10;
|
||||
_avoltyBuff.Add(_vSum, Input.IsNew);
|
||||
double avgvolty = _avoltyBuff.Average();
|
||||
|
||||
double prevAvolty = _avoltyBuff.Newest();
|
||||
double avolty = prevAvolty + 2.0 / (Math.Max(4.0 * _period, 30) + 1.0) * (vsum - prevAvolty);
|
||||
_avoltyBuff.Add(avolty, BarInput.IsNew);
|
||||
double rvolty = (avgvolty > 0) ? volty / avgvolty : 1;
|
||||
rvolty = Math.Min(Math.Max(rvolty, 1.0), Math.Pow(_len1, 1.0 / _pow1));
|
||||
|
||||
double dVolty = (avolty > 0) ? volty / avolty : 0;
|
||||
dVolty = Math.Min(Math.Max(dVolty, 1.0), Math.Pow(_len1, 1.0 / _pow1));
|
||||
double pow2 = Math.Pow(rvolty, _pow1);
|
||||
double Kv = Math.Pow(_beta, Math.Sqrt(pow2));
|
||||
|
||||
double pow2 = Math.Pow(dVolty, _pow1);
|
||||
double len2 = Math.Sqrt(0.5 * (_period - 1)) * _len1;
|
||||
double Kv = Math.Pow(len2 / (len2 + 1), Math.Sqrt(pow2));
|
||||
_upperBand = (del1 >= 0) ? price : price - (Kv * del1);
|
||||
_lowerBand = (del2 <= 0) ? price : price - (Kv * del2);
|
||||
|
||||
_upperBand = (del1 > 0) ? hprice : hprice - (Kv * del1);
|
||||
_lowerBand = (del2 < 0) ? lprice : lprice - (Kv * del2);
|
||||
|
||||
|
||||
double alpha = Math.Pow(_beta, pow2);
|
||||
double ma1 = (1 - alpha) * Input.Value + alpha * _prevMa1;
|
||||
_prevMa1 = ma1;
|
||||
|
||||
double det0 = (price - ma1) * (1 - _beta) + _beta * _prevDet0;
|
||||
_prevDet0 = det0;
|
||||
double ma2 = ma1 + _phase * det0;
|
||||
|
||||
double det1 = ((ma2 - _prevJma) * (1 - alpha) * (1 - alpha) ) + (alpha * alpha * _prevDet1);
|
||||
_prevDet1 = det1;
|
||||
double jma = _prevJma + det1;
|
||||
_prevJma = jma;
|
||||
|
||||
UpperBand = _upperBand;
|
||||
LowerBand = _lowerBand;
|
||||
Volty = volty;
|
||||
VSum = _vSum;
|
||||
AvgVolty = avgvolty;
|
||||
Jma = jma;
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return volty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Relative Strength Index (RSI) calculator following Wilder's algorithm.
|
||||
/// </summary>
|
||||
public class Rsi : AbstractBase
|
||||
{
|
||||
private readonly Rma _avgGain;
|
||||
private readonly Rma _avgLoss;
|
||||
private double _prevValue, _p_prevValue;
|
||||
|
||||
public Rsi(int period = 14)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
_avgGain = new(period, useSma: true);
|
||||
_avgLoss = new(period, useSma: true);
|
||||
_index = 0;
|
||||
WarmupPeriod = period + 1;
|
||||
Name = $"RSI({period})";
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_index++;
|
||||
_p_prevValue = _prevValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_prevValue = _p_prevValue;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
if (_index == 1)
|
||||
{
|
||||
_prevValue = Input.Value;
|
||||
}
|
||||
|
||||
double change = Input.Value - _prevValue;
|
||||
double gain = Math.Max(change, 0);
|
||||
double loss = Math.Max(-change, 0);
|
||||
_prevValue = Input.Value;
|
||||
|
||||
_avgGain.Calc(gain, IsNew: Input.IsNew);
|
||||
_avgLoss.Calc(loss, IsNew: Input.IsNew);
|
||||
|
||||
double rsi = (_avgLoss.Value > 0) ? 100 - (100 / (1 + (_avgGain.Value / _avgLoss.Value))) : 100;
|
||||
|
||||
|
||||
return rsi;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
/// <summary>
|
||||
/// Jurik's superior replacement for RSI
|
||||
/// </summary>
|
||||
public class Rsx : AbstractBase
|
||||
{
|
||||
private readonly Rma _avgGain;
|
||||
private readonly Rma _avgLoss;
|
||||
private readonly Jma _rsx;
|
||||
private double _prevValue, _p_prevValue;
|
||||
|
||||
public Rsx(int period = 14, int phase = 0, double factor = 0.55)
|
||||
{
|
||||
if (period < 1)
|
||||
throw new ArgumentOutOfRangeException(nameof(period));
|
||||
_avgGain = new(period);
|
||||
_avgLoss = new(period);
|
||||
_rsx = new(8, 100, 0.25, 3);
|
||||
_index = 0;
|
||||
WarmupPeriod = period + 1;
|
||||
Name = $"RSX({period})";
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_index++;
|
||||
_p_prevValue = _prevValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_prevValue = _p_prevValue;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
if (_index == 1)
|
||||
{
|
||||
_prevValue = Input.Value;
|
||||
}
|
||||
|
||||
double change = Input.Value - _prevValue;
|
||||
double gain = Math.Max(change, 0);
|
||||
double loss = Math.Max(-change, 0);
|
||||
_prevValue = Input.Value;
|
||||
|
||||
_avgGain.Calc(gain, IsNew: Input.IsNew);
|
||||
_avgLoss.Calc(loss, IsNew: Input.IsNew);
|
||||
|
||||
double rsi = (_avgLoss.Value > 0) ? 100 - (100 / (1 + (_avgGain.Value / _avgLoss.Value))) : 100;
|
||||
double rsx = _rsx.Calc(rsi, Input.IsNew);
|
||||
|
||||
return rsx;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,12 @@
|
||||
|
||||
- **Jurik Volatility (Volty)**
|
||||
- **Standard Deviation**
|
||||
- **Relative Volatility Index (RVI)**
|
||||
- **RVI Relative Volatility Index**
|
||||
- **CMO Chande Momentum Oscillator**
|
||||
- **Historical Volatility**
|
||||
- **Average True Range (ATR) (High, Low, Close)**
|
||||
|
||||
- Normalized ATR
|
||||
- Ulcer Index
|
||||
- ARCH/GARCH Models
|
||||
- Exponential Weighted Moving Average (EWMA) Volatility
|
||||
@@ -15,14 +20,10 @@
|
||||
- Volatility Cone
|
||||
- Bollinger Bands
|
||||
- Stochastic Volatility: Typically modeled using closing prices, but can incorporate other price information
|
||||
|
||||
## OHLC Input (Open, High, Low, Close)
|
||||
|
||||
- Garman-Klass Volatility
|
||||
- Rogers-Satchell Volatility
|
||||
- Yang-Zhang Volatility
|
||||
- Parkinson Volatility (High, Low)
|
||||
- Average True Range (ATR) (High, Low, Close)
|
||||
- Chaikin Volatility (High, Low)
|
||||
- Keltner Channels (typically Close, High, Low)
|
||||
- High-Low Volatility (High, Low)
|
||||
|
||||
+42
-99
@@ -4,7 +4,7 @@
|
||||
|
||||
#!csharp
|
||||
|
||||
#r "..\src\obj\Debug\QuanTAlib.dll"
|
||||
#r "..\lib\obj\Debug\QuanTAlib.dll"
|
||||
|
||||
#r "nuget:Skender.Stock.Indicators"
|
||||
using Skender.Stock.Indicators;
|
||||
@@ -13,113 +13,56 @@ QuanTAlib.Formatters.Initialize();
|
||||
|
||||
#!csharp
|
||||
|
||||
Atr ma = new(10);
|
||||
GbmFeed gbm = new();
|
||||
EmaCalc ema1 = new(gbm.Close, 10, useSma: false);
|
||||
EmaCalc ema2 = new(gbm.Close, 10, useSma: true);
|
||||
TValSeries res1 = new(ema1);
|
||||
TValSeries res2 = new(ema2);
|
||||
gbm.Add(50);
|
||||
List<double> mse1 = new();
|
||||
List<double> mse2 = new();
|
||||
|
||||
|
||||
gbm.Add(30);
|
||||
IEnumerable<Quote> quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume });
|
||||
var SkResults = quotes.GetAtr(10).Select(i => i.Atr.Null2NaN()!);
|
||||
for (int i=0; i< gbm.Length; i++) {
|
||||
double v= gbm.Close[i].Value;
|
||||
double e1 = res1[i].Value;
|
||||
mse1.Add((e1-v)*(e1-v));
|
||||
double e2 = res2[i].Value;
|
||||
mse2.Add((e2-v)*(e2-v));
|
||||
|
||||
//Console.WriteLine($"{i,3} {mse1.Average(),10:F4} {mse2.Average(),10:F4}");
|
||||
ma.Calc(gbm[i]);
|
||||
Console.WriteLine($"{i,3} {ma.Value,10:F3} \t {SkResults.ElementAt(i):F3}");
|
||||
}
|
||||
|
||||
Console.WriteLine($"{mse2.Average()-mse1.Average(),10:F8}");
|
||||
|
||||
#!csharp
|
||||
|
||||
display(res1);
|
||||
|
||||
#!csharp
|
||||
|
||||
Atr ma = new(10);
|
||||
GbmFeed gbm = new();
|
||||
EmaCalc ema1 = new(gbm.Close, 10, useSma: false);
|
||||
EmaCalc ema2 = new(gbm.Close, 10, useSma: true);
|
||||
TValSeries res1 = new(ema1);
|
||||
TValSeries res2 = new(ema2);
|
||||
gbm.Add(30);
|
||||
IEnumerable<Quote> quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume });
|
||||
var SkResults = quotes.GetTr().Select(i => i.Tr.Null2NaN()!);
|
||||
for (int i=0; i< gbm.Length; i++) {
|
||||
ma.Calc(new TBar(gbm[i]));
|
||||
|
||||
Console.WriteLine($"{gbm.High[i].Value,6:F4} \t{gbm.Low[i].Value,6:F4} \t{gbm.Close[i].Value,6:F4} \t{ma.Tr,10:F4} \t{SkResults.ElementAt(i),10:F4}");
|
||||
}
|
||||
|
||||
#!csharp
|
||||
|
||||
//ATR test
|
||||
GbmFeed gbm = new();
|
||||
TBarSeries feed = new(gbm);
|
||||
|
||||
Atr ma1 = new(gbm, 10);
|
||||
TSeries res1 = new(ma1);
|
||||
gbm.Add(30);
|
||||
IEnumerable<Quote> quotes = gbm.Select(item => new Quote { Date = item.Time, Open = (decimal)item.Open, High = (decimal)item.High, Low = (decimal)item.Low, Close = (decimal)item.Close, Volume = (decimal)item.Volume });
|
||||
var SkResults = quotes.GetAtr(10).Select(i => i.Atr.Null2NaN()!);
|
||||
for (int i=0; i< gbm.Length; i++) {
|
||||
double delta = Math.Round(res1[i].Value, 10) - Math.Round(SkResults.ElementAt(i), 10);
|
||||
//Console.WriteLine($"{i,3} {gbm.High[i].Value,6:F2} {gbm.Low[i].Value,6:F2} {gbm.Close[i].Value,6:F2} {res1[i].Value,10:F4} {SkResults.ElementAt(i),10:F4}\t{delta}");
|
||||
Console.WriteLine($"{i,3} h:{gbm.High[i].Value,6:F2} l:{gbm.Low[i].Value,6:F2} c:{gbm.Close[i].Value,6:F2} {res1[i].Atr,10:F4} {SkResults.ElementAt(i),10:F4}\t{delta}");
|
||||
}
|
||||
|
||||
#!csharp
|
||||
|
||||
//EMA test
|
||||
GbmFeed gbm = new();
|
||||
Ema ema1 = new(gbm.Close, 10, useSma: true);
|
||||
TSeries res1 = new(ema1);
|
||||
gbm.Add(30);
|
||||
IEnumerable<Quote> quotes = gbm.Close.Select(item => new Quote { Date = item.Time, Close = (decimal)item.Value });
|
||||
var SkResults = quotes.GetEma(10).Select(i => i.Ema.Null2NaN()!);
|
||||
for (int i=0; i< gbm.Length; i++) {
|
||||
Console.WriteLine($"{i,3} {gbm.Close[i].Value,6:F2} {res1[i].Value,10:F4} {res2[i].Value,10:F4} {SkResults.ElementAt(i),10:F4}");
|
||||
double delta = Math.Round(res1[i].Value, 10) - Math.Round(SkResults.ElementAt(i), 10);
|
||||
Console.WriteLine($"{i,3} {gbm.Close[i].Value,6:F2} {res1[i].Value,10:F4} {SkResults.ElementAt(i),10:F4}\t{delta}");
|
||||
}
|
||||
|
||||
#!csharp
|
||||
|
||||
TValSeries test = new();
|
||||
|
||||
EmaCalc ma1 = new(test, 7, true);
|
||||
TValSeries res1 = new(ma1);
|
||||
|
||||
EmaCalc ma2 = new(test, 7, false);
|
||||
TValSeries res2 = new(ma2);
|
||||
|
||||
test.Add(new[]{1.0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0});
|
||||
|
||||
for (int i=0; i<res1.Count; i++) {
|
||||
Console.WriteLine($"{i,2} {test[i].Value,7:F4} {res1[i].Value,7:F4} {res2[i].Value,7:F4}");
|
||||
}
|
||||
|
||||
#!csharp
|
||||
|
||||
TValSeries test = new();
|
||||
EmaCalc ma = new(test,3);
|
||||
TValSeries result = new();
|
||||
|
||||
for (int i=1; i<10; i++) {
|
||||
test.Add(new TValue(DateTime.Now, (double)i, true, true));
|
||||
result.Add(ma.Tick);
|
||||
}
|
||||
display(result);
|
||||
|
||||
#!csharp
|
||||
|
||||
TValSeries test = new();
|
||||
SmaCalc ma = new(test,7);
|
||||
TValSeries result = new(ma);
|
||||
test.Add(new[]{81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29});
|
||||
//test.Add(new[]{1.0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0});
|
||||
|
||||
display(result);
|
||||
|
||||
#!csharp
|
||||
|
||||
TValue test = new(DateTime.Today, 100, IsHot: false);
|
||||
TValSeries pub = new();
|
||||
TValSeries sub = new(pub);
|
||||
pub.Add(test);
|
||||
pub.Add(test);
|
||||
pub.Add(2, true);
|
||||
pub.Add(DateTime.Today, 123.1234214234, IsHot: true);
|
||||
|
||||
|
||||
display(sub);
|
||||
display(test);
|
||||
|
||||
#!csharp
|
||||
|
||||
TBar test = new(DateTime.Now, double.NaN,1,2,3,400.1234);
|
||||
|
||||
TBarSeries source = new();
|
||||
TValSeries target = new(source.Close);
|
||||
|
||||
source.Add(new TBar(DateTime.Now,1,2,3,4,125, true));
|
||||
source.Add(new TBar(DateTime.Now,2,1,5,2,1312, true));
|
||||
source.Add(test);
|
||||
source.Name = "MSFT";
|
||||
display(source);
|
||||
display(test)
|
||||
|
||||
#!csharp
|
||||
|
||||
#r "nuget:Skender.Stock.Indicators"
|
||||
using Skender.Stock.Indicators;
|
||||
|
||||
+90
-69
@@ -82,58 +82,77 @@ TSeries MarketJMA = new() { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
|
||||
#!csharp
|
||||
|
||||
public class Jma1 : AbstractBase
|
||||
public class Jmaxx : AbstractBase
|
||||
{
|
||||
public readonly int Period;
|
||||
private readonly double _period;
|
||||
private readonly double _phase;
|
||||
private readonly int _vshort, _vlong;
|
||||
private CircularBuffer _voltyShort;
|
||||
private CircularBuffer _vsumBuff;
|
||||
private CircularBuffer _avoltyBuff;
|
||||
private readonly CircularBuffer _vsumBuff;
|
||||
private readonly CircularBuffer _avoltyBuff;
|
||||
|
||||
private double _beta, _len1, _pow1;
|
||||
private double _upperBand, _lowerBand, _prevMa1, _prevDet0, _prevDet1, _prevJma;
|
||||
private double _p_UpperBand, _p_LowerBand, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma;
|
||||
private double _len1;
|
||||
private double _pow1;
|
||||
private readonly double _beta;
|
||||
private double _upperBand, _lowerBand, _p_upperBand, _p_lowerBand;
|
||||
private double _prevMa1, _prevDet0, _prevDet1, _prevJma, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma;
|
||||
private double _vSum, _p_vSum;
|
||||
|
||||
public Jma1(int period, double phase = 0, int vshort = 10) : base()
|
||||
|
||||
public double UpperBand { get; set; }
|
||||
public double LowerBand { get; set; }
|
||||
public double Volty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Jma class with the specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="period">The period over which to calculate the Jvolty.</param>
|
||||
/// <param name="phase">The phase parameter for the JMA-style calculation.</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Jmaxx(int period, int phase = 0)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
Period = period;
|
||||
_vshort = vshort;
|
||||
_vlong = 65;
|
||||
_period = period;
|
||||
|
||||
_phase = Math.Clamp((phase * 0.01) + 1.5, 0.5, 2.5);
|
||||
|
||||
_voltyShort = new CircularBuffer(vshort);
|
||||
_vsumBuff = new CircularBuffer(_vlong);
|
||||
_avoltyBuff = new CircularBuffer(2);
|
||||
_vsumBuff = new CircularBuffer(10);
|
||||
_avoltyBuff = new CircularBuffer(65);
|
||||
_beta = 0.45 * (_period - 1) / (0.45 * (_period - 1) + 2);
|
||||
|
||||
Name = "JMA";
|
||||
WarmupPeriod = period * 2;
|
||||
Init();
|
||||
WarmupPeriod = (int)_period * 2;
|
||||
Name = $"JMA({period})";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Jma instance by setting up the initial state.
|
||||
/// </summary>
|
||||
public override void Init()
|
||||
{
|
||||
_upperBand = _lowerBand = _prevMa1 = _prevDet0 = _prevDet1 = _prevJma = 0.0;
|
||||
_p_UpperBand = _p_LowerBand = _p_prevMa1 = _p_prevDet0 = _p_prevDet1 = _p_prevJma = 0.0;
|
||||
_avoltyBuff.Clear();
|
||||
_avoltyBuff.Add(0, true);
|
||||
_avoltyBuff.Add(0, true);
|
||||
base.Init();
|
||||
_upperBand = _lowerBand = 0.0;
|
||||
_p_upperBand = _p_lowerBand = 0.0;
|
||||
_len1 = Math.Max((Math.Log(Math.Sqrt(_period - 1)) / Math.Log(2.0)) + 2.0, 0);
|
||||
_pow1 = Math.Max(_len1 - 2.0, 0.5);
|
||||
_avoltyBuff.Clear();
|
||||
_vsumBuff.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manages the state of the Jma instance based on whether a new value is being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current input is a new value.</param>
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
// Save current state
|
||||
_p_UpperBand = _upperBand;
|
||||
_p_LowerBand = _lowerBand;
|
||||
_p_upperBand = _upperBand;
|
||||
_p_lowerBand = _lowerBand;
|
||||
_p_vSum = _vSum;
|
||||
_p_prevMa1 = _prevMa1;
|
||||
_p_prevDet0 = _prevDet0;
|
||||
_p_prevDet1 = _prevDet1;
|
||||
@@ -141,66 +160,73 @@ public class Jma1 : AbstractBase
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore previous state
|
||||
_upperBand = _p_UpperBand;
|
||||
_lowerBand = _p_LowerBand;
|
||||
_upperBand = _p_upperBand;
|
||||
_lowerBand = _p_lowerBand;
|
||||
_vSum = _p_vSum;
|
||||
_prevMa1 = _p_prevMa1;
|
||||
_prevDet0 = _p_prevDet0;
|
||||
_prevDet1 = _p_prevDet1;
|
||||
_prevJma = _p_prevJma;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs the Jma calculation for the current value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The calculated Jma value for the current input.
|
||||
/// </returns>
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double price = Input.Value;
|
||||
if (_index == 1)
|
||||
{
|
||||
_prevMa1 = _prevJma = Input.Value;
|
||||
return Input.Value;
|
||||
_upperBand = _lowerBand = price;
|
||||
}
|
||||
|
||||
double del1 = Input.Value - _upperBand;
|
||||
double del2 = Input.Value - _lowerBand;
|
||||
double del1 = price - _upperBand;
|
||||
double del2 = price - _lowerBand;
|
||||
double volty = Math.Max(Math.Abs(del1), Math.Abs(del2));
|
||||
|
||||
_voltyShort.Add(volty, Input.IsNew);
|
||||
double vsum = _vsumBuff.Newest() + 0.1 * (volty - _voltyShort.Oldest());
|
||||
_vsumBuff.Add(vsum, Input.IsNew);
|
||||
_vsumBuff.Add(volty, Input.IsNew);
|
||||
_vSum += (_vsumBuff[^1] - _vsumBuff[0]) / 10;
|
||||
_avoltyBuff.Add(_vSum, Input.IsNew);
|
||||
double avgvolty = _avoltyBuff.Average();
|
||||
|
||||
double avolty = 0;
|
||||
for (int i = 0; i < _vsumBuff.Count; i++) { avolty += _vsumBuff[i]; }
|
||||
avolty /= _vsumBuff.Count;
|
||||
double rvolty = (avgvolty > 0) ? volty / avgvolty : 1;
|
||||
rvolty = Math.Min(Math.Max(rvolty, 1.0), Math.Pow(_len1, 1.0 / _pow1));
|
||||
|
||||
double rVolty = (avolty > 0) ? volty / avolty *20: 0;
|
||||
double _len1 = Math.Max((Math.Log(Math.Sqrt(Period)) / Math.Log(2.0)) + 2.0, 0);
|
||||
double _pow1 = Math.Max(_len1 - 2, 0.5);
|
||||
double pow2 = Math.Pow(rvolty, _pow1);
|
||||
double Kv = Math.Pow(_beta, Math.Sqrt(pow2));
|
||||
|
||||
rVolty = Math.Clamp(rVolty, 1.0, Math.Pow(_len1, 1.0 / _pow1));
|
||||
_upperBand = (del1 >= 0) ? price : price - (Kv * del1);
|
||||
_lowerBand = (del2 <= 0) ? price : price - (Kv * del2);
|
||||
|
||||
double _pow2 = Math.Pow(rVolty, _pow1);
|
||||
double _beta = 0.45 * (Period - 1) / (0.45 * (Period - 1) + 2);
|
||||
double len2 = Math.Sqrt(0.5 * (Period - 1)) * _len1;
|
||||
|
||||
double _Kv = Math.Pow (_beta, Math.Sqrt(_pow2)) *1.5;
|
||||
|
||||
_upperBand = (del1 > 0) ? Input.Value : Input.Value - (_Kv * del1);
|
||||
_lowerBand = (del2 < 0) ? Input.Value : Input.Value - (_Kv * del2);
|
||||
|
||||
double alpha = Math.Pow(_beta, _pow2);
|
||||
double ma1 = alpha * (_prevMa1 - Input.Value) + Input.Value;
|
||||
|
||||
|
||||
|
||||
double alpha = Math.Pow(_beta, pow2);
|
||||
double ma1 = (1 - alpha) * Input.Value + alpha * _prevMa1;
|
||||
_prevMa1 = ma1;
|
||||
|
||||
double det0 = _beta * (_prevDet0 - Input.Value + ma1) + Input.Value - ma1;
|
||||
double det0 = (price - ma1) * (1 - _beta) + _beta * _prevDet0;
|
||||
_prevDet0 = det0;
|
||||
double ma2 = ma1 + _phase * det0;
|
||||
|
||||
double det1 = ((1 - alpha) * (1 - alpha) * (ma2 - _prevJma)) + (alpha * alpha * _prevDet1 );
|
||||
double det1 = ((ma2 - _prevJma) * (1 - alpha) * (1 - alpha) ) + (alpha * alpha * _prevDet1);
|
||||
_prevDet1 = det1;
|
||||
double jma = _prevJma + det1;
|
||||
_prevJma = jma;
|
||||
|
||||
UpperBand = _upperBand;
|
||||
LowerBand = _lowerBand;
|
||||
Volty = volty;
|
||||
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
return jma;
|
||||
}
|
||||
@@ -208,22 +234,17 @@ public class Jma1 : AbstractBase
|
||||
|
||||
#!csharp
|
||||
|
||||
TSeries ma = Triangle;
|
||||
TSeries re = TriangleJMA;
|
||||
TSeries ma = Complex;
|
||||
TSeries re = ComplexJMA;
|
||||
TSeries out1 = new();
|
||||
TSeries out2 = new();
|
||||
Jma calc = new(10);
|
||||
Jma1 calc1 = new(10);
|
||||
|
||||
Jmaxx calc = new(10);
|
||||
|
||||
foreach (var value in ma) { out1.Add(calc.Calc(value)); }
|
||||
foreach (var value in ma) { out2.Add(calc1.Calc(value)); }
|
||||
|
||||
Plot plt = new();
|
||||
var sigplot = plt.Add.Signal(ma.v.ToArray()[60..80]);
|
||||
var jmaplot = plt.Add.Signal(re.v.ToArray()[60..80]); sigplot.Color = ScottPlot.Colors.Red; sigplot.LineWidth = 2; jmaplot.LineWidth = 3;
|
||||
//var jma1plot = plt.Add.Signal(out1.v.ToArray()[60..80]); jma1plot.Color = ScottPlot.Colors.Purple; jma1plot.LineWidth = 3;
|
||||
var jma2plot = plt.Add.Signal(out2.v.ToArray()[60..80]); jma2plot.Color = ScottPlot.Colors.Blue; jma2plot.LineWidth = 3;
|
||||
var jma1plot = plt.Add.Signal(out1.v.ToArray()[60..80]); jma1plot.Color = ScottPlot.Colors.Purple; jma1plot.LineWidth = 3;
|
||||
|
||||
plt.Display();
|
||||
|
||||
#!csharp
|
||||
|
||||
#r "nuget: Plotly.net.Interactive"
|
||||
using Plotly.NET.Interactive;
|
||||
|
||||
@@ -9,7 +9,10 @@ public class JmaIndicator : Indicator, IWatchlistIndicator
|
||||
public int Periods { get; set; } = 10;
|
||||
|
||||
[InputParameter("Phase", sortIndex: 2, -100, 100, 1, 0)]
|
||||
public double Phase { get; set; } = 0;
|
||||
public int Phase { get; set; } = 0;
|
||||
|
||||
[InputParameter("Beta factor", sortIndex: 3, minimum: 0, maximum:5 , increment: 0.01, decimalPlaces: 2)]
|
||||
public double Factor { get; set; } = 0.45;
|
||||
|
||||
[InputParameter("Data source", sortIndex: 4, variants: [
|
||||
"Open", SourceType.Open,
|
||||
@@ -34,7 +37,7 @@ public class JmaIndicator : Indicator, IWatchlistIndicator
|
||||
public int MinHistoryDepths => Math.Max(65,Periods * 2);
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public override string ShortName => $"JMA {Periods}:{Phase}:{SourceName}";
|
||||
public override string ShortName => $"JMA {Periods}:{Phase}:{Factor:F2}:{SourceName}";
|
||||
|
||||
public JmaIndicator()
|
||||
{
|
||||
@@ -49,7 +52,7 @@ public class JmaIndicator : Indicator, IWatchlistIndicator
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
ma = new Jma(Periods, Phase);
|
||||
ma = new Jma(period: Periods, phase: Phase, factor: Factor);
|
||||
SourceName = Source.ToString();
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
using System.Diagnostics.Metrics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class MacdIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
[InputParameter("Slow EMA", sortIndex: 1, 1, 1000, 1, 0)]
|
||||
public int Slow { get; set; } = 26;
|
||||
|
||||
[InputParameter("Fast EMA", sortIndex: 2, 1, 2000, 1, 0)]
|
||||
public int Fast { get; set; } = 12;
|
||||
|
||||
[InputParameter("Signal line", sortIndex: 3, 1, 2000, 1, 0)]
|
||||
public int Signal { get; set; } = 9;
|
||||
|
||||
[InputParameter("Use SMA for warmup period", sortIndex: 2)]
|
||||
public bool UseSMA { get; set; } = false;
|
||||
|
||||
[InputParameter("Data source", sortIndex: 3, variants: [
|
||||
"Open", SourceType.Open,
|
||||
"High", SourceType.High,
|
||||
"Low", SourceType.Low,
|
||||
"Close", SourceType.Close,
|
||||
"HL/2 (Median)", SourceType.HL2,
|
||||
"OC/2 (Midpoint)", SourceType.OC2,
|
||||
"OHL/3 (Mean)", SourceType.OHL3,
|
||||
"HLC/3 (Typical)", SourceType.HLC3,
|
||||
"OHLC/4 (Average)", SourceType.OHLC4,
|
||||
"HLCC/4 (Weighted)", SourceType.HLCC4
|
||||
])]
|
||||
public SourceType Source { get; set; } = SourceType.Close;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 21)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
|
||||
private Ema? slow_ma;
|
||||
private Ema? fast_ma;
|
||||
private Ema? signal_ma;
|
||||
private Slope? histSlope;
|
||||
protected LineSeries? MainSeries;
|
||||
protected LineSeries? SignalSeries;
|
||||
protected LineSeries? HistogramSeries;
|
||||
protected LineSeries? HistSlopeSeries;
|
||||
|
||||
protected string? SourceName;
|
||||
public int MinHistoryDepths => Slow;
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public override string ShortName => $"MACD {Slow}:{Fast}:{Signal}";
|
||||
|
||||
public MacdIndicator()
|
||||
{
|
||||
OnBackGround = true;
|
||||
SeparateWindow = true;
|
||||
SourceName = Source.ToString();
|
||||
Name = "MACD - Moving Average Convergence Divergence";
|
||||
Description = "MACD";
|
||||
MainSeries = new(name: $"MAIN", color: Color.Blue, width: 2, style: LineStyle.Solid);
|
||||
SignalSeries = new(name: $"SIGNAL", color: Color.Yellow, width: 2, style: LineStyle.Solid);
|
||||
HistogramSeries = new(name: $"HISTOGRAM", color: Color.White, width: 2, style: LineStyle.Solid);
|
||||
HistSlopeSeries = new(name: $"SLOPE", color: Color.Transparent, width: 2, style: LineStyle.Solid);
|
||||
HistSlopeSeries.Visible = false;
|
||||
|
||||
AddLineSeries(MainSeries);
|
||||
AddLineSeries(SignalSeries);
|
||||
AddLineSeries(HistogramSeries);
|
||||
AddLineSeries(HistSlopeSeries);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
slow_ma = new(Slow, useSma: UseSMA);
|
||||
fast_ma = new(Fast, useSma: UseSMA);
|
||||
signal_ma = new(Signal, useSma: UseSMA);
|
||||
histSlope = new(2);
|
||||
SourceName = Source.ToString();
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TValue input = this.GetInputValue(args, Source);
|
||||
slow_ma!.Calc(input);
|
||||
fast_ma!.Calc(input);
|
||||
double main = fast_ma.Value - slow_ma.Value;
|
||||
double signal = signal_ma!.Calc(main);
|
||||
double histogram = main - signal;
|
||||
histSlope!.Calc(histogram);
|
||||
|
||||
MainSeries!.SetValue(main);
|
||||
MainSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here
|
||||
SignalSeries!.SetValue(signal);
|
||||
SignalSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here
|
||||
HistogramSeries!.SetValue(histogram);
|
||||
HistogramSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here
|
||||
HistSlopeSeries!.SetValue(histSlope.Value);
|
||||
HistSlopeSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here
|
||||
}
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
gr.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
var mainWindow = this.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
|
||||
gr.SetClip(clientRect);
|
||||
DateTime leftTime = new[] { converter.GetTime(clientRect.Left), this.HistoricalData.Time(this!.Count - 1) }.Max();
|
||||
DateTime rightTime = new[] { converter.GetTime(clientRect.Right), this.HistoricalData.Time(0) }.Min();
|
||||
int leftIndex = (int)this.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1;
|
||||
int rightIndex = (int)this.HistoricalData.GetIndexByTime(rightTime.Ticks);
|
||||
|
||||
for (int i = rightIndex; i < leftIndex; i++)
|
||||
{
|
||||
int barX = (int)converter.GetChartX(this.HistoricalData.Time(i));
|
||||
int barY = (int)converter.GetChartY(HistogramSeries![i]*2.0);
|
||||
int barY0 = (int)converter.GetChartY(0);
|
||||
int HistBarWidth = this.CurrentChart.BarsWidth - 2;
|
||||
|
||||
Brush lowGreen = new SolidBrush(Color.FromArgb(255, 0, 100, 0));
|
||||
Brush highGreen = new SolidBrush(Color.FromArgb(255, 50, 255, 50));
|
||||
Brush lowRed = new SolidBrush(Color.FromArgb(255, 100, 0, 0));
|
||||
Brush highRed = new SolidBrush(Color.FromArgb(255, 255, 50, 50));
|
||||
|
||||
if (HistogramSeries[i] > 0)
|
||||
{
|
||||
Brush col = HistSlopeSeries![i] > 0 ? highGreen : lowGreen;
|
||||
gr.FillRectangle(col, barX, barY, HistBarWidth, Math.Abs(barY - barY0));
|
||||
}
|
||||
else
|
||||
{
|
||||
Brush col = HistSlopeSeries![i] < 0 ? highRed : lowRed;
|
||||
gr.FillRectangle(col, barX, barY0, HistBarWidth, Math.Abs(barY0 - barY));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.PaintSmoothCurve(args, MainSeries!, slow_ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.3);
|
||||
this.PaintSmoothCurve(args, SignalSeries!, slow_ma!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
|
||||
base.OnPaintChart(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,12 @@ public enum SourceType
|
||||
{
|
||||
Open, High, Low, Close, HL2, OC2, OHL3, HLC3, OHLC4, HLCC4
|
||||
}
|
||||
|
||||
public enum MaType
|
||||
{
|
||||
Alma, Dema, Dsma, Dwma, Ema, Epma, Frama, Fwma, Gma, Hma, Hwma, Jma, Kama, Maaf, Mgdi, MMa, Pwma, Rema, Rma, Sinema, Sma, Smma, T3, Tema, Trima, Vidya, Wma, Zlema
|
||||
}
|
||||
|
||||
public static class IndicatorExtensions
|
||||
{
|
||||
public static TValue GetInputValue(this Indicator indicator, UpdateArgs args, SourceType source)
|
||||
@@ -59,14 +65,35 @@ public static class IndicatorExtensions
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
|
||||
public static void PaintHLine(this Indicator indicator, PaintChartEventArgs args, double value, Pen pen)
|
||||
{
|
||||
if (indicator.CurrentChart == null)
|
||||
return;
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
var mainWindow = indicator.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
gr.SetClip(clientRect);
|
||||
int leftX = clientRect.Left;
|
||||
int rightX = clientRect.Right;
|
||||
int Y = (int)converter.GetChartY(value);
|
||||
using (pen)
|
||||
{
|
||||
gr.DrawLine(pen, new Point(leftX, Y), new Point(rightX, Y));
|
||||
}
|
||||
}
|
||||
|
||||
public static void PaintSmoothCurve(this Indicator indicator, PaintChartEventArgs args, LineSeries series, int warmupPeriod, bool showColdValues = true, double tension = 0.2)
|
||||
{
|
||||
if (!series.Visible || indicator.CurrentChart == null)
|
||||
return;
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
var mainWindow = indicator.CurrentChart.MainWindow;
|
||||
gr.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
var mainWindow = indicator.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
|
||||
gr.SetClip(clientRect);
|
||||
@@ -110,6 +137,53 @@ public static class IndicatorExtensions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void PaintHistogram(this Indicator indicator, PaintChartEventArgs args, LineSeries series, int warmupPeriod, bool showColdValues = true)
|
||||
{
|
||||
if (!series.Visible || indicator.CurrentChart == null)
|
||||
return;
|
||||
|
||||
Graphics gr = args.Graphics;
|
||||
gr.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
var mainWindow = indicator.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
|
||||
gr.SetClip(clientRect);
|
||||
DateTime leftTime = new[] { converter.GetTime(clientRect.Left), indicator.HistoricalData.Time(indicator!.Count - 1) }.Max();
|
||||
DateTime rightTime = new[] { converter.GetTime(clientRect.Right), indicator.HistoricalData.Time(0) }.Min();
|
||||
int leftIndex = (int)indicator.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1;
|
||||
int rightIndex = (int)indicator.HistoricalData.GetIndexByTime(rightTime.Ticks);
|
||||
|
||||
for (int i = rightIndex; i < leftIndex; i++)
|
||||
{
|
||||
int barX = (int)converter.GetChartX(indicator.HistoricalData.Time(i));
|
||||
int barY = (int)converter.GetChartY(series[i]);
|
||||
int barY0 = (int)converter.GetChartY(0);
|
||||
int HistBarWidth = indicator.CurrentChart.BarsWidth - 2;
|
||||
|
||||
if (series[i] > 0)
|
||||
{
|
||||
using (Brush hist = new SolidBrush(Color.FromArgb(150, 0, 255, 0)))
|
||||
{
|
||||
gr.FillRectangle(hist, barX, barY, HistBarWidth, Math.Abs(barY - barY0));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (Brush hist = new SolidBrush(Color.FromArgb(150, 255, 0, 0)))
|
||||
{
|
||||
gr.FillRectangle(hist, barX, barY0, HistBarWidth, Math.Abs(barY0 - barY));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void DrawText(this Indicator indicator, PaintChartEventArgs args, string text)
|
||||
{
|
||||
if (indicator.CurrentChart == null)
|
||||
|
||||
@@ -8,9 +8,12 @@ public class AtrIndicator : 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 Atr? atr;
|
||||
protected LineSeries? AtrSeries;
|
||||
public static int MinHistoryDepths => 2;
|
||||
public int MinHistoryDepths => Math.Max(5, Periods * 2);
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public AtrIndicator()
|
||||
@@ -19,7 +22,7 @@ public class AtrIndicator : Indicator, IWatchlistIndicator
|
||||
Description = "Measures market volatility by calculating the average range between high and low prices.";
|
||||
SeparateWindow = true;
|
||||
|
||||
AtrSeries = new("ATR", Color.Blue, 2, LineStyle.Solid);
|
||||
AtrSeries = new($"ATR {Periods}", Color.Blue, 2, LineStyle.Solid);
|
||||
AddLineSeries(AtrSeries);
|
||||
}
|
||||
|
||||
@@ -35,7 +38,17 @@ public class AtrIndicator : Indicator, IWatchlistIndicator
|
||||
TValue result = atr!.Calc(input);
|
||||
|
||||
AtrSeries!.SetValue(result.Value);
|
||||
AtrSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here
|
||||
|
||||
}
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
|
||||
public override string ShortName => $"ATR ({Periods})";
|
||||
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
this.PaintHLine(args, 0.05, new Pen(Color.DarkRed, width: 2));
|
||||
this.PaintSmoothCurve(args, AtrSeries!, atr!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class CmoIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
[InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Periods { get; set; } = 9;
|
||||
|
||||
[InputParameter("Data source", sortIndex: 5, variants: [
|
||||
"Open", SourceType.Open,
|
||||
"High", SourceType.High,
|
||||
"Low", SourceType.Low,
|
||||
"Close", SourceType.Close,
|
||||
"HL/2 (Median)", SourceType.HL2,
|
||||
"OC/2 (Midpoint)", SourceType.OC2,
|
||||
"OHL/3 (Mean)", SourceType.OHL3,
|
||||
"HLC/3 (Typical)", SourceType.HLC3,
|
||||
"OHLC/4 (Average)", SourceType.OHLC4,
|
||||
"HLCC/4 (Weighted)", SourceType.HLCC4
|
||||
])]
|
||||
public SourceType Source { get; set; } = SourceType.Close;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 21)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
|
||||
private Cmo? cmo;
|
||||
protected string? SourceName;
|
||||
protected LineSeries? CmoSeries;
|
||||
public int MinHistoryDepths => Periods + 1;
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
|
||||
public CmoIndicator()
|
||||
{
|
||||
Name = "CMO - Chande Momentum Oscillator";
|
||||
Description = "Measures the momentum of price changes using the difference between the sum of recent gains and the sum of recent losses.";
|
||||
SeparateWindow = true;
|
||||
SourceName = Source.ToString();
|
||||
CmoSeries = new($"CMO {Periods}", Color.Blue, 2, LineStyle.Solid);
|
||||
AddLineSeries(CmoSeries);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
cmo = new Cmo(Periods);
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TValue input = this.GetInputValue(args, Source);
|
||||
cmo!.Calc(input);
|
||||
|
||||
CmoSeries!.SetValue(cmo.Value);
|
||||
CmoSeries!.SetMarker(0, Color.Transparent); //OnPaintChart draws the line, hidden here
|
||||
|
||||
}
|
||||
|
||||
public override string ShortName => $"CMO ({Periods}:{SourceName})";
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
this.PaintHLine(args, 0, new Pen(Color.DarkGray, width: 1));
|
||||
this.PaintHLine(args, 50, new Pen(Color.Blue, width: 1));
|
||||
this.PaintHLine(args, -50, new Pen(Color.Blue, width: 1));
|
||||
this.PaintSmoothCurve(args, CmoSeries!, cmo!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class FlowIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
protected string? SourceName;
|
||||
public static int MinHistoryDepths => 2;
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public FlowIndicator()
|
||||
{
|
||||
Name = "Flow Visualization";
|
||||
SeparateWindow = false;
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
// placeholder
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
// placeholder
|
||||
}
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
Graphics gr = args.Graphics;
|
||||
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
||||
var mainWindow = this.CurrentChart.Windows[args.WindowIndex];
|
||||
var converter = mainWindow.CoordinatesConverter;
|
||||
var clientRect = mainWindow.ClientRectangle;
|
||||
gr.SetClip(clientRect);
|
||||
DateTime leftTime = new[] { converter.GetTime(clientRect.Left), this.HistoricalData.Time(this!.Count - 1) }.Max();
|
||||
DateTime rightTime = new[] { converter.GetTime(clientRect.Right), this.HistoricalData.Time(0) }.Min();
|
||||
|
||||
int leftIndex = (int)this.HistoricalData.GetIndexByTime(leftTime.Ticks) + 1;
|
||||
int rightIndex = (int)this.HistoricalData.GetIndexByTime(rightTime.Ticks);
|
||||
int width = this.CurrentChart.BarsWidth;
|
||||
|
||||
for (int i = rightIndex; i < leftIndex; i++)
|
||||
{
|
||||
int barX1 = (int)converter.GetChartX(this.HistoricalData.Time(i));
|
||||
int barY1 = (int)converter.GetChartY(this.HistoricalData.Open(i));
|
||||
int barYHigh = (int)converter.GetChartY(this.HistoricalData.High(i));
|
||||
int barYLow = (int)converter.GetChartY(this.HistoricalData.Low(i));
|
||||
int barX2 = barX1 + width;
|
||||
int barY2 = (int)converter.GetChartY(this.HistoricalData.Close(i));
|
||||
using (Brush transparentBrush = new SolidBrush(Color.FromArgb(250, 70, 70, 70)))
|
||||
{
|
||||
gr.FillRectangle(transparentBrush, barX1, barYHigh - 1, CurrentChart.BarsWidth, Math.Abs(barYLow - barYHigh) + 2);
|
||||
}
|
||||
using (Brush circ = new SolidBrush(Color.FromArgb(100, 255, 255, 0)))
|
||||
{
|
||||
int size = 3;
|
||||
gr.FillEllipse(circ, barX1 - size, barY1 - size, 2 * size, 2 * size);
|
||||
gr.FillEllipse(circ, barX2 - size, barY2 - size, 2 * size, 2 * size);
|
||||
}
|
||||
using (Pen defaultPen = new(Color.Yellow, 3))
|
||||
{
|
||||
defaultPen.StartCap = LineCap.Round;
|
||||
defaultPen.EndCap = LineCap.Round;
|
||||
gr.DrawLine(defaultPen, barX1, barY1, barX2, barY2);
|
||||
}
|
||||
if (i > 0)
|
||||
{
|
||||
int barX0 = (int)converter.GetChartX(this.HistoricalData.Time(i - 1));
|
||||
int barY0 = (int)converter.GetChartY(this.HistoricalData.Open(i - 1));
|
||||
using (Pen dottedPen = new(Color.Yellow, 1))
|
||||
{
|
||||
dottedPen.DashStyle = DashStyle.Dot;
|
||||
gr.DrawLine(dottedPen, barX2, barY2, barX0, barY0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class JbandsIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
[InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Periods { get; set; } = 14;
|
||||
|
||||
[InputParameter("Data source", sortIndex: 5, variants: [
|
||||
"Open", SourceType.Open,
|
||||
"High", SourceType.High,
|
||||
"Low", SourceType.Low,
|
||||
"Close", SourceType.Close,
|
||||
"HL/2 (Median)", SourceType.HL2,
|
||||
"OC/2 (Midpoint)", SourceType.OC2,
|
||||
"OHL/3 (Mean)", SourceType.OHL3,
|
||||
"HLC/3 (Typical)", SourceType.HLC3,
|
||||
"OHLC/4 (Average)", SourceType.OHLC4,
|
||||
"HLCC/4 (Weighted)", SourceType.HLCC4
|
||||
])]
|
||||
public SourceType Source { get; set; } = SourceType.Close;
|
||||
|
||||
[InputParameter("vShort", sortIndex: 6, -100, 100, 1, 0)]
|
||||
public int Phase { get; set; } = 10;
|
||||
|
||||
private Jma? jmaUp;
|
||||
private Jma? jmaLo;
|
||||
protected LineSeries? UbSeries;
|
||||
protected LineSeries? LbSeries;
|
||||
protected string? SourceName;
|
||||
public static int MinHistoryDepths => 2;
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public JbandsIndicator()
|
||||
{
|
||||
Name = "JBANDS - Mark Jurik's Bands";
|
||||
Description = "Upper and Lower Bands.";
|
||||
SeparateWindow = false;
|
||||
|
||||
UbSeries = new("UB", Color.Blue, 2, LineStyle.Solid);
|
||||
LbSeries = new("LB", Color.Red, 2, LineStyle.Solid);
|
||||
AddLineSeries(UbSeries);
|
||||
AddLineSeries(LbSeries);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
jmaUp = new(Periods, phase: Phase);
|
||||
jmaLo = new(Periods, phase: Phase);
|
||||
SourceName = Source.ToString();
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TBar input = IndicatorExtensions.GetInputBar(this, args);
|
||||
jmaUp!.Calc(input.High);
|
||||
jmaLo!.Calc(input.Low);
|
||||
|
||||
UbSeries!.SetValue(jmaUp.UpperBand);
|
||||
LbSeries!.SetValue(jmaLo.LowerBand);
|
||||
}
|
||||
|
||||
public override string ShortName => $"JBands ({Periods}:{Phase})";
|
||||
}
|
||||
@@ -6,11 +6,27 @@ namespace QuanTAlib;
|
||||
public class JvoltyIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
[InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Periods { get; set; } = 20;
|
||||
public int Periods { get; set; } = 14;
|
||||
|
||||
private Jvolty? jvolty;
|
||||
[InputParameter("Data source", sortIndex: 5, variants: [
|
||||
"Open", SourceType.Open,
|
||||
"High", SourceType.High,
|
||||
"Low", SourceType.Low,
|
||||
"Close", SourceType.Close,
|
||||
"HL/2 (Median)", SourceType.HL2,
|
||||
"OC/2 (Midpoint)", SourceType.OC2,
|
||||
"OHL/3 (Mean)", SourceType.OHL3,
|
||||
"HLC/3 (Typical)", SourceType.HLC3,
|
||||
"OHLC/4 (Average)", SourceType.OHLC4,
|
||||
"HLCC/4 (Weighted)", SourceType.HLCC4
|
||||
])]
|
||||
public SourceType Source { get; set; } = SourceType.Close;
|
||||
|
||||
private Jma? jma;
|
||||
protected LineSeries? JvoltySeries;
|
||||
public static int MinHistoryDepths => 2;
|
||||
|
||||
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public JvoltyIndicator()
|
||||
@@ -25,16 +41,17 @@ public class JvoltyIndicator : Indicator, IWatchlistIndicator
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
jvolty = new (Periods);
|
||||
jma = new(Periods);
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TBar input = IndicatorExtensions.GetInputBar(this, args);
|
||||
TValue result = jvolty!.Calc(input);
|
||||
TValue input = this.GetInputValue(args, Source);
|
||||
jma!.Calc(input);
|
||||
|
||||
JvoltySeries!.SetValue(jma.Volty);
|
||||
|
||||
JvoltySeries!.SetValue(result.Value);
|
||||
}
|
||||
|
||||
public override string ShortName => $"JVOLTY ({Periods})";
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class RsiIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
[InputParameter("Periods", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Periods { get; set; } = 14;
|
||||
|
||||
[InputParameter("Data source", sortIndex: 5, variants: [
|
||||
"Open", SourceType.Open,
|
||||
"High", SourceType.High,
|
||||
"Low", SourceType.Low,
|
||||
"Close", SourceType.Close,
|
||||
"HL/2 (Median)", SourceType.HL2,
|
||||
"OC/2 (Midpoint)", SourceType.OC2,
|
||||
"OHL/3 (Mean)", SourceType.OHL3,
|
||||
"HLC/3 (Typical)", SourceType.HLC3,
|
||||
"OHLC/4 (Average)", SourceType.OHLC4,
|
||||
"HLCC/4 (Weighted)", SourceType.HLCC4
|
||||
])]
|
||||
public SourceType Source { get; set; } = SourceType.Close;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 21)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
|
||||
private Rsi? rsi;
|
||||
protected string? SourceName;
|
||||
protected LineSeries? RsiSeries;
|
||||
public int MinHistoryDepths => Periods + 1;
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public RsiIndicator()
|
||||
{
|
||||
Name = "RSI - Relative Strength Index";
|
||||
Description = "Measures the speed and magnitude of recent price changes to evaluate overbought or oversold conditions.";
|
||||
SeparateWindow = true;
|
||||
SourceName = Source.ToString();
|
||||
RsiSeries = new($"RSI {Periods}", Color.Blue, 2, LineStyle.Solid);
|
||||
AddLineSeries(RsiSeries);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
rsi = new Rsi(Periods);
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TValue input = this.GetInputValue(args, Source);
|
||||
rsi!.Calc(input);
|
||||
|
||||
RsiSeries!.SetValue(rsi.Value);
|
||||
RsiSeries!.SetMarker(0, Color.Transparent);
|
||||
}
|
||||
|
||||
public override string ShortName => $"RSI ({Periods}:{SourceName})";
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
this.PaintSmoothCurve(args, RsiSeries!, rsi!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Drawing;
|
||||
using TradingPlatform.BusinessLayer;
|
||||
|
||||
namespace QuanTAlib;
|
||||
|
||||
public class RsxIndicator : Indicator, IWatchlistIndicator
|
||||
{
|
||||
[InputParameter("Rsi Period", sortIndex: 1, 1, 2000, 1, 0)]
|
||||
public int Period { get; set; } = 14;
|
||||
|
||||
[InputParameter("Data source", sortIndex: 5, variants: [
|
||||
"Open", SourceType.Open,
|
||||
"High", SourceType.High,
|
||||
"Low", SourceType.Low,
|
||||
"Close", SourceType.Close,
|
||||
"HL/2 (Median)", SourceType.HL2,
|
||||
"OC/2 (Midpoint)", SourceType.OC2,
|
||||
"OHL/3 (Mean)", SourceType.OHL3,
|
||||
"HLC/3 (Typical)", SourceType.HLC3,
|
||||
"OHLC/4 (Average)", SourceType.OHLC4,
|
||||
"HLCC/4 (Weighted)", SourceType.HLCC4
|
||||
])]
|
||||
public SourceType Source { get; set; } = SourceType.Close;
|
||||
|
||||
[InputParameter("Show cold values", sortIndex: 21)]
|
||||
public bool ShowColdValues { get; set; } = true;
|
||||
|
||||
private Rsx? rsx;
|
||||
protected string? SourceName;
|
||||
protected LineSeries? RsxSeries;
|
||||
public int MinHistoryDepths => Period + 1;
|
||||
int IWatchlistIndicator.MinHistoryDepths => MinHistoryDepths;
|
||||
|
||||
public RsxIndicator()
|
||||
{
|
||||
Name = "RSX - Jurik Trend Strengt Index";
|
||||
Description = "Measures the speed and magnitude of recent price changes to evaluate overbought or oversold conditions.";
|
||||
SeparateWindow = true;
|
||||
SourceName = Source.ToString();
|
||||
RsxSeries = new($"RSX {Period}", Color.Blue, 2, LineStyle.Solid);
|
||||
AddLineSeries(RsxSeries);
|
||||
}
|
||||
|
||||
protected override void OnInit()
|
||||
{
|
||||
rsx = new(Period);
|
||||
base.OnInit();
|
||||
}
|
||||
|
||||
protected override void OnUpdate(UpdateArgs args)
|
||||
{
|
||||
TValue input = this.GetInputValue(args, Source);
|
||||
rsx!.Calc(input);
|
||||
|
||||
RsxSeries!.SetValue(rsx.Value);
|
||||
RsxSeries!.SetMarker(0, Color.Transparent);
|
||||
}
|
||||
|
||||
public override string ShortName => $"RSX ({Period}:{SourceName})";
|
||||
|
||||
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
public override void OnPaintChart(PaintChartEventArgs args)
|
||||
{
|
||||
base.OnPaintChart(args);
|
||||
this.PaintSmoothCurve(args, RsxSeries!, rsx!.WarmupPeriod, showColdValues: ShowColdValues, tension: 0.2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user