mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-27 17:27:43 +00:00
Fibonacci Moving Average
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
namespace QuanTAlib;
|
||||
using System;
|
||||
|
||||
/* <summary>
|
||||
FMA: Fibonacci Moving Average
|
||||
FMA calculates the average across multiple EMAs with periods following Fibonacci sequence
|
||||
(skipping initial Fibonacci numbers of 1, 1, 2) 3, 5, 8, 13, 21, 34...
|
||||
|
||||
FMA(n) = Average(EMA(3), EMA(5), EMA(8), ema(13), ... EMA(n-th Fib))
|
||||
|
||||
Sources:
|
||||
https://kaabar-sofien.medium.com/the-fibonacci-moving-average-the-full-guide-60e718117595
|
||||
https://www.tradingview.com/script/6pxgp2vh-Fibonacci-Moving-Average-FMA/
|
||||
|
||||
</summary> */
|
||||
|
||||
public class FMA_Series : Single_TSeries_Indicator {
|
||||
double[,] fib;
|
||||
double _oldsum;
|
||||
int _len;
|
||||
|
||||
public FMA_Series(TSeries source, int period) : base(source, period, false) {
|
||||
_len = period;
|
||||
fib = new double[_len, 4];
|
||||
int a = 3;
|
||||
int b = 5;
|
||||
int f = 0;
|
||||
fib[0, 0] = 2 / ((double)a - 1);
|
||||
if (_len > 1) { fib[1, 0] = 2 / ((double)b - 1); }
|
||||
if (_len > 2) {
|
||||
for (int i = 2; i < _len; i++) {
|
||||
f = a + b;
|
||||
a = b;
|
||||
b = f;
|
||||
fib[i, 0] = 2 / ((double)f - 1);
|
||||
}
|
||||
}
|
||||
_oldsum = 0;
|
||||
if (this._data.Count > 0) { base.Add(this._data); }
|
||||
}
|
||||
|
||||
public override void Add((DateTime t, double v) TValue, bool update) {
|
||||
double _sum = 0;
|
||||
for (int i = 0; i < _len; i++) {
|
||||
if (update) { fib[i, 1] = fib[i, 3]; _sum = _oldsum; }
|
||||
else { fib[i, 3] = fib[i, 1]; _oldsum = _sum; }
|
||||
|
||||
if (this.Count == 0) { fib[i, 1] = TValue.v; }
|
||||
else {
|
||||
fib[i, 2] = fib[i, 0] * (TValue.v - fib[i, 1]) + fib[i, 1];
|
||||
fib[i, 1] = fib[i, 2];
|
||||
}
|
||||
_sum += fib[i, 1];
|
||||
}
|
||||
|
||||
double _fma = _sum / _len;
|
||||
base.Add((TValue.t, _fma), update, _NaN);
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ public class JMA_Series : Single_TSeries_Indicator {
|
||||
upperBand = lowerBand = prev_ma1 = prev_det0 = prev_det1 = prev_vsum = prev_jma = Kv = del1 = del2 = 0.0;
|
||||
Kv = 0;
|
||||
pr = (phase * 0.01) + 1.5;
|
||||
if (phase < -100) pr = 0.5;
|
||||
if (phase > 100) pr = 2.5;
|
||||
if (phase < -100) { pr = 0.5; }
|
||||
if (phase > 100) { pr = 2.5; }
|
||||
|
||||
mma1 = new();
|
||||
mma2 = new();
|
||||
@@ -83,8 +83,7 @@ public class JMA_Series : Single_TSeries_Indicator {
|
||||
vsum = prev_vsum + 0.1 * (volty - volty_10.First());
|
||||
if (update) { vsum_buff[vsum_buff.Count - 1] = vsum; }
|
||||
else { vsum_buff.Add(vsum); }
|
||||
if (vsum_buff.Count > (10*_p))
|
||||
vsum_buff.RemoveAt(0);
|
||||
if (vsum_buff.Count > (10 * _p)) { vsum_buff.RemoveAt(0); }
|
||||
double avolty = 0;
|
||||
for (int i = 0; i < vsum_buff.Count; i++) { avolty += vsum_buff[i]; }
|
||||
avolty /= vsum_buff.Count;
|
||||
@@ -94,10 +93,8 @@ public class JMA_Series : Single_TSeries_Indicator {
|
||||
double len1 = (Math.Log(Math.Sqrt(2.0 * _p)) / Math.Log(2.0)) + 2;
|
||||
if (len1 < 0) len1 = 0;
|
||||
double pow1 = Math.Max(len1 - 2.0, 0.5);
|
||||
if (rvolty > Math.Pow(len1, 1.0 / pow1))
|
||||
rvolty = Math.Pow(len1, 1.0 / pow1);
|
||||
if (rvolty < 1)
|
||||
rvolty = 1;
|
||||
if (rvolty > Math.Pow(len1, 1.0 / pow1)) { rvolty = Math.Pow(len1, 1.0 / pow1); }
|
||||
if (rvolty < 1) { rvolty = 1; }
|
||||
|
||||
//// from rvolty to second smoothing
|
||||
double pow2 = Math.Pow(rvolty, pow1);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
using Xunit;
|
||||
using System;
|
||||
using QuanTAlib;
|
||||
|
||||
namespace MovingAvg;
|
||||
public class FMA_Test
|
||||
{
|
||||
[Fact]
|
||||
public void Add_Test()
|
||||
{
|
||||
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
|
||||
FMA_Series c = new(a, 3);
|
||||
Assert.Equal(6, c.Count);
|
||||
a.Add(5);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(0, update: true);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Edge_Test()
|
||||
{
|
||||
TSeries a = new() { double.NaN, double.Epsilon, double.PositiveInfinity, double.MaxValue };
|
||||
FMA_Series c = new(a, 3);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.NaN);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
a.Add(double.PositiveInfinity);
|
||||
Assert.Equal(a.Count, c.Count);
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -155,7 +155,18 @@ public class Update {
|
||||
Assert.Equal(lastLen, QL.Count); // same size
|
||||
Assert.Equal(lastCalc, QL.Last()); // same data
|
||||
}
|
||||
[Fact] public void HEMA() {
|
||||
[Fact]
|
||||
public void FMA() {
|
||||
FMA_Series QL = new(source: bars.Close, period: period);
|
||||
var lastData = bars.Close.Last();
|
||||
var lastCalc = QL.Last();
|
||||
int lastLen = QL.Count;
|
||||
QL.Add((DateTime.Today, 0), update: true);
|
||||
QL.Add(lastData, update: true);
|
||||
Assert.Equal(lastLen, QL.Count); // same size
|
||||
Assert.Equal(lastCalc, QL.Last()); // same data
|
||||
}
|
||||
[Fact] public void HEMA() {
|
||||
HEMA_Series QL = new(source: bars.Close, period: period);
|
||||
var lastData = bars.Close.Last();
|
||||
var lastCalc = QL.Last();
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# FMA: Fibonacci Moving Average
|
||||
period = 6
|
||||
|
||||

|
||||
@@ -9,6 +9,7 @@
|
||||
* [SMMA - Smoothed Moving Average](SMMA.md)
|
||||
* [TRIMA - Triangular Moving Average](TRIMA.md)
|
||||
* [DWMA - Double Weighted Moving Average](DWMA.md)
|
||||
* [FMA - Fibonacci Moving Average](FMA.md)
|
||||
* [DEMA - Double Exponential MA](DEMA.md)
|
||||
* [TEMA - Triple Exponential MA](TEMA.md)
|
||||
* [ALMA - Arnaud Legoux Moving Average](ALMA.md)
|
||||
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 154 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 762 KiB |
+1
-1
@@ -57,7 +57,7 @@
|
||||
|⭐EMA - Exponential Moving Average|`EMA_Series`|✔️EMA|✔️GetEma|✔️ema|✔️ema|
|
||||
|EPMA - Endpoint Moving Average|||GetEpma||
|
||||
|FRAMA - Fractal Adaptive Moving Average|||||
|
||||
|FWMA - Fibonacci's Weighted Moving Average||||fwma|
|
||||
|FMA - Fibonacci's Weighted Moving Average|`FMA_Series`|||fwma|
|
||||
|HILO - Gann High-Low Activator||||hilo|
|
||||
|HEMA - Hull/EMA Average|`HEMA_Series`||||
|
||||
|Hilbert Transform Instantaneous Trendline||HT_TRENDLINE|GetHtTrendline||
|
||||
|
||||
+19
-15
@@ -12,30 +12,24 @@
|
||||
[](https://github.com/mihakralj/QuanTAlib/watchers)
|
||||
[](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)
|
||||
|
||||
**Quan**titative **TA** **lib**rary (QuanTAlib) is a C# library of classess and methods for quantitative technical analysis useful for trading securities with [Quantower](https://www.quantower.com/) and other C#-based trading platforms.
|
||||
**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 - some reasons why there is '_yet another C# TA library_':
|
||||
**QuanTAlib** is written with some specific design criteria in mind - why there is '_yet another C# TA library_':
|
||||
|
||||
- Supports both **historical data analysis** (working on bulk of historical arrays) and **real-time streaming analysis** (adding one data item at the time without the need to re-calculate the whole history)
|
||||
- **Calculate early data right** - no hiding of incomplete calculations with NaN values (unless explicitly requested), data is as valid as mathematically possible from the first value
|
||||
- Usage of events for communication between indicators - each data series is an event publisher, each indicator can be a subscriber - this allows easy and seamless data flow between indicators
|
||||
- Prioritize **real-time data analysis** (series can add new data and indicator doesn't have to re-calculate the whole history)
|
||||
- **Allow updates** to the last quote and adjusting the calculation to the still-forming bar
|
||||
- **Calculate early data right** - output data is as valid as mathematically possible from the first value onwards
|
||||
|
||||

|
||||
|
||||
If not obvious, QuanTAlib is intended for developers, and it does not focus on sources of OHLCV quotes. There are some very basic data feeds available to use in the learning process: `RND_Feed` and `GBM_Feed` for random data, `Yahoo_Feed` and `Alphavantage_Feed` for a quick grab of daily data of US stock market.
|
||||
|
||||
See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/getting_started.ipynb) .NET interactive notebook to get a feel how library works. Developers can use QuanTAlib in .NET interactive or in console apps, but the best usage of the library is withing C#-enabled trading platforms - see **QuanTower_Charts** folder for Quantower examples.
|
||||
See [Getting Started](https://github.com/mihakralj/QuanTAlib/blob/main/Docs/getting_started.ipynb) .NET interactive notebook to get a feel how library works. Developers can use QuanTAlib in [Polyglot Notebooks](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) or in console apps, but the best usage of the library is with C#-enabled trading platforms - see **QuanTower_Charts** folder for Quantower examples and check **Releases** for compiled Quantower DLL.
|
||||
|
||||
### Coverage
|
||||
|
||||
[List of all indicators - current and planned](indicators.md)
|
||||
|
||||
- **Basic calculations:** ADD, DIV, MAX, MIDPOINT, MIDPRICE, MIN, MUL, SUB, SUM, ZL
|
||||
- **Momentum:** CCI
|
||||
- **Statistics:** BIAS, VORR, COVAR, ENTROPY, KURTOSIS, LINREG, MAD, MAPE, MEDIAN, MSE, SDEV, SMAPE, SSDEV, SVAR, VAR, WMAPE, ZSCORE
|
||||
- **Trends:** ALMA, DEMA, DWMA, 3EMA, HEMA, HMA, JMA, KAMA, MACD, MAMA, RMA, SMA, SMMA, T3, TEMA, TRIMA, TRIX, WMA, ZLEMA
|
||||
- **Volatility:** ADL, ADOSC, ATR, ATRP, BBANDS, CMO, RSI
|
||||
- **Volume:** OBV
|
||||
- **Feeds:** GBM, RND, Yahoo, Alphavantage
|
||||
|
||||
### Validation
|
||||
|
||||
QuanTAlib uses validation tests with four other TA libraries to assure accuracy and validity of results:
|
||||
@@ -43,4 +37,14 @@ QuanTAlib uses validation tests with four other TA libraries to assure accuracy
|
||||
- [TA-LIB](https://www.ta-lib.org/function.html)
|
||||
- [Skender Stock Indicators](https://dotnet.stockindicators.dev/)
|
||||
- [Pandas-TA](https://twopirllc.github.io/pandas-ta/)
|
||||
- [Tulip Indicators](https://tulipindicators.org/)
|
||||
- [Tulip Indicators](https://tulipindicators.org/)
|
||||
|
||||
### Performance
|
||||
|
||||
Is QuanTAlib fast? Well, _no_, but actually *yes*. QuanTAlib works on an additive principle, meaning that even when served a full list of quotes, QuanTAlib will process one item at the time, rolling forward throug time series of data.
|
||||
- If the last bar is still forming (parameter `update: true`), QuanTAlib easily recalculates the last entry as often as needed without any need to recalculate the history.
|
||||
- If a new bar is added to the input, QuanTAlib will process that one item (default parameter `update: false`) and add that one result to the List. No recalculation of the history needed.
|
||||
|
||||
If you feed QuanTAlib 500 historical bars and calculate EMA(20) on it, the performance of QuanTAlib will be dead last compared to all other TA libraries.
|
||||
|
||||
But when system uses 10,000 historical bars, does updates to the current/last bar every tick, and adds a new bar every minute, QuanTAlib has no rivals; all other libraries need to re-calculate the full length of the array on each update/addition to the time series. Longer the series and more updates/additions it gets, more advantage for QuanTAlib.
|
||||
Reference in New Issue
Block a user