diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj
index 44158e8a..974ec457 100644
--- a/Tests/Tests.csproj
+++ b/Tests/Tests.csproj
@@ -33,7 +33,6 @@
-
diff --git a/Tests/test_skender.stock.cs b/Tests/test_skender.stock.cs
index 7c7fe3d5..fabc63db 100644
--- a/Tests/test_skender.stock.cs
+++ b/Tests/test_skender.stock.cs
@@ -13,10 +13,9 @@ public class SkenderTests
private readonly Random rnd;
private readonly double range;
private int period;
- private readonly int iterations;
+ private readonly int iterations = 3; // Initialized directly at declaration
private readonly IEnumerable quotes;
-
public SkenderTests()
{
rnd = new((int)DateTime.Now.Ticks);
@@ -24,7 +23,6 @@ public class SkenderTests
bars = new(feed);
range = 1e-9;
feed.Add(10000);
- iterations = 3;
quotes = bars.Select(q => new Quote
{
Date = q.Time,
@@ -338,15 +336,11 @@ public class SkenderTests
var atrValues = quotes.GetAtr(lookbackPeriods: period).Select(i => i.Atr.Null2NaN()!);
const int AdditionalPeriods = 500;
-<<<<<<< HEAD
- for (int i = QL.Length - 1; i > period + 500; i--)
-=======
for (int i = QL.Length - 1; i > period + AdditionalPeriods; i--)
->>>>>>> dev
{
Assert.InRange(atrValues.ElementAt(i) - QL[i].Value, -range, range);
}
}
}
-}
\ No newline at end of file
+}
diff --git a/lib/averages/Frama.cs b/lib/averages/Frama.cs
index 89733302..223b1458 100644
--- a/lib/averages/Frama.cs
+++ b/lib/averages/Frama.cs
@@ -81,16 +81,8 @@ public class Frama : AbstractBase
}
}
-<<<<<<< HEAD
- protected override double Calculation()
- {
- ManageState(Input.IsNew);
-
- _buffer.Add(Input.Value, Input.IsNew);
-=======
double n1 = (hh - ll) / _period;
double n2 = (hh1 - ll1 + hh2 - ll2) / (_period / 2);
->>>>>>> dev
double d = (Math.Log(n2 + double.Epsilon) - Math.Log(n1 + double.Epsilon)) / Math.Log(2);
diff --git a/lib/averages/Qema.cs b/lib/averages/Qema.cs
index 76d1f96f..d09e6ef0 100644
--- a/lib/averages/Qema.cs
+++ b/lib/averages/Qema.cs
@@ -2,33 +2,24 @@ namespace QuanTAlib;
public class Qema : AbstractBase
{
- private readonly double _k1, _k2, _k3, _k4;
+
private readonly Ema _ema1, _ema2, _ema3, _ema4;
private double _lastQema, _p_lastQema;
-<<<<<<< HEAD
- 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)
->>>>>>> dev
{
if (k1 <= 0 || k2 <= 0 || k3 <= 0 || k4 <= 0)
{
- throw new ArgumentOutOfRangeException("All k values must be in the range (0, 1].");
+ throw new ArgumentOutOfRangeException(nameof(k1), "All k values must be in the range (0, 1].");
}
- _k1 = k1;
- _k2 = k2;
- _k3 = k3;
- _k4 = k4;
-
_ema1 = new Ema(k1);
_ema2 = new Ema(k2);
_ema3 = new Ema(k3);
_ema4 = new Ema(k4);
Name = $"QEMA ({k1:F2},{k2:F2},{k3:F2},{k4:F2})";
- double smK = Math.Min(Math.Min(_k1, _k2), Math.Min(_k3, _k4));
+ double smK = Math.Min(Math.Min(k1, k2), Math.Min(k3, k4));
WarmupPeriod = (int)((2 - smK) / smK);
Init();
diff --git a/lib/averages/Rma.cs b/lib/averages/Rma.cs
index d1381725..d41c19e9 100644
--- a/lib/averages/Rma.cs
+++ b/lib/averages/Rma.cs
@@ -1,45 +1,29 @@
using System;
-using System.Runtime.CompilerServices;
-<<<<<<< HEAD
-namespace QuanTAlib
-{
-
- 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));
- }
-=======
namespace QuanTAlib;
-
-
+///
+/// RMA: Relative Moving Average (also known as Wilder's Moving Average)
+/// RMA is similar to EMA but uses a different smoothing factor.
+///
+///
+/// Key characteristics:
+/// - Uses no buffer, relying only on the previous RMA value.
+/// - The weight of new data points (alpha) is calculated as 1 / period.
+/// - Provides a smoother curve compared to SMA and EMA, reacting more slowly to price changes.
+///
+/// Calculation method:
+/// RMA = (Previous RMA * (period - 1) + New Data) / period
+///
+/// Sources:
+/// - https://www.tradingview.com/pine-script-reference/v5/#fun_ta{dot}rma
+/// - https://www.investopedia.com/terms/w/wilders-smoothing.asp
+///
public class Rma : AbstractBase
{
private readonly int _period;
+ private double _lastRma;
private readonly double _alpha;
- private double _lastRMA;
- private double _savedLastRMA;
+ private double _savedLastRma;
public Rma(int period)
{
@@ -63,21 +47,22 @@ public class Rma : AbstractBase
public override void Init()
{
base.Init();
- _lastRMA = 0;
- _savedLastRMA = 0;
+ _lastRma = 0;
+ _savedLastRma = 0;
}
protected override void ManageState(bool isNew)
{
- if (!isNew)
+ if (isNew)
{
- _lastRMA = _savedLastRMA;
- return;
+ _savedLastRma = _lastRma;
+ _lastValidValue = Input.Value;
+ _index++;
+ }
+ else
+ {
+ _lastRma = _savedLastRma;
}
-
- _savedLastRMA = _lastRMA;
- _lastValidValue = Input.Value;
- _index++;
}
protected override double Calculation()
@@ -88,73 +73,22 @@ public class Rma : AbstractBase
if (_index == 1)
{
- return Input.Value;
+ rma = Input.Value;
}
-
- if (_index <= _period)
+ else if (_index <= _period)
{
// Simple average during initial period
- return (_lastRMA * (_index - 1) + Input.Value) / _index;
+ rma = (_lastRma * (_index - 1) + Input.Value) / _index;
+ }
+ else
+ {
+ // Wilder's smoothing method
+ rma = _alpha * (_lastRma - Input.Value) + _lastRma;
}
- // Wilder's smoothing method
- return _alpha * (Input.Value - _lastRMA) + _lastRMA;
- }
-
- _lastRMA = rma;
+ _lastRma = rma;
IsHot = _index >= WarmupPeriod;
->>>>>>> dev
- 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;
- }
+ return rma;
}
-<<<<<<< HEAD
}
-=======
-}
->>>>>>> dev
diff --git a/lib/core/AbstractBarBase.cs b/lib/core/AbstractBarBase.cs
index 16b9c79a..3e46d8d9 100644
--- a/lib/core/AbstractBarBase.cs
+++ b/lib/core/AbstractBarBase.cs
@@ -8,7 +8,7 @@ namespace QuanTAlib;
/// and methods used by inheriting indicator types. It handles the basic flow of
/// receiving bar data, performing calculations, and publishing results.
///
-public abstract class AbstractBarBase : iTValue
+public abstract class AbstractBarBase : ITValue
{
public DateTime Time { get; set; }
public double Value { get; set; }
diff --git a/lib/core/circularbuffer.cs b/lib/core/circularbuffer.cs
index 5a2e9c7a..42740f67 100644
--- a/lib/core/circularbuffer.cs
+++ b/lib/core/circularbuffer.cs
@@ -89,9 +89,9 @@ public class CircularBuffer : IEnumerable
}
[MethodImpl(MethodImplOptions.NoInlining)]
- private static void ThrowArgumentOutOfRangeException()
+ private static void ThrowArgumentOutOfRangeException(string paramName)
{
- throw new ArgumentOutOfRangeException("index", "Index is out of range.");
+ throw new ArgumentOutOfRangeException(paramName, "Index is out of range.");
}
///
@@ -221,13 +221,6 @@ public class CircularBuffer : IEnumerable
if (_start + _size <= Capacity)
{
return new ReadOnlySpan(_buffer, _start, _size);
-<<<<<<< HEAD
- }
- else
- {
- return new ReadOnlySpan(ToArray());
-=======
->>>>>>> dev
}
return new ReadOnlySpan(ToArray());
diff --git a/lib/feeds/GbmFeed.cs b/lib/feeds/GbmFeed.cs
index f4f93f77..f4c69a0e 100644
--- a/lib/feeds/GbmFeed.cs
+++ b/lib/feeds/GbmFeed.cs
@@ -8,11 +8,7 @@ public class GbmFeed : TBarSeries
private readonly Random _random;
private double _lastClose, _lastHigh, _lastLow;
-<<<<<<< HEAD
- public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2) : base()
-=======
public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2)
->>>>>>> dev
{
_lastClose = _lastHigh = _lastLow = initialPrice;
_mu = mu;
@@ -26,7 +22,6 @@ public class GbmFeed : TBarSeries
public void Add(int count)
{
DateTime startTime = DateTime.UtcNow - TimeSpan.FromHours(count);
- TBar lastBar = new();
for (int i = 0; i < count; i++)
{
Add(startTime, true);
diff --git a/lib/statistics/Min.cs b/lib/statistics/Min.cs
index fade78e9..6eea3fad 100644
--- a/lib/statistics/Min.cs
+++ b/lib/statistics/Min.cs
@@ -26,11 +26,7 @@ public class Min : AbstractBase
///
/// Thrown when period is less than 1 or decay is negative.
///
-<<<<<<< HEAD
- public Min(int period, double decay = 0) : base()
-=======
public Min(int period, double decay = 0)
->>>>>>> dev
{
if (period < 1)
{
diff --git a/lib/statistics/Mode.cs b/lib/statistics/Mode.cs
index 7579bf84..33438f7b 100644
--- a/lib/statistics/Mode.cs
+++ b/lib/statistics/Mode.cs
@@ -21,11 +21,7 @@ public class Mode : AbstractBase
///
/// Thrown when period is less than 1.
///
-<<<<<<< HEAD
- public Mode(int period) : base()
-=======
public Mode(int period)
->>>>>>> dev
{
if (period < 1)
{
diff --git a/lib/statistics/Percentile.cs b/lib/statistics/Percentile.cs
index b4de2b69..b15155c8 100644
--- a/lib/statistics/Percentile.cs
+++ b/lib/statistics/Percentile.cs
@@ -24,11 +24,7 @@ public class Percentile : AbstractBase
///
/// Thrown when period is less than 2 or percent is not between 0 and 100.
///
-<<<<<<< HEAD
- public Percentile(int period, double percent) : base()
-=======
public Percentile(int period, double percent)
->>>>>>> dev
{
if (period < 2)
{
diff --git a/lib/statistics/Skew.cs b/lib/statistics/Skew.cs
index babb967f..38e4e1be 100644
--- a/lib/statistics/Skew.cs
+++ b/lib/statistics/Skew.cs
@@ -22,11 +22,7 @@ public class Skew : AbstractBase
///
/// Thrown when period is less than 3.
///
-<<<<<<< HEAD
- public Skew(int period) : base()
-=======
public Skew(int period)
->>>>>>> dev
{
if (period < 3)
{
diff --git a/lib/statistics/Stddev.cs b/lib/statistics/Stddev.cs
index d7d01fd8..247413dd 100644
--- a/lib/statistics/Stddev.cs
+++ b/lib/statistics/Stddev.cs
@@ -11,7 +11,6 @@ namespace QuanTAlib;
///
public class Stddev : AbstractBase
{
- private readonly int Period;
private readonly bool IsPopulation;
private readonly CircularBuffer _buffer;
@@ -26,17 +25,12 @@ public class Stddev : AbstractBase
///
/// Thrown when period is less than 2.
///
-<<<<<<< HEAD
- public Stddev(int period, bool isPopulation = false) : base()
-=======
public Stddev(int period, bool isPopulation = false)
->>>>>>> dev
{
if (period < 2)
{
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
}
- Period = period;
IsPopulation = isPopulation;
WarmupPeriod = 0;
_buffer = new CircularBuffer(period);
diff --git a/lib/statistics/Variance.cs b/lib/statistics/Variance.cs
index a669a828..a7c6f3e0 100644
--- a/lib/statistics/Variance.cs
+++ b/lib/statistics/Variance.cs
@@ -11,7 +11,6 @@ namespace QuanTAlib;
///
public class Variance : AbstractBase
{
- private readonly int Period;
private readonly bool IsPopulation;
private readonly CircularBuffer _buffer;
@@ -26,17 +25,12 @@ public class Variance : AbstractBase
///
/// Thrown when period is less than 2.
///
-<<<<<<< HEAD
- public Variance(int period, bool isPopulation = false) : base()
-=======
public Variance(int period, bool isPopulation = false)
->>>>>>> dev
{
if (period < 2)
{
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
}
- Period = period;
IsPopulation = isPopulation;
WarmupPeriod = 0;
_buffer = new CircularBuffer(period);
diff --git a/lib/statistics/Zscore.cs b/lib/statistics/Zscore.cs
index 2a7e4664..946a8e34 100644
--- a/lib/statistics/Zscore.cs
+++ b/lib/statistics/Zscore.cs
@@ -21,11 +21,7 @@ public class Zscore : AbstractBase
///
/// Thrown when period is less than 2.
///
-<<<<<<< HEAD
- public Zscore(int period) : base()
-=======
public Zscore(int period)
->>>>>>> dev
{
if (period < 2)
{
diff --git a/lib/volatility/Atr.cs b/lib/volatility/Atr.cs
index 34df9043..e6c20845 100644
--- a/lib/volatility/Atr.cs
+++ b/lib/volatility/Atr.cs
@@ -8,11 +8,7 @@ namespace QuanTAlib;
/// of the true range. The true range is the greatest of: current high - current low,
/// absolute value of current high - previous close, or absolute value of current low - previous close.
///
-<<<<<<< HEAD
-public class Atr : AbstractBarBase
-=======
public class Atr : AbstractBase
->>>>>>> dev
{
private readonly Ema _ma;
private double _prevClose, _p_prevClose;
@@ -86,11 +82,7 @@ public class Atr : AbstractBase
///
protected override double Calculation()
{
-<<<<<<< HEAD
- ManageState(Input.IsNew);
-=======
ManageState(BarInput.IsNew);
->>>>>>> dev
double trueRange = Math.Max(
Math.Max(
@@ -101,11 +93,7 @@ public class Atr : AbstractBase
);
if (_index < 2)
{
-<<<<<<< HEAD
- trueRange = Input.High - Input.Low;
-=======
trueRange = BarInput.High - BarInput.Low;
->>>>>>> dev
}
TValue emaTrueRange = _ma.Calc(new TValue(Input.Time, trueRange, Input.IsNew));
diff --git a/lib/volatility/Historical.cs b/lib/volatility/Historical.cs
index a6fcb880..9417b14d 100644
--- a/lib/volatility/Historical.cs
+++ b/lib/volatility/Historical.cs
@@ -25,11 +25,7 @@ public class Historical : AbstractBase
///
/// Thrown when period is less than 2.
///
-<<<<<<< HEAD
- public Historical(int period, bool isAnnualized = true) : base()
-=======
public Historical(int period, bool isAnnualized = true)
->>>>>>> dev
{
if (period < 2)
{
diff --git a/lib/volatility/Realized.cs b/lib/volatility/Realized.cs
index 09dfb139..5798919b 100644
--- a/lib/volatility/Realized.cs
+++ b/lib/volatility/Realized.cs
@@ -25,11 +25,7 @@ public class Realized : AbstractBase
///
/// Thrown when period is less than 2.
///
-<<<<<<< HEAD
- public Realized(int period, bool isAnnualized = true) : base()
-=======
public Realized(int period, bool isAnnualized = true)
->>>>>>> dev
{
if (period < 2)
{
diff --git a/lib/volatility/Rvi.cs b/lib/volatility/Rvi.cs
index 35ff6824..7047176c 100644
--- a/lib/volatility/Rvi.cs
+++ b/lib/volatility/Rvi.cs
@@ -15,7 +15,6 @@ namespace QuanTAlib;
///
public class Rvi : AbstractBase
{
- private readonly int Period;
private readonly Stddev _upStdDev, _downStdDev;
private readonly Sma _upSma, _downSma;
private double _previousClose;
@@ -27,17 +26,13 @@ public class Rvi : AbstractBase
///
/// Thrown when period is less than 2.
///
-<<<<<<< HEAD
- public Rvi(int period) : base()
-=======
public Rvi(int period)
->>>>>>> dev
{
if (period < 2)
{
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 2.");
}
- Period = period;
+ int Period = period;
WarmupPeriod = period;
Name = $"RVI(period={period})";
_upStdDev = new Stddev(Period);
@@ -109,18 +104,7 @@ public class Rvi : AbstractBase
_downSma.Calc(_downStdDev.Calc(new TValue(Input.Time, downMove, Input.IsNew)));
double rvi;
-<<<<<<< HEAD
- if (_upSma.Value + _downSma.Value != 0)
- {
- rvi = 100 * _upSma.Value / (_upSma.Value + _downSma.Value);
- }
- else
- {
- rvi = 0;
- }
-=======
rvi = (_upSma.Value + _downSma.Value != 0) ? 100 * _upSma.Value / (_upSma.Value + _downSma.Value) : 0;
->>>>>>> dev
_previousClose = close;
IsHot = _index >= WarmupPeriod;