From 148f0ea8469178a46ef2973dc2a4bfa42554dae2 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Thu, 26 Sep 2024 10:44:09 -0700 Subject: [PATCH] dependabot --- benchmark/growthBench.cs | 15 +- docs/_sidebar.md | 35 +- docs/essays/realtime.md | 43 +++ docs/indicators/averages/afirma/afirma.md | 46 +-- docs/indicators/averages/afirma/analysis.md | 60 +++ docs/indicators/averages/afirma/calc.md | 67 ++++ docs/indicators/averages/afirma/charts.dib | 14 +- docs/indicators/averages/afirma/charts.md | 4 +- .../averages/afirma/img/AFIRMA6_B.svg | 330 ++++++++++++++++ .../{AFIRMA10_Chirp.svg => AFIRMA6_Chirp.svg} | 158 ++++---- ...AFIRMA10_ChirpG.svg => AFIRMA6_ChirpG.svg} | 158 ++++---- ...IRMA10_Complex.svg => AFIRMA6_Complex.svg} | 158 ++++---- .../averages/afirma/img/AFIRMA6_Gauss.svg | 327 ++++++++++++++++ .../averages/afirma/img/AFIRMA6_HF.svg | 330 ++++++++++++++++ ...IRMA10_Impulse.svg => AFIRMA6_Impulse.svg} | 62 +-- .../averages/afirma/img/AFIRMA6_ImpulseHF.svg | 320 +++++++++++++++ .../averages/afirma/img/AFIRMA6_Market.svg | 357 +++++++++++++++++ ...MA10_Sawtooth.svg => AFIRMA6_Sawtooth.svg} | 114 +++--- ..._SawtoothHF.svg => AFIRMA6_SawtoothHF.svg} | 158 ++++---- .../{AFIRMA10_Sine.svg => AFIRMA6_Sine.svg} | 158 ++++---- .../{AFIRMA10_SineG.svg => AFIRMA6_SineG.svg} | 158 ++++---- .../{AFIRMA10_Spike.svg => AFIRMA6_Spike.svg} | 64 +-- ...MA10_Triangle.svg => AFIRMA6_Triangle.svg} | 158 ++++---- .../averages/afirma/img/AFIRMA6_White.svg | 335 ++++++++++++++++ docs/indicators/averages/alma/analysis.md | 51 +++ docs/indicators/averages/alma/calc.md | 45 +++ docs/indicators/averages/dema/analysis.md | 65 ++++ docs/indicators/averages/dema/calc.md | 48 +++ docs/indicators/averages/dsma/analysis.md | 0 docs/indicators/averages/dsma/calc.md | 0 docs/indicators/averages/dwma/analysis.md | 0 docs/indicators/averages/dwma/calc.md | 0 docs/indicators/averages/ema/analysis.md | 0 docs/indicators/averages/ema/calc.md | 0 docs/indicators/averages/sma/calc.md | 0 docs/indicators/averages/tema/analysis.md | 0 docs/indicators/averages/tema/calc.md | 52 +++ docs/indicators/averages/tema/charts.dib | 60 +++ docs/indicators/averages/tema/charts.md | 3 + .../AFIRMA10_B.svg => tema/img/TEMA10_B.svg} | 158 ++++---- .../averages/tema/img/TEMA10_Chirp.svg | 334 ++++++++++++++++ .../averages/tema/img/TEMA10_ChirpG.svg | 352 +++++++++++++++++ .../averages/tema/img/TEMA10_Complex.svg | 334 ++++++++++++++++ .../img/TEMA10_Gauss.svg} | 158 ++++---- .../img/TEMA10_HF.svg} | 158 ++++---- .../averages/tema/img/TEMA10_Impulse.svg | 346 +++++++++++++++++ .../img/TEMA10_ImpulseHF.svg} | 158 ++++---- .../img/TEMA10_Market.svg} | 158 ++++---- .../averages/tema/img/TEMA10_Sawtooth.svg | 364 ++++++++++++++++++ .../averages/tema/img/TEMA10_SawtoothHF.svg | 336 ++++++++++++++++ .../averages/tema/img/TEMA10_Sine.svg | 334 ++++++++++++++++ .../averages/tema/img/TEMA10_SineG.svg | 347 +++++++++++++++++ .../averages/tema/img/TEMA10_Spike.svg | 339 ++++++++++++++++ .../averages/tema/img/TEMA10_Triangle.svg | 355 +++++++++++++++++ .../img/TEMA10_White.svg} | 158 ++++---- docs/readme.md | 24 +- lib/averages/Afirma.cs | 233 +++++++---- lib/averages/Ama.cs | 89 +++++ quantower/Averages/AfirmaIndicator.cs | 28 +- quantower/Averages/AmaIndicator.cs | 25 ++ 60 files changed, 7437 insertions(+), 1304 deletions(-) create mode 100644 docs/essays/realtime.md create mode 100644 docs/indicators/averages/afirma/analysis.md create mode 100644 docs/indicators/averages/afirma/calc.md create mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_B.svg rename docs/indicators/averages/afirma/img/{AFIRMA10_Chirp.svg => AFIRMA6_Chirp.svg} (78%) rename docs/indicators/averages/afirma/img/{AFIRMA10_ChirpG.svg => AFIRMA6_ChirpG.svg} (79%) rename docs/indicators/averages/afirma/img/{AFIRMA10_Complex.svg => AFIRMA6_Complex.svg} (79%) create mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg create mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_HF.svg rename docs/indicators/averages/afirma/img/{AFIRMA10_Impulse.svg => AFIRMA6_Impulse.svg} (89%) create mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg create mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_Market.svg rename docs/indicators/averages/afirma/img/{AFIRMA10_Sawtooth.svg => AFIRMA6_Sawtooth.svg} (84%) rename docs/indicators/averages/afirma/img/{AFIRMA10_SawtoothHF.svg => AFIRMA6_SawtoothHF.svg} (79%) rename docs/indicators/averages/afirma/img/{AFIRMA10_Sine.svg => AFIRMA6_Sine.svg} (79%) rename docs/indicators/averages/afirma/img/{AFIRMA10_SineG.svg => AFIRMA6_SineG.svg} (79%) rename docs/indicators/averages/afirma/img/{AFIRMA10_Spike.svg => AFIRMA6_Spike.svg} (89%) rename docs/indicators/averages/afirma/img/{AFIRMA10_Triangle.svg => AFIRMA6_Triangle.svg} (80%) create mode 100644 docs/indicators/averages/afirma/img/AFIRMA6_White.svg create mode 100644 docs/indicators/averages/alma/analysis.md create mode 100644 docs/indicators/averages/alma/calc.md create mode 100644 docs/indicators/averages/dema/analysis.md create mode 100644 docs/indicators/averages/dema/calc.md create mode 100644 docs/indicators/averages/dsma/analysis.md create mode 100644 docs/indicators/averages/dsma/calc.md create mode 100644 docs/indicators/averages/dwma/analysis.md create mode 100644 docs/indicators/averages/dwma/calc.md create mode 100644 docs/indicators/averages/ema/analysis.md create mode 100644 docs/indicators/averages/ema/calc.md create mode 100644 docs/indicators/averages/sma/calc.md create mode 100644 docs/indicators/averages/tema/analysis.md create mode 100644 docs/indicators/averages/tema/calc.md create mode 100644 docs/indicators/averages/tema/charts.dib create mode 100644 docs/indicators/averages/tema/charts.md rename docs/indicators/averages/{afirma/img/AFIRMA10_B.svg => tema/img/TEMA10_B.svg} (79%) create mode 100644 docs/indicators/averages/tema/img/TEMA10_Chirp.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_ChirpG.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_Complex.svg rename docs/indicators/averages/{afirma/img/AFIRMA10_Gauss.svg => tema/img/TEMA10_Gauss.svg} (79%) rename docs/indicators/averages/{afirma/img/AFIRMA10_HF.svg => tema/img/TEMA10_HF.svg} (78%) create mode 100644 docs/indicators/averages/tema/img/TEMA10_Impulse.svg rename docs/indicators/averages/{afirma/img/AFIRMA10_ImpulseHF.svg => tema/img/TEMA10_ImpulseHF.svg} (78%) rename docs/indicators/averages/{afirma/img/AFIRMA10_Market.svg => tema/img/TEMA10_Market.svg} (80%) create mode 100644 docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_Sine.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_SineG.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_Spike.svg create mode 100644 docs/indicators/averages/tema/img/TEMA10_Triangle.svg rename docs/indicators/averages/{afirma/img/AFIRMA10_White.svg => tema/img/TEMA10_White.svg} (80%) create mode 100644 lib/averages/Ama.cs create mode 100644 quantower/Averages/AmaIndicator.cs diff --git a/benchmark/growthBench.cs b/benchmark/growthBench.cs index c01cdd8f..6dd123e4 100644 --- a/benchmark/growthBench.cs +++ b/benchmark/growthBench.cs @@ -38,9 +38,9 @@ public class EmaBenchmark } [Benchmark] - public void Afirma_bench() + public void Ema_bench() { - Afirma ma1 = new(Period); + Ema ma1 = new(Period); for (int i = 0; i < Length; i++) { TValue item = gbm.Generate(DateTime.Now).Close; @@ -70,15 +70,4 @@ public class EmaBenchmark ma1.Calc(item); } } - - [Benchmark] - public void Ema_bench() - { - Ema ma1 = new(Period); - for (int i = 0; i < Length; i++) - { - TValue item = gbm.Generate(DateTime.Now).Close; - ma1.Calc(item); - } - } } \ No newline at end of file diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 2bdd1409..cc1650b9 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -1,20 +1,36 @@ * [QuanTAlib](/) + * [Historical vs Real-time analysis](essays/realtime.md) * [Indicators](indicators/indicators.md) * Averages & Trends * [AFIRMA - Adaptive Filtering Integrated Recursive Moving Average](indicators/averages/afirma/afirma.md) - * [AFIRMA Charts](indicators/averages/afirma/charts.md) + * [Calculation](indicators/averages/afirma/calc.md) + * [Analysis](indicators/averages/afirma/analysis.md) + * [Charts](indicators/averages/afirma/charts.md) * [ALMA - Arnaud Legoux Moving Average](indicators/averages/alma/alma.md) - * [ALMA Charts](indicators/averages/alma/charts.md) + * [Calculation](indicators/averages/alma/calc.md) + * [Analysis](indicators/averages/alma/analysis.md) + * [Charts](indicators/averages/alma/charts.md) + * [AMA - Adaptive Moving Average](indicators/averages/ama/ama.md) + * [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) - * [DEMA Charts](indicators/averages/dema/charts.md) + * [Calculation](indicators/averages/dema/calc.md) + * [Analysis](indicators/averages/dema/analysis.md) + * [Charts](indicators/averages/dema/charts.md) * [DSMA - Deviation Scaled Moving Average](indicators/averages/dsma/dsma.md) - * [DSMA Charts](indicators/averages/dsma/charts.md) - * DWMA - Double Weighted Moving Average - * [DWMA Charts](indicators/averages/dwma/charts.md) + * [Calculation](indicators/averages/dsma/calculation.md) + * [Quality](indicators/averages/dsma/quality.md) + * [Charts](indicators/averages/dsma/charts.md) + * [DWMA - Double Weighted Moving Average](indicators/averages/dwma/calculation.md) + * [Calculation](indicators/averages/dwma/calculation.md) + * [Quality](indicators/averages/dwma/quality.md) + * [Charts](indicators/averages/dwma/charts.md) * [EMA - Exponential Moving Average](indicators/averages/ema/ema.md) * [Calculation](indicators/averages/ema/calculation.md) * [Quality](indicators/averages/ema/quality.md) - * [EMA Charts](indicators/averages/ema/charts.md) + * [Charts](indicators/averages/ema/charts.md) * EPMA - Endpoint Moving Average * FRAMA - Fractal Adaptive Moving Average * FWMA - Fibonacci-Weighted Moving Average @@ -37,7 +53,10 @@ * [Charts](indicators/averages/sma/charts.md) * SMMA - Smoothed Moving Average * T3 - Tillson T3 Moving Average - * TEMA - Triple Exponential Moving Average + * [TEMA - Triple Exponential Moving Average](indicators/averages/tema/tema.md) + * [Calculation](indicators/averages/tema/calc.md) + * [Analysis](indicators/averages/tema/analysis.md) + * [Charts](indicators/averages/tema/charts.md) * TRIMA - Triangular Moving Average * VIDYA - Variable Index Dynamic Average * WMA - Weighted Moving Average diff --git a/docs/essays/realtime.md b/docs/essays/realtime.md new file mode 100644 index 00000000..13a3f46f --- /dev/null +++ b/docs/essays/realtime.md @@ -0,0 +1,43 @@ +# Historical vs. Real-time Indicators: A Tale of Two Approaches + +**Indicators for historical analysis** are like long automation trains. They zoom through a complete set of provided historical data, crunching numbers faster in the series than you can say "bullish pattern." These indicators have the luxury of seeing the big picture all at once, from the oldest to the most current data point. That is allowing them to make end-to-end calculations with a bird's-eye view of market trends. + +On the flip side, **real-time indicators** are more like surfers riding the wave of not-yet-known incoming data. They process information as it arrives, often dealing with updates and corrections to the most recent data point. + +"*Currently the Close value of the bar is at \$3.10. Actually, it is at \$3.20. No, scrape that, it is at \$3.25, which also makes a new High of the current bar.*" + +It's a bit like trying to predict the ocean's next move while you're already on the wave – exciting, but challenging! Unknown upcoming data trends alongside with the constant possiblity of corrections of the last provided value - that makes historical analysis indicators practically useless; they are fine-tuned to calculate an output on a well-known array of all known and valid historical inputs. + + +### The High-Frequency Data Dilemma + +Imagine you attach your system to an active forex or crypto ticker, and you're receiving up to 200 updates per second to form a single one-second bar. 200 updates per second is not uncommon during an active trading rally of the day, sometimes exceeding 500 updates/second. That's a lot of data to process in real-time, right? Let's break it down: + +- In one second: Up to 200 updates +- In one minute: 12,000 updates +- In one hour: 720,000 updates +- In 24 hours: 17,280,000 updates + +Now, if we're talking about gathering 24 hours of one-second bars, we're looking at `86,400` data points (60 seconds * 60 minutes * 24 hours). And every single time we receive a new update (or a signal that a new bar started so the last bar is now sealed), we need to crunch through nearly 100,000 datapoints. And do that 200 times per second. That's the calculation demand that will make even the most hard-core historical analysis indicator choke and give up. + +### The Great Calculation Showdown + +Let's compare how our historical and real-time approaches would handle this data tsunami: + +**Historical Analysis Approach:** + +- Imagine recalculating the entire history with each new or updated data point. It's like rewriting the entire encyclopedia every time you learn a new fact. With 17,280,000 updates in a day , you'd be needing: +- `17,280,000 * 86,400 = 1,492,992,000,000` calculations. +- That's nearly 1.5 trillion calculations! Your poor computer might just decide to pack its bags and go on vacation. + +**Real-time Analysis Approach:** + +- Our real-time indicator doesn't need to recalculate the entire history. It just processes each new (or updated) data point as it arrives, and spits out the result. So, we're looking at a mere 17,280,000 calculations per day, one single calculation per each update. + +### Why This Matters + +This enormous difference in calculation requirements isn't just about saving your computer from a meltdown. It's about providing traders with insights when they use tens of indicators with many parameter variations across hundreds of tracked symbols. Real-time indicators allow for quicker decision-making, more responsive trading strategies, and the ability to catch market movements as they happen. + +So, the next time someone tells you that fine-tuned historical indicators are basically faster than performance of real-time indicators, you can wow them with your newfound knowledge. Just remember, in the world of technical analysis, being real-time isn't just a feature – it's a superpower! + +**Real-time analysis is like having a super-efficient personal assistant who only tells you what's new, while historical analysis is like that friend who insists on retelling you their entire life story every time you meet up for coffee.** \ No newline at end of file diff --git a/docs/indicators/averages/afirma/afirma.md b/docs/indicators/averages/afirma/afirma.md index ec8a714e..db119ae2 100644 --- a/docs/indicators/averages/afirma/afirma.md +++ b/docs/indicators/averages/afirma/afirma.md @@ -1,39 +1,27 @@ -## AFIRMA: Adaptive Filtering Integrated Recursive Moving Average +# AFIRMA: Autoregressive Finite Impulse Response Moving Average -### Concept +## Concept -AFIRMA combines elements of simple moving averages (`SMA`) with adaptive filtering techniques from signal processing. It aims to provide a more responsive indicator that can quickly adjust to market changes while maintaining stability. +AFIRMA indicator is a hybrid moving average that combines the benefits of digital filtering and cubic spline fitting to provide a smooth and accurate representation of price movement without significant time lag. -### Origin +## Origin -AFIRMA (Adaptive Filtering Integrated Recursive Moving Average) was developed by Clive Bowsher and Roland Meeks in their 2008 paper titled "*The Dynamics of Economic Functions: Modeling and Forecasting the Yield Curve.*" It was created as an improvement over traditional moving averages, designed to adapt more quickly to changes in financial time series data. +The AFIRMA indicator is based on the principles of digital signal processing and curve fitting. It was developed to address the limitations of traditional moving averages, which often suffer from time lag or fail to accurately track price movements. -### Key Features +## Key Features -1. **Adaptive Nature**: AFIRMA adjusts its behavior based on recent price movements, allowing it to respond more quickly to significant changes. -2. **Error-based Adaptation**: It uses the error between its last output and the current input to determine how much to adapt. -3. **Customizable Sensitivity**: The alpha parameter allows fine-tuning the indicator's responsiveness. +- **Digital Filter**: The AFIRMA indicator uses a digital filter to smooth out price movements. +- **Cubic Spline Fitting**: The latest candlesticks are smoothed using cubic spline fitting with the least square method to ensure a seamless transition. +- **Combined Moving Average**: The indicator combines the digital filter and cubic spline fitting to create a smooth moving average that accurately tracks prices without time lag. +- **Customizable Parameters**: The AFIRMA indicator allows users to adjust the Periods, Taps, and Window parameters to fine-tune the indicator's performance. -### Usage +## Advantages -1. **Trend Identification**: AFIRMA can help identify the start or end of trends more quickly than traditional moving averages. -2. **Signal Generation**: Traders may use crossovers of AFIRMA with price or other indicators to generate buy/sell signals. -3. **Dynamic Support/Resistance**: The AFIRMA line can act as a dynamic support or resistance level. -4. **Volatility Analysis**: The adaptive nature of AFIRMA can provide insights into market volatility. +- **Accurate Price Tracking**: The AFIRMA indicator provides a smooth and accurate representation of price movement without time lag. +- **Hybrid Approach**: The combination of digital filtering and cubic spline fitting provides a unique and effective approach to moving average calculation. -### Advantages +## Considerations -- More responsive to market changes compared to traditional moving averages. -- Reduces lag typically associated with moving averages. -- Customizable through its `alpha` parameter to suit different market conditions or trading styles. - -### Considerations - -- **Adaptive Factor**: Alpha serves as the base adaptive factor. It has a range between 0.0 and 1.0 that determines how quickly the AFIRMA responds to changes in the input data. -- **Error Sensitivity**: Alpha is used in calculating the adaptive factor, which is based on the error between the current input and the last AFIRMA value. -- **Balancing Stability and Responsiveness**: A smaller alpha (closer to 0.0) makes the AFIRMA more stable but less responsive to recent changes. -A larger alpha (closer to 1) makes the AFIRMA more responsive to recent changes but potentially more volatile. -- **Fine-tuning the Indicator**: - - In trending markets, a higher alpha might be preferred to capture price movements more quickly. - - In ranging markets, a lower alpha might be better to reduce false signals from price noise. -- **Adaptive Nature**: The use of alpha allows AFIRMA to adapt its behavior based on recent price movements. When there are significant changes (large errors), the adaptive factor increases, allowing AFIRMA to adjust more quickly. \ No newline at end of file +**Complexity**: The AFIRMA indicator is a complex filter that requires some understanding of digital signal processing and curve fitting to use it right. +- **Parameter Optimization**: Finding the optimal parameters for the AFIRMA indicator may require some experimentation and testing. +- **Computational Resources**: The AFIRMA indicator is computationally more intensive than traditional moving averages due to the use of cubic spline fitting. \ No newline at end of file diff --git a/docs/indicators/averages/afirma/analysis.md b/docs/indicators/averages/afirma/analysis.md new file mode 100644 index 00000000..8392e240 --- /dev/null +++ b/docs/indicators/averages/afirma/analysis.md @@ -0,0 +1,60 @@ +# AFIRMA: Benchmark Analysis + +This analysis evaluates the Autoregressive Finite Impulse Response Moving Average (AFIRMA) across four core benchmarks: accuracy, timeliness, overshooting, and smoothness. These benchmarks provide a comprehensive view of AFIRMA's performance characteristics and serve as a basis for comparison with other moving averages. + +## Accuracy (closeness to the original data) + +AFIRMA generally exhibits high accuracy in representing the original price data due to its sophisticated approach combining digital filtering and cubic spline fitting. + +- **Strengths**: + - The digital filter component helps to reduce noise while preserving important price trends. + - Cubic spline fitting for recent candlesticks ensures that the most current price movements are accurately represented. + +- **Considerations**: + - Accuracy can vary based on parameter settings. Incorrect parameter selection might lead to over-smoothing or under-smoothing, potentially reducing accuracy. + - In highly volatile markets, AFIRMA may sacrifice some accuracy for smoothness, especially if the parameters are set to prioritize noise reduction. + +## Timeliness (amount of lag) + +AFIRMA is designed to minimize lag, which is one of its key advantages over traditional moving averages. + +- **Strengths**: + - The combination of ARMA modeling and FIR filtering allows AFIRMA to respond quickly to price changes. + - Cubic spline fitting of recent data points further reduces lag for the most current price movements. + +- **Considerations**: + - While AFIRMA generally has less lag than traditional MAs, it's not entirely lag-free. Some minimal lag may still be present, especially with longer period settings. + - The amount of lag can be influenced by parameter settings. Optimizing for minimal lag might come at the cost of increased noise sensitivity. + +## Overshooting (overcompensation during reversals) + +AFIRMA's design helps to mitigate overshooting during price reversals, but the extent can vary based on settings and market conditions. + +- **Strengths**: + - The digital filtering component helps to dampen extreme price movements, reducing the likelihood of significant overshooting. + - Cubic spline fitting allows for smoother transitions during reversals, potentially minimizing overshoot. + +- **Considerations**: + - Overshooting can still occur, especially in markets with sudden, sharp reversals. + - The degree of overshooting can be influenced by parameter settings. More aggressive settings might increase responsiveness but also the risk of overshooting. + +## Smoothness (continuous 2nd derivative, less jagged flow) + +AFIRMA generally produces a smoother line than many traditional moving averages, which is one of its defining characteristics. + +- **Strengths**: + - The digital filtering component effectively smooths out minor price fluctuations and noise. + - Cubic spline fitting ensures a smooth transition between historical and current data points. + - The combination of these techniques results in a visually smooth line that can make trend identification easier. + +- **Considerations**: + - The degree of smoothness can be adjusted through parameter settings. Excessive smoothing might lead to a loss of responsiveness to genuine price changes. + - In some cases, the smooth line might mask short-term volatility that could be relevant for certain trading strategies. + +## Conclusion + +AFIRMA demonstrates strong performance across all four benchmarks, particularly excelling in accuracy, timeliness, and smoothness. Its complex approach allows it to balance these often competing characteristics more effectively than many traditional moving averages. + +However, it's important to note that AFIRMA's performance can be significantly influenced by its parameter settings. Optimal use of AFIRMA requires careful tuning of these parameters to balance accuracy, timeliness, overshooting resistance, and smoothness for the specific asset and timeframe being analyzed. + +When compared to other moving averages, AFIRMA generally offers superior or comparable performance across these benchmarks. However, this comes at the cost of increased complexity and computational requirements. Traders and analysts should weigh these factors when deciding whether to incorporate AFIRMA into their technical analysis toolkit. \ No newline at end of file diff --git a/docs/indicators/averages/afirma/calc.md b/docs/indicators/averages/afirma/calc.md new file mode 100644 index 00000000..fcc2255d --- /dev/null +++ b/docs/indicators/averages/afirma/calc.md @@ -0,0 +1,67 @@ +# The Math Behind AFIRMA + +## Components of AFIRMA + +AFIRMA is a hybrid beast, combining two main components: + +- Autoregressive Moving Average (ARMA) +- Finite Impulse Response (FIR) filter + +### ARMA Component + +$ X_t = c + \epsilon_t + \sum_{i=1}^p \phi_i X_{t-i} + \sum_{j=1}^q \theta_j \epsilon_{t-j} $ + +Where: +- $X_t$ is the time series value at time $t$
+- $c$ is a constant
+- $\phi_i$ are the parameters of the autoregressive term
+- $\theta_j$ are the parameters of the moving average term
+- $\epsilon_t$ is white noise
+ +### FIR Component + +$ y[n] = \sum_{i=0}^{N-1} b_i \cdot x[n-i] $ + +Where: +- $y[n]$ is the output signal +- $x[n]$ is the input signal +- $b_i$ are the filter coefficients +- $N$ is the filter order + +### AFIRMA: Putting It All Together + +AFIRMA combines these components and adds cubic spline fitting to the mix. The general form can be expressed as: + +$ AFIRMA_t = ARMA_t + FIR_t + CS_t $ + +Where: +- $ARMA_t$ is the ARMA component at time $t$ +- $FIR_t$ is the FIR component at time $t$ +- $CS_t$ is the cubic spline fitting component at time $t$ + +### Digital Filtering Process + +- The price data is passed through the digital filter to smooth out fluctuations. +- The filter coefficients are optimized based on the specified parameters (Periods, Taps, Window). + +### Cubic Spline Fitting + +For the most recent bars: + +- A cubic spline is fitted to the data points using the least squares method. +- This ensures a smooth transition between the filtered data and the most recent price movements. + +### Parameter Definitions + +The AFIRMA indicator allows for the adjustment of three main parameters: + +- **Periods**: Affects the overall smoothness of the indicator. +- *Taps*: Influences the complexity of the digital filter. +- *Window*: Determines the number of recent bars to which the cubic spline fitting is applied. + +### Computational Process + +- Apply the ARMA model to the price data. +- Pass the result through the FIR filter. +- Apply cubic spline fitting to the most recent data points. +- Combine the results to produce the final AFIRMA value. diff --git a/docs/indicators/averages/afirma/charts.dib b/docs/indicators/averages/afirma/charts.dib index d1c8c640..7d93d388 100644 --- a/docs/indicators/averages/afirma/charts.dib +++ b/docs/indicators/averages/afirma/charts.dib @@ -42,20 +42,22 @@ Dictionary Data = new Dictionary #!csharp String Name = "AFIRMA"; -int p = 10; -double alpha = 0.5; -Func Indicator = period => new Afirma(period,alpha); +int taps = 6; +int periods = 6; +Afirma.WindowType window = Afirma.WindowType.BlackmanHarris; + +Func Indicator = (taps, periods, windows) => new Afirma(taps: taps, periods: periods, window: window); foreach (var item in Data) { string Signal = item.Key; double[] Input = item.Value; TSeries Output = new(); - var ma = Indicator(p); + var ma = Indicator(taps, periods, window); foreach (var value in Input) { Output.Add(ma.Calc(value)); } Plot plt = new(); var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; - plt.Title($"{Signal} - {Name}({p}, {alpha})"); + plt.Title($"{Signal} - {Name}({taps}, {periods}, {window.ToString()})"); plt.Display(); - plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); + plt.SaveSvg($"img/{Name}{taps}_{Signal}.svg", 450, 300); } diff --git a/docs/indicators/averages/afirma/charts.md b/docs/indicators/averages/afirma/charts.md index d3b95b46..d4b19d30 100644 --- a/docs/indicators/averages/afirma/charts.md +++ b/docs/indicators/averages/afirma/charts.md @@ -1,3 +1,3 @@ -# AFIRMA Charts +# AFIRMA: Charts -![](img/AFIRMA10_Spike.svg) ![](img/AFIRMA10_Impulse.svg) ![](img/AFIRMA10_Triangle.svg) ![](img/AFIRMA10_Sawtooth.svg) ![](img/AFIRMA10_Sine.svg) ![](img/AFIRMA10_Chirp.svg) ![](img/AFIRMA10_White.svg) ![](img/AFIRMA10_Gauss.svg) ![](img/AFIRMA10_B.svg) ![](img/AFIRMA10_HF.svg) ![](img/AFIRMA10_ImpulseHF.svg) ![](img/AFIRMA10_SawtoothHF.svg) ![](img/AFIRMA10_SineG.svg) ![](img/AFIRMA10_ChirpG.svg) ![](img/AFIRMA10_Complex.svg) ![](img/AFIRMA10_Market.svg) +![](img/AFIRMA6_Spike.svg) ![](img/AFIRMA6_Impulse.svg) ![](img/AFIRMA6_Triangle.svg) ![](img/AFIRMA6_Sawtooth.svg) ![](img/AFIRMA6_Sine.svg) ![](img/AFIRMA6_Chirp.svg) ![](img/AFIRMA6_White.svg) ![](img/AFIRMA6_Gauss.svg) ![](img/AFIRMA6_B.svg) ![](img/AFIRMA6_HF.svg) ![](img/AFIRMA6_ImpulseHF.svg) ![](img/AFIRMA6_SawtoothHF.svg) ![](img/AFIRMA6_SineG.svg) ![](img/AFIRMA6_ChirpG.svg) ![](img/AFIRMA6_Complex.svg) ![](img/AFIRMA6_Market.svg) diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_B.svg b/docs/indicators/averages/afirma/img/AFIRMA6_B.svg new file mode 100644 index 00000000..43dcf35a --- /dev/null +++ b/docs/indicators/averages/afirma/img/AFIRMA6_B.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + B - AFIRMA(6, 6, BlackmanHarris) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Chirp.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg similarity index 78% rename from docs/indicators/averages/afirma/img/AFIRMA10_Chirp.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg index 1c8e44c7..b1826d0d 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Chirp.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Chirp.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -324,7 +324,7 @@ - - Chirp - AFIRMA(10, 0.5) + + Chirp - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_ChirpG.svg b/docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_ChirpG.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg index 62dd210d..2c61faa3 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_ChirpG.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_ChirpG.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -342,7 +342,7 @@ - - ChirpG - AFIRMA(10, 0.5) + + ChirpG - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Complex.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_Complex.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg index ed8b1c42..4a1b92bc 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Complex.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Complex.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -327,7 +327,7 @@ - - Complex - AFIRMA(10, 0.5) + + Complex - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg new file mode 100644 index 00000000..6e6747fb --- /dev/null +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Gauss.svg @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + + + + + + + + + + + + + + + + + + + + + Gauss - AFIRMA(6, 6, BlackmanHarris) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_HF.svg b/docs/indicators/averages/afirma/img/AFIRMA6_HF.svg new file mode 100644 index 00000000..ec93b5b8 --- /dev/null +++ b/docs/indicators/averages/afirma/img/AFIRMA6_HF.svg @@ -0,0 +1,330 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + HF - AFIRMA(6, 6, BlackmanHarris) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Impulse.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg similarity index 89% rename from docs/indicators/averages/afirma/img/AFIRMA10_Impulse.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg index 45ddbb94..878244c4 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Impulse.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Impulse.svg @@ -3,10 +3,10 @@ - + - + @@ -81,26 +81,26 @@ - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -125,15 +125,15 @@ - - - - - - - - - + + + + + + + + + @@ -332,7 +332,7 @@ - - Impulse - AFIRMA(10, 0.5) + + Impulse - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg b/docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg new file mode 100644 index 00000000..bff64afa --- /dev/null +++ b/docs/indicators/averages/afirma/img/AFIRMA6_ImpulseHF.svg @@ -0,0 +1,320 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 0.5 + + + + 1 + + + + + + + + + + + + + + + + + + + + + ImpulseHF - AFIRMA(6, 6, BlackmanHarris) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_Market.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Market.svg new file mode 100644 index 00000000..6f006235 --- /dev/null +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Market.svg @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 64 + + + + 66 + + + + 68 + + + + 70 + + + + 72 + + + + 74 + + + + 76 + + + + 78 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Market - AFIRMA(6, 6, BlackmanHarris) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Sawtooth.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg similarity index 84% rename from docs/indicators/averages/afirma/img/AFIRMA10_Sawtooth.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg index ec5cadb8..a4d68182 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Sawtooth.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Sawtooth.svg @@ -3,10 +3,10 @@ - + - + @@ -81,61 +81,61 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -349,7 +349,7 @@ - - Sawtooth - AFIRMA(10, 0.5) + + Sawtooth - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_SawtoothHF.svg b/docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_SawtoothHF.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg index 392508d4..7cdb3f2b 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_SawtoothHF.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_SawtoothHF.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -326,7 +326,7 @@ - - SawtoothHF - AFIRMA(10, 0.5) + + SawtoothHF - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Sine.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_Sine.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg index 5d391a00..c08c7024 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Sine.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Sine.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -324,7 +324,7 @@ - - Sine - AFIRMA(10, 0.5) + + Sine - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_SineG.svg b/docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_SineG.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg index 4f8b6d2b..d731a839 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_SineG.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_SineG.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -340,7 +340,7 @@ - - SineG - AFIRMA(10, 0.5) + + SineG - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Spike.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg similarity index 89% rename from docs/indicators/averages/afirma/img/AFIRMA10_Spike.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg index ef3d9095..004c96d0 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Spike.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Spike.svg @@ -3,10 +3,10 @@ - + - + @@ -81,26 +81,26 @@ - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -125,16 +125,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -332,7 +332,7 @@ - - Spike - AFIRMA(10, 0.5) + + Spike - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Triangle.svg b/docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg similarity index 80% rename from docs/indicators/averages/afirma/img/AFIRMA10_Triangle.svg rename to docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg index f4fc099c..e675197d 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Triangle.svg +++ b/docs/indicators/averages/afirma/img/AFIRMA6_Triangle.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -349,7 +349,7 @@ - - Triangle - AFIRMA(10, 0.5) + + Triangle - AFIRMA(6, 6, BlackmanHarris) diff --git a/docs/indicators/averages/afirma/img/AFIRMA6_White.svg b/docs/indicators/averages/afirma/img/AFIRMA6_White.svg new file mode 100644 index 00000000..b649a062 --- /dev/null +++ b/docs/indicators/averages/afirma/img/AFIRMA6_White.svg @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -0.4 + + + + -0.2 + + + + 0 + + + + 0.2 + + + + 0.4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + White - AFIRMA(6, 6, BlackmanHarris) + + diff --git a/docs/indicators/averages/alma/analysis.md b/docs/indicators/averages/alma/analysis.md new file mode 100644 index 00000000..87bf847d --- /dev/null +++ b/docs/indicators/averages/alma/analysis.md @@ -0,0 +1,51 @@ +# ALMA: Benchmark Analysis + +This analysis evaluates the Arnaud Legoux Moving Average (ALMA) across four core benchmarks: accuracy, timeliness, overshooting, and smoothness. These benchmarks provide a comprehensive view of ALMA's performance characteristics and serve as a basis for comparison with other moving averages. + +## Accuracy (closeness to the original data) + +ALMA generally exhibits good accuracy in representing the original price data due to its Gaussian distribution-based weighting system. + +- **Strengths**: + - The Gaussian distribution weighting helps to reduce noise while preserving important price trends. + - The offset parameter allows for fine-tuning of the balance between recent and historical data representation. + +- **Considerations**: + - Accuracy can vary based on parameter settings. Incorrect parameter selection might lead to over-smoothing or under-smoothing, potentially reducing accuracy. + - In highly volatile markets, ALMA may sacrifice some accuracy for smoothness, especially if the sigma parameter is set to prioritize noise reduction. + +## Timeliness (amount of lag) + +ALMA is designed to minimize lag, which is one of its key advantages over traditional moving averages. + +- **Strengths**: + - The offset parameter allows ALMA to be more responsive to recent price changes, potentially reducing lag. + - The ability to adjust the window size provides flexibility in balancing timeliness and stability. + +- **Considerations**: + - While ALMA generally has less lag than traditional MAs, it's not entirely lag-free. Some minimal lag may still be present, especially with larger window sizes. + - The amount of lag can be influenced by parameter settings. Optimizing for minimal lag might come at the cost of increased noise sensitivity. + +## Overshooting (overcompensation during reversals) + +ALMA's design helps to mitigate overshooting during price reversals, but the extent can vary based on settings and market conditions. + +- **Strengths**: + - The Gaussian distribution weighting helps to dampen extreme price movements, reducing the likelihood of significant overshooting. + - The sigma parameter allows for control over the smoothness of transitions, potentially minimizing overshoot. + +- **Considerations**: + - Overshooting can still occur, especially in markets with sudden, sharp reversals. + - The degree of overshooting can be influenced by parameter settings. More aggressive settings (lower sigma, higher offset) might increase responsiveness but also the risk of overshooting. + +## Smoothness (continuous 2nd derivative, less jagged flow) + +ALMA generally produces a smoother line than many traditional moving averages, which is one of its defining characteristics. + +- **Strengths**: + - The Gaussian distribution weighting effectively smooths out minor price fluctuations and noise. + - The sigma parameter provides direct control over the smoothness of the line. + - The resulting smooth line can make trend identification easier. + +- **Considerations**: + - The degree of smoothness can be adjusted through parameter settings. \ No newline at end of file diff --git a/docs/indicators/averages/alma/calc.md b/docs/indicators/averages/alma/calc.md new file mode 100644 index 00000000..7c9bc48b --- /dev/null +++ b/docs/indicators/averages/alma/calc.md @@ -0,0 +1,45 @@ +# The Math Behind ALMA + +## Components of ALMA + +ALMA is a single-formula moving average that incorporates elements of several advanced techniques: + +- Gaussian distribution +- Weighted moving average +- Offset parameter + +### ALMA Formula + +$ ALMA_t = \sum_{i=0}^{n-1} w_i \cdot P_{t-i} $ + +Where: +- $ALMA_t$ is the ALMA value at time $t$ +- $n$ is the window size (number of periods) +- $P_{t-i}$ is the price at time $t-i$ +- $w_i$ are the weights + +### Weight Calculation + +The weights $w_i$ are calculated using a Gaussian distribution function with an offset: + +$ w_i = \exp\left(-\frac{(i - m)^2}{2s^2}\right) $ + +Where: +- $i$ is the position of the price in the window (0 to $n-1$) +- $m$ is the offset of the Gaussian distribution, calculated as $m = \text{floor}(offset \cdot (n - 1))$ +- $s$ is the standard deviation of the Gaussian distribution, calculated as $s = \frac{n}{sigma}$ + +### Parameter Definitions + +ALMA uses three main parameters: + +- **Window size** ($n$): Affects the overall reactivity of the indicator. +- **Offset**: Influences the lag of the moving average. Lower values reduce lag but may increase noise. +- **Sigma**: Controls the smoothness of the indicator. Higher values increase smoothness but may increase lag. + +### Computational Process + +For each new data point: +- Calculate the weights for the entire window. +- Apply these weights to the most recent $n$ prices. +- Sum the weighted prices to produce the final ALMA value. diff --git a/docs/indicators/averages/dema/analysis.md b/docs/indicators/averages/dema/analysis.md new file mode 100644 index 00000000..ee4ada70 --- /dev/null +++ b/docs/indicators/averages/dema/analysis.md @@ -0,0 +1,65 @@ +# DEMA: Benchmark Analysis + +This analysis evaluates the Double Exponential Moving Average (DEMA) across four core benchmarks: accuracy, timeliness, overshooting, and smoothness. + +## Accuracy (closeness to the original data) + +DEMA generally provides a good balance between accuracy and smoothing. + +- **Strengths**: + - The double smoothing process helps to reduce noise while preserving important price trends. + - More accurate than a simple EMA, especially during trend changes. + +- **Considerations**: + - In highly volatile markets, DEMA may sacrifice some accuracy for smoothness. + - Accuracy can vary based on the period setting. Shorter periods increase accuracy but may introduce more noise. + +## Timeliness (amount of lag) + +DEMA is designed to reduce lag compared to traditional moving averages, which is one of its key advantages. + +- **Strengths**: + - The double smoothing formula effectively reduces lag compared to standard EMAs. + - Responds more quickly to price changes than simple or exponential moving averages. + +- **Considerations**: + - While DEMA has less lag than traditional MAs, it's not entirely lag-free. + - Shorter periods reduce lag but may increase sensitivity to noise. + +## Overshooting (overcompensation during reversals) + +DEMA is known for significant overshooting during price reversals, which is one of its main drawbacks. + +- **Weaknesses**: + - Prone to substantial overshooting, especially during sharp price reversals. + - The double exponential smoothing, while reducing lag, can exaggerate price movements during trend changes. + +- **Considerations**: + - Overshooting is particularly pronounced in volatile markets or during sudden trend reversals. + - Shorter periods may further increase the risk and magnitude of overshooting. + - This characteristic can lead to false signals or exaggerated price projections, potentially misleading traders. + +## Smoothness (continuous 2nd derivative, less jagged flow) + +DEMA produces a relatively smooth line, balancing smoothness with responsiveness. + +- **Strengths**: + - Smoother than a standard EMA, making trend identification easier. + - The double smoothing process effectively reduces minor fluctuations. + +- **Considerations**: + - Less smooth than higher-order moving averages or those with explicit smoothing parameters. + - The degree of smoothness is primarily controlled by the period setting, offering less flexibility than some advanced moving averages. + +## Conclusion + +DEMA demonstrates mixed performance across the four benchmarks. It excels in reducing lag and maintains a good degree of smoothness, but its tendency to overshoot significantly during price reversals is a major drawback. + +DEMA's performance is influenced by its single parameter (the period). While this simplicity is an advantage for ease of use, it also means there's less flexibility to mitigate its overshooting tendency. + +Compared to more complex moving averages like AFIRMA or ALMA, DEMA offers simplicity and excellent lag reduction. However, its proneness to overshooting can make it less reliable during volatile market conditions or during trend reversals. + +Traders and analysts should carefully consider DEMA's strengths and weaknesses. While it offers improved lag reduction over simple moving averages, its overshooting characteristic can lead to false signals. This makes it potentially risky to use on its own, especially in volatile markets. +DEMA might be most effectively used in conjunction with other indicators that can help confirm signals and mitigate the risk of false readings due to overshooting. It may be particularly useful in strongly trending markets where its lag reduction is beneficial and the risk of reversal (and thus overshooting) is lower. + +In summary, DEMA's simplicity and lag reduction make it an interesting tool, but its tendency to overshoot means it should be used with caution and preferably as part of a broader analytical approach rather than as a standalone indicator. \ No newline at end of file diff --git a/docs/indicators/averages/dema/calc.md b/docs/indicators/averages/dema/calc.md new file mode 100644 index 00000000..bf9035dc --- /dev/null +++ b/docs/indicators/averages/dema/calc.md @@ -0,0 +1,48 @@ +# The Math Behind DEMA + +## Components of DEMA + +DEMA is composed of two main components: + +1. Exponential Moving Average (EMA) +2. A "double smoothing" factor + +Let's break these down: + +### EMA Calculation + +The Exponential Moving Average (EMA) is calculated as: + +$ EMA_t = \alpha \cdot P_t + (1 - \alpha) \cdot EMA_{t-1} $ + +Where: +- $EMA_t$ is the EMA value at time $t$ +- $P_t$ is the price at time $t$ +- $\alpha$ is the smoothing factor, calculated as $\frac{2}{n+1}$ +- $n$ is the number of periods + +### DEMA Formula + +The DEMA is then calculated using the following formula: + +$ DEMA_t = 2 \cdot EMA_t - EMA(EMA_t) $ + +Where: +- $DEMA_t$ is the DEMA value at time $t$ +- $EMA_t$ is the EMA of the price +- $EMA(EMA_t)$ is the EMA of the EMA + +## Calculation Process + +1. Calculate the EMA of the price series. +2. Calculate another EMA on the result of step 1. +3. Multiply the first EMA by 2. +4. Subtract the second EMA from the result of step 3. + +This process effectively reduces lag while maintaining smoothness. + +## Parameter + +DEMA uses a single parameter: + +- **Period** ($n$): Determines the number of periods used in the EMA calculations. This affects the overall reactivity and smoothness of the indicator. diff --git a/docs/indicators/averages/dsma/analysis.md b/docs/indicators/averages/dsma/analysis.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/dsma/calc.md b/docs/indicators/averages/dsma/calc.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/dwma/analysis.md b/docs/indicators/averages/dwma/analysis.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/dwma/calc.md b/docs/indicators/averages/dwma/calc.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/ema/analysis.md b/docs/indicators/averages/ema/analysis.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/ema/calc.md b/docs/indicators/averages/ema/calc.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/sma/calc.md b/docs/indicators/averages/sma/calc.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/tema/analysis.md b/docs/indicators/averages/tema/analysis.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/indicators/averages/tema/calc.md b/docs/indicators/averages/tema/calc.md new file mode 100644 index 00000000..631b5647 --- /dev/null +++ b/docs/indicators/averages/tema/calc.md @@ -0,0 +1,52 @@ +# The Math Behind TEMA + +## Components of TEMA + +TEMA is composed of three main components: + +1. Exponential Moving Average (EMA) +2. A "triple smoothing" factor + +Let's break these down: + +### EMA Calculation + +The Exponential Moving Average (EMA) is calculated as: + +$ EMA_t = \alpha \cdot P_t + (1 - \alpha) \cdot EMA_{t-1} $ + +Where: +- $EMA_t$ is the EMA value at time $t$ +- $P_t$ is the price at time $t$ +- $\alpha$ is the smoothing factor, calculated as $\frac{2}{n+1}$ +- $n$ is the number of periods + +### TEMA Formula + +The TEMA is then calculated using the following formula: + +$ TEMA_t = 3 \cdot EMA_t - 3 \cdot EMA(EMA_t) + EMA(EMA(EMA_t)) $ + +Where: +- $TEMA_t$ is the TEMA value at time $t$ +- $EMA_t$ is the EMA of the price +- $EMA(EMA_t)$ is the EMA of the EMA +- $EMA(EMA(EMA_t))$ is the EMA of the EMA of the EMA + +## Calculation Process + +1. Calculate the EMA of the price series (EMA1). +2. Calculate another EMA on the result of step 1 (EMA2). +3. Calculate a third EMA on the result of step 2 (EMA3). +4. Multiply EMA1 by 3. +5. Multiply EMA2 by 3. +6. Subtract EMA2 * 3 from EMA1 * 3. +7. Add EMA3 to the result. + +This process effectively reduces lag while maintaining smoothness and attempting to minimize overshooting. + +## Parameter + +TEMA uses a single parameter: + +- **Period** ($n$): Determines the number of periods used in the EMA calculations. This affects the overall reactivity and smoothness of the indicator. \ No newline at end of file diff --git a/docs/indicators/averages/tema/charts.dib b/docs/indicators/averages/tema/charts.dib new file mode 100644 index 00000000..956337cb --- /dev/null +++ b/docs/indicators/averages/tema/charts.dib @@ -0,0 +1,60 @@ +#!meta + +{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"name":"csharp"}]}} + +#!csharp + +#r "..\..\..\..\lib\obj\Debug\QuanTAlib.dll" + +#r "nuget: ScottPlot" + +using QuanTAlib; +using ScottPlot; +using Microsoft.DotNet.Interactive.Formatting; + +QuanTAlib.Formatters.Initialize(); +Formatter.Register(typeof(ScottPlot.Plot), (p, w) => + w.Write(((ScottPlot.Plot)p).GetSvgXml(600, 300)), HtmlFormatter.MimeType); + +#!csharp + +Dictionary Data = new Dictionary +{ + { "Spike", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,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,0,0,0,0,0,0,0,1,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,0,0,0,0,0,0 } }, + { "Impulse", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,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,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 } }, + { "Triangle", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2 } }, + { "Sawtooth", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,33,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,0,0,0,0,0 } }, + { "Sine", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.39,0.56,0.72,0.84,0.93,0.99,1,0.97,0.91,0.81,0.68,0.52,0.33,0.14,-0.06,-0.26,-0.44,-0.61,-0.76,-0.87,-0.95,-0.99,-1,-0.96,-0.88,-0.77,-0.63,-0.46,-0.28,-0.08,0.12,0.31,0.49,0.66,0.79,0.9,0.97,1,0.99,0.94,0.85,0.73,0.58,0.41,0.22,0.02,-0.17,-0.37,-0.54,-0.7,-0.83,-0.92,-0.98,-1,-0.98,-0.92,-0.82,-0.69,-0.54,-0.36,-0.17,0.03,0.23,0.42,0.59,0.74 } }, + { "Chirp", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0.93,0.27,-0.59,-1,-0.71,0.05,0.75,1,0.67,0,-0.67,-0.99,-0.85,-0.34,0.31,0.81,1,0.82,0.35,-0.22,-0.71,-0.98,-0.95,-0.66,-0.2,0.31,0.72,0.96,0.98,0.78,0.43,-0.01,-0.43,-0.77,-0.96,-0.99,-0.85,-0.58,-0.23,0.16,0.51,0.79,0.95,1,0.92,0.73,0.47,0.15,-0.17,-0.47,-0.72,-0.9,-0.99,-0.99,-0.9,-0.74,-0.52,-0.26,0.01,0.28,0.53,0.73,0.88,0.97,1,0.97 } }, + { "White", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0.03,-0.4,-0.47,0.19,-0.4,-0.23,0.31,0.41,0.19,0.16,-0.5,-0.31,-0.21,0.25,0.18,-0.48,-0.1,0.38,0.29,-0.38,-0.08,-0.21,0.34,0.01,-0.46,0.28,-0.48,0.11,0.02,-0.37,0.19,-0.2,0.1,0.24,0.08,-0.22,-0.12,0.15,0.36,-0.43,-0.03,-0.32,0.45,-0.5,-0.04,-0.04,-0.08,-0.18,0.13,-0.33,-0.19,0.36,-0.39,0.2,-0.31,0.28,-0.13,-0.07,-0.29,0.37,0.03,-0.25,-0.06,-0.3,-0.08,-0.09 } }, + { "Gauss", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,0,0.03,0.11,-0.1,-0.43,-0.08,0.36,-0.04,-0.04,-0.21,-0.3,0.26,0.2,0.28,0.2,0.27,-0.01,-0.1,-0.23,-0.13,-0.41,-0.23,-0.07,-0.21,0.32,-0.18,-0.48,0.3,0.46,-0.2,0.52,-0.81,-0.25,-0.21,-0.12,-0.18,0.18,0.52,0.29,0.44,0.18,-1.2,0.38,0.24,0.06,0.28,0.34,0.3,-0.13,0.19,-0.5,0.59,-0.36,0.22,-0.23,0.24,0.39,0.13,-0.33,-0.57,-0.23,0.49,-0.13,0.76,0.59,0.61 } }, + { "B", new double[] { -0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0.4,-0.4,0,-0.28,0.41,-0.54,0.65,-0.75,0.84,-0.91,0.96,-0.99,1,-0.99,0.96,-0.92,0.85,-0.77,0.67,-0.56,0.44,-0.3,0.17,-0.03,-0.11,0.25,-0.39,0.51,-0.63,0.73,-0.82,0.89,-0.95,0.98,-1,0.99,-0.97,0.93,-0.86,0.78,-0.69,0.58,-0.46,0.33,-0.19,0.05,0.09,-0.23,0.36,-0.49,0.61,-0.71,0.81,-0.88,0.94,-0.98,1,-1,0.98,-0.94,0.88,-0.8,0.71,-0.6,0.48,-0.35,0.22,-0.08,-0.06 } }, + { "HF", new double[] { -0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,-0.6,0.6,0,0.14,-0.76,-0.96,-0.28,0.66,0.99,0.41,-0.54,-1,-0.54,0.42,0.99,0.65,-0.29,-0.96,-0.75,0.15,0.91,0.84,-0.01,-0.85,-0.91,-0.13,0.76,0.96,0.27,-0.66,-0.99,-0.4,0.55,1,0.53,-0.43,-0.99,-0.64,0.3,0.96,0.75,-0.16,-0.92,-0.83,0.02,0.85,0.9,0.12,-0.77,-0.95,-0.26,0.67,0.99,0.4,-0.56,-1,-0.52,0.44,0.99,0.64,-0.3,-0.97,-0.74,0.17,0.92,0.83,-0.03,-0.86 } }, + { "ImpulseHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.05,-0.25,-0.32,-0.09,0.22,0.33,0.14,-0.18,-0.33,-0.18,0.14,0.33,0.22,-0.1,-0.32,-0.25,0.05,0.3,0.28,0,-0.28,-0.3,-0.04,0.25,0.32,0.09,-0.22,-0.33,-0.13,0.18,0.33,0.18,0.86,0.67,0.79,1.1,1.32,1.25,0.95,0.69,0.72,1.01,1.28,1.3,1.04,0.74,0.68,0.91,1.22,1.33,1.13,0.81,0.67,0.83,1.15,1.33,1.21,0.9,0.68,0.75,1.06,1.31,1.28,0.99,0.71 } }, + { "SawtoothHF", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,2.7,-0.8,-0.8,3.6,9.3,11.95,10.05,6.3,5,8.3,14.1,17.95,17.25,13.55,11.2,13.25,18.75,23.55,24.2,20.95,17.75,18.45,23.35,28.8,30.8,28.35,24.7,24.05,28,33.75,37,35.65,31.85,28.05,-3.2,1.5,4.8,3.75,-0.8,-4.6,-4.15,0.1,4.25,4.5,0.6,-3.85,-4.75,-1.3,3.35,4.95,2,-2.8,-5,-2.6,2.2,4.95,3.2,-1.5,-4.85,-3.7,0.85,4.6,4.15,-0.15,-4.3} }, + { "SineG", new double[] { -0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0.2,-0.2,0,0,0.59,0.83,0.74,0.5,0.91,1.36,0.93,0.87,0.6,0.38,0.78,0.53,0.42,0.14,0.01,-0.45,-0.71,-0.99,-1,-1.36,-1.22,-1.07,-1.17,-0.56,-0.95,-1.11,-0.16,0.18,-0.28,0.64,-0.5,0.24,0.45,0.67,0.72,1.15,1.52,1.28,1.38,1.03,-0.47,0.96,0.65,0.28,0.3,0.17,-0.07,-0.67,-0.51,-1.33,-0.33,-1.34,-0.78,-1.21,-0.68,-0.43,-0.56,-0.87,-0.93,-0.4,0.52,0.1,1.18,1.18,1.35} }, + { "ChirpG", new double[] { 0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,0,0.01,1.3,0.3,-0.48,-1.1,-1.14,-0.03,1.11,0.96,0.63,-0.21,-0.97,-0.73,-0.65,-0.06,0.51,1.08,0.99,0.72,0.12,-0.35,-1.12,-1.21,-1.02,-0.87,0.12,0.13,0.24,1.26,1.44,0.58,0.95,-0.82,-0.68,-0.98,-1.08,-1.17,-0.67,-0.06,0.06,0.6,0.69,-0.41,1.33,1.24,0.98,1.01,0.81,0.45,-0.3,-0.28,-1.22,-0.31,-1.35,-0.77,-1.13,-0.5,-0.13,-0.13,-0.32,-0.29,0.3,1.22,0.75,1.73,1.59,1.58} }, + { "Complex", new double[] { 175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.1,175.6,175.44,176.27,176.04,176.99,175.49,175.68,174.34,176.4,174.05,174.4,174.2,176.16,175,177.72,174.33,176.96,174.62,174.76,170.9,171.12,171.05,170.01,169.24,172.64,171.96,175.72,174.16,175.81,177.3,178.38,176.75,177.19,175.55,178.49,176.52,178.45,178.04,178.25,177.8,176.97,172.94,174.92,173.98,172.29,171.19,172.54,172.11,175.32,175.63,176.65,173.8,176.04,172.74,175.24,171.84,171.54,172.17,171.85,172.38,170.78,173.49,173.69,171.71,174.38,173.99,174.83} }, + { "Market", new double[] { 68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,68.75,68.25,67.75,67.75,72.75,74.75,72.25,71.25,71.75,72.75,77.75,76,76,76,74.75,75.5,74.75,73.75,74,74.75,72.25,72.5,72.25,74.5,74.75,75.75,75.75,75.75,74.25,73.75,74.75,72,71.75,72.5,72.25,71,72,71.75,71.75,73.25,72.5,73.75,74,76.75,75.75,75,75.75,74.5,74.25,73.5,71.75,70.5,69,70.5,70,68.75,67.25,68.5,70.75,70,70.5,68.25,68.25,68.25,63.75,64.25} } + +}; + +#!csharp + +String Name = "TEMA"; +int p = 10; +Func Indicator = period => new Tema(period); + +foreach (var item in Data) { + string Signal = item.Key; + double[] Input = item.Value; + TSeries Output = new(); + var ma = Indicator(p); + foreach (var value in Input) { Output.Add(ma.Calc(value)); } + Plot plt = new(); + var p1a = plt.Add.Signal(Input[24..]); p1a.Color = ScottPlot.Colors.Red; p1a.LineWidth = 2; + var p1b = plt.Add.Signal(Output.v.ToArray()[24..]); p1b.Color = ScottPlot.Colors.Blue; p1b.LineWidth = 4; + plt.Title($"{Signal} - {Name}({p})"); + plt.Display(); + plt.SaveSvg($"img/{Name}{p}_{Signal}.svg", 450, 300); +} diff --git a/docs/indicators/averages/tema/charts.md b/docs/indicators/averages/tema/charts.md new file mode 100644 index 00000000..a7309bfd --- /dev/null +++ b/docs/indicators/averages/tema/charts.md @@ -0,0 +1,3 @@ +# TEMA Charts + +![](img/TEMA10_Spike.svg) ![](img/TEMA10_Impulse.svg) ![](img/TEMA10_Triangle.svg) ![](img/TEMA10_Sawtooth.svg) ![](img/TEMA10_Sine.svg) ![](img/TEMA10_Chirp.svg) ![](img/TEMA10_White.svg) ![](img/TEMA10_Gauss.svg) ![](img/TEMA10_B.svg) ![](img/TEMA10_HF.svg) ![](img/TEMA10_ImpulseHF.svg) ![](img/TEMA10_SawtoothHF.svg) ![](img/TEMA10_SineG.svg) ![](img/TEMA10_ChirpG.svg) ![](img/TEMA10_Complex.svg) ![](img/TEMA10_Market.svg) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_B.svg b/docs/indicators/averages/tema/img/TEMA10_B.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_B.svg rename to docs/indicators/averages/tema/img/TEMA10_B.svg index 08fbe8bf..e0b2fac7 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_B.svg +++ b/docs/indicators/averages/tema/img/TEMA10_B.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -324,7 +324,7 @@ - - B - AFIRMA(10, 0.5) + + B - TEMA(10) diff --git a/docs/indicators/averages/tema/img/TEMA10_Chirp.svg b/docs/indicators/averages/tema/img/TEMA10_Chirp.svg new file mode 100644 index 00000000..88cd9d6e --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Chirp.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + Chirp - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_ChirpG.svg b/docs/indicators/averages/tema/img/TEMA10_ChirpG.svg new file mode 100644 index 00000000..0cb96318 --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_ChirpG.svg @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1.5 + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + 1 + + + + 1.5 + + + + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ChirpG - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_Complex.svg b/docs/indicators/averages/tema/img/TEMA10_Complex.svg new file mode 100644 index 00000000..fa50d5dd --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Complex.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 170 + + + + 172 + + + + 174 + + + + 176 + + + + 178 + + + + + + + + + + + + + + + + + + + + + + + + + + + Complex - TEMA(10) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Gauss.svg b/docs/indicators/averages/tema/img/TEMA10_Gauss.svg similarity index 79% rename from docs/indicators/averages/afirma/img/AFIRMA10_Gauss.svg rename to docs/indicators/averages/tema/img/TEMA10_Gauss.svg index 98190bd9..f56510ae 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Gauss.svg +++ b/docs/indicators/averages/tema/img/TEMA10_Gauss.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -321,7 +321,7 @@ - - Gauss - AFIRMA(10, 0.5) + + Gauss - TEMA(10) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_HF.svg b/docs/indicators/averages/tema/img/TEMA10_HF.svg similarity index 78% rename from docs/indicators/averages/afirma/img/AFIRMA10_HF.svg rename to docs/indicators/averages/tema/img/TEMA10_HF.svg index c2259c57..6227f0fc 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_HF.svg +++ b/docs/indicators/averages/tema/img/TEMA10_HF.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -324,7 +324,7 @@ - - HF - AFIRMA(10, 0.5) + + HF - TEMA(10) diff --git a/docs/indicators/averages/tema/img/TEMA10_Impulse.svg b/docs/indicators/averages/tema/img/TEMA10_Impulse.svg new file mode 100644 index 00000000..e4d9cf92 --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Impulse.svg @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 0.2 + + + + 0.4 + + + + 0.6 + + + + 0.8 + + + + 1 + + + + 1.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Impulse - TEMA(10) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_ImpulseHF.svg b/docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg similarity index 78% rename from docs/indicators/averages/afirma/img/AFIRMA10_ImpulseHF.svg rename to docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg index 4a5c8479..90c19c1d 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_ImpulseHF.svg +++ b/docs/indicators/averages/tema/img/TEMA10_ImpulseHF.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -314,7 +314,7 @@ - - ImpulseHF - AFIRMA(10, 0.5) + + ImpulseHF - TEMA(10) diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_Market.svg b/docs/indicators/averages/tema/img/TEMA10_Market.svg similarity index 80% rename from docs/indicators/averages/afirma/img/AFIRMA10_Market.svg rename to docs/indicators/averages/tema/img/TEMA10_Market.svg index cf860443..f3b8bef4 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_Market.svg +++ b/docs/indicators/averages/tema/img/TEMA10_Market.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -351,7 +351,7 @@ - - Market - AFIRMA(10, 0.5) + + Market - TEMA(10) diff --git a/docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg b/docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg new file mode 100644 index 00000000..4481c708 --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Sawtooth.svg @@ -0,0 +1,364 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -5 + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sawtooth - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg b/docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg new file mode 100644 index 00000000..9a6da825 --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_SawtoothHF.svg @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -10 + + + + 0 + + + + 10 + + + + 20 + + + + 30 + + + + 40 + + + + + + + + + + + + + + + + + + + + + + + + + SawtoothHF - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_Sine.svg b/docs/indicators/averages/tema/img/TEMA10_Sine.svg new file mode 100644 index 00000000..9c3950fa --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Sine.svg @@ -0,0 +1,334 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + Sine - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_SineG.svg b/docs/indicators/averages/tema/img/TEMA10_SineG.svg new file mode 100644 index 00000000..ac43a37a --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_SineG.svg @@ -0,0 +1,347 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1.5 + + + + -1 + + + + -0.5 + + + + 0 + + + + 0.5 + + + + 1 + + + + 1.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SineG - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_Spike.svg b/docs/indicators/averages/tema/img/TEMA10_Spike.svg new file mode 100644 index 00000000..de7a15bf --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Spike.svg @@ -0,0 +1,339 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 0.2 + + + + 0.4 + + + + 0.6 + + + + 0.8 + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + Spike - TEMA(10) + + diff --git a/docs/indicators/averages/tema/img/TEMA10_Triangle.svg b/docs/indicators/averages/tema/img/TEMA10_Triangle.svg new file mode 100644 index 00000000..1a6e063e --- /dev/null +++ b/docs/indicators/averages/tema/img/TEMA10_Triangle.svg @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + 40 + + + + 45 + + + + 50 + + + + 55 + + + + 60 + + + + 65 + + + + 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + 5 + + + + 10 + + + + 15 + + + + 20 + + + + 25 + + + + 30 + + + + 35 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Triangle - TEMA(10) + + diff --git a/docs/indicators/averages/afirma/img/AFIRMA10_White.svg b/docs/indicators/averages/tema/img/TEMA10_White.svg similarity index 80% rename from docs/indicators/averages/afirma/img/AFIRMA10_White.svg rename to docs/indicators/averages/tema/img/TEMA10_White.svg index d23c6dd3..69601237 100644 --- a/docs/indicators/averages/afirma/img/AFIRMA10_White.svg +++ b/docs/indicators/averages/tema/img/TEMA10_White.svg @@ -3,10 +3,10 @@ - + - + @@ -81,83 +81,83 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -329,7 +329,7 @@ - - White - AFIRMA(10, 0.5) + + White - TEMA(10) diff --git a/docs/readme.md b/docs/readme.md index 6364377f..32247e64 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,7 +1,3 @@ -# QuanTAlib - quantitative technical indicators for Quantower - -### (and other C#-based trading platorms) - [![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=mihakralj_QuanTAlib&metric=ncloc)](https://sonarcloud.io/summary/overall?id=mihakralj_QuanTAlib) [![Codacy grade](https://img.shields.io/codacy/grade/b1f9109222234c87bce45f1fd4c63aee?style=flat-square)](https://app.codacy.com/gh/mihakralj/QuanTAlib/dashboard) [![codecov](https://codecov.io/gh/mihakralj/QuanTAlib/branch/main/graph/badge.svg?style=flat-square&token=YNMJRGKMTJ?style=flat-square)](https://codecov.io/gh/mihakralj/QuanTAlib) @@ -14,14 +10,24 @@ [![GitHub watchers](https://img.shields.io/github/watchers/mihakralj/QuanTAlib?style=flat-square)](https://github.com/mihakralj/QuanTAlib/watchers) [![.NET8.0](https://img.shields.io/badge/.NET-8.0-blue?style=flat-square)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) +![Alt text](./img/quotes.gif) + +# QuanTAlib - quantitative technical indicators for Quantower + **Quan**titative **TA** **lib**rary (QuanTAlib) is a C# library of classess and methods for quantitative technical analysis useful for analyzing quotes with [Quantower](https://www.quantower.com/) and other C#-based trading platforms. -**QuanTAlib** is written with some specific design criteria in mind - why there is '_yet another C# TA library_': +[**Visit documentation pages**](https://mihakralj.github.io/QuanTAlib/#/) -- Prioritize **real-time data analysis**: As new data items arrives, indicators don't have to re-calculate the entire history and can generate a result directly from the last item +**QuanTAlib** is a C# library written with some specific design criteria in mind. Here is why there is '_yet another C# TA library_': + +- QuanTAlib focuses on **[real-time data analysis](essays/realtime.md)**: As new data items arrives, indicators don't have to re-calculate the entire history and can generate a result directly from the last item - **Allow updates/corrections** of the last quote - QuanTAlib is re-calculating the last value as many times as required before continuing to the new bar - **Calculate early data right** - calculated data is as valid as mathematically possible from the first value onwards - no blackout or warming-up periods. All indicators return data from the first bar, alongside with a flag `isHot` - defining if calculation is already stable. +### Coverage + +[List of indicators - implemented and planned](indicators/indicators.md) + ## Installation to Quantower - `` is the directory where Quantower is installed - where `Start.lnk` launcher is @@ -29,14 +35,10 @@ - Copy `Statistics.dll` from Releases to `\Settings\Scripts\Indicators\Statistics\Statistics.dll` - Copy `SyntheticVendor.dll` from Releases to `\Settings\Scripts\Vendors\SyntheticVendor\SyntheticVendor.dll` -![Alt text](./img/quotes.gif) + QuanTAlib is intended for developers and users of Quantower, therefore it does not focus on privind sources of OHLCV quotes. There are some very basic data feeds available to use in the learning process: `GBM_Feed` for Random (Geometric Brownian Motion) data, and `SyntheticVendor` data generator for Quantower. -### Coverage - -[List of indicators - implemented and planned](indicators/indicators.md) - ### Validation QuanTAlib uses validation tests with four other TA libraries to assure accuracy and validity of results: diff --git a/lib/averages/Afirma.cs b/lib/averages/Afirma.cs index e2771a61..2bbb5b35 100644 --- a/lib/averages/Afirma.cs +++ b/lib/averages/Afirma.cs @@ -1,89 +1,162 @@ -namespace QuanTAlib; +using System; -public class Afirma : AbstractBase +namespace QuanTAlib { - private readonly int Period; - private readonly CircularBuffer _buffer; - private readonly double _alpha; // Adaptive factor - private double _lastAfirma, _p_lastAfirma; - private double _lastError, _p_lastError; - public Afirma(int period, double alpha = 0.1) + public class Afirma : AbstractBase { - if (period < 1) + + public enum WindowType { - throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); + Rectangular, + Hanning1, + Hanning2, + Blackman, + BlackmanHarris } - if (alpha <= 0 || alpha >= 1) + + private readonly int Periods; + private readonly int Taps; + private readonly WindowType Window; + private readonly CircularBuffer _buffer; + private readonly double[] _weights; + private readonly double _wsum; + private readonly double[] _armaBuffer; + private readonly int _n; + private readonly double _sx2, _sx3, _sx4, _sx5, _sx6, _den; + + public Afirma(int periods, int taps, WindowType window) { - throw new ArgumentOutOfRangeException(nameof(alpha), "Alpha must be between 0 and 1 (exclusive)."); + if (periods < 1) + { + throw new ArgumentOutOfRangeException(nameof(periods), "Periods must be greater than or equal to 1."); + } + if (taps < 1) + { + throw new ArgumentOutOfRangeException(nameof(taps), "Taps must be greater than or equal to 1."); + } + Periods = periods; + Taps = taps; + Window = window; + WarmupPeriod = taps; + _buffer = new CircularBuffer(taps); + _weights = new double[taps]; + _wsum = CalculateWeights(); + _armaBuffer = new double[taps]; + _n = (Taps - 1) / 2; + + // Calculate least squares coefficients in the constructor + _sx2 = (2 * _n + 1) / 3.0; + _sx3 = _n * (_n + 1) / 2.0; + _sx4 = _sx2 * (3 * _n * _n + 3 * _n - 1) / 5.0; + _sx5 = _sx3 * (2 * _n * _n + 2 * _n - 1) / 3.0; + _sx6 = _sx2 * (3 * Math.Pow(_n, 3) * (_n + 2) - 3 * _n + 1) / 7.0; + _den = _sx6 * _sx4 / _sx5 - _sx5; + + Name = "Afirma"; + Init(); } - Period = period; - WarmupPeriod = period; - _buffer = new CircularBuffer(period); - _alpha = alpha; - Name = "Afirma"; - WarmupPeriod = period; - Init(); + + public Afirma(object source, int periods, int taps, WindowType window) : this(periods, taps, window) + { + var pubEvent = source.GetType().GetEvent("Pub"); + pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); + } + + protected override void ManageState(bool isNew) + { + if (isNew) + { + _lastValidValue = Input.Value; + _index++; + } + } + + protected override double Calculation() + { + ManageState(IsNew); + _buffer.Add(Input.Value, Input.IsNew); + + if (_index >= Taps) + { + double a0 = _buffer[_n]; + double a1 = _buffer[_n] - _buffer[_n + 1]; + double sx2y = 0.0; + double sx3y = 0.0; + + for (int i = 0; i <= _n; i++) + { + sx2y += i * i * _buffer[_n - i]; + sx3y += i * i * i * _buffer[_n - i]; + } + + sx2y = 2.0 * sx2y / _n / (_n + 1); + sx3y = 2.0 * sx3y / _n / (_n + 1); + double p = sx2y - a0 * _sx2 - a1 * _sx3; + double q = sx3y - a0 * _sx3 - a1 * _sx4; + double a2 = (p * _sx6 / _sx5 - q) / _den; + double a3 = (q * _sx4 / _sx5 - p) / _den; + + for (int k = 0; k <= _n; k++) + { + _armaBuffer[_n - k] = a0 + k * a1 + k * k * a2 + k * k * k * a3; + } + } + + double result = 0.0; + for (int k = 0; k < Taps; k++) + { + result += _buffer[k] * _weights[k] / _wsum; + } + + IsHot = _index >= WarmupPeriod; + return result; + } + + private double CalculateWeights() + { + double wsum = 0.0; + double centerTap = (Taps - 1) / 2.0; + for (int k = 0; k < Taps; k++) + { + double windowWeight; + switch (Window) + { + case WindowType.Rectangular: + windowWeight = 1.0; + break; + case WindowType.Hanning1: + windowWeight = 0.50 - 0.50 * Math.Cos(2.0 * Math.PI * k / (Taps - 1)); + break; + case WindowType.Hanning2: + windowWeight = 0.54 - 0.46 * Math.Cos(2.0 * Math.PI * k / (Taps - 1)); + break; + case WindowType.Blackman: + windowWeight = 0.42 - 0.50 * Math.Cos(2.0 * Math.PI * k / (Taps - 1)) + 0.08 * Math.Cos(4.0 * Math.PI * k / (Taps - 1)); + break; + case WindowType.BlackmanHarris: + windowWeight = 0.35875 - 0.48829 * Math.Cos(2.0 * Math.PI * k / (Taps - 1)) + 0.14128 * Math.Cos(4.0 * Math.PI * k / (Taps - 1)) - 0.01168 * Math.Cos(6.0 * Math.PI * k / (Taps - 1)); + break; + default: + windowWeight = 1.0; + break; + } + + double sincWeight; + if (Math.Abs(k - centerTap) < 1e-10) + { + sincWeight = 1.0; + } + else + { + sincWeight = Math.Sin(Math.PI * (k - centerTap) / Periods) / (Math.PI * (k - centerTap) / Periods); + } + + _weights[k] = windowWeight * sincWeight; + wsum += _weights[k]; + } + return wsum; + } + } - - public Afirma(object source, int period, double alpha = 0.1) : this(period: period, alpha: alpha) - { - var pubEvent = source.GetType().GetEvent("Pub"); - pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); - } - - public override void Init() - { - base.Init(); - _lastAfirma = 0; - _lastError = 0; - } - - protected override void ManageState(bool isNew) - { - if (isNew) - { - _lastValidValue = Input.Value; - _index++; - _p_lastAfirma = _lastAfirma; - _p_lastError = _lastError; - } - else - { - _lastAfirma = _p_lastAfirma; - _lastError = _p_lastError; - } - } - - /// - /// Core AFIRMA calculation - /// - protected override double Calculation() - { - double result; - ManageState(IsNew); - _buffer.Add(Input.Value, Input.IsNew); - - if (_index < Period) - { - // Use simple average during warmup period - result = _buffer.Average(); - } - else - { - // AFIRMA calculation - double sma = _buffer.Average(); - double error = Input.Value - _lastAfirma; - double denominator = Math.Abs(error) + Math.Abs(_lastError); - double adaptiveFactor = denominator != 0 ? _alpha * Math.Abs(error) / denominator : _alpha; - result = sma + adaptiveFactor * (Input.Value - sma); - - _lastError = error; - } - - _lastAfirma = result; - IsHot = _index >= WarmupPeriod; - return result; - } -} \ No newline at end of file +} diff --git a/lib/averages/Ama.cs b/lib/averages/Ama.cs new file mode 100644 index 00000000..78beb01e --- /dev/null +++ b/lib/averages/Ama.cs @@ -0,0 +1,89 @@ +namespace QuanTAlib; + +public class Ama : AbstractBase +{ + private readonly int Period; + private readonly CircularBuffer _buffer; + private readonly double _alpha; // Adaptive factor + private double _lastAfirma, _p_lastAfirma; + private double _lastError, _p_lastError; + + public Ama(int period, double alpha = 0.1) + { + if (period < 1) + { + throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1."); + } + if (alpha <= 0 || alpha >= 1) + { + throw new ArgumentOutOfRangeException(nameof(alpha), "Alpha must be between 0 and 1 (exclusive)."); + } + Period = period; + WarmupPeriod = period; + _buffer = new CircularBuffer(period); + _alpha = alpha; + Name = "Afirma"; + WarmupPeriod = period; + Init(); + } + + public Ama(object source, int period, double alpha = 0.1) : this(period: period, alpha: alpha) + { + var pubEvent = source.GetType().GetEvent("Pub"); + pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); + } + + public override void Init() + { + base.Init(); + _lastAfirma = 0; + _lastError = 0; + } + + protected override void ManageState(bool isNew) + { + if (isNew) + { + _lastValidValue = Input.Value; + _index++; + _p_lastAfirma = _lastAfirma; + _p_lastError = _lastError; + } + else + { + _lastAfirma = _p_lastAfirma; + _lastError = _p_lastError; + } + } + + /// + /// Core AFIRMA calculation + /// + protected override double Calculation() + { + double result; + ManageState(IsNew); + _buffer.Add(Input.Value, Input.IsNew); + + if (_index < Period) + { + // Use simple average during warmup period + result = _buffer.Average(); + } + else + { + // AFIRMA calculation + double sma = _buffer.Average(); + double error = Input.Value - _lastAfirma; + double denominator = Math.Abs(error) + Math.Abs(_lastError); + double adaptiveFactor = denominator != 0 ? _alpha * Math.Abs(error) / denominator : _alpha; + result = sma + adaptiveFactor * (Input.Value - sma); + + _lastError = error; + } + + _lastAfirma = result; + IsHot = _index >= WarmupPeriod; + return result; + } +} \ No newline at end of file diff --git a/quantower/Averages/AfirmaIndicator.cs b/quantower/Averages/AfirmaIndicator.cs index b7fb250d..44449832 100644 --- a/quantower/Averages/AfirmaIndicator.cs +++ b/quantower/Averages/AfirmaIndicator.cs @@ -3,23 +3,35 @@ namespace QuanTAlib; public class AfirmaIndicator : IndicatorBase { - [InputParameter("Period", sortIndex: 1, 1, 2000, 1, 0)] - public int Period { get; set; } = 10; + [InputParameter("Taps (number of weights)", sortIndex: 1, 1, 2000, 1, 0)] + public int Taps { get; set; } = 6; + + [InputParameter("Periods for lowpass cutoff", sortIndex: 2, 1, 2000, 1, 0)] + public int Periods { get; set; } = 6; + + + + [InputParameter("Window Type", sortIndex: 3, variants: [ + "Rectangular", Afirma.WindowType.Rectangular, + "Hanning", Afirma.WindowType.Hanning1, + "Hamming", Afirma.WindowType.Hanning2, + "Blackman", Afirma.WindowType.Blackman, + "Blackman-Harris", Afirma.WindowType.BlackmanHarris + ])] + public Afirma.WindowType Window { get; set; } = Afirma.WindowType.Hanning1; - [InputParameter("Alpha", sortIndex: 2, 0.01, 0.99, 0.01, 2)] - public double Alpha { get; set; } = 0.1; private Afirma? ma; protected override AbstractBase QuanTAlib => ma!; - public override string ShortName => $"AFIRMA {Period} : {SourceName}"; + public override string ShortName => $"AFIRMA {Taps}:{Periods}:{Window} : {SourceName}"; public AfirmaIndicator() { - Name = "AFIRMA - Adaptive Filtering Integrated Recursive Moving Average"; - Description = "Adaptive Filtering Integrated Recursive Moving Average"; + Name = "AFIRMA - Adaptive Finite Impulse Response Moving Average"; + Description = "Adaptive Finite Impulse Response Moving Average with ARMA component"; } protected override void InitIndicator() { - ma = new Afirma(period: Period, alpha: Alpha); + ma = new Afirma(periods: Periods, taps: Taps, window: Window); } } \ No newline at end of file diff --git a/quantower/Averages/AmaIndicator.cs b/quantower/Averages/AmaIndicator.cs new file mode 100644 index 00000000..417700b5 --- /dev/null +++ b/quantower/Averages/AmaIndicator.cs @@ -0,0 +1,25 @@ +using TradingPlatform.BusinessLayer; +namespace QuanTAlib; + +public class AmaIndicator : IndicatorBase +{ + [InputParameter("Period", sortIndex: 1, 2, 2000, 1, 0)] + public int Period { get; set; } = 10; + + [InputParameter("Alpha", sortIndex: 2, minimum: -0.01, maximum: 1.0, increment: 0.01, decimalPlaces: 2)] + public double Alpha { get; set; } = 0.1; + private Ama? ma; + protected override AbstractBase QuanTAlib => ma!; + public override string ShortName => $"AMA {Period} : {Alpha} : {SourceName}"; + + + public AmaIndicator() + { + Name = "AMA - Adaptive Moving Average"; + } + + protected override void InitIndicator() + { + ma = new Ama(period: Period, alpha: Alpha); + } +}