mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-29 10:07:43 +00:00
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:
committed by
GitHub
parent
ed45c9e5b8
commit
40842ba5fc
@@ -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
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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); }
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace QuanTAlib
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
|
||||
_buffer.Add(Input.Value, Input.IsNew);
|
||||
|
||||
if (_buffer.Count < _period)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user