diff --git a/.sonarlint/mihakralj_quantalib/CSharp/SonarLint.xml b/.sonarlint/mihakralj_quantalib/CSharp/SonarLint.xml
new file mode 100644
index 00000000..90bc98df
--- /dev/null
+++ b/.sonarlint/mihakralj_quantalib/CSharp/SonarLint.xml
@@ -0,0 +1,89 @@
+
+
+
+
+ sonar.cs.analyzeGeneratedCode
+ false
+
+
+ sonar.cs.file.suffixes
+ .cs
+
+
+ sonar.cs.ignoreHeaderComments
+ true
+
+
+ sonar.cs.roslyn.ignoreIssues
+ false
+
+
+
+
+ S107
+
+
+ max
+ 7
+
+
+
+
+ S110
+
+
+ max
+ 5
+
+
+
+
+ S1479
+
+
+ maximum
+ 30
+
+
+
+
+ S2342
+
+
+ flagsAttributeFormat
+ ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?s$
+
+
+ format
+ ^([A-Z]{1,3}[a-z0-9]+)*([A-Z]{2})?$
+
+
+
+
+ S2436
+
+
+ max
+ 2
+
+
+ maxMethod
+ 3
+
+
+
+
+ S3776
+
+
+ propertyThreshold
+ 3
+
+
+ threshold
+ 15
+
+
+
+
+
\ No newline at end of file
diff --git a/.sonarlint/mihakralj_quantalibcsharp.ruleset b/.sonarlint/mihakralj_quantalibcsharp.ruleset
index 150340f7..22a7ac94 100644
--- a/.sonarlint/mihakralj_quantalibcsharp.ruleset
+++ b/.sonarlint/mihakralj_quantalibcsharp.ruleset
@@ -380,6 +380,7 @@
+
diff --git a/Quantower/Indicators/JMA_chart.cs b/Quantower/Indicators/JMA_chart.cs
index 208a7696..d6c38982 100644
--- a/Quantower/Indicators/JMA_chart.cs
+++ b/Quantower/Indicators/JMA_chart.cs
@@ -8,17 +8,22 @@ namespace QuanTAlib;
public class JMA_chart : Indicator {
#region Parameters
- [InputParameter("Smoothing period", 0, 1, 999, 1, 1)]
- private int Period = 10;
-
- [InputParameter("Data source", 1, variants: new object[]
+ [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("Slope calc", 2, 2, 10, 1, 1)]
- private int SlopePeriod = 3;
+ 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
@@ -26,21 +31,19 @@ public class JMA_chart : Indicator {
///////
private JMA_Series indicator;
- private LINREG_Series slope;
///////
public JMA_chart() {
this.SeparateWindow = false;
this.Name = "JMA - Jurik Moving Avg";
this.Description = "Jurik Moving Average description";
- this.AddLineSeries("JMA", Color.Blue, 4, LineStyle.Solid);
+ 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, useNaN: false);
- this.slope = new(source: this.indicator, period: this.SlopePeriod);
+ 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) {
@@ -51,7 +54,6 @@ public class JMA_chart : Indicator {
this.GetPrice(PriceType.Close), this.GetPrice(PriceType.Volume), update);
double result = this.indicator[this.indicator.Count - 1].v;
- this.LinesSeries[0].SetMarker(offset: 0,color: this.slope > 0 ? Color.FromArgb(0,160,0) : Color.FromArgb(255, 0, 0));
this.SetValue(result, lineIndex: 0);
}
}
diff --git a/Quantower/Quantower.csproj b/Quantower/Quantower.csproj
index 7d91a984..a1495bc3 100644
--- a/Quantower/Quantower.csproj
+++ b/Quantower/Quantower.csproj
@@ -1,9 +1,9 @@
- net48
+ net6
preview
- true
+ false
AnyCPU
Indicator
Quantower_QTAlib
@@ -21,9 +21,7 @@
True
anycpu
full
-
+ C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Indicators\Quantower
embedded
@@ -31,21 +29,24 @@
3
True
anycpu
-
+ C:\Quantower\TradingPlatform\v1.130.7\..\..\Settings\Scripts\Indicators\Quantower
QuanTAlib\%(RecursiveDir)%(Filename)%(Extension)
+
+
+
+
- C:\Quantower\TradingPlatform\v1.129.11\bin\TradingPlatform.BusinessLayer.dll
+ C:\Quantower\TradingPlatform\v1.130.7\bin\TradingPlatform.BusinessLayer.dll
\ No newline at end of file
diff --git a/Quantower/dll/TradingPlatform.BusinessLayer.dll b/Quantower/dll/TradingPlatform.BusinessLayer.dll
index 95e71e6e..245e51a7 100644
Binary files a/Quantower/dll/TradingPlatform.BusinessLayer.dll and b/Quantower/dll/TradingPlatform.BusinessLayer.dll differ
diff --git a/Source/Basics/Single_TSeries_Abstract.cs b/Source/Basics/Single_TSeries_Abstract.cs
index 24e5e5f4..6c283237 100644
--- a/Source/Basics/Single_TSeries_Abstract.cs
+++ b/Source/Basics/Single_TSeries_Abstract.cs
@@ -23,30 +23,29 @@ public abstract class Single_TSeries_Indicator : TSeries
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)
- {
- this._data = source;
- this._period = period;
- this._p = _period;
- this._NaN = useNaN;
- this._data.Pub += this.Sub;
- }
+ // 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
+ // overridable Add() method to add/update a single item at the end of the list
- public virtual void Add((System.DateTime t, double v) TValue, bool update, bool useNaN)
- {
- if (_period == 0) { _p = this.Length; }
- var res = (TValue.t, this.Count < this._p - 1 && this._NaN ? double.NaN : TValue.v);
- base.Add(res, update);
- }
- public new virtual void Add((System.DateTime t, double v) TValue, bool update) => base.Add(TValue, update);
+ 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) { for (int i = 0; i < data.Count; i++) { this.Add(TValue: data[i], update: false); } }
-
- public new void Add((System.DateTime t, double v) TValue) => this.Add(TValue: TValue, update: false);
+ // 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);
diff --git a/Source/Basics/TSeries.cs b/Source/Basics/TSeries.cs
index af9b8da7..15f53d9f 100644
--- a/Source/Basics/TSeries.cs
+++ b/Source/Basics/TSeries.cs
@@ -1,5 +1,7 @@
namespace QuanTAlib;
using System;
+using System.Collections.Generic;
+using System.Linq;
/*
TSeries is the cornerstone of all QuanTAlib classess.
@@ -11,87 +13,44 @@ TSeries is the cornerstone of all QuanTAlib classess.
- includes publishing and subscribing methods that attach to events
*/
-public class TSeries : System.Collections.Generic.List<(DateTime t, double v)>
-{
- // when asked for a (t,v) tuple, return the last (t,v) on the List
- public static implicit operator (DateTime t, double v)(TSeries l) => l[l.Count - 1];
+public class TSeries : List<(DateTime t, double v)> {
- // when asked for a (double), return the value part of the last tuple on the list
- public static implicit operator double(TSeries l) => l[l.Count - 1].v;
+ public static implicit operator (DateTime t, double v)(TSeries l) => l[^1];
+ public static implicit operator double(TSeries l) => l[^1].v;
+ public static implicit operator DateTime(TSeries l) => l[^1].t;
+ public List t => this.Select(item => item.t).ToList();
+ public List v => this.Select(item => item.v).ToList();
+ public int Length => this.Count;
- // when asked for a (DateTime), return the DateTime part of the last tuple on the list
- public static implicit operator DateTime(TSeries l) => l[l.Count - 1].t;
-
- //convert from tuple List(t,v) to single List(DateTime)
- public System.Collections.Generic.List t {
- get { System.Collections.Generic.List TList = new();
- for (int i = 0; i < this.Count; i++) { TList.Add(this[i].t); }
- return TList;
- }
- }
+ public TSeries Tail(int count = 10) {
+ var tailSeries = new TSeries();
+ tailSeries.AddRange(this.Skip(Math.Max(0, this.Count - count)).Take(count));
+ return tailSeries;
+ }
+ public void Add((DateTime t, double v) TValue, bool update = false) {
+ if (update) { this[^1] = TValue; }
+ else { base.Add(TValue); }
+ OnEvent(update);
+ }
- //convert from tuple List(t,v) to single List(double)
- public System.Collections.Generic.List v {
- get { System.Collections.Generic.List VList = new();
- for (int i = 0; i < this.Count; i++) { VList.Add(this[i].v); }
- return VList;
- }
- }
+ public void Add(DateTime t, double v, bool update = false) => this.Add((t, v), update);
+ public void Add(double v, bool update = false) => this.Add((DateTime.Now, v), update);
+ protected virtual void OnEvent(bool update = false) {
+ Pub?.Invoke(this, new TSeriesEventArgs { update = update }); }
- public int Length => this.Count;
+ public delegate void NewDataEventHandler(object source, TSeriesEventArgs args);
+ public event NewDataEventHandler Pub;
- public TSeries Tail(int count=10) {
- TSeries outSeries = new();
- if (count > this.Count) { count = this.Count; }
- for (int i = this.Count-count; i this.Add((t, v), update);
-
- public void Add(double v, bool update = false) => this.Add((DateTime.Now, v), update);
-
- // Broadcast handler - only to valid targets
- protected virtual void OnEvent(bool update = false)
- {
- if (Pub != null && Pub.Target != this)
- {
- Pub(this, new TSeriesEventArgs { update = update });
- }
- }
-
- // delegate used by event handler + event handler (Pub == publisher)
- public delegate
- void NewDataEventHandler(object source, TSeriesEventArgs args);
- public event NewDataEventHandler Pub;
-
- public void Sub(object source, TSeriesEventArgs e)
- {
- TSeries ss = (TSeries)source;
- if (ss.Count > 0)
- {
- for (int i = 0; i < ss.Count; i++)
- {
- this.Add(ss[i]);
- }
- }
- else
- {
- this.Add(ss[ss.Count - 1], e.update);
- }
- }
+ public void Sub(object source, TSeriesEventArgs e) {
+ TSeries ss = (TSeries)source;
+ if (ss.Count > 0) {
+ this.AddRange(ss);
+ } else {
+ Add(ss[^1], e.update);
+ }
+ }
}
-// EventArgs extension - carries the update field
-public class TSeriesEventArgs : EventArgs
-{
- public bool update { get; set; }
+public class TSeriesEventArgs : EventArgs{
+ public bool update { get; set; }
}
diff --git a/Source/QuanTAlib.csproj b/Source/QuanTAlib.csproj
index b8259724..8e07cace 100644
--- a/Source/QuanTAlib.csproj
+++ b/Source/QuanTAlib.csproj
@@ -2,7 +2,7 @@
QuanTAlib
- 0.1.29
+ 0.1.30
Library of Technical Indicators for .NET
Quantitative Technical Analysis library for real-time (streaming) data analysis
git
@@ -11,7 +11,7 @@
Miha Kralj
Miha Kralj
readme.md
- net7.0;net6.0;netstandard2.1;net48
+ net6.0
disable
preview
disable
diff --git a/Source/Trends/JMA_Series.cs b/Source/Trends/JMA_Series.cs
index 855306b4..0ce50524 100644
--- a/Source/Trends/JMA_Series.cs
+++ b/Source/Trends/JMA_Series.cs
@@ -21,7 +21,7 @@ Issues:
*/
public class JMA_Series : Single_TSeries_Indicator {
- private readonly System.Collections.Generic.List volty_10 = new();
+ 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; }
@@ -30,14 +30,17 @@ public class JMA_Series : Single_TSeries_Indicator {
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, bool useNaN = false) : base(source, period, useNaN) {
+ 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();
@@ -77,32 +80,32 @@ public class JMA_Series : Single_TSeries_Indicator {
if (Math.Abs(del1) < Math.Abs(del2)) { volty = Math.Abs(del2); }
//// from volty to avolty
- if (update) { volty_10[volty_10.Count - 1] = volty; }
- else { volty_10.Add(volty); }
- if (volty_10.Count > 10) { volty_10.RemoveAt(0); }
- vsum = prev_vsum + 0.1 * (volty - volty_10.First());
+ 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 > (10 * _p)) { vsum_buff.RemoveAt(0); }
+ 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(2.0 * _p)) / Math.Log(2.0)) + 2;
- if (len1 < 0) len1 = 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 len2 = Math.Sqrt(0.5 * (_p - 2)) * len1;
- Kv = Math.Pow(len2 / (len2 + 2), Math.Sqrt(pow2));
double beta = 0.45 * (_p - 1) / (0.45 * (_p - 1) + 2);
- double alpha = Math.Pow(beta * 1.1, pow2);
+ 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);
diff --git a/Tests/Validations/Trends/Pandas_TA.cs b/Tests/Validations/Trends/Pandas_TA.cs
index 64d38ee9..6c05cbc8 100644
--- a/Tests/Validations/Trends/Pandas_TA.cs
+++ b/Tests/Validations/Trends/Pandas_TA.cs
@@ -5,6 +5,8 @@ using Python.Runtime;
using Python.Included;
namespace Validations;
+
+/*
public class PandasTA : IDisposable
{
private readonly GBM_Feed bars;
@@ -144,7 +146,7 @@ public class PandasTA : IDisposable
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
- */
+
[Fact] void EMA() {
EMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.ema(close: df.close, length: period);
@@ -155,7 +157,7 @@ public class PandasTA : IDisposable
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
- /*
+
[Fact] void ENTROPY() {
ENTROPY_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.entropy(close: df.close, length: period);
@@ -309,7 +311,7 @@ public class PandasTA : IDisposable
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
- */
+
[Fact] void SMA() {
SMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.sma(close: df.close, length: period);
@@ -320,7 +322,7 @@ public class PandasTA : IDisposable
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
- /*
+
[Fact] void SSDEV() {
SSDEV_Series QL = new(bars.Close, period, useNaN: false);
var pta = df.ta.stdev(close: df.close, length: period, ddof: 1);
@@ -432,5 +434,6 @@ public class PandasTA : IDisposable
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
- */
-}
\ No newline at end of file
+
+}
+*/
\ No newline at end of file