This commit is contained in:
Miha Kralj
2023-01-07 22:32:33 -08:00
parent 3c9bfb265d
commit 6db1ba7562
3 changed files with 74 additions and 69 deletions
+39 -42
View File
@@ -9,7 +9,7 @@ public class PandasTA : IDisposable
{ {
private readonly GBM_Feed bars; private readonly GBM_Feed bars;
private readonly Random rnd = new(); private readonly Random rnd = new();
private readonly int period, sample; private readonly int period, skip;
private int digits; private int digits;
private readonly string dllpath; private readonly string dllpath;
private readonly dynamic np; private readonly dynamic np;
@@ -20,8 +20,8 @@ public class PandasTA : IDisposable
public PandasTA() { public PandasTA() {
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0); bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0);
period = rnd.Next(maxValue: 28) + 3; period = rnd.Next(maxValue: 28) + 3;
sample = period+1; skip = period+10;
digits = 10; digits = 8;
Installer.InstallPath = Path.GetFullPath(path: "."); Installer.InstallPath = Path.GetFullPath(path: ".");
Installer.SetupPython().Wait(); Installer.SetupPython().Wait();
@@ -30,10 +30,7 @@ public class PandasTA : IDisposable
Installer.PipInstallModule(module_name: "pandas"); Installer.PipInstallModule(module_name: "pandas");
Installer.PipInstallModule(module_name: "pandas-ta"); Installer.PipInstallModule(module_name: "pandas-ta");
dllpath = Installer.InstallPath + "\\" + Installer.InstallDirectory + "\\" + Runtime.PythonDLL; dllpath = Installer.InstallPath + "\\" + Installer.InstallDirectory + "\\" + Runtime.PythonDLL;
Runtime.PythonDLL = dllpath; Runtime.PythonDLL = dllpath;
//Runtime.PythonDLL = "python.dll";
PythonEngine.Initialize(); PythonEngine.Initialize();
np = Py.Import(name: "numpy"); np = Py.Import(name: "numpy");
@@ -60,7 +57,7 @@ public class PandasTA : IDisposable
[Fact] void ADL() { [Fact] void ADL() {
ADL_Series QL = new(bars); ADL_Series QL = new(bars);
var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume); var pta = df.ta.ad(high: df.high, low: df.low, close:df.close, volume:df.volume);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i-1].v; double QL_item = QL[i-1].v;
double PanTA_item = (double)pta[i-1]; double PanTA_item = (double)pta[i-1];
@@ -72,7 +69,7 @@ public class PandasTA : IDisposable
[Fact] void ADOSC() { [Fact] void ADOSC() {
ADOSC_Series QL = new(bars); ADOSC_Series QL = new(bars);
var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume); var pta = df.ta.adosc(high: df.high, low: df.low, close: df.close, volume: df.volume);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -82,7 +79,7 @@ public class PandasTA : IDisposable
[Fact] void ATR() { [Fact] void ATR() {
ATR_Series QL = new(bars, period); ATR_Series QL = new(bars, period);
var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period); var pta = df.ta.atr(high: df.high, low: df.low, close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -93,7 +90,7 @@ public class PandasTA : IDisposable
void BBANDS() { void BBANDS() {
BBANDS_Series QL = new(bars.Close, period); BBANDS_Series QL = new(bars.Close, period);
var pta = df.ta.bbands(close: df.close, length: period).to_numpy(); var pta = df.ta.bbands(close: df.close, length: period).to_numpy();
for (int i = QL.Length-1; i > QL.Length - sample; i--) { for (int i = QL.Length-1; i > skip; i--) {
double QL_item = QL.Lower[i].v; double QL_item = QL.Lower[i].v;
double PanTA_item = (double)pta[i][0]; //lower double PanTA_item = (double)pta[i][0]; //lower
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -108,7 +105,7 @@ public class PandasTA : IDisposable
[Fact] void BIAS() { [Fact] void BIAS() {
BIAS_Series QL = new(bars.Close, period, false); BIAS_Series QL = new(bars.Close, period, false);
var pta = df.ta.bias(close: df.close, length: period); var pta = df.ta.bias(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -119,7 +116,7 @@ public class PandasTA : IDisposable
void CCI() { void CCI() {
CCI_Series QL = new(bars, period, false); CCI_Series QL = new(bars, period, false);
var pta = df.ta.cci(close: df.close, length: period); var pta = df.ta.cci(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length - sample; i--) { for (int i = QL.Length-1; i > skip; i--) {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -130,7 +127,7 @@ public class PandasTA : IDisposable
void CMO() { void CMO() {
CMO_Series QL = new(bars.Close, period, false); CMO_Series QL = new(bars.Close, period, false);
var pta = df.ta.cmo(close: df.close, length: period); var pta = df.ta.cmo(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length - sample; i--) { for (int i = QL.Length-1; i > skip; i--) {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -140,7 +137,7 @@ public class PandasTA : IDisposable
[Fact] void DEMA() { [Fact] void DEMA() {
DEMA_Series QL = new(bars.Close, period, false); DEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.dema(close: df.close, length: period); var pta = df.ta.dema(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -150,7 +147,7 @@ public class PandasTA : IDisposable
[Fact] void EMA() { [Fact] void EMA() {
EMA_Series QL = new(bars.Close, period, false); EMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.ema(close: df.close, length: period); var pta = df.ta.ema(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -160,7 +157,7 @@ public class PandasTA : IDisposable
[Fact] void ENTROPY() { [Fact] void ENTROPY() {
ENTROPY_Series QL = new(bars.Close, period, useNaN: false); ENTROPY_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.entropy(close: df.close, length: period); var pta = df.ta.entropy(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -169,7 +166,7 @@ public class PandasTA : IDisposable
} }
[Fact] void HL2() { [Fact] void HL2() {
var pta = df.ta.hl2(high: df.high, low: df.low); var pta = df.ta.hl2(high: df.high, low: df.low);
for (int i = bars.HL2.Length; i > bars.HL2.Length-sample; i--) for (int i = bars.HL2.Length-1; i > skip; i--)
{ {
double QL_item = bars.HL2[i - 1].v; double QL_item = bars.HL2[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -178,7 +175,7 @@ public class PandasTA : IDisposable
} }
[Fact] void HLC3() { [Fact] void HLC3() {
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close); var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
for (int i = bars.HLC3.Length; i > bars.HLC3.Length-sample; i--) for (int i = bars.HLC3.Length; i > skip; i--)
{ {
double QL_item = bars.HLC3[i - 1].v; double QL_item = bars.HLC3[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -188,7 +185,7 @@ public class PandasTA : IDisposable
[Fact] void HMA() { [Fact] void HMA() {
HMA_Series QL = new(bars.Close, period, false); HMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.hma(close: df.close, length: period); var pta = df.ta.hma(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -199,7 +196,7 @@ public class PandasTA : IDisposable
[Fact] void HWMA() { [Fact] void HWMA() {
HWMA_Series QL = new(bars.Close, useNaN: false); HWMA_Series QL = new(bars.Close, useNaN: false);
var pta = df.ta.hwma(close: df.close); var pta = df.ta.hwma(close: df.close);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -210,7 +207,7 @@ public class PandasTA : IDisposable
[Fact] void KAMA() { [Fact] void KAMA() {
KAMA_Series QL = new(bars.Close, period); KAMA_Series QL = new(bars.Close, period);
var pta = df.ta.kama(close: df.close, length: period); var pta = df.ta.kama(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -220,7 +217,7 @@ public class PandasTA : IDisposable
[Fact] void KURTOSIS() { [Fact] void KURTOSIS() {
KURTOSIS_Series QL = new(bars.Close, period, useNaN: false); KURTOSIS_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.kurtosis(close: df.close, length: period); var pta = df.ta.kurtosis(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -231,7 +228,7 @@ public class PandasTA : IDisposable
void MACD() { void MACD() {
MACD_Series QL = new(bars.Close, 26,fast: 12,signal:9); MACD_Series QL = new(bars.Close, 26,fast: 12,signal:9);
var pta = df.ta.macd(close: df.close).to_numpy(); var pta = df.ta.macd(close: df.close).to_numpy();
for (int i = QL.Length; i > QL.Length - sample; i--) { for (int i = QL.Length-1; i > skip; i--) {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1][0]; double PanTA_item = (double)pta[i - 1][0];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -244,7 +241,7 @@ public class PandasTA : IDisposable
{ {
MAD_Series QL = new(bars.Close, period, useNaN: false); MAD_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.mad(close: df.close, length: period); var pta = df.ta.mad(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -254,7 +251,7 @@ public class PandasTA : IDisposable
[Fact] void MEDIAN() { [Fact] void MEDIAN() {
MEDIAN_Series QL = new(bars.Close, period); MEDIAN_Series QL = new(bars.Close, period);
var pta = df.ta.median(close: df.close, length: period); var pta = df.ta.median(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -264,7 +261,7 @@ public class PandasTA : IDisposable
[Fact] void OBV() { [Fact] void OBV() {
OBV_Series QL = new(bars); OBV_Series QL = new(bars);
var pta = df.ta.obv(close: df.close, volume: df.volume); var pta = df.ta.obv(close: df.close, volume: df.volume);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -273,7 +270,7 @@ public class PandasTA : IDisposable
} }
[Fact] void OHLC4() { [Fact] void OHLC4() {
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close); var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
for (int i = bars.OHLC4.Length; i > bars.OHLC4.Length-sample; i--) for (int i = bars.OHLC4.Length; i > skip; i--)
{ {
double QL_item = bars.OHLC4[i - 1].v; double QL_item = bars.OHLC4[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -283,7 +280,7 @@ public class PandasTA : IDisposable
[Fact] void RMA() { [Fact] void RMA() {
RMA_Series QL = new(bars.Close, period, false); RMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.rma(close: df.close, length: period); var pta = df.ta.rma(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -293,7 +290,7 @@ public class PandasTA : IDisposable
[Fact] void RSI() { [Fact] void RSI() {
RSI_Series QL = new(bars.Close, period); RSI_Series QL = new(bars.Close, period);
var pta = df.ta.rsi(close: df.close, length: period); var pta = df.ta.rsi(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -303,7 +300,7 @@ public class PandasTA : IDisposable
[Fact] void SDEV() { [Fact] void SDEV() {
SDEV_Series QL = new(bars.Close, period, useNaN: false); SDEV_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.stdev(close: df.close, length: period, ddof: 0); var pta = df.ta.stdev(close: df.close, length: period, ddof: 0);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -313,7 +310,7 @@ public class PandasTA : IDisposable
[Fact] void SMA() { [Fact] void SMA() {
SMA_Series QL = new(bars.Close, period, false); SMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.sma(close: df.close, length: period); var pta = df.ta.sma(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -323,7 +320,7 @@ public class PandasTA : IDisposable
[Fact] void SSDEV() { [Fact] void SSDEV() {
SSDEV_Series QL = new(bars.Close, period, useNaN: false); SSDEV_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.stdev(close: df.close, length: period, ddof: 1); var pta = df.ta.stdev(close: df.close, length: period, ddof: 1);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -333,7 +330,7 @@ public class PandasTA : IDisposable
[Fact] void SVARIANCE() { [Fact] void SVARIANCE() {
SVAR_Series QL = new(bars.Close, period); SVAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof: 1); var pta = df.ta.variance(close: df.close, length: period, ddof: 1);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -344,7 +341,7 @@ public class PandasTA : IDisposable
[Fact] void T3() { [Fact] void T3() {
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false); T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false);
var pta = df.ta.t3(close: df.close, length: period, a: 0.7); var pta = df.ta.t3(close: df.close, length: period, a: 0.7);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -354,7 +351,7 @@ public class PandasTA : IDisposable
[Fact] void TEMA() { [Fact] void TEMA() {
TEMA_Series QL = new(bars.Close, period, false); TEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.tema(close: df.close, length: period); var pta = df.ta.tema(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -364,7 +361,7 @@ public class PandasTA : IDisposable
[Fact] void TR() { [Fact] void TR() {
TR_Series QL = new(bars); TR_Series QL = new(bars);
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close); var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -375,7 +372,7 @@ public class PandasTA : IDisposable
// TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right // TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right
TRIMA_Series QL = new(bars.Close, 11); TRIMA_Series QL = new(bars.Close, 11);
var pta = df.ta.trima(close: df.close, length: 11); var pta = df.ta.trima(close: df.close, length: 11);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -385,7 +382,7 @@ public class PandasTA : IDisposable
[Fact] void TRIX() { [Fact] void TRIX() {
TRIX_Series QL = new(bars.Close, period); TRIX_Series QL = new(bars.Close, period);
var pta = df.ta.trix(close: df.close, length: period).to_numpy(); var pta = df.ta.trix(close: df.close, length: period).to_numpy();
for (int i = QL.Length; i > QL.Length - sample; i--) { for (int i = QL.Length-1; i > skip; i--) {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1][0]; double PanTA_item = (double)pta[i - 1][0];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits)); Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -394,7 +391,7 @@ public class PandasTA : IDisposable
[Fact] void VARIANCE() { [Fact] void VARIANCE() {
VAR_Series QL = new(bars.Close, period); VAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof:0); var pta = df.ta.variance(close: df.close, length: period, ddof:0);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -404,7 +401,7 @@ public class PandasTA : IDisposable
[Fact] void WMA() { [Fact] void WMA() {
WMA_Series QL = new(bars.Close, period, false); WMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.wma(close: df.close, length: period); var pta = df.ta.wma(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -414,7 +411,7 @@ public class PandasTA : IDisposable
[Fact] void ZLEMA() { [Fact] void ZLEMA() {
ZLEMA_Series QL = new(bars.Close, period, false); ZLEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.zlma(close: df.close, length: period); var pta = df.ta.zlma(close: df.close, length: period);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
@@ -424,7 +421,7 @@ public class PandasTA : IDisposable
[Fact] void ZSCORE() { [Fact] void ZSCORE() {
ZSCORE_Series QL = new(bars.Close, period, useNaN: false); ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.zscore(close: df.close, length: period, ddof: 0); var pta = df.ta.zscore(close: df.close, length: period, ddof: 0);
for (int i = QL.Length; i > QL.Length-sample; i--) for (int i = QL.Length-1; i > skip; i--)
{ {
double QL_item = QL[i - 1].v; double QL_item = QL[i - 1].v;
double PanTA_item = (double)pta[i - 1]; double PanTA_item = (double)pta[i - 1];
+34 -26
View File
@@ -1,9 +1,5 @@
# SMA: Simple Moving Average # SMA: Simple Moving Average
period = 10
![Alt text](./img/SMA_chart.svg)
SMA is is an arithmetic moving average where the weights in SMA are **equally** distributed across the given period, resulting in a mean() of the data within the period. SMA is is an arithmetic moving average where the weights in SMA are **equally** distributed across the given period, resulting in a mean() of the data within the period.
## Calculation ## Calculation
@@ -12,38 +8,50 @@ SMA is a rolling calculation that is looking backwards from the position ${n}$ a
$$ $$
SMA_p{(data)} = \frac{1}{p}\sum_{i=n-p+1}^{n} data_i SMA_p{(data)} = \frac{1}{p}\sum_{i=n-p+1}^{n} data_i
$$ $$
When calculating the value of the next $SMA_{p,next}$ while knowing all previous SMA values, SMA calculation can be reduced to: When calculating the value of the next $SMA_{p,next}$ while knowing previous SMA values, SMA calculation can be reduced to:
$$ $$
SMA_{p,next} = SMA_{p,prev}+\frac{1}{p}\left( data_{n+1}-data_{n+1-p}\right) SMA_{p,next} = SMA_{p,prev}+\frac{1}{p}\left( data_{n+1}-data_{n+1-p}\right)
$$ $$
## Reference Calculation ## Implementation
`TSeries SMA_Series (TSeries source, int period = 0, bool useNaN = false)`
- SMA_Series returns TSeries list
- `source`: input of type TSeries; SMA_Series automatically subscribes to events of new data added to the source
- `period`: optional size of a lookback window; if set to 0, SMA calculates cumulative average across the whole source
- `useNaN`: if set to _true_, SMA_Series will hide values within the initial period with NaN (for compatibility with other libraries)
[Link to source](..\Source\Trends\SMA_Series.cs)
## Behavior
![Alt text](./img/SMA_chart.svg)
## Reference Calculation & Validation
period = 5 period = 5
``` ```
TSeries data = new() {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29}; TSeries data = new() {81.59, 81.06, 82.87, 83.00, 83.61, 83.15, 82.84, 83.99, 84.55, 84.36, 85.53, 86.54, 86.89, 87.77, 87.29};
SMA_Series sma = new(data, 5, useNaN: false); SMA_Series sma = new(data, 5, useNaN: false);
SMA_Series sma_nan = new(data, 5, useNaN: true);
for (int i=0; i< data.Count; i++)
Console.WriteLine($"{i}\t{data[i].v,7:f2}\t{sma_nan[i].v,7:f3}\t{sma[i].v,7:f3}");
``` ```
|#|input|sma_NaN|sma| | #| Input | **QuanTAlib** | _TA-LIB_ | _Skender_ | _Pandas-TA_ | _Tulip_ |
|--|:--:|:--:|:--:| |--|:--:|:--:|:--:|:--:|:--:|:--:|
|0| 81.59| NaN| 81.590| | 0| 212.80|**212.80**| _NaN_| _NaN_| _NaN_| _NaN_|
|1| 81.06| NaN| 81.325| | 1| 214.06|**213.43**| _NaN_| _NaN_| _NaN_| _NaN_|
|2| 82.87| NaN| 81.840| | 2| 213.89|**213.58**| _NaN_| _NaN_| _NaN_| _NaN_|
|3| 83.00| NaN| 82.130| | 3| 214.66|**213.85**| _NaN_| _NaN_| _NaN_| _NaN_|
|4| 83.61| 82.426| 82.426| | 4| 213.95|**213.87**| _213.87_| _213.87_| _213.87_| _213.87_|
|5| 83.15| 82.738| 82.738| | 5| 213.95|**214.10**| _214.10_| _214.10_| _214.10_| _214.10_|
|6| 82.84| 83.094| 83.094| | 6| 214.55|**214.20**| _214.20_| _214.20_| _214.20_| _214.20_|
|7| 83.99| 83.318| 83.318| | 7| 214.02|**214.23**| _214.23_| _214.23_| _214.23_| _214.23_|
|8| 84.55| 83.628| 83.628| | 8| 214.51|**214.20**| _214.20_| _214.20_| _214.20_| _214.20_|
|9| 84.36| 83.778| 83.778| | 9| 213.75|**214.16**| _214.16_| _214.16_| _214.16_| _214.16_|
|10| 85.53| 84.254| 84.254| |10| 214.22|**214.21**| _214.21_| _214.21_| _214.21_| _214.21_|
|11| 86.54| 84.994| 84.994| |11| 213.43|**213.99**| _213.99_| _213.99_| _213.99_| _213.99_|
|12| 86.89| 85.574| 85.574| |12| 214.21|**214.02**| _214.02_| _214.02_| _214.02_| _214.02_|
|13| 87.77| 86.218| 86.218| |13| 213.66|**213.85**| _213.85_| _213.85_| _213.85_| _213.85_|
|14| 87.29| 86.804| 86.804| |14| 215.03|**214.11**| _214.11_| _214.11_| _214.11_| _214.11_|
|15| 216.89|**214.64**| _214.64_| _214.64_| _214.64_| _214.64_|
|16| 216.66|**215.29**| _215.29_| _215.29_| _215.29_| _215.29_|
## References ## References
- https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average - https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average
+1 -1
View File
@@ -75,7 +75,7 @@
|PWMA - Pascal's Weighted Moving Average||||pwma| |PWMA - Pascal's Weighted Moving Average||||pwma|
|⭐RMA - WildeR's Moving Average|`RMA_Series`|||✔️rma|✔️rma| |⭐RMA - WildeR's Moving Average|`RMA_Series`|||✔️rma|✔️rma|
|SINWMA - Sine Weighted Moving Average||||sinwma| |SINWMA - Sine Weighted Moving Average||||sinwma|
|⭐SMA - Simple Moving Average|`SMA_Series`|✔️SMA|✔️GetSma|✔️sma|✔️sma| |⭐[SMA - Simple Moving Average](SMA.md)|`SMA_Series`|✔️SMA|✔️GetSma|✔️sma|✔️sma|
|SMMA - Smoothed Moving Average|`SMMA_Series`||✔️GetSmma|| |SMMA - Smoothed Moving Average|`SMMA_Series`||✔️GetSmma||
|SSF - Ehler's Super Smoother Filter||||ssf| |SSF - Ehler's Super Smoother Filter||||ssf|
|SUPERTREND - Supertrend||||supertrend| |SUPERTREND - Supertrend||||supertrend|