style: format code with dotnet-format

This commit fixes the style issues introduced in ed45c9e according to the output
from dotnet-format.

Details: None
This commit is contained in:
deepsource-autofix[bot]
2024-10-06 07:24:57 +00:00
committed by GitHub
parent ed45c9e5b8
commit 40842ba5fc
116 changed files with 1773 additions and 2748 deletions
+1 -1
View File
@@ -338,7 +338,7 @@ public class SkenderTests
var SK = quotes.GetAtr(lookbackPeriods: period).Select(i => i.Atr.Null2NaN()!);
Assert.Equal(QL.Length, QL.Length);
for (int i = QL.Length - 1; i > period +500; i--)
for (int i = QL.Length - 1; i > period + 500; i--)
{
Assert.InRange(SK.ElementAt(i) - QL[i].Value, -range, range);
}
+19 -19
View File
@@ -12,7 +12,7 @@ public class TAlibTests
private readonly GbmFeed feed;
private readonly Random rnd;
private readonly double range;
private readonly int iterations;
private readonly int iterations;
private readonly double[] data;
private readonly double[] TALIB;
@@ -110,28 +110,28 @@ public class TAlibTests
}
}
//TODO fix WMA
/*
[Fact]
public void WMA()
{
for (int run = 0; run < iterations; run++)
//TODO fix WMA
/*
[Fact]
public void WMA()
{
period = rnd.Next(50) + 5;
Wma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
Core.Wma(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(QL.Length, TALIB.Count());
for (int i = QL.Length - 1; i > period*3; i--)
for (int run = 0; run < iterations; run++)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
period = rnd.Next(50) + 5;
Wma ma = new(period);
TSeries QL = new();
foreach (TBar item in feed)
{ QL.Add(ma.Calc(new TValue(item.Time, item.Close))); }
Core.Wma(data, 0, QL.Length - 1, TALIB, out int outBegIdx, out _, period);
Assert.Equal(QL.Length, TALIB.Count());
for (int i = QL.Length - 1; i > period*3; i--)
{
double TL = i < outBegIdx ? double.NaN : TALIB[i - outBegIdx];
Assert.InRange(TALIB[i - outBegIdx] - QL[i].Value, -range, range);
}
}
}
}
*/
*/
[Fact]
public void T3()
+35 -50
View File
@@ -3,45 +3,44 @@ using System;
public readonly record struct TValue(DateTime Time, double Value, bool IsNew = true, bool IsHot = true)
{
public DateTime Time { get; init; } = Time;
public double Value { get; init; } = Value;
public bool IsNew { get; init; } = IsNew;
public bool IsHot { get; init; } = IsHot;
public double Value { get; init; } = Value;
public bool IsNew { get; init; } = IsNew;
public bool IsHot { get; init; } = IsHot;
public TValue() : this(DateTime.UtcNow, 0) { }
public TValue(double value) : this(DateTime.UtcNow, value) { }
public TValue((DateTime time, double value) tuple) : this(tuple.time, tuple.value) { }
public TValue() : this(DateTime.UtcNow, 0) { }
public TValue(double value) : this(DateTime.UtcNow, value) { }
public TValue((DateTime time, double value) tuple) : this(tuple.time, tuple.value) { }
public static implicit operator double(TValue tv) => tv.Value;
public static implicit operator DateTime(TValue tv) => tv.Time;
public static implicit operator TValue(double value) => new TValue(DateTime.UtcNow, value);
public static implicit operator double(TValue tv) => tv.Value;
public static implicit operator DateTime(TValue tv) => tv.Time;
public static implicit operator TValue(double value) => new TValue(DateTime.UtcNow, value);
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: {Value:F2}]";
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: {Value:F2}]";
}
public readonly record struct TBar(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true)
{
public DateTime Time { get; init; } = Time;
public double Open { get; init; } = Open;
public double High { get; init; } = High;
public double Low { get; init; } = Low;
public double Close { get; init; } = Close;
public double Volume { get; init; } = Volume;
public bool IsNew { get; init; } = IsNew;
public double Open { get; init; } = Open;
public double High { get; init; } = High;
public double Low { get; init; } = Low;
public double Close { get; init; } = Close;
public double Volume { get; init; } = Volume;
public bool IsNew { get; init; } = IsNew;
public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { }
public TBar(double open, double high, double low, double close, double volume) : this(DateTime.UtcNow, open, high, low, close, volume) { }
public TBar((DateTime time, double open, double high, double low, double close, double volume) tuple) : this(tuple.time, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume) { }
public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { }
public TBar(double open, double high, double low, double close, double volume) : this(DateTime.UtcNow, open, high, low, close, volume) { }
public TBar((DateTime time, double open, double high, double low, double close, double volume) tuple) : this(tuple.time, tuple.open, tuple.high, tuple.low, tuple.close, tuple.volume) { }
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]";
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]";
}
/////////////////////
///
/////////////////////
public class GBM_Feed
{
public class GBM_Feed {
private readonly double _mu;
private readonly double _sigma;
private readonly Random _random;
@@ -49,8 +48,7 @@ public class GBM_Feed
private double _lastHigh;
private double _lastLow;
public GBM_Feed(double initialPrice, double mu, double sigma)
{
public GBM_Feed(double initialPrice, double mu, double sigma) {
_lastClose = initialPrice;
_lastHigh = initialPrice;
_lastLow = initialPrice;
@@ -59,8 +57,7 @@ public class GBM_Feed
_random = Random.Shared;
}
public TBar Generate(bool IsNew = true)
{
public TBar Generate(bool IsNew = true) {
DateTime time = DateTime.UtcNow;
double dt = 1.0 / 252; // Assuming daily steps in a trading year of 252 days
double drift = (_mu - 0.5 * _sigma * _sigma) * dt;
@@ -72,13 +69,10 @@ public class GBM_Feed
double low = Math.Min(open, newClose) * (1 - _random.NextDouble() * 0.01);
double volume = 1000 + _random.NextDouble() * 1000; // Random volume between 1000 and 2000
if (!IsNew)
{
if (!IsNew) {
high = Math.Max(_lastHigh, high);
low = Math.Min(_lastLow, low);
}
else
{
} else {
_lastClose = newClose;
}
@@ -88,8 +82,7 @@ public class GBM_Feed
return new TBar(time, open, high, low, newClose, volume, IsNew);
}
private double NormalRandom()
{
private double NormalRandom() {
// Box-Muller transform to generate standard normal random variable
double u1 = 1.0 - _random.NextDouble(); // Uniform(0,1] random doubles
double u2 = 1.0 - _random.NextDouble();
@@ -102,8 +95,7 @@ public class GBM_Feed
/// ////////////////
/// </summary>
public class EMA
{
public class EMA {
private double lastEma, lastEmaCandidate, k;
private int period, i;
public TValue Value { get; private set; }
@@ -113,8 +105,7 @@ public class EMA
Init(period);
}
public void Init(int period)
{
public void Init(int period) {
this.period = period;
this.k = 2.0 / (period + 1);
this.lastEma = this.lastEmaCandidate = double.NaN;
@@ -130,7 +121,7 @@ public class EMA
i++;
}
double kk = (i<period)?(2.0/(i+1)):k;
double kk = (i < period) ? (2.0 / (i + 1)) : k;
ema = lastEma + kk * (input.Value - lastEma);
lastEmaCandidate = ema;
@@ -143,21 +134,18 @@ public class EMA
/////////////////
///
public class SMA
{
public class SMA {
private CircularBuffer<double> buffer;
private int period;
private double sum;
public TValue Value { get; private set; }
public bool IsHot { get; private set; }
public SMA(int period)
{
public SMA(int period) {
Init(period);
}
public void Init(int period)
{
public void Init(int period) {
this.period = period;
this.buffer = new CircularBuffer<double>(period);
this.sum = 0;
@@ -165,10 +153,8 @@ public class SMA
this.Value = default;
}
public TValue Update(TValue input, bool IsNew = true)
{
if (IsNew)
{
public TValue Update(TValue input, bool IsNew = true) {
if (IsNew) {
if (buffer.Count == period) {
sum -= buffer[0];
}
@@ -197,8 +183,7 @@ public class SMA
/////////////////////
public class CircularBuffer<double>
{
public class CircularBuffer<double> {
private double[] _buffer;
private int _start;
private int _size;
+5 -10
View File
@@ -9,23 +9,18 @@ Remarks:
</summary> */
public class ADD_Series : Pair_TSeries_Indicator
{
public ADD_Series(TSeries d1, TSeries d2) : base(d1, d2)
{
public class ADD_Series : Pair_TSeries_Indicator {
public ADD_Series(TSeries d1, TSeries d2) : base(d1, d2) {
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); } }
}
public ADD_Series(TSeries d1, double dd2) : base(d1, dd2)
{
public ADD_Series(TSeries d1, double dd2) : base(d1, dd2) {
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
}
public ADD_Series(double dd1, TSeries d2) : base(dd1, d2)
{
public ADD_Series(double dd1, TSeries d2) : base(dd1, d2) {
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
}
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v + TValue2.v);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
}
+3 -6
View File
@@ -15,10 +15,8 @@ Sources:
</summary> */
public class CORR_Series : Pair_TSeries_Indicator
{
public CORR_Series(TSeries d1, TSeries d2, int period, bool useNaN = false) : base(d1, d2, period, useNaN)
{
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); } }
}
@@ -28,8 +26,7 @@ public class CORR_Series : Pair_TSeries_Indicator
private readonly System.Collections.Generic.List<double> _yy = new();
private readonly System.Collections.Generic.List<double> _xy = new();
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
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);
+5 -10
View File
@@ -14,14 +14,10 @@ Sources:
</summary> */
public class COVAR_Series : Pair_TSeries_Indicator
{
public COVAR_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++)
{
public class COVAR_Series : Pair_TSeries_Indicator {
public COVAR_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);
}
}
@@ -31,8 +27,7 @@ public class COVAR_Series : Pair_TSeries_Indicator
private readonly System.Collections.Generic.List<double> _y = new();
private readonly System.Collections.Generic.List<double> _xy = new();
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
BufferTrim(_x, TValue1.v, _p, update);
BufferTrim(_y, TValue2.v, _p, update);
BufferTrim(_xy, TValue1.v * TValue2.v, _p, update);
+5 -10
View File
@@ -8,23 +8,18 @@ Remarks:
Most of scaffolding is packaged in abstracty class Pair_TSeries_Indicator.
</summary> */
public class DIV_Series : Pair_TSeries_Indicator
{
public DIV_Series(TSeries d1, TSeries d2) : base(d1, d2)
{
public class DIV_Series : Pair_TSeries_Indicator {
public DIV_Series(TSeries d1, TSeries d2) : base(d1, d2) {
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); } }
}
public DIV_Series(TSeries d1, double dd2) : base(d1, dd2)
{
public DIV_Series(TSeries d1, double dd2) : base(d1, dd2) {
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
}
public DIV_Series(double dd1, TSeries d2) : base(dd1, d2)
{
public DIV_Series(double dd1, TSeries d2) : base(dd1, d2) {
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
}
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,
(TValue2.v is not 0) ? TValue1.v / TValue2.v : Double.PositiveInfinity);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
+5 -10
View File
@@ -6,23 +6,18 @@ MUL - multiply TSeries*TSeries together, or TSeries*double, or double*TSeries
</summary> */
public class MUL_Series : Pair_TSeries_Indicator
{
public MUL_Series(TSeries d1, TSeries d2) : base(d1, d2)
{
public class MUL_Series : Pair_TSeries_Indicator {
public MUL_Series(TSeries d1, TSeries d2) : base(d1, d2) {
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); } }
}
public MUL_Series(TSeries d1, double dd2) : base(d1, dd2)
{
public MUL_Series(TSeries d1, double dd2) : base(d1, dd2) {
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
}
public MUL_Series(double dd1, TSeries d2) : base(dd1, d2)
{
public MUL_Series(double dd1, TSeries d2) : base(dd1, d2) {
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
}
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,
TValue1.v * TValue2.v);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
+5 -10
View File
@@ -7,23 +7,18 @@ SUB - subtracting TSeries-TSeries, or TSeries-double, or double-TSeries
</summary> */
public class SUB_Series : Pair_TSeries_Indicator
{
public SUB_Series(TSeries d1, TSeries d2) : base(d1, d2)
{
public class SUB_Series : Pair_TSeries_Indicator {
public SUB_Series(TSeries d1, TSeries d2) : base(d1, d2) {
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); } }
}
public SUB_Series(TSeries d1, double dd2) : base(d1, dd2)
{
public SUB_Series(TSeries d1, double dd2) : base(d1, dd2) {
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
}
public SUB_Series(double dd1, TSeries d2) : base(dd1, d2)
{
public SUB_Series(double dd1, TSeries d2) : base(dd1, d2) {
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
}
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
(System.DateTime t, double v) result = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t,
TValue1.v - TValue2.v);
if (update) { base[base.Count - 1] = result; } else { base.Add(result); }
@@ -16,8 +16,7 @@ Abstract classes with all scaffolding required to build indicators.
</summary> */
public abstract class Pair_TSeries_Indicator : TSeries
{
public abstract class Pair_TSeries_Indicator : TSeries {
protected readonly int _p;
protected readonly bool _NaN;
protected readonly TSeries _d1;
@@ -25,8 +24,7 @@ public abstract class Pair_TSeries_Indicator : TSeries
protected readonly double _dd1, _dd2;
// Chainable Constructors - add them at the end of primary constructors if needed
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN)
{
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2, int period, bool useNaN) {
_p = period;
_NaN = useNaN;
_d1 = source1;
@@ -37,8 +35,7 @@ public abstract class Pair_TSeries_Indicator : TSeries
_d2.Pub += Sub;
}
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2)
{
protected Pair_TSeries_Indicator(TSeries source1, TSeries source2) {
_d1 = source1;
_d2 = source2;
_dd1 = double.NaN;
@@ -47,8 +44,7 @@ public abstract class Pair_TSeries_Indicator : TSeries
_d2.Pub += Sub;
}
protected Pair_TSeries_Indicator(TSeries source1, double dd2)
{
protected Pair_TSeries_Indicator(TSeries source1, double dd2) {
_d1 = source1;
_d2 = new TSeries();
_dd1 = double.NaN;
@@ -56,8 +52,7 @@ public abstract class Pair_TSeries_Indicator : TSeries
_d1.Pub += Sub;
}
protected Pair_TSeries_Indicator(double dd1, TSeries source2)
{
protected Pair_TSeries_Indicator(double dd1, TSeries source2) {
_d1 = new TSeries();
_d2 = source2;
_dd1 = dd1;
@@ -66,91 +61,68 @@ public abstract class Pair_TSeries_Indicator : TSeries
}
// overridable Add(Tvalue, Tvalue) method to add/update a single value at the end of the list
public virtual void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2, bool update)
{
public virtual void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2, bool update) {
base.Add((TValue1.t, 0), update);
// default inserts zeros
}
// potentially overridable Add() bulk variations (could be replaced with faster bulk algos)
public virtual void Add(TSeries d1, TSeries d2)
{
for (var i = 0; i < d1.Count; i++)
{
public virtual void Add(TSeries d1, TSeries d2) {
for (var i = 0; i < d1.Count; i++) {
Add(d1[i], d2[i], false);
}
}
public virtual void Add(TSeries d1, double dd2)
{
for (var i = 0; i < d1.Count; i++)
{
public virtual void Add(TSeries d1, double dd2) {
for (var i = 0; i < d1.Count; i++) {
Add(d1[i], (d1[i].t, dd2), false);
}
}
public virtual void Add(double dd1, TSeries d2)
{
for (var i = 0; i < d2.Count; i++)
{
public virtual void Add(double dd1, TSeries d2) {
for (var i = 0; i < d2.Count; i++) {
Add((d2[i].t, dd1), d2[i], false);
}
}
public void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2)
{
public void Add((DateTime t, double v) TValue1, (DateTime t, double v) TValue2) {
Add(TValue1, TValue2, false);
}
public void Add(bool update)
{
if (_dd1 is double.NaN && _dd2 is double.NaN)
{
public void Add(bool update) {
if (_dd1 is double.NaN && _dd2 is double.NaN) {
// (Series, Series)
if (update || (_d1.Count > Count && _d2.Count > Count))
{
if (update || (_d1.Count > Count && _d2.Count > Count)) {
Add(_d1[_d1.Count - 1], _d2[_d2.Count - 1], update);
}
}
else if (_dd2 is not double.NaN && _dd1 is double.NaN)
{
} else if (_dd2 is not double.NaN && _dd1 is double.NaN) {
// (Series, Double)
Add(_d1[_d1.Count - 1], (_d1[_d1.Count - 1].t, _dd2), update);
}
else
{
} else {
// (Double, Series)
Add((_d2[_d2.Count - 1].t, _dd1), _d2[_d2.Count - 1], update);
}
}
public void Add()
{
public void Add() {
Add(false);
}
public new void Sub(object source, TSeriesEventArgs e)
{
public new void Sub(object source, TSeriesEventArgs e) {
Add(e.update);
}
protected static void Add_Replace(List<double> l, double v, bool update)
{
if (update)
{
protected static void Add_Replace(List<double> l, double v, bool update) {
if (update) {
l[l.Count - 1] = v;
}
else
{
} else {
l.Add(v);
}
}
protected static void Add_Replace_Trim(List<double> l, double v, int p, bool update)
{
protected static void Add_Replace_Trim(List<double> l, double v, int p, bool update) {
Add_Replace(l, v, update);
if (l.Count > p && p != 0)
{
if (l.Count > p && p != 0) {
l.RemoveAt(0);
}
}
@@ -11,11 +11,9 @@ Alphavantage - Free API to collect 100 recent daily quotes. It requires a (free)
</summary>
*/
public class Alphavantage_Feed : TBars
{
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")
{
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;
@@ -27,15 +25,12 @@ public class Alphavantage_Feed : TBars
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)
{
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)
{
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;
+5 -10
View File
@@ -18,27 +18,23 @@ GBM - Geometric Brownian Motion is a random simulator of market movement, return
</summary> */
public class GBM_Feed : TBars
{
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)
{
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 < Bars; i++)
{
for (int i = 0; i < Bars; i++) {
DateTime Timestamp = DateTime.Today.AddDays(i - Bars);
this.Add(Timestamp);
}
}
public void Add(bool update = false) { this.Add(DateTime.Now, update); }
public void Add(DateTime timestamp, bool update = false)
{
public void Add(DateTime timestamp, bool update = false) {
double Open = GBM_value(seed, volatility * volatility, drift, precision);
double Close = GBM_value(Open, volatility, drift, precision);
@@ -56,8 +52,7 @@ public class GBM_Feed : TBars
seed = Close;
}
private static double GBM_value(double Seed, double Volatility, double Drift, int precision)
{
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();
+3 -6
View File
@@ -9,14 +9,11 @@ Random Bars generator - used for testing, validation and fun
</summary> */
public class RND_Feed : TBars
{
public RND_Feed(int Bars, double Volatility = 0.05, double Startvalue = 100.0)
{
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++)
{
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);
+3 -6
View File
@@ -12,10 +12,8 @@ Yahoo Finance - Free API feed to collect daily market quotes
</summary>
*/
public class Yahoo_Feed : TBars
{
public Yahoo_Feed(string Symbol = "IBM", int Period = 252)
{
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=" +
@@ -36,8 +34,7 @@ public class Yahoo_Feed : TBars
json[0].TryGetProperty("close", out JsonElement close);
json[0].TryGetProperty("volume", out JsonElement volume);
for (int i = 0; i < datetime.GetArrayLength(); i++)
{
for (int i = 0; i < datetime.GetArrayLength(); i++) {
DateTime d = DateTimeOffset.FromUnixTimeSeconds(long.Parse(datetime[i].GetRawText())).DateTime;
double o = Math.Round(double.Parse(open[i].GetRawText()), 3);
double h = Math.Round(double.Parse(high[i].GetRawText()), 3);
+6 -12
View File
@@ -7,30 +7,24 @@ COMPARE - Generates +1 if A is above B, -1 if A is below B and 0 if A=B
</summary> */
public class COMPARE_Series : Pair_TSeries_Indicator
{
public class COMPARE_Series : Pair_TSeries_Indicator {
public COMPARE_Series(TSeries d1, TSeries d2) : base(d1, d2)
{
public COMPARE_Series(TSeries d1, TSeries d2) : base(d1, d2) {
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); } }
}
public COMPARE_Series(TSeries d1, double dd2) : base(d1, dd2)
{
public COMPARE_Series(TSeries d1, double dd2) : base(d1, dd2) {
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
}
public COMPARE_Series(double dd1, TSeries d2) : base(dd1, d2)
{
public COMPARE_Series(double dd1, TSeries d2) : base(dd1, d2) {
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
}
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
double val = TValue1.v > TValue2.v ? 1 : -1;
val = TValue1.v == TValue2.v ? 0 : val;
(System.DateTime t, double v) over = ((TValue1.t > TValue2.t) ? TValue1.t : TValue2.t, TValue1.v > TValue2.v ? 1 : val);
if (update) { base[^1] = over; }
else { base.Add(over); }
if (update) { base[^1] = over; } else { base.Add(over); }
}
+6 -12
View File
@@ -9,26 +9,21 @@ Remarks:
</summary> */
public class CROSS_Series : Pair_TSeries_Indicator
{
public class CROSS_Series : Pair_TSeries_Indicator {
public TSeries Cross { get; set; } = new();
private double _previous = double.NaN;
public CROSS_Series(TSeries d1, TSeries d2) : base(d1, d2)
{
public CROSS_Series(TSeries d1, TSeries d2) : base(d1, d2) {
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); } }
}
public CROSS_Series(TSeries d1, double dd2) : base(d1, dd2)
{
public CROSS_Series(TSeries d1, double dd2) : base(d1, dd2) {
if (base._d1.Count > 0) { for (int i = 0; i < base._d1.Count; i++) { this.Add(base._d1[i], (base._d1[i].t, dd2), false); } }
}
public CROSS_Series(double dd1, TSeries d2) : base(dd1, d2)
{
public CROSS_Series(double dd1, TSeries d2) : base(dd1, d2) {
if (base._d2.Count > 0) { for (int i = 0; i < base._d2.Count; i++) { this.Add((base._d2[i].t, dd1), base._d2[i], false); } }
}
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update)
{
public override void Add((System.DateTime t, double v) TValue1, (System.DateTime t, double v) TValue2, bool update) {
double val = TValue1.v > TValue2.v ? 1 : -1;
val = TValue1.v == TValue2.v ? 0 : val;
@@ -40,8 +35,7 @@ public class CROSS_Series : Pair_TSeries_Indicator
this._previous = over;
if (update) { base[^1] = result; }
else { base.Add(result); }
if (update) { base[^1] = result; } else { base.Add(result); }
}
}
+5 -10
View File
@@ -6,8 +6,7 @@ using System.Data;
using System.Linq;
public enum OType
{
public enum OType {
NIL = 0, // No position
BTO = 1, // Buy to Open
STC = 2, // Sell to Close
@@ -17,19 +16,15 @@ public enum OType
}
public class TOrders : List<(DateTime t, OType o)>
{
public class TOrders : List<(DateTime t, OType o)> {
public void Add((DateTime t, OType o) TOrder, bool update = false)
{
if (update) { this[^1] = TOrder; }
else { base.Add(TOrder); }
public void Add((DateTime t, OType o) TOrder, bool update = false) {
if (update) { this[^1] = TOrder; } else { base.Add(TOrder); }
OnEvent(update);
}
protected virtual void OnEvent(bool update = false)
{
protected virtual void OnEvent(bool update = false) {
Pub?.Invoke(this, new TSeriesEventArgs { update = update });
}
public delegate void NewDataEventHandler(object source, TSeriesEventArgs args);
+11 -22
View File
@@ -15,19 +15,16 @@ Sources:
</summary> */
public class ADL_Series : TSeries
{
public class ADL_Series : TSeries {
protected readonly TBars _data;
private double _lastadl, _lastlastadl;
//core constructors
public ADL_Series()
{
public ADL_Series() {
Name = $"ADL()";
_lastadl = _lastlastadl = 0;
}
public ADL_Series(TBars source)
{
public ADL_Series(TBars source) {
_data = source;
Name = $"ADL({(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_lastadl = _lastlastadl = 0;
@@ -37,15 +34,12 @@ public class ADL_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
if (update) { this._lastadl = this._lastlastadl; }
else { this._lastlastadl = this._lastadl; }
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update) { this._lastadl = this._lastlastadl; } else { this._lastlastadl = this._lastadl; }
double _adl = 0;
double tmp = TBar.h - TBar.l;
if (tmp > 0.0)
{
if (tmp > 0.0) {
_adl = _lastadl + ((2 * TBar.c - TBar.l - TBar.h) / tmp * TBar.v);
}
_lastadl = _adl;
@@ -54,26 +48,21 @@ public class ADL_Series : TSeries
return base.Add(ret, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_lastadl = _lastlastadl = 0;
}
}
+10 -20
View File
@@ -14,23 +14,20 @@ Sources:
</summary> */
public class ADOSC_Series : TSeries
{
public class ADOSC_Series : TSeries {
protected readonly TBars _data;
private readonly double _k1, _k2;
private double _lastema1, _lastlastema1, _lastema2, _lastlastema2;
private double _lastadl, _lastlastadl;
//core constructors
public ADOSC_Series(int shortPeriod, int longPeriod, bool useNaN = false)
{
public ADOSC_Series(int shortPeriod, int longPeriod, bool useNaN = false) {
Name = $"ADOSC()";
_k1 = 2.0 / (shortPeriod + 1);
_k2 = 2.0 / (longPeriod + 1);
_lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0;
}
public ADOSC_Series(TBars source, int shortPeriod, int longPeriod, bool useNaN = false) : this(shortPeriod, longPeriod, useNaN)
{
public ADOSC_Series(TBars source, int shortPeriod, int longPeriod, bool useNaN = false) : this(shortPeriod, longPeriod, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_lastadl = _lastlastadl = 0;
@@ -44,11 +41,9 @@ public class ADOSC_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update)
{
if (update) {
_lastadl = _lastlastadl;
_lastema1 = _lastlastema1;
_lastema2 = _lastlastema2;
@@ -75,26 +70,21 @@ public class ADOSC_Series : TSeries
return base.Add(ret, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_lastadl = _lastlastadl = _lastema1 = _lastlastema1 = _lastema2 = _lastlastema2 = 0;
}
}
+15 -30
View File
@@ -19,8 +19,7 @@ Sources:
Discrepancy with Pandas-TA (but passes the validation with Skender.GetAlma)
</summary> */
public class ALMA_Series : TSeries
{
public class ALMA_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
@@ -31,8 +30,7 @@ public class ALMA_Series : TSeries
private readonly double _offset, _sigma;
//core constructors
public ALMA_Series(int period, double offset, double sigma, bool useNaN)
{
public ALMA_Series(int period, double offset, double sigma, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"ALMA({period})";
@@ -40,8 +38,7 @@ public class ALMA_Series : TSeries
_sigma = sigma;
_weight = new();
}
public ALMA_Series(TSeries source, int period, double offset, double sigma, bool useNaN) : this(period, offset, sigma, useNaN)
{
public ALMA_Series(TSeries source, int period, double offset, double sigma, bool useNaN) : this(period, offset, sigma, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -58,31 +55,25 @@ public class ALMA_Series : TSeries
public ALMA_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, offset: 0.85, sigma: 6.0, useNaN: useNaN) { }
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, double.NaN), update);
}
BufferTrim(_buffer, TValue.v, _period, update);
if (_weight.Count < _buffer.Count)
{
for (var i = 0; i < _buffer.Count - _weight.Count; i++)
{
if (_weight.Count < _buffer.Count) {
for (var i = 0; i < _buffer.Count - _weight.Count; i++) {
_weight.Add(0.0);
}
}
if (_buffer.Count <= _period || _period == 0)
{
if (_buffer.Count <= _period || _period == 0) {
var _len = _buffer.Count;
_norm = 0;
var _m = _offset * (_len - 1);
var _s = _len / _sigma;
for (var i = 0; i < _len; i++)
{
for (var i = 0; i < _len; i++) {
var _wt = Math.Exp(-((i - _m) * (i - _m)) / (2 * _s * _s));
_weight[i] = _wt;
_norm += _wt;
@@ -90,8 +81,7 @@ public class ALMA_Series : TSeries
}
double _weightedSum = 0;
for (var i = 0; i < _buffer.Count; i++)
{
for (var i = 0; i < _buffer.Count; i++) {
_weightedSum += _weight[i] * _buffer[i];
}
@@ -102,27 +92,22 @@ public class ALMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
_weight.Clear();
}
+11 -24
View File
@@ -12,8 +12,7 @@ Sources:
</summary> */
public class ATRP_Series : TSeries
{
public class ATRP_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TBars _data;
@@ -22,16 +21,14 @@ public class ATRP_Series : TSeries
private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum;
//core constructors
public ATRP_Series(int period, bool useNaN)
{
public ATRP_Series(int period, bool useNaN) {
_period = period;
_k = 1.0 / (double)(_period);
_NaN = useNaN;
_len = 0;
Name = $"ATRP({period})";
}
public ATRP_Series(TBars source, int period, bool useNaN) : this(period, useNaN)
{
public ATRP_Series(TBars source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -44,11 +41,8 @@ public class ATRP_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; }
else
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; } else {
_lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum;
_k = (_period == 0) ? 1 / (double)_len : _k;
_len++;
@@ -62,9 +56,7 @@ public class ATRP_Series : TSeries
_cm1 = TBar.c;
double _atr = 0;
if (this.Count == 0) { _atr = d.v; }
else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); }
else { _atr = _k * (d.v - _lastatr) + _lastatr; }
if (this.Count == 0) { _atr = d.v; } else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); } else { _atr = _k * (d.v - _lastatr) + _lastatr; }
_lastatr = _atr;
double _atrp = 100 * (_atr / TBar.c);
@@ -72,26 +64,21 @@ public class ATRP_Series : TSeries
return base.Add(res, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
}
}
+11 -24
View File
@@ -14,8 +14,7 @@ Sources:
</summary> */
public class ATR_Series : TSeries
{
public class ATR_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TBars _data;
@@ -24,16 +23,14 @@ public class ATR_Series : TSeries
private double _lastatr, _lastlastatr, _cm1, _lastcm1, _sum, _oldsum;
//core constructors
public ATR_Series(int period, bool useNaN)
{
public ATR_Series(int period, bool useNaN) {
_period = period;
_k = 1.0 / (double)(_period);
_NaN = useNaN;
_len = 0;
Name = $"ATR({period})";
}
public ATR_Series(TBars source, int period, bool useNaN) : this(period, useNaN)
{
public ATR_Series(TBars source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -46,11 +43,8 @@ public class ATR_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; }
else
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update) { _lastatr = _lastlastatr; _cm1 = _lastcm1; _sum = _oldsum; } else {
_lastlastatr = _lastatr; _lastcm1 = _cm1; _oldsum = _sum;
_k = (_period == 0) ? 1 / (double)_len : _k;
_len++;
@@ -64,35 +58,28 @@ public class ATR_Series : TSeries
_cm1 = TBar.c;
double _atr = 0;
if (this.Count == 0) { _atr = d.v; }
else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); }
else { _atr = _k * (d.v - _lastatr) + _lastatr; }
if (this.Count == 0) { _atr = d.v; } else if (this.Count < _period + 1) { _sum += d.v; _atr = _sum / (this.Count); } else { _atr = _k * (d.v - _lastatr) + _lastatr; }
_lastatr = _atr;
var res = (TBar.t, Count < _period - 1 && _NaN ? double.NaN : _atr);
return base.Add(res, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
}
}
+9 -18
View File
@@ -26,8 +26,7 @@ Note:
</summary> */
public class BBANDS_Series : TSeries
{
public class BBANDS_Series : TSeries {
protected readonly int _period;
protected readonly double _multiplier;
protected readonly bool _NaN;
@@ -41,15 +40,13 @@ public class BBANDS_Series : TSeries
private readonly SDEV_Series _sdev;
//core constructors
public BBANDS_Series(int period, double multiplier, bool useNaN)
{
public BBANDS_Series(int period, double multiplier, bool useNaN) {
_period = period;
_multiplier = multiplier;
_NaN = useNaN;
Name = $"BBANDS({period})";
}
public BBANDS_Series(TSeries source, int period, double multiplier, bool useNaN) : this(period, multiplier, useNaN)
{
public BBANDS_Series(TSeries source, int period, double multiplier, bool useNaN) : this(period, multiplier, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
Upper = new("BB_Up");
@@ -75,8 +72,7 @@ public class BBANDS_Series : TSeries
public BBANDS_Series(TSeries source, int period, bool useNaN) : this(source: source, period: period, multiplier: 2.0, useNaN: useNaN) { }
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
var _mid = Mid.Add(TValue, update);
var _sd = this._sdev.Add(TValue, update);
var _upper = Upper.Add((TValue.t, _mid.v + _sd.v * _multiplier), update);
@@ -92,27 +88,22 @@ public class BBANDS_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
Mid.Clear();
_sdev.Clear();
Upper.Clear();
+9 -18
View File
@@ -13,23 +13,20 @@ Sources:
</summary> */
public class BIAS_Series : TSeries
{
public class BIAS_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
private readonly SMA_Series _sma;
//core constructors
public BIAS_Series(int period, bool useNaN)
{
public BIAS_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"BIAS({period})";
_sma = new(period, false);
}
public BIAS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public BIAS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -45,8 +42,7 @@ public class BIAS_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
var _s = _sma.Add(TValue, update);
double _bias = (TValue.v / ((_s.v != 0) ? _s.v : 1)) - 1;
@@ -54,28 +50,23 @@ public class BIAS_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_sma.Reset();
}
}
+11 -23
View File
@@ -18,22 +18,19 @@ Sources:
</summary> */
public class CCI_Series : TSeries
{
public class CCI_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TBars _data;
private readonly System.Collections.Generic.List<double> _tp = new();
//core constructors
public CCI_Series(int period, bool useNaN)
{
public CCI_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"CCI({period})";
}
public CCI_Series(TBars source, int period, bool useNaN) : this(period, useNaN)
{
public CCI_Series(TBars source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -46,15 +43,11 @@ public class CCI_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
double _tpItem = (TBar.h + TBar.l + TBar.c) / 3.0;
if (update)
{
if (update) {
this._tp[this._tp.Count - 1] = _tpItem;
}
else
{
} else {
this._tp.Add(_tpItem);
}
if (this._tp.Count > this._period) { this._tp.RemoveAt(0); }
@@ -72,26 +65,21 @@ public class CCI_Series : TSeries
return base.Add(res, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_tp.Clear();
}
}
+10 -20
View File
@@ -18,8 +18,7 @@ Sources:
</summary> */
public class CMO_Series : TSeries
{
public class CMO_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buff_up = new();
private readonly System.Collections.Generic.List<double> _buff_dn = new();
protected readonly int _period;
@@ -28,14 +27,12 @@ public class CMO_Series : TSeries
private double _plast_value, _last_value;
//core constructors
public CMO_Series(int period, bool useNaN)
{
public CMO_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"CMO({period})";
}
public CMO_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public CMO_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -51,16 +48,14 @@ public class CMO_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) { _last_value = _plast_value; } else { _plast_value = _last_value; }
BufferTrim(buffer: _buff_up, (TValue.v > _last_value) ? TValue.v - _last_value : 0, period: _period, update: update);
BufferTrim(buffer: _buff_dn, (TValue.v < _last_value) ? _last_value - TValue.v : 0, period: _period, update: 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++)
{
for (int i = 0; i < Math.Min(_buff_up.Count, _buff_dn.Count); i++) {
_cmo_up += _buff_up[i];
_cmo_dn += _buff_dn[i];
}
@@ -71,29 +66,24 @@ public class CMO_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buff_up.Clear();
_buff_dn.Clear();
}
+9 -18
View File
@@ -11,8 +11,7 @@ Sources:
https://en.wikipedia.org/wiki/CUSUM
</summary> */
public class CUSUM_Series : TSeries
{
public class CUSUM_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
@@ -20,14 +19,12 @@ public class CUSUM_Series : TSeries
protected readonly TSeries _data;
//core constructors
public CUSUM_Series(int period, bool useNaN)
{
public CUSUM_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"CUSUM({period})";
}
public CUSUM_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public CUSUM_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -43,8 +40,7 @@ public class CUSUM_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sum = 0;
@@ -53,28 +49,23 @@ public class CUSUM_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+11 -22
View File
@@ -13,8 +13,7 @@ DECAY:
</summary> */
public class DECAY_Series : TSeries
{
public class DECAY_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
@@ -23,8 +22,7 @@ public class DECAY_Series : TSeries
private readonly double _dfactor;
//core constructors
public DECAY_Series(int period, bool exponential, bool useNaN)
{
public DECAY_Series(int period, bool exponential, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"DECAY({period})";
@@ -32,8 +30,7 @@ public class DECAY_Series : TSeries
_dfactor = (_exp) ? 1.0 - 1.0 / (double)_period : 1 / (double)_period;
_pdecay = _ppdecay = 0;
}
public DECAY_Series(TSeries source, int period, bool exponential, bool useNaN) : this(period, exponential, useNaN)
{
public DECAY_Series(TSeries source, int period, bool exponential, bool useNaN) : this(period, exponential, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -50,14 +47,11 @@ public class DECAY_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
if (update) { _pdecay = _ppdecay; }
else { _ppdecay = _pdecay; }
if (update) { _pdecay = _ppdecay; } else { _ppdecay = _pdecay; }
if (this.Count == 0) { _pdecay = TValue.v; }
double _decay = Math.Max(TValue.v, Math.Max((_exp) ? _pdecay * _dfactor : _pdecay - _dfactor, 0));
@@ -66,28 +60,23 @@ public class DECAY_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_pdecay = _ppdecay = 0;
}
}
+17 -37
View File
@@ -17,8 +17,7 @@ Remark:
</summary> */
public class DEMA_Series : TSeries
{
public class DEMA_Series : TSeries {
private double _k;
private double _sum, _oldsum;
private double _lastema1, _oldema1, _lastema2, _oldema2;
@@ -29,8 +28,7 @@ public class DEMA_Series : TSeries
protected readonly TSeries _data;
//core constructor
public DEMA_Series(int period, bool useNaN, bool useSMA)
{
public DEMA_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
_useSMA = useSMA;
@@ -48,8 +46,7 @@ public class DEMA_Series : TSeries
public DEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { }
public DEMA_Series(TSeries source, int period) : this(source, period, false, true) { }
public DEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { }
public DEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public DEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -57,40 +54,30 @@ public class DEMA_Series : TSeries
}
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (update)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) {
_lastema1 = _oldema1;
_lastema2 = _oldema2;
_sum = _oldsum;
}
else
{
} else {
_oldema1 = _lastema1;
_oldema2 = _lastema2;
_oldsum = _sum;
_len++;
}
if (_period == 0)
{
if (_period == 0) {
_k = 2.0 / (_len + 1);
}
double _ema1, _ema2, _dema;
if (Count == 0)
{
if (Count == 0) {
_ema1 = _ema2 = _sum = TValue.v;
}
else if (_len <= _period && _useSMA && _period != 0)
{
} else if (_len <= _period && _useSMA && _period != 0) {
_sum += TValue.v;
_ema1 = _sum / Math.Min(_len, _period);
_ema2 = _ema1;
}
else
{
} else {
_ema1 = (TValue.v - _lastema1) * _k + _lastema1;
_ema2 = (_ema1 - _lastema2) * _k + _lastema2;
}
@@ -105,39 +92,32 @@ public class DEMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
if (data == null)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) {
return (DateTime.Today, double.NaN);
}
foreach (var item in data)
{
foreach (var item in data) {
Add(item, false);
}
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return Add(_data.Last, update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(_data.Last, false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(_data.Last, e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_sum = _oldsum = _lastema1 = _lastema2 = 0;
_len = 0;
}
+22 -44
View File
@@ -11,8 +11,7 @@ DWMA: Double Weighted Moving Average
</summary> */
public class DWMA_Series : TSeries
{
public class DWMA_Series : TSeries {
private readonly List<double> _buffer = new();
private List<double> _weights;
protected readonly int _period;
@@ -21,8 +20,7 @@ public class DWMA_Series : TSeries
protected int _len;
//core constructors
public DWMA_Series(int period, bool useNaN)
{
public DWMA_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"DWMA({period})";
@@ -30,45 +28,36 @@ public class DWMA_Series : TSeries
_weights = CalculateWeights(_period);
}
public DWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public DWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
Add(_data);
}
public DWMA_Series() : this(0, false)
{
public DWMA_Series() : this(0, false) {
}
public DWMA_Series(int period) : this(period, false)
{
public DWMA_Series(int period) : this(period, false) {
}
public DWMA_Series(TBars source) : this(source.Close, 0, false)
{
public DWMA_Series(TBars source) : this(source.Close, 0, false) {
}
public DWMA_Series(TBars source, int period) : this(source.Close, period, false)
{
public DWMA_Series(TBars source, int period) : this(source.Close, period, false) {
}
public DWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN)
{
public DWMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) {
}
public DWMA_Series(TSeries source, int period) : this(source, period, false)
{
public DWMA_Series(TSeries source, int period) : this(source, period, false) {
}
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(_buffer, TValue.v, _period, update);
if (_period == 0)
{
if (_period == 0) {
_len++;
_weights = CalculateWeights(_len);
}
@@ -77,11 +66,9 @@ public class DWMA_Series : TSeries
var bufferCount = _buffer.Count;
var lockObj = new object();
Parallel.For(0, bufferCount, i =>
{
Parallel.For(0, bufferCount, i => {
var temp = _buffer[i] * _weights[i];
lock (lockObj)
{
lock (lockObj) {
_dwma += temp;
_wsum += _weights[i];
}
@@ -91,42 +78,34 @@ public class DWMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
if (data == null)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) {
return (DateTime.Today, double.NaN);
}
foreach (var item in data)
{
foreach (var item in data) {
Add(item, false);
}
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return Add(_data.Last, update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(_data.Last, false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(_data.Last, e.update);
}
//calculating weights
private static List<double> CalculateWeights(int period)
{
private static List<double> CalculateWeights(int period) {
var weights = new List<double>(period);
for (var i = 0; i < period; i++)
{
for (var i = 0; i < period; i++) {
weights.Add((i + 1) * (i + 1));
}
@@ -134,8 +113,7 @@ public class DWMA_Series : TSeries
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
_buffer.Clear();
_weights = CalculateWeights(_period);
+16 -35
View File
@@ -21,8 +21,7 @@ Issues:
</summary> */
public class EMA_Series : TSeries
{
public class EMA_Series : TSeries {
private double _k;
private double _lastema, _oldema;
private double _sum, _oldsum;
@@ -34,8 +33,7 @@ public class EMA_Series : TSeries
//core constructors
public EMA_Series(int period, bool useNaN, bool useSMA)
{
public EMA_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
_useSMA = useSMA;
@@ -44,8 +42,7 @@ public class EMA_Series : TSeries
_len = 0;
_sum = _oldsum = _lastema = _oldema = 0;
}
public EMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public EMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -62,42 +59,31 @@ public class EMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (update)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) {
_lastema = _oldema;
_sum = _oldsum;
}
else
{
} else {
_oldema = _lastema;
_oldsum = _sum;
_len++;
}
double _ema = 0;
if (_period == 0)
{
if (_period == 0) {
_k = 2.0 / (_len + 1);
}
if (Count == 0)
{
if (Count == 0) {
_ema = _sum = TValue.v;
}
else if (_len <= _period && _useSMA && _period != 0)
{
} else if (_len <= _period && _useSMA && _period != 0) {
_sum += TValue.v;
if (_period != 0 && _len > _period)
{
if (_period != 0 && _len > _period) {
_sum -= _data[Count - _period - (update ? 1 : 0)].v;
}
_ema = _sum / Math.Min(_len, _period);
}
else
{
} else {
_ema = _k * (TValue.v - _lastema) + _lastema;
}
@@ -108,28 +94,23 @@ public class EMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_sum = _oldsum = _lastema = _oldema = 0;
_len = 0;
}
+10 -20
View File
@@ -18,8 +18,7 @@ Sources:
</summary> */
public class ENTROPY_Series : TSeries
{
public class ENTROPY_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
@@ -28,15 +27,13 @@ public class ENTROPY_Series : TSeries
private readonly System.Collections.Generic.List<double> _buff2 = new();
//core constructors
public ENTROPY_Series(int period, double logbase, bool useNaN)
{
public ENTROPY_Series(int period, double logbase, bool useNaN) {
_period = period;
_NaN = useNaN;
_logbase = logbase;
Name = $"ENTROPY({period})";
}
public ENTROPY_Series(TSeries source, int period, double logbase, bool useNaN) : this(period, logbase, useNaN)
{
public ENTROPY_Series(TSeries source, int period, double logbase, bool useNaN) : this(period, logbase, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -53,10 +50,8 @@ public class ENTROPY_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
@@ -69,28 +64,23 @@ public class ENTROPY_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
_buff2.Clear();
}
+12 -24
View File
@@ -10,8 +10,7 @@ FWMA: Fibonacci's Weighted Moving Average is similar to a Weighted Moving Averag
(WMA) where the weights are based on the Fibonacci Sequence.
</summary> */
public class FWMA_Series : TSeries
{
public class FWMA_Series : TSeries {
private readonly List<double> _buffer = new();
private List<double> _weights;
protected readonly int _period;
@@ -19,8 +18,7 @@ public class FWMA_Series : TSeries
protected readonly TSeries _data;
protected int _len;
public FWMA_Series(int period, bool useNaN)
{
public FWMA_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"FWMA({period})";
@@ -28,8 +26,7 @@ public class FWMA_Series : TSeries
_weights = CalculateWeights(_period);
}
public FWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public FWMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -45,19 +42,16 @@ public class FWMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
if (_period == 0)
{
if (_period == 0) {
_len++;
_weights = CalculateWeights(_len);
}
double _fwma = 0;
double totalWeights = _weights.Sum();
object lockObj = new object();
Parallel.For(0, _buffer.Count, i =>
{
Parallel.For(0, _buffer.Count, i => {
double temp = _buffer[i] * _weights[i];
lock (lockObj) { _fwma += temp; }
});
@@ -65,30 +59,25 @@ public class FWMA_Series : TSeries
var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _fwma);
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
private static List<double> CalculateWeights(int period)
{
private static List<double> CalculateWeights(int period) {
//to prevent overflow, max period can be no more than 1476
period = (period > 1476) ? 1476 : period;
List<double> weights = new List<double>(period);
BigInteger a = 0;
BigInteger b = 1;
for (int i = 0; i < period; i++)
{
for (int i = 0; i < period; i++) {
BigInteger temp = a;
a = b;
b = temp + b;
@@ -97,8 +86,7 @@ public class FWMA_Series : TSeries
return weights;
}
public override void Reset()
{
public override void Reset() {
_weights = CalculateWeights(_period);
_buffer.Clear();
}
+16 -35
View File
@@ -13,8 +13,7 @@ Raw HMA = (2 * EMA1) - EMA2
EMA3 = EMA(sqrt(n)) of Raw HMA - where k = 2/(sqrt(n)+1)
</summary> */
public class HEMA_Series : TSeries
{
public class HEMA_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
@@ -25,8 +24,7 @@ public class HEMA_Series : TSeries
private double _lasthema, _oldhema;
//core constructors
public HEMA_Series(int period, bool useNaN)
{
public HEMA_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"HEMA({period})";
@@ -34,8 +32,7 @@ public class HEMA_Series : TSeries
_len = 0;
_lastema1 = _oldema1 = _lastema2 = _oldema2 = _lasthema = _oldhema = 0;
}
public HEMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public HEMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -51,36 +48,26 @@ public class HEMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (update)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) {
_lastema1 = _oldema1;
_lastema2 = _oldema2;
_lasthema = _oldhema;
}
else
{
} else {
_oldema1 = _lastema1;
_oldema2 = _lastema2;
_oldhema = _lasthema;
}
double _ema1, _ema2, _hema;
if (_period == 0)
{
if (_period == 0) {
_len++;
(_k1, _k2, _k3) = CalculateK(_len);
}
if (double.IsNaN(TValue.v))
{
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, double.NaN), update);
}
else if (this.Count == 0)
{
} else if (this.Count == 0) {
_ema1 = _ema2 = _hema = TValue.v;
}
else
{
} else {
_ema1 = _k1 * (TValue.v - _lastema1) + _lastema1;
_ema2 = _k2 * (TValue.v - _lastema2) + _lastema2;
_hema = _k3 * (((2 * _ema1) - _ema2) - _lasthema) + _lasthema;
@@ -94,35 +81,29 @@ public class HEMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_lastema1 = _lastema2 = _lasthema = 0;
_oldema1 = _oldema2 = _oldhema = 0;
_len = 0;
}
public static (double k1, double k2, double k3) CalculateK(int len)
{
public static (double k1, double k2, double k3) CalculateK(int len) {
double k1 = 8 / (double)(len + 7);
double k2 = 3 / (double)(len + 2);
double k3 = 2 / Math.Sqrt(len + 3);
+10 -20
View File
@@ -18,16 +18,14 @@ HMA = WMA(sqrt(n)) of Raw HMA
</summary> */
public class HMA_Series : TSeries
{
public class HMA_Series : TSeries {
protected int _period, _period2, _psqrt;
protected readonly bool _NaN;
protected readonly TSeries _data;
protected WMA_Series _wma1, _wma2, _wma3;
//core constructors
public HMA_Series(int period, bool useNaN)
{
public HMA_Series(int period, bool useNaN) {
_period = period;
_period2 = period / 2;
_psqrt = (int)Math.Sqrt(period);
@@ -37,8 +35,7 @@ public class HMA_Series : TSeries
_wma3 = new(Math.Max(_psqrt, 1), useNaN);
Name = $"HMA({period})";
}
public HMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public HMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -54,10 +51,8 @@ public class HMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (_period == 0)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (_period == 0) {
_wma1.Len = this.Count / 2;
_wma2.Len = this.Count;
_wma1.Len = (int)Math.Sqrt(this.Count);
@@ -69,28 +64,23 @@ public class HMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_wma1.Reset();
_wma2.Reset();
_wma3.Reset();
+14 -29
View File
@@ -31,8 +31,7 @@ HWMA[i] = F[i] + V[i] + 0.5 * A[i]
</summary> */
public class HWMA_Series : TSeries
{
public class HWMA_Series : TSeries {
private int _len;
protected readonly int _period;
protected readonly bool _NaN;
@@ -43,8 +42,7 @@ public class HWMA_Series : TSeries
//core constructors
public HWMA_Series(double nA, double nB, double nC, bool useNaN)
{
public HWMA_Series(double nA, double nB, double nC, bool useNaN) {
_period = (int)((2 - nA) / nA);
_nA = nA;
_nB = nB;
@@ -53,8 +51,7 @@ public class HWMA_Series : TSeries
Name = $"HWMA({_period})";
_len = 0;
}
public HWMA_Series(TSeries source, double nA, double nB, double nC, bool useNaN = false) : this(nA, nB, nC, useNaN)
{
public HWMA_Series(TSeries source, double nA, double nB, double nC, bool useNaN = false) : this(nA, nB, nC, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -62,8 +59,7 @@ public class HWMA_Series : TSeries
}
public HWMA_Series() : this(period: 0, useNaN: false) { }
public HWMA_Series(int period) : this(period, useNaN: false) { }
public HWMA_Series(int period, bool useNaN) : this(nA: 2 / (1 + (double)period), nB: 1 / (double)period, nC: 1 / (double)period, useNaN)
{
public HWMA_Series(int period, bool useNaN) : this(nA: 2 / (1 + (double)period), nB: 1 / (double)period, nC: 1 / (double)period, useNaN) {
_period = period;
}
public HWMA_Series(TBars source) : this(source.Close, period: 0, useNaN: false) { }
@@ -74,32 +70,26 @@ public class HWMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
double _F, _V, _A;
if (_len == 0) { _pF = TValue.v; _pA = _pV = 0; }
if (update) { _pF = _ppF; _pV = _ppV; _pA = _ppA; }
else
{
if (update) { _pF = _ppF; _pV = _ppV; _pA = _ppA; } else {
_ppF = _pF;
_ppV = _pV;
_ppA = _pA;
_len++;
}
if (_period == 0)
{
if (_period == 0) {
_nA = 2 / (1 + (double)_len);
_nB = 1 / (double)_len;
_nC = 1 / (double)_len;
}
if (_period == 1)
{
if (_period == 1) {
_nA = 1;
_nB = 0;
_nC = 0;
@@ -119,28 +109,23 @@ public class HWMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
}
}
+14 -29
View File
@@ -21,8 +21,7 @@ Issues:
</summary> */
public class JMA_Series : TSeries
{
public class JMA_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
@@ -35,8 +34,7 @@ public class JMA_Series : TSeries
private readonly int _voltyS, _voltyL;
//core constructors
public JMA_Series(int period, double phase, int vshort, int vlong, bool useNaN)
{
public JMA_Series(int period, double phase, int vshort, int vlong, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"JMA({period})";
@@ -48,8 +46,7 @@ public class JMA_Series : TSeries
_voltyL = vlong;
}
public JMA_Series(TSeries source, int period, double phase, int vshort, int vlong, bool useNaN) : this(period, phase, vshort, vlong, useNaN)
{
public JMA_Series(TSeries source, int period, double phase, int vshort, int vlong, bool useNaN) : this(period, phase, vshort, vlong, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -66,11 +63,9 @@ public class JMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (this.Count == 0) { prev_ma1 = prev_jma = TValue.v; }
if (update)
{
if (update) {
upperBand = p_upperBand;
lowerBand = p_lowerBand;
Kv = p_Kv;
@@ -79,9 +74,7 @@ public class JMA_Series : TSeries
prev_det0 = p_prev_det0;
prev_det1 = p_prev_det1;
prev_jma = p_prev_jma;
}
else
{
} else {
p_upperBand = upperBand;
p_lowerBand = lowerBand;
p_Kv = Kv;
@@ -92,8 +85,7 @@ public class JMA_Series : TSeries
p_prev_jma = prev_jma;
}
if (double.IsNaN(TValue.v))
{
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, double.NaN), update);
}
@@ -107,13 +99,11 @@ public class JMA_Series : TSeries
Math.Abs(0.5 * (del1 + del2)));
//// from volty to avolty
if (update) { volty_short[volty_short.Count - 1] = volty; }
else { volty_short.Add(volty); }
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 (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]; }
@@ -149,28 +139,23 @@ public class JMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
upperBand = lowerBand = prev_ma1 = prev_det0 = prev_det1 = prev_vsum = prev_jma = Kv = 0.0;
}
}
+12 -25
View File
@@ -24,8 +24,7 @@ Remark:
</summary> */
public class KAMA_Series : TSeries
{
public class KAMA_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
private double _lastkama, _lastlastkama;
private readonly double _scFast, _scSlow;
@@ -34,8 +33,7 @@ public class KAMA_Series : TSeries
protected readonly TSeries _data;
//core constructors
public KAMA_Series(int period, int fast, int slow, bool useNaN)
{
public KAMA_Series(int period, int fast, int slow, bool useNaN) {
_period = period;
_NaN = useNaN;
_scFast = 2.0 / (((period < fast) ? period : fast) + 1);
@@ -43,8 +41,7 @@ public class KAMA_Series : TSeries
_lastkama = _lastlastkama = 0;
Name = $"KAMA({period})";
}
public KAMA_Series(TSeries source, int period, int fast, int slow, bool useNaN) : this(period, fast, slow, useNaN)
{
public KAMA_Series(TSeries source, int period, int fast, int slow, bool useNaN) : this(period, fast, slow, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -63,21 +60,16 @@ public class KAMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
if (update) { _lastkama = _lastlastkama; }
else { _lastlastkama = _lastkama; }
if (update) { _lastkama = _lastlastkama; } else { _lastlastkama = _lastkama; }
BufferTrim(buffer: _buffer, value: TValue.v, period: _period + 1, update: update);
double _kama = 0;
if (this.Count < _period) { _kama = TValue.v; }
else
{
if (this.Count < _period) { _kama = TValue.v; } else {
double _change = Math.Abs(_buffer[^1] - _buffer[(_buffer.Count > _period + 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]); }
@@ -90,28 +82,23 @@ public class KAMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
_lastkama = _lastlastkama = 0;
}
@@ -25,22 +25,19 @@ Sources:
</summary> */
public class KURTOSIS_Series : TSeries
{
public class KURTOSIS_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
private readonly System.Collections.Generic.List<double> _buffer = new();
//core constructors
public KURTOSIS_Series(int period, bool useNaN)
{
public KURTOSIS_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"KURTOSIS({period})";
}
public KURTOSIS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public KURTOSIS_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -53,10 +50,8 @@ public class KURTOSIS_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
@@ -66,8 +61,7 @@ public class KURTOSIS_Series : TSeries
double _s2 = 0;
double _s4 = 0;
for (int i = 0; i < this._buffer.Count; i++)
{
for (int i = 0; i < this._buffer.Count; i++) {
_s2 += (_buffer[i] - _avg) * (_buffer[i] - _avg);
_s4 += (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg) * (_buffer[i] - _avg);
}
@@ -80,28 +74,23 @@ public class KURTOSIS_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+10 -20
View File
@@ -11,8 +11,7 @@ MACD: Moving Average Convergence/Divergence
</summary> */
public class MACD_Series : TSeries
{
public class MACD_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _slow, _fast, _signal;
@@ -23,8 +22,7 @@ public class MACD_Series : TSeries
public EMA_Series Signal { get; }
//core constructors
public MACD_Series(int slow = 26, int fast = 12, int signal = 9, bool useNaN = false)
{
public MACD_Series(int slow = 26, int fast = 12, int signal = 9, bool useNaN = false) {
_slow = slow;
_fast = fast;
_signal = signal;
@@ -34,8 +32,7 @@ public class MACD_Series : TSeries
_TFast = new(fast, useNaN: false, useSMA: true);
Signal = new(signal, useNaN: false, useSMA: true);
}
public MACD_Series(TSeries source, int slow, int fast, int signal, bool useNaN) : this(slow, fast, signal, useNaN)
{
public MACD_Series(TSeries source, int slow, int fast, int signal, bool useNaN) : this(slow, fast, signal, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -46,10 +43,8 @@ public class MACD_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
@@ -61,28 +56,23 @@ public class MACD_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -17,22 +17,19 @@ Sources:
</summary> */
public class MAD_Series : TSeries
{
public class MAD_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MAD_Series(int period, bool useNaN)
{
public MAD_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MAD({period})";
}
public MAD_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MAD_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -48,8 +45,7 @@ public class MAD_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -61,28 +57,23 @@ public class MAD_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -14,22 +14,19 @@ Sources:
</summary> */
public class MAE_Series : TSeries
{
public class MAE_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MAE_Series(int period, bool useNaN)
{
public MAE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MSE({period})";
}
public MAE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MAE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -45,8 +42,7 @@ public class MAE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -59,28 +55,23 @@ public class MAE_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+18 -38
View File
@@ -17,8 +17,7 @@ Sources:
</summary> */
public class MAMA_Series : TSeries
{
public class MAMA_Series : TSeries {
private int _len;
protected readonly int _period;
protected readonly bool _NaN;
@@ -33,8 +32,7 @@ public class MAMA_Series : TSeries
//core constructors
public MAMA_Series(double fastlimit, double slowlimit, bool useNaN)
{
public MAMA_Series(double fastlimit, double slowlimit, bool useNaN) {
_period = (int)(2 / fastlimit) - 1;
fastl = fastlimit;
slowl = slowlimit;
@@ -43,8 +41,7 @@ public class MAMA_Series : TSeries
Name = $"MAMA({_period})";
_len = 0;
}
public MAMA_Series(TSeries source, double fastlimit, double slowlimit, bool useNaN = false) : this(fastlimit, slowlimit, useNaN)
{
public MAMA_Series(TSeries source, double fastlimit, double slowlimit, bool useNaN = false) : this(fastlimit, slowlimit, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -52,8 +49,7 @@ public class MAMA_Series : TSeries
}
public MAMA_Series() : this(period: 0, useNaN: false) { }
public MAMA_Series(int period) : this(period, useNaN: false) { }
public MAMA_Series(int period, bool useNaN) : this(fastlimit: 2 / (period + 1), slowlimit: 0.2 / (period + 1), useNaN)
{
public MAMA_Series(int period, bool useNaN) : this(fastlimit: 2 / (period + 1), slowlimit: 0.2 / (period + 1), useNaN) {
_period = period;
}
public MAMA_Series(TBars source) : this(source.Close, period: 0, useNaN: false) { }
@@ -65,14 +61,11 @@ public class MAMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
if (!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;
@@ -87,20 +80,17 @@ public class MAMA_Series : TSeries
fama.i1 = fama.i;
_len++;
}
if (_period == 0)
{
if (_period == 0) {
fastl = 2 / (double)_len;
slowl = fastl * 0.1;
}
if (_period == 1)
{
if (_period == 1) {
fastl = 1;
slowl = 1;
}
var i = _len - 1;
pr.i = TValue.v;
if (i > 5)
{
if (i > 5) {
var adj = 0.075 * pd.i1 + 0.54;
// smooth and detrender
@@ -153,19 +143,14 @@ public class MAMA_Series : TSeries
// final indicators
mama.i = alpha * (pr.i - mama.i1) + mama.i1;
fama.i = 0.5d * alpha * (mama.i - fama.i1) + fama.i1;
}
else
{
} 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);
if (_len == 1)
{
if (_len == 1) {
mamaseed = famaseed = TValue.v;
}
else
{
} else {
mamaseed = fastl * (TValue.v - mamaseed) + mamaseed;
famaseed = slowl * (TValue.v - famaseed) + famaseed;
}
@@ -180,28 +165,23 @@ public class MAMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
}
}
+10 -20
View File
@@ -20,22 +20,19 @@ Remark:
</summary> */
public class MAPE_Series : TSeries
{
public class MAPE_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MAPE_Series(int period, bool useNaN)
{
public MAPE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MAPE({period})";
}
public MAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -51,15 +48,13 @@ public class MAPE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
double _mape = 0;
for (int i = 0; i < _buffer.Count; i++)
{
for (int i = 0; i < _buffer.Count; i++) {
_mape += (_buffer[i] != 0) ? Math.Abs(_buffer[i] - _sma) / Math.Abs(_buffer[i]) : double.PositiveInfinity;
}
_mape /= (_buffer.Count > 0) ? _buffer.Count : 1;
@@ -68,28 +63,23 @@ public class MAPE_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -10,22 +10,19 @@ MAX - Maximum value in the given period in the series.
</summary> */
public class MAX_Series : TSeries
{
public class MAX_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MAX_Series(int period, bool useNaN)
{
public MAX_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MAX({period})";
}
public MAX_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MAX_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -41,8 +38,7 @@ public class MAX_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _max = _buffer.Max();
@@ -50,28 +46,23 @@ public class MAX_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -23,22 +23,19 @@ Sources:
</summary> */
public class MEDIAN_Series : TSeries
{
public class MEDIAN_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MEDIAN_Series(int period, bool useNaN)
{
public MEDIAN_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MEDIAN({period})";
}
public MEDIAN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MEDIAN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -54,8 +51,7 @@ public class MEDIAN_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
System.Collections.Generic.List<double> _s = new(this._buffer);
@@ -68,28 +64,23 @@ public class MEDIAN_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
@@ -13,22 +13,19 @@ Sources:
</summary> */
public class MIDPOINT_Series : TSeries
{
public class MIDPOINT_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MIDPOINT_Series(int period, bool useNaN)
{
public MIDPOINT_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MIDPOINT({period})";
}
public MIDPOINT_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MIDPOINT_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -44,8 +41,7 @@ public class MIDPOINT_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _max = _buffer.Max();
@@ -54,28 +50,23 @@ public class MIDPOINT_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
@@ -9,8 +9,7 @@ MIDPRICE: Midpoint price (highhest high + lowest low)/2 in the given period in t
</summary> */
public class MIDPRICE_Series : TSeries
{
public class MIDPRICE_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TBars _data;
@@ -18,14 +17,12 @@ public class MIDPRICE_Series : TSeries
private readonly System.Collections.Generic.List<double> _bufferlo = new();
//core constructors
public MIDPRICE_Series(int period, bool useNaN)
{
public MIDPRICE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MIDPRICE({period})";
}
public MIDPRICE_Series(TBars source, int period, bool useNaN) : this(period, useNaN)
{
public MIDPRICE_Series(TBars source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -38,8 +35,7 @@ public class MIDPRICE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
BufferTrim(_bufferhi, TBar.h, _period, update);
BufferTrim(_bufferlo, TBar.l, _period, update);
double _mid = (_bufferhi.Max() + _bufferlo.Min()) * 0.5;
@@ -48,26 +44,21 @@ public class MIDPRICE_Series : TSeries
return base.Add(res, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_bufferhi.Clear();
_bufferlo.Clear();
}
+9 -18
View File
@@ -10,22 +10,19 @@ MIN - Minimum value in the given period in the series.
</summary> */
public class MIN_Series : TSeries
{
public class MIN_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MIN_Series(int period, bool useNaN)
{
public MIN_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MAX({period})";
}
public MIN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MIN_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -41,8 +38,7 @@ public class MIN_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _max = _buffer.Min();
@@ -50,28 +46,23 @@ public class MIN_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -13,22 +13,19 @@ Sources:
</summary> */
public class MSE_Series : TSeries
{
public class MSE_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public MSE_Series(int period, bool useNaN)
{
public MSE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"MSE({period})";
}
public MSE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public MSE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -44,8 +41,7 @@ public class MSE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -58,28 +54,23 @@ public class MSE_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+10 -20
View File
@@ -26,8 +26,7 @@ Note:
</summary> */
public class OBV_Series : TSeries
{
public class OBV_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TBars _data;
@@ -35,16 +34,14 @@ public class OBV_Series : TSeries
private double _lastclose, _lastlastclose;
//core constructors
public OBV_Series(int period, bool useNaN)
{
public OBV_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"OBV({period})";
this._lastobv = this._lastlastobv = 0;
this._lastclose = this._lastlastclose = 0;
}
public OBV_Series(TBars source, int period, bool useNaN) : this(period, useNaN)
{
public OBV_Series(TBars source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -57,11 +54,9 @@ public class OBV_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update)
{
if (update) {
this._lastobv = this._lastlastobv;
this._lastclose = this._lastlastclose;
}
@@ -80,26 +75,21 @@ public class OBV_Series : TSeries
return base.Add(res, update);
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
this._lastobv = this._lastlastobv = 0;
this._lastclose = this._lastlastclose = 0;
}
+16 -35
View File
@@ -20,8 +20,7 @@ Issues:
</summary> */
public class RMA_Series : TSeries
{
public class RMA_Series : TSeries {
private double _k;
private double _lastrma, _oldrma;
private double _sum, _oldsum;
@@ -32,8 +31,7 @@ public class RMA_Series : TSeries
protected readonly TSeries _data;
//core constructor
public RMA_Series(int period, bool useNaN, bool useSMA)
{
public RMA_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
_useSMA = useSMA;
@@ -51,8 +49,7 @@ public class RMA_Series : TSeries
public RMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { }
public RMA_Series(TSeries source, int period) : this(source, period, false, true) { }
public RMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { }
public RMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public RMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -60,42 +57,31 @@ public class RMA_Series : TSeries
}
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (update)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) {
_lastrma = _oldrma;
_sum = _oldsum;
}
else
{
} else {
_oldrma = _lastrma;
_oldsum = _sum;
_len++;
}
double _rma = 0;
if (_period == 0)
{
if (_period == 0) {
_k = 1.0 / (double)(this._len);
}
if (Count == 0)
{
if (Count == 0) {
_rma = _sum = TValue.v;
}
else if (_len <= _period && _useSMA && _period != 0)
{
} else if (_len <= _period && _useSMA && _period != 0) {
_sum += TValue.v;
if (_period != 0 && _len > _period)
{
if (_period != 0 && _len > _period) {
_sum -= _data[Count - _period - (update ? 1 : 0)].v;
}
_rma = _sum / Math.Min(_len, _period);
}
else
{
} else {
_rma = _k * (TValue.v - _lastrma) + _lastrma;
}
@@ -105,28 +91,23 @@ public class RMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_sum = _oldsum = _lastrma = _oldrma = 0;
_len = 0;
}
+15 -31
View File
@@ -15,8 +15,7 @@ Sources:
</summary> */
public class RSI_Series : TSeries
{
public class RSI_Series : TSeries {
private readonly System.Collections.Generic.List<double> _gain = new();
private readonly System.Collections.Generic.List<double> _loss = new();
protected readonly int _period;
@@ -27,15 +26,13 @@ public class RSI_Series : TSeries
private int i;
//core constructors
public RSI_Series(int period, bool useNaN)
{
public RSI_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"RSI({period})";
i = 0;
}
public RSI_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public RSI_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -51,18 +48,14 @@ public class RSI_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
double _rsi = 0;
if (update)
{
if (update) {
_lastValue = _lastValue_o;
_avgGain = _avgGain_o;
_avgLoss = _avgLoss_o;
}
else
{
} else {
_lastValue_o = _lastValue;
_avgGain_o = _avgGain;
_avgLoss_o = _avgLoss;
@@ -77,20 +70,16 @@ public class RSI_Series : TSeries
_lastValue = TValue.v;
// calculate RSI
if (i > _period && _period != 0)
{
if (i > _period && _period != 0) {
_avgGain = ((_avgGain * (_period - 1)) + _gain[^1]) / _period;
_avgLoss = ((_avgLoss * (_period - 1)) + _loss[^1]) / _period;
if (_avgLoss > 0)
{
if (_avgLoss > 0) {
double rs = _avgGain / _avgLoss;
_rsi = 100 - (100 / (1 + rs));
}
else { _rsi = 100; }
} else { _rsi = 100; }
}
// initialize average gain
else
{
else {
double _sumGain = 0;
for (int p = 0; p < _gain.Count; p++) { _sumGain += _gain[p]; }
double _sumLoss = 0;
@@ -107,28 +96,23 @@ public class RSI_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
i = 0;
}
}
+9 -18
View File
@@ -18,22 +18,19 @@ Remark:
</summary> */
public class SDEV_Series : TSeries
{
public class SDEV_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public SDEV_Series(int period, bool useNaN)
{
public SDEV_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"SDEV({period})";
}
public SDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -49,8 +46,7 @@ public class SDEV_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -64,28 +60,23 @@ public class SDEV_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+8 -16
View File
@@ -22,8 +22,7 @@ Sources:
</summary> */
public class SLOPE_Series : TSeries
{
public class SLOPE_Series : TSeries {
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
@@ -35,14 +34,12 @@ public class SLOPE_Series : TSeries
public TSeries RSquared => p_RSquared;
public TSeries StdDev => p_StdDev;
//core constructors
public SLOPE_Series(int period, bool useNaN)
{
public SLOPE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"SLOPE({period})";
}
public SLOPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SLOPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -58,8 +55,7 @@ public class SLOPE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
int _len = this._buffer.Count;
@@ -68,8 +64,7 @@ public class SLOPE_Series : TSeries
double sumX = 0;
double sumY = 0;
for (int p = 0; p < _len; p++)
{
for (int p = 0; p < _len; p++) {
sumX += this.Count - _len + 2 + p;
sumY += _buffer[p];
}
@@ -81,8 +76,7 @@ public class SLOPE_Series : TSeries
double sumSqY = 0;
double sumSqXY = 0;
for (int p = 0; p < _len; p++)
{
for (int p = 0; p < _len; p++) {
double devX = this.Count - _len + 2 + p - avgX;
double devY = _buffer[p] - avgY;
@@ -115,16 +109,14 @@ public class SLOPE_Series : TSeries
return base.Add(ret, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -13,22 +13,19 @@ Sources:
</summary> */
public class SMAPE_Series : TSeries
{
public class SMAPE_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public SMAPE_Series(int period, bool useNaN)
{
public SMAPE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"SMAPE({period})";
}
public SMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -44,8 +41,7 @@ public class SMAPE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -57,28 +53,23 @@ public class SMAPE_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+14 -30
View File
@@ -16,8 +16,7 @@ Remark:
implementation, but it does allow incremental additions of inputs and real-time calculations of SMA()
</summary> */
public class SMA_Series : TSeries
{
public class SMA_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
private double _sum, _oldsum;
@@ -26,15 +25,13 @@ public class SMA_Series : TSeries
protected readonly bool _NaN;
//core constructor
public SMA_Series(int period, bool useNaN)
{
public SMA_Series(int period, bool useNaN) {
_period = Math.Max(0, period);
_NaN = useNaN;
Name = $"SMA({period})";
_sum = _oldsum = 0;
}
public SMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -50,29 +47,21 @@ public class SMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return (TValue.t, double.NaN);
}
else
{
if (update && _buffer.Count > 0)
{
} else {
if (update && _buffer.Count > 0) {
_sum -= _buffer[^1];
_buffer[^1] = TValue.v;
_oldsum = _sum;
}
else
{
} else {
_buffer.Add(TValue.v);
_oldsum = _sum;
}
_sum += TValue.v;
if (_period != 0 && _buffer.Count > _period)
{
if (_period != 0 && _buffer.Count > _period) {
_sum -= _buffer[0];
_buffer.RemoveAt(0);
}
@@ -83,29 +72,24 @@ public class SMA_Series : TSeries
var res = (TValue.t, Count < _period - 1 && _NaN ? double.NaN : _sma);
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_sum = _oldsum = 0;
_buffer.Clear();
}
+12 -25
View File
@@ -18,8 +18,7 @@ Sources:
</summary> */
public class SMMA_Series : TSeries
{
public class SMMA_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
@@ -28,14 +27,12 @@ public class SMMA_Series : TSeries
private double _lastsmma, _lastlastsmma;
//core constructors
public SMMA_Series(int period, bool useNaN)
{
public SMMA_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"SMMA({period})";
}
public SMMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SMMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -51,23 +48,18 @@ public class SMMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, double.NaN), update);
}
double _smma = 0;
if (update) { this._lastsmma = this._lastlastsmma; }
if (this.Count < this._period)
{
if (this.Count < this._period) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
_smma = _buffer.Average();
}
else
{
} else {
_smma = ((_lastsmma * (_period - 1)) + TValue.v) / _period;
}
@@ -77,28 +69,23 @@ public class SMMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
this._lastsmma = this._lastlastsmma = 0;
}
+9 -18
View File
@@ -18,22 +18,19 @@ Remark:
</summary> */
public class SSDEV_Series : TSeries
{
public class SSDEV_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public SSDEV_Series(int period, bool useNaN)
{
public SSDEV_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"SSDEV({period})";
}
public SSDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SSDEV_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -49,8 +46,7 @@ public class SSDEV_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -64,28 +60,23 @@ public class SSDEV_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+9 -18
View File
@@ -18,22 +18,19 @@ Remark:
</summary> */
public class SVAR_Series : TSeries
{
public class SVAR_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public SVAR_Series(int period, bool useNaN)
{
public SVAR_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"SVAR({period})";
}
public SVAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public SVAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -49,8 +46,7 @@ public class SVAR_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -63,28 +59,23 @@ public class SVAR_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+13 -27
View File
@@ -14,8 +14,7 @@ Sources:
http://www.binarytribune.com/forex-trading-indicators/t3-moving-average-indicator/
</summary> */
public class T3_Series : TSeries
{
public class T3_Series : TSeries {
private readonly double _k, _k1m, _c1, _c2, _c3, _c4;
private readonly System.Collections.Generic.List<double> _buffer1 = new();
private readonly System.Collections.Generic.List<double> _buffer2 = new();
@@ -32,8 +31,7 @@ public class T3_Series : TSeries
protected readonly TSeries _data;
//core constructors
public T3_Series(int period, double vfactor, bool useSMA, bool useNaN)
{
public T3_Series(int period, double vfactor, bool useSMA, bool useNaN) {
_period = period;
_len = 0;
_NaN = useNaN;
@@ -49,8 +47,7 @@ public class T3_Series : TSeries
_k1m = 1.0 - _k;
_lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0;
}
public T3_Series(TSeries source, int period, double vfactor, bool useSMA, bool useNaN) : this(period, vfactor, useSMA, useNaN)
{
public T3_Series(TSeries source, int period, double vfactor, bool useSMA, bool useNaN) : this(period, vfactor, useSMA, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -71,22 +68,18 @@ public class T3_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
double _ema1, _ema2, _ema3, _ema4, _ema5, _ema6;
if (double.IsNaN(TValue.v))
{
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
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 (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 (_len == 0) { _lastema1 = _lastema2 = _lastema3 = _lastema4 = _lastema5 = _lastema6 = TValue.v; }
if ((_len < _period) && _useSMA)
{
if ((_len < _period) && _useSMA) {
BufferTrim(_buffer1, TValue.v, _period, update);
_ema1 = 0;
for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; }
@@ -116,9 +109,7 @@ public class T3_Series : TSeries
_ema6 = 0;
for (int i = 0; i < _buffer6.Count; i++) { _ema6 += _buffer6[i]; }
_ema6 /= _buffer6.Count;
}
else
{
} 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);
@@ -139,28 +130,23 @@ public class T3_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = _lastema4 = _llastema4 = _lastema5 = _llastema5 = _lastema5 = _llastema5 = 0;
_buffer1.Clear();
_buffer2.Clear();
+16 -33
View File
@@ -10,8 +10,7 @@ TBars class - includes all series for common data used in indicators and other c
</summary> */
public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)>
{
public class TBars : System.Collections.Generic.List<(DateTime t, double o, double h, double l, double c, double v)> {
public string Name { get; set; }
private readonly TSeries _open = new("open");
private readonly TSeries _high = new("high");
@@ -39,23 +38,19 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
public TBars() { }
public TBars(string Name)
{
public TBars(string Name) {
this.Name = Name;
}
public (DateTime t, double o, double h, double l, double c, double v) Last => this[^1];
public TBars Tail(int count = 10)
{
public TBars Tail(int count = 10) {
TBars outBars = new();
if (count > this.Count) { count = this.Count; }
for (int i = this.Count - count; i < this.Count; i++) { outBars.Add(this[i]); }
return outBars;
}
public TSeries Select(int source)
{
return source switch
{
public TSeries Select(int source) {
return source switch {
0 => _open,
1 => _high,
2 => _low,
@@ -68,10 +63,8 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
_ => _hlcc4,
};
}
public static string SelectStr(int source)
{
return source switch
{
public static string SelectStr(int source) {
return source switch {
0 => "Open",
1 => "High",
2 => "Low",
@@ -94,8 +87,7 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
public virtual (DateTime t, double v) Add(DateTime t, double o, double h, double l, double c, double v, bool update = false) =>
this.Add((t, o, h, l, c, v), update);
public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update) { this[^1] = TBar; } else { base.Add(TBar); }
_open.Add((TBar.t, TBar.o), update);
@@ -116,38 +108,29 @@ public class TBars : System.Collections.Generic.List<(DateTime t, double o, doub
public delegate void NewDataEventHandler(object source, TSeriesEventArgs args);
public event NewDataEventHandler Pub;
protected virtual void OnEvent(bool update = false)
{
if (Pub != null && Pub.Target != this)
{
protected virtual void OnEvent(bool update = false) {
if (Pub != null && Pub.Target != this) {
Pub(this, new TSeriesEventArgs { update = update });
}
}
public void Sub(object source, TSeriesEventArgs e)
{
TBars ss = (TBars)source; if (ss.Count > 1)
{
public void Sub(object source, TSeriesEventArgs e) {
TBars ss = (TBars)source; if (ss.Count > 1) {
for (int i = 0; i < ss.Count; i++) { this.Add(ss[i]); }
}
else
{
} else {
this.Add(ss[^1], e.update);
}
}
/// common helpers
public static void BufferTrim(System.Collections.Generic.List<double> buffer, double value, int period, bool update)
{
if (!update)
{
public static void BufferTrim(System.Collections.Generic.List<double> buffer, double value, int period, bool update) {
if (!update) {
buffer.Add(value);
if (buffer.Count > period && period > 0) { buffer.RemoveAt(0); }
return;
}
buffer[^1] = value;
}
public virtual void Reset()
{
public virtual void Reset() {
}
}
+14 -31
View File
@@ -18,8 +18,7 @@ Remark:
</summary> */
public class TEMA_Series : TSeries
{
public class TEMA_Series : TSeries {
private double _k;
private double _sum, _oldsum;
private double _lastema1, _oldema1, _lastema2, _oldema2, _lastema3, _oldema3;
@@ -30,8 +29,7 @@ public class TEMA_Series : TSeries
protected readonly TSeries _data;
//core constructor
public TEMA_Series(int period, bool useNaN, bool useSMA)
{
public TEMA_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
_useSMA = useSMA;
@@ -47,8 +45,7 @@ public class TEMA_Series : TSeries
public TEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { }
public TEMA_Series(TSeries source, int period) : this(source, period, false, true) { }
public TEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { }
public TEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public TEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -56,17 +53,13 @@ public class TEMA_Series : TSeries
}
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (update)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) {
_lastema1 = _oldema1;
_lastema2 = _oldema2;
_lastema3 = _oldema3;
_sum = _oldsum;
}
else
{
} else {
_oldema1 = _lastema1;
_oldema2 = _lastema2;
_oldema3 = _lastema3;
@@ -77,19 +70,14 @@ public class TEMA_Series : TSeries
if (_period == 0) { _k = 2.0 / (_len + 1); }
double _ema1, _ema2, _ema3, _tema;
if (this.Count == 0)
{
if (this.Count == 0) {
_ema1 = _ema2 = _ema3 = _sum = TValue.v;
}
else if (_len <= _period && _useSMA && _period != 0)
{
} else if (_len <= _period && _useSMA && _period != 0) {
_sum += TValue.v;
_ema1 = _sum / Math.Min(_len, _period);
_ema2 = _ema1;
_ema3 = _ema2;
}
else
{
} else {
_ema1 = (TValue.v - _lastema1) * _k + _lastema1;
_ema2 = (_ema1 - _lastema2) * _k + _lastema2;
_ema3 = (_ema2 - _lastema3) * _k + _lastema3;
@@ -106,28 +94,23 @@ public class TEMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_sum = _oldsum = _lastema1 = _lastema2 = 0;
_len = 0;
}
+10 -20
View File
@@ -15,8 +15,7 @@ Remark:
</summary> */
public class TRIMA_Series : TSeries
{
public class TRIMA_Series : TSeries {
private readonly int _p1a, _p1b;
private readonly SMA_Series sma, trima;
protected readonly int _period;
@@ -24,8 +23,7 @@ public class TRIMA_Series : TSeries
protected readonly TSeries _data;
//core constructors
public TRIMA_Series(int period, bool useNaN)
{
public TRIMA_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"xMA({period})";
@@ -35,8 +33,7 @@ public class TRIMA_Series : TSeries
trima = new(_p1b);
}
public TRIMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public TRIMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -52,10 +49,8 @@ public class TRIMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
@@ -66,28 +61,23 @@ public class TRIMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
sma.Reset();
trima.Reset();
}
+13 -28
View File
@@ -14,8 +14,7 @@ Sources:
</summary> */
public class TRIX_Series : TSeries
{
public class TRIX_Series : TSeries {
private readonly double _k;
private readonly System.Collections.Generic.List<double> _buffer1 = new();
private readonly System.Collections.Generic.List<double> _buffer2 = new();
@@ -30,8 +29,7 @@ public class TRIX_Series : TSeries
//core constructors
public TRIX_Series(int period, bool useNaN, bool useSMA)
{
public TRIX_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
_useSMA = useSMA;
@@ -40,8 +38,7 @@ public class TRIX_Series : TSeries
_len = 0;
_lastema1 = _llastema1 = _lastema2 = _llastema2 = _lastema3 = _llastema3 = 0;
}
public TRIX_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public TRIX_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -58,22 +55,17 @@ public class TRIX_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (double.IsNaN(TValue.v))
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (double.IsNaN(TValue.v)) {
return base.Add((TValue.t, Double.NaN), update);
}
if (_len == 0) { _lastema1 = _lastema2 = _lastema3 = TValue.v; }
if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; }
else
{
if (update) { _lastema1 = _llastema1; _lastema2 = _llastema2; _lastema3 = _llastema3; } else {
_llastema1 = _lastema1; _llastema2 = _lastema2; _llastema3 = _lastema3; _len++;
}
double _ema1, _ema2, _ema3;
if ((this.Count < _period) && _useSMA)
{
if ((this.Count < _period) && _useSMA) {
BufferTrim(_buffer1, TValue.v, _period, update);
_ema1 = 0;
for (int i = 0; i < _buffer1.Count; i++) { _ema1 += _buffer1[i]; }
@@ -88,9 +80,7 @@ public class TRIX_Series : TSeries
_ema3 = 0;
for (int i = 0; i < _buffer3.Count; i++) { _ema3 += _buffer3[i]; }
_ema3 /= _buffer3.Count;
}
else
{
} else {
_ema1 = (TValue.v - _lastema1) * _k + _lastema1;
_ema2 = (_ema1 - _lastema2) * _k + _lastema2;
_ema3 = (_ema2 - _lastema3) * _k + _lastema3;
@@ -105,28 +95,23 @@ public class TRIX_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
}
}
+12 -25
View File
@@ -18,19 +18,16 @@ Sources:
</summary> */
public class TR_Series : TSeries
{
public class TR_Series : TSeries {
protected readonly TBars _data;
private double _cm1, _cm1_o;
//core constructors
public TR_Series()
{
public TR_Series() {
Name = $"TR()";
_cm1 = _cm1_o = double.NaN;
}
public TR_Series(TBars source)
{
public TR_Series(TBars source) {
_data = source;
Name = $"TR({(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_cm1 = _cm1_o = double.NaN;
@@ -40,20 +37,15 @@ public class TR_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update)
{
if (update) {
_cm1 = _cm1_o;
}
else
{
} else {
_cm1_o = _cm1;
}
if (_cm1 is double.NaN)
{
if (_cm1 is double.NaN) {
_cm1 = TBar.c;
}
@@ -66,26 +58,21 @@ public class TR_Series : TSeries
}
public new void Add(TBars data)
{
public new void Add(TBars data) {
foreach (var item in data) { Add(item, false); }
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TBar: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TBar: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TBar: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_cm1 = _cm1_o = double.NaN;
}
}
+21 -44
View File
@@ -15,13 +15,11 @@ TSeries is the cornerstone of all QuanTAlib classes.
- includes publishing and subscribing methods that attach to events
</summary> */
public class TSeriesEventArgs : EventArgs
{
public class TSeriesEventArgs : EventArgs {
public bool update { get; set; }
}
public class TSeries : List<(DateTime t, double v)>
{
public class TSeries : List<(DateTime t, double v)> {
private readonly (DateTime t, double v) Default = (DateTime.MinValue, double.NaN);
public IEnumerable<DateTime> t => this.Select(item => item.t);
public IEnumerable<double> v => this.Select(item => item.v);
@@ -31,29 +29,22 @@ public class TSeries : List<(DateTime t, double v)>
public string Name { get; set; }
public int Keep = 0;
public TSeries()
{
public TSeries() {
this.Name = "data";
}
public TSeries(string Name)
{
public TSeries(string Name) {
this.Name = Name;
}
public virtual (DateTime t, double v) Add(double v, bool update = false)
{
public virtual (DateTime t, double v) Add(double v, bool update = false) {
return Add((t: Count == 0 ? DateTime.Today : this[^1].t.AddDays(1), v), update);
}
public virtual (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
if (update)
{
public virtual (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
if (update) {
this[^1] = TValue;
}
else
{
} else {
base.Add(TValue);
}
@@ -61,14 +52,10 @@ public class TSeries : List<(DateTime t, double v)>
return TValue;
}
public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false)
{
if (update)
{
public virtual (DateTime t, double v) Add((DateTime t, double o, double h, double l, double c, double v) TBar, bool update = false) {
if (update) {
this[this.Count - 1] = (TBar.t, TBar.c);
}
else
{
} else {
base.Add((TBar.t, TBar.c));
}
@@ -76,20 +63,17 @@ public class TSeries : List<(DateTime t, double v)>
return (TBar.t, TBar.c);
}
public virtual (DateTime t, double v) Add(TSeries data)
{
public virtual (DateTime t, double v) Add(TSeries data) {
foreach (var item in data) { Add(item); }
return data.Last;
}
public virtual (DateTime t, double v) Add(TBars data)
{
public virtual (DateTime t, double v) Add(TBars data) {
foreach (var item in data) { Add(item.c, false); }
return (data.Last.t, data.Last.c);
}
public void Sub(object source, TSeriesEventArgs e)
{
public void Sub(object source, TSeriesEventArgs e) {
var data = (TSeries)source;
if (data == null) { return; }
foreach (var item in data) { Add(item); }
@@ -99,34 +83,27 @@ public class TSeries : List<(DateTime t, double v)>
public event NewEventHandler Pub;
protected virtual void OnEvent(bool update = false)
{
if (Keep > 0)
{
protected virtual void OnEvent(bool update = false) {
if (Keep > 0) {
TrimToSize(keep: Keep);
}
Pub?.Invoke(this, new TSeriesEventArgs { update = update });
}
/// common helpers
public static void BufferTrim(List<double> buffer, double value, int period, bool update)
{
if (!update)
{
public static void BufferTrim(List<double> buffer, double value, int period, bool update) {
if (!update) {
buffer.Add(value);
if (buffer.Count > period && period > 0) { buffer.RemoveAt(0); }
return;
}
buffer[^1] = value;
}
public virtual void Reset()
{
public virtual void Reset() {
}
public void TrimToSize(int keep)
{
if (keep >= this.Count)
{
public void TrimToSize(int keep) {
if (keep >= this.Count) {
return; // No need to trim if the series is already smaller than or equal to n
}
+9 -18
View File
@@ -18,22 +18,19 @@ Remark:
</summary> */
public class VAR_Series : TSeries
{
public class VAR_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public VAR_Series(int period, bool useNaN)
{
public VAR_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"VAR({period})";
}
public VAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public VAR_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -49,8 +46,7 @@ public class VAR_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -63,28 +59,23 @@ public class VAR_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+10 -20
View File
@@ -15,22 +15,19 @@ Sources:
</summary> */
public class WMAPE_Series : TSeries
{
public class WMAPE_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public WMAPE_Series(int period, bool useNaN)
{
public WMAPE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"WMAPE({period})";
}
public WMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public WMAPE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -46,16 +43,14 @@ public class WMAPE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
double _div = 0;
double _wmape = 0;
for (int i = 0; i < _buffer.Count; i++)
{
for (int i = 0; i < _buffer.Count; i++) {
_wmape += Math.Abs(_buffer[i] - _sma);
_div += Math.Abs(_buffer[i]);
}
@@ -65,28 +60,23 @@ public class WMAPE_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+14 -28
View File
@@ -17,31 +17,27 @@ Sources:
</summary> */
public class WMA_Series : TSeries
{
public class WMA_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
private System.Collections.Generic.List<double> _weights;
protected int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
protected int _len;
public int Len
{
public int Len {
get { return _len; }
set { _len = value; }
}
//core constructors
public WMA_Series(int period, bool useNaN)
{
public WMA_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"WMA({period})";
_len = 1;
_weights = CalculateWeights(_period);
}
public WMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public WMA_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -56,19 +52,16 @@ public class WMA_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
if (_period == 0)
{
if (_period == 0) {
_weights = CalculateWeights(_len);
_len++;
}
double _wma = 0;
double totalWeights = (_buffer.Count * (_buffer.Count + 1)) * 0.5;
object lockObj = new object();
Parallel.For(0, _buffer.Count, i =>
{
Parallel.For(0, _buffer.Count, i => {
double temp = _buffer[i] * this._weights[i];
lock (lockObj) { _wma += temp; }
});
@@ -77,39 +70,32 @@ public class WMA_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//calculating weights
private static List<double> CalculateWeights(int period)
{
private static List<double> CalculateWeights(int period) {
List<double> weights = new List<double>(period);
for (int i = 0; i < period; i++)
{
for (int i = 0; i < period; i++) {
weights.Add(i + 1);
}
return weights;
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_len = 0;
_weights = CalculateWeights(_period);
_buffer.Clear();
+11 -22
View File
@@ -21,8 +21,7 @@ Remark:
</summary> */
public class ZLEMA_Series : TSeries
{
public class ZLEMA_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
private int _len;
protected readonly int _period;
@@ -31,8 +30,7 @@ public class ZLEMA_Series : TSeries
private readonly EMA_Series _ema;
//core constructor
public ZLEMA_Series(int period, bool useNaN, bool useSMA)
{
public ZLEMA_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
Name = $"ZLEMA({period})";
@@ -48,8 +46,7 @@ public class ZLEMA_Series : TSeries
public ZLEMA_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { }
public ZLEMA_Series(TSeries source, int period) : this(source, period, false, true) { }
public ZLEMA_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { }
public ZLEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public ZLEMA_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -57,16 +54,13 @@ public class ZLEMA_Series : TSeries
}
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
int _lag;
if (_period == 0)
{
if (_period == 0) {
_lag = (int)((_len - 1) * 0.5);
_len++;
}
else { _lag = (int)((_period - 1) * 0.5); }
} else { _lag = (int)((_period - 1) * 0.5); }
_lag = Math.Min(_lag, _buffer.Count - 1);
_lag = Math.Max(_lag, 0) + 1;
double _zlValue = 2 * TValue.v - _buffer[^_lag];
@@ -76,29 +70,24 @@ public class ZLEMA_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
_ema.Reset();
}
+11 -22
View File
@@ -17,8 +17,7 @@ Sources:
</summary> */
public class ZL_Series : TSeries
{
public class ZL_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
private int _len;
protected readonly int _period;
@@ -27,8 +26,7 @@ public class ZL_Series : TSeries
private readonly EMA_Series _ema;
//core constructor
public ZL_Series(int period, bool useNaN, bool useSMA)
{
public ZL_Series(int period, bool useNaN, bool useSMA) {
_period = period;
_NaN = useNaN;
Name = $"ZL({period})";
@@ -44,8 +42,7 @@ public class ZL_Series : TSeries
public ZL_Series(TBars source, int period, bool useNaN) : this(source.Close, period, useNaN) { }
public ZL_Series(TSeries source, int period) : this(source, period, false, true) { }
public ZL_Series(TSeries source, int period, bool useNaN) : this(source, period, useNaN, true) { }
public ZL_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA)
{
public ZL_Series(TSeries source, int period, bool useNaN, bool useSMA) : this(period, useNaN, useSMA) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -53,16 +50,13 @@ public class ZL_Series : TSeries
}
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
int _lag;
if (_period == 0)
{
if (_period == 0) {
_lag = (int)((_len - 1) * 0.5);
_len++;
}
else { _lag = (int)((_period - 1) * 0.5); }
} else { _lag = (int)((_period - 1) * 0.5); }
_lag = Math.Min(_lag, _buffer.Count - 1);
_lag = Math.Max(_lag, 0) + 1;
double _zlValue = 2 * TValue.v - _buffer[^_lag];
@@ -72,28 +66,23 @@ public class ZL_Series : TSeries
}
//variation of Add()
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
_ema.Reset();
}
+9 -18
View File
@@ -24,22 +24,19 @@ Calculation:
</summary> */
public class ZSCORE_Series : TSeries
{
public class ZSCORE_Series : TSeries {
private readonly System.Collections.Generic.List<double> _buffer = new();
protected readonly int _period;
protected readonly bool _NaN;
protected readonly TSeries _data;
//core constructors
public ZSCORE_Series(int period, bool useNaN)
{
public ZSCORE_Series(int period, bool useNaN) {
_period = period;
_NaN = useNaN;
Name = $"ZSCORE({period})";
}
public ZSCORE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN)
{
public ZSCORE_Series(TSeries source, int period, bool useNaN) : this(period, useNaN) {
_data = source;
Name = Name.Substring(0, Name.IndexOf(")")) + $", {(string.IsNullOrEmpty(_data.Name) ? "data" : _data.Name)})";
_data.Pub += Sub;
@@ -55,8 +52,7 @@ public class ZSCORE_Series : TSeries
//////////////////
// core Add() algo
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false)
{
public override (DateTime t, double v) Add((DateTime t, double v) TValue, bool update = false) {
BufferTrim(buffer: _buffer, value: TValue.v, period: _period, update: update);
double _sma = _buffer.Average();
@@ -70,28 +66,23 @@ public class ZSCORE_Series : TSeries
return base.Add(res, update);
}
public override (DateTime t, double v) Add(TSeries data)
{
public override (DateTime t, double v) Add(TSeries data) {
if (data == null) { return (DateTime.Today, Double.NaN); }
foreach (var item in data) { Add(item, false); }
return _data.Last;
}
public (DateTime t, double v) Add(bool update)
{
public (DateTime t, double v) Add(bool update) {
return this.Add(TValue: _data.Last, update: update);
}
public (DateTime t, double v) Add()
{
public (DateTime t, double v) Add() {
return Add(TValue: _data.Last, update: false);
}
private new void Sub(object source, TSeriesEventArgs e)
{
private new void Sub(object source, TSeriesEventArgs e) {
Add(TValue: _data.Last, update: e.update);
}
//reset calculation
public override void Reset()
{
public override void Reset() {
_buffer.Clear();
}
}
+14 -28
View File
@@ -4,8 +4,7 @@ using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverage_chart : Indicator
{
public class MovingAverage_chart : Indicator {
#region Parameters
[InputParameter("MA1: Type:", 0, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
@@ -51,28 +50,24 @@ public class MovingAverage_chart : Indicator
///////
public MovingAverage_chart()
{
public MovingAverage_chart() {
this.SeparateWindow = false;
this.Name = "MAs Crossover";
this.AddLineSeries("MA1", Color.LimeGreen, 2, LineStyle.Solid);
this.AddLineSeries("MA2", Color.OrangeRed, 2, LineStyle.Solid);
}
protected override void OnInit()
{
protected override void OnInit() {
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--)
{
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
this.Name = "MAs Cross: [ ";
switch (MA1type)
{
switch (MA1type) {
case 0:
MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMA";
@@ -146,8 +141,7 @@ public class MovingAverage_chart : Indicator
this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : ";
switch (MA2type)
{
switch (MA2type) {
case 0:
MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMA";
@@ -230,8 +224,7 @@ public class MovingAverage_chart : Indicator
trades = new(MA1, MA2);
}
protected override void OnUpdate(UpdateArgs args)
{
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),
@@ -242,35 +235,28 @@ public class MovingAverage_chart : Indicator
this.SetValue(this.MA1[^1].v, lineIndex: 0);
this.SetValue(this.MA2[^1].v, lineIndex: 1);
if (trades[^1].v == 1)
{
if (trades[^1].v == 1) {
this.EndCloud(0, 1, Color.Empty);
if (LongTrades)
{
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Green));
}
if (ShortTrades)
{
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
if (trades[^1].v == -1)
{
if (trades[^1].v == -1) {
this.EndCloud(0, 1, Color.Empty);
if (ShortTrades)
{
if (ShortTrades) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow));
this.BeginCloud(0, 1, Color.FromArgb(127, Color.Red));
}
if (LongTrades)
{
if (LongTrades) {
this.LinesSeries[0].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
}
}
}
public override void OnPaintChart(PaintChartEventArgs args)
{
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) { return; }
Graphics graphics = args.Graphics;
+16 -34
View File
@@ -4,8 +4,7 @@ using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class MovingAverageSlope_chart : Indicator
{
public class MovingAverageSlope_chart : Indicator {
#region Parameters
[InputParameter("MA1: Type:", 0, variants: new object[]
{ "SMA", 0, "EMA", 1, "WMA", 2, "T3", 3, "SMMA", 4, "TRIMA", 5, "DWMA", 6, "FWMA", 7, "DEMA", 8, "TEMA", 9,
@@ -55,28 +54,24 @@ public class MovingAverageSlope_chart : Indicator
private bool inLong, inShort;
///////
public MovingAverageSlope_chart()
{
public MovingAverageSlope_chart() {
this.SeparateWindow = false;
this.Name = "Slopes convergence";
this.AddLineSeries("MA1", Color.DarkSlateGray, 2, LineStyle.Solid);
this.AddLineSeries("MA2", Color.DarkSlateGray, 2, LineStyle.Solid);
}
protected override void OnInit()
{
protected override void OnInit() {
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--)
{
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
rec[PriceType.Close], rec[PriceType.Volume]);
}
this.Name = "Slopes convergence: [ ";
switch (MA1type)
{
switch (MA1type) {
case 0:
MA1 = new SMA_Series(source: bars.Select(this.MA1DataSource), period: this.MA1Period, useNaN: false);
this.Name += $"SMA";
@@ -150,8 +145,7 @@ public class MovingAverageSlope_chart : Indicator
this.Name = this.Name + $" ({MA1Period}:{TBars.SelectStr(this.MA1DataSource)}) : ";
switch (MA2type)
{
switch (MA2type) {
case 0:
MA2 = new SMA_Series(source: bars.Select(this.MA2DataSource), period: this.MA2Period, useNaN: false);
this.Name += $"SMA";
@@ -239,8 +233,7 @@ public class MovingAverageSlope_chart : Indicator
sig2.Keep = maxKeep;
}
protected override void OnUpdate(UpdateArgs args)
{
protected override void OnUpdate(UpdateArgs args) {
bool update = !(args.Reason == UpdateReason.NewBar ||
args.Reason == UpdateReason.HistoricalBar);
this.bars.Add(this.Time(), this.Open(), this.High(), this.Low(), this.Close(), this.Volume(), update);
@@ -253,46 +246,35 @@ public class MovingAverageSlope_chart : Indicator
this.LinesSeries[0].SetMarker(0, s1Color);
this.LinesSeries[1].SetMarker(0, s2Color);
if (sig1[^1].v > 0 || sig2[^1].v > 0)
{
if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0 && LongTrades)
{
if (sig1[^1].v > 0 || sig2[^1].v > 0) {
if (sMA1[^1].v >= 0 && sMA2[^1].v >= 0 && LongTrades) {
inLong = true;
this.BeginCloud(0, 1, Color.FromArgb(127, Color.DarkGreen));
this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.UpArrow));
}
else
{
} else {
this.EndCloud(0, 1, Color.Empty);
if (inShort && this.Count > 1)
{
if (inShort && this.Count > 1) {
this.LinesSeries[(this.MA1[^1].v < this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.DownArrow));
inShort = false;
}
}
}
if (sig1[^1].v < 0 || sig2[^1].v < 0)
{
if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0 && ShortTrades)
{
if (sig1[^1].v < 0 || sig2[^1].v < 0) {
if (sMA1[^1].v <= 0 && sMA2[^1].v <= 0 && ShortTrades) {
inShort = true;
this.BeginCloud(0, 1, Color.FromArgb(100, Color.Red));
this.LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 0 : 1].SetMarker(0, new IndicatorLineMarker(Color.OrangeRed, upperIcon: IndicatorLineMarkerIconType.UpArrow));
}
else
{
} else {
this.EndCloud(0, 1, Color.Empty);
if (inLong && this.Count > 1)
{
if (inLong && this.Count > 1) {
LinesSeries[(this.MA1[^1].v > this.MA2[^1].v) ? 1 : 0].SetMarker(1, new IndicatorLineMarker(Color.LimeGreen, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
inLong = false;
}
}
}
}
public override void OnPaintChart(PaintChartEventArgs args)
{
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null) { return; }
Graphics graphics = args.Graphics;
+7 -14
View File
@@ -6,8 +6,7 @@ using TradingPlatform.BusinessLayer;
using TradingPlatform.BusinessLayer.Chart;
namespace QuanTAlib;
public class JMA_chart : Indicator
{
public class JMA_chart : Indicator {
#region Parameters
[InputParameter("Data source", 0, variants: new object[]
@@ -39,8 +38,7 @@ public class JMA_chart : Indicator
protected int firstOnScreenBarIndex, lastOnScreenBarIndex;
protected HistoricalData History;
protected int HistPeriod;
public JMA_chart()
{
public JMA_chart() {
Name = "JMA - Jurik Moving Avg";
Description = "Jurik Moving Average description";
AddLineSeries(lineName: "JMA", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid);
@@ -49,8 +47,7 @@ public class JMA_chart : Indicator
}
protected override void OnInit()
{
protected override void OnInit() {
base.OnInit();
bars = new();
var dur1 = this.HistoricalData.FromTime;
@@ -58,8 +55,7 @@ public class JMA_chart : Indicator
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--)
{
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
@@ -72,8 +68,7 @@ public class JMA_chart : Indicator
indicator.Keep = Math.Max(Period, 100);
}
protected override void OnUpdate(UpdateArgs args)
{
protected override void OnUpdate(UpdateArgs args) {
base.OnUpdate(args);
bars.Add(Time(), GetPrice(PriceType.Open),
GetPrice(PriceType.High),
@@ -84,11 +79,9 @@ public class JMA_chart : Indicator
this.SetValue(indicator[^1].v, lineIndex: 0);
}
public override void OnPaintChart(PaintChartEventArgs args)
{
public override void OnPaintChart(PaintChartEventArgs args) {
base.OnPaintChart(args);
if (this.CurrentChart == null)
{
if (this.CurrentChart == null) {
return;
}
+7 -14
View File
@@ -5,8 +5,7 @@ using System.Linq;
using TradingPlatform.BusinessLayer;
namespace QuanTAlib;
public class TrailingStop_chart : Indicator
{
public class TrailingStop_chart : Indicator {
#region Parameters
[InputParameter("Period", 0, 1, 100, 1, 1)]
@@ -31,8 +30,7 @@ public class TrailingStop_chart : Indicator
///////
public TrailingStop_chart()
{
public TrailingStop_chart() {
Name = $"ATR Trailing Stop";
AddLineSeries(lineName: "TrailingATR Long", lineColor: Color.Yellow, lineWidth: 1, lineStyle: LineStyle.Dot);
AddLineSeries(lineName: "Ratchet Long", lineColor: Color.Yellow, lineWidth: 3, lineStyle: LineStyle.Solid);
@@ -44,14 +42,12 @@ public class TrailingStop_chart : Indicator
}
protected override void OnInit()
{
protected override void OnInit() {
this.Name = $"Trailing Stop (ATR:{_period}, Mult:{_factor:f2})";
this.bars = new();
this.History = this.Symbol.GetHistory(period: this.HistoricalData.Period, fromTime: HistoricalData.FromTime);
for (int i = this.History.Count - 1; i >= 0; i--)
{
for (int i = this.History.Count - 1; i >= 0; i--) {
var rec = this.History[i, SeekOriginHistory.Begin];
bars.Add(rec.TimeLeft, rec[PriceType.Open],
rec[PriceType.High], rec[PriceType.Low],
@@ -67,8 +63,7 @@ public class TrailingStop_chart : Indicator
this.LinesSeries[3].Visible = _ShortTS;
}
protected override void OnUpdate(UpdateArgs args)
{
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),
@@ -79,16 +74,14 @@ public class TrailingStop_chart : Indicator
_tslineL = bars.High[^1].v - (_factor * _atr[^1].v);
_ratchetL = Math.Max(_tslineL, _ratchetL);
if (_ratchetL > bars.Low[^1].v)
{
if (_ratchetL > bars.Low[^1].v) {
this.LinesSeries[1].SetMarker(0, new IndicatorLineMarker(Color.Yellow, bottomIcon: IndicatorLineMarkerIconType.DownArrow));
_ratchetL = _tslineL;
}
_tslineS = bars.High[^1].v + (_factor * _atr[^1].v);
_ratchetS = Math.Min(_tslineS, _ratchetS);
if (_ratchetS < bars.High[^1].v)
{
if (_ratchetS < bars.High[^1].v) {
this.LinesSeries[3].SetMarker(0, new IndicatorLineMarker(Color.Yellow, upperIcon: IndicatorLineMarkerIconType.UpArrow));
_ratchetS = _tslineS;
}
+13 -26
View File
@@ -4,8 +4,7 @@ using QuanTAlib;
namespace Basics;
#nullable disable
public class Indicators
{
public class Indicators {
private static Type[] maSeriesTypes = new Type[]
{
typeof(SMA_Series),
@@ -32,8 +31,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Name_exists(Type classType)
{
public void Name_exists(Type classType) {
TSeries data = new("Data") { 1, 2, 3 };
var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries;
@@ -42,8 +40,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Series_Length(Type classType)
{
public void Series_Length(Type classType) {
GBM_Feed feed = new(1000);
TSeries data = feed.OHLC4;
@@ -53,8 +50,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Return_data(Type classType)
{
public void Return_data(Type classType) {
TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries;
@@ -64,8 +60,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Update(Type classType)
{
public void Update(Type classType) {
TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries;
@@ -81,8 +76,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Period_zero(Type classType)
{
public void Period_zero(Type classType) {
GBM_Feed feed = new(100);
TSeries data = feed.OHLC4;
@@ -93,8 +87,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Reset(Type classType)
{
public void Reset(Type classType) {
GBM_Feed feed = new(10);
TSeries data = feed.OHLC4;
var MA_Series = Activator.CreateInstance(classType, data, 10, false) as TSeries;
@@ -105,8 +98,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Period_one(Type classType)
{
public void Period_one(Type classType) {
GBM_Feed feed = new(100);
TSeries data = feed.OHLC4;
@@ -116,8 +108,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void NaN_test(Type classType)
{
public void NaN_test(Type classType) {
GBM_Feed feed = new(100);
TSeries data = feed.OHLC4;
@@ -129,8 +120,7 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Edge_numbers(Type classType)
{
public void Edge_numbers(Type classType) {
TSeries data = new() { double.Epsilon, double.PositiveInfinity, double.MaxValue, double.NegativeInfinity };
var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries;
Assert.Equal(4, MA_Series.Count);
@@ -138,17 +128,14 @@ public class Indicators
[Theory]
[MemberData(nameof(MASeriesData))]
public void handling_NaN(Type classType)
{
public void handling_NaN(Type classType) {
TSeries data = new("Name") { 1, 2, 3, 4, 5, 6, double.NaN, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries;
Assert.False(double.IsNaN(MA_Series.Last.v));
}
public static IEnumerable<object[]> MASeriesData()
{
foreach (var type in maSeriesTypes)
{
public static IEnumerable<object[]> MASeriesData() {
foreach (var type in maSeriesTypes) {
yield return new object[] { type };
}
}
+13 -26
View File
@@ -5,8 +5,7 @@ using QuanTAlib;
namespace Basics;
#nullable disable
public class Oscillators
{
public class Oscillators {
private static Type[] maSeriesTypes = new[]
{
typeof(BIAS_Series),
@@ -37,8 +36,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Name_exists(Type classType)
{
public void Name_exists(Type classType) {
TSeries data = new("Data") { 1, 2, 3 };
var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries;
@@ -47,8 +45,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Series_Length(Type classType)
{
public void Series_Length(Type classType) {
GBM_Feed feed = new(1000);
TSeries data = feed.OHLC4;
@@ -58,8 +55,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Return_data(Type classType)
{
public void Return_data(Type classType) {
TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries;
@@ -69,8 +65,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Update(Type classType)
{
public void Update(Type classType) {
TSeries data = new() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var MA_Series = Activator.CreateInstance(classType, data, 5, false) as TSeries;
@@ -86,8 +81,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Period_zero(Type classType)
{
public void Period_zero(Type classType) {
GBM_Feed feed = new(100);
TSeries data = feed.OHLC4;
@@ -98,8 +92,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Reset(Type classType)
{
public void Reset(Type classType) {
GBM_Feed feed = new(10);
TSeries data = feed.OHLC4;
var MA_Series = Activator.CreateInstance(classType, data, 10, false) as TSeries;
@@ -110,8 +103,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Period_one(Type classType)
{
public void Period_one(Type classType) {
GBM_Feed feed = new(100);
TSeries data = feed.OHLC4;
@@ -121,8 +113,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void NaN_test(Type classType)
{
public void NaN_test(Type classType) {
GBM_Feed feed = new(100);
TSeries data = feed.OHLC4;
@@ -134,8 +125,7 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void Edge_numbers(Type classType)
{
public void Edge_numbers(Type classType) {
TSeries data = new() { double.Epsilon, double.PositiveInfinity, double.MaxValue, double.NegativeInfinity };
var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries;
Assert.Equal(4, MA_Series.Count);
@@ -143,17 +133,14 @@ public class Oscillators
[Theory]
[MemberData(nameof(MASeriesData))]
public void handling_NaN(Type classType)
{
public void handling_NaN(Type classType) {
TSeries data = new("Name") { 1, 2, 3, 4, 5, 6, double.NaN, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
var MA_Series = Activator.CreateInstance(classType, data, 10, true) as TSeries;
Assert.False(double.IsNaN(MA_Series.Last.v));
}
public static IEnumerable<object[]> MASeriesData()
{
foreach (var type in maSeriesTypes)
{
public static IEnumerable<object[]> MASeriesData() {
foreach (var type in maSeriesTypes) {
yield return new object[] { type };
}
}
+9 -18
View File
@@ -5,8 +5,7 @@ using QuanTAlib;
namespace Basics;
#nullable disable
public class TBars
{
public class TBars {
private static Type[] maSeriesTypes = new Type[]
{
typeof(ATR_Series),
@@ -21,8 +20,7 @@ public class TBars
[Theory]
[MemberData(nameof(MASeriesData))]
public void Name_exists(Type classType)
{
public void Name_exists(Type classType) {
GBM_Feed data = new(10);
var MA_Series = Activator.CreateInstance(classType, data) as TSeries;
@@ -31,8 +29,7 @@ public class TBars
[Theory]
[MemberData(nameof(MASeriesData))]
public void Series_Length(Type classType)
{
public void Series_Length(Type classType) {
GBM_Feed data = new(1000);
var MA_Series = Activator.CreateInstance(classType, data) as TSeries;
@@ -41,8 +38,7 @@ public class TBars
[Theory]
[MemberData(nameof(MASeriesData))]
public void Return_data(Type classType)
{
public void Return_data(Type classType) {
GBM_Feed data = new(10);
var MA_Series = Activator.CreateInstance(classType, data) as TSeries;
var result = MA_Series.Add((DateTime.Today, 1, 2, 3, 4, 5));
@@ -51,8 +47,7 @@ public class TBars
[Theory]
[MemberData(nameof(MASeriesData))]
public void Update(Type classType)
{
public void Update(Type classType) {
GBM_Feed data = new(10);
var MA_Series = Activator.CreateInstance(classType, data) as TSeries;
var pre_update = MA_Series.Last;
@@ -67,8 +62,7 @@ public class TBars
[Theory]
[MemberData(nameof(MASeriesData))]
public void Reset(Type classType)
{
public void Reset(Type classType) {
GBM_Feed data = new(10);
var MA_Series = Activator.CreateInstance(classType, data) as TSeries;
MA_Series.Reset();
@@ -78,18 +72,15 @@ public class TBars
[Theory]
[MemberData(nameof(MASeriesData))]
public void Period_default(Type classType)
{
public void Period_default(Type classType) {
GBM_Feed data = new(100);
var MA_Series = Activator.CreateInstance(classType, data) as TSeries;
Assert.False(double.IsNaN(MA_Series.Last.v));
}
public static IEnumerable<object[]> MASeriesData()
{
foreach (var type in maSeriesTypes)
{
public static IEnumerable<object[]> MASeriesData() {
foreach (var type in maSeriesTypes) {
yield return new object[] { type };
}
}
+7 -14
View File
@@ -3,11 +3,9 @@ using System;
using QuanTAlib;
namespace Pairs;
public class ADD_Test
{
public class ADD_Test {
[Fact]
public void ADDSeriesSeries_Test()
{
public void ADDSeriesSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
ADD_Series c = new(a, b);
@@ -15,24 +13,21 @@ public class ADD_Test
}
[Fact]
public void ADDSeriesDouble_Test()
{
public void ADDSeriesDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
ADD_Series c = new(a, 10.0);
Assert.Equal(15, c.Last().v);
}
[Fact]
public void ADDDoubleSeries_Test()
{
public void ADDDoubleSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
ADD_Series c = new(10.0, a);
Assert.Equal(15, c.Last().v);
}
[Fact]
public void ADDEventing_Test()
{
public void ADDEventing_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
ADD_Series c = new(a, b);
@@ -42,8 +37,7 @@ public class ADD_Test
}
[Fact]
public void ADDUpdateDouble_Test()
{
public void ADDUpdateDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
double b = 10;
ADD_Series c = new(a, b);
@@ -52,8 +46,7 @@ public class ADD_Test
}
[Fact]
public void ADDUpdating_Test()
{
public void ADDUpdating_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
ADD_Series c = new(a, b);
+7 -14
View File
@@ -3,11 +3,9 @@ using System;
using QuanTAlib;
namespace Pairs;
public class DIV_Test
{
public class DIV_Test {
[Fact]
public void DIVSeriesSeries_Test()
{
public void DIVSeriesSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 15 };
TSeries b = new() { 5, 4, 3, 2, 1, 3 };
DIV_Series c = new(a, b);
@@ -15,24 +13,21 @@ public class DIV_Test
}
[Fact]
public void DIVSeriesDouble_Test()
{
public void DIVSeriesDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 15.0 };
DIV_Series c = new(a, 0);
Assert.Equal(double.PositiveInfinity, c.Last().v);
}
[Fact]
public void DIVDoubleSeries_Test()
{
public void DIVDoubleSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 3.0 };
DIV_Series c = new(12.0, a);
Assert.Equal(4.0, c.Last().v);
}
[Fact]
public void DIVEventing_Test()
{
public void DIVEventing_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
DIV_Series c = new(a, b);
@@ -42,8 +37,7 @@ public class DIV_Test
}
[Fact]
public void DIVUpdatewDouble_Test()
{
public void DIVUpdatewDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 15 };
double b = 2;
DIV_Series c = new(a, b);
@@ -52,8 +46,7 @@ public class DIV_Test
}
[Fact]
public void DIVUpdating_Test()
{
public void DIVUpdating_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 1 };
DIV_Series c = new(a, b);
+7 -14
View File
@@ -3,11 +3,9 @@ using System;
using QuanTAlib;
namespace Pairs;
public class MUL_Test
{
public class MUL_Test {
[Fact]
public void MULSeriesSeries_Test()
{
public void MULSeriesSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 1 };
MUL_Series c = new(a, b);
@@ -15,24 +13,21 @@ public class MUL_Test
}
[Fact]
public void MULSeriesDouble_Test()
{
public void MULSeriesDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
MUL_Series c = new(a, 10.0);
Assert.Equal(50, c.Last().v);
}
[Fact]
public void MULDoubleSeries_Test()
{
public void MULDoubleSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
MUL_Series c = new(5.0, a);
Assert.Equal(25, c.Last().v);
}
[Fact]
public void MULEventing_Test()
{
public void MULEventing_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
MUL_Series c = new(a, b);
@@ -42,8 +37,7 @@ public class MUL_Test
}
[Fact]
public void MULUpdateDouble_Test()
{
public void MULUpdateDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
double b = 10;
MUL_Series c = new(a, b);
@@ -52,8 +46,7 @@ public class MUL_Test
}
[Fact]
public void MULUpdating_Test()
{
public void MULUpdating_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
MUL_Series c = new(a, b);
+7 -14
View File
@@ -3,11 +3,9 @@ using System;
using QuanTAlib;
namespace Pairs;
public class SUB_Test
{
public class SUB_Test {
[Fact]
public void SUBSeriesSeries_Test()
{
public void SUBSeriesSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 1 };
SUB_Series c = new(a, b);
@@ -15,24 +13,21 @@ public class SUB_Test
}
[Fact]
public void SUBSeriesDouble_Test()
{
public void SUBSeriesDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 15.0 };
SUB_Series c = new(a, 10.0);
Assert.Equal(5.0, c.Last().v);
}
[Fact]
public void SUBDoubleSeries_Test()
{
public void SUBDoubleSeries_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 15.0 };
SUB_Series c = new(10.0, a);
Assert.Equal(-5.0, c.Last().v);
}
[Fact]
public void SUBEventing_Test()
{
public void SUBEventing_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 0 };
SUB_Series c = new(a, b);
@@ -42,8 +37,7 @@ public class SUB_Test
}
[Fact]
public void SUBUpdatewDouble_Test()
{
public void SUBUpdatewDouble_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 15 };
double b = 10;
SUB_Series c = new(a, b);
@@ -52,8 +46,7 @@ public class SUB_Test
}
[Fact]
public void SUBUpdating_Test()
{
public void SUBUpdating_Test() {
TSeries a = new() { 0, 1, 2, 3, 4, 5 };
TSeries b = new() { 5, 4, 3, 2, 1, 1 };
SUB_Series c = new(a, b);
+6 -12
View File
@@ -3,11 +3,9 @@ using System;
using QuanTAlib;
namespace Bars;
public class TBars_Test
{
public class TBars_Test {
[Fact]
public void InsertingTuple()
{
public void InsertingTuple() {
TBars s = new() { (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue, c: Double.NegativeInfinity, v: Double.PositiveInfinity) };
var tup = (t: DateTime.Today, o: double.Epsilon, h: double.NaN, l: Double.MaxValue,
c: Double.NegativeInfinity, v: Double.PositiveInfinity);
@@ -15,8 +13,7 @@ public class TBars_Test
}
[Fact]
public void Casting_Parameters()
{
public void Casting_Parameters() {
TBars s = new()
{
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1, false }
@@ -31,8 +28,7 @@ public class TBars_Test
}
[Fact]
public void Updating_Value()
{
public void Updating_Value() {
TBars s = new()
{
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 }
@@ -47,8 +43,7 @@ public class TBars_Test
Assert.Equal(2, s.Count);
}
[Fact]
public void Extracting_TSeries()
{
public void Extracting_TSeries() {
TBars s = new()
{
{ DateTime.Today, 0.1, 1.1, 2.1, 3.1, 4.1 },
@@ -100,8 +95,7 @@ public class TBars_Test
Assert.Equal(t.v, s.HLCC4.v);
}
[Fact]
public void Broadcasting_Events()
{
public void Broadcasting_Events() {
TBars s = new() { (DateTime.Today, 2.1, 3.1, 4.1, 5.1, 6.1) };
TSeries t = new();
s.Close.Pub += t.Sub;
+74 -153
View File
@@ -7,8 +7,7 @@ using Python.Runtime;
namespace Validations;
public class PandasTA : IDisposable
{
public class PandasTA : IDisposable {
private bool disposed = false;
private readonly GBM_Feed bars;
private readonly Random rnd = new();
@@ -19,8 +18,7 @@ public class PandasTA : IDisposable
private readonly dynamic pd;
private readonly dynamic df;
public PandasTA()
{
public PandasTA() {
bars = new GBM_Feed(5000, 0.8, 0.0);
period = rnd.Next(28) + 3;
skip = period + 50;
@@ -36,8 +34,7 @@ public class PandasTA : IDisposable
string[] cols = { "open", "high", "low", "close", "volume" };
var ary = new double[bars.Count, 5];
for (var i = 0; i < bars.Count; i++)
{
for (var i = 0; i < bars.Count; i++) {
ary[i, 0] = bars.Open[i].v;
ary[i, 1] = bars.High[i].v;
ary[i, 2] = bars.Low[i].v;
@@ -48,33 +45,27 @@ public class PandasTA : IDisposable
df = ta.DataFrame(data: np.array(ary), index: np.array(bars.Close.t), columns: np.array(cols));
}
public void Dispose()
{
public void Dispose() {
Dispose(true);
PythonEngine.Shutdown();
GC.SuppressFinalize(this);
}
~PandasTA()
{
~PandasTA() {
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
protected virtual void Dispose(bool disposing) {
if (!disposed) {
disposed = true;
}
}
[Fact]
private void ADL()
{
private void ADL() {
ADL_Series QL = new(bars);
var pta = df.ta.ad(high: df.high, low: df.low, close: df.close, volume: df.volume);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -82,12 +73,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void BBANDS()
{
private void BBANDS() {
BBANDS_Series QL = new(bars.Close, period);
var pta = df.ta.bbands(close: df.close, length: period).to_numpy();
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL.Lower[i].v;
var PanTA_item = (double)pta[i][0]; //lower
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -101,12 +90,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void BIAS()
{
private void BIAS() {
BIAS_Series QL = new(bars.Close, period, false);
var pta = df.ta.bias(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -114,12 +101,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void CCI()
{
private void CCI() {
CCI_Series QL = new(bars, period, false);
var pta = df.ta.cci(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -127,12 +112,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void DEMA()
{
private void DEMA() {
DEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.dema(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -140,12 +123,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void EMA()
{
private void EMA() {
EMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.ema(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -153,12 +134,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void ENTROPY()
{
private void ENTROPY() {
ENTROPY_Series QL = new(bars.Close, period, false);
var pta = df.ta.entropy(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -166,11 +145,9 @@ public class PandasTA : IDisposable
}
[Fact]
private void HL2()
{
private void HL2() {
var pta = df.ta.hl2(high: df.high, low: df.low);
for (var i = bars.HL2.Length - 1; i > skip; i--)
{
for (var i = bars.HL2.Length - 1; i > skip; i--) {
var QL_item = bars.HL2[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -178,11 +155,9 @@ public class PandasTA : IDisposable
}
[Fact]
private void HLC3()
{
private void HLC3() {
var pta = df.ta.hlc3(high: df.high, low: df.low, close: df.close);
for (var i = bars.HLC3.Length; i > skip; i--)
{
for (var i = bars.HLC3.Length; i > skip; i--) {
var QL_item = bars.HLC3[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -190,12 +165,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void HMA()
{
private void HMA() {
HMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.hma(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -203,12 +176,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void KURTOSIS()
{
private void KURTOSIS() {
KURTOSIS_Series QL = new(bars.Close, period, false);
var pta = df.ta.kurtosis(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -216,12 +187,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void MACD()
{
private void MACD() {
MACD_Series QL = new(bars.Close, 26, 12, 9, false);
var pta = df.ta.macd(close: df.close).to_numpy();
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1][0];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -232,12 +201,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void MAD()
{
private void MAD() {
MAD_Series QL = new(bars.Close, period, false);
var pta = df.ta.mad(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -245,12 +212,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void MEDIAN()
{
private void MEDIAN() {
MEDIAN_Series QL = new(bars.Close, period);
var pta = df.ta.median(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -258,12 +223,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void OBV()
{
private void OBV() {
OBV_Series QL = new(bars);
var pta = df.ta.obv(close: df.close, volume: df.volume);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -271,11 +234,9 @@ public class PandasTA : IDisposable
}
[Fact]
private void OHLC4()
{
private void OHLC4() {
var pta = df.ta.ohlc4(open: df.open, high: df.high, low: df.low, close: df.close);
for (var i = bars.OHLC4.Length; i > skip; i--)
{
for (var i = bars.OHLC4.Length; i > skip; i--) {
var QL_item = bars.OHLC4[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -283,12 +244,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void SDEV()
{
private void SDEV() {
SDEV_Series QL = new(bars.Close, period, false);
var pta = df.ta.stdev(close: df.close, length: period, ddof: 0);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -296,12 +255,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void SMA()
{
private void SMA() {
SMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.sma(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -309,12 +266,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void SSDEV()
{
private void SSDEV() {
SSDEV_Series QL = new(bars.Close, period, false);
var pta = df.ta.stdev(close: df.close, length: period, ddof: 1);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -322,12 +277,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void SVARIANCE()
{
private void SVARIANCE() {
SVAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof: 1);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -335,12 +288,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void TEMA()
{
private void TEMA() {
TEMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.tema(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -348,12 +299,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void TR()
{
private void TR() {
TR_Series QL = new(bars);
var pta = df.ta.true_range(high: df.high, low: df.low, close: df.close);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -361,13 +310,11 @@ public class PandasTA : IDisposable
}
[Fact]
private void TRIMA()
{
private void TRIMA() {
// TODO: return length to variable length (period) when Pandas-TA fixes trima to calculate even periods right
TRIMA_Series QL = new(bars.Close, 11);
var pta = df.ta.trima(close: df.close, length: 11);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -375,12 +322,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void VARIANCE()
{
private void VARIANCE() {
VAR_Series QL = new(bars.Close, period);
var pta = df.ta.variance(close: df.close, length: period, ddof: 0);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -388,12 +333,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void WMA()
{
private void WMA() {
WMA_Series QL = new(bars.Close, period, false);
var pta = df.ta.wma(close: df.close, length: period);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -401,12 +344,10 @@ public class PandasTA : IDisposable
}
[Fact]
private void ZSCORE()
{
private void ZSCORE() {
ZSCORE_Series QL = new(bars.Close, period, false);
var pta = df.ta.zscore(close: df.close, length: period, ddof: 0);
for (var i = QL.Length - 1; i > skip; i--)
{
for (var i = QL.Length - 1; i > skip; i--) {
var QL_item = QL[i - 1].v;
var PanTA_item = (double)pta[i - 1];
Assert.InRange(PanTA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -414,22 +355,15 @@ public class PandasTA : IDisposable
}
}
public static class PythonLibrary
{
public static string Locate()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
public static class PythonLibrary {
public static string Locate() {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
string[] paths = Environment.GetEnvironmentVariable("PATH")?.Split(';') ?? Array.Empty<string>();
foreach (string path in paths)
{
foreach (string path in paths) {
string[] pythonDLLs = Directory.GetFiles(path, "python3*.dll");
if (pythonDLLs.Length > 0)
{
foreach (string item in pythonDLLs)
{
if (!item.EndsWith("python3.dll", StringComparison.OrdinalIgnoreCase))
{
if (pythonDLLs.Length > 0) {
foreach (string item in pythonDLLs) {
if (!item.EndsWith("python3.dll", StringComparison.OrdinalIgnoreCase)) {
return item;
}
}
@@ -437,9 +371,7 @@ public static class PythonLibrary
}
}
throw new FileNotFoundException("Python library not found in PATH");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
return "/usr/lib/x86_64-linux-gnu/libpython3.10.so";
/*
List<string> pythonLibraries = new List<string>();
@@ -454,28 +386,17 @@ public static class PythonLibrary
throw new FileNotFoundException("Python library not found");
}
*/
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
} else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
throw new NotSupportedException("Not supported yet");
}
else { throw new NotSupportedException("Unsupported operating system"); }
} else { throw new NotSupportedException("Unsupported operating system"); }
}
static void SearchFiles(List<string> directoriesToSearch, string filePattern, List<string> foundFiles)
{
foreach (string directory in directoriesToSearch)
{
if (Directory.Exists(directory))
{
try
{
static void SearchFiles(List<string> directoriesToSearch, string filePattern, List<string> foundFiles) {
foreach (string directory in directoriesToSearch) {
if (Directory.Exists(directory)) {
try {
string[] files = Directory.GetFiles(directory, filePattern, SearchOption.AllDirectories);
foundFiles.AddRange(files);
}
catch (Exception e)
{
} catch (Exception e) {
Console.WriteLine("Error searching in directory: " + directory + " - " + e.Message);
}
}
+71 -142
View File
@@ -4,23 +4,20 @@ using Skender.Stock.Indicators;
using Xunit;
namespace Validations;
public class Skender
{
public class Skender {
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period, digits, skip;
private readonly IEnumerable<Quote> quotes;
public Skender()
{
public Skender() {
bars = new(Bars: 10000, Volatility: 0.5, Drift: 0.0, Precision: 2);
period = rnd.Next(30) + 5;
digits = 6; //minimizing rounding errors in type conversions
skip = period + 2;
quotes = bars.Select(q => new Quote
{
quotes = bars.Select(q => new Quote {
Date = q.t,
Open = (decimal)q.o,
High = (decimal)q.h,
@@ -45,48 +42,40 @@ public class Skender
}
*/
[Fact]
public void ALMA()
{
public void ALMA() {
ALMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetAlma(period).Select(i => i.Alma.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void ATR()
{
public void ATR() {
ATR_Series QL = new(bars, period: period, useNaN: false);
var SK = quotes.GetAtr(period).Select(i => i.Atr.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void ATRP()
{
public void ATRP() {
ATRP_Series QL = new(bars, period, false);
var SK = quotes.GetAtr(period).Select(i => i.Atrp.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void BBANDS()
{
public void BBANDS() {
BBANDS_Series QL = new(bars.Close, period, 2.0, useNaN: false);
var SK = quotes.GetBollingerBands(period, 2.0);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL.Mid[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Sma!.Value;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
@@ -108,108 +97,90 @@ public class Skender
}
}
[Fact]
public void CCI()
{
public void CCI() {
CCI_Series QL = new(bars, period, false);
var SK = quotes.GetCci(period).Select(i => i.Cci.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void CMO()
{
public void CMO() {
CMO_Series QL = new(bars.Close, period, false);
var SK = quotes.GetCmo(period).Select(i => i.Cmo.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void CORR()
{
public void CORR() {
CORR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Correlation.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void COVAR()
{
public void COVAR() {
COVAR_Series QL = new(bars.High, bars.Low, period, false);
var SK = quotes.Use(CandlePart.High).GetCorrelation(quotes.Use(CandlePart.Low), period).Select(i => i.Covariance.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void DEMA()
{
public void DEMA() {
DEMA_Series QL = new(bars.Close, period, false, useSMA: true);
var SK = quotes.GetDema(period).Select(i => i.Dema.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void EMA()
{
public void EMA() {
EMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetEma(lookbackPeriods: period).Select(i => i.Ema.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void HL2()
{
public void HL2() {
TSeries QL = bars.HL2;
var SK = quotes.GetBaseQuote(CandlePart.HL2).ToList();
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Value;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void HLC3()
{
public void HLC3() {
TSeries QL = bars.HLC3;
var SK = quotes.GetBaseQuote(CandlePart.HLC3).ToList();
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Value;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void HMA()
{
public void HMA() {
HMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetHma(period).Select(i => i.Hma.Null2NaN()!);
for (int i = QL.Length; i > skip * 2; i--)
{
for (int i = QL.Length; i > skip * 2; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
@@ -217,25 +188,21 @@ public class Skender
}
[Fact]
public void KAMA()
{
public void KAMA() {
// TODO: check precision of KAMA()
KAMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetKama(period).Select(i => i.Kama.Null2NaN()!);
for (int i = QL.Length; i > skip + 2; i--)
{
for (int i = QL.Length; i > skip + 2; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void SLOPE()
{
public void SLOPE() {
SLOPE_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSlope(period);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = (double)SK.ElementAt(i - 1).Slope!;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
@@ -251,12 +218,10 @@ public class Skender
}
}
[Fact]
public void MACD()
{
public void MACD() {
MACD_Series QL = new(bars.Close, 26, 12, 9, useNaN: false);
var SK = quotes.GetMacd(12, 26, 9);
for (int i = QL.Length; i > 27; i--)
{
for (int i = QL.Length; i > 27; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Macd.Null2NaN()!;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
@@ -266,24 +231,20 @@ public class Skender
}
}
[Fact]
public void MAD()
{
public void MAD() {
MAD_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mad.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void MAMA()
{
public void MAMA() {
MAMA_Series QL = new(bars.HL2, fastlimit: 0.5, slowlimit: 0.05);
var SK = quotes.GetMama(fastLimit: 0.5, slowLimit: 0.05);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Mama.Null2NaN()!;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
@@ -293,36 +254,30 @@ public class Skender
}
}
[Fact]
public void MAPE()
{
public void MAPE() {
MAPE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mape.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void MSE()
{
public void MSE() {
MSE_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSmaAnalysis(period).Select(i => i.Mse.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void OBV()
{
public void OBV() {
OBV_Series QL = new(bars, period, false);
var SK = quotes.GetObv(period).Select(i => i.Obv!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL.Last().v;
// adding volume[0] to OBV to pass the test and keep compatibility with TA-LIB
double SK_item = SK.Last()! + (double)quotes.First().Volume!;
@@ -330,156 +285,130 @@ public class Skender
}
}
[Fact]
public void OC2()
{
public void OC2() {
TSeries QL = bars.OC2;
var SK = quotes.GetBaseQuote(CandlePart.OC2).ToList();
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Value;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void OHL3()
{
public void OHL3() {
TSeries QL = bars.OHL3;
var SK = quotes.GetBaseQuote(CandlePart.OHL3).ToList();
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Value;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void OHLC4()
{
public void OHLC4() {
TSeries QL = bars.OHLC4;
var SK = quotes.GetBaseQuote(CandlePart.OHLC4).ToList();
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1).Value;
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void RSI()
{
public void RSI() {
RSI_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetRsi(period).Select(i => i.Rsi.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void SDEV()
{
public void SDEV() {
SDEV_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period).Select(i => i.StdDev.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void SMA()
{
public void SMA() {
SMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetSma(period).Select(i => i.Sma.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void SMMA()
{
public void SMMA() {
SMMA_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetSmma(period).Select(i => i.Smma.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void T3()
{
public void T3() {
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, false);
var SK = quotes.GetT3(lookbackPeriods: period, volumeFactor: 0.7).Select(i => i.T3.Null2NaN()!);
for (int i = QL.Length; i > period * 15; i--)
{
for (int i = QL.Length; i > period * 15; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void TRIX()
{
public void TRIX() {
TRIX_Series QL = new(bars.Close, period, false);
var SK = quotes.GetTrix(period).Select(i => i.Trix.Null2NaN()!);
for (int i = QL.Length; i > period * 12; i--)
{
for (int i = QL.Length; i > period * 12; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void TEMA()
{
public void TEMA() {
TEMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetTema(period).Select(i => i.Tema.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void TR()
{
public void TR() {
TR_Series QL = new(bars);
var SK = quotes.GetTr().Select(i => i.Tr.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void WMA()
{
public void WMA() {
WMA_Series QL = new(bars.Close, period, false);
var SK = quotes.GetWma(period).Select(i => i.Wma.Null2NaN()!);
for (int i = QL.Length; i > skip * 2; i--)
{
for (int i = QL.Length; i > skip * 2; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
}
}
[Fact]
public void ZSCORE()
{
public void ZSCORE() {
ZSCORE_Series QL = new(bars.Close, period, useNaN: false);
var SK = quotes.GetStdDev(period).Select(i => i.ZScore.Null2NaN()!);
for (int i = QL.Length; i > skip; i--)
{
for (int i = QL.Length; i > skip; i--) {
double QL_item = QL[i - 1].v;
double SK_item = SK.ElementAt(i - 1);
Assert.InRange(SK_item! - QL_item, -Math.Pow(10, -digits), Math.Pow(10, -digits));
+70 -140
View File
@@ -4,8 +4,7 @@ using TALib;
using QuanTAlib;
namespace Validations;
public class Ta_Lib
{
public class Ta_Lib {
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period, digits, skip;
@@ -17,8 +16,7 @@ public class Ta_Lib
private readonly double[] inclose;
private readonly double[] involume;
public Ta_Lib()
{
public Ta_Lib() {
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3);
period = rnd.Next(28) + 3;
skip = period + 2;
@@ -34,48 +32,40 @@ public class Ta_Lib
}
[Fact]
public void ADD()
{
public void ADD() {
ADD_Series QL = new(bars.Open, bars.Close);
Core.Add(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ADL()
{
public void ADL() {
ADL_Series QL = new(bars);
Core.Ad(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > 0; i--)
{
for (int i = QL.Length - 1; i > 0; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ADOSC()
{
public void ADOSC() {
ADOSC_Series QL = new(bars, 3, 10, false);
Core.AdOsc(inhigh, inlow, inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip * 2; i--)
{
for (int i = QL.Length - 1; i > skip * 2; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ATR()
{
public void ATR() {
ATR_Series QL = new(bars, period: period, useNaN: false);
Core.Atr(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -83,15 +73,13 @@ public class Ta_Lib
}
[Fact]
public void BBANDS()
{
public void BBANDS() {
double[] outMiddle = new double[bars.Count];
double[] outUpper = new double[bars.Count];
double[] outLower = new double[bars.Count];
BBANDS_Series QL = new(bars.Close, period: period, multiplier: 2.0, false);
Core.Bbands(inclose, 0, bars.Count - 1, outRealUpperBand: outUpper, outRealMiddleBand: outMiddle, outRealLowerBand: outLower, out int outBegIdx, out _, optInTimePeriod: period, optInNbDevUp: 2.0, optInNbDevDn: 2.0);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL.Upper[i].v;
double TA_item = outUpper[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), high: Math.Exp(-digits));
@@ -104,12 +92,10 @@ public class Ta_Lib
}
}
[Fact]
public void CCI()
{
public void CCI() {
CCI_Series QL = new(bars, period, false);
Core.Cci(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -128,111 +114,93 @@ public class Ta_Lib
}
*/
[Fact]
public void CORR()
{
public void CORR() {
CORR_Series QL = new(bars.Open, bars.Close, period);
Core.Correl(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, optInTimePeriod: period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void DEMA()
{
public void DEMA() {
DEMA_Series QL = new(bars.Close, period, false, useSMA: false);
Core.Dema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > period * 10; i--)
{
for (int i = QL.Length - 1; i > period * 10; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void DIV()
{
public void DIV() {
DIV_Series QL = new(bars.Open, bars.Close);
Core.Div(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void EMA()
{
public void EMA() {
EMA_Series QL = new(bars.Close, period, false);
Core.Ema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void HL2()
{
public void HL2() {
TSeries QL = bars.HL2;
Core.MedPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void HLC3()
{
public void HLC3() {
TSeries QL = bars.HLC3;
Core.TypPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void HLCC4()
{
public void HLCC4() {
TSeries QL = bars.HLCC4;
Core.WclPrice(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void KAMA()
{
public void KAMA() {
KAMA_Series QL = new(bars.Close, period, fast: 2, slow: 30);
Core.Kama(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period);
for (int i = QL.Length - 1; i > skip * 15; i--)
{
for (int i = QL.Length - 1; i > skip * 15; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MACD()
{
public void MACD() {
double[] macdSignal = new double[bars.Count];
double[] macdHist = new double[bars.Count];
MACD_Series QL = new(bars.Close, slow: 26, fast: 12, signal: 9, false);
// TA-LIB runs EMA without SMA, leaving first 100 values for convergence
Core.Macd(inclose, 0, bars.Count - 1, outMacd: TALIB, outMacdSignal: macdSignal, outMacdHist: macdHist, out int outBegIdx, out _, optInFastPeriod: 12, optInSlowPeriod: 26, optInSignalPeriod: 9);
for (int i = QL.Length - 1; i > 100; i--)
{
for (int i = QL.Length - 1; i > 100; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -256,228 +224,190 @@ public class Ta_Lib
}
*/
[Fact]
public void MAX()
{
public void MAX() {
MAX_Series QL = new(bars.Close, period, false);
Core.Max(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MIDPOINT()
{
public void MIDPOINT() {
MIDPOINT_Series QL = new(bars.Close, period, false);
Core.MidPoint(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MIDPRICE()
{
public void MIDPRICE() {
MIDPRICE_Series QL = new(bars, period, false);
Core.MidPrice(inhigh, inlow, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MIN()
{
public void MIN() {
MIN_Series QL = new(bars.Close, period, false);
Core.Min(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MUL()
{
public void MUL() {
MUL_Series QL = new(bars.Open, bars.Close);
Core.Mult(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void OBV()
{
public void OBV() {
OBV_Series QL = new(bars, period, false);
Core.Obv(inclose, involume, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void OHLC4()
{
public void OHLC4() {
TSeries QL = bars.OHLC4;
Core.AvgPrice(inopen, inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void RSI()
{
public void RSI() {
RSI_Series QL = new(bars.Close, period, false);
Core.Rsi(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SDEV()
{
public void SDEV() {
SDEV_Series QL = new(bars.Close, period, false);
Core.StdDev(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SMA()
{
public void SMA() {
SMA_Series QL = new(bars.Close, period, false);
Core.Sma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SUB()
{
public void SUB() {
SUB_Series QL = new(bars.Open, bars.Close);
Core.Sub(inopen, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SUM()
{
public void SUM() {
CUSUM_Series QL = new(bars.Close, period, false);
Core.Sum(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void T3()
{
public void T3() {
T3_Series QL = new(source: bars.Close, period: period, vfactor: 0.7, useNaN: false);
Core.T3(inReal: inclose, startIdx: 0, endIdx: bars.Count - 1, outReal: TALIB, outBegIdx: out int outBegIdx, outNbElement: out _, optInTimePeriod: period, optInVFactor: 0.7);
for (int i = QL.Length - 1; i > period * 10; i--)
{
for (int i = QL.Length - 1; i > period * 10; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TEMA()
{
public void TEMA() {
TEMA_Series QL = new(bars.Close, period, false);
Core.Tema(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip * 15; i--)
{
for (int i = QL.Length - 1; i > skip * 15; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TR()
{
public void TR() {
TR_Series QL = new(bars);
Core.TRange(inhigh, inlow, inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TRIMA()
{
public void TRIMA() {
TRIMA_Series QL = new(bars.Close, period, false);
Core.Trima(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TRIX()
{
public void TRIX() {
TRIX_Series QL = new(bars.Close, period, useNaN: false, useSMA: true);
Core.Trix(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > period * 10; i--)
{
for (int i = QL.Length - 1; i > period * 10; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void VAR()
{
public void VAR() {
VAR_Series QL = new(bars.Close, period, false);
Core.Var(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip * 15; i--)
{
for (int i = QL.Length - 1; i > skip * 15; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void WMA()
{
public void WMA() {
WMA_Series QL = new(bars.Close, period, false);
Core.Wma(inclose, 0, bars.Count - 1, TALIB, out int outBegIdx, out _, period);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TA_item = TALIB[i - outBegIdx];
Assert.InRange(TA_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
+72 -144
View File
@@ -4,8 +4,7 @@ using Tulip;
using QuanTAlib;
namespace Validations;
public class Tulip_Test
{
public class Tulip_Test {
private readonly GBM_Feed bars;
private readonly Random rnd = new();
private readonly int period, digits, skip;
@@ -16,8 +15,7 @@ public class Tulip_Test
private readonly double[] inclose;
private readonly double[] involume;
public Tulip_Test()
{
public Tulip_Test() {
bars = new(Bars: 5000, Volatility: 0.8, Drift: 0.0, Precision: 3);
period = rnd.Next(28) + 3;
skip = period + 5;
@@ -32,67 +30,58 @@ public class Tulip_Test
}
[Fact]
public void ADL()
{
public void ADL() {
double[][] arrin = { inhigh, inlow, inclose, involume };
double[][] arrout = { outdata };
ADL_Series QL = new(bars);
Tulip.Indicators.ad.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ADD()
{
public void ADD() {
double[][] arrin = { inhigh, inlow };
double[][] arrout = { outdata };
ADD_Series QL = new(bars.High, bars.Low);
Tulip.Indicators.add.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ADOSC()
{
public void ADOSC() {
double[][] arrin = { inhigh, inlow, inclose, involume };
double[][] arrout = { outdata };
int s = 3;
ADOSC_Series QL = new(bars, s, period, false);
Tulip.Indicators.adosc.Run(inputs: arrin, options: new double[] { s, period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ATR()
{
public void ATR() {
double[][] arrin = { inhigh, inlow, inclose };
double[][] arrout = { outdata };
ATR_Series QL = new(bars, period: period, useNaN: false);
Tulip.Indicators.atr.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
//Tulip ATR doesn't use warm-up SMA, compensating with 200 warming bars
for (int i = QL.Length - 1; i > 200 + skip; i--)
{
for (int i = QL.Length - 1; i > 200 + skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void BBANDS()
{
public void BBANDS() {
double[][] arrin = { inclose };
double[] outmid = new double[bars.Count];
double[] outlower = new double[bars.Count];
@@ -100,8 +89,7 @@ public class Tulip_Test
double[][] arrout = { outlower, outmid, outupper };
BBANDS_Series QL = new(bars.Close, period, 2, false);
Tulip.Indicators.bbands.Run(inputs: arrin, options: new double[] { period, 2 }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL.Lower[i].v;
double TU_item = outlower[i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -129,130 +117,112 @@ public class Tulip_Test
}
*/
[Fact]
public void CMO()
{
public void CMO() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
CMO_Series QL = new(bars.Close, period, useNaN: false);
Tulip.Indicators.cmo.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void DECAY()
{
public void DECAY() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
DECAY_Series QL = new(bars.Close, period, useNaN: false);
Tulip.Indicators.decay.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip + 200; i--)
{
for (int i = QL.Length - 1; i > skip + 200; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void DEMA()
{
public void DEMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
DEMA_Series QL = new(bars.Close, period, useNaN: false, useSMA: false);
Tulip.Indicators.dema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip + 200; i--)
{
for (int i = QL.Length - 1; i > skip + 200; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - (period + period - 2)];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void DIV()
{
public void DIV() {
double[][] arrin = { inhigh, inlow };
double[][] arrout = { outdata };
DIV_Series QL = new(bars.High, bars.Low);
Tulip.Indicators.div.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void EDECAY()
{
public void EDECAY() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
DECAY_Series QL = new(bars.Close, period, exponential: true, useNaN: false);
Tulip.Indicators.edecay.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip + 200; i--)
{
for (int i = QL.Length - 1; i > skip + 200; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void EMA()
{
public void EMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
// Tulip EMA doesn't use SMA to warm-up
EMA_Series QL = new(bars.Close, period, false, useSMA: false);
Tulip.Indicators.ema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void HL2()
{
public void HL2() {
double[][] arrin = { inhigh, inlow };
double[][] arrout = { outdata };
TSeries QL = bars.HL2;
Tulip.Indicators.medprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void HLC3()
{
public void HLC3() {
double[][] arrin = { inhigh, inlow, inclose };
double[][] arrout = { outdata };
TSeries QL = bars.HLC3;
Tulip.Indicators.typprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void HLCC4()
{
public void HLCC4() {
double[][] arrin = { inhigh, inlow, inclose };
double[][] arrout = { outdata };
TSeries QL = bars.HLCC4;
Tulip.Indicators.wcprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -260,15 +230,13 @@ public class Tulip_Test
}
[Fact]
public void HMA()
{
public void HMA() {
int p = 10;
double[][] arrin = { inclose };
double[][] arrout = { outdata };
HMA_Series QL = new(bars.Close, p, false);
Tulip.Indicators.hma.Run(inputs: arrin, options: new double[] { p }, outputs: arrout);
for (int i = QL.Length - 1; i > skip + 2; i--)
{
for (int i = QL.Length - 1; i > skip + 2; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - p - 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits - 2), Math.Exp(-digits - 2));
@@ -276,14 +244,12 @@ public class Tulip_Test
}
[Fact]
public void KAMA()
{
public void KAMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
KAMA_Series QL = new(bars.Close, period);
Tulip.Indicators.kama.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > 250; i--)
{
for (int i = QL.Length - 1; i > 250; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -291,22 +257,19 @@ public class Tulip_Test
}
[Fact]
public void LINREG()
{
public void LINREG() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
SLOPE_Series QL = new(bars.Close, period);
Tulip.Indicators.linregslope.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MACD()
{
public void MACD() {
double[] outsignal = new double[bars.Count];
double[] outhist = new double[bars.Count];
@@ -314,205 +277,176 @@ public class Tulip_Test
double[][] arrout = { outdata, outsignal, outhist };
MACD_Series QL = new(bars.Close, slow: 26, fast: 10, signal: 9);
Tulip.Indicators.macd.Run(inputs: arrin, options: new double[] { 10, 26, 9 }, outputs: arrout);
for (int i = QL.Length - 1; i > 150; i--)
{
for (int i = QL.Length - 1; i > 150; i--) {
double QL_item = QL[i].v;
double TU_item = outdata[i - 26 + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MAX()
{
public void MAX() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
MAX_Series QL = new(bars.Close, period, false);
Tulip.Indicators.max.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MIN()
{
public void MIN() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
MIN_Series QL = new(bars.Close, period, false);
Tulip.Indicators.min.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void MUL()
{
public void MUL() {
double[][] arrin = { inhigh, inlow };
double[][] arrout = { outdata };
MUL_Series QL = new(bars.High, bars.Low);
Tulip.Indicators.mul.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void OBV()
{
public void OBV() {
double[][] arrin = { inclose, involume };
double[][] arrout = { outdata };
OBV_Series QL = new(bars, period, false);
Tulip.Indicators.obv.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i] + arrin[1][0];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void OHLC4()
{
public void OHLC4() {
double[][] arrin = { inopen, inhigh, inlow, inclose };
double[][] arrout = { outdata };
TSeries QL = bars.OHLC4;
Tulip.Indicators.avgprice.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void RMA()
{
public void RMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
RMA_Series QL = new(bars.Close, period, false);
Tulip.Indicators.wilders.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void RSI()
{
public void RSI() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
RSI_Series QL = new(bars.Close, period, false);
Tulip.Indicators.rsi.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SMA()
{
public void SMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
SMA_Series QL = new(bars.Close, period, false);
Tulip.Indicators.sma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SDEV()
{
public void SDEV() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
SDEV_Series QL = new(bars.Close, period, false);
Tulip.Indicators.stddev.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SUB()
{
public void SUB() {
double[][] arrin = { inhigh, inlow };
double[][] arrout = { outdata };
SUB_Series QL = new(bars.High, bars.Low);
Tulip.Indicators.sub.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void SUM()
{
public void SUM() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
CUSUM_Series QL = new(bars.Close, period, false);
Tulip.Indicators.sum.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TR()
{
public void TR() {
double[][] arrin = { inhigh, inlow, inclose };
double[][] arrout = { outdata };
TR_Series QL = new(bars);
Tulip.Indicators.tr.Run(inputs: arrin, options: new double[] { }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TEMA()
{
public void TEMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
TEMA_Series QL = new(bars.Close, period, false);
Tulip.Indicators.tema.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip + 200; i--)
{
for (int i = QL.Length - 1; i > skip + 200; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - (period - 1) * 3];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void TRIMA()
{
public void TRIMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
TRIMA_Series QL = new(bars.Close, period, false);
Tulip.Indicators.trima.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
@@ -533,43 +467,37 @@ public class Tulip_Test
}
*/
[Fact]
public void VAR()
{
public void VAR() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
VAR_Series QL = new(bars.Close, period, false);
Tulip.Indicators.var.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void WMA()
{
public void WMA() {
double[][] arrin = { inclose };
double[][] arrout = { outdata };
WMA_Series QL = new(bars.Close, period, false);
Tulip.Indicators.wma.Run(inputs: arrin, options: new double[] { period }, outputs: arrout);
for (int i = QL.Length - 1; i > skip; i--)
{
for (int i = QL.Length - 1; i > skip; i--) {
double QL_item = QL[i].v;
double TU_item = arrout[0][i - period + 1];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits), Math.Exp(-digits));
}
}
[Fact]
public void ZLEMA()
{
public void ZLEMA() {
int p = 4;
double[][] arrin = { inclose };
double[][] arrout = { outdata };
ZLEMA_Series QL = new(bars.Close, p, false);
Tulip.Indicators.zlema.Run(inputs: arrin, options: new double[] { p }, outputs: arrout);
for (int i = QL.Length - 1; i > skip + 20; i--)
{
for (int i = QL.Length - 1; i > skip + 20; i--) {
double QL_item = QL[i].v;
double TU_item = outdata[i];
Assert.InRange(TU_item! - QL_item, -Math.Exp(-digits - 2), Math.Exp(-digits - 2));
+2 -2
View File
@@ -52,13 +52,13 @@ public class Dsma : AbstractBase
// SuperSmoother filter coefficients
double _a1 = Math.Exp(-1.414 * Math.PI / (0.5 * period));
double _b1 = 2 * _a1 * Math.Cos(1.414 * Math.PI / (0.5 * period));
_c2 = _b1;
_c3 = -_a1 * _a1;
_c1 = 1 - _c2 - _c3;
Name = "Dsma";
WarmupPeriod = (int) (period * 1.5); // A conservative estimate
WarmupPeriod = (int)(period * 1.5); // A conservative estimate
Init();
}
+1 -1
View File
@@ -45,7 +45,7 @@ namespace QuanTAlib
protected override double Calculation()
{
ManageState(Input.IsNew);
_buffer.Add(Input.Value, Input.IsNew);
if (_buffer.Count < _period)
+5 -2
View File
@@ -40,7 +40,9 @@ public class Mgdi : AbstractBase
{
_p_prevMd = _prevMd;
_index++;
} else {
}
else
{
_prevMd = _p_prevMd;
}
}
@@ -50,7 +52,8 @@ public class Mgdi : AbstractBase
ManageState(Input.IsNew);
double value = Input.Value;
if (_index < 2){
if (_index < 2)
{
_prevMd = value;
}
else
+3 -3
View File
@@ -6,9 +6,9 @@ public class Qema : AbstractBase
private readonly Ema _ema1, _ema2, _ema3, _ema4;
private double _lastQema, _p_lastQema;
public Qema(double k1=0.2, double k2=0.2, double k3=0.2, double k4=0.2) : base()
public Qema(double k1 = 0.2, double k2 = 0.2, double k3 = 0.2, double k4 = 0.2) : base()
{
if (k1 <= 0 || k2 <= 0 || k3 <= 0 || k4 <= 0 )
if (k1 <= 0 || k2 <= 0 || k3 <= 0 || k4 <= 0)
{
throw new ArgumentOutOfRangeException("All k values must be in the range (0, 1].");
}
@@ -26,7 +26,7 @@ public class Qema : AbstractBase
Name = $"QEMA ({k1:F2},{k2:F2},{k3:F2},{k4:F2})";
double smK = Math.Min(Math.Min(_k1, _k2), Math.Min(_k3, _k4));
WarmupPeriod = (int) ((2 - smK) / smK);
WarmupPeriod = (int)((2 - smK) / smK);
Init();
}
+71 -55
View File
@@ -1,65 +1,81 @@
using System;
using System.Runtime.CompilerServices;
namespace QuanTAlib {
namespace QuanTAlib
{
public class Rma : AbstractBase {
private readonly int _period;
private double _alpha;
private double _lastRMA;
private double _savedLastRMA;
public class Rma : AbstractBase
{
private readonly int _period;
private double _alpha;
private double _lastRMA;
private double _savedLastRMA;
public Rma(int period) : base() {
if (period < 1) {
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
}
_period = period;
WarmupPeriod = period * 2;
_alpha = 1.0 / _period; // Wilder's smoothing factor
Name = $"Rma({_period})";
Init();
}
public Rma(object source, int period) : this(period) {
var pubEvent = source.GetType().GetEvent("Pub");
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
}
public override void Init() {
base.Init();
_lastRMA = 0;
_savedLastRMA = 0;
}
protected override void ManageState(bool isNew) {
if (isNew) {
_savedLastRMA = _lastRMA;
_lastValidValue = Input.Value;
_index++;
} else {
_lastRMA = _savedLastRMA;
}
}
protected override double Calculation() {
ManageState(Input.IsNew);
double rma;
if (_index == 1) {
rma = Input.Value;
} else if (_index <= _period) {
// Simple average during initial period
rma = (_lastRMA * (_index - 1) + Input.Value) / _index;
} else {
// Wilder's smoothing method
rma = _alpha * (Input.Value - _lastRMA) + _lastRMA;
public Rma(int period) : base()
{
if (period < 1)
{
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
}
_period = period;
WarmupPeriod = period * 2;
_alpha = 1.0 / _period; // Wilder's smoothing factor
Name = $"Rma({_period})";
Init();
}
_lastRMA = rma;
IsHot = _index >= WarmupPeriod;
public Rma(object source, int period) : this(period)
{
var pubEvent = source.GetType().GetEvent("Pub");
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
}
return rma;
public override void Init()
{
base.Init();
_lastRMA = 0;
_savedLastRMA = 0;
}
protected override void ManageState(bool isNew)
{
if (isNew)
{
_savedLastRMA = _lastRMA;
_lastValidValue = Input.Value;
_index++;
}
else
{
_lastRMA = _savedLastRMA;
}
}
protected override double Calculation()
{
ManageState(Input.IsNew);
double rma;
if (_index == 1)
{
rma = Input.Value;
}
else if (_index <= _period)
{
// Simple average during initial period
rma = (_lastRMA * (_index - 1) + Input.Value) / _index;
}
else
{
// Wilder's smoothing method
rma = _alpha * (Input.Value - _lastRMA) + _lastRMA;
}
_lastRMA = rma;
IsHot = _index >= WarmupPeriod;
return rma;
}
}
}
}
+27 -12
View File
@@ -1,6 +1,7 @@
namespace QuanTAlib;
public class T3 : AbstractBase {
public class T3 : AbstractBase
{
private readonly int _period;
private readonly double _vfactor;
private readonly bool _useSma;
@@ -9,8 +10,10 @@ public class T3 : AbstractBase {
private double _lastEma1, _lastEma2, _lastEma3, _lastEma4, _lastEma5, _lastEma6;
private double _p_lastEma1, _p_lastEma2, _p_lastEma3, _p_lastEma4, _p_lastEma5, _p_lastEma6;
public T3(int period, double vfactor = 0.7, bool useSma = true) {
if (period < 1) {
public T3(int period, double vfactor = 0.7, bool useSma = true)
{
if (period < 1)
{
throw new ArgumentException("Period must be greater than or equal to 1.", nameof(period));
}
_period = period;
@@ -37,12 +40,14 @@ public class T3 : AbstractBase {
Init();
}
public T3(object source, int period, double vfactor = 0.7, bool useSma = true) : this(period, vfactor, useSma) {
public T3(object source, int period, double vfactor = 0.7, bool useSma = true) : this(period, vfactor, useSma)
{
var pubEvent = source.GetType().GetEvent("Pub");
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
}
public override void Init() {
public override void Init()
{
_lastEma1 = _lastEma2 = _lastEma3 = _lastEma4 = _lastEma5 = _lastEma6 = 0;
_buffer1.Clear();
_buffer2.Clear();
@@ -52,8 +57,10 @@ public class T3 : AbstractBase {
_buffer6.Clear();
}
protected override void ManageState(bool isNew) {
if (isNew) {
protected override void ManageState(bool isNew)
{
if (isNew)
{
_lastValidValue = Input.Value;
_index++;
_p_lastEma1 = _lastEma1;
@@ -62,7 +69,9 @@ public class T3 : AbstractBase {
_p_lastEma4 = _lastEma4;
_p_lastEma5 = _lastEma5;
_p_lastEma6 = _lastEma6;
} else {
}
else
{
_lastEma1 = _p_lastEma1;
_lastEma2 = _p_lastEma2;
_lastEma3 = _p_lastEma3;
@@ -73,14 +82,18 @@ public class T3 : AbstractBase {
}
protected override double Calculation() {
protected override double Calculation()
{
ManageState(Input.IsNew);
double ema1, ema2, ema3, ema4, ema5, ema6;
if (_index == 1) {
if (_index == 1)
{
ema1 = ema2 = ema3 = ema4 = ema5 = ema6 = Input.Value;
} else if (_index <= _period && _useSma) {
}
else if (_index <= _period && _useSma)
{
_buffer1.Add(Input.Value, Input.IsNew);
ema1 = _buffer1.Average();
_buffer2.Add(ema1, Input.IsNew);
@@ -93,7 +106,9 @@ public class T3 : AbstractBase {
ema5 = _buffer5.Average();
_buffer6.Add(ema5, Input.IsNew);
ema6 = _buffer6.Average();
} else {
}
else
{
ema1 = _k * (Input.Value - _lastEma1) + _lastEma1;
ema2 = _k * (ema1 - _lastEma2) + _lastEma2;
ema3 = _k * (ema2 - _lastEma3) + _lastEma3;
+1 -1
View File
@@ -58,7 +58,7 @@ public class Tema : AbstractBase
{
double result, _ema1, _ema2, _ema3;
ManageState(Input.IsNew);
_e = (_e > 1e-10) ? (1 - _k) * _e : 0;
double _invE = (_e > 1e-10) ? 1 / (1 - _e) : 1;
+1 -1
View File
@@ -55,7 +55,7 @@ public class Zlema : AbstractBase
protected override double Calculation()
{
ManageState(Input.IsNew);
_buffer!.Add(Input.Value, Input.IsNew);
int lag = Math.Max(Math.Min((int)((_period - 1) * 0.5), _buffer.Count - 1), 0) + 1;
+14 -7
View File
@@ -8,7 +8,8 @@ namespace QuanTAlib;
/// and methods used by inheriting indicator types. It handles the basic flow of
/// receiving bar data, performing calculations, and publishing results.
/// </remarks>
public abstract class AbstractBarBase : iTValue {
public abstract class AbstractBarBase : iTValue
{
public DateTime Time { get; set; }
public double Value { get; set; }
public bool IsNew { get; set; }
@@ -20,7 +21,8 @@ public abstract class AbstractBarBase : iTValue {
public event ValueSignal Pub = delegate { };
protected int _index;
protected double _lastValidValue;
protected AbstractBarBase() {
protected AbstractBarBase()
{
// Add parameters into constructor if needed
}
@@ -34,7 +36,8 @@ public abstract class AbstractBarBase : iTValue {
/// <summary>
/// Initializes the indicator's state.
/// </summary>
public virtual void Init() {
public virtual void Init()
{
_index = 0;
_lastValidValue = 0;
}
@@ -44,9 +47,11 @@ public abstract class AbstractBarBase : iTValue {
/// </summary>
/// <param name="input">The input bar data.</param>
/// <returns>A TValue containing the calculated result.</returns>
public virtual TValue Calc(TBar input) {
public virtual TValue Calc(TBar input)
{
Input = input;
if (double.IsNaN(input.Close) || double.IsInfinity(input.Close)) {
if (double.IsNaN(input.Close) || double.IsInfinity(input.Close))
{
return Process(new TValue(Time: input.Time, Value: GetLastValid(), IsNew: input.IsNew, IsHot: true));
}
this.Value = Calculation();
@@ -57,7 +62,8 @@ public abstract class AbstractBarBase : iTValue {
/// Retrieves the last valid calculated value.
/// </summary>
/// <returns>The last valid value of the indicator.</returns>
protected virtual double GetLastValid() {
protected virtual double GetLastValid()
{
return this.Value;
}
@@ -79,7 +85,8 @@ public abstract class AbstractBarBase : iTValue {
/// </summary>
/// <param name="value">The calculated TValue to process.</param>
/// <returns>The processed TValue.</returns>
protected virtual TValue Process(TValue value) {
protected virtual TValue Process(TValue value)
{
this.Time = value.Time;
this.Value = value.Value;
this.IsNew = value.IsNew;
+96 -46
View File
@@ -12,7 +12,8 @@ namespace QuanTAlib;
/// a fixed-size buffer of double values. It uses SIMD operations for improved performance
/// on supported hardware.
/// </remarks>
public class CircularBuffer : IEnumerable<double> {
public class CircularBuffer : IEnumerable<double>
{
private readonly double[] _buffer;
private int _start = 0;
private int _size = 0;
@@ -31,7 +32,8 @@ public class CircularBuffer : IEnumerable<double> {
/// Initializes a new instance of the CircularBuffer class with the specified capacity.
/// </summary>
/// <param name="capacity">The maximum number of elements the buffer can hold.</param>
public CircularBuffer(int capacity) {
public CircularBuffer(int capacity)
{
Capacity = capacity;
_buffer = GC.AllocateArray<double>(capacity, pinned: true);
}
@@ -42,16 +44,23 @@ public class CircularBuffer : IEnumerable<double> {
/// <param name="item">The item to add to the buffer.</param>
/// <param name="isNew">Indicates whether the item is a new value or an update to the last added value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(double item, bool isNew = true) {
if (_size == 0 || isNew) {
if (_size < Capacity) {
public void Add(double item, bool isNew = true)
{
if (_size == 0 || isNew)
{
if (_size < Capacity)
{
_buffer[(_start + _size) % Capacity] = item;
_size++;
} else {
}
else
{
_buffer[_start] = item;
_start = (_start + 1) % Capacity;
}
} else {
}
else
{
_buffer[(_start + _size - 1) % Capacity] = item;
}
}
@@ -61,15 +70,18 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <param name="index">The zero-based index of the element to get or set.</param>
/// <returns>The element at the specified index.</returns>
public double this[Index index] {
public double this[Index index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
get
{
int actualIndex = index.IsFromEnd ? _size - index.Value : index.Value;
actualIndex = Math.Clamp(actualIndex, 0, _size - 1);
return _buffer[(_start + actualIndex) % Capacity];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set {
set
{
int actualIndex = index.IsFromEnd ? _size - index.Value : index.Value;
actualIndex = Math.Clamp(actualIndex, 0, _size - 1);
_buffer[(_start + actualIndex) % Capacity] = value;
@@ -77,7 +89,8 @@ public class CircularBuffer : IEnumerable<double> {
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowArgumentOutOfRangeException() {
private static void ThrowArgumentOutOfRangeException()
{
throw new ArgumentOutOfRangeException("index", "Index is out of range.");
}
@@ -86,7 +99,8 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>The newest element in the buffer.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Newest() {
public double Newest()
{
if (_size == 0)
return 0;
return _buffer[(_start + _size - 1) % Capacity];
@@ -97,14 +111,16 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>The oldest element in the buffer.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Oldest() {
public double Oldest()
{
if (_size == 0)
ThrowInvalidOperationException();
return _buffer[_start];
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInvalidOperationException() {
private static void ThrowInvalidOperationException()
{
throw new InvalidOperationException("Buffer is empty.");
}
@@ -119,13 +135,15 @@ public class CircularBuffer : IEnumerable<double> {
/// <summary>
/// Represents an enumerator for the CircularBuffer.
/// </summary>
public struct Enumerator : IEnumerator<double> {
public struct Enumerator : IEnumerator<double>
{
private readonly CircularBuffer _buffer;
private int _index;
private double _current;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Enumerator(CircularBuffer buffer) {
internal Enumerator(CircularBuffer buffer)
{
_buffer = buffer;
_index = -1;
_current = default;
@@ -136,7 +154,8 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext() {
public bool MoveNext()
{
if (_index + 1 >= _buffer._size)
return false;
@@ -154,7 +173,8 @@ public class CircularBuffer : IEnumerable<double> {
/// <summary>
/// Sets the enumerator to its initial position, which is before the first element in the buffer.
/// </summary>
public void Reset() {
public void Reset()
{
_index = -1;
_current = default;
}
@@ -171,13 +191,17 @@ public class CircularBuffer : IEnumerable<double> {
/// <param name="destination">The one-dimensional array that is the destination of the elements copied from the buffer.</param>
/// <param name="destinationIndex">The zero-based index in array at which copying begins.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(double[] destination, int destinationIndex) {
public void CopyTo(double[] destination, int destinationIndex)
{
if (_size == 0)
return;
if (_start + _size <= Capacity) {
if (_start + _size <= Capacity)
{
Array.Copy(_buffer, _start, destination, destinationIndex, _size);
} else {
}
else
{
int firstPartLength = Capacity - _start;
Array.Copy(_buffer, _start, destination, destinationIndex, firstPartLength);
Array.Copy(_buffer, 0, destination, destinationIndex + firstPartLength, _size - firstPartLength);
@@ -189,13 +213,17 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>A read-only span over the buffer contents.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpan<double> GetSpan() {
public ReadOnlySpan<double> GetSpan()
{
if (_size == 0)
return ReadOnlySpan<double>.Empty;
if (_start + _size <= Capacity) {
if (_start + _size <= Capacity)
{
return new ReadOnlySpan<double>(_buffer, _start, _size);
} else {
}
else
{
return new ReadOnlySpan<double>(ToArray());
}
}
@@ -216,7 +244,8 @@ public class CircularBuffer : IEnumerable<double> {
/// Removes all elements from the buffer.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear() {
public void Clear()
{
Array.Clear(_buffer, 0, _buffer.Length);
_start = 0;
_size = 0;
@@ -227,7 +256,8 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>The maximum value in the buffer.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Max() {
public double Max()
{
if (_size == 0)
ThrowInvalidOperationException();
@@ -239,7 +269,8 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>The minimum value in the buffer.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Min() {
public double Min()
{
if (_size == 0)
ThrowInvalidOperationException();
@@ -251,7 +282,8 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>The sum of all values in the buffer.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Sum() {
public double Sum()
{
return SumSimd();
}
@@ -260,7 +292,8 @@ public class CircularBuffer : IEnumerable<double> {
/// </summary>
/// <returns>The average of all values in the buffer.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public double Average() {
public double Average()
{
if (_size == 0)
ThrowInvalidOperationException();
@@ -268,22 +301,26 @@ public class CircularBuffer : IEnumerable<double> {
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double MaxSimd() {
private double MaxSimd()
{
var span = GetSpan();
var vectorSize = Vector<double>.Count;
var maxVector = new Vector<double>(double.MinValue);
int i = 0;
for (; i <= span.Length - vectorSize; i += vectorSize) {
for (; i <= span.Length - vectorSize; i += vectorSize)
{
maxVector = Vector.Max(maxVector, new Vector<double>(span.Slice(i, vectorSize)));
}
double max = double.MinValue;
for (int j = 0; j < vectorSize; j++) {
for (int j = 0; j < vectorSize; j++)
{
max = Math.Max(max, maxVector[j]);
}
for (; i < span.Length; i++) {
for (; i < span.Length; i++)
{
max = Math.Max(max, span[i]);
}
@@ -291,22 +328,26 @@ public class CircularBuffer : IEnumerable<double> {
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double MinSimd() {
private double MinSimd()
{
var span = GetSpan();
var vectorSize = Vector<double>.Count;
var minVector = new Vector<double>(double.MaxValue);
int i = 0;
for (; i <= span.Length - vectorSize; i += vectorSize) {
for (; i <= span.Length - vectorSize; i += vectorSize)
{
minVector = Vector.Min(minVector, new Vector<double>(span.Slice(i, vectorSize)));
}
double min = double.MaxValue;
for (int j = 0; j < vectorSize; j++) {
for (int j = 0; j < vectorSize; j++)
{
min = Math.Min(min, minVector[j]);
}
for (; i < span.Length; i++) {
for (; i < span.Length; i++)
{
min = Math.Min(min, span[i]);
}
@@ -314,22 +355,26 @@ public class CircularBuffer : IEnumerable<double> {
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double SumSimd() {
private double SumSimd()
{
var span = GetSpan();
var vectorSize = Vector<double>.Count;
var sumVector = Vector<double>.Zero;
int i = 0;
for (; i <= span.Length - vectorSize; i += vectorSize) {
for (; i <= span.Length - vectorSize; i += vectorSize)
{
sumVector += new Vector<double>(span.Slice(i, vectorSize));
}
double sum = 0;
for (int j = 0; j < vectorSize; j++) {
for (int j = 0; j < vectorSize; j++)
{
sum += sumVector[j];
}
for (; i < span.Length; i++) {
for (; i < span.Length; i++)
{
sum += span[i];
}
@@ -340,7 +385,8 @@ public class CircularBuffer : IEnumerable<double> {
/// Copies the buffer elements to a new array.
/// </summary>
/// <returns>An array containing copies of the buffer elements.</returns>
public double[] ToArray() {
public double[] ToArray()
{
double[] array = new double[_size];
CopyTo(array, 0);
return array;
@@ -350,10 +396,12 @@ public class CircularBuffer : IEnumerable<double> {
/// Performs a parallel operation on the buffer elements.
/// </summary>
/// <param name="operation">The operation to perform on each partition of the buffer.</param>
public void ParallelOperation(Func<double[], int, int, double> operation) {
public void ParallelOperation(Func<double[], int, int, double> operation)
{
const int MinimumPartitionSize = 1024;
if (_size < MinimumPartitionSize) {
if (_size < MinimumPartitionSize)
{
var span = GetSpan();
var array = span.ToArray();
operation(array, 0, array.Length);
@@ -363,7 +411,8 @@ public class CircularBuffer : IEnumerable<double> {
int partitionCount = Environment.ProcessorCount;
int partitionSize = _size / partitionCount;
if (partitionSize < MinimumPartitionSize) {
if (partitionSize < MinimumPartitionSize)
{
partitionCount = Math.Max(1, _size / MinimumPartitionSize);
partitionSize = _size / partitionCount;
}
@@ -371,7 +420,8 @@ public class CircularBuffer : IEnumerable<double> {
var buffer = ToArray();
var results = new double[partitionCount];
Parallel.For(0, partitionCount, i => {
Parallel.For(0, partitionCount, i =>
{
int start = i * partitionSize;
int length = (i == partitionCount - 1) ? _size - start : partitionSize;
results[i] = operation(buffer, start, length);
+19 -19
View File
@@ -14,28 +14,28 @@ public interface iTBar
public readonly record struct TBar(DateTime Time, double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : iTBar
{
public DateTime Time { get; init; } = Time;
public double Open { get; init; } = Open;
public double High { get; init; } = High;
public double Low { get; init; } = Low;
public double Close { get; init; } = Close;
public double Volume { get; init; } = Volume;
public bool IsNew { get; init; } = IsNew;
public double Open { get; init; } = Open;
public double High { get; init; } = High;
public double Low { get; init; } = Low;
public double Close { get; init; } = Close;
public double Volume { get; init; } = Volume;
public bool IsNew { get; init; } = IsNew;
public double HL2 => (High + Low) * 0.5;
public double OC2 => (Open + Close) * 0.5;
public double OHL3 => (Open + High + Low) / 3;
public double HLC3 => (High + Low + Close) / 3;
public double OHLC4 => (Open + High + Low + Close) * 0.25;
public double HLCC4 => (High + Low + Close + Close) * 0.25;
public double HL2 => (High + Low) * 0.5;
public double OC2 => (Open + Close) * 0.5;
public double OHL3 => (Open + High + Low) / 3;
public double HLC3 => (High + Low + Close) / 3;
public double OHLC4 => (Open + High + Low + Close) * 0.25;
public double HLCC4 => (High + Low + Close + Close) * 0.25;
public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { }
public TBar(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : this(DateTime.UtcNow, Open, High, Low, Close, Volume, IsNew) { }
public TBar(double value) : this(Time: DateTime.UtcNow, Open: value, High: value, Low: value, Close: value, Volume: value, IsNew: true) { }
public TBar(TValue value) : this(Time: value.Time, Open: value.Value, High: value.Value, Low: value.Value, Close: value.Value, Volume: value.Value, IsNew: value.IsNew) { }
public TBar() : this(DateTime.UtcNow, 0, 0, 0, 0, 0) { }
public TBar(double Open, double High, double Low, double Close, double Volume, bool IsNew = true) : this(DateTime.UtcNow, Open, High, Low, Close, Volume, IsNew) { }
public TBar(double value) : this(Time: DateTime.UtcNow, Open: value, High: value, Low: value, Close: value, Volume: value, IsNew: true) { }
public TBar(TValue value) : this(Time: value.Time, Open: value.Value, High: value.Value, Low: value.Value, Close: value.Value, Volume: value.Value, IsNew: value.IsNew) { }
public static implicit operator double(TBar bar) => bar.Close;
public static implicit operator DateTime(TBar tv) => tv.Time;
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]";
public static implicit operator double(TBar bar) => bar.Close;
public static implicit operator DateTime(TBar tv) => tv.Time;
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]";
}
public delegate void BarSignal(object source, in TBarEventArgs args);

Some files were not shown because too many files have changed in this diff Show More