mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-06 04:57:44 +00:00
style: format code with dotnet-format
This commit fixes the style issues introduced in 931bbdb according to the output
from dotnet-format.
Details: https://github.com/mihakralj/QuanTAlib/pull/30
This commit is contained in:
committed by
GitHub
parent
931bbdb6a0
commit
85b9d9217a
@@ -53,22 +53,22 @@ public class EventingTests
|
||||
};
|
||||
|
||||
// Generate 200 random values and feed them to both direct and event-based indicators
|
||||
for (int i = 0; i < 200; i++)
|
||||
for (int i = 0; i< 200; i++)
|
||||
{
|
||||
double randomValue = random.NextDouble() * 100;
|
||||
input.Add(randomValue);
|
||||
input.Add(randomValue);
|
||||
|
||||
// Calculate direct indicators
|
||||
foreach (var (direct, _) in indicators)
|
||||
{
|
||||
direct.Calc(randomValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the results of direct and event-based calculations
|
||||
foreach (var (direct, eventBased) in indicators)
|
||||
{
|
||||
Assert.Equal(direct.Value, eventBased.Value, 9);
|
||||
}
|
||||
// Compare the results of direct and event-based calculations
|
||||
foreach (var (direct, eventBased) in indicators)
|
||||
{
|
||||
Assert.Equal(direct.Value, eventBased.Value, 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
public Qema(double k1 = 0.2, double k2 = 0.2, double k3 = 0.2, double k4 = 0.2)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -22,23 +22,23 @@ public class Rma : AbstractBase
|
||||
_alpha = 1.0 / _period; // Wilder's smoothing factor
|
||||
Name = $"Rma({_period})";
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
public Rma(object source, int period) : this(period)
|
||||
{
|
||||
public Rma(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_lastRMA = 0;
|
||||
_savedLastRMA = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (!isNew)
|
||||
{
|
||||
_lastRMA = _savedLastRMA;
|
||||
@@ -48,10 +48,10 @@ public class Rma : AbstractBase
|
||||
_savedLastRMA = _lastRMA;
|
||||
_lastValidValue = Input.Value;
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
protected override double Calculation()
|
||||
{
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(Input.IsNew);
|
||||
|
||||
double rma;
|
||||
@@ -69,9 +69,9 @@ public class Rma : AbstractBase
|
||||
|
||||
// Wilder's smoothing method
|
||||
return _alpha * (Input.Value - _lastRMA) + _lastRMA;
|
||||
}
|
||||
}
|
||||
|
||||
_lastRMA = rma;
|
||||
_lastRMA = rma;
|
||||
IsHot = _index >= WarmupPeriod;
|
||||
|
||||
return rma;
|
||||
|
||||
+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);
|
||||
|
||||
+15
-14
@@ -11,19 +11,19 @@ public interface ITValue
|
||||
public readonly record struct TValue(DateTime Time, double Value, bool IsNew = true, bool IsHot = true) : ITValue
|
||||
{
|
||||
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 DateTime t => Time;
|
||||
public double v => Value;
|
||||
public double Value { get; init; } = Value;
|
||||
public bool IsNew { get; init; } = IsNew;
|
||||
public bool IsHot { get; init; } = IsHot;
|
||||
public DateTime t => Time;
|
||||
public double v => Value;
|
||||
|
||||
public TValue() : this(DateTime.UtcNow, 0) { }
|
||||
public TValue(double value, bool isNew = true, bool isHot = true) : this(DateTime.UtcNow, value, IsNew: isNew, IsHot: isHot) { }
|
||||
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 TValue() : this(DateTime.UtcNow, 0) { }
|
||||
public TValue(double value, bool isNew = true, bool isHot = true) : this(DateTime.UtcNow, value, IsNew: isNew, IsHot: isHot) { }
|
||||
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}, IsNew: {IsNew}, IsHot: {IsHot}]";
|
||||
public override string ToString() => $"[{Time:yyyy-MM-dd HH:mm:ss}, {Value:F2}, IsNew: {IsNew}, IsHot: {IsHot}]";
|
||||
}
|
||||
|
||||
public delegate void ValueSignal(object source, in ValueEventArgs args);
|
||||
@@ -54,10 +54,11 @@ public class TSeries : List<TValue>
|
||||
{
|
||||
|
||||
var nameProperty = source.GetType().GetProperty("Name");
|
||||
if (nameProperty != null) {
|
||||
if (nameProperty != null)
|
||||
{
|
||||
Name = nameProperty.GetValue(nameProperty)?.ToString()!;
|
||||
}
|
||||
|
||||
|
||||
pubEvent.AddEventHandler(source, new ValueSignal(Sub));
|
||||
}
|
||||
}
|
||||
@@ -66,7 +67,7 @@ public class TSeries : List<TValue>
|
||||
|
||||
public new virtual void Add(TValue tick)
|
||||
{
|
||||
if (tick.IsNew || base.Count==0) { base.Add(tick); }
|
||||
if (tick.IsNew || base.Count == 0) { base.Add(tick); }
|
||||
else { this[^1] = tick; }
|
||||
Pub?.Invoke(this, new ValueEventArgs(tick));
|
||||
}
|
||||
|
||||
+56
-56
@@ -4,67 +4,67 @@ namespace QuanTAlib;
|
||||
|
||||
public class GbmFeed : TBarSeries
|
||||
{
|
||||
private readonly double _mu, _sigma;
|
||||
private readonly Random _random;
|
||||
private double _lastClose, _lastHigh, _lastLow;
|
||||
private readonly double _mu, _sigma;
|
||||
private readonly Random _random;
|
||||
private double _lastClose, _lastHigh, _lastLow;
|
||||
|
||||
public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2)
|
||||
{
|
||||
_lastClose = _lastHigh = _lastLow = initialPrice;
|
||||
_mu = mu;
|
||||
_sigma = sigma;
|
||||
_random = new Random((int)DateTime.Now.Ticks);
|
||||
this.Name = $"GBM({_sigma:F2})";
|
||||
}
|
||||
public GbmFeed(double initialPrice = 100.0, double mu = 0.05, double sigma = 0.2)
|
||||
{
|
||||
_lastClose = _lastHigh = _lastLow = initialPrice;
|
||||
_mu = mu;
|
||||
_sigma = sigma;
|
||||
_random = new Random((int)DateTime.Now.Ticks);
|
||||
this.Name = $"GBM({_sigma:F2})";
|
||||
}
|
||||
|
||||
public void Add(bool isNew = true) => Add(time: DateTime.Now, isNew: isNew);
|
||||
public void Add(DateTime time, bool isNew = true) => base.Add(Generate(time, isNew));
|
||||
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);
|
||||
Add(startTime, false);
|
||||
Add(startTime, false);
|
||||
startTime = startTime.AddHours(1);
|
||||
}
|
||||
}
|
||||
public void Add(bool isNew = true) => Add(time: DateTime.Now, isNew: isNew);
|
||||
public void Add(DateTime time, bool isNew = true) => base.Add(Generate(time, isNew));
|
||||
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);
|
||||
Add(startTime, false);
|
||||
Add(startTime, false);
|
||||
startTime = startTime.AddHours(1);
|
||||
}
|
||||
}
|
||||
|
||||
public TBar Generate(DateTime time, bool isNew = true)
|
||||
{
|
||||
double dt = 1.0 / 252;
|
||||
double drift = (_mu - 0.5 * _sigma * _sigma) * dt;
|
||||
double diffusion = _sigma * Math.Sqrt(dt) * GenerateNormalRandom();
|
||||
double newClose = _lastClose * Math.Exp(drift + diffusion);
|
||||
public TBar Generate(DateTime time, bool isNew = true)
|
||||
{
|
||||
double dt = 1.0 / 252;
|
||||
double drift = (_mu - 0.5 * _sigma * _sigma) * dt;
|
||||
double diffusion = _sigma * Math.Sqrt(dt) * GenerateNormalRandom();
|
||||
double newClose = _lastClose * Math.Exp(drift + diffusion);
|
||||
|
||||
double open = _lastClose;
|
||||
double high = Math.Max(_lastHigh, Math.Max(open, newClose) * (1 + _random.NextDouble() * 0.01));
|
||||
double low = Math.Min(_lastLow, Math.Min(open, newClose) * (1 - _random.NextDouble() * 0.01));
|
||||
double volume = 1000 + _random.NextDouble() * 1000;
|
||||
double open = _lastClose;
|
||||
double high = Math.Max(_lastHigh, Math.Max(open, newClose) * (1 + _random.NextDouble() * 0.01));
|
||||
double low = Math.Min(_lastLow, Math.Min(open, newClose) * (1 - _random.NextDouble() * 0.01));
|
||||
double volume = 1000 + _random.NextDouble() * 1000;
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
_lastClose = newClose;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = Math.Max(_lastHigh, high);
|
||||
low = Math.Min(_lastLow, low);
|
||||
}
|
||||
_lastHigh = high;
|
||||
_lastLow = low;
|
||||
if (isNew)
|
||||
{
|
||||
_lastClose = newClose;
|
||||
}
|
||||
else
|
||||
{
|
||||
high = Math.Max(_lastHigh, high);
|
||||
low = Math.Min(_lastLow, low);
|
||||
}
|
||||
_lastHigh = high;
|
||||
_lastLow = low;
|
||||
|
||||
TBar bar = new(time, open, high, low, newClose, volume, isNew);
|
||||
return bar;
|
||||
}
|
||||
TBar bar = new(time, open, high, low, newClose, volume, isNew);
|
||||
return bar;
|
||||
}
|
||||
|
||||
private double GenerateNormalRandom()
|
||||
{
|
||||
// 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();
|
||||
return Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
|
||||
}
|
||||
private double GenerateNormalRandom()
|
||||
{
|
||||
// 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();
|
||||
return Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
|
||||
}
|
||||
}
|
||||
+22
-11
@@ -8,7 +8,8 @@ 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.
|
||||
/// </remarks>
|
||||
public class Atr : AbstractBase {
|
||||
public class Atr : AbstractBase
|
||||
{
|
||||
private readonly Ema _ma;
|
||||
private double _prevClose, _p_prevClose;
|
||||
|
||||
@@ -19,11 +20,13 @@ public class Atr : AbstractBase {
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// Thrown when period is less than 1.
|
||||
/// </exception>
|
||||
public Atr(int period) {
|
||||
if (period < 1) {
|
||||
public Atr(int period)
|
||||
{
|
||||
if (period < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
||||
}
|
||||
_ma = new(1.0/period);
|
||||
_ma = new(1.0 / period);
|
||||
WarmupPeriod = _ma.WarmupPeriod;
|
||||
Name = $"ATR({period})";
|
||||
}
|
||||
@@ -33,7 +36,8 @@ public class Atr : AbstractBase {
|
||||
/// </summary>
|
||||
/// <param name="source">The source object to subscribe to for bar updates.</param>
|
||||
/// <param name="period">The period over which to calculate the ATR.</param>
|
||||
public Atr(object source, int period) : this(period) {
|
||||
public Atr(object source, int period) : this(period)
|
||||
{
|
||||
var pubEvent = source.GetType().GetEvent("Pub");
|
||||
pubEvent?.AddEventHandler(source, new BarSignal(Sub));
|
||||
}
|
||||
@@ -41,7 +45,8 @@ public class Atr : AbstractBase {
|
||||
/// <summary>
|
||||
/// Initializes the Atr instance by setting up the initial state.
|
||||
/// </summary>
|
||||
public override void Init() {
|
||||
public override void Init()
|
||||
{
|
||||
base.Init();
|
||||
_ma.Init();
|
||||
_prevClose = double.NaN;
|
||||
@@ -51,11 +56,15 @@ public class Atr : AbstractBase {
|
||||
/// Manages the state of the Atr instance based on whether a new bar is being processed.
|
||||
/// </summary>
|
||||
/// <param name="isNew">Indicates whether the current input is a new bar.</param>
|
||||
protected override void ManageState(bool isNew) {
|
||||
if (isNew) {
|
||||
protected override void ManageState(bool isNew)
|
||||
{
|
||||
if (isNew)
|
||||
{
|
||||
_index++;
|
||||
_p_prevClose = _prevClose;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_prevClose = _p_prevClose;
|
||||
}
|
||||
}
|
||||
@@ -71,7 +80,8 @@ public class Atr : AbstractBase {
|
||||
/// to smooth the true range values. For the first bar, it uses the high-low range
|
||||
/// as the true range.
|
||||
/// </remarks>
|
||||
protected override double Calculation() {
|
||||
protected override double Calculation()
|
||||
{
|
||||
ManageState(BarInput.IsNew);
|
||||
|
||||
double trueRange = Math.Max(
|
||||
@@ -81,7 +91,8 @@ public class Atr : AbstractBase {
|
||||
),
|
||||
Math.Abs(BarInput.Low - _prevClose)
|
||||
);
|
||||
if (_index < 2) {
|
||||
if (_index < 2)
|
||||
{
|
||||
trueRange = BarInput.High - BarInput.Low;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user