Fibonacci Moving Average

This commit is contained in:
Miha Kralj
2023-01-04 13:51:50 -08:00
parent fc474f19ee
commit ca54856a66
10 changed files with 133 additions and 25 deletions
+59
View File
@@ -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);
}
}
+5 -8
View File
@@ -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);
+31
View File
@@ -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
View File
@@ -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();
+4
View File
@@ -0,0 +1,4 @@
# FMA: Fibonacci Moving Average
period = 6
![Alt text](./img/FMA_chart.svg)
+1
View File
@@ -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
View File
@@ -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
View File
@@ -12,30 +12,24 @@
[![GitHub watchers](https://img.shields.io/github/watchers/mihakralj/QuanTAlib?style=flat-square)](https://github.com/mihakralj/QuanTAlib/watchers)
[![.NET7.0](https://img.shields.io/badge/.NET-7.0%20%7C%206.0%20%7C%204.8-blue?style=flat-square)](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
![Alt text](./img/quotes.gif)
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.