diff --git a/.github/workflows/main_automation.yml b/.github/workflows/main_automation.yml
index 9829947f..ed5b381f 100644
--- a/.github/workflows/main_automation.yml
+++ b/.github/workflows/main_automation.yml
@@ -52,7 +52,7 @@ jobs:
/d:sonar.cs.dotcover.reportsPaths=./coveragereport.html
- name: Build Core DLL
- run: dotnet build ./Source/QuanTAlib.csproj --verbosity minimal --configuration Release --nologo
+ run: dotnet build ./Calculations/QuanTAlib.csproj --verbosity minimal --configuration Release --nologo
- name: Build Quantower DLL
run: dotnet build ./Quantower/Quantower.csproj --verbosity minimal --configuration Release --nologo
@@ -93,11 +93,13 @@ jobs:
automatic_release_tag: "latest"
prerelease: true
title: "Latest Build"
- files: /Quantower/Settings/Scripts/Indicators/QuanTAlib/*.dll
+ files: |
+ /Quantower/Settings/Scripts/Indicators/QuanTAlib/*.dll
+ /Quantower/Settings/Scripts/Strategies/QuanTAlib/*.dll
- - name: Authenticate to Github packages source
+ - name: Authenticate to Github packages Calculations
if: ${{ github.ref == 'refs/heads/main' }}
- run: dotnet nuget add source
+ run: dotnet nuget add Calculations
--username mihakralj
--password ${{ secrets.GITHUB_TOKEN }}
--store-password-in-clear-text
@@ -105,14 +107,14 @@ jobs:
- name: Push package to github
if: ${{ github.ref == 'refs/heads/main' }}
- run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg'
+ run: dotnet nuget push '.\Calculations\bin\Release\QuanTAlib.*.nupkg'
--api-key ${{ secrets.GITHUB_TOKEN }}
- --source https://nuget.pkg.github.com/mihakralj/index.json
+ --Calculations https://nuget.pkg.github.com/mihakralj/index.json
--skip-duplicate
- name: Push package to nuget.org
if: ${{ github.ref == 'refs/heads/main' }}
- run: dotnet nuget push '.\Source\bin\Release\QuanTAlib.*.nupkg'
+ run: dotnet nuget push '.\Calculations\bin\Release\QuanTAlib.*.nupkg'
--api-key ${{ secrets.NUGET_DEPLOY_KEY_QUANTLIB }}
- --source https://api.nuget.org/v3/index.json
+ --Calculations https://api.nuget.org/v3/index.json
--skip-duplicate
diff --git a/Source/Basics/ADD_Series.cs b/Calculations/Basics/ADD_Series.cs
similarity index 100%
rename from Source/Basics/ADD_Series.cs
rename to Calculations/Basics/ADD_Series.cs
diff --git a/Source/Basics/DIV_Series.cs b/Calculations/Basics/DIV_Series.cs
similarity index 100%
rename from Source/Basics/DIV_Series.cs
rename to Calculations/Basics/DIV_Series.cs
diff --git a/Source/Basics/MAX_Series.cs b/Calculations/Basics/MAX_Series.cs
similarity index 96%
rename from Source/Basics/MAX_Series.cs
rename to Calculations/Basics/MAX_Series.cs
index b8b197c3..109461a9 100644
--- a/Source/Basics/MAX_Series.cs
+++ b/Calculations/Basics/MAX_Series.cs
@@ -1,25 +1,25 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-MAX - Maximum value in the given period in the series.
- If period = 0 => period = full length of the series
- */
-
-public class MAX_Series : Single_TSeries_Indicator
-{
- public MAX_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- double _max = _buffer.Max();
-
- base.Add((TValue.t, _max), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+MAX - Maximum value in the given period in the series.
+ If period = 0 => period = full length of the series
+ */
+
+public class MAX_Series : Single_TSeries_Indicator
+{
+ public MAX_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ double _max = _buffer.Max();
+
+ base.Add((TValue.t, _max), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Basics/MIDPOINT_Series.cs b/Calculations/Basics/MIDPOINT_Series.cs
similarity index 96%
rename from Source/Basics/MIDPOINT_Series.cs
rename to Calculations/Basics/MIDPOINT_Series.cs
index 9bccdebf..d96a39a6 100644
--- a/Source/Basics/MIDPOINT_Series.cs
+++ b/Calculations/Basics/MIDPOINT_Series.cs
@@ -1,37 +1,37 @@
-namespace QuanTAlib;
-using System;
-
-/*
-MIDPOINT: Midpoint value (max+min)/2 in the given period in the series.
- If period = 0 => period = full length of the series
-
-Sources:
- https://thefaqblog.com/what-is-the-midpoint-in-statistics/
-
- */
-
-public class MIDPOINT_Series : Single_TSeries_Indicator
-{
- public MIDPOINT_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0)
- { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
-
- double _max = TValue.v;
- double _min = TValue.v;
- for (int i = 0; i < this._buffer.Count; i++)
- {
- _max = Math.Max(this._buffer[i], _max);
- _min = Math.Min(this._buffer[i], _min);
- }
- double _mid = (_max + _min) * 0.5;
-
- base.Add((TValue.t, _mid), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+MIDPOINT: Midpoint value (max+min)/2 in the given period in the series.
+ If period = 0 => period = full length of the series
+
+Sources:
+ https://thefaqblog.com/what-is-the-midpoint-in-statistics/
+
+ */
+
+public class MIDPOINT_Series : Single_TSeries_Indicator
+{
+ public MIDPOINT_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0)
+ { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+
+ double _max = TValue.v;
+ double _min = TValue.v;
+ for (int i = 0; i < this._buffer.Count; i++)
+ {
+ _max = Math.Max(this._buffer[i], _max);
+ _min = Math.Min(this._buffer[i], _min);
+ }
+ double _mid = (_max + _min) * 0.5;
+
+ base.Add((TValue.t, _mid), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Basics/MIDPRICE_Series.cs b/Calculations/Basics/MIDPRICE_Series.cs
similarity index 96%
rename from Source/Basics/MIDPRICE_Series.cs
rename to Calculations/Basics/MIDPRICE_Series.cs
index f7602c3a..c3a3c444 100644
--- a/Source/Basics/MIDPRICE_Series.cs
+++ b/Calculations/Basics/MIDPRICE_Series.cs
@@ -1,32 +1,32 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series.
- If period = 0 => period = full length of the series
-
- */
-
-public class MIDPRICE_Series : Single_TBars_Indicator
-{
- public MIDPRICE_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._bars.Count > 0)
- { base.Add(base._bars); }
- }
- private readonly System.Collections.Generic.List _bufferhi = new();
- private readonly System.Collections.Generic.List _bufferlo = new();
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
- {
- Add_Replace_Trim(_bufferhi, TBar.h, _p, update);
- Add_Replace_Trim(_bufferlo, TBar.l, _p, update);
-
- double _max = _bufferhi.Max();
- double _min = _bufferlo.Min();
- double _mid = (_max + _min) * 0.5;
-
- base.Add((TBar.t, _mid), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in the series.
+ If period = 0 => period = full length of the series
+
+ */
+
+public class MIDPRICE_Series : Single_TBars_Indicator
+{
+ public MIDPRICE_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._bars.Count > 0)
+ { base.Add(base._bars); }
+ }
+ private readonly System.Collections.Generic.List _bufferhi = new();
+ private readonly System.Collections.Generic.List _bufferlo = new();
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
+ {
+ Add_Replace_Trim(_bufferhi, TBar.h, _p, update);
+ Add_Replace_Trim(_bufferlo, TBar.l, _p, update);
+
+ double _max = _bufferhi.Max();
+ double _min = _bufferlo.Min();
+ double _mid = (_max + _min) * 0.5;
+
+ base.Add((TBar.t, _mid), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Basics/MIN_Series.cs b/Calculations/Basics/MIN_Series.cs
similarity index 96%
rename from Source/Basics/MIN_Series.cs
rename to Calculations/Basics/MIN_Series.cs
index 2621ec75..e41a0ba4 100644
--- a/Source/Basics/MIN_Series.cs
+++ b/Calculations/Basics/MIN_Series.cs
@@ -1,25 +1,25 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-MIN - Minimum value in the given period in the series.
- If period = 0 => period = full length of the series
- */
-
-public class MIN_Series : Single_TSeries_Indicator
-{
- public MIN_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
-
- double _min = _buffer.Min();
- base.Add((TValue.t, _min), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+MIN - Minimum value in the given period in the series.
+ If period = 0 => period = full length of the series
+ */
+
+public class MIN_Series : Single_TSeries_Indicator
+{
+ public MIN_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+
+ double _min = _buffer.Min();
+ base.Add((TValue.t, _min), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Basics/MUL_Series.cs b/Calculations/Basics/MUL_Series.cs
similarity index 100%
rename from Source/Basics/MUL_Series.cs
rename to Calculations/Basics/MUL_Series.cs
diff --git a/Source/Basics/Pair_TSeries_Abstract.cs b/Calculations/Basics/Pair_TSeries_Abstract.cs
similarity index 100%
rename from Source/Basics/Pair_TSeries_Abstract.cs
rename to Calculations/Basics/Pair_TSeries_Abstract.cs
diff --git a/Source/Basics/SUB_Series.cs b/Calculations/Basics/SUB_Series.cs
similarity index 100%
rename from Source/Basics/SUB_Series.cs
rename to Calculations/Basics/SUB_Series.cs
diff --git a/Source/Basics/SUM_Series.cs b/Calculations/Basics/SUM_Series.cs
similarity index 96%
rename from Source/Basics/SUM_Series.cs
rename to Calculations/Basics/SUM_Series.cs
index b3846737..bb98134d 100644
--- a/Source/Basics/SUM_Series.cs
+++ b/Calculations/Basics/SUM_Series.cs
@@ -1,35 +1,35 @@
-namespace QuanTAlib;
-using System;
-
-/*
-SUM: Cumulative Sum (aka Running Total)
- SUM across a period provides a rolling sum of all values across the period.
- If SUM values would be divided with period, the output would be SMA()
-
-Sources:
- https://en.wikipedia.org/wiki/CUSUM
-
- */
-
-public class SUM_Series : Single_TSeries_Indicator
-{
- public SUM_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
- else { _buffer.Add(TValue.v); }
- if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
-
- double _sum = 0;
- for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; }
-
- var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sum);
-
- base.Add(result, update);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+SUM: Cumulative Sum (aka Running Total)
+ SUM across a period provides a rolling sum of all values across the period.
+ If SUM values would be divided with period, the output would be SMA()
+
+Sources:
+ https://en.wikipedia.org/wiki/CUSUM
+
+ */
+
+public class SUM_Series : Single_TSeries_Indicator
+{
+ public SUM_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ if (update) { _buffer[_buffer.Count - 1] = TValue.v; }
+ else { _buffer.Add(TValue.v); }
+ if (_buffer.Count > this._p && this._p != 0) { _buffer.RemoveAt(0); }
+
+ double _sum = 0;
+ for (int i = 0; i < _buffer.Count; i++) { _sum += _buffer[i]; }
+
+ var result = (TValue.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _sum);
+
+ base.Add(result, update);
+ }
+}
diff --git a/Source/Basics/Single_TBars_Abstract.cs b/Calculations/Basics/Single_TBars_Abstract.cs
similarity index 100%
rename from Source/Basics/Single_TBars_Abstract.cs
rename to Calculations/Basics/Single_TBars_Abstract.cs
diff --git a/Source/Basics/Single_TSeries_Abstract.cs b/Calculations/Basics/Single_TSeries_Abstract.cs
similarity index 97%
rename from Source/Basics/Single_TSeries_Abstract.cs
rename to Calculations/Basics/Single_TSeries_Abstract.cs
index 6c283237..d52ad80d 100644
--- a/Source/Basics/Single_TSeries_Abstract.cs
+++ b/Calculations/Basics/Single_TSeries_Abstract.cs
@@ -1,70 +1,70 @@
-namespace QuanTAlib;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-/*
-Abstract classes with all scaffolding required to build indicators.
- All abstracts support period, NaN, and all permutations of Add() methods.
- Indicator classess need to implement:
- - Chaining constructor (Abstract's constructor executes first)
- - Default Add(value) class
- - optional Add(series) bulk insert class (for optimization of historical analysis)
-
- Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
- Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
- Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
-
- */
-public abstract class Single_TSeries_Indicator : TSeries
-{
- protected readonly int _period;
- protected readonly bool _NaN;
- protected readonly TSeries _data;
- protected int _p;
-
- // Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
- protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN) {
- _data = source;
- _period = period;
- _p = _period;
- _NaN = useNaN;
- _data.Pub += Sub;
- }
-
- // overridable Add() method to add/update a single item at the end of the list
-
- public virtual void Add((DateTime t, double v) TValue, bool update, bool useNaN) {
- if (_period == 0) { _p = Length; }
- var res = (TValue.t, Count < _p - 1 && _NaN ? double.NaN : TValue.v);
- base.Add(res, update);
- }
- public new virtual void Add((DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
-
- // potentially overridable Add() method for the whole series (could be replaced with faster bulk algo)
- public virtual void Add(TSeries data) {
- foreach (var item in data) { Add(TValue: item, update: false); }
- }
- public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
- public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update);
- public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false);
- public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
-
- protected static void Add_Replace(List l, double v, bool update)
- {
- if (update)
- { l[l.Count - 1] = v; }
- else
- { l.Add(v); }
- }
- protected static double Add_Replace_Trim(List l, double v, int p, bool update)
- {
- Add_Replace(l, v, update);
- double ret = (l.Count > 0) ? l.First() : 0;
- if (l.Count > p && p != 0)
- {
- l.RemoveAt(0);
- }
- return ret;
- }
-}
+namespace QuanTAlib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+/*
+Abstract classes with all scaffolding required to build indicators.
+ All abstracts support period, NaN, and all permutations of Add() methods.
+ Indicator classess need to implement:
+ - Chaining constructor (Abstract's constructor executes first)
+ - Default Add(value) class
+ - optional Add(series) bulk insert class (for optimization of historical analysis)
+
+ Single_TSeries_Indicator - one single-value TSeries in, one TSeries out.
+ Pair_TSeries_Indicator - Two TSeries in, one TSeries out. (includes simple semaphoring)
+ Single_TBars_Indicator - One OHLCV TBars in, one TSeries out.
+
+ */
+public abstract class Single_TSeries_Indicator : TSeries
+{
+ protected readonly int _period;
+ protected readonly bool _NaN;
+ protected readonly TSeries _data;
+ protected int _p;
+
+ // Chainable Constructor - add it at the end of primary constructor :base(source: source, period: period, useNaN: useNaN)
+ protected Single_TSeries_Indicator(TSeries source, int period, bool useNaN) {
+ _data = source;
+ _period = period;
+ _p = _period;
+ _NaN = useNaN;
+ _data.Pub += Sub;
+ }
+
+ // overridable Add() method to add/update a single item at the end of the list
+
+ public virtual void Add((DateTime t, double v) TValue, bool update, bool useNaN) {
+ if (_period == 0) { _p = Length; }
+ var res = (TValue.t, Count < _p - 1 && _NaN ? double.NaN : TValue.v);
+ base.Add(res, update);
+ }
+ public new virtual void Add((DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
+
+ // potentially overridable Add() method for the whole series (could be replaced with faster bulk algo)
+ public virtual void Add(TSeries data) {
+ foreach (var item in data) { Add(TValue: item, update: false); }
+ }
+ public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
+ public void Add(bool update) => this.Add(TValue: this._data[this._data.Count - 1], update: update);
+ public void Add() => this.Add(TValue: this._data[this._data.Count - 1], update: false);
+ public new void Sub(object source, TSeriesEventArgs e) => this.Add(TValue: this._data[this._data.Count - 1], update: e.update);
+
+ protected static void Add_Replace(List l, double v, bool update)
+ {
+ if (update)
+ { l[l.Count - 1] = v; }
+ else
+ { l.Add(v); }
+ }
+ protected static double Add_Replace_Trim(List l, double v, int p, bool update)
+ {
+ Add_Replace(l, v, update);
+ double ret = (l.Count > 0) ? l.First() : 0;
+ if (l.Count > p && p != 0)
+ {
+ l.RemoveAt(0);
+ }
+ return ret;
+ }
+}
diff --git a/Source/Basics/TBars.cs b/Calculations/Basics/TBars.cs
similarity index 100%
rename from Source/Basics/TBars.cs
rename to Calculations/Basics/TBars.cs
diff --git a/Source/Basics/TR_Series.cs b/Calculations/Basics/TR_Series.cs
similarity index 100%
rename from Source/Basics/TR_Series.cs
rename to Calculations/Basics/TR_Series.cs
diff --git a/Source/Basics/TSeries.cs b/Calculations/Basics/TSeries.cs
similarity index 100%
rename from Source/Basics/TSeries.cs
rename to Calculations/Basics/TSeries.cs
diff --git a/Source/Basics/ZL_Series.cs b/Calculations/Basics/ZL_Series.cs
similarity index 96%
rename from Source/Basics/ZL_Series.cs
rename to Calculations/Basics/ZL_Series.cs
index 7e06bf96..0a85f65b 100644
--- a/Source/Basics/ZL_Series.cs
+++ b/Calculations/Basics/ZL_Series.cs
@@ -1,34 +1,34 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ZL: Zero Lag
- Data is de-lagged by removing the data from “lag” days ago, thus removing
- (or attempting to) the cumulative effect of the moving average.
-
-Calculation:
- Lag = (Period-1)/2
- ZL = Data + (Data - Data(Lag days ago) )
-
-Sources:
- https://mudrex.com/blog/zero-lag-ema-trading-strategy/
-
- */
-
-public class ZL_Series : Single_TSeries_Indicator
-{
- public ZL_Series(TSeries source, int period, bool useNaN = false) : base(source, period:period, useNaN:useNaN) {
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- int _lag = (int)((_p-1) * 0.5);
- _lag = (this.Count-_lag < 0) ? 0 : this.Count-_lag;
-
- double _zl = TValue.v + (TValue.v - _data[_lag].v);
-
- var ret = (TValue.t, (base.Count==0 && base._NaN) ? double.NaN : _zl );
- base.Add(ret, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+ZL: Zero Lag
+ Data is de-lagged by removing the data from “lag” days ago, thus removing
+ (or attempting to) the cumulative effect of the moving average.
+
+Calculation:
+ Lag = (Period-1)/2
+ ZL = Data + (Data - Data(Lag days ago) )
+
+Sources:
+ https://mudrex.com/blog/zero-lag-ema-trading-strategy/
+
+ */
+
+public class ZL_Series : Single_TSeries_Indicator
+{
+ public ZL_Series(TSeries source, int period, bool useNaN = false) : base(source, period:period, useNaN:useNaN) {
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ int _lag = (int)((_p-1) * 0.5);
+ _lag = (this.Count-_lag < 0) ? 0 : this.Count-_lag;
+
+ double _zl = TValue.v + (TValue.v - _data[_lag].v);
+
+ var ret = (TValue.t, (base.Count==0 && base._NaN) ? double.NaN : _zl );
+ base.Add(ret, update);
+ }
}
\ No newline at end of file
diff --git a/Source/QuanTAlib.csproj b/Calculations/Calculations.csproj
similarity index 90%
rename from Source/QuanTAlib.csproj
rename to Calculations/Calculations.csproj
index 8e07cace..ae442495 100644
--- a/Source/QuanTAlib.csproj
+++ b/Calculations/Calculations.csproj
@@ -1,71 +1,71 @@
-
-
-
- QuanTAlib
- 0.1.30
- Library of Technical Indicators for .NET
- Quantitative Technical Analysis library for real-time (streaming) data analysis
- git
- https://github.com/mihakralj/QuanTAlib
- true
- Miha Kralj
- Miha Kralj
- readme.md
- net6.0
- disable
- preview
- disable
- true
- en-US
- QuanTAlib
- QuanTAlib
- True
- AnyCPU
- False
- embedded
- True
- True
-
- Indicators;Stock;Market;Technical;Analysis;Algorithmic;Trading;Trade;Trend;Momentum;Finance;Algorithm;Algo;
- AlgoTrading;Financial;Strategy;Chart;Charting;Oscillator;Overlay;Equity;Bitcoin;Crypto;Cryptocurrency;Forex;
- Quantitative;Historical;Quotes;
-
- Apache-2.0
-
-
-
- full
- True
- 7
- True
- anycpu
-
-
-
- True
- 7
- True
- anycpu
-
-
- QuanTAlib2.png
- https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png
- True
- ..\.sonarlint\mihakralj_quantalibcsharp.ruleset
-
-
-
-
-
-
- True
-
-
-
- True
- False
-
-
-
-
+
+
+
+ QuanTAlib
+ 0.1.31
+ Library of TA Calculations, Charts and Strategies for Quantower
+ Quantitative Technical Analysis Library in C# for Quantower
+ git
+ https://github.com/mihakralj/QuanTAlib
+ true
+ Miha Kralj
+ Miha Kralj
+ readme.md
+ net8.0;net7.0;net6.0
+ disable
+ preview
+ disable
+ true
+ en-US
+ QuanTAlib
+ QuanTAlib
+ True
+ AnyCPU
+ False
+ embedded
+ True
+ True
+
+ Indicators;Stock;Market;Technical;Analysis;Algorithmic;Trading;Trade;Trend;Momentum;Finance;Algorithm;Algo;
+ AlgoTrading;Financial;Strategy;Chart;Charting;Oscillator;Overlay;Equity;Bitcoin;Crypto;Cryptocurrency;Forex;
+ Quantitative;Historical;Quotes;
+
+ Apache-2.0
+
+
+
+ full
+ True
+ 7
+ True
+ anycpu
+
+
+
+ True
+ 7
+ True
+ anycpu
+
+
+ QuanTAlib2.png
+ https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png
+ True
+ ..\.sonarlint\mihakralj_quantalibcsharp.ruleset
+
+
+
+
+
+
+ True
+
+
+
+ True
+ False
+
+
+
+
\ No newline at end of file
diff --git a/Source/Feeds/Alphavantage_Feed.cs b/Calculations/Feeds/Alphavantage_Feed.cs
similarity index 97%
rename from Source/Feeds/Alphavantage_Feed.cs
rename to Calculations/Feeds/Alphavantage_Feed.cs
index 2f521ae2..a5c52eba 100644
--- a/Source/Feeds/Alphavantage_Feed.cs
+++ b/Calculations/Feeds/Alphavantage_Feed.cs
@@ -1,56 +1,56 @@
-namespace QuanTAlib;
-using System;
-using System.Text.Json;
-
-/*
-Alphavantage - Free API to collect 100 recent daily quotes. It requires a (free) API key
- Get API key at https://www.alphavantage.co/support/#api-key
- Parameters:
- Symbol: stock ("AAPL"),
- APIkey: unique Alphavantage API key
-
-
-
-public class Alphavantage_Feed : TBars
-{
- public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1}
- public Alphavantage_Feed(string Symbol = "IBM", string APIkey = "demo")
- {
- System.Net.Http.HttpClient client = new();
-
- string req = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED" + "&symbol=" + Symbol + "&apikey=" + APIkey;
- var msg = client.GetStringAsync(req).Result;
- var jres = JsonSerializer.Deserialize(msg).RootElement;
- jres.TryGetProperty("Time Series (Daily)", out JsonElement json);
-
- if (json.ValueKind == JsonValueKind.Undefined) {throw new InvalidOperationException("Stock symbol "+Symbol+" not found"); }
- foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); }
- base.Reverse();
- }
- private static (DateTime t, double o, double h, double l, double c, double v) GetOHLC(JsonProperty json)
- {
- double o, h, l, c, v;
- o = h = l = c = v = 0;
- DateTime date = Convert.ToDateTime(json.Name);
- foreach (var val in json.Value.EnumerateObject())
- {
- switch (val.Name)
- {
- case "1. open": o = Convert.ToDouble(val.Value.ToString()); break;
- case "1b. open (USD)": o = Convert.ToDouble(val.Value.ToString()); break;
- case "2. high": h = Convert.ToDouble(val.Value.ToString()); break;
- case "2b. high (USD)": h = Convert.ToDouble(val.Value.ToString()); break;
- case "3. low": l = Convert.ToDouble(val.Value.ToString()); break;
- case "3b. low (USD)": l = Convert.ToDouble(val.Value.ToString()); break;
- case "4. close": c = Convert.ToDouble(val.Value.ToString()); break;
- case "4b. close (USD)": c = Convert.ToDouble(val.Value.ToString()); break;
- case "5. adjusted close": c = Convert.ToDouble(val.Value.ToString()); break;
- case "5. volume": v = Convert.ToDouble(val.Value.ToString()); break;
- case "6. volume": v = Convert.ToDouble(val.Value.ToString()); break;
- default: o = 0; h = 0; l = 0; c = 0; v = 0; break;
- }
- }
- return (date, o, h, l, c, v);
- }
-}
+namespace QuanTAlib;
+using System;
+using System.Text.Json;
+
+/*
+Alphavantage - Free API to collect 100 recent daily quotes. It requires a (free) API key
+ Get API key at https://www.alphavantage.co/support/#api-key
+ Parameters:
+ Symbol: stock ("AAPL"),
+ APIkey: unique Alphavantage API key
+
+
+
+public class Alphavantage_Feed : TBars
+{
+ public enum Interval { Month, Week, Day, Hour, Min30, Min15, Min5, Min1}
+ public Alphavantage_Feed(string Symbol = "IBM", string APIkey = "demo")
+ {
+ System.Net.Http.HttpClient client = new();
+
+ string req = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED" + "&symbol=" + Symbol + "&apikey=" + APIkey;
+ var msg = client.GetStringAsync(req).Result;
+ var jres = JsonSerializer.Deserialize(msg).RootElement;
+ jres.TryGetProperty("Time Series (Daily)", out JsonElement json);
+
+ if (json.ValueKind == JsonValueKind.Undefined) {throw new InvalidOperationException("Stock symbol "+Symbol+" not found"); }
+ foreach (var val in json.EnumerateObject()) { base.Add(GetOHLC(val)); }
+ base.Reverse();
+ }
+ private static (DateTime t, double o, double h, double l, double c, double v) GetOHLC(JsonProperty json)
+ {
+ double o, h, l, c, v;
+ o = h = l = c = v = 0;
+ DateTime date = Convert.ToDateTime(json.Name);
+ foreach (var val in json.Value.EnumerateObject())
+ {
+ switch (val.Name)
+ {
+ case "1. open": o = Convert.ToDouble(val.Value.ToString()); break;
+ case "1b. open (USD)": o = Convert.ToDouble(val.Value.ToString()); break;
+ case "2. high": h = Convert.ToDouble(val.Value.ToString()); break;
+ case "2b. high (USD)": h = Convert.ToDouble(val.Value.ToString()); break;
+ case "3. low": l = Convert.ToDouble(val.Value.ToString()); break;
+ case "3b. low (USD)": l = Convert.ToDouble(val.Value.ToString()); break;
+ case "4. close": c = Convert.ToDouble(val.Value.ToString()); break;
+ case "4b. close (USD)": c = Convert.ToDouble(val.Value.ToString()); break;
+ case "5. adjusted close": c = Convert.ToDouble(val.Value.ToString()); break;
+ case "5. volume": v = Convert.ToDouble(val.Value.ToString()); break;
+ case "6. volume": v = Convert.ToDouble(val.Value.ToString()); break;
+ default: o = 0; h = 0; l = 0; c = 0; v = 0; break;
+ }
+ }
+ return (date, o, h, l, c, v);
+ }
+}
*/
\ No newline at end of file
diff --git a/Source/Feeds/GBM_Feed.cs b/Calculations/Feeds/GBM_Feed.cs
similarity index 97%
rename from Source/Feeds/GBM_Feed.cs
rename to Calculations/Feeds/GBM_Feed.cs
index e0ca22dc..a08568c1 100644
--- a/Source/Feeds/GBM_Feed.cs
+++ b/Calculations/Feeds/GBM_Feed.cs
@@ -1,63 +1,63 @@
-namespace QuanTAlib;
-using System;
-
-/*
-GBM - Geometric Brownian Motion is a random simulator of market movement, returning List
- GBM can be used for testing indicators, validation and Monte Carlo simulations of strategies.
-
- Sample usage:
- GBM-Random data = new(); // generates 1 year (252) list of bars
- GBM-Random data = new(Bars: 1000); // generates 1,000 bars
- GBM-Random data = new(Bars: 252, Volatility: 0.05, Drift: 0.0005, Seed: 100.0)
-
- Parameters
- Bars: number of bars (quotes) requested
- Volatility: how dymamic/volatile the series should be; default is 1
- Drift: incremental drift due to annual interest rate; default is 5%
- Seed: starting value of the random series; should not be 0
-
-
*/
-
-public class GBM_Feed : TBars
-{
- private double seed;
- readonly double drift, volatility;
- readonly int precision;
- public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0, int Precision = 2) {
- this.seed = Seed;
- volatility = Volatility*0.01;
- drift = Drift*0.01;
- precision = Precision;
- for (int i = 0; i OCMin)? (2 * OCMin) - Low : Low;
-
- double Volume = GBM_value(seed*10, volatility*2, Drift:0, precision: 1);
-
- base.Add((timestamp, Open, High, Low, Close, Volume), update);
- seed = Close;
- }
-
- private static double GBM_value(double Seed, double Volatility, double Drift, int precision) {
- Random rnd = new();
- double U1 = 1.0-rnd.NextDouble();
- double U2 = 1.0-rnd.NextDouble();
- double Z = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2);
- return Math.Round(Seed * Math.Exp( Drift - (Volatility*Volatility*0.5) + (Volatility * Z)), digits: precision);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+GBM - Geometric Brownian Motion is a random simulator of market movement, returning List
+ GBM can be used for testing indicators, validation and Monte Carlo simulations of strategies.
+
+ Sample usage:
+ GBM-Random data = new(); // generates 1 year (252) list of bars
+ GBM-Random data = new(Bars: 1000); // generates 1,000 bars
+ GBM-Random data = new(Bars: 252, Volatility: 0.05, Drift: 0.0005, Seed: 100.0)
+
+ Parameters
+ Bars: number of bars (quotes) requested
+ Volatility: how dymamic/volatile the series should be; default is 1
+ Drift: incremental drift due to annual interest rate; default is 5%
+ Seed: starting value of the random series; should not be 0
+
+
*/
+
+public class GBM_Feed : TBars
+{
+ private double seed;
+ readonly double drift, volatility;
+ readonly int precision;
+ public GBM_Feed(int Bars = 252, double Volatility = 1.0, double Drift = 0.05, double Seed = 100.0, int Precision = 2) {
+ this.seed = Seed;
+ volatility = Volatility*0.01;
+ drift = Drift*0.01;
+ precision = Precision;
+ for (int i = 0; i OCMin)? (2 * OCMin) - Low : Low;
+
+ double Volume = GBM_value(seed*10, volatility*2, Drift:0, precision: 1);
+
+ base.Add((timestamp, Open, High, Low, Close, Volume), update);
+ seed = Close;
+ }
+
+ private static double GBM_value(double Seed, double Volatility, double Drift, int precision) {
+ Random rnd = new();
+ double U1 = 1.0-rnd.NextDouble();
+ double U2 = 1.0-rnd.NextDouble();
+ double Z = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2);
+ return Math.Round(Seed * Math.Exp( Drift - (Volatility*Volatility*0.5) + (Volatility * Z)), digits: precision);
+ }
}
\ No newline at end of file
diff --git a/Source/Feeds/RND_Feed.cs b/Calculations/Feeds/RND_Feed.cs
similarity index 97%
rename from Source/Feeds/RND_Feed.cs
rename to Calculations/Feeds/RND_Feed.cs
index 1d17840d..c6e311af 100644
--- a/Source/Feeds/RND_Feed.cs
+++ b/Calculations/Feeds/RND_Feed.cs
@@ -1,28 +1,28 @@
-namespace QuanTAlib;
-using System;
-
-/*
-Random Bars generator - used for testing, validation and fun
- Returns 'bars' number of candles that follow common market movement.
- volatility defines how 'jumpy' is the series of
- startvalue defines beginning closing price that then guides the rest of series
-
- */
-
-public class RND_Feed : TBars
-{
- public RND_Feed(int Bars, double Volatility = 0.05, double Startvalue = 100.0)
- {
- Random rnd = new();
- double c = Startvalue;
- for (int i = 0; i < Bars; i++)
- {
- double o = Math.Round(c + (c * (((Volatility * 0.1) * rnd.NextDouble()) - 0.005)), 2);
- double h = Math.Round(o + (c * Volatility * rnd.NextDouble()), 2);
- double l = Math.Round(o - (c * Volatility * rnd.NextDouble()), 2);
- c = Math.Round(l + ((h - l) * rnd.NextDouble()), 2);
- double v = Math.Round(1000 * rnd.NextDouble(), 2);
- this.Add(DateTime.Today.AddDays(i - Bars), o, h, l, c, v);
- }
- }
+namespace QuanTAlib;
+using System;
+
+/*
+Random Bars generator - used for testing, validation and fun
+ Returns 'bars' number of candles that follow common market movement.
+ volatility defines how 'jumpy' is the series of
+ startvalue defines beginning closing price that then guides the rest of series
+
+ */
+
+public class RND_Feed : TBars
+{
+ public RND_Feed(int Bars, double Volatility = 0.05, double Startvalue = 100.0)
+ {
+ Random rnd = new();
+ double c = Startvalue;
+ for (int i = 0; i < Bars; i++)
+ {
+ double o = Math.Round(c + (c * (((Volatility * 0.1) * rnd.NextDouble()) - 0.005)), 2);
+ double h = Math.Round(o + (c * Volatility * rnd.NextDouble()), 2);
+ double l = Math.Round(o - (c * Volatility * rnd.NextDouble()), 2);
+ c = Math.Round(l + ((h - l) * rnd.NextDouble()), 2);
+ double v = Math.Round(1000 * rnd.NextDouble(), 2);
+ this.Add(DateTime.Today.AddDays(i - Bars), o, h, l, c, v);
+ }
+ }
}
\ No newline at end of file
diff --git a/Source/Feeds/Yahoo_Feed.cs b/Calculations/Feeds/Yahoo_Feed.cs
similarity index 97%
rename from Source/Feeds/Yahoo_Feed.cs
rename to Calculations/Feeds/Yahoo_Feed.cs
index 4df7d380..b904fbac 100644
--- a/Source/Feeds/Yahoo_Feed.cs
+++ b/Calculations/Feeds/Yahoo_Feed.cs
@@ -1,49 +1,49 @@
-namespace QuanTAlib;
-using System;
-using System.Text.Json;
-
-/*
-Yahoo Finance - Free API feed to collect daily market quotes
- Parameters:
- Symbol: stock symbol (default: "IBM")
- Period: number of days of collected history (default: 252)
- Usage:
- Yahoo_Feed ticker = new("MSFT", 20)
-
-
-
-public class Yahoo_Feed : TBars
-{
- public Yahoo_Feed(string Symbol = "IBM", int Period = 252) {
- Period = (int)(Period*1.45);
- string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+
- Symbol+"?interval=1d&period1="+
- (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+
- (int)new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
- System.Net.Http.HttpClient client = new();
- var msg = client.GetStringAsync(requestUrl).Result;
- var jresult = JsonSerializer.Deserialize(msg).RootElement;
-
- jresult.TryGetProperty("chart",out JsonElement json);
- json.TryGetProperty("result",out json);
- json[0].TryGetProperty("timestamp",out JsonElement datetime);
- json[0].TryGetProperty("indicators",out json);
- json.TryGetProperty("quote",out json);
- json[0].TryGetProperty("open",out JsonElement open);
- json[0].TryGetProperty("high",out JsonElement high);
- json[0].TryGetProperty("low",out JsonElement low);
- json[0].TryGetProperty("close",out JsonElement close);
- json[0].TryGetProperty("volume",out JsonElement volume);
-
- for (int i=0; i
+Yahoo Finance - Free API feed to collect daily market quotes
+ Parameters:
+ Symbol: stock symbol (default: "IBM")
+ Period: number of days of collected history (default: 252)
+ Usage:
+ Yahoo_Feed ticker = new("MSFT", 20)
+
+
+
+public class Yahoo_Feed : TBars
+{
+ public Yahoo_Feed(string Symbol = "IBM", int Period = 252) {
+ Period = (int)(Period*1.45);
+ string requestUrl = "https://query1.finance.yahoo.com/v8/finance/chart/"+
+ Symbol+"?interval=1d&period1="+
+ (int)new DateTimeOffset(DateTime.UtcNow.AddDays(-Period+1)).ToUnixTimeSeconds()+"&period2="+
+ (int)new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
+ System.Net.Http.HttpClient client = new();
+ var msg = client.GetStringAsync(requestUrl).Result;
+ var jresult = JsonSerializer.Deserialize(msg).RootElement;
+
+ jresult.TryGetProperty("chart",out JsonElement json);
+ json.TryGetProperty("result",out json);
+ json[0].TryGetProperty("timestamp",out JsonElement datetime);
+ json[0].TryGetProperty("indicators",out json);
+ json.TryGetProperty("quote",out json);
+ json[0].TryGetProperty("open",out JsonElement open);
+ json[0].TryGetProperty("high",out JsonElement high);
+ json[0].TryGetProperty("low",out JsonElement low);
+ json[0].TryGetProperty("close",out JsonElement close);
+ json[0].TryGetProperty("volume",out JsonElement volume);
+
+ for (int i=0; i
-CCI: Commodity Channel Index
- Commodity Channel Index is a momentum oscillator used to primarily identify overbought
- and oversold levels relative to a mean. CCI measures the current price level relative
- to an average price level over a given period of time:
- - CCI is relatively high when prices are far above their average.
- - CCI is relatively low when prices are far below their average.
- Using this method, CCI can be used to identify overbought and oversold levels.
-
-Sources:
- https://www.investopedia.com/terms/c/commoditychannelindex.asp
- https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/cci
-
- */
-
-public class CCI_Series : Single_TBars_Indicator
-{
- private readonly System.Collections.Generic.List _tp = new();
-
- public CCI_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
- {
- if (_bars.Count > 0) { base.Add(_bars); }
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
- {
- double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0;
- if (update) { this._tp[this._tp.Count - 1] = _tpItem; } else { this._tp.Add(_tpItem); }
- if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
-
- // average TP over _tp buffer
- double _avgTp = _tp.Average();
-
- // average Deviation over _tp buffer
- double _avgDv = 0;
- for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); }
- _avgDv /= this._tp.Count;
-
-
- double _cci = (_avgDv == 0) ? double.NaN : (this._tp[this._tp.Count-1] - _avgTp) / (0.015 * _avgDv);
-
- base.Add((TBar.t, _cci), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+using static System.Net.Mime.MediaTypeNames;
+
+/*
+CCI: Commodity Channel Index
+ Commodity Channel Index is a momentum oscillator used to primarily identify overbought
+ and oversold levels relative to a mean. CCI measures the current price level relative
+ to an average price level over a given period of time:
+ - CCI is relatively high when prices are far above their average.
+ - CCI is relatively low when prices are far below their average.
+ Using this method, CCI can be used to identify overbought and oversold levels.
+
+Sources:
+ https://www.investopedia.com/terms/c/commoditychannelindex.asp
+ https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/cci
+
+ */
+
+public class CCI_Series : Single_TBars_Indicator
+{
+ private readonly System.Collections.Generic.List _tp = new();
+
+ public CCI_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
+ {
+ if (_bars.Count > 0) { base.Add(_bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
+ {
+ double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0;
+ if (update) { this._tp[this._tp.Count - 1] = _tpItem; } else { this._tp.Add(_tpItem); }
+ if (this._tp.Count > this._p) { this._tp.RemoveAt(0); }
+
+ // average TP over _tp buffer
+ double _avgTp = _tp.Average();
+
+ // average Deviation over _tp buffer
+ double _avgDv = 0;
+ for (int i = 0; i < this._tp.Count; i++) { _avgDv += Math.Abs(_avgTp - this._tp[i]); }
+ _avgDv /= this._tp.Count;
+
+
+ double _cci = (_avgDv == 0) ? double.NaN : (this._tp[this._tp.Count-1] - _avgTp) / (0.015 * _avgDv);
+
+ base.Add((TBar.t, _cci), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Statistics/BIAS_Series.cs b/Calculations/Statistics/BIAS_Series.cs
similarity index 100%
rename from Source/Statistics/BIAS_Series.cs
rename to Calculations/Statistics/BIAS_Series.cs
diff --git a/Source/Statistics/CORR_Series.cs b/Calculations/Statistics/CORR_Series.cs
similarity index 97%
rename from Source/Statistics/CORR_Series.cs
rename to Calculations/Statistics/CORR_Series.cs
index f82d82de..246baa79 100644
--- a/Source/Statistics/CORR_Series.cs
+++ b/Calculations/Statistics/CORR_Series.cs
@@ -1,52 +1,52 @@
-namespace QuanTAlib;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-/*
-CORR: Pearson's Correlation Coefficient
- PCC is a measure of linear correlation between two sets of data.
- It is the ratio between the covariance of two variables and the product of
- their standard deviations; it is essentially a normalized measurement of
- the covariance, such that the result always has a value between −1 and 1.
-
-Sources:
- https://en.wikipedia.org/wiki/Pearson_correlation_coefficient
-
- */
-
-public class CORR_Series : Pair_TSeries_Indicator
-{
- public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN)
- {
- if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
- }
-
- private readonly System.Collections.Generic.List _x = new();
- private readonly System.Collections.Generic.List _xx = new();
- private readonly System.Collections.Generic.List _y = new();
- private readonly System.Collections.Generic.List _yy = new();
- private readonly System.Collections.Generic.List _xy = new();
-
- public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
- {
- Add_Replace_Trim(_x, TValue1.v, _p, update);
- Add_Replace_Trim(_xx, TValue1.v * TValue1.v, _p, update);
- Add_Replace_Trim(_y, TValue2.v, _p, update);
- Add_Replace_Trim(_yy, TValue2.v * TValue2.v, _p, update);
- Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update);
-
- double _sumx = _x.Sum();
- double _sumxx = _xx.Sum();
- double _sumy = _y.Sum();
- double _sumyy = _yy.Sum();
- double _sumxy = _xy.Sum();
-
- double _covar = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p);
- double _cor = (_covar != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_covar) : 0.0;
-
- var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor);
- if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
-
- }
-}
+namespace QuanTAlib;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+/*
+CORR: Pearson's Correlation Coefficient
+ PCC is a measure of linear correlation between two sets of data.
+ It is the ratio between the covariance of two variables and the product of
+ their standard deviations; it is essentially a normalized measurement of
+ the covariance, such that the result always has a value between −1 and 1.
+
+Sources:
+ https://en.wikipedia.org/wiki/Pearson_correlation_coefficient
+
+ */
+
+public class CORR_Series : Pair_TSeries_Indicator
+{
+ public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN)
+ {
+ if (base._d1.Count > 0 && base._d2.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], base._d2[i], false); } }
+ }
+
+ private readonly System.Collections.Generic.List _x = new();
+ private readonly System.Collections.Generic.List _xx = new();
+ private readonly System.Collections.Generic.List _y = new();
+ private readonly System.Collections.Generic.List _yy = new();
+ private readonly System.Collections.Generic.List _xy = new();
+
+ public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
+ {
+ Add_Replace_Trim(_x, TValue1.v, _p, update);
+ Add_Replace_Trim(_xx, TValue1.v * TValue1.v, _p, update);
+ Add_Replace_Trim(_y, TValue2.v, _p, update);
+ Add_Replace_Trim(_yy, TValue2.v * TValue2.v, _p, update);
+ Add_Replace_Trim(_xy, TValue1.v * TValue2.v, _p, update);
+
+ double _sumx = _x.Sum();
+ double _sumxx = _xx.Sum();
+ double _sumy = _y.Sum();
+ double _sumyy = _yy.Sum();
+ double _sumxy = _xy.Sum();
+
+ double _covar = (_sumxx - _sumx * _sumx / _p) * (_sumyy - _sumy * _sumy / _p);
+ double _cor = (_covar != 0) ? (_sumxy - _sumx * _sumy / _p) / Math.Sqrt(_covar) : 0.0;
+
+ var result = (TValue1.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _cor);
+ if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
+
+ }
+}
diff --git a/Source/Statistics/COVAR_Series.cs b/Calculations/Statistics/COVAR_Series.cs
similarity index 100%
rename from Source/Statistics/COVAR_Series.cs
rename to Calculations/Statistics/COVAR_Series.cs
diff --git a/Source/Statistics/DECAY_Series.cs b/Calculations/Statistics/DECAY_Series.cs
similarity index 100%
rename from Source/Statistics/DECAY_Series.cs
rename to Calculations/Statistics/DECAY_Series.cs
diff --git a/Source/Statistics/ENTROPY_Series.cs b/Calculations/Statistics/ENTROPY_Series.cs
similarity index 100%
rename from Source/Statistics/ENTROPY_Series.cs
rename to Calculations/Statistics/ENTROPY_Series.cs
diff --git a/Source/Statistics/KURTOSIS_Series.cs b/Calculations/Statistics/KURTOSIS_Series.cs
similarity index 100%
rename from Source/Statistics/KURTOSIS_Series.cs
rename to Calculations/Statistics/KURTOSIS_Series.cs
diff --git a/Source/Statistics/LINREG_Series.cs b/Calculations/Statistics/LINREG_Series.cs
similarity index 97%
rename from Source/Statistics/LINREG_Series.cs
rename to Calculations/Statistics/LINREG_Series.cs
index 0987555c..2aff6af2 100644
--- a/Source/Statistics/LINREG_Series.cs
+++ b/Calculations/Statistics/LINREG_Series.cs
@@ -1,91 +1,91 @@
-namespace QuanTAlib;
-using System;
-
-/*
-LINREG: Linear Regression (using Least Square Method)
- Linear Regression provides a slope of a straight line that is the best approximation of the given set of data.
- The method of least squares is a standard approach in linear regression analysis to approximate the solution
- by minimizing the sum of the squares of the residuals made in the results of each individual equation.
-
-Additional outputs provided by LINREG:
- .Intercept - y-intercept point of the best fit line
- .RSquared - R-Squared (R²), Coefficient of Determination
- .StdDev - Standard Deviation of data over given periods
-
- y = Slope * x + Intercept
-
-Sources:
- https://en.wikipedia.org/wiki/Least_squares
-
- */
-
-public class LINREG_Series : Single_TSeries_Indicator
-{
- public readonly TSeries Intercept = new();
- public readonly TSeries RSquared = new();
- public readonly TSeries StdDev = new();
- private readonly System.Collections.Generic.List _buffer = new();
-
- public LINREG_Series(TSeries source, int period, bool useNaN = false)
- : base(source, period, useNaN)
- {
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
-
- int _len = this._buffer.Count;
-
- // get averages for period
- double sumX = 0;
- double sumY = 0;
-
- for (int p = 0; p < _len; p++)
- {
- sumX += this.Count - _len + 2 + p;
- sumY += _buffer[p];
- }
- double avgX = sumX / _len;
- double avgY = sumY / _len;
-
- // least squares method
- double sumSqX = 0;
- double sumSqY = 0;
- double sumSqXY = 0;
-
- for (int p = 0; p < _len; p++)
- {
- double devX = this.Count - _len + 2 + p - avgX;
- double devY = _buffer[p] - avgY;
-
- sumSqX += devX * devX;
- sumSqY += devY * devY;
- sumSqXY += devX * devY;
- }
-
- double _slope = sumSqXY / sumSqX;
- double _intercept = avgY - (_slope * avgX);
-
- // calculate Standard Deviation and R-Squared
- double stdDevX = Math.Sqrt(sumSqX / _len);
- double stdDevY = Math.Sqrt(sumSqY / _len);
- double _StdDev = stdDevY;
-
- double arrr = (stdDevX * stdDevY != 0) ? sumSqXY / (stdDevX * stdDevY) / _len : 0;
- double _RSquared = arrr * arrr;
-
- var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _slope);
- base.Add(ret, update, _NaN);
-
- ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
- Intercept.Add(ret, update);
-
- ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _StdDev);
- StdDev.Add(ret, update);
-
- ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _RSquared);
- RSquared.Add(ret, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+LINREG: Linear Regression (using Least Square Method)
+ Linear Regression provides a slope of a straight line that is the best approximation of the given set of data.
+ The method of least squares is a standard approach in linear regression analysis to approximate the solution
+ by minimizing the sum of the squares of the residuals made in the results of each individual equation.
+
+Additional outputs provided by LINREG:
+ .Intercept - y-intercept point of the best fit line
+ .RSquared - R-Squared (R²), Coefficient of Determination
+ .StdDev - Standard Deviation of data over given periods
+
+ y = Slope * x + Intercept
+
+Sources:
+ https://en.wikipedia.org/wiki/Least_squares
+
+ */
+
+public class LINREG_Series : Single_TSeries_Indicator
+{
+ public readonly TSeries Intercept = new();
+ public readonly TSeries RSquared = new();
+ public readonly TSeries StdDev = new();
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public LINREG_Series(TSeries source, int period, bool useNaN = false)
+ : base(source, period, useNaN)
+ {
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+
+ int _len = this._buffer.Count;
+
+ // get averages for period
+ double sumX = 0;
+ double sumY = 0;
+
+ for (int p = 0; p < _len; p++)
+ {
+ sumX += this.Count - _len + 2 + p;
+ sumY += _buffer[p];
+ }
+ double avgX = sumX / _len;
+ double avgY = sumY / _len;
+
+ // least squares method
+ double sumSqX = 0;
+ double sumSqY = 0;
+ double sumSqXY = 0;
+
+ for (int p = 0; p < _len; p++)
+ {
+ double devX = this.Count - _len + 2 + p - avgX;
+ double devY = _buffer[p] - avgY;
+
+ sumSqX += devX * devX;
+ sumSqY += devY * devY;
+ sumSqXY += devX * devY;
+ }
+
+ double _slope = sumSqXY / sumSqX;
+ double _intercept = avgY - (_slope * avgX);
+
+ // calculate Standard Deviation and R-Squared
+ double stdDevX = Math.Sqrt(sumSqX / _len);
+ double stdDevY = Math.Sqrt(sumSqY / _len);
+ double _StdDev = stdDevY;
+
+ double arrr = (stdDevX * stdDevY != 0) ? sumSqXY / (stdDevX * stdDevY) / _len : 0;
+ double _RSquared = arrr * arrr;
+
+ var ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _slope);
+ base.Add(ret, update, _NaN);
+
+ ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _intercept);
+ Intercept.Add(ret, update);
+
+ ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _StdDev);
+ StdDev.Add(ret, update);
+
+ ret = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _RSquared);
+ RSquared.Add(ret, update);
+ }
}
\ No newline at end of file
diff --git a/Source/Statistics/MAD_Series.cs b/Calculations/Statistics/MAD_Series.cs
similarity index 100%
rename from Source/Statistics/MAD_Series.cs
rename to Calculations/Statistics/MAD_Series.cs
diff --git a/Source/Statistics/MAPE_Series.cs b/Calculations/Statistics/MAPE_Series.cs
similarity index 100%
rename from Source/Statistics/MAPE_Series.cs
rename to Calculations/Statistics/MAPE_Series.cs
diff --git a/Source/Statistics/MEDIAN_Series.cs b/Calculations/Statistics/MEDIAN_Series.cs
similarity index 100%
rename from Source/Statistics/MEDIAN_Series.cs
rename to Calculations/Statistics/MEDIAN_Series.cs
diff --git a/Source/Statistics/MSE_Series.cs b/Calculations/Statistics/MSE_Series.cs
similarity index 100%
rename from Source/Statistics/MSE_Series.cs
rename to Calculations/Statistics/MSE_Series.cs
diff --git a/Source/Statistics/SDEV_Series.cs b/Calculations/Statistics/SDEV_Series.cs
similarity index 100%
rename from Source/Statistics/SDEV_Series.cs
rename to Calculations/Statistics/SDEV_Series.cs
diff --git a/Source/Statistics/SMAPE_Series.cs b/Calculations/Statistics/SMAPE_Series.cs
similarity index 100%
rename from Source/Statistics/SMAPE_Series.cs
rename to Calculations/Statistics/SMAPE_Series.cs
diff --git a/Source/Statistics/SSDEV_Series.cs b/Calculations/Statistics/SSDEV_Series.cs
similarity index 100%
rename from Source/Statistics/SSDEV_Series.cs
rename to Calculations/Statistics/SSDEV_Series.cs
diff --git a/Source/Statistics/SVAR_Series.cs b/Calculations/Statistics/SVAR_Series.cs
similarity index 97%
rename from Source/Statistics/SVAR_Series.cs
rename to Calculations/Statistics/SVAR_Series.cs
index 5f569081..a83d5deb 100644
--- a/Source/Statistics/SVAR_Series.cs
+++ b/Calculations/Statistics/SVAR_Series.cs
@@ -1,38 +1,38 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-SVAR: Sample Variance
- Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
-
-Sources:
- https://en.wikipedia.org/wiki/Variance
- Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
-
-Remark:
- SVAR is also known as the Unbiased Sample Variance, while VAR (Population Variance) is known as
- the Biased Sample Variance.
-
- */
-
-public class SVAR_Series : Single_TSeries_Indicator
-{
- public SVAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- double _sma = _buffer.Average();
-
- double _svar = 0;
- for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); }
- _svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction
-
- base.Add((TValue.t, _svar), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+SVAR: Sample Variance
+ Sample variance uses Bessel's correction to correct the bias in the estimation of population variance.
+
+Sources:
+ https://en.wikipedia.org/wiki/Variance
+ Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
+
+Remark:
+ SVAR is also known as the Unbiased Sample Variance, while VAR (Population Variance) is known as
+ the Biased Sample Variance.
+
+ */
+
+public class SVAR_Series : Single_TSeries_Indicator
+{
+ public SVAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ double _sma = _buffer.Average();
+
+ double _svar = 0;
+ for (int i = 0; i < this._buffer.Count; i++) { _svar += (this._buffer[i] - _sma) * (this._buffer[i] - _sma); }
+ _svar /= (this._buffer.Count > 1) ? this._buffer.Count - 1 : 1; // Bessel's correction
+
+ base.Add((TValue.t, _svar), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Statistics/VAR_Series.cs b/Calculations/Statistics/VAR_Series.cs
similarity index 96%
rename from Source/Statistics/VAR_Series.cs
rename to Calculations/Statistics/VAR_Series.cs
index 2aebee3b..447ae16f 100644
--- a/Source/Statistics/VAR_Series.cs
+++ b/Calculations/Statistics/VAR_Series.cs
@@ -1,38 +1,38 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-VAR: Population Variance
- Population variance without Bessel's correction
-
-Sources:
- https://en.wikipedia.org/wiki/Variance
- Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
-
-Remark:
- VAR (Population Variance) is also known as a biased Sample Variance. For unbiased
- sample variance use SVAR instead.
-
- */
-
-public class VAR_Series : Single_TSeries_Indicator
-{
- public VAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- double _sma = _buffer.Average();
-
- double _pvar = 0;
- for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
- _pvar /= this._buffer.Count;
-
- base.Add((TValue.t, _pvar), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+VAR: Population Variance
+ Population variance without Bessel's correction
+
+Sources:
+ https://en.wikipedia.org/wiki/Variance
+ Bessel's correction: https://en.wikipedia.org/wiki/Bessel%27s_correction
+
+Remark:
+ VAR (Population Variance) is also known as a biased Sample Variance. For unbiased
+ sample variance use SVAR instead.
+
+ */
+
+public class VAR_Series : Single_TSeries_Indicator
+{
+ public VAR_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ double _sma = _buffer.Average();
+
+ double _pvar = 0;
+ for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
+ _pvar /= this._buffer.Count;
+
+ base.Add((TValue.t, _pvar), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Statistics/WMAPE_Series.cs b/Calculations/Statistics/WMAPE_Series.cs
similarity index 100%
rename from Source/Statistics/WMAPE_Series.cs
rename to Calculations/Statistics/WMAPE_Series.cs
diff --git a/Source/Statistics/ZSCORE_Series.cs b/Calculations/Statistics/ZSCORE_Series.cs
similarity index 97%
rename from Source/Statistics/ZSCORE_Series.cs
rename to Calculations/Statistics/ZSCORE_Series.cs
index 097482d9..fbaf02b9 100644
--- a/Source/Statistics/ZSCORE_Series.cs
+++ b/Calculations/Statistics/ZSCORE_Series.cs
@@ -1,46 +1,46 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-ZSCORE: number of standard deviations from SMA
- Z-score describes a value's relationship to the mean of a series, as measured in
- terms of standard deviations from the mean. If a Z-score is 0, it indicates that
- the data point's score is identical to the mean score. A Z-score of 1.0 would
- indicate a value that is one standard deviation from the mean. Z-scores may be
- positive or negative, with a positive value indicating the score is above the
- mean and a negative score indicating it is below the mean.
-
-Sources:
- https://en.wikipedia.org/wiki/Z-score
- https://www.investopedia.com/terms/z/zscore.asp
-
-Calculation:
- std = std * STDEV(close, length)
- mean = SMA(close, length)
- ZSCORE = (close - mean) / std
-
- */
-
-public class ZSCORE_Series : Single_TSeries_Indicator
-{
- public ZSCORE_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- double _sma = _buffer.Average();
-
- double _pvar = 0;
- for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
- _pvar /= this._buffer.Count;
- double _psdev = Math.Sqrt(_pvar);
- double _zscore = (_psdev == 0) ? double.NaN : (TValue.v - _sma) / _psdev;
-
- base.Add((TValue.t, _zscore), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+ZSCORE: number of standard deviations from SMA
+ Z-score describes a value's relationship to the mean of a series, as measured in
+ terms of standard deviations from the mean. If a Z-score is 0, it indicates that
+ the data point's score is identical to the mean score. A Z-score of 1.0 would
+ indicate a value that is one standard deviation from the mean. Z-scores may be
+ positive or negative, with a positive value indicating the score is above the
+ mean and a negative score indicating it is below the mean.
+
+Sources:
+ https://en.wikipedia.org/wiki/Z-score
+ https://www.investopedia.com/terms/z/zscore.asp
+
+Calculation:
+ std = std * STDEV(close, length)
+ mean = SMA(close, length)
+ ZSCORE = (close - mean) / std
+
+ */
+
+public class ZSCORE_Series : Single_TSeries_Indicator
+{
+ public ZSCORE_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ double _sma = _buffer.Average();
+
+ double _pvar = 0;
+ for (int i = 0; i < _buffer.Count; i++) { _pvar += (_buffer[i] - _sma) * (_buffer[i] - _sma); }
+ _pvar /= this._buffer.Count;
+ double _psdev = Math.Sqrt(_pvar);
+ double _zscore = (_psdev == 0) ? double.NaN : (TValue.v - _sma) / _psdev;
+
+ base.Add((TValue.t, _zscore), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/ALMA_Series.cs b/Calculations/Trends/ALMA_Series.cs
similarity index 97%
rename from Source/Trends/ALMA_Series.cs
rename to Calculations/Trends/ALMA_Series.cs
index 39ff8101..ceb70320 100644
--- a/Source/Trends/ALMA_Series.cs
+++ b/Calculations/Trends/ALMA_Series.cs
@@ -1,63 +1,63 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ALMA: Arnaud Legoux Moving Average
- The ALMA moving average uses the curve of the Normal (Gauss) distribution, which
- can be shifted from 0 to 1. This allows regulating the smoothness and high
- sensitivity of the indicator. Sigma is another parameter that is responsible for
- the shape of the curve coefficients. This moving average reduces lag of the data
- in conjunction with smoothing to reduce noise.
-
-
-Sources:
- https://phemex.com/academy/what-is-arnaud-legoux-moving-averages
- https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/
-
-TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma)
-
- */
-
-public class ALMA_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly double[] _weight;
- private double _norm;
- private readonly double _offset, _sigma;
-
- public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
- : base(source, period, useNaN)
- {
- _offset = offset;
- _sigma = sigma;
- _weight = new double[period];
-
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
-
- if (this._buffer.Count <= _p)
- {
- int _len = this._buffer.Count;
- _norm = 0;
- double _m = _offset * (_len - 1);
- double _s = _len / _sigma;
- for (int i = 0; i < _len; i++)
- {
- double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
- _weight[i] = _wt;
- _norm += _wt;
- }
- }
-
- double _weightedSum = 0;
- for (int i = 0; i < this._buffer.Count; i++)
- { _weightedSum += _weight[i] * _buffer[i]; }
- double _alma = _weightedSum / _norm;
-
- base.Add((TValue.t, _alma), update, _NaN);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+ALMA: Arnaud Legoux Moving Average
+ The ALMA moving average uses the curve of the Normal (Gauss) distribution, which
+ can be shifted from 0 to 1. This allows regulating the smoothness and high
+ sensitivity of the indicator. Sigma is another parameter that is responsible for
+ the shape of the curve coefficients. This moving average reduces lag of the data
+ in conjunction with smoothing to reduce noise.
+
+
+Sources:
+ https://phemex.com/academy/what-is-arnaud-legoux-moving-averages
+ https://www.prorealcode.com/prorealtime-indicators/alma-arnaud-legoux-moving-average/
+
+TODO: Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma)
+
+ */
+
+public class ALMA_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double[] _weight;
+ private double _norm;
+ private readonly double _offset, _sigma;
+
+ public ALMA_Series(TSeries source, int period, double offset = 0.85, double sigma = 6.0, bool useNaN = false)
+ : base(source, period, useNaN)
+ {
+ _offset = offset;
+ _sigma = sigma;
+ _weight = new double[period];
+
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+
+ if (this._buffer.Count <= _p)
+ {
+ int _len = this._buffer.Count;
+ _norm = 0;
+ double _m = _offset * (_len - 1);
+ double _s = _len / _sigma;
+ for (int i = 0; i < _len; i++)
+ {
+ double _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
+ _weight[i] = _wt;
+ _norm += _wt;
+ }
+ }
+
+ double _weightedSum = 0;
+ for (int i = 0; i < this._buffer.Count; i++)
+ { _weightedSum += _weight[i] * _buffer[i]; }
+ double _alma = _weightedSum / _norm;
+
+ base.Add((TValue.t, _alma), update, _NaN);
+ }
+}
diff --git a/Source/Trends/DEMA_Series.cs b/Calculations/Trends/DEMA_Series.cs
similarity index 96%
rename from Source/Trends/DEMA_Series.cs
rename to Calculations/Trends/DEMA_Series.cs
index bc874e9e..3aaf2560 100644
--- a/Source/Trends/DEMA_Series.cs
+++ b/Calculations/Trends/DEMA_Series.cs
@@ -1,75 +1,75 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-using System.Runtime.CompilerServices;
-
-/*
-DEMA: Double Exponential Moving Average
- DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
-
-Sources:
- https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
-
-Remark:
- ema1 = EMA(close, length)
- ema2 = EMA(ema1, length)
- DEMA = 2 * ema1 - ema2
-
- */
-
-public class DEMA_Series : Single_TSeries_Indicator
-{
- private readonly double _k;
- private int _len;
- private readonly bool _useSMA;
- private double _sum, _lastsum, _lastlastsum;
- private double _lastema1, _lastlastema1;
- private double _lastema2, _lastlastema2;
-
- public DEMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN)
- {
- _k = 2.0 / (_p + 1);
- _len = 0;
- _useSMA = useSMA;
- _sum = _lastema1 = _lastema2 =0;
- if (_data.Count > 0) { base.Add(_data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- if (update) {
- _lastsum = _lastlastsum;
- _lastema1 = _lastlastema1;
- _lastema2 = _lastlastema2;
- }
- else {
- _lastlastsum = _lastsum;
- _lastlastema1 = _lastema1;
- _lastlastema2 = _lastema2;
- _len++;
- }
-
- double _ema1, _ema2, _dema;
- if (this.Count == 0) {
- _ema1 = _ema2 = _sum = TValue.v;
- }
- else if (_len <= _period && _useSMA && _period != 0) {
- _sum += TValue.v;
- if (_period != 0 && _len > _period) {
- _sum -= (_data[base.Count - _period - (update ? 1 : 0)].v);
- }
- _ema1 = _sum / Math.Min(_len, _period);
- _ema2 = _ema1;
- }
- else {
- _ema1 = (TValue.v - _lastema1) * _k + _lastema1;
- _ema2 = (_ema1 - _lastema2) * _k + _lastema2;
- }
- _dema = 2*_ema1 - _ema2;
-
- _lastema1 = _ema1;
- _lastema2 = _ema2;
-
- base.Add((TValue.t, _dema), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+/*
+DEMA: Double Exponential Moving Average
+ DEMA uses EMA(EMA()) to calculate smoother Exponential moving average.
+
+Sources:
+ https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/double-exponential-moving-average-dema/
+
+Remark:
+ ema1 = EMA(close, length)
+ ema2 = EMA(ema1, length)
+ DEMA = 2 * ema1 - ema2
+
+ */
+
+public class DEMA_Series : Single_TSeries_Indicator
+{
+ private readonly double _k;
+ private int _len;
+ private readonly bool _useSMA;
+ private double _sum, _lastsum, _lastlastsum;
+ private double _lastema1, _lastlastema1;
+ private double _lastema2, _lastlastema2;
+
+ public DEMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN)
+ {
+ _k = 2.0 / (_p + 1);
+ _len = 0;
+ _useSMA = useSMA;
+ _sum = _lastema1 = _lastema2 =0;
+ if (_data.Count > 0) { base.Add(_data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ if (update) {
+ _lastsum = _lastlastsum;
+ _lastema1 = _lastlastema1;
+ _lastema2 = _lastlastema2;
+ }
+ else {
+ _lastlastsum = _lastsum;
+ _lastlastema1 = _lastema1;
+ _lastlastema2 = _lastema2;
+ _len++;
+ }
+
+ double _ema1, _ema2, _dema;
+ if (this.Count == 0) {
+ _ema1 = _ema2 = _sum = TValue.v;
+ }
+ else if (_len <= _period && _useSMA && _period != 0) {
+ _sum += TValue.v;
+ if (_period != 0 && _len > _period) {
+ _sum -= (_data[base.Count - _period - (update ? 1 : 0)].v);
+ }
+ _ema1 = _sum / Math.Min(_len, _period);
+ _ema2 = _ema1;
+ }
+ else {
+ _ema1 = (TValue.v - _lastema1) * _k + _lastema1;
+ _ema2 = (_ema1 - _lastema2) * _k + _lastema2;
+ }
+ _dema = 2*_ema1 - _ema2;
+
+ _lastema1 = _ema1;
+ _lastema2 = _ema2;
+
+ base.Add((TValue.t, _dema), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/DWMA_Series.cs b/Calculations/Trends/DWMA_Series.cs
similarity index 96%
rename from Source/Trends/DWMA_Series.cs
rename to Calculations/Trends/DWMA_Series.cs
index ebda7418..7cdb0954 100644
--- a/Source/Trends/DWMA_Series.cs
+++ b/Calculations/Trends/DWMA_Series.cs
@@ -1,35 +1,35 @@
-namespace QuanTAlib;
-using System;
-
-/*
-DWMA: Double Weighted Moving Average
- The weights are decreasing over the period with p^2 decay
- and the most recent data has the heaviest weight.
-
- */
-
-public class DWMA_Series : Single_TSeries_Indicator {
- public DWMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
- for (int i = 0; i < this._p; i++) {
- double _weight = (i + 1) * (i + 1);
- this._weights.Add(_weight);
- }
-
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer1 = new();
- private readonly System.Collections.Generic.List _weights = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update) {
- Add_Replace_Trim(_buffer1, TValue.v, _p, update);
- double _wma1 = 0;
- double _wsum = 0;
- for (int i = 0; i < _buffer1.Count; i++) {
- _wma1 += _buffer1[i] * this._weights[i];
- _wsum += this._weights[i];
- }
- _wma1 /= _wsum;
-
- base.Add((TValue.t, _wma1), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+DWMA: Double Weighted Moving Average
+ The weights are decreasing over the period with p^2 decay
+ and the most recent data has the heaviest weight.
+
+ */
+
+public class DWMA_Series : Single_TSeries_Indicator {
+ public DWMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
+ for (int i = 0; i < this._p; i++) {
+ double _weight = (i + 1) * (i + 1);
+ this._weights.Add(_weight);
+ }
+
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer1 = new();
+ private readonly System.Collections.Generic.List _weights = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update) {
+ Add_Replace_Trim(_buffer1, TValue.v, _p, update);
+ double _wma1 = 0;
+ double _wsum = 0;
+ for (int i = 0; i < _buffer1.Count; i++) {
+ _wma1 += _buffer1[i] * this._weights[i];
+ _wsum += this._weights[i];
+ }
+ _wma1 /= _wsum;
+
+ base.Add((TValue.t, _wma1), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/EMA_Series.cs b/Calculations/Trends/EMA_Series.cs
similarity index 97%
rename from Source/Trends/EMA_Series.cs
rename to Calculations/Trends/EMA_Series.cs
index 6a3011ab..6fe35b19 100644
--- a/Source/Trends/EMA_Series.cs
+++ b/Calculations/Trends/EMA_Series.cs
@@ -1,71 +1,71 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-EMA: Exponential Moving Average
- EMA needs very short history buffer and calculates the EMA value using just the
- previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
-
-Sources:
- https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
- https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
- https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
-
-Issues:
- There is no consensus what the first EMA value should be - a zero, a first
- datapoint, or an average of the initial Period bars. All three starting methods
- converge within 20+ bars to the same moving average. Most implementations (including this one)
- use SMA() for the first Period bars as a seeding value for EMA.
-
- */
-
-public class EMA_Series : Single_TSeries_Indicator {
- private double _k;
- private double _lastema, _lastlastema;
- private double _sum, _oldsum;
- private int _len;
- private readonly bool _useSMA;
-
- public EMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN) {
- _k = 2.0 / (_p + 1);
- _sum = _oldsum = _lastema = _lastlastema = 0;
- _len = 0;
- _useSMA = useSMA;
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update) {
-
- if (update) { _lastema = _lastlastema; _sum = _oldsum; }
- else { _lastlastema = _lastema; _oldsum = _sum; _len++; }
-
- double _ema = 0;
- // when period = 0, create cumulative/additive series where _k is progressively larger
- if (_period == 0) { _k = 2.0 / (_len + 1); }
-
- // the first value of the series
- if (this.Count == 0) {
- _ema = _sum = TValue.v;
- }
- // if SMA is used for seeding, calculate SMA within period
- else if (_len <= _period && _useSMA && _period != 0) {
- _sum += TValue.v;
- if (_period != 0 && _len > _period) {
- _sum -= (_data[base.Count - _period - (update ? 1 : 0)].v);
- }
- _ema = _sum / Math.Min(_len, _period);
- }
- // calculate EMA out from last EMA and factor k
- else {
- _ema = _k * (TValue.v - _lastema) + _lastema;
- }
- _lastema = _ema;
-
- base.Add((TValue.t, _ema), update, _NaN);
- }
- public void Reset() {
- _sum = _oldsum = _lastema = _lastlastema = 0;
- _len = 0;
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+EMA: Exponential Moving Average
+ EMA needs very short history buffer and calculates the EMA value using just the
+ previous EMA value. The weight of the new datapoint (k) is k = 2 / (period-1)
+
+Sources:
+ https://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
+ https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp
+ https://blog.fugue88.ws/archives/2017-01/The-correct-way-to-start-an-Exponential-Moving-Average-EMA
+
+Issues:
+ There is no consensus what the first EMA value should be - a zero, a first
+ datapoint, or an average of the initial Period bars. All three starting methods
+ converge within 20+ bars to the same moving average. Most implementations (including this one)
+ use SMA() for the first Period bars as a seeding value for EMA.
+
+ */
+
+public class EMA_Series : Single_TSeries_Indicator {
+ private double _k;
+ private double _lastema, _lastlastema;
+ private double _sum, _oldsum;
+ private int _len;
+ private readonly bool _useSMA;
+
+ public EMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN) {
+ _k = 2.0 / (_p + 1);
+ _sum = _oldsum = _lastema = _lastlastema = 0;
+ _len = 0;
+ _useSMA = useSMA;
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update) {
+
+ if (update) { _lastema = _lastlastema; _sum = _oldsum; }
+ else { _lastlastema = _lastema; _oldsum = _sum; _len++; }
+
+ double _ema = 0;
+ // when period = 0, create cumulative/additive series where _k is progressively larger
+ if (_period == 0) { _k = 2.0 / (_len + 1); }
+
+ // the first value of the series
+ if (this.Count == 0) {
+ _ema = _sum = TValue.v;
+ }
+ // if SMA is used for seeding, calculate SMA within period
+ else if (_len <= _period && _useSMA && _period != 0) {
+ _sum += TValue.v;
+ if (_period != 0 && _len > _period) {
+ _sum -= (_data[base.Count - _period - (update ? 1 : 0)].v);
+ }
+ _ema = _sum / Math.Min(_len, _period);
+ }
+ // calculate EMA out from last EMA and factor k
+ else {
+ _ema = _k * (TValue.v - _lastema) + _lastema;
+ }
+ _lastema = _ema;
+
+ base.Add((TValue.t, _ema), update, _NaN);
+ }
+ public void Reset() {
+ _sum = _oldsum = _lastema = _lastlastema = 0;
+ _len = 0;
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/FMA_Series.cs b/Calculations/Trends/FMA_Series.cs
similarity index 100%
rename from Source/Trends/FMA_Series.cs
rename to Calculations/Trends/FMA_Series.cs
diff --git a/Source/Trends/HEMA_Series.cs b/Calculations/Trends/HEMA_Series.cs
similarity index 97%
rename from Source/Trends/HEMA_Series.cs
rename to Calculations/Trends/HEMA_Series.cs
index 3f1678f5..dcb9d560 100644
--- a/Source/Trends/HEMA_Series.cs
+++ b/Calculations/Trends/HEMA_Series.cs
@@ -1,57 +1,57 @@
-namespace QuanTAlib;
-using System;
-
-/*
-HEMA: Hull-EMA Moving Average - a hybrid indicator
- Modified HUll Moving Average; instead of using WMA (Weighted MA) for calculation,
- HEMA uses EMA for Hull's formula:
-
-EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
-EMA2 = EMA(n) of price - where k = 3/(n+1)
-Raw HMA = (2 * EMA1) - EMA2
-EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
-
- */
-
-public class HEMA_Series : Single_TSeries_Indicator
-{
- public HEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- this._k1 = 4 / ((period * 0.5) + 1);
- this._k2 = 3 / (double)(period + 1);
- this._k3 = 2 / (Math.Sqrt(period) + 1);
- this._lastema1 = this._lastlastema1 = double.NaN;
- this._lastema2 = this._lastlastema2 = double.NaN;
- this._lastema3 = this._lastlastema3 = double.NaN;
-
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly double _k1, _k2, _k3;
- private double _lastema1, _lastlastema1;
- private double _lastema2, _lastlastema2;
- private double _lastema3, _lastlastema3;
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- if (update)
- {
- this._lastema1 = this._lastlastema1;
- this._lastema2 = this._lastlastema2;
- this._lastema3 = this._lastlastema3;
- }
- double _ema1 = System.Double.IsNaN(this._lastema1) ? TValue.v : TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
- double _ema2 = System.Double.IsNaN(this._lastema2) ? TValue.v : TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
-
- double _rawhema = (2 * _ema1) - _ema2;
- double _ema3 = System.Double.IsNaN(this._lastema3) ? _rawhema : _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
-
- this._lastlastema1 = this._lastema1;
- this._lastlastema2 = this._lastema2;
- this._lastlastema3 = this._lastema3;
- this._lastema1 = _ema1;
- this._lastema2 = _ema2;
- this._lastema3 = _ema3;
-
- base.Add((TValue.t, _ema3), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+HEMA: Hull-EMA Moving Average - a hybrid indicator
+ Modified HUll Moving Average; instead of using WMA (Weighted MA) for calculation,
+ HEMA uses EMA for Hull's formula:
+
+EMA1 = EMA(n/2) of price - where k = 4/(n/2 +1)
+EMA2 = EMA(n) of price - where k = 3/(n+1)
+Raw HMA = (2 * EMA1) - EMA2
+EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
+
+ */
+
+public class HEMA_Series : Single_TSeries_Indicator
+{
+ public HEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ this._k1 = 4 / ((period * 0.5) + 1);
+ this._k2 = 3 / (double)(period + 1);
+ this._k3 = 2 / (Math.Sqrt(period) + 1);
+ this._lastema1 = this._lastlastema1 = double.NaN;
+ this._lastema2 = this._lastlastema2 = double.NaN;
+ this._lastema3 = this._lastlastema3 = double.NaN;
+
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly double _k1, _k2, _k3;
+ private double _lastema1, _lastlastema1;
+ private double _lastema2, _lastlastema2;
+ private double _lastema3, _lastlastema3;
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ if (update)
+ {
+ this._lastema1 = this._lastlastema1;
+ this._lastema2 = this._lastlastema2;
+ this._lastema3 = this._lastlastema3;
+ }
+ double _ema1 = System.Double.IsNaN(this._lastema1) ? TValue.v : TValue.v * this._k1 + this._lastema1 * (1 - this._k1);
+ double _ema2 = System.Double.IsNaN(this._lastema2) ? TValue.v : TValue.v * this._k2 + this._lastema2 * (1 - this._k2);
+
+ double _rawhema = (2 * _ema1) - _ema2;
+ double _ema3 = System.Double.IsNaN(this._lastema3) ? _rawhema : _rawhema * this._k3 + this._lastema3 * (1 - this._k3);
+
+ this._lastlastema1 = this._lastema1;
+ this._lastlastema2 = this._lastema2;
+ this._lastlastema3 = this._lastema3;
+ this._lastema1 = _ema1;
+ this._lastema2 = _ema2;
+ this._lastema3 = _ema3;
+
+ base.Add((TValue.t, _ema3), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/HMA_Series.cs b/Calculations/Trends/HMA_Series.cs
similarity index 96%
rename from Source/Trends/HMA_Series.cs
rename to Calculations/Trends/HMA_Series.cs
index ad6f30f8..8a522fba 100644
--- a/Source/Trends/HMA_Series.cs
+++ b/Calculations/Trends/HMA_Series.cs
@@ -1,119 +1,119 @@
-namespace QuanTAlib;
-using System;
-
-/*
-HMA: Hull Moving Average
- Developed by Alan Hull, an extremely fast and smooth moving average; almost
- eliminates lag altogether and manages to improve smoothing at the same time.
-
-Sources:
- https://alanhull.com/hull-moving-average
- https://school.stockcharts.com/doku.php?id=technical_indicators:hull_moving_average
-
-WMA1 = WMA(n/2) of price
-WMA2 = WMA(n) of price
-Raw HMA = (2 * WMA1) - WMA2
-HMA = WMA(sqrt(n)) of Raw HMA
-
- */
-
-public class HMA_Series : TSeries
-{
- private readonly int _p;
- private readonly bool _NaN;
- private readonly TSeries _data;
- private double _wma1, _wma2;
- private readonly System.Collections.Generic.List _buf1 = new();
- private readonly System.Collections.Generic.List _buf2 = new();
- private readonly System.Collections.Generic.List _buf3 = new();
- private readonly System.Collections.Generic.List _weights = new();
-
- public HMA_Series(TSeries source, int period, bool useNaN = false)
- {
- this._p = period;
- this._data = source;
- this._NaN = useNaN;
- for (int i = 0; i < this._p; i++)
- {
- this._weights.Add(i + 1);
- }
-
- source.Pub += this.Sub;
- if (source.Count > 0)
- {
- for (int i = 0; i < source.Count; i++)
- {
- this.Add(source[i], false);
- }
- }
- }
- public new void Add((System.DateTime t, double v) data, bool update = false)
- {
- if (update)
- {
- this._buf1[this._buf1.Count - 1] = data.v;
- this._buf2[this._buf2.Count - 1] = data.v;
- }
- else
- {
- this._buf1.Add(data.v);
- this._buf2.Add(data.v);
- }
- if (this._buf1.Count > (int)((double)this._p / 2))
- {
- this._buf1.RemoveAt(0);
- }
- if (this._buf2.Count > this._p)
- {
- this._buf2.RemoveAt(0);
- }
-
- this._wma1 = 0;
- for (int i = 0; i < this._buf1.Count; i++)
- {
- this._wma1 += this._buf1[i] * this._weights[i];
- }
- this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5;
-
- this._wma2 = 0;
- for (int i = 0; i < this._buf2.Count; i++)
- {
- this._wma2 += this._buf2[i] * this._weights[i];
- }
- this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5;
-
- if (update)
- {
- this._buf3[this._buf3.Count - 1] = 2 * this._wma1 - this._wma2;
- }
- else
- {
- this._buf3.Add(2 * this._wma1 - this._wma2);
- }
-
- if (this._buf3.Count > (int)Math.Sqrt(this._p))
- {
- this._buf3.RemoveAt(0);
- }
-
- double _hma = 0;
- for (int i = 0; i < this._buf3.Count; i++)
- {
- _hma += this._buf3[i] * this._weights[i];
- }
-
- _hma /= (this._buf3.Count * (this._buf3.Count + 1)) * 0.5;
-
- (System.DateTime t, double v) result =
- (data.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _hma);
- base.Add(result, update);
- }
- public void Add(bool update = false)
- {
- this.Add(this._data[this._data.Count - 1], update);
- }
- public new void Sub(object source, TSeriesEventArgs e)
- {
- this.Add(this._data[this._data.Count - 1], e.update);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+HMA: Hull Moving Average
+ Developed by Alan Hull, an extremely fast and smooth moving average; almost
+ eliminates lag altogether and manages to improve smoothing at the same time.
+
+Sources:
+ https://alanhull.com/hull-moving-average
+ https://school.stockcharts.com/doku.php?id=technical_indicators:hull_moving_average
+
+WMA1 = WMA(n/2) of price
+WMA2 = WMA(n) of price
+Raw HMA = (2 * WMA1) - WMA2
+HMA = WMA(sqrt(n)) of Raw HMA
+
+ */
+
+public class HMA_Series : TSeries
+{
+ private readonly int _p;
+ private readonly bool _NaN;
+ private readonly TSeries _data;
+ private double _wma1, _wma2;
+ private readonly System.Collections.Generic.List _buf1 = new();
+ private readonly System.Collections.Generic.List _buf2 = new();
+ private readonly System.Collections.Generic.List _buf3 = new();
+ private readonly System.Collections.Generic.List _weights = new();
+
+ public HMA_Series(TSeries source, int period, bool useNaN = false)
+ {
+ this._p = period;
+ this._data = source;
+ this._NaN = useNaN;
+ for (int i = 0; i < this._p; i++)
+ {
+ this._weights.Add(i + 1);
+ }
+
+ source.Pub += this.Sub;
+ if (source.Count > 0)
+ {
+ for (int i = 0; i < source.Count; i++)
+ {
+ this.Add(source[i], false);
+ }
+ }
+ }
+ public new void Add((System.DateTime t, double v) data, bool update = false)
+ {
+ if (update)
+ {
+ this._buf1[this._buf1.Count - 1] = data.v;
+ this._buf2[this._buf2.Count - 1] = data.v;
+ }
+ else
+ {
+ this._buf1.Add(data.v);
+ this._buf2.Add(data.v);
+ }
+ if (this._buf1.Count > (int)((double)this._p / 2))
+ {
+ this._buf1.RemoveAt(0);
+ }
+ if (this._buf2.Count > this._p)
+ {
+ this._buf2.RemoveAt(0);
+ }
+
+ this._wma1 = 0;
+ for (int i = 0; i < this._buf1.Count; i++)
+ {
+ this._wma1 += this._buf1[i] * this._weights[i];
+ }
+ this._wma1 /= (this._buf1.Count * (this._buf1.Count + 1)) * 0.5;
+
+ this._wma2 = 0;
+ for (int i = 0; i < this._buf2.Count; i++)
+ {
+ this._wma2 += this._buf2[i] * this._weights[i];
+ }
+ this._wma2 /= (this._buf2.Count * (this._buf2.Count + 1)) * 0.5;
+
+ if (update)
+ {
+ this._buf3[this._buf3.Count - 1] = 2 * this._wma1 - this._wma2;
+ }
+ else
+ {
+ this._buf3.Add(2 * this._wma1 - this._wma2);
+ }
+
+ if (this._buf3.Count > (int)Math.Sqrt(this._p))
+ {
+ this._buf3.RemoveAt(0);
+ }
+
+ double _hma = 0;
+ for (int i = 0; i < this._buf3.Count; i++)
+ {
+ _hma += this._buf3[i] * this._weights[i];
+ }
+
+ _hma /= (this._buf3.Count * (this._buf3.Count + 1)) * 0.5;
+
+ (System.DateTime t, double v) result =
+ (data.t, (this.Count < this._p - 1 && this._NaN) ? double.NaN : _hma);
+ base.Add(result, update);
+ }
+ public void Add(bool update = false)
+ {
+ this.Add(this._data[this._data.Count - 1], update);
+ }
+ public new void Sub(object source, TSeriesEventArgs e)
+ {
+ this.Add(this._data[this._data.Count - 1], e.update);
+ }
+}
diff --git a/Source/Trends/HWMA_Series.cs b/Calculations/Trends/HWMA_Series.cs
similarity index 100%
rename from Source/Trends/HWMA_Series.cs
rename to Calculations/Trends/HWMA_Series.cs
diff --git a/Source/Trends/JMA_Series.cs b/Calculations/Trends/JMA_Series.cs
similarity index 97%
rename from Source/Trends/JMA_Series.cs
rename to Calculations/Trends/JMA_Series.cs
index 0ce50524..09cdeeb3 100644
--- a/Source/Trends/JMA_Series.cs
+++ b/Calculations/Trends/JMA_Series.cs
@@ -1,125 +1,125 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-JMA: Jurik Moving Average
- Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
- underlying activity. It has extremely low lag, is very smooth and is responsive
- to market gaps.
-
-Sources:
- https://c.mql5.com/forextsd/forum/164/jurik_1.pdf
- https://www.prorealcode.com/prorealtime-indicators/jurik-volatility-bands/
-
-Issues:
- Real JMA algorithm is not published and this formula is derived through
- deduction and reverse analysis of JMA behavior. It is really close, but not
- exact - published JMA tests against JMA.CSV fail with small deviation. The
- original algo is slightly different, yet this approximation is close enough.
-
-
-*/
-public class JMA_Series : Single_TSeries_Indicator {
- private readonly System.Collections.Generic.List volty_short = new();
- private readonly System.Collections.Generic.List vsum_buff = new();
- private readonly double pr;
- public TSeries mma1 { get; }
- public TSeries mma2 { get; }
-
- private double upperBand, lowerBand, vsum, Kv, del1, del2;
- private double prev_ma1, prev_det0, prev_det1, prev_vsum, prev_jma;
- private double p_upperBand, p_lowerBand, p_Kv, p_prev_ma1, p_prev_det0, p_prev_det1, p_prev_vsum, p_prev_jma;
- private readonly int _voltyS, _voltyL;
-
- public JMA_Series(TSeries source, int period, double phase = 0.0, int vshort = 10, int vlong = 65, bool useNaN = false) : base(source, period, useNaN) {
- 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; }
- _voltyS = vshort;
- _voltyL = vlong;
- mma1 = new();
- mma2 = new();
-
- if (base._data.Count > 0) { base.Add(base._data); }
- }
-
- public override void Add((System.DateTime t, double v) TValue, bool update) {
- if (this.Count == 0) { prev_ma1 = prev_jma = TValue.v; }
- if (update) {
- upperBand = p_upperBand;
- lowerBand = p_lowerBand;
- Kv = p_Kv;
- prev_vsum = p_prev_vsum;
- prev_ma1 = p_prev_ma1;
- prev_det0 = p_prev_det0;
- prev_det1 = p_prev_det1;
- prev_jma = p_prev_jma;
- }
- else {
- p_upperBand = upperBand;
- p_lowerBand = lowerBand;
- p_Kv = Kv;
- p_prev_vsum = prev_vsum;
- p_prev_ma1 = prev_ma1;
- p_prev_det0 = prev_det0;
- p_prev_det1 = prev_det1;
- p_prev_jma = prev_jma;
- }
-
- // from Tvalue to volty
- del1 = TValue.v - upperBand;
- del2 = TValue.v - lowerBand;
- upperBand = (del1 > 0) ? TValue.v : TValue.v - (Kv * del1);
- lowerBand = (del2 < 0) ? TValue.v : TValue.v - (Kv * del2);
- double volty = 0;
- if (Math.Abs(del1) > Math.Abs(del2)) { volty = Math.Abs(del1); }
- if (Math.Abs(del1) < Math.Abs(del2)) { volty = Math.Abs(del2); }
-
- //// from volty to avolty
- if (update) { volty_short[volty_short.Count - 1] = volty; }
- else { volty_short.Add(volty); }
- if (volty_short.Count > _voltyS) { volty_short.RemoveAt(0); }
- vsum = prev_vsum + 0.1 * (volty - volty_short.First());
- prev_vsum = vsum;
- if (update) { vsum_buff[vsum_buff.Count - 1] = vsum; }
- else { vsum_buff.Add(vsum); }
- if (vsum_buff.Count > _voltyL) { vsum_buff.RemoveAt(0); }
- double avolty = 0;
- for (int i = 0; i < vsum_buff.Count; i++) { avolty += vsum_buff[i]; }
- avolty /= vsum_buff.Count;
-
- /// from avolty to rolty
- double rvolty = (avolty != 0) ? volty / avolty : 0;
- double len1 = (Math.Log(Math.Sqrt(_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; }
-
- //// from rvolty to second smoothing
- double pow2 = Math.Pow(rvolty, pow1);
- double beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2);
- Kv = Math.Pow(beta, Math.Sqrt(pow2));
- double alpha = Math.Pow(beta, pow2);
- double ma1 = (1 - alpha) * TValue.v + alpha * prev_ma1;
- prev_ma1 = ma1;
- mma1.Add(ma1);
-
- double det0 = (1 - beta) * (TValue.v - ma1) + beta * prev_det0;
- prev_det0 = det0;
- double ma2 = ma1 + pr * det0;
- mma2.Add(ma2);
-
- double det1 = ((1 - alpha) * (1 - alpha) * (ma2 - prev_jma)) + (alpha * alpha * prev_det1);
- prev_det1 = det1;
- double jma = prev_jma + det1;
- prev_jma = jma;
-
- base.Add((TValue.t, jma), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+JMA: Jurik Moving Average
+ Mark Jurik's Moving Average (JMA) attempts to eliminate noise to see the
+ underlying activity. It has extremely low lag, is very smooth and is responsive
+ to market gaps.
+
+Sources:
+ https://c.mql5.com/forextsd/forum/164/jurik_1.pdf
+ https://www.prorealcode.com/prorealtime-indicators/jurik-volatility-bands/
+
+Issues:
+ Real JMA algorithm is not published and this formula is derived through
+ deduction and reverse analysis of JMA behavior. It is really close, but not
+ exact - published JMA tests against JMA.CSV fail with small deviation. The
+ original algo is slightly different, yet this approximation is close enough.
+
+
+*/
+public class JMA_Series : Single_TSeries_Indicator {
+ private readonly System.Collections.Generic.List volty_short = new();
+ private readonly System.Collections.Generic.List vsum_buff = new();
+ private readonly double pr;
+ public TSeries mma1 { get; }
+ public TSeries mma2 { get; }
+
+ private double upperBand, lowerBand, vsum, Kv, del1, del2;
+ private double prev_ma1, prev_det0, prev_det1, prev_vsum, prev_jma;
+ private double p_upperBand, p_lowerBand, p_Kv, p_prev_ma1, p_prev_det0, p_prev_det1, p_prev_vsum, p_prev_jma;
+ private readonly int _voltyS, _voltyL;
+
+ public JMA_Series(TSeries source, int period, double phase = 0.0, int vshort = 10, int vlong = 65, bool useNaN = false) : base(source, period, useNaN) {
+ 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; }
+ _voltyS = vshort;
+ _voltyL = vlong;
+ mma1 = new();
+ mma2 = new();
+
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update) {
+ if (this.Count == 0) { prev_ma1 = prev_jma = TValue.v; }
+ if (update) {
+ upperBand = p_upperBand;
+ lowerBand = p_lowerBand;
+ Kv = p_Kv;
+ prev_vsum = p_prev_vsum;
+ prev_ma1 = p_prev_ma1;
+ prev_det0 = p_prev_det0;
+ prev_det1 = p_prev_det1;
+ prev_jma = p_prev_jma;
+ }
+ else {
+ p_upperBand = upperBand;
+ p_lowerBand = lowerBand;
+ p_Kv = Kv;
+ p_prev_vsum = prev_vsum;
+ p_prev_ma1 = prev_ma1;
+ p_prev_det0 = prev_det0;
+ p_prev_det1 = prev_det1;
+ p_prev_jma = prev_jma;
+ }
+
+ // from Tvalue to volty
+ del1 = TValue.v - upperBand;
+ del2 = TValue.v - lowerBand;
+ upperBand = (del1 > 0) ? TValue.v : TValue.v - (Kv * del1);
+ lowerBand = (del2 < 0) ? TValue.v : TValue.v - (Kv * del2);
+ double volty = 0;
+ if (Math.Abs(del1) > Math.Abs(del2)) { volty = Math.Abs(del1); }
+ if (Math.Abs(del1) < Math.Abs(del2)) { volty = Math.Abs(del2); }
+
+ //// from volty to avolty
+ if (update) { volty_short[volty_short.Count - 1] = volty; }
+ else { volty_short.Add(volty); }
+ if (volty_short.Count > _voltyS) { volty_short.RemoveAt(0); }
+ vsum = prev_vsum + 0.1 * (volty - volty_short.First());
+ prev_vsum = vsum;
+ if (update) { vsum_buff[vsum_buff.Count - 1] = vsum; }
+ else { vsum_buff.Add(vsum); }
+ if (vsum_buff.Count > _voltyL) { vsum_buff.RemoveAt(0); }
+ double avolty = 0;
+ for (int i = 0; i < vsum_buff.Count; i++) { avolty += vsum_buff[i]; }
+ avolty /= vsum_buff.Count;
+
+ /// from avolty to rolty
+ double rvolty = (avolty != 0) ? volty / avolty : 0;
+ double len1 = (Math.Log(Math.Sqrt(_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; }
+
+ //// from rvolty to second smoothing
+ double pow2 = Math.Pow(rvolty, pow1);
+ double beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2);
+ Kv = Math.Pow(beta, Math.Sqrt(pow2));
+ double alpha = Math.Pow(beta, pow2);
+ double ma1 = (1 - alpha) * TValue.v + alpha * prev_ma1;
+ prev_ma1 = ma1;
+ mma1.Add(ma1);
+
+ double det0 = (1 - beta) * (TValue.v - ma1) + beta * prev_det0;
+ prev_det0 = det0;
+ double ma2 = ma1 + pr * det0;
+ mma2.Add(ma2);
+
+ double det1 = ((1 - alpha) * (1 - alpha) * (ma2 - prev_jma)) + (alpha * alpha * prev_det1);
+ prev_det1 = det1;
+ double jma = prev_jma + det1;
+ prev_jma = jma;
+
+ base.Add((TValue.t, jma), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/KAMA_Series.cs b/Calculations/Trends/KAMA_Series.cs
similarity index 97%
rename from Source/Trends/KAMA_Series.cs
rename to Calculations/Trends/KAMA_Series.cs
index 812fa6c2..808ce8c7 100644
--- a/Source/Trends/KAMA_Series.cs
+++ b/Calculations/Trends/KAMA_Series.cs
@@ -1,64 +1,64 @@
-namespace QuanTAlib;
-using System;
-
-/*
-KAMA: Kaufman's Adaptive Moving Average
- Created in 1988 by American quantitative finance theorist Perry J. Kaufman and is known as
- Kaufman's Adaptive Moving Average (KAMA). Even though the method was developed as early as 1972,
- it was not until the popular book titled "Trading Systems and Methods" that it was made widely
- available to the public. Unlike other conventional moving averages systems, the Kaufman's Adaptive
- Moving Average, considers market volatility apart from price fluctuations.
-
- KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
-
-Sources:
- https://www.tutorialspoint.com/kaufman-s-adaptive-moving-average-kama-formula-and-how-does-it-work
- https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/kaufmans-adaptive-moving-average-kama/
- https://www.technicalindicators.net/indicators-technical-analysis/152-kama-kaufman-adaptive-moving-average
-
-Remark:
- If useNaN:true argument is provided, KAMA starts calculating values from [period] bar onwards.
- Without useNaN argument (default setting), KAMA starts calculating values from bar 1 - and yields
- slightly different results for the first 50 bars - and then converges with the other one.
-
- */
-
-public class KAMA_Series : Single_TSeries_Indicator
-{
- private readonly double _scFast, _scSlow;
- private readonly System.Collections.Generic.List _buffer = new();
- private double _lastkama = double.NaN;
- private double _lastlastkama;
-
- public KAMA_Series(TSeries source, int period, int fast = 2, int slow= 30, bool useNaN = false) : base(source, period, useNaN) {
- _scFast = 2.0 / (fast+1);
- _scSlow = 2.0 / (slow+1);
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- if (update){
- _buffer[_buffer.Count - 1] = TValue.v;
- _lastkama = _lastlastkama;
- }
- else {
- _buffer.Add(TValue.v);
- _lastlastkama = _lastkama;
- }
- if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
-
- double _kama = 0;
- if (this.Count < this._p) { _kama = TValue.v; }
- else {
- double _change = Math.Abs(_buffer[_buffer.Count - 1] - _buffer[(_buffer.Count > _p + 1) ? 1 : 0]);
- double _sumpv = 0;
- for (int i = 1; i < _buffer.Count; i++)
- { _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]); }
- double _er = (_sumpv == 0) ? 0 : _change / _sumpv;
- double _sc = (_er * (_scFast - _scSlow)) + _scSlow;
- _kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama)));
- }
- _lastkama = _kama;
- base.Add((TValue.t, _kama), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+KAMA: Kaufman's Adaptive Moving Average
+ Created in 1988 by American quantitative finance theorist Perry J. Kaufman and is known as
+ Kaufman's Adaptive Moving Average (KAMA). Even though the method was developed as early as 1972,
+ it was not until the popular book titled "Trading Systems and Methods" that it was made widely
+ available to the public. Unlike other conventional moving averages systems, the Kaufman's Adaptive
+ Moving Average, considers market volatility apart from price fluctuations.
+
+ KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
+
+Sources:
+ https://www.tutorialspoint.com/kaufman-s-adaptive-moving-average-kama-formula-and-how-does-it-work
+ https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/kaufmans-adaptive-moving-average-kama/
+ https://www.technicalindicators.net/indicators-technical-analysis/152-kama-kaufman-adaptive-moving-average
+
+Remark:
+ If useNaN:true argument is provided, KAMA starts calculating values from [period] bar onwards.
+ Without useNaN argument (default setting), KAMA starts calculating values from bar 1 - and yields
+ slightly different results for the first 50 bars - and then converges with the other one.
+
+ */
+
+public class KAMA_Series : Single_TSeries_Indicator
+{
+ private readonly double _scFast, _scSlow;
+ private readonly System.Collections.Generic.List _buffer = new();
+ private double _lastkama = double.NaN;
+ private double _lastlastkama;
+
+ public KAMA_Series(TSeries source, int period, int fast = 2, int slow= 30, bool useNaN = false) : base(source, period, useNaN) {
+ _scFast = 2.0 / (fast+1);
+ _scSlow = 2.0 / (slow+1);
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ if (update){
+ _buffer[_buffer.Count - 1] = TValue.v;
+ _lastkama = _lastlastkama;
+ }
+ else {
+ _buffer.Add(TValue.v);
+ _lastlastkama = _lastkama;
+ }
+ if (_buffer.Count > _p + 1) { _buffer.RemoveAt(0); }
+
+ double _kama = 0;
+ if (this.Count < this._p) { _kama = TValue.v; }
+ else {
+ double _change = Math.Abs(_buffer[_buffer.Count - 1] - _buffer[(_buffer.Count > _p + 1) ? 1 : 0]);
+ double _sumpv = 0;
+ for (int i = 1; i < _buffer.Count; i++)
+ { _sumpv += Math.Abs(_buffer[(_buffer.Count > 0) ? i : 0] - _buffer[i - 1]); }
+ double _er = (_sumpv == 0) ? 0 : _change / _sumpv;
+ double _sc = (_er * (_scFast - _scSlow)) + _scSlow;
+ _kama = (_lastkama + (_sc * _sc * (TValue.v - _lastkama)));
+ }
+ _lastkama = _kama;
+ base.Add((TValue.t, _kama), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/MACD_Series.cs b/Calculations/Trends/MACD_Series.cs
similarity index 97%
rename from Source/Trends/MACD_Series.cs
rename to Calculations/Trends/MACD_Series.cs
index ebe205f2..02f9360c 100644
--- a/Source/Trends/MACD_Series.cs
+++ b/Calculations/Trends/MACD_Series.cs
@@ -1,45 +1,45 @@
-namespace QuanTAlib;
-using System;
-
-/*
-MACD: Moving Average Convergence/Divergence
- Moving average convergence divergence (MACD) is a trend-following momentum
- indicator that shows the relationship between two moving averages of a series.
- The MACD is calculated by subtracting the 26-period exponential moving average (EMA)
- from the 12-period EMA. MACD Signal is 9-day EMA of MACD.
-
-Sources:
- https://www.investopedia.com/terms/m/macd.asp
- https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/macd
-
- */
-
-public class MACD_Series : Single_TSeries_Indicator
-{
- private readonly EMA_Series _TSslow;
- private readonly EMA_Series _TSfast;
- private readonly SUB_Series _TSmacd;
- public EMA_Series Signal { get; }
-
- public MACD_Series(TSeries source, int slow = 26, int fast = 12, int signal = 9, bool useNaN = false)
- : base(source, period: 0, useNaN)
- {
- _TSslow = new(source: source, period: slow, useNaN: false);
- _TSfast = new(source: source, period: fast, useNaN: false);
- _TSmacd = new(_TSfast, _TSslow);
- this.Signal = new(source: _TSmacd, period: signal, useNaN: useNaN);
-
- if (source.Count > 0) { base.Add(_TSmacd); }
- }
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- double _macd;
- if (update)
- {
- _TSslow.Add(TValue, true);
- _TSfast.Add(TValue, true);
- }
- _macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v;
- base.Add((TValue.t, _macd), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+MACD: Moving Average Convergence/Divergence
+ Moving average convergence divergence (MACD) is a trend-following momentum
+ indicator that shows the relationship between two moving averages of a series.
+ The MACD is calculated by subtracting the 26-period exponential moving average (EMA)
+ from the 12-period EMA. MACD Signal is 9-day EMA of MACD.
+
+Sources:
+ https://www.investopedia.com/terms/m/macd.asp
+ https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/macd
+
+ */
+
+public class MACD_Series : Single_TSeries_Indicator
+{
+ private readonly EMA_Series _TSslow;
+ private readonly EMA_Series _TSfast;
+ private readonly SUB_Series _TSmacd;
+ public EMA_Series Signal { get; }
+
+ public MACD_Series(TSeries source, int slow = 26, int fast = 12, int signal = 9, bool useNaN = false)
+ : base(source, period: 0, useNaN)
+ {
+ _TSslow = new(source: source, period: slow, useNaN: false);
+ _TSfast = new(source: source, period: fast, useNaN: false);
+ _TSmacd = new(_TSfast, _TSslow);
+ this.Signal = new(source: _TSmacd, period: signal, useNaN: useNaN);
+
+ if (source.Count > 0) { base.Add(_TSmacd); }
+ }
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ double _macd;
+ if (update)
+ {
+ _TSslow.Add(TValue, true);
+ _TSfast.Add(TValue, true);
+ }
+ _macd = this._TSmacd[(this.Count < this._TSmacd.Count) ? this.Count : this._TSmacd.Count - 1].v;
+ base.Add((TValue.t, _macd), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/MAMA_Series.cs b/Calculations/Trends/MAMA_Series.cs
similarity index 97%
rename from Source/Trends/MAMA_Series.cs
rename to Calculations/Trends/MAMA_Series.cs
index 0224dc98..ff85d784 100644
--- a/Source/Trends/MAMA_Series.cs
+++ b/Calculations/Trends/MAMA_Series.cs
@@ -1,118 +1,118 @@
-namespace QuanTAlib;
-using System;
-
-/*
-MAMA: MESA Adaptive Moving Average
- Created by John Ehlers, the MAMA indicator is a 5-period adaptive moving average of
- high/low price that uses classic electrical radio-frequency signal processing algorithms
- to reduce noise.
-
- KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
-
-Sources:
- https://mesasoftware.com/papers/MAMA.pdf
- https://www.tradingview.com/script/foQxLbU3-Ehlers-MESA-Adaptive-Moving-Average-LazyBear/
-
- */
-
-public class MAMA_Series : Single_TSeries_Indicator
-{
- public MAMA_Series(TSeries source, double fastlimit = 0.5, double slowlimit = 0.05, bool useNaN = false) : base(source, period: 5, useNaN)
- {
- fastl = fastlimit;
- slowl = slowlimit;
- Fama = new();
- if (base._data.Count > 0) { base.Add(base._data); }
- }
-
- private double sumPr, jI, jQ, fastl, slowl;
- private (double i, double i1, double i2, double i3, double i4, double i5, double i6, double io) pr, i1, q1, sm, dt;
- private (double i, double i1, double io) i2, q2, re, im, pd, ph, mama, fama;
- public TSeries Fama { get; }
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
-
- if (!update) {
- // roll forward (oldx = x)
- pr.io = pr.i6; pr.i6 = pr.i5; pr.i5 = pr.i4; pr.i4 = pr.i3; pr.i3 = pr.i2; pr.i2 = pr.i1; pr.i1 = pr.i;
- i1.io = i1.i6; i1.i6 = i1.i5; i1.i5 = i1.i4; i1.i4 = i1.i3; i1.i3 = i1.i2; i1.i2 = i1.i1; i1.i1 = i1.i;
- q1.io = q1.i6; q1.i6 = q1.i5; q1.i5 = q1.i4; q1.i4 = q1.i3; q1.i3 = q1.i2; q1.i2 = q1.i1; q1.i1 = q1.i;
- dt.io = dt.i6; dt.i6 = dt.i5; dt.i5 = dt.i4; dt.i4 = dt.i3; dt.i3 = dt.i2; dt.i2 = dt.i1; dt.i1 = dt.i;
- sm.io = sm.i6; sm.i6 = sm.i5; sm.i5 = sm.i4; sm.i4 = sm.i3; sm.i3 = sm.i2; sm.i2 = sm.i1; sm.i1 = sm.i;
- i2.io = i2.i1; i2.i1 = i2.i;
- q2.io = q2.i1; q2.i1 = q2.i;
- re.io = re.i1; re.i1 = re.i;
- im.io = im.i1; im.i1 = im.i;
- pd.io = pd.i1; pd.i1 = pd.i;
- ph.io = ph.i1; ph.i1 = ph.i;
- mama.io = mama.i1; mama.i1 = mama.i;
- fama.io = fama.i1; fama.i1 = fama.i;
- }
- int i = base.Count;
- pr.i = TValue.v;
- if (i > 5) {
- double adj = (0.075 * pd.i1) + 0.54;
-
- // smooth and detrender
- sm.i = ((4 * pr.i) + (3 * pr.i1) + (2 * pr.i2) + pr.i3) / 10;
- dt.i = ((0.0962 * sm.i) + (0.5769 * sm.i2) - (0.5769 * sm.i4) - (0.0962 * sm.i6)) * adj;
-
- // in-phase and quadrature
- q1.i = ((0.0962 * dt.i) + (0.5769 * dt.i2) - (0.5769 * dt.i4) - (0.0962 * dt.i6)) * adj;
- i1.i = dt.i3;
-
- // advance the phases by 90 degrees
- jI = ((0.0962 * i1.i) + (0.5769 * i1.i2) - (0.5769 * i1.i4) - (0.0962 * i1.i6)) * adj;
- jQ = ((0.0962 * q1.i) + (0.5769 * q1.i2) - (0.5769 * q1.i4) - (0.0962 * q1.i6)) * adj;
-
- // phasor addition for 3-bar averaging
- i2.i = i1.i - jQ;
- q2.i = q1.i + jI;
-
- i2.i = (0.2 * i2.i) + (0.8 * i2.i1); // smoothing it
- q2.i = (0.2 * q2.i) + (0.8 * q2.i1);
-
- // homodyne discriminator
- re.i = (i2.i * i2.i1) + (q2.i * q2.i1);
- im.i = (i2.i * q2.i1) - (q2.i * i2.i1);
-
- re.i = (0.2 * re.i) + (0.8 * re.i1); // smoothing it
- im.i = (0.2 * im.i) + (0.8 * im.i1);
-
- // calculate period
- pd.i = (im.i != 0 && re.i != 0) ? (6.283185307179586 / Math.Atan(im.i / re.i)) : 0d;
-
- // adjust period to thresholds
- pd.i = (pd.i > 1.5 * pd.i1) ? 1.5 * pd.i1 : pd.i;
- pd.i = (pd.i < 0.67 * pd.i1) ? 0.67 * pd.i1 : pd.i;
- pd.i = (pd.i < 6d) ? 6d : pd.i;
- pd.i = (pd.i > 50d) ? 50d : pd.i;
-
- // smooth the period
- pd.i = (0.2 * pd.i) + (0.8 * pd.i1);
-
- // determine phase position
- ph.i = (i1.i != 0) ? Math.Atan(q1.i / i1.i) * 57.29577951308232 : 0;
-
- // change in phase
- double delta = Math.Max(ph.i1 - ph.i, 1d);
-
- // adaptive alpha value
- double alpha = Math.Max(fastl / delta, slowl);
-
- // final indicators
- mama.i = ((alpha * pr.i) + ((1d - alpha) * mama.i1));
- fama.i = ((0.5d * alpha * mama.i) + ((1d - (0.5d * alpha)) * fama.i1));
- }
- else {
- sumPr += pr.i;
- pd.i = sm.i = dt.i = i1.i = q1.i = i2.i = q2.i = re.i = im.i = ph.i = 0;
- mama.i = fama.i = sumPr / (i+1);
- }
-
- base.Add((TValue.t, mama.i), update, _NaN);
- var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : fama.i);
- Fama.Add(result, update);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+MAMA: MESA Adaptive Moving Average
+ Created by John Ehlers, the MAMA indicator is a 5-period adaptive moving average of
+ high/low price that uses classic electrical radio-frequency signal processing algorithms
+ to reduce noise.
+
+ KAMAi = KAMAi - 1 + SC * ( price - KAMAi-1 )
+
+Sources:
+ https://mesasoftware.com/papers/MAMA.pdf
+ https://www.tradingview.com/script/foQxLbU3-Ehlers-MESA-Adaptive-Moving-Average-LazyBear/
+
+ */
+
+public class MAMA_Series : Single_TSeries_Indicator
+{
+ public MAMA_Series(TSeries source, double fastlimit = 0.5, double slowlimit = 0.05, bool useNaN = false) : base(source, period: 5, useNaN)
+ {
+ fastl = fastlimit;
+ slowl = slowlimit;
+ Fama = new();
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+
+ private double sumPr, jI, jQ, fastl, slowl;
+ private (double i, double i1, double i2, double i3, double i4, double i5, double i6, double io) pr, i1, q1, sm, dt;
+ private (double i, double i1, double io) i2, q2, re, im, pd, ph, mama, fama;
+ public TSeries Fama { get; }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+
+ if (!update) {
+ // roll forward (oldx = x)
+ pr.io = pr.i6; pr.i6 = pr.i5; pr.i5 = pr.i4; pr.i4 = pr.i3; pr.i3 = pr.i2; pr.i2 = pr.i1; pr.i1 = pr.i;
+ i1.io = i1.i6; i1.i6 = i1.i5; i1.i5 = i1.i4; i1.i4 = i1.i3; i1.i3 = i1.i2; i1.i2 = i1.i1; i1.i1 = i1.i;
+ q1.io = q1.i6; q1.i6 = q1.i5; q1.i5 = q1.i4; q1.i4 = q1.i3; q1.i3 = q1.i2; q1.i2 = q1.i1; q1.i1 = q1.i;
+ dt.io = dt.i6; dt.i6 = dt.i5; dt.i5 = dt.i4; dt.i4 = dt.i3; dt.i3 = dt.i2; dt.i2 = dt.i1; dt.i1 = dt.i;
+ sm.io = sm.i6; sm.i6 = sm.i5; sm.i5 = sm.i4; sm.i4 = sm.i3; sm.i3 = sm.i2; sm.i2 = sm.i1; sm.i1 = sm.i;
+ i2.io = i2.i1; i2.i1 = i2.i;
+ q2.io = q2.i1; q2.i1 = q2.i;
+ re.io = re.i1; re.i1 = re.i;
+ im.io = im.i1; im.i1 = im.i;
+ pd.io = pd.i1; pd.i1 = pd.i;
+ ph.io = ph.i1; ph.i1 = ph.i;
+ mama.io = mama.i1; mama.i1 = mama.i;
+ fama.io = fama.i1; fama.i1 = fama.i;
+ }
+ int i = base.Count;
+ pr.i = TValue.v;
+ if (i > 5) {
+ double adj = (0.075 * pd.i1) + 0.54;
+
+ // smooth and detrender
+ sm.i = ((4 * pr.i) + (3 * pr.i1) + (2 * pr.i2) + pr.i3) / 10;
+ dt.i = ((0.0962 * sm.i) + (0.5769 * sm.i2) - (0.5769 * sm.i4) - (0.0962 * sm.i6)) * adj;
+
+ // in-phase and quadrature
+ q1.i = ((0.0962 * dt.i) + (0.5769 * dt.i2) - (0.5769 * dt.i4) - (0.0962 * dt.i6)) * adj;
+ i1.i = dt.i3;
+
+ // advance the phases by 90 degrees
+ jI = ((0.0962 * i1.i) + (0.5769 * i1.i2) - (0.5769 * i1.i4) - (0.0962 * i1.i6)) * adj;
+ jQ = ((0.0962 * q1.i) + (0.5769 * q1.i2) - (0.5769 * q1.i4) - (0.0962 * q1.i6)) * adj;
+
+ // phasor addition for 3-bar averaging
+ i2.i = i1.i - jQ;
+ q2.i = q1.i + jI;
+
+ i2.i = (0.2 * i2.i) + (0.8 * i2.i1); // smoothing it
+ q2.i = (0.2 * q2.i) + (0.8 * q2.i1);
+
+ // homodyne discriminator
+ re.i = (i2.i * i2.i1) + (q2.i * q2.i1);
+ im.i = (i2.i * q2.i1) - (q2.i * i2.i1);
+
+ re.i = (0.2 * re.i) + (0.8 * re.i1); // smoothing it
+ im.i = (0.2 * im.i) + (0.8 * im.i1);
+
+ // calculate period
+ pd.i = (im.i != 0 && re.i != 0) ? (6.283185307179586 / Math.Atan(im.i / re.i)) : 0d;
+
+ // adjust period to thresholds
+ pd.i = (pd.i > 1.5 * pd.i1) ? 1.5 * pd.i1 : pd.i;
+ pd.i = (pd.i < 0.67 * pd.i1) ? 0.67 * pd.i1 : pd.i;
+ pd.i = (pd.i < 6d) ? 6d : pd.i;
+ pd.i = (pd.i > 50d) ? 50d : pd.i;
+
+ // smooth the period
+ pd.i = (0.2 * pd.i) + (0.8 * pd.i1);
+
+ // determine phase position
+ ph.i = (i1.i != 0) ? Math.Atan(q1.i / i1.i) * 57.29577951308232 : 0;
+
+ // change in phase
+ double delta = Math.Max(ph.i1 - ph.i, 1d);
+
+ // adaptive alpha value
+ double alpha = Math.Max(fastl / delta, slowl);
+
+ // final indicators
+ mama.i = ((alpha * pr.i) + ((1d - alpha) * mama.i1));
+ fama.i = ((0.5d * alpha * mama.i) + ((1d - (0.5d * alpha)) * fama.i1));
+ }
+ else {
+ sumPr += pr.i;
+ pd.i = sm.i = dt.i = i1.i = q1.i = i2.i = q2.i = re.i = im.i = ph.i = 0;
+ mama.i = fama.i = sumPr / (i+1);
+ }
+
+ base.Add((TValue.t, mama.i), update, _NaN);
+ var result = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : fama.i);
+ Fama.Add(result, update);
+ }
+}
diff --git a/Source/Trends/RMA_Series.cs b/Calculations/Trends/RMA_Series.cs
similarity index 97%
rename from Source/Trends/RMA_Series.cs
rename to Calculations/Trends/RMA_Series.cs
index e8b1ef63..f7059c51 100644
--- a/Source/Trends/RMA_Series.cs
+++ b/Calculations/Trends/RMA_Series.cs
@@ -1,56 +1,56 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-RMA: wildeR Moving Average
- J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
- set as 1/period, giving less weight to the new data compared to EMA.
-
-Sources:
- https://archive.org/details/newconceptsintec00wild/page/23/mode/2up
- https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
- https://www.incrediblecharts.com/indicators/wilder_moving_average.php
-
-Issues:
- Pandas-TA library calculates RMA using straight Exponential Weighted Mean:
- pandas.ewm().mean() and returns incorrect first (period) of bars compared to
- published formula. This implementation passess the validation test in Wilder's book.
-
- */
-
-public class RMA_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly double _k, _k1m;
- private double _lastema, _lastlastema;
-
- public RMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- this._k = 1.0 / (double)(this._p);
- this._k1m = 1.0 - this._k;
- this._lastema = this._lastlastema = double.NaN;
- if (_data.Count > 0) { base.Add(_data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- double _ema;
- if (update) { this._lastema = this._lastlastema; }
-
- if (this.Count < this._p)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- _ema = _buffer.Average();
- }
- else
- {
- _ema = (TValue.v * _k) + (_lastema * _k1m);
- }
-
- this._lastlastema = this._lastema;
- this._lastema = _ema;
-
- base.Add((TValue.t, _ema), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+RMA: wildeR Moving Average
+ J. Welles Wilder introduced RMA as an alternative to EMA. RMA's weight (k) is
+ set as 1/period, giving less weight to the new data compared to EMA.
+
+Sources:
+ https://archive.org/details/newconceptsintec00wild/page/23/mode/2up
+ https://tlc.thinkorswim.com/center/reference/Tech-Indicators/studies-library/V-Z/WildersSmoothing
+ https://www.incrediblecharts.com/indicators/wilder_moving_average.php
+
+Issues:
+ Pandas-TA library calculates RMA using straight Exponential Weighted Mean:
+ pandas.ewm().mean() and returns incorrect first (period) of bars compared to
+ published formula. This implementation passess the validation test in Wilder's book.
+
+ */
+
+public class RMA_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k, _k1m;
+ private double _lastema, _lastlastema;
+
+ public RMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ this._k = 1.0 / (double)(this._p);
+ this._k1m = 1.0 - this._k;
+ this._lastema = this._lastlastema = double.NaN;
+ if (_data.Count > 0) { base.Add(_data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ double _ema;
+ if (update) { this._lastema = this._lastlastema; }
+
+ if (this.Count < this._p)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ _ema = _buffer.Average();
+ }
+ else
+ {
+ _ema = (TValue.v * _k) + (_lastema * _k1m);
+ }
+
+ this._lastlastema = this._lastema;
+ this._lastema = _ema;
+
+ base.Add((TValue.t, _ema), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/SMA_Series.cs b/Calculations/Trends/SMA_Series.cs
similarity index 96%
rename from Source/Trends/SMA_Series.cs
rename to Calculations/Trends/SMA_Series.cs
index 9c23f298..84c8395d 100644
--- a/Source/Trends/SMA_Series.cs
+++ b/Calculations/Trends/SMA_Series.cs
@@ -1,44 +1,44 @@
-namespace QuanTAlib;
-using System;
-
-/*
-SMA: Simple Moving Average
- The weights are equally distributed across the period, resulting in a mean() of
- the data within the period
-
-Sources:
- https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
- https://stats.stackexchange.com/a/24739
-
-Remark:
- This calc doesn't use LINQ or SUM() or any of (slow) iterative methods. It is not as fast as TA-LIB
- implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
-
- */
-
-public class SMA_Series : Single_TSeries_Indicator {
- private double _sum, _oldsum;
- private int _len;
-
- public SMA_Series(TSeries source, int period = 0, bool useNaN = false) : base(source, period, false) {
- _sum = _oldsum = 0;
- _len = 0;
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update) {
- if (update) { _sum = _oldsum; }
- else { _oldsum = _sum; _len++; }
-
- _sum += TValue.v;
- if (_period != 0 && _len > _period) {
- _sum -= (_data[base.Count - _period - (update ? 1 : 0)].v);
- }
- double _div = (_period == 0) ? _len : Math.Min(_len, _period);
- base.Add((TValue.t, _sum / _div), update, _NaN);
- }
- public void Reset() {
- _sum = _oldsum = 0;
- _len = 0;
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+SMA: Simple Moving Average
+ The weights are equally distributed across the period, resulting in a mean() of
+ the data within the period
+
+Sources:
+ https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/simple-moving-average-sma/
+ https://stats.stackexchange.com/a/24739
+
+Remark:
+ This calc doesn't use LINQ or SUM() or any of (slow) iterative methods. It is not as fast as TA-LIB
+ implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
+
+ */
+
+public class SMA_Series : Single_TSeries_Indicator {
+ private double _sum, _oldsum;
+ private int _len;
+
+ public SMA_Series(TSeries source, int period = 0, bool useNaN = false) : base(source, period, false) {
+ _sum = _oldsum = 0;
+ _len = 0;
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update) {
+ if (update) { _sum = _oldsum; }
+ else { _oldsum = _sum; _len++; }
+
+ _sum += TValue.v;
+ if (_period != 0 && _len > _period) {
+ _sum -= (_data[base.Count - _period - (update ? 1 : 0)].v);
+ }
+ double _div = (_period == 0) ? _len : Math.Min(_len, _period);
+ base.Add((TValue.t, _sum / _div), update, _NaN);
+ }
+ public void Reset() {
+ _sum = _oldsum = 0;
+ _len = 0;
+ }
+}
diff --git a/Source/Trends/SMMA_Series.cs b/Calculations/Trends/SMMA_Series.cs
similarity index 97%
rename from Source/Trends/SMMA_Series.cs
rename to Calculations/Trends/SMMA_Series.cs
index 08a22068..27d3bfcd 100644
--- a/Source/Trends/SMMA_Series.cs
+++ b/Calculations/Trends/SMMA_Series.cs
@@ -1,51 +1,51 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-SMMA: Smoothed Moving Average
- The Smoothed Moving Average (SMMA) is a combination of a SMA and an EMA. It gives the recent prices
- an equal weighting as the historic prices as it takes all available price data into account.
- The main advantage of a smoothed moving average is that it removes short-term fluctuations.
-
- SMMA(i) = (SMMA-1*(N-1) + CLOSE (i)) / N
-
-Sources:
- https://blog.earn2trade.com/smoothed-moving-average
- https://guide.traderevolution.com/traderevolution/mobile-applications/phone/android/technical-indicators/moving-averages/smma-smoothed-moving-average
- https://www.chartmill.com/documentation/technical-analysis-indicators/217-MOVING-AVERAGES-%7C-The-Smoothed-Moving-Average-%28SMMA%29
-
- */
-
-public class SMMA_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _buffer = new();
- private double _lastsmma, _lastlastsmma;
-
- public SMMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- this._lastsmma = this._lastlastsmma = double.NaN;
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- double _smma = 0;
- if (update) { this._lastsmma = this._lastlastsmma; }
-
- if (this.Count < this._p)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- _smma = _buffer.Average();
- }
- else
- {
- _smma = ((_lastsmma * (_p-1)) + TValue.v) / _p ;
- }
-
- this._lastlastsmma = this._lastsmma;
- this._lastsmma = _smma;
-
- base.Add((TValue.t, _smma), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+SMMA: Smoothed Moving Average
+ The Smoothed Moving Average (SMMA) is a combination of a SMA and an EMA. It gives the recent prices
+ an equal weighting as the historic prices as it takes all available price data into account.
+ The main advantage of a smoothed moving average is that it removes short-term fluctuations.
+
+ SMMA(i) = (SMMA-1*(N-1) + CLOSE (i)) / N
+
+Sources:
+ https://blog.earn2trade.com/smoothed-moving-average
+ https://guide.traderevolution.com/traderevolution/mobile-applications/phone/android/technical-indicators/moving-averages/smma-smoothed-moving-average
+ https://www.chartmill.com/documentation/technical-analysis-indicators/217-MOVING-AVERAGES-%7C-The-Smoothed-Moving-Average-%28SMMA%29
+
+ */
+
+public class SMMA_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private double _lastsmma, _lastlastsmma;
+
+ public SMMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ this._lastsmma = this._lastlastsmma = double.NaN;
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ double _smma = 0;
+ if (update) { this._lastsmma = this._lastlastsmma; }
+
+ if (this.Count < this._p)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ _smma = _buffer.Average();
+ }
+ else
+ {
+ _smma = ((_lastsmma * (_p-1)) + TValue.v) / _p ;
+ }
+
+ this._lastlastsmma = this._lastsmma;
+ this._lastsmma = _smma;
+
+ base.Add((TValue.t, _smma), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/T3_Series.cs b/Calculations/Trends/T3_Series.cs
similarity index 97%
rename from Source/Trends/T3_Series.cs
rename to Calculations/Trends/T3_Series.cs
index 12479ceb..304fc200 100644
--- a/Source/Trends/T3_Series.cs
+++ b/Calculations/Trends/T3_Series.cs
@@ -1,110 +1,110 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-using System.Numerics;
-
-/*
-T3: Tillson T3 Moving Average
- Tim Tillson described it in "Technical Analysis of Stocks and Commodities", January 1998 in the
- article "Better Moving Averages". Tillson’s moving average becomes a popular indicator of
- technical analysis as it gets less lag with the price chart and its curve is considerably smoother.
-
-Sources:
- https://technicalindicators.net/indicators-technical-analysis/150-t3-moving-average
- http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/
-
-Calculation:
- Volume Factor is typically 0.7 (but also 0.618);
- Ema1 = Ema (Close);
- Ema2 = Ema (Ema1);
- Ema3 = Ema (Ema2);
- Ema4 = Ema (Ema3);
- Ema5 = Ema (Ema4);
- Ema6 = Ema (Ema5);
- T3 = –(a*a*a) * Ema6 + (3*a*a + 3*a*a*a) * Ema5 + (–6*a*a – 3*a – 3*a*a*a) * Ema4 + (1 + 3*a + a*a*a + 3*a*a) * Ema3
-
- */
-public class T3_Series : Single_TSeries_Indicator {
- private readonly double _k, _k1m, _c1, _c2, _c3, _c4;
- private readonly System.Collections.Generic.List _buffer1 = new();
- private readonly System.Collections.Generic.List _buffer2 = new();
- private readonly System.Collections.Generic.List _buffer3 = new();
- private readonly System.Collections.Generic.List _buffer4 = new();
- private readonly System.Collections.Generic.List _buffer5 = new();
- private readonly System.Collections.Generic.List _buffer6 = new();
-
- private double _lastema1, _lastema2, _lastema3, _lastema4, _lastema5, _lastema6;
- private double _llastema1, _llastema2, _llastema3, _llastema4, _llastema5, _llastema6;
- private bool _useSMA;
-
- public T3_Series(TSeries source, int period, double vfactor = 0.7, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN) {
- double _a = vfactor; //0.7; //0.618
- _c1 = -_a * _a * _a;
- _c2 = 3 * _a * _a + 3 * _a * _a * _a;
- _c3 = -6 * _a * _a - 3 * _a - 3 * _a * _a * _a;
- _c4 = 1 + 3 * _a + _a * _a * _a + 3 * _a * _a;
-
- _k = 2.0 / (_p + 1);
- _k1m = 1.0 - _k;
- _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0;
- _useSMA = useSMA;
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update) {
- double _ema1, _ema2, _ema3, _ema4, _ema5, _ema6;
- if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; _lastema4 = _llastema4; _lastema5 = _llastema5; _lastema6 = _llastema6; }
- else { _llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _llastema4 = _lastema4; _llastema5 = _lastema5; _llastema6 = _lastema6; }
-
- if (this.Count == 0) { _lastema1 = _lastema2 = _lastema3 = _lastema4 = _lastema5 = _lastema6 = TValue.v; }
-
- if ((this.Count < _p) && _useSMA) {
- Add_Replace(_buffer1, TValue.v, update);
- _ema1 = 0;
- for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; }
- _ema1 /= _buffer1.Count;
-
- Add_Replace(_buffer2, _ema1, update);
- _ema2 = 0;
- for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; }
- _ema2 /= _buffer2.Count;
-
- Add_Replace(_buffer3, _ema2, update);
- _ema3 = 0;
- for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; }
- _ema3 /= _buffer3.Count;
-
- Add_Replace(_buffer4, _ema3, update);
- _ema4 = 0;
- for (int i = 0; i < _buffer4.Count; i++) { _ema4 += _buffer4[i]; }
- _ema4 /= _buffer4.Count;
-
- Add_Replace(_buffer5, _ema4, update);
- _ema5 = 0;
- for (int i = 0; i < _buffer5.Count; i++) { _ema5 += _buffer5[i]; }
- _ema5 /= _buffer5.Count;
-
- Add_Replace(_buffer6, _ema5, update);
- _ema6 = 0;
- for (int i = 0; i < _buffer6.Count; i++) { _ema6 += _buffer6[i]; }
- _ema6 /= _buffer6.Count;
- }
- else {
- _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
- _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
- _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
- _ema4 = (_ema3 * this._k) + (this._lastema4 * this._k1m);
- _ema5 = (_ema4 * this._k) + (this._lastema5 * this._k1m);
- _ema6 = (_ema5 * this._k) + (this._lastema6 * this._k1m);
- }
- _lastema1 = _ema1;
- _lastema2 = _ema2;
- _lastema3 = _ema3;
- _lastema4 = _ema4;
- _lastema5 = _ema5;
- _lastema6 = _ema6;
-
- double _T3 = _c1 * _ema6 + _c2 * _ema5 + _c3 * _ema4 + _c4 * _ema3;
- base.Add((TValue.t, _T3), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+using System.Numerics;
+
+/*
+T3: Tillson T3 Moving Average
+ Tim Tillson described it in "Technical Analysis of Stocks and Commodities", January 1998 in the
+ article "Better Moving Averages". Tillson’s moving average becomes a popular indicator of
+ technical analysis as it gets less lag with the price chart and its curve is considerably smoother.
+
+Sources:
+ https://technicalindicators.net/indicators-technical-analysis/150-t3-moving-average
+ http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/
+
+Calculation:
+ Volume Factor is typically 0.7 (but also 0.618);
+ Ema1 = Ema (Close);
+ Ema2 = Ema (Ema1);
+ Ema3 = Ema (Ema2);
+ Ema4 = Ema (Ema3);
+ Ema5 = Ema (Ema4);
+ Ema6 = Ema (Ema5);
+ T3 = –(a*a*a) * Ema6 + (3*a*a + 3*a*a*a) * Ema5 + (–6*a*a – 3*a – 3*a*a*a) * Ema4 + (1 + 3*a + a*a*a + 3*a*a) * Ema3
+
+ */
+public class T3_Series : Single_TSeries_Indicator {
+ private readonly double _k, _k1m, _c1, _c2, _c3, _c4;
+ private readonly System.Collections.Generic.List _buffer1 = new();
+ private readonly System.Collections.Generic.List _buffer2 = new();
+ private readonly System.Collections.Generic.List _buffer3 = new();
+ private readonly System.Collections.Generic.List _buffer4 = new();
+ private readonly System.Collections.Generic.List _buffer5 = new();
+ private readonly System.Collections.Generic.List _buffer6 = new();
+
+ private double _lastema1, _lastema2, _lastema3, _lastema4, _lastema5, _lastema6;
+ private double _llastema1, _llastema2, _llastema3, _llastema4, _llastema5, _llastema6;
+ private bool _useSMA;
+
+ public T3_Series(TSeries source, int period, double vfactor = 0.7, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN) {
+ double _a = vfactor; //0.7; //0.618
+ _c1 = -_a * _a * _a;
+ _c2 = 3 * _a * _a + 3 * _a * _a * _a;
+ _c3 = -6 * _a * _a - 3 * _a - 3 * _a * _a * _a;
+ _c4 = 1 + 3 * _a + _a * _a * _a + 3 * _a * _a;
+
+ _k = 2.0 / (_p + 1);
+ _k1m = 1.0 - _k;
+ _lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0;
+ _useSMA = useSMA;
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update) {
+ double _ema1, _ema2, _ema3, _ema4, _ema5, _ema6;
+ if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; _lastema4 = _llastema4; _lastema5 = _llastema5; _lastema6 = _llastema6; }
+ else { _llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _llastema4 = _lastema4; _llastema5 = _lastema5; _llastema6 = _lastema6; }
+
+ if (this.Count == 0) { _lastema1 = _lastema2 = _lastema3 = _lastema4 = _lastema5 = _lastema6 = TValue.v; }
+
+ if ((this.Count < _p) && _useSMA) {
+ Add_Replace(_buffer1, TValue.v, update);
+ _ema1 = 0;
+ for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; }
+ _ema1 /= _buffer1.Count;
+
+ Add_Replace(_buffer2, _ema1, update);
+ _ema2 = 0;
+ for (int i = 0; i < _buffer2.Count; i++) { _ema2 += _buffer2[i]; }
+ _ema2 /= _buffer2.Count;
+
+ Add_Replace(_buffer3, _ema2, update);
+ _ema3 = 0;
+ for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; }
+ _ema3 /= _buffer3.Count;
+
+ Add_Replace(_buffer4, _ema3, update);
+ _ema4 = 0;
+ for (int i = 0; i < _buffer4.Count; i++) { _ema4 += _buffer4[i]; }
+ _ema4 /= _buffer4.Count;
+
+ Add_Replace(_buffer5, _ema4, update);
+ _ema5 = 0;
+ for (int i = 0; i < _buffer5.Count; i++) { _ema5 += _buffer5[i]; }
+ _ema5 /= _buffer5.Count;
+
+ Add_Replace(_buffer6, _ema5, update);
+ _ema6 = 0;
+ for (int i = 0; i < _buffer6.Count; i++) { _ema6 += _buffer6[i]; }
+ _ema6 /= _buffer6.Count;
+ }
+ else {
+ _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
+ _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
+ _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
+ _ema4 = (_ema3 * this._k) + (this._lastema4 * this._k1m);
+ _ema5 = (_ema4 * this._k) + (this._lastema5 * this._k1m);
+ _ema6 = (_ema5 * this._k) + (this._lastema6 * this._k1m);
+ }
+ _lastema1 = _ema1;
+ _lastema2 = _ema2;
+ _lastema3 = _ema3;
+ _lastema4 = _ema4;
+ _lastema5 = _ema5;
+ _lastema6 = _ema6;
+
+ double _T3 = _c1 * _ema6 + _c2 * _ema5 + _c3 * _ema4 + _c4 * _ema3;
+ base.Add((TValue.t, _T3), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/TEMA_Series.cs b/Calculations/Trends/TEMA_Series.cs
similarity index 96%
rename from Source/Trends/TEMA_Series.cs
rename to Calculations/Trends/TEMA_Series.cs
index 3cb1aafc..71f84698 100644
--- a/Source/Trends/TEMA_Series.cs
+++ b/Calculations/Trends/TEMA_Series.cs
@@ -1,70 +1,70 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-TEMA: Triple Exponential Moving Average
- TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
-
-Sources:
- https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
-
-Remark:
- ema1 = EMA(close, length)
- ema2 = EMA(ema1, length)
- ema3 = EMA(ema2, length)
- TEMA = 3 * (ema1 - ema2) + ema3
-
- */
-
-public class TEMA_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly double _k, _k1m;
- private double _lastema1, _lastlastema1;
- private double _lastema2, _lastlastema2;
- private double _lastema3, _lastlastema3;
-
- public TEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- this._k = 2.0 / (this._p + 1);
- this._k1m = 1.0 - this._k;
- if (_data.Count > 0) { base.Add(_data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update)
- {
- if (update)
- {
- this._lastema1 = this._lastlastema1;
- this._lastema2 = this._lastlastema2;
- this._lastema3 = this._lastlastema3;
- }
-
- double _ema1, _ema2, _ema3;
-
- if (this.Count < this._p)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
- double _sma = _buffer.Average();
- _ema1 = _ema2 = _ema3 = _sma;
- }
- else
- {
- _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
- _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
- _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
- }
-
- double _tema = (3 * (_ema1 - _ema2)) + _ema3;
-
- this._lastlastema1 = this._lastema1;
- this._lastlastema2 = this._lastema2;
- this._lastlastema3 = this._lastema3;
- this._lastema1 = _ema1;
- this._lastema2 = _ema2;
- this._lastema3 = _ema3;
-
- base.Add((TValue.t, _tema), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+TEMA: Triple Exponential Moving Average
+ TEMA uses EMA(EMA(EMA())) to calculate less laggy Exponential moving average.
+
+Sources:
+ https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triple-exponential-moving-average-tema/
+
+Remark:
+ ema1 = EMA(close, length)
+ ema2 = EMA(ema1, length)
+ ema3 = EMA(ema2, length)
+ TEMA = 3 * (ema1 - ema2) + ema3
+
+ */
+
+public class TEMA_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k, _k1m;
+ private double _lastema1, _lastlastema1;
+ private double _lastema2, _lastlastema2;
+ private double _lastema3, _lastlastema3;
+
+ public TEMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ this._k = 2.0 / (this._p + 1);
+ this._k1m = 1.0 - this._k;
+ if (_data.Count > 0) { base.Add(_data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update)
+ {
+ if (update)
+ {
+ this._lastema1 = this._lastlastema1;
+ this._lastema2 = this._lastlastema2;
+ this._lastema3 = this._lastlastema3;
+ }
+
+ double _ema1, _ema2, _ema3;
+
+ if (this.Count < this._p)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+ double _sma = _buffer.Average();
+ _ema1 = _ema2 = _ema3 = _sma;
+ }
+ else
+ {
+ _ema1 = (TValue.v * this._k) + (this._lastema1 * this._k1m);
+ _ema2 = (_ema1 * this._k) + (this._lastema2 * this._k1m);
+ _ema3 = (_ema2 * this._k) + (this._lastema3 * this._k1m);
+ }
+
+ double _tema = (3 * (_ema1 - _ema2)) + _ema3;
+
+ this._lastlastema1 = this._lastema1;
+ this._lastlastema2 = this._lastema2;
+ this._lastlastema3 = this._lastema3;
+ this._lastema1 = _ema1;
+ this._lastema2 = _ema2;
+ this._lastema3 = _ema3;
+
+ base.Add((TValue.t, _tema), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/TRIMA_Series.cs b/Calculations/Trends/TRIMA_Series.cs
similarity index 97%
rename from Source/Trends/TRIMA_Series.cs
rename to Calculations/Trends/TRIMA_Series.cs
index d0276359..7a082b7e 100644
--- a/Source/Trends/TRIMA_Series.cs
+++ b/Calculations/Trends/TRIMA_Series.cs
@@ -1,43 +1,43 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-TRIMA: Triangular Moving Average
- A weighted moving average where the shape of the weights are triangular and the greatest
- weight is in the middle of the period,
-
-Sources:
- https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
-
-Remark:
- trima = sma(sma(signal, n/2), n/2)
-
- */
-
-public class TRIMA_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _buffer1 = new();
- private readonly System.Collections.Generic.List _buffer2 = new();
- private readonly int _p1a, _p1b;
-
- public TRIMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- _p1a = (int) Math.Floor((period * 0.5) + 1);
- _p1b = (int) Math.Ceiling(0.5 * period);
- if (base._data.Count > 0) { base.Add(base._data); }
- }
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- if (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
- if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
- double _sma1 = _buffer1.Average();
-
- if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
- if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
- double _trima = _buffer2.Average();
-
- base.Add((TValue.t, _trima), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+TRIMA: Triangular Moving Average
+ A weighted moving average where the shape of the weights are triangular and the greatest
+ weight is in the middle of the period,
+
+Sources:
+ https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/triangular-moving-average-trima/
+
+Remark:
+ trima = sma(sma(signal, n/2), n/2)
+
+ */
+
+public class TRIMA_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer1 = new();
+ private readonly System.Collections.Generic.List _buffer2 = new();
+ private readonly int _p1a, _p1b;
+
+ public TRIMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ _p1a = (int) Math.Floor((period * 0.5) + 1);
+ _p1b = (int) Math.Ceiling(0.5 * period);
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ if (update) { _buffer1[_buffer1.Count - 1] = TValue.v; } else { _buffer1.Add(TValue.v); }
+ if (_buffer1.Count > this._p1b && this._p1b != 0) { _buffer1.RemoveAt(0); }
+ double _sma1 = _buffer1.Average();
+
+ if (update) { _buffer2[_buffer2.Count - 1] = _sma1; } else { _buffer2.Add(_sma1); }
+ if (_buffer2.Count > this._p1a && this._p1a != 0) { _buffer2.RemoveAt(0); }
+ double _trima = _buffer2.Average();
+
+ base.Add((TValue.t, _trima), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/TRIX_Series.cs b/Calculations/Trends/TRIX_Series.cs
similarity index 99%
rename from Source/Trends/TRIX_Series.cs
rename to Calculations/Trends/TRIX_Series.cs
index d557bc56..36c97fdb 100644
--- a/Source/Trends/TRIX_Series.cs
+++ b/Calculations/Trends/TRIX_Series.cs
@@ -1,25 +1,25 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-using System.Numerics;
-
-/*
-TRIX: Triple Exponential Average
- Developed by Jack Hutson in the early 1980s, the triple exponential average (TRIX)
- has become a popular technical analysis tool to aid chartists in spotting diversions
-and directional cues in stock trading patterns.
-
-
-Calculation:
- Ema1 = Ema (Close);
- Ema2 = Ema (Ema1);
- Ema3 = Ema (Ema2);
- TRIX = (Ema3-Ema3[1]) / Ema3[1]
-
-Sources:
- https://www.investopedia.com/terms/t/trix.asp
-
- */
+namespace QuanTAlib;
+using System;
+using System.Linq;
+using System.Numerics;
+
+/*
+TRIX: Triple Exponential Average
+ Developed by Jack Hutson in the early 1980s, the triple exponential average (TRIX)
+ has become a popular technical analysis tool to aid chartists in spotting diversions
+and directional cues in stock trading patterns.
+
+
+Calculation:
+ Ema1 = Ema (Close);
+ Ema2 = Ema (Ema1);
+ Ema3 = Ema (Ema2);
+ TRIX = (Ema3-Ema3[1]) / Ema3[1]
+
+Sources:
+ https://www.investopedia.com/terms/t/trix.asp
+
+ */
public class TRIX_Series : Single_TSeries_Indicator
{
private readonly double _k, _k1m;
@@ -78,5 +78,5 @@ public class TRIX_Series : Single_TSeries_Indicator
_lastema3 = _ema3;
base.Add((TValue.t, _trix), update, _NaN);
- }
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/WMA_Series.cs b/Calculations/Trends/WMA_Series.cs
similarity index 97%
rename from Source/Trends/WMA_Series.cs
rename to Calculations/Trends/WMA_Series.cs
index a6c4a1aa..2b835b7f 100644
--- a/Source/Trends/WMA_Series.cs
+++ b/Calculations/Trends/WMA_Series.cs
@@ -1,35 +1,35 @@
-namespace QuanTAlib;
-using System;
-
-/*
-WMA: (linearly) Weighted Moving Average
- The weights are linearly decreasing over the period and the most recent data has
- the heaviest weight.
-
-Sources:
- https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/weighted-moving-average-wma/
- https://www.technicalindicators.net/indicators-technical-analysis/83-moving-averages-simple-exponential-weighted
-
- */
-
-public class WMA_Series : Single_TSeries_Indicator
-{
- public WMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
- {
- for (int i = 0; i < this._p; i++) { this._weights.Add(i + 1); }
- if (base._data.Count > 0) { base.Add(base._data); }
- }
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly System.Collections.Generic.List _weights = new();
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- Add_Replace_Trim(_buffer, TValue.v, _p, update);
-
- double _wma = 0;
- for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; }
- _wma /= (this._buffer.Count * (this._buffer.Count + 1)) * 0.5;
-
- base.Add((TValue.t, _wma), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+WMA: (linearly) Weighted Moving Average
+ The weights are linearly decreasing over the period and the most recent data has
+ the heaviest weight.
+
+Sources:
+ https://corporatefinanceinstitute.com/resources/knowledge/trading-investing/weighted-moving-average-wma/
+ https://www.technicalindicators.net/indicators-technical-analysis/83-moving-averages-simple-exponential-weighted
+
+ */
+
+public class WMA_Series : Single_TSeries_Indicator
+{
+ public WMA_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN)
+ {
+ for (int i = 0; i < this._p; i++) { this._weights.Add(i + 1); }
+ if (base._data.Count > 0) { base.Add(base._data); }
+ }
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly System.Collections.Generic.List _weights = new();
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ Add_Replace_Trim(_buffer, TValue.v, _p, update);
+
+ double _wma = 0;
+ for (int i = 0; i < _buffer.Count; i++) { _wma += _buffer[i] * this._weights[i]; }
+ _wma /= (this._buffer.Count * (this._buffer.Count + 1)) * 0.5;
+
+ base.Add((TValue.t, _wma), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Trends/ZLEMA_Series.cs b/Calculations/Trends/ZLEMA_Series.cs
similarity index 96%
rename from Source/Trends/ZLEMA_Series.cs
rename to Calculations/Trends/ZLEMA_Series.cs
index 2f4276d3..a72da3ce 100644
--- a/Source/Trends/ZLEMA_Series.cs
+++ b/Calculations/Trends/ZLEMA_Series.cs
@@ -1,62 +1,62 @@
-namespace QuanTAlib;
-using System;
-using System.Linq;
-
-/*
-ZLEMA: Zero Lag Exponential Moving Average
- The Zero lag exponential moving average (ZLEMA) indicator was created by John
- Ehlers and Ric Way.
-
-The formula for a given N-Day period and for a given Data series is:
- Lag = (Period-1)/2
- Ema Data = {Data+(Data-Data(Lag days ago))
- ZLEMA = EMA (EmaData,Period)
-
-Remark:
- The idea is do a regular exponential moving average (EMA) calculation but on a
- de-lagged data instead of doing it on the regular data. Data is de-lagged by
- removing the data from "lag" days ago thus removing (or attempting to remove)
- the cumulative lag effect of the moving average.
-
- */
-
-public class ZLEMA_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly double _k, _k1m;
- private double _lastema, _lastema_o;
- private int _llag;
- private readonly bool _useSMA;
-
- public ZLEMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN)
- {
- this._k = 2.0 / (this._p + 1);
- this._k1m = 1.0 - this._k;
- this._lastema = this._lastema_o = double.NaN;
- _llag = (int)((_p-1) * 0.5);
- _useSMA = useSMA;
- if (_data.Count > 0) { base.Add(_data); }
- }
-
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- int _lag = Math.Max(this.Count-_llag, 0);
- if (update) {
- _lastema = _lastema_o; _lag--;
- } else {
- _lastema_o = _lastema;
- }
- double _zl = TValue.v + (TValue.v - _data[_lag].v);
- double _ema = 0;
-
- if (this.Count < this._p && _useSMA) {
- Add_Replace_Trim(_buffer, _zl, _p, update);
- _ema = _buffer.Average();
- } else {
- _ema = (_zl * _k) + (_lastema * _k1m);
- }
- _lastema = _ema;
-
- base.Add((TValue.t, _ema), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+using System.Linq;
+
+/*
+ZLEMA: Zero Lag Exponential Moving Average
+ The Zero lag exponential moving average (ZLEMA) indicator was created by John
+ Ehlers and Ric Way.
+
+The formula for a given N-Day period and for a given Data series is:
+ Lag = (Period-1)/2
+ Ema Data = {Data+(Data-Data(Lag days ago))
+ ZLEMA = EMA (EmaData,Period)
+
+Remark:
+ The idea is do a regular exponential moving average (EMA) calculation but on a
+ de-lagged data instead of doing it on the regular data. Data is de-lagged by
+ removing the data from "lag" days ago thus removing (or attempting to remove)
+ the cumulative lag effect of the moving average.
+
+ */
+
+public class ZLEMA_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k, _k1m;
+ private double _lastema, _lastema_o;
+ private int _llag;
+ private readonly bool _useSMA;
+
+ public ZLEMA_Series(TSeries source, int period, bool useNaN = false, bool useSMA = true) : base(source, period, useNaN)
+ {
+ this._k = 2.0 / (this._p + 1);
+ this._k1m = 1.0 - this._k;
+ this._lastema = this._lastema_o = double.NaN;
+ _llag = (int)((_p-1) * 0.5);
+ _useSMA = useSMA;
+ if (_data.Count > 0) { base.Add(_data); }
+ }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ int _lag = Math.Max(this.Count-_llag, 0);
+ if (update) {
+ _lastema = _lastema_o; _lag--;
+ } else {
+ _lastema_o = _lastema;
+ }
+ double _zl = TValue.v + (TValue.v - _data[_lag].v);
+ double _ema = 0;
+
+ if (this.Count < this._p && _useSMA) {
+ Add_Replace_Trim(_buffer, _zl, _p, update);
+ _ema = _buffer.Average();
+ } else {
+ _ema = (_zl * _k) + (_lastema * _k1m);
+ }
+ _lastema = _ema;
+
+ base.Add((TValue.t, _ema), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Volatility/ADL_Series.cs b/Calculations/Volatility/ADL_Series.cs
similarity index 96%
rename from Source/Volatility/ADL_Series.cs
rename to Calculations/Volatility/ADL_Series.cs
index 7e0a962f..0eb43ec2 100644
--- a/Source/Volatility/ADL_Series.cs
+++ b/Calculations/Volatility/ADL_Series.cs
@@ -1,40 +1,40 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ADL: Chaikin Accumulation/Distribution Line
- ADL is a volume-based indicator that measures the cumulative Money Flow Volume:
-
- 1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low)
- 2. Money Flow Volume = Money Flow Multiplier x Volume for the Period
- 3. ADL = Previous ADL + Current Period's Money Flow Volume
-
-Sources:
- https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
-
- */
-
-public class ADL_Series : Single_TBars_Indicator
-{
- private double _lastadl, _lastlastadl;
-
- public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN)
- {
- _lastadl = _lastlastadl = 0;
- if (_bars.Count > 0) { base.Add(_bars); }
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
- {
- if (update) { this._lastadl = this._lastlastadl; }
-
- double _adl = 0;
- double tmp = TBar.h - TBar.l;
- if (tmp > 0.0 ) { _adl = _lastadl + ((2*TBar.c - TBar.l - TBar.h) / tmp * TBar.v); }
-
- this._lastlastadl = this._lastadl;
- this._lastadl = _adl;
-
- base.Add((TBar.t, _adl), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+ADL: Chaikin Accumulation/Distribution Line
+ ADL is a volume-based indicator that measures the cumulative Money Flow Volume:
+
+ 1. Money Flow Multiplier = [(Close - Low) - (High - Close)] /(High - Low)
+ 2. Money Flow Volume = Money Flow Multiplier x Volume for the Period
+ 3. ADL = Previous ADL + Current Period's Money Flow Volume
+
+Sources:
+ https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
+
+ */
+
+public class ADL_Series : Single_TBars_Indicator
+{
+ private double _lastadl, _lastlastadl;
+
+ public ADL_Series(TBars source, bool useNaN = false) : base(source, 0, useNaN)
+ {
+ _lastadl = _lastlastadl = 0;
+ if (_bars.Count > 0) { base.Add(_bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
+ {
+ if (update) { this._lastadl = this._lastlastadl; }
+
+ double _adl = 0;
+ double tmp = TBar.h - TBar.l;
+ if (tmp > 0.0 ) { _adl = _lastadl + ((2*TBar.c - TBar.l - TBar.h) / tmp * TBar.v); }
+
+ this._lastlastadl = this._lastadl;
+ this._lastadl = _adl;
+
+ base.Add((TBar.t, _adl), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Volatility/ADOSC_Series.cs b/Calculations/Volatility/ADOSC_Series.cs
similarity index 96%
rename from Source/Volatility/ADOSC_Series.cs
rename to Calculations/Volatility/ADOSC_Series.cs
index e5b279bb..9fca7e30 100644
--- a/Source/Volatility/ADOSC_Series.cs
+++ b/Calculations/Volatility/ADOSC_Series.cs
@@ -1,87 +1,87 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ADO: Chaikin Accumulation/Distribution Oscillator
- ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
- and fast (3-day) EMA(ADL):
-
- Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
-
-Sources:
- https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
-
- */
-
-
-public class ADOSC_Series : Single_TBars_Indicator
-{
- private readonly double _k1, _k2;
- private double _lastema1, _lastlastema1, _lastema2, _lastlastema2;
- private double _lastadl, _lastlastadl;
-
- public ADOSC_Series(TBars source, int shortPeriod = 3, int longPeriod =10, bool useNaN = false) : base(source, period: 0, useNaN)
- {
- _k1 = 2.0 / (shortPeriod + 1);
- _k2 = 2.0 / (longPeriod + 1);
- _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0;
- if (_bars.Count > 0) { base.Add(_bars); }
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
- {
- if (update) {
- _lastadl = _lastlastadl;
- _lastema1 = _lastlastema1;
- _lastema2 = _lastlastema2;
- }
-
- double _adl = 0;
- double tmp = TBar.h - TBar.l;
- if (tmp > 0.0) { _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); }
- if (this.Count == 0) { _lastema1 = _lastema2 = _adl; }
-
- double _ema1 = (_adl - _lastema1) * _k1 + _lastema1;
- double _ema2 = (_adl - _lastema2) * _k2 + _lastema2;
-
- _lastlastadl = _lastadl; _lastadl = _adl;
- _lastlastema1 = _lastema1; _lastema1 = _ema1;
- _lastlastema2 = _lastema2; _lastema2 = _ema2;
-
- double _adosc = _ema1 - _ema2;
- base.Add((TBar.t, _adosc), update, _NaN);
- }
-
-}
-/*
-public class ADOSC_Series : Single_TBars_Indicator
-{
- private readonly ADL_Series _TSadl;
-
- private readonly EMA_Series _TSslow;
- private readonly EMA_Series _TSfast;
- private readonly SUB_Series _TSado;
-
- public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
- {
- _TSadl = new(source: source, useNaN: false);
- _TSslow = new(source: _TSadl, period: 10, useNaN: false);
- _TSfast = new(source: _TSadl, period: 3, useNaN: false);
- _TSado = new(_TSfast, _TSslow);
-
- if (source.Count > 0)
- { base.Add(_TSado); }
- Console.WriteLine(base.Count);
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
- {
- if (update)
- { _TSadl.Add(TBar, true); }
-
- double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
- var result = (TBar.t, _ado);
- base.Add(result, update);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+ADO: Chaikin Accumulation/Distribution Oscillator
+ ADO measures the momentum of ADL using the difference between slow (10-day) EMA(ADL)
+ and fast (3-day) EMA(ADL):
+
+ Chaikin A/D Oscillator = (3-day EMA of ADL) - (10-day EMA of ADL)
+
+Sources:
+ https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_oscillator
+
+ */
+
+
+public class ADOSC_Series : Single_TBars_Indicator
+{
+ private readonly double _k1, _k2;
+ private double _lastema1, _lastlastema1, _lastema2, _lastlastema2;
+ private double _lastadl, _lastlastadl;
+
+ public ADOSC_Series(TBars source, int shortPeriod = 3, int longPeriod =10, bool useNaN = false) : base(source, period: 0, useNaN)
+ {
+ _k1 = 2.0 / (shortPeriod + 1);
+ _k2 = 2.0 / (longPeriod + 1);
+ _lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0;
+ if (_bars.Count > 0) { base.Add(_bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
+ {
+ if (update) {
+ _lastadl = _lastlastadl;
+ _lastema1 = _lastlastema1;
+ _lastema2 = _lastlastema2;
+ }
+
+ double _adl = 0;
+ double tmp = TBar.h - TBar.l;
+ if (tmp > 0.0) { _adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v); }
+ if (this.Count == 0) { _lastema1 = _lastema2 = _adl; }
+
+ double _ema1 = (_adl - _lastema1) * _k1 + _lastema1;
+ double _ema2 = (_adl - _lastema2) * _k2 + _lastema2;
+
+ _lastlastadl = _lastadl; _lastadl = _adl;
+ _lastlastema1 = _lastema1; _lastema1 = _ema1;
+ _lastlastema2 = _lastema2; _lastema2 = _ema2;
+
+ double _adosc = _ema1 - _ema2;
+ base.Add((TBar.t, _adosc), update, _NaN);
+ }
+
+}
+/*
+public class ADOSC_Series : Single_TBars_Indicator
+{
+ private readonly ADL_Series _TSadl;
+
+ private readonly EMA_Series _TSslow;
+ private readonly EMA_Series _TSfast;
+ private readonly SUB_Series _TSado;
+
+ public ADOSC_Series(TBars source, bool useNaN = false) : base(source, period: 0, useNaN)
+ {
+ _TSadl = new(source: source, useNaN: false);
+ _TSslow = new(source: _TSadl, period: 10, useNaN: false);
+ _TSfast = new(source: _TSadl, period: 3, useNaN: false);
+ _TSado = new(_TSfast, _TSslow);
+
+ if (source.Count > 0)
+ { base.Add(_TSado); }
+ Console.WriteLine(base.Count);
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
+ {
+ if (update)
+ { _TSadl.Add(TBar, true); }
+
+ double _ado = this._TSado[(this.Count < this._TSado.Count) ? this.Count : this._TSado.Count - 1].v;
+ var result = (TBar.t, _ado);
+ base.Add(result, update);
+ }
+}
*/
\ No newline at end of file
diff --git a/Source/Volatility/ATRP_Series.cs b/Calculations/Volatility/ATRP_Series.cs
similarity index 97%
rename from Source/Volatility/ATRP_Series.cs
rename to Calculations/Volatility/ATRP_Series.cs
index 72fdcd48..086db3db 100644
--- a/Source/Volatility/ATRP_Series.cs
+++ b/Calculations/Volatility/ATRP_Series.cs
@@ -1,48 +1,48 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ATRP: Average True Range Percent
- Average True Range Percent is (ATR/Close Price)*100.
- This normalizes so it can be compared to other stocks.
-
-Sources:
- https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atrp
-
- */
-
-public class ATRP_Series : Single_TBars_Indicator {
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly double _k;
- private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum;
- private readonly int _period;
-
- public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) {
- _period = period;
- _k = 1.0 / (double)(_p);
- _lastatr = _lastlastatr = _cm1 = _lastcm1 = _sum = _oldsum = 0;
- if (this._bars.Count > 0) { base.Add(this._bars); }
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) {
- if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; }
- else { _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; }
-
- if (this.Count == 0) { _cm1 = TBar.c; }
- double d1 = Math.Abs(TBar.h - TBar.l);
- double d2 = Math.Abs(_cm1 - TBar.h);
- double d3 = Math.Abs(_cm1 - TBar.l);
- (DateTime t, double v) d = (TBar.t, Math.Max(d1, Math.Max(d2, d3)));
- _cm1 = TBar.c;
-
- double _atr = 0;
- if (this.Count == 0) { _atr = d.v; }
- else if (this.Count < _p + 1) { _sum += d.v; _atr = _sum / (this.Count); }
- else { _atr = _k * (d.v - _lastatr) + _lastatr; }
- _lastatr = _atr;
-
- double _atrp = 100 * (_atr / TBar.c);
- var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atrp);
- base.Add(ret, update);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+ATRP: Average True Range Percent
+ Average True Range Percent is (ATR/Close Price)*100.
+ This normalizes so it can be compared to other stocks.
+
+Sources:
+ https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/atrp
+
+ */
+
+public class ATRP_Series : Single_TBars_Indicator {
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k;
+ private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum;
+ private readonly int _period;
+
+ public ATRP_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) {
+ _period = period;
+ _k = 1.0 / (double)(_p);
+ _lastatr = _lastlastatr = _cm1 = _lastcm1 = _sum = _oldsum = 0;
+ if (this._bars.Count > 0) { base.Add(this._bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) {
+ if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; }
+ else { _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; }
+
+ if (this.Count == 0) { _cm1 = TBar.c; }
+ double d1 = Math.Abs(TBar.h - TBar.l);
+ double d2 = Math.Abs(_cm1 - TBar.h);
+ double d3 = Math.Abs(_cm1 - TBar.l);
+ (DateTime t, double v) d = (TBar.t, Math.Max(d1, Math.Max(d2, d3)));
+ _cm1 = TBar.c;
+
+ double _atr = 0;
+ if (this.Count == 0) { _atr = d.v; }
+ else if (this.Count < _p + 1) { _sum += d.v; _atr = _sum / (this.Count); }
+ else { _atr = _k * (d.v - _lastatr) + _lastatr; }
+ _lastatr = _atr;
+
+ double _atrp = 100 * (_atr / TBar.c);
+ var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atrp);
+ base.Add(ret, update);
+ }
+}
diff --git a/Source/Volatility/ATR_Series.cs b/Calculations/Volatility/ATR_Series.cs
similarity index 97%
rename from Source/Volatility/ATR_Series.cs
rename to Calculations/Volatility/ATR_Series.cs
index cd99885f..bc641e92 100644
--- a/Source/Volatility/ATR_Series.cs
+++ b/Calculations/Volatility/ATR_Series.cs
@@ -1,49 +1,49 @@
-namespace QuanTAlib;
-using System;
-
-/*
-ATR: wildeR Moving Average
- The average true range (ATR) is a price volatility indicator
- showing the average price variation of assets within a given time period.
-
-Sources:
- https://en.wikipedia.org/wiki/Average_true_range
- https://www.tradingview.com/wiki/Average_True_Range_(ATR)
- https://www.investopedia.com/terms/a/atr.asp
-
- */
-
-public class ATR_Series : Single_TBars_Indicator {
- private readonly System.Collections.Generic.List _buffer = new();
- private readonly double _k;
- private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum;
- private readonly int _period;
-
- public ATR_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) {
- _period = period;
- _k = 1.0 / (double)(_p);
- _lastatr = _lastlastatr = _cm1 = _lastcm1 = _sum = _oldsum = 0;
- if (this._bars.Count > 0) { base.Add(this._bars); }
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) {
- if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; }
- else { _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; }
-
- if (this.Count == 0) { _cm1 = TBar.c; }
- double d1 = Math.Abs(TBar.h - TBar.l);
- double d2 = Math.Abs(_cm1 - TBar.h);
- double d3 = Math.Abs(_cm1 - TBar.l);
- (DateTime t, double v) d = (TBar.t, Math.Max(d1, Math.Max(d2, d3)));
- _cm1 = TBar.c;
-
- double _atr = 0;
- if (this.Count == 0) { _atr = d.v; }
- else if (this.Count < _p + 1) { _sum += d.v; _atr = _sum / (this.Count); }
- else { _atr = _k * (d.v - _lastatr) + _lastatr; }
- _lastatr = _atr;
-
- var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atr);
- base.Add(ret, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+ATR: wildeR Moving Average
+ The average true range (ATR) is a price volatility indicator
+ showing the average price variation of assets within a given time period.
+
+Sources:
+ https://en.wikipedia.org/wiki/Average_true_range
+ https://www.tradingview.com/wiki/Average_True_Range_(ATR)
+ https://www.investopedia.com/terms/a/atr.asp
+
+ */
+
+public class ATR_Series : Single_TBars_Indicator {
+ private readonly System.Collections.Generic.List _buffer = new();
+ private readonly double _k;
+ private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum;
+ private readonly int _period;
+
+ public ATR_Series(TBars source, int period, bool useNaN = false) : base(source, period, useNaN) {
+ _period = period;
+ _k = 1.0 / (double)(_p);
+ _lastatr = _lastlastatr = _cm1 = _lastcm1 = _sum = _oldsum = 0;
+ if (this._bars.Count > 0) { base.Add(this._bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update) {
+ if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; }
+ else { _lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum; }
+
+ if (this.Count == 0) { _cm1 = TBar.c; }
+ double d1 = Math.Abs(TBar.h - TBar.l);
+ double d2 = Math.Abs(_cm1 - TBar.h);
+ double d3 = Math.Abs(_cm1 - TBar.l);
+ (DateTime t, double v) d = (TBar.t, Math.Max(d1, Math.Max(d2, d3)));
+ _cm1 = TBar.c;
+
+ double _atr = 0;
+ if (this.Count == 0) { _atr = d.v; }
+ else if (this.Count < _p + 1) { _sum += d.v; _atr = _sum / (this.Count); }
+ else { _atr = _k * (d.v - _lastatr) + _lastatr; }
+ _lastatr = _atr;
+
+ var ret = (d.t, this.Count < this._p - 1 && this._NaN ? double.NaN : _atr);
+ base.Add(ret, update);
+ }
}
\ No newline at end of file
diff --git a/Source/Volatility/BBANDS_Series.cs b/Calculations/Volatility/BBANDS_Series.cs
similarity index 97%
rename from Source/Volatility/BBANDS_Series.cs
rename to Calculations/Volatility/BBANDS_Series.cs
index 499fba44..169f8f35 100644
--- a/Source/Volatility/BBANDS_Series.cs
+++ b/Calculations/Volatility/BBANDS_Series.cs
@@ -1,73 +1,73 @@
-namespace QuanTAlib;
-using System;
-
-/*
-BBANDS: Bollinger Bands®
- Price channels created by John Bollinger, depict volatility as standard deviation boundary
- line range from a moving average of price. The bands automatically widen when volatility
- increases and contract when volatility decreases. Their dynamic nature allows them to be
- used on different securities with the standard settings.
-
- Mid Band = simple moving average (SMA)
- Upper Band = SMA + (standard deviation of price x multiplier)
- Lower Band = SMA - (standard deviation of price x multiplier)
- Bandwidth = Width of the channel: (Upper-Lower)/SMA
- %B = The location of the data point within the channel: (Price-Lower)/(Upper/Lower)
- Z-Score = number of standard deviations of the data point from SMA
-
-Sources:
- https://www.investopedia.com/terms/b/bollingerbands.asp
- https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands
-
-Note:
- Bollinger Bands® is a registered trademark of John A. Bollinger.
-
- */
-
-public class BBANDS_Series : Single_TSeries_Indicator
-{
- public SMA_Series Mid { get; }
- public ADD_Series Upper { get; }
- public SUB_Series Lower { get; }
- public DIV_Series PercentB { get; }
- public DIV_Series Bandwidth { get; }
- public DIV_Series Zscore { get; }
-
- private readonly SDEV_Series _sdev;
- private readonly MUL_Series _mulsdev;
- private readonly SUB_Series _pbdnd;
- private readonly SUB_Series _pbdvr;
- private readonly SUB_Series _zdnd;
-
- public BBANDS_Series(TSeries source, int period = 26, double multiplier = 2.0, bool useNaN = false)
- : base(source, period: 0, useNaN)
- {
- this.Mid = new(source: source, period: period, useNaN: useNaN);
-
- _sdev = new(source, period, useNaN: useNaN);
- _mulsdev = new(_sdev, multiplier);
- this.Upper = new(Mid, _mulsdev);
- this.Lower = new(Mid, _mulsdev);
-
- _pbdnd = new(source, Lower);
- _pbdvr = new(Upper, Lower);
-
- this.PercentB = new(_pbdnd, _pbdvr);
- this.Bandwidth = new(_pbdvr, Mid);
-
- _zdnd = new(source, Mid);
- this.Zscore = new(_zdnd, _sdev);
-
- if (source.Count > 0)
- { base.Add(this.Bandwidth); }
- }
- public override void Add((System.DateTime t, double v) TValue, bool update)
- {
- double _bbandwidth;
- if (update)
- { _sdev.Add(TValue, true); }
- _bbandwidth = this.Bandwidth[(this.Count < this.Bandwidth.Count) ? this.Count : this.Bandwidth.Count - 1].v;
- var result = (TValue.t, _bbandwidth);
- base.Add(result, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+BBANDS: Bollinger Bands®
+ Price channels created by John Bollinger, depict volatility as standard deviation boundary
+ line range from a moving average of price. The bands automatically widen when volatility
+ increases and contract when volatility decreases. Their dynamic nature allows them to be
+ used on different securities with the standard settings.
+
+ Mid Band = simple moving average (SMA)
+ Upper Band = SMA + (standard deviation of price x multiplier)
+ Lower Band = SMA - (standard deviation of price x multiplier)
+ Bandwidth = Width of the channel: (Upper-Lower)/SMA
+ %B = The location of the data point within the channel: (Price-Lower)/(Upper/Lower)
+ Z-Score = number of standard deviations of the data point from SMA
+
+Sources:
+ https://www.investopedia.com/terms/b/bollingerbands.asp
+ https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands
+
+Note:
+ Bollinger Bands® is a registered trademark of John A. Bollinger.
+
+ */
+
+public class BBANDS_Series : Single_TSeries_Indicator
+{
+ public SMA_Series Mid { get; }
+ public ADD_Series Upper { get; }
+ public SUB_Series Lower { get; }
+ public DIV_Series PercentB { get; }
+ public DIV_Series Bandwidth { get; }
+ public DIV_Series Zscore { get; }
+
+ private readonly SDEV_Series _sdev;
+ private readonly MUL_Series _mulsdev;
+ private readonly SUB_Series _pbdnd;
+ private readonly SUB_Series _pbdvr;
+ private readonly SUB_Series _zdnd;
+
+ public BBANDS_Series(TSeries source, int period = 26, double multiplier = 2.0, bool useNaN = false)
+ : base(source, period: 0, useNaN)
+ {
+ this.Mid = new(source: source, period: period, useNaN: useNaN);
+
+ _sdev = new(source, period, useNaN: useNaN);
+ _mulsdev = new(_sdev, multiplier);
+ this.Upper = new(Mid, _mulsdev);
+ this.Lower = new(Mid, _mulsdev);
+
+ _pbdnd = new(source, Lower);
+ _pbdvr = new(Upper, Lower);
+
+ this.PercentB = new(_pbdnd, _pbdvr);
+ this.Bandwidth = new(_pbdvr, Mid);
+
+ _zdnd = new(source, Mid);
+ this.Zscore = new(_zdnd, _sdev);
+
+ if (source.Count > 0)
+ { base.Add(this.Bandwidth); }
+ }
+ public override void Add((System.DateTime t, double v) TValue, bool update)
+ {
+ double _bbandwidth;
+ if (update)
+ { _sdev.Add(TValue, true); }
+ _bbandwidth = this.Bandwidth[(this.Count < this.Bandwidth.Count) ? this.Count : this.Bandwidth.Count - 1].v;
+ var result = (TValue.t, _bbandwidth);
+ base.Add(result, update);
+ }
}
\ No newline at end of file
diff --git a/Source/Volatility/CMO_Series.cs b/Calculations/Volatility/CMO_Series.cs
similarity index 97%
rename from Source/Volatility/CMO_Series.cs
rename to Calculations/Volatility/CMO_Series.cs
index 9a47b469..9295dfa5 100644
--- a/Source/Volatility/CMO_Series.cs
+++ b/Calculations/Volatility/CMO_Series.cs
@@ -1,47 +1,47 @@
-namespace QuanTAlib;
-using System;
-
-/*
-CMO: Chande Momentum Oscillator
- Chande Momentum Oscillator (also known as CMO indicator) was developed by Tushar S. Chande
- CMO is similar to other momentum oscillators (e.g. RSI or Stochastics). Alike RSI oscillator,
- the CMO values move in the range from -100 to +100 points and its aim is to detect the
- overbought and oversold market conditions. CMO calculates the price momentum on both the up
- days as well as the down days. The CMO calculation is based on non-smoothed price values
- meaning that it can reach its extremes more frequently and the short-time swings are more visible.
-
-Sources:
- https://www.technicalindicators.net/indicators-technical-analysis/144-cmo-chande-momentum-oscillator
-
- */
-
-public class CMO_Series : Single_TSeries_Indicator {
- private readonly System.Collections.Generic.List _buff_up = new();
- private readonly System.Collections.Generic.List _buff_dn = new();
- private double _plast_value, _last_value;
-
- public CMO_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
- if (this._data.Count > 0) { base.Add(this._data); }
- }
-
- public override void Add((DateTime t, double v) TValue, bool update) {
- if (this.Count == 0) { _plast_value = _last_value = TValue.v; }
- if (update) _last_value = _plast_value; else _plast_value = _last_value;
-
- Add_Replace_Trim(_buff_up, (TValue.v > _last_value) ? TValue.v-_last_value : 0, _p, update);
- Add_Replace_Trim(_buff_dn, (TValue.v < _last_value) ? _last_value-TValue.v : 0, _p, update);
- _last_value = TValue.v;
-
- double _cmo_up = 0;
- double _cmo_dn = 0;
- for (int i = 0; i < Math.Min(_buff_up.Count, _buff_dn.Count); i++) {
- _cmo_up += _buff_up[i];
- _cmo_dn += _buff_dn[i];
- }
-
- double _cmo = 100 * (_cmo_up - _cmo_dn) / (_cmo_up + _cmo_dn);
- if (_cmo_up + _cmo_dn == 0)
- _cmo = 0;
- base.Add((TValue.t, _cmo), update, _NaN);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+CMO: Chande Momentum Oscillator
+ Chande Momentum Oscillator (also known as CMO indicator) was developed by Tushar S. Chande
+ CMO is similar to other momentum oscillators (e.g. RSI or Stochastics). Alike RSI oscillator,
+ the CMO values move in the range from -100 to +100 points and its aim is to detect the
+ overbought and oversold market conditions. CMO calculates the price momentum on both the up
+ days as well as the down days. The CMO calculation is based on non-smoothed price values
+ meaning that it can reach its extremes more frequently and the short-time swings are more visible.
+
+Sources:
+ https://www.technicalindicators.net/indicators-technical-analysis/144-cmo-chande-momentum-oscillator
+
+ */
+
+public class CMO_Series : Single_TSeries_Indicator {
+ private readonly System.Collections.Generic.List _buff_up = new();
+ private readonly System.Collections.Generic.List _buff_dn = new();
+ private double _plast_value, _last_value;
+
+ public CMO_Series(TSeries source, int period, bool useNaN = false) : base(source, period, useNaN) {
+ if (this._data.Count > 0) { base.Add(this._data); }
+ }
+
+ public override void Add((DateTime t, double v) TValue, bool update) {
+ if (this.Count == 0) { _plast_value = _last_value = TValue.v; }
+ if (update) _last_value = _plast_value; else _plast_value = _last_value;
+
+ Add_Replace_Trim(_buff_up, (TValue.v > _last_value) ? TValue.v-_last_value : 0, _p, update);
+ Add_Replace_Trim(_buff_dn, (TValue.v < _last_value) ? _last_value-TValue.v : 0, _p, update);
+ _last_value = TValue.v;
+
+ double _cmo_up = 0;
+ double _cmo_dn = 0;
+ for (int i = 0; i < Math.Min(_buff_up.Count, _buff_dn.Count); i++) {
+ _cmo_up += _buff_up[i];
+ _cmo_dn += _buff_dn[i];
+ }
+
+ double _cmo = 100 * (_cmo_up - _cmo_dn) / (_cmo_up + _cmo_dn);
+ if (_cmo_up + _cmo_dn == 0)
+ _cmo = 0;
+ base.Add((TValue.t, _cmo), update, _NaN);
+ }
}
\ No newline at end of file
diff --git a/Source/Volatility/RSI_Series.cs b/Calculations/Volatility/RSI_Series.cs
similarity index 97%
rename from Source/Volatility/RSI_Series.cs
rename to Calculations/Volatility/RSI_Series.cs
index e4f6a350..0805df35 100644
--- a/Source/Volatility/RSI_Series.cs
+++ b/Calculations/Volatility/RSI_Series.cs
@@ -1,78 +1,78 @@
-namespace QuanTAlib;
-using System;
-
-/*
-RSI: Relative Strength Index
- Created by J. Welles Wilder, the Relative Strength Index measures strength
- of the winning/losing streak over N lookback periods on a scale of 0 to 100,
- to depict overbought and oversold conditions.
-
-Sources:
- https://www.investopedia.com/terms/r/rsi.asp
-
- */
-
-public class RSI_Series : Single_TSeries_Indicator
-{
- private readonly System.Collections.Generic.List _gain = new();
- private readonly System.Collections.Generic.List _loss = new();
- private double _avgGain, _avgLoss, _lastValue;
- private double _avgGain_o, _avgLoss_o, _lastValue_o;
- private int i;
-
- public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN) {
- i = 0;
- if (source.Count > 0) { base.Add(source); }
- }
-
- public override void Add((System.DateTime t, double v) TValue, bool update) {
- double _rsi = 0;
- if (update) {
- _lastValue = _lastValue_o;
- _avgGain = _avgGain_o;
- _avgLoss = _avgLoss_o;
- }
- else {
- _lastValue_o = _lastValue;
- _avgGain_o = _avgGain;
- _avgLoss_o = _avgLoss;
- }
-
- if (i == 0) { _lastValue = TValue.v; }
-
- double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
- Add_Replace_Trim(_gain, _gainval, _p, update);
- double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
- Add_Replace_Trim(_loss, _lossval, _p, update);
- _lastValue = TValue.v;
-
- // calculate RSI
- if (i > _p)
- {
- _avgGain = ((_avgGain * (_p - 1)) + _gain[_gain.Count - 1]) / _p;
- _avgLoss = ((_avgLoss * (_p - 1)) + _loss[_loss.Count - 1]) / _p;
- if (_avgLoss > 0) {
- double rs = _avgGain / _avgLoss;
- _rsi = 100 - (100 / (1 + rs));
- }
- else { _rsi = 100; }
- }
- // initialize average gain
- else
- {
- double _sumGain = 0;
- for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
- double _sumLoss = 0;
- for (int p = 0; p < _loss.Count; p++) { _sumLoss += _loss[p]; }
-
- _avgGain = _sumGain / _gain.Count;
- _avgLoss = _sumLoss / _loss.Count;
-
- _rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100;
- }
-
- if (!update) { i++; }
- var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
- base.Add(result, update);
- }
+namespace QuanTAlib;
+using System;
+
+/*
+RSI: Relative Strength Index
+ Created by J. Welles Wilder, the Relative Strength Index measures strength
+ of the winning/losing streak over N lookback periods on a scale of 0 to 100,
+ to depict overbought and oversold conditions.
+
+Sources:
+ https://www.investopedia.com/terms/r/rsi.asp
+
+ */
+
+public class RSI_Series : Single_TSeries_Indicator
+{
+ private readonly System.Collections.Generic.List _gain = new();
+ private readonly System.Collections.Generic.List _loss = new();
+ private double _avgGain, _avgLoss, _lastValue;
+ private double _avgGain_o, _avgLoss_o, _lastValue_o;
+ private int i;
+
+ public RSI_Series(TSeries source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN) {
+ i = 0;
+ if (source.Count > 0) { base.Add(source); }
+ }
+
+ public override void Add((System.DateTime t, double v) TValue, bool update) {
+ double _rsi = 0;
+ if (update) {
+ _lastValue = _lastValue_o;
+ _avgGain = _avgGain_o;
+ _avgLoss = _avgLoss_o;
+ }
+ else {
+ _lastValue_o = _lastValue;
+ _avgGain_o = _avgGain;
+ _avgLoss_o = _avgLoss;
+ }
+
+ if (i == 0) { _lastValue = TValue.v; }
+
+ double _gainval = (TValue.v > _lastValue) ? TValue.v - _lastValue : 0;
+ Add_Replace_Trim(_gain, _gainval, _p, update);
+ double _lossval = (TValue.v < _lastValue) ? _lastValue - TValue.v : 0;
+ Add_Replace_Trim(_loss, _lossval, _p, update);
+ _lastValue = TValue.v;
+
+ // calculate RSI
+ if (i > _p)
+ {
+ _avgGain = ((_avgGain * (_p - 1)) + _gain[_gain.Count - 1]) / _p;
+ _avgLoss = ((_avgLoss * (_p - 1)) + _loss[_loss.Count - 1]) / _p;
+ if (_avgLoss > 0) {
+ double rs = _avgGain / _avgLoss;
+ _rsi = 100 - (100 / (1 + rs));
+ }
+ else { _rsi = 100; }
+ }
+ // initialize average gain
+ else
+ {
+ double _sumGain = 0;
+ for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
+ double _sumLoss = 0;
+ for (int p = 0; p < _loss.Count; p++) { _sumLoss += _loss[p]; }
+
+ _avgGain = _sumGain / _gain.Count;
+ _avgLoss = _sumLoss / _loss.Count;
+
+ _rsi = (_avgLoss > 0) ? 100 - (100 / (1 + (_avgGain / _avgLoss))) : 100;
+ }
+
+ if (!update) { i++; }
+ var result = (TValue.t, (this.Count < this._p && this._NaN) ? double.NaN : _rsi);
+ base.Add(result, update);
+ }
}
\ No newline at end of file
diff --git a/Source/Volume/OBV_Series.cs b/Calculations/Volume/OBV_Series.cs
similarity index 97%
rename from Source/Volume/OBV_Series.cs
rename to Calculations/Volume/OBV_Series.cs
index c77570a8..73d4e327 100644
--- a/Source/Volume/OBV_Series.cs
+++ b/Calculations/Volume/OBV_Series.cs
@@ -1,59 +1,59 @@
-namespace QuanTAlib;
-using System;
-
-/*
-OBV: On-Balance Volume
- On-balance volume (OBV) is a technical trading momentum indicator that uses volume flow to predict
- changes in stock price. Joseph Granville first developed the OBV metric in the 1963 book
- Granville's New Key to Stock Market Profits.
-
- | +volume; if close > close[previous]
- OBV = OBV[previous] + | 0; if close = close[previous]
- | -volume; if close < close[previous]
-
-Sources:
- https://www.investopedia.com/terms/o/onbalancevolume.asp
- https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
- https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
- https://www.motivewave.com/studies/on_balance_volume.htm
-
-Note:
- There is no consensus on what is the first OBV value in the series:
- - TA-LIB uses the first volume: OBV[0] = volume[0]
- - Skender stock library uses 0: OBV[0] = 0
-
- */
-
-public class OBV_Series : Single_TBars_Indicator
-{
- private double _lastobv, _lastlastobv;
- private double _lastclose, _lastlastclose;
- public OBV_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
- {
- this._lastobv = this._lastlastobv = 0;
- this._lastclose = this._lastlastclose = 0;
- if (_bars.Count > 0) { base.Add(_bars); }
- }
-
- public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
- {
- if (update)
- {
- this._lastobv = this._lastlastobv;
- this._lastclose = this._lastlastclose;
- }
-
- double _obv = this._lastobv;
- if (TBar.c > this._lastclose) { _obv += TBar.v; }
- if (TBar.c < this._lastclose) { _obv -= TBar.v; }
-
- this._lastlastobv = this._lastobv;
- this._lastobv = _obv;
-
- this._lastlastclose = this._lastclose;
- this._lastclose = TBar.c;
-
- var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _obv);
- base.Add(result, update);
- }
-}
+namespace QuanTAlib;
+using System;
+
+/*
+OBV: On-Balance Volume
+ On-balance volume (OBV) is a technical trading momentum indicator that uses volume flow to predict
+ changes in stock price. Joseph Granville first developed the OBV metric in the 1963 book
+ Granville's New Key to Stock Market Profits.
+
+ | +volume; if close > close[previous]
+ OBV = OBV[previous] + | 0; if close = close[previous]
+ | -volume; if close < close[previous]
+
+Sources:
+ https://www.investopedia.com/terms/o/onbalancevolume.asp
+ https://www.tradingview.com/wiki/On_Balance_Volume_(OBV)
+ https://www.tradingtechnologies.com/help/x-study/technical-indicator-definitions/on-balance-volume-obv/
+ https://www.motivewave.com/studies/on_balance_volume.htm
+
+Note:
+ There is no consensus on what is the first OBV value in the series:
+ - TA-LIB uses the first volume: OBV[0] = volume[0]
+ - Skender stock library uses 0: OBV[0] = 0
+
+ */
+
+public class OBV_Series : Single_TBars_Indicator
+{
+ private double _lastobv, _lastlastobv;
+ private double _lastclose, _lastlastclose;
+ public OBV_Series(TBars source, int period = 10, bool useNaN = false) : base(source, period: period, useNaN: useNaN)
+ {
+ this._lastobv = this._lastlastobv = 0;
+ this._lastclose = this._lastlastclose = 0;
+ if (_bars.Count > 0) { base.Add(_bars); }
+ }
+
+ public override void Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update)
+ {
+ if (update)
+ {
+ this._lastobv = this._lastlastobv;
+ this._lastclose = this._lastlastclose;
+ }
+
+ double _obv = this._lastobv;
+ if (TBar.c > this._lastclose) { _obv += TBar.v; }
+ if (TBar.c < this._lastclose) { _obv -= TBar.v; }
+
+ this._lastlastobv = this._lastobv;
+ this._lastobv = _obv;
+
+ this._lastlastclose = this._lastclose;
+ this._lastclose = TBar.c;
+
+ var result = (TBar.t, (this.Count < this._p && this._NaN) ? double.NaN : _obv);
+ base.Add(result, update);
+ }
+}
diff --git a/Indicators/Basics/QuanTAlib_Indicator.cs b/Indicators/Basics/QuanTAlib_Indicator.cs
new file mode 100644
index 00000000..ea2644a6
--- /dev/null
+++ b/Indicators/Basics/QuanTAlib_Indicator.cs
@@ -0,0 +1,40 @@
+using TradingPlatform.BusinessLayer;
+using System.Drawing;
+using QuanTAlib;
+using System;
+using TradingPlatform.BusinessLayer.Chart;
+
+namespace QuanTAlib;
+
+public class QuanTAlib_Indicator : Indicator {
+ protected TBars bars;
+ protected IChartWindow mainWindow;
+ protected Graphics graphics;
+ protected int firstOnScreenBarIndex, lastOnScreenBarIndex;
+
+ protected override void OnInit() {
+ base.OnInit();
+ bars = new();
+ }
+
+ protected override void OnUpdate(UpdateArgs args) {
+ base.OnUpdate(args);
+ bars.Add(Time(), GetPrice(PriceType.Open),
+ GetPrice(PriceType.High),
+ GetPrice(PriceType.Low),
+ GetPrice(PriceType.Close),
+ GetPrice(PriceType.Volume),
+ update: !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar));
+ }
+ public override void OnPaintChart(PaintChartEventArgs args) {
+ base.OnPaintChart(args);
+ if (this.CurrentChart == null) return;
+ graphics = args.Graphics;
+ mainWindow = this.CurrentChart.MainWindow;
+
+ DateTime leftTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Left);
+ DateTime rightTime = mainWindow.CoordinatesConverter.GetTime(mainWindow.ClientRectangle.Right);
+ firstOnScreenBarIndex = (int)mainWindow.CoordinatesConverter.GetBarIndex(leftTime);
+ lastOnScreenBarIndex = (int)Math.Ceiling(mainWindow.CoordinatesConverter.GetBarIndex(rightTime));
+ }
+}
\ No newline at end of file
diff --git a/Indicators/Charts/ATR_chart.cs b/Indicators/Charts/ATR_chart.cs
new file mode 100644
index 00000000..c8fd76f9
--- /dev/null
+++ b/Indicators/Charts/ATR_chart.cs
@@ -0,0 +1,32 @@
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class ATR_chart : QuanTAlib_Indicator {
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private readonly int Period = 10;
+
+ #endregion Parameters
+
+ private ATR_Series indicator;
+
+ public ATR_chart()
+ {
+ this.SeparateWindow = true;
+ this.Name = "ATR - Average True Range";
+ this.Description = "Average True Range description";
+ this.AddLineSeries("ATR", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit() { base.OnInit();
+ indicator = new(source: bars, period: Period, useNaN: false);
+ }
+
+ protected override void OnUpdate(UpdateArgs args) {
+ base.OnUpdate(args);
+ this.SetValue(indicator[^1].v, lineIndex: 0);
+ }
+
+}
diff --git a/Quantower/Indicators/BIAS_chart.cs b/Indicators/Charts/BIAS_chart.cs
similarity index 100%
rename from Quantower/Indicators/BIAS_chart.cs
rename to Indicators/Charts/BIAS_chart.cs
diff --git a/Quantower/Indicators/CCI_chart.cs b/Indicators/Charts/CCI_chart.cs
similarity index 96%
rename from Quantower/Indicators/CCI_chart.cs
rename to Indicators/Charts/CCI_chart.cs
index 38d5ec7e..748828f5 100644
--- a/Quantower/Indicators/CCI_chart.cs
+++ b/Indicators/Charts/CCI_chart.cs
@@ -1,43 +1,43 @@
-using System.Diagnostics;
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class CCI_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private readonly int Period = 10;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////
- private CCI_Series indicator;
- ///////
-
- public CCI_chart()
- {
- this.SeparateWindow = true;
- this.Name = "CCI - Commodity Channel Index";
- this.Description = "CCI description";
- this.AddLineSeries("CCI", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: bars, period: this.Period, useNaN: false);
- }
-
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = (args.Reason != UpdateReason.NewBar && args.Reason != UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
- this.SetValue(result);
- }
-}
+using System.Diagnostics;
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class CCI_chart : Indicator
+{
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private readonly int Period = 10;
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////
+ private CCI_Series indicator;
+ ///////
+
+ public CCI_chart()
+ {
+ this.SeparateWindow = true;
+ this.Name = "CCI - Commodity Channel Index";
+ this.Description = "CCI description";
+ this.AddLineSeries("CCI", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit()
+ {
+ this.bars = new();
+ this.indicator = new(source: bars, period: this.Period, useNaN: false);
+ }
+
+ protected override void OnUpdate(UpdateArgs args)
+ {
+ bool update = (args.Reason != UpdateReason.NewBar && args.Reason != UpdateReason.HistoricalBar);
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
+ this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
+ double result = this.indicator[this.indicator.Count - 1].v;
+ this.SetValue(result);
+ }
+}
diff --git a/Quantower/Indicators/DEMA_chart.cs b/Indicators/Charts/DEMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/DEMA_chart.cs
rename to Indicators/Charts/DEMA_chart.cs
diff --git a/Indicators/Charts/DJMA_chart.cs b/Indicators/Charts/DJMA_chart.cs
new file mode 100644
index 00000000..b58824f3
--- /dev/null
+++ b/Indicators/Charts/DJMA_chart.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class DJMA_chart : Indicator {
+ #region Parameters
+
+ [InputParameter("Fast Data source", 0, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int FDataSource = 3;
+
+ [InputParameter("Fast Smoothing period", 1, 1, 999, 1, 1)]
+ private int FPeriod = 12;
+
+ [InputParameter("Fast Volatility short", 2, 3, 50, 1, 1)]
+ private int FVshort = 10;
+
+ [InputParameter("Fast Volatility long", 3, 20, 500, 5, 1)]
+ private int FVlong = 65;
+
+ [InputParameter("Fast Phase", 4, -100, 100, 1, 2)]
+ private double FJphase = 100.0;
+
+ [InputParameter("Slow Data source", 5, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int SDataSource = 3;
+
+ [InputParameter("Slow Smoothing period", 6, 1, 999, 1, 1)]
+ private int SPeriod = 26;
+
+ [InputParameter("Slow Volatility short", 7, 3, 50, 1, 1)]
+ private int SVshort = 10;
+
+ [InputParameter("Slow Volatility long", 8, 20, 500, 5, 1)]
+ private int SVlong = 65;
+
+ [InputParameter("Slow Phase", 9, -100, 100, 1, 2)]
+ private double SJphase = -100.0;
+
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////
+ private JMA_Series fJma, sJma;
+ ///////
+
+ public DJMA_chart() {
+ this.SeparateWindow = false;
+ this.Name = "DJMA - Two JMAs";
+ this.Description = "Jurik Moving Average description";
+ this.AddLineSeries("JMA-fast", Color.Blue, 2, LineStyle.Solid);
+ this.AddLineSeries("JMA-slow", Color.Green, 2, LineStyle.Solid);
+ }
+
+
+ protected override void OnInit() {
+ this.bars = new();
+ this.fJma = new(source: bars.Select(this.FDataSource), period: this.FPeriod, phase: FJphase, vshort: FVshort, vlong: FVlong, useNaN: false);
+ this.sJma = new(source: bars.Select(this.SDataSource), period: this.SPeriod, phase: SJphase, vshort: SVshort, vlong: SVlong, useNaN: false);
+ }
+
+ protected override void OnUpdate(UpdateArgs args) {
+ bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
+
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
+ this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
+ this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
+ this.SetValue(this.fJma[^1].v, lineIndex: 0);
+ this.SetValue(this.sJma[^1].v, lineIndex: 1);
+ }
+}
\ No newline at end of file
diff --git a/Quantower/Indicators/EMA_chart.cs b/Indicators/Charts/EMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/EMA_chart.cs
rename to Indicators/Charts/EMA_chart.cs
diff --git a/Quantower/Indicators/ENTP_chart.cs b/Indicators/Charts/ENTP_chart.cs
similarity index 100%
rename from Quantower/Indicators/ENTP_chart.cs
rename to Indicators/Charts/ENTP_chart.cs
diff --git a/Quantower/Indicators/HEMA_chart.cs b/Indicators/Charts/HEMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/HEMA_chart.cs
rename to Indicators/Charts/HEMA_chart.cs
diff --git a/Quantower/Indicators/HMA_chart.cs b/Indicators/Charts/HMA_chart.cs
similarity index 96%
rename from Quantower/Indicators/HMA_chart.cs
rename to Indicators/Charts/HMA_chart.cs
index 93667ef6..72b1e2fa 100644
--- a/Quantower/Indicators/HMA_chart.cs
+++ b/Indicators/Charts/HMA_chart.cs
@@ -1,52 +1,52 @@
-using System.Diagnostics;
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class HMA_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private int Period = 10;
-
- [InputParameter("Data source", 1, variants: new object[]
- { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
- "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
- private int DataSource = 3;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////
- private HMA_Series indicator;
- ///////
-
- public HMA_chart()
- {
- this.SeparateWindow = false;
- this.Name = "HMA - Hull Moving Average";
- this.Description = "Hull Moving Average description";
- this.AddLineSeries("HMA", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: bars.Select(this.DataSource),
- period: this.Period, useNaN: false);
- Debug.WriteLine("Send to debug output.");
-}
-
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
-
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close),this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
- this.SetValue(result);
- }
-}
+using System.Diagnostics;
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class HMA_chart : Indicator
+{
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private int Period = 10;
+
+ [InputParameter("Data source", 1, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int DataSource = 3;
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////
+ private HMA_Series indicator;
+ ///////
+
+ public HMA_chart()
+ {
+ this.SeparateWindow = false;
+ this.Name = "HMA - Hull Moving Average";
+ this.Description = "Hull Moving Average description";
+ this.AddLineSeries("HMA", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit()
+ {
+ this.bars = new();
+ this.indicator = new(source: bars.Select(this.DataSource),
+ period: this.Period, useNaN: false);
+ Debug.WriteLine("Send to debug output.");
+}
+
+ protected override void OnUpdate(UpdateArgs args)
+ {
+ bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
+
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
+ this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
+ this.GetPrice(PriceType.Close),this.GetPrice(PriceType.Volume), update);
+ double result = this.indicator[this.indicator.Count - 1].v;
+ this.SetValue(result);
+ }
+}
diff --git a/Indicators/Charts/JMA_chart.cs b/Indicators/Charts/JMA_chart.cs
new file mode 100644
index 00000000..340c2287
--- /dev/null
+++ b/Indicators/Charts/JMA_chart.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class JMA_chart : QuanTAlib_Indicator {
+ #region Parameters
+
+ [InputParameter("Data source", 0, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int DataSource = 3;
+
+ [InputParameter("Smoothing period", 1, 1, 999, 1, 1)]
+ private int Period = 10;
+
+ [InputParameter("Volatility short", 2, 3, 50, 1, 1)]
+ private int Vshort = 10;
+
+ [InputParameter("Volatility long", 3, 20, 500, 1, 1)]
+ private int Vlong = 65;
+
+ [InputParameter("Phase", 4, -100, 100, 1, 2)]
+ private double Jphase = 0.0;
+
+ #endregion Parameters
+
+ ///////
+ private JMA_Series indicator;
+ ///////
+
+ public JMA_chart() :base() {
+ Name = "JMA - Jurik Moving Avg";
+ Description = "Jurik Moving Average description";
+ AddLineSeries(lineName: "JMA", lineColor: Color.Yellow, lineWidth: 3,lineStyle: LineStyle.Solid);
+ SeparateWindow = false;
+ }
+
+
+ protected override void OnInit() {
+ base.OnInit();
+ indicator = new(source: bars.Select(DataSource), period: Period,
+ phase: Jphase, vshort: Vshort, vlong: Vlong,
+ useNaN: false);
+ }
+
+ protected override void OnUpdate(UpdateArgs args) {
+ base.OnUpdate(args);
+ this.SetValue(indicator[^1].v, lineIndex: 0);
+ }
+}
diff --git a/Quantower/Indicators/KAMA_chart.cs b/Indicators/Charts/KAMA_chart.cs
similarity index 97%
rename from Quantower/Indicators/KAMA_chart.cs
rename to Indicators/Charts/KAMA_chart.cs
index 88658444..8de883f7 100644
--- a/Quantower/Indicators/KAMA_chart.cs
+++ b/Indicators/Charts/KAMA_chart.cs
@@ -1,55 +1,55 @@
-using System.Diagnostics;
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class KAMA_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private int Period = 10;
- [InputParameter("Fastest EMA", 1, 1, 999, 1, 1)]
- private int Fast = 2;
- [InputParameter("Slowest EMA", 2, 1, 999, 1, 1)]
- private int Slow = 30;
-
- [InputParameter("Data source", 3, variants: new object[]
- { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
- "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
- private int DataSource = 3;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////
- private KAMA_Series indicator;
- ///////
-
- public KAMA_chart()
- {
- this.SeparateWindow = false;
- this.Name = "KAMA - Kaufman's Adaptive Moving Average";
- this.Description = "Kaufman's Adaptive Moving Average description";
- this.AddLineSeries("KAMA", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: bars.Select(this.DataSource), period: this.Period, fast: this.Fast, slow: this.Slow, useNaN: false);
- }
-
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar ||
- args.Reason == UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
- double result = this.indicator;
- this.SetValue(result);
- Debug.WriteLine($"{this.indicator[0].v}");
- }
-}
+using System.Diagnostics;
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class KAMA_chart : Indicator
+{
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private int Period = 10;
+ [InputParameter("Fastest EMA", 1, 1, 999, 1, 1)]
+ private int Fast = 2;
+ [InputParameter("Slowest EMA", 2, 1, 999, 1, 1)]
+ private int Slow = 30;
+
+ [InputParameter("Data source", 3, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int DataSource = 3;
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////
+ private KAMA_Series indicator;
+ ///////
+
+ public KAMA_chart()
+ {
+ this.SeparateWindow = false;
+ this.Name = "KAMA - Kaufman's Adaptive Moving Average";
+ this.Description = "Kaufman's Adaptive Moving Average description";
+ this.AddLineSeries("KAMA", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit()
+ {
+ this.bars = new();
+ this.indicator = new(source: bars.Select(this.DataSource), period: this.Period, fast: this.Fast, slow: this.Slow, useNaN: false);
+ }
+
+ protected override void OnUpdate(UpdateArgs args)
+ {
+ bool update = !(args.Reason == UpdateReason.NewBar ||
+ args.Reason == UpdateReason.HistoricalBar);
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
+ this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
+ this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
+ double result = this.indicator;
+ this.SetValue(result);
+ Debug.WriteLine($"{this.indicator[0].v}");
+ }
+}
diff --git a/Quantower/Indicators/KURT_chart.cs b/Indicators/Charts/KURT_chart.cs
similarity index 100%
rename from Quantower/Indicators/KURT_chart.cs
rename to Indicators/Charts/KURT_chart.cs
diff --git a/Quantower/Indicators/MAD_chart.cs b/Indicators/Charts/MAD_chart.cs
similarity index 100%
rename from Quantower/Indicators/MAD_chart.cs
rename to Indicators/Charts/MAD_chart.cs
diff --git a/Quantower/Indicators/MAPE_chart.cs b/Indicators/Charts/MAPE_chart.cs
similarity index 100%
rename from Quantower/Indicators/MAPE_chart.cs
rename to Indicators/Charts/MAPE_chart.cs
diff --git a/Quantower/Indicators/MAX_chart.cs b/Indicators/Charts/MAX_chart.cs
similarity index 100%
rename from Quantower/Indicators/MAX_chart.cs
rename to Indicators/Charts/MAX_chart.cs
diff --git a/Quantower/Indicators/MED_chart.cs b/Indicators/Charts/MED_chart.cs
similarity index 100%
rename from Quantower/Indicators/MED_chart.cs
rename to Indicators/Charts/MED_chart.cs
diff --git a/Quantower/Indicators/MIN_chart.cs b/Indicators/Charts/MIN_chart.cs
similarity index 100%
rename from Quantower/Indicators/MIN_chart.cs
rename to Indicators/Charts/MIN_chart.cs
diff --git a/Quantower/Indicators/MSE_chart.cs b/Indicators/Charts/MSE_chart.cs
similarity index 100%
rename from Quantower/Indicators/MSE_chart.cs
rename to Indicators/Charts/MSE_chart.cs
diff --git a/Quantower/Indicators/RMA_chart.cs b/Indicators/Charts/RMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/RMA_chart.cs
rename to Indicators/Charts/RMA_chart.cs
diff --git a/Indicators/Charts/RSI_chart.cs b/Indicators/Charts/RSI_chart.cs
new file mode 100644
index 00000000..85a5c78d
--- /dev/null
+++ b/Indicators/Charts/RSI_chart.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class RSI_chart : QuanTAlib_Indicator {
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private int Period = 10;
+
+ [InputParameter("Data source", 1, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int DataSource = 8;
+
+ [InputParameter("Overbought level", 2, 1, 100, 1, 1)]
+ private int Overbought = 70;
+
+ [InputParameter("Oversold level", 2, 1, 100, 1, 1)]
+ private int Oversold = 30;
+
+ #endregion Parameters
+
+ ///////
+ private RSI_Series indicator;
+ ///////
+
+ public RSI_chart() : base() {
+ this.Name = "RSI - Relative Strength Index";
+ this.Description = "RSI description";
+ this.AddLineSeries("RSI", Color.RoyalBlue, 3, LineStyle.Solid);
+ this.SeparateWindow = true;
+ }
+
+ protected override void OnInit() {
+ base.OnInit();
+ indicator = new(source: bars.Select(this.DataSource), period: this.Period, useNaN: true);
+ }
+
+ protected override void OnUpdate(UpdateArgs args) {
+ base.OnUpdate(args);
+ SetValue(indicator[^1].v, lineIndex: 0);
+ if (indicator[^1].v >= Overbought)
+ LinesSeries[0].SetMarker(0, color: Color.Red);
+ if (indicator[^1].v <= Oversold)
+ LinesSeries[0].SetMarker(0, color: Color.Red);
+ }
+ public override void OnPaintChart(PaintChartEventArgs args) {
+ base.OnPaintChart(args);
+ for (int i = firstOnScreenBarIndex; i <= lastOnScreenBarIndex; i++) {
+ int xLeft = (int)Math.Round(mainWindow.CoordinatesConverter.GetChartX(Time(Count - i - 1)));
+ int y = (int)Math.Round((mainWindow.CoordinatesConverter.GetChartY(Overbought)));
+ }
+ }
+}
diff --git a/Quantower/Indicators/SDEV_chart.cs b/Indicators/Charts/SDEV_chart.cs
similarity index 96%
rename from Quantower/Indicators/SDEV_chart.cs
rename to Indicators/Charts/SDEV_chart.cs
index 2e6a423d..84778581 100644
--- a/Quantower/Indicators/SDEV_chart.cs
+++ b/Indicators/Charts/SDEV_chart.cs
@@ -1,51 +1,51 @@
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class SDEV_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private int Period = 10;
-
- [InputParameter("Data source", 1, variants: new object[]
- { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
- "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
- private int DataSource = 8;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////dotnet
- private SDEV_Series indicator;
- ///////
-
- public SDEV_chart()
- {
- this.SeparateWindow = true;
- this.Name = "SDEV - Standard Deviation";
- this.Description = "SDEV description";
- this.AddLineSeries("SDEV", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: bars.Select(this.DataSource),
- period: this.Period, useNaN: true);
- }
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar ||
- args.Reason == UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close),
- this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
-
- this.SetValue(result, 0);
- }
-}
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class SDEV_chart : Indicator
+{
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private int Period = 10;
+
+ [InputParameter("Data source", 1, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int DataSource = 8;
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////dotnet
+ private SDEV_Series indicator;
+ ///////
+
+ public SDEV_chart()
+ {
+ this.SeparateWindow = true;
+ this.Name = "SDEV - Standard Deviation";
+ this.Description = "SDEV description";
+ this.AddLineSeries("SDEV", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit()
+ {
+ this.bars = new();
+ this.indicator = new(source: bars.Select(this.DataSource),
+ period: this.Period, useNaN: true);
+ }
+ protected override void OnUpdate(UpdateArgs args)
+ {
+ bool update = !(args.Reason == UpdateReason.NewBar ||
+ args.Reason == UpdateReason.HistoricalBar);
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
+ this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
+ this.GetPrice(PriceType.Close),
+ this.GetPrice(PriceType.Volume), update);
+ double result = this.indicator[this.indicator.Count - 1].v;
+
+ this.SetValue(result, 0);
+ }
+}
diff --git a/Quantower/Indicators/SMAPE_chart.cs b/Indicators/Charts/SMAPE_chart.cs
similarity index 100%
rename from Quantower/Indicators/SMAPE_chart.cs
rename to Indicators/Charts/SMAPE_chart.cs
diff --git a/Quantower/Indicators/SMA_chart.cs b/Indicators/Charts/SMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/SMA_chart.cs
rename to Indicators/Charts/SMA_chart.cs
diff --git a/Quantower/Indicators/SMMA_chart.cs b/Indicators/Charts/SMMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/SMMA_chart.cs
rename to Indicators/Charts/SMMA_chart.cs
diff --git a/Quantower/Indicators/TEMA_chart.cs b/Indicators/Charts/TEMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/TEMA_chart.cs
rename to Indicators/Charts/TEMA_chart.cs
diff --git a/Quantower/Indicators/VAR_chart.cs b/Indicators/Charts/VAR_chart.cs
similarity index 96%
rename from Quantower/Indicators/VAR_chart.cs
rename to Indicators/Charts/VAR_chart.cs
index d16725e8..89573ee7 100644
--- a/Quantower/Indicators/VAR_chart.cs
+++ b/Indicators/Charts/VAR_chart.cs
@@ -1,52 +1,52 @@
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class VAR_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private int Period = 10;
-
- [InputParameter("Data source", 1, variants: new object[]
- { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
- "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
- private int DataSource = 8;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////dotnet
- private VAR_Series indicator;
- ///////
-
- public VAR_chart()
- {
- this.SeparateWindow = true;
- this.Name = "VAR - Variance";
- this.Description = "VAR description";
- this.AddLineSeries("VAR", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: bars.Select(this.DataSource),
- period: this.Period, useNaN: true);
- }
-
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar ||
- args.Reason == UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close),
- this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
-
- this.SetValue(result, 0);
- }
-}
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+namespace QuanTAlib;
+
+public class VAR_chart : Indicator
+{
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private int Period = 10;
+
+ [InputParameter("Data source", 1, variants: new object[]
+ { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
+ "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
+ private int DataSource = 8;
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////dotnet
+ private VAR_Series indicator;
+ ///////
+
+ public VAR_chart()
+ {
+ this.SeparateWindow = true;
+ this.Name = "VAR - Variance";
+ this.Description = "VAR description";
+ this.AddLineSeries("VAR", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit()
+ {
+ this.bars = new();
+ this.indicator = new(source: bars.Select(this.DataSource),
+ period: this.Period, useNaN: true);
+ }
+
+ protected override void OnUpdate(UpdateArgs args)
+ {
+ bool update = !(args.Reason == UpdateReason.NewBar ||
+ args.Reason == UpdateReason.HistoricalBar);
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
+ this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
+ this.GetPrice(PriceType.Close),
+ this.GetPrice(PriceType.Volume), update);
+ double result = this.indicator[this.indicator.Count - 1].v;
+
+ this.SetValue(result, 0);
+ }
+}
diff --git a/Quantower/Indicators/WMAPE_chart.cs b/Indicators/Charts/WMAPE_chart.cs
similarity index 96%
rename from Quantower/Indicators/WMAPE_chart.cs
rename to Indicators/Charts/WMAPE_chart.cs
index e607561a..bd89c693 100644
--- a/Quantower/Indicators/WMAPE_chart.cs
+++ b/Indicators/Charts/WMAPE_chart.cs
@@ -1,55 +1,55 @@
-namespace QuanTAlib;
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-
-public class WMAPE_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private readonly int Period = 10;
-
- [InputParameter("Data source", 1, variants: new object[]{
- "Open", 0,
- "High", 1,
- "Low", 2,
- "Close", 3,
- "HL2", 4,
- "OC2", 5,
- "OHL3", 6,
- "HLC3", 7,
- "OHLC4", 8,
- "Weighted (HLCC4)", 9
- })]
- private readonly int DataSource = 8;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////dotnet
- private QuanTAlib.WMAPE_Series indicator;
- ///////
-
- public WMAPE_chart()
- {
- this.SeparateWindow = true;
- this.Name = "WMAPE - Weighted Mean Absolute Percentage Error";
- this.Description = "WMAPE description";
- this.AddLineSeries("WMAPE", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: this.bars.Select(this.DataSource), period: this.Period, useNaN: true);
- }
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
-
- this.SetValue(result, 0);
- }
-}
+namespace QuanTAlib;
+using System.Drawing;
+using TradingPlatform.BusinessLayer;
+
+public class WMAPE_chart : Indicator
+{
+ #region Parameters
+
+ [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
+ private readonly int Period = 10;
+
+ [InputParameter("Data source", 1, variants: new object[]{
+ "Open", 0,
+ "High", 1,
+ "Low", 2,
+ "Close", 3,
+ "HL2", 4,
+ "OC2", 5,
+ "OHL3", 6,
+ "HLC3", 7,
+ "OHLC4", 8,
+ "Weighted (HLCC4)", 9
+ })]
+ private readonly int DataSource = 8;
+
+ #endregion Parameters
+
+ private TBars bars;
+
+ ///////dotnet
+ private QuanTAlib.WMAPE_Series indicator;
+ ///////
+
+ public WMAPE_chart()
+ {
+ this.SeparateWindow = true;
+ this.Name = "WMAPE - Weighted Mean Absolute Percentage Error";
+ this.Description = "WMAPE description";
+ this.AddLineSeries("WMAPE", Color.RoyalBlue, 3, LineStyle.Solid);
+ }
+
+ protected override void OnInit()
+ {
+ this.bars = new();
+ this.indicator = new(source: this.bars.Select(this.DataSource), period: this.Period, useNaN: true);
+ }
+ protected override void OnUpdate(UpdateArgs args)
+ {
+ bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
+ this.bars.Add(this.Time(), this.GetPrice(PriceType.Open), this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low), this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
+ double result = this.indicator[this.indicator.Count - 1].v;
+
+ this.SetValue(result, 0);
+ }
+}
diff --git a/Quantower/Indicators/WMA_chart.cs b/Indicators/Charts/WMA_chart.cs
similarity index 100%
rename from Quantower/Indicators/WMA_chart.cs
rename to Indicators/Charts/WMA_chart.cs
diff --git a/Quantower/Quantower.csproj b/Indicators/Indicators.csproj
similarity index 75%
rename from Quantower/Quantower.csproj
rename to Indicators/Indicators.csproj
index a1495bc3..547741b9 100644
--- a/Quantower/Quantower.csproj
+++ b/Indicators/Indicators.csproj
@@ -1,52 +1,47 @@
-
-
-
- net6
- preview
- false
- AnyCPU
- Indicator
- Quantower_QTAlib
- QuanTAlib
- embedded
- preview
- AnyCPU
- disable
- False
- ..\.sonarlint\mihakralj_quantalibcsharp.ruleset
-
-
- True
- 3
- True
- anycpu
- full
- C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Indicators\Quantower
-
-
- embedded
- True
- 3
- True
- anycpu
- C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Indicators\Quantower
-
-
-
- QuanTAlib\%(RecursiveDir)%(Filename)%(Extension)
-
-
-
-
-
-
-
-
- C:\Quantower\TradingPlatform\v1.130.7\bin\TradingPlatform.BusinessLayer.dll
-
-
+
+
+
+ net6
+ preview
+ false
+ AnyCPU
+ Indicator
+ Quantower_QTAlib
+ QuanTAlib
+ embedded
+ AnyCPU
+ disable
+ False
+ ..\.sonarlint\mihakralj_quantalibcsharp.ruleset
+
+
+ True
+ 3
+ True
+ anycpu
+ full
+ C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Indicators\QuanTAlib
+
+
+ embedded
+ True
+ 3
+ True
+ anycpu
+ C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Indicators\QuanTAlib
+
+
+
+
+
+
+
+
+
+
+
+
+ C:\Quantower\TradingPlatform\v1.130.7\bin\TradingPlatform.BusinessLayer.dll
+
+
\ No newline at end of file
diff --git a/QuanTAlib.sln b/QuanTAlib.sln
index 3242afe2..d0b6ce59 100644
--- a/QuanTAlib.sln
+++ b/QuanTAlib.sln
@@ -3,11 +3,44 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32210.308
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuanTAlib", "Source\QuanTAlib.csproj", "{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Calculations", "Calculations\Calculations.csproj", "{AAE21F8A-9BC2-4647-A9EB-4DC86C569080}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "Tests\Tests.csproj", "{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Quantower", "Quantower\Quantower.csproj", "{693713F9-F33A-4B33-8F98-63794CA9734C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Indicators", "Indicators\Indicators.csproj", "{43AD2D78-024C-4D96-A70B-915CF519965A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Strategies", "Strategies\Strategies.csproj", "{FA526AF6-95BC-4AC0-8B46-A304FD06689D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{47B6ACDB-F535-4FEB-9A0A-C427CAE8C28E}"
+ ProjectSection(SolutionItems) = preProject
+ docs\.nojekyll = docs\.nojekyll
+ docs\ALMA.md = docs\ALMA.md
+ docs\DEMA.md = docs\DEMA.md
+ docs\DWMA.md = docs\DWMA.md
+ docs\EMA.md = docs\EMA.md
+ docs\FMA.md = docs\FMA.md
+ docs\getting_started.ipynb = docs\getting_started.ipynb
+ docs\HEMA.md = docs\HEMA.md
+ docs\HMA.md = docs\HMA.md
+ docs\HWMA.md = docs\HWMA.md
+ docs\index.html = docs\index.html
+ docs\indicators.md = docs\indicators.md
+ docs\JMA.md = docs\JMA.md
+ docs\KAMA.md = docs\KAMA.md
+ docs\LICENSE = docs\LICENSE
+ docs\MAMA.md = docs\MAMA.md
+ docs\QA.md = docs\QA.md
+ docs\readme.md = docs\readme.md
+ docs\RMA.md = docs\RMA.md
+ docs\SMA.md = docs\SMA.md
+ docs\SMMA.md = docs\SMMA.md
+ docs\T3.md = docs\T3.md
+ docs\TEMA.md = docs\TEMA.md
+ docs\TRIMA.md = docs\TRIMA.md
+ docs\WMA.md = docs\WMA.md
+ docs\ZLEMA.md = docs\ZLEMA.md
+ docs\_sidebar.md = docs\_sidebar.md
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -23,10 +56,14 @@ Global
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{283EACC9-3AF6-4DAE-9C1C-0F7F8C8CD70D}.Release|Any CPU.Build.0 = Release|Any CPU
- {693713F9-F33A-4B33-8F98-63794CA9734C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {693713F9-F33A-4B33-8F98-63794CA9734C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {693713F9-F33A-4B33-8F98-63794CA9734C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {693713F9-F33A-4B33-8F98-63794CA9734C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {43AD2D78-024C-4D96-A70B-915CF519965A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {43AD2D78-024C-4D96-A70B-915CF519965A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {43AD2D78-024C-4D96-A70B-915CF519965A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {43AD2D78-024C-4D96-A70B-915CF519965A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FA526AF6-95BC-4AC0-8B46-A304FD06689D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FA526AF6-95BC-4AC0-8B46-A304FD06689D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FA526AF6-95BC-4AC0-8B46-A304FD06689D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FA526AF6-95BC-4AC0-8B46-A304FD06689D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Quantower/Indicators/ATR_chart.cs b/Quantower/Indicators/ATR_chart.cs
deleted file mode 100644
index 5467c3de..00000000
--- a/Quantower/Indicators/ATR_chart.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class ATR_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private readonly int Period = 10;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////
- private ATR_Series indicator;
- ///////
-
- public ATR_chart()
- {
- this.SeparateWindow = true;
- this.Name = "ATR - Average True Range";
- this.Description = "Average True Range description";
- this.AddLineSeries("ATR", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
-this.indicator = new(source: bars, period: this.Period, useNaN: false);
- }
-
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar ||
- args.Reason == UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close),
- this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
- this.SetValue(result);
- }
-}
diff --git a/Quantower/Indicators/JMA_chart.cs b/Quantower/Indicators/JMA_chart.cs
deleted file mode 100644
index d6c38982..00000000
--- a/Quantower/Indicators/JMA_chart.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Drawing;
-using System.Linq;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class JMA_chart : Indicator {
- #region Parameters
-
- [InputParameter("Data source", 0, variants: new object[]
- { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
- "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
- private int DataSource = 3;
-
- [InputParameter("Smoothing period", 1, 1, 999, 1, 1)]
- private int Period = 10;
-
- [InputParameter("Volatility short", 2, 3, 50, 1, 1)]
- private int Vshort = 10;
-
- [InputParameter("Volatility long", 3, 20, 500, 1, 1)]
- private int Vlong = 65;
-
- [InputParameter("Phase", 4, -100, 100, 1, 2)]
- private double Jphase = 0.0;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////
- private JMA_Series indicator;
- ///////
-
- public JMA_chart() {
- this.SeparateWindow = false;
- this.Name = "JMA - Jurik Moving Avg";
- this.Description = "Jurik Moving Average description";
- this.AddLineSeries("JMA", Color.Yellow, 3, LineStyle.Solid);
- }
-
-
- protected override void OnInit() {
- this.bars = new();
- this.indicator = new(source: bars.Select(this.DataSource), period: this.Period, phase: Jphase, vshort: Vshort, vlong: Vlong, useNaN: false);
- }
-
- protected override void OnUpdate(UpdateArgs args) {
- bool update = !(args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar);
-
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
-
- this.SetValue(result, lineIndex: 0);
- }
-}
diff --git a/Quantower/Indicators/RSI_chart.cs b/Quantower/Indicators/RSI_chart.cs
deleted file mode 100644
index ebd9d80b..00000000
--- a/Quantower/Indicators/RSI_chart.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.Drawing;
-using TradingPlatform.BusinessLayer;
-namespace QuanTAlib;
-
-public class RSI_chart : Indicator
-{
- #region Parameters
-
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private int Period = 10;
-
- [InputParameter("Data source", 1, variants: new object[]
- { "Open", 0, "High", 1, "Low", 2, "Close", 3, "HL2", 4, "OC2", 5,
- "OHL3", 6, "HLC3", 7, "OHLC4", 8, "Weighted (HLCC4)", 9 })]
- private int DataSource = 8;
-
- #endregion Parameters
-
- private TBars bars;
-
- ///////
- private RSI_Series indicator;
- ///////
-
- public RSI_chart()
- {
- this.SeparateWindow = true;
- this.Name = "RSI - Relative Strength Index";
- this.Description = "RSI description";
- this.AddLineSeries("RSI", Color.RoyalBlue, 3, LineStyle.Solid);
- }
-
- protected override void OnInit()
- {
- this.bars = new();
- this.indicator = new(source: bars.Select(this.DataSource),
- period: this.Period, useNaN: true);
- }
- protected override void OnUpdate(UpdateArgs args)
- {
- bool update = !(args.Reason == UpdateReason.NewBar ||
- args.Reason == UpdateReason.HistoricalBar);
- this.bars.Add(this.Time(), this.GetPrice(PriceType.Open),
- this.GetPrice(PriceType.High), this.GetPrice(PriceType.Low),
- this.GetPrice(PriceType.Close),
- this.GetPrice(PriceType.Volume), update);
- double result = this.indicator[this.indicator.Count - 1].v;
-
- this.SetValue(result, 0);
- }
-}
diff --git a/Quantower/dll/TradingPlatform.BusinessLayer.dll b/Quantower/dll/TradingPlatform.BusinessLayer.dll
deleted file mode 100644
index 245e51a7..00000000
Binary files a/Quantower/dll/TradingPlatform.BusinessLayer.dll and /dev/null differ
diff --git a/Strategies/SimpleMACross1.cs b/Strategies/SimpleMACross1.cs
new file mode 100644
index 00000000..98e14aa2
--- /dev/null
+++ b/Strategies/SimpleMACross1.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TradingPlatform.BusinessLayer;
+using QuanTAlib;
+using System.Drawing;
+
+namespace SimpleMACross {
+ public class SimpleMACross1 : Strategy, ICurrentAccount, ICurrentSymbol {
+ [InputParameter("Symbol", 0)]
+ public Symbol CurrentSymbol { get; set; }
+
+ [InputParameter("Account", 1)]
+ public Account CurrentAccount { get; set; }
+
+ [InputParameter("Fast MA", 2, minimum: 1, maximum: 100, increment: 1, decimalPlaces: 0)]
+ public int FastMA = 5;
+
+ [InputParameter("Slow MA", 3, minimum: 1, maximum: 100, increment: 1, decimalPlaces: 0)]
+ public int SlowMA = 10;
+
+ [InputParameter("Quantity", 4, 0.1, 99999, 0.1, 2)]
+ public double Quantity = 1.0;
+
+ [InputParameter("Period", 5)]
+ public Period period = Period.MIN1;
+
+ public override string[] MonitoringConnectionsIds => new string[] { this.CurrentSymbol?.ConnectionId, this.CurrentAccount?.ConnectionId };
+
+ private HistoricalData hdm;
+ private DateTime prev_time;
+ private readonly TBars bars = new();
+
+ public SimpleMACross1()
+ : base() {
+ this.Name = "Miha MA Cross strategy 3";
+ this.Description = "Raw strategy without any additional functional";
+ }
+
+ protected override void OnRun() {
+ if (this.CurrentAccount != null && this.CurrentAccount.State == BusinessObjectState.Fake) this.CurrentAccount = Core.Instance.GetAccount(this.CurrentAccount.CreateInfo());
+ if (this.CurrentSymbol != null && this.CurrentSymbol.State == BusinessObjectState.Fake) this.CurrentSymbol = Core.Instance.GetSymbol(this.CurrentSymbol.CreateInfo());
+ if (this.CurrentSymbol == null || this.CurrentAccount == null || this.CurrentSymbol.ConnectionId != this.CurrentAccount.ConnectionId) {
+ this.Log("Incorrect input parameters... Symbol or Account are not specified or they have different connectionID.", StrategyLoggingLevel.Error);
+ return; }
+
+ /////////////////////////////////////////////////////
+ this.hdm = this.CurrentSymbol.GetHistory(Period.MIN1, this.CurrentSymbol.HistoryType, Core.TimeUtils.DateTimeUtcNow.AddDays(-1));
+ ////////////////////////////////////////////////////
+
+
+ this.LogInfo($"Symbol: {CurrentSymbol.Name} period: {this.period} :-: {this.CurrentSymbol.HistoryType.ToString()} :-: {this.hdm.Count} bars loaded");
+ this.hdm.HistoryItemUpdated += this.Hdm_HistoryItemUpdated;
+ }
+
+ private void Hdm_HistoryItemUpdated(object sender, HistoryEventArgs e) {
+ this.OnUpdate();
+ }
+
+ private void OnUpdate() {
+ bool update = hdm.Last().TimeLeft - prev_time < this.period.Duration ? true : false;
+ if (!update) prev_time = hdm.Last().TimeLeft;
+
+ bars.Add(hdm.Last().TimeLeft, hdm.Last()[PriceType.Open], hdm.Last()[PriceType.High],
+ hdm.Last()[PriceType.Low], hdm.Last()[PriceType.Close], hdm.Last()[PriceType.Volume], update);
+
+ if (!update) this.LogInfo($"{bars.Close.Last().t} OHLC4:{(double)bars.OHLC4}");
+
+ }
+
+ protected override List OnGetMetrics() {
+ var result = base.OnGetMetrics();
+
+ // An example of adding custom strategy metrics:
+ result.Add("Bars processed", this.bars.Count.ToString());
+ /*
+ result.Add("Trades [#]", "0");
+ result.Add("Long trades [#]", this.longPositionsCount.ToString());
+ result.Add("Short trades [#]", this.shortPositionsCount.ToString());
+ result.Add("Profitable trades [#]", "0");
+ result.Add("Win Rate [%]", "0");
+ result.Add("Best Trade [%]", "0");
+ result.Add("Worst Trade[%]", "0");
+ result.Add("Avg Winning Trade [%]", "0");
+ result.Add("Avg Losing Trade [%]", "0");
+ result.Add("Profit Factor", "0");
+ result.Add("Sharpe Ratio", "0");
+ result.Add("Sortino Ratio", "0");
+ result.Add("Omega Ratio", "0");
+ result.Add("Calmar Ratio", "0");
+ result.Add("Beta", "0");
+ result.Add("Alpha", "0");
+ */
+ return result;
+ }
+
+ protected override void OnStop() {
+ if (this.hdm != null) {
+ this.hdm.HistoryItemUpdated -= this.Hdm_HistoryItemUpdated;
+ this.hdm.Dispose();
+ }
+
+ base.OnStop();
+ }
+ }
+}
+
diff --git a/Strategies/Strategies.csproj b/Strategies/Strategies.csproj
new file mode 100644
index 00000000..f067f1fa
--- /dev/null
+++ b/Strategies/Strategies.csproj
@@ -0,0 +1,45 @@
+
+
+ net6.0
+ preview
+ false
+ AnyCPU
+ Strategy
+ Strategy
+ Strategy
+ AnyCPU
+ disable
+ False
+ Program
+ C:\Quantower\TradingPlatform\v1.130.7\Console.StarterNew.exe
+ --address 127.0.0.1 --port 51113
+ ..\.sonarlint\mihakralj_quantalibcsharp.ruleset
+
+
+ True
+ 3
+ True
+ anycpu
+ full
+ C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Strategies\QuanTAlib
+
+
+ embedded
+ True
+ 3
+ True
+ anycpu
+ C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Strategies\QuanTAlib
+
+
+
+
+
+
+
+
+
+ C:\Quantower\TradingPlatform\v1.130.7\bin\TradingPlatform.BusinessLayer.dll
+
+
+
\ No newline at end of file
diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 38bc8c2b..358c4d94 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -24,7 +24,7 @@
-
+