diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 00000000..90c7b22c
Binary files /dev/null and b/.DS_Store differ
diff --git a/.github/codeql/extensions/quantalib-csharp/codeql-pack.yml b/.github/codeql/extensions/quantalib-csharp/codeql-pack.yml
new file mode 100644
index 00000000..feaae3df
--- /dev/null
+++ b/.github/codeql/extensions/quantalib-csharp/codeql-pack.yml
@@ -0,0 +1,7 @@
+name: mihakralj/quantalib-csharp
+version: 0.0.0
+library: true
+extensionTargets:
+ codeql/csharp-all: '*'
+dataExtensions:
+ - models/**/*.yml
diff --git a/.sonarlint/CSharp/SonarLint.xml b/.sonarlint/CSharp/SonarLint.xml
new file mode 100644
index 00000000..99dacdae
--- /dev/null
+++ b/.sonarlint/CSharp/SonarLint.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+ csharpsquid:S3776
+
+
+
+
+
diff --git a/.sonarlint/csharp.ruleset b/.sonarlint/csharp.ruleset
new file mode 100644
index 00000000..5dff3f86
--- /dev/null
+++ b/.sonarlint/csharp.ruleset
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.vscode/launch.json b/.vscode/launch.json
deleted file mode 100644
index 5b4a7dfb..00000000
--- a/.vscode/launch.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "version": "0.2.0",
- "configurations": [
-
- {
- "name": "Build lib/quantalib.csproj (Debug net10.0)",
- "type": "coreclr",
- "request": "launch",
- "program": "dotnet",
- "args": [
- "build",
- "${workspaceFolder}/lib/quantalib.csproj",
- "--configuration",
- "Debug",
- "--framework",
- "net10.0"
- ],
- "cwd": "${workspaceFolder}",
- "stopAtEntry": false,
- "console": "integratedTerminal",
- "logging": {
- "moduleLoad": false
- }
- },
- {
- "name": "Debug Tests",
- "type": "coreclr",
- "request": "launch",
- "preLaunchTask": "build-sln-debug",
- "program": "dotnet",
- "args": [
- "test",
- "${workspaceFolder}/QuanTAlib.sln",
- "--no-build"
- ],
- "cwd": "${workspaceFolder}",
- "stopAtEntry": false,
- "console": "internalConsole",
- "logging": {
- "moduleLoad": false
- }
- },
- {
- "name": "Debug Library",
- "type": "coreclr",
- "request": "attach",
- "processId": "${command:pickProcess}",
- "justMyCode": true,
- "logging": {
- "moduleLoad": false
- }
- },
- {
- "name": "Build solution (Debug)",
- "type": "coreclr",
- "request": "launch",
- "preLaunchTask": "build-sln-debug",
- "program": "dotnet",
- "args": [
- "build",
- "${workspaceFolder}/QuanTAlib.sln",
- "--configuration",
- "Debug"
- ],
- "cwd": "${workspaceFolder}",
- "stopAtEntry": false,
- "console": "integratedTerminal",
- "logging": {
- "moduleLoad": false
- }
- }
- ]
-}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 8fa0c170..42ecf80c 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -2,23 +2,8 @@
"version": "2.0.0",
"tasks": [
{
- "label": "Build & Audit (Roslyn + JetBrains)",
- "dependsOrder": "sequence",
- "dependsOn": ["Create .sarif Dir", "Build: QuanTAlib", "JetBrains: Inspect"],
- "group": { "kind": "build", "isDefault": true }
- },
- {
- "label": "Create .sarif Dir",
- "type": "shell",
- "command": "mkdir -p .sarif",
- "windows": {
- "command": "powershell",
- "args": ["-Command", "if (!(Test-Path .sarif)) { New-Item -Path .sarif -ItemType Directory }"]
- },
- "presentation": { "reveal": "silent" }
- },
- {
- "label": "Build: QuanTAlib",
+ "label": "Build",
+ "detail": "dotnet build QuanTAlib.sln",
"type": "process",
"command": "dotnet",
"args": [
@@ -27,63 +12,36 @@
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
- "problemMatcher": "$msCompile"
- },
- {
- "label": "JetBrains: Inspect",
- "type": "shell",
- "command": "jb inspectcode QuanTAlib.sln --output=.sarif/jetbrains.sarif --format=Sarif",
- "presentation": { "reveal": "always" },
- "problemMatcher": [],
- "postLines": ["Analysis complete. Open .sarif/jetbrains.sarif to view results."]
- },
- {
- "label": "JetBrains: Cleanup",
- "type": "shell",
- "command": "jb cleanupcode QuanTAlib.sln",
- "problemMatcher": []
- },
- {
- "label": "test-net10",
- "command": "dotnet",
- "type": "process",
- "args": [
- "test",
- "${workspaceFolder}/lib/QuanTAlib.Tests.csproj",
- "--framework",
- "net10.0"
- ],
"problemMatcher": "$msCompile",
- "group": { "kind": "test", "isDefault": true },
- "presentation": { "reveal": "always", "panel": "new" }
+ "group": { "kind": "build", "isDefault": true }
},
{
- "label": "build-lib-net10-debug",
+ "label": "Build Library",
+ "detail": "dotnet build lib/quantalib.csproj (Debug, net10.0)",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/lib/quantalib.csproj",
- "--configuration",
- "Debug",
- "--framework",
- "net10.0"
+ "--configuration", "Debug",
+ "--framework", "net10.0"
],
"problemMatcher": "$msCompile",
- "group": { "kind": "build", "isDefault": false }
+ "group": "build"
},
{
- "label": "build-sln-debug",
+ "label": "Test",
+ "detail": "dotnet test lib/QuanTAlib.Tests.csproj (net10.0)",
"type": "process",
"command": "dotnet",
"args": [
- "build",
- "${workspaceFolder}/QuanTAlib.sln",
- "--configuration",
- "Debug"
+ "test",
+ "${workspaceFolder}/lib/QuanTAlib.Tests.csproj",
+ "--framework", "net10.0"
],
"problemMatcher": "$msCompile",
- "group": { "kind": "build", "isDefault": false }
+ "group": { "kind": "test", "isDefault": true },
+ "presentation": { "reveal": "always", "panel": "new" }
}
]
}
diff --git a/Directory.Build.props b/Directory.Build.props
index f5979f3a..62afc10c 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -19,7 +19,7 @@
true
snupkg
true
-
+
true
true
@@ -33,12 +33,15 @@
- $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'QuanTAlib.sln'))\.sarif
- $(SarifOutputDir)\$(MSBuildProjectName).sarif,version=2.1
+
+ $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), 'QuanTAlib.sln'))/.sarif
+ $(SarifOutputDir)/$(MSBuildProjectName).sarif,version=2.1
-
+
+
+
@@ -46,15 +49,15 @@
portable
true
true
-
+
link
-
+
false
false
true
-
+
false
@@ -62,7 +65,8 @@
- $(NoWarn);S107;S1144;S1944;S2053;S2245;S2259;S2583;S2589;S3329;S3604;S3655;S3776;S3949;S3966;S4158;S4347;S5773;S6781;MA0048;MA0051;MA0076;RCS1123;RCS1159;IDE0007
+
+ $(NoWarn);S107;S1144;S1944;S2053;S2245;S2259;S2583;S2589;S3329;S3604;S3655;S3776;S3949;S3966;S4158;S4347;S5773;S6781;MA0007;MA0048;MA0051;MA0076;RCS1123;RCS1159;IDE0007
@@ -74,6 +78,16 @@
[xunit.*]*,[*.Tests]*
+
+
+ $(MSBuildThisFileDirectory).sonarlint\csharp.ruleset
+
+
+
+ Properties\SonarLint.xml
+
+
+
diff --git a/lib/channels/maenv/Maenv.cs b/lib/channels/maenv/Maenv.cs
index 82a60b31..ba0ac540 100644
--- a/lib/channels/maenv/Maenv.cs
+++ b/lib/channels/maenv/Maenv.cs
@@ -289,7 +289,7 @@ public sealed class Maenv : ITValuePublisher
private double CalculateEMA(double value, bool isNew)
{
// Use EmaWeight==0 to detect first value for correct isNew=false behavior
- if (_state.EmaWeight == 0)
+ if (Math.Abs(_state.EmaWeight) < double.Epsilon)
{
// First value - persist only for isNew=true
if (isNew)
diff --git a/lib/channels/sdchannel/Sdchannel.cs b/lib/channels/sdchannel/Sdchannel.cs
index 166d9430..a94454cb 100644
--- a/lib/channels/sdchannel/Sdchannel.cs
+++ b/lib/channels/sdchannel/Sdchannel.cs
@@ -75,6 +75,9 @@ public sealed class Sdchannel : ITValuePublisher
public event TValuePublishedHandler? Pub;
+ ///
+ /// Initializes a new Standard Deviation Channel indicator with specified period and multiplier.
+ ///
/// Lookback period for regression (default 20, must be > 1)
/// Standard deviation multiplier for bands (default 2.0, must be > 0)
public Sdchannel(int period = 20, double multiplier = 2.0)
diff --git a/lib/cycles/stc/Stc.cs b/lib/cycles/stc/Stc.cs
index cbbebd67..8f76832f 100644
--- a/lib/cycles/stc/Stc.cs
+++ b/lib/cycles/stc/Stc.cs
@@ -1,6 +1,5 @@
using System;
using System.Buffers;
-using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -121,7 +120,6 @@ public sealed class Stc : AbstractBase
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- [SuppressMessage("SonarQube", "S3776:Cognitive Complexity", Justification = "High-performance SIMD code with intentionally optimized control flow")]
private static void UpdateMinMax(double added, double removed, bool hasRemoved, RingBuffer buf, ref double min, ref double max)
{
if (double.IsNaN(added)) return;
@@ -559,4 +557,4 @@ public sealed class Stc : AbstractBase
ArrayPool.Shared.Return(rentedStoch1);
}
}
-}
\ No newline at end of file
+}
diff --git a/lib/momentum/roc/Roc.cs b/lib/momentum/roc/Roc.cs
index eaf50931..b13371cd 100644
--- a/lib/momentum/roc/Roc.cs
+++ b/lib/momentum/roc/Roc.cs
@@ -27,6 +27,9 @@ public sealed class Roc : AbstractBase
public override bool IsHot => _buffer.Count > _period;
+ ///
+ /// Initializes a new Rate of Change indicator with specified lookback period.
+ ///
/// Lookback period (must be >= 1)
public Roc(int period = 9)
{
@@ -39,6 +42,9 @@ public sealed class Roc : AbstractBase
WarmupPeriod = period + 1;
}
+ ///
+ /// Initializes a new Rate of Change indicator with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Lookback period
public Roc(ITValuePublisher source, int period = 9) : this(period)
diff --git a/lib/numerics/change/Change.cs b/lib/numerics/change/Change.cs
index 6ad5f3d7..59c2785b 100644
--- a/lib/numerics/change/Change.cs
+++ b/lib/numerics/change/Change.cs
@@ -27,6 +27,9 @@ public sealed class Change : AbstractBase
public override bool IsHot => _buffer.Count > _period;
+ ///
+ ///
+ ///
/// Lookback period (must be >= 1)
public Change(int period = 1)
{
@@ -39,6 +42,9 @@ public sealed class Change : AbstractBase
WarmupPeriod = period + 1;
}
+ ///
+ ///
+ ///
/// Source indicator for chaining
/// Lookback period
public Change(ITValuePublisher source, int period = 1) : this(period)
@@ -99,7 +105,7 @@ public sealed class Change : AbstractBase
for (int i = 0; i < source.Length; i++)
{
- Update(new TValue(time, source[i]), true);
+ Update(new TValue(time, value: source[i]), isNew: true);
time += interval;
}
}
@@ -189,4 +195,4 @@ public sealed class Change : AbstractBase
_p_state = default;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/numerics/exptrans/Exptrans.cs b/lib/numerics/exptrans/Exptrans.cs
index a95232a1..a2810b3a 100644
--- a/lib/numerics/exptrans/Exptrans.cs
+++ b/lib/numerics/exptrans/Exptrans.cs
@@ -30,6 +30,9 @@ public sealed class Exptrans : AbstractBase
WarmupPeriod = 0;
}
+ ///
+ /// Creates Exptrans with source for event-based chaining.
+ ///
/// Source indicator for chaining
public Exptrans(ITValuePublisher source) : this()
{
@@ -146,4 +149,4 @@ public sealed class Exptrans : AbstractBase
_p_state = new(1.0);
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/numerics/highest/Highest.cs b/lib/numerics/highest/Highest.cs
index 824940e7..414b1abe 100644
--- a/lib/numerics/highest/Highest.cs
+++ b/lib/numerics/highest/Highest.cs
@@ -26,6 +26,9 @@ public sealed class Highest : AbstractBase
public override bool IsHot => _buffer.Count >= _period;
+ ///
+ /// Initializes a new Highest indicator with specified lookback period.
+ ///
/// Lookback window size (must be >= 1)
public Highest(int period)
{
@@ -38,6 +41,9 @@ public sealed class Highest : AbstractBase
WarmupPeriod = period;
}
+ ///
+ /// Initializes a new Highest indicator with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Lookback window size
public Highest(ITValuePublisher source, int period) : this(period)
@@ -89,7 +95,7 @@ public sealed class Highest : AbstractBase
for (int i = 0; i < source.Length; i++)
{
- Update(new TValue(time, source[i]), true);
+ Update(input: new TValue(time, source[i]), isNew: true);
time += interval;
}
}
diff --git a/lib/numerics/lineartrans/Lineartrans.cs b/lib/numerics/lineartrans/Lineartrans.cs
index 0a6fc988..f7744da4 100644
--- a/lib/numerics/lineartrans/Lineartrans.cs
+++ b/lib/numerics/lineartrans/Lineartrans.cs
@@ -48,6 +48,9 @@ public sealed class Lineartrans : AbstractBase
WarmupPeriod = 0;
}
+ ///
+ /// Creates a Linear transformer with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Multiplicative factor (default: 1.0)
/// Additive constant (default: 0.0)
diff --git a/lib/numerics/logtrans/Logtrans.cs b/lib/numerics/logtrans/Logtrans.cs
index e280b53f..2aff50e0 100644
--- a/lib/numerics/logtrans/Logtrans.cs
+++ b/lib/numerics/logtrans/Logtrans.cs
@@ -30,6 +30,9 @@ public sealed class Logtrans : AbstractBase
WarmupPeriod = 0;
}
+ ///
+ /// Creates Logtrans with source for event-based chaining.
+ ///
/// Source indicator for chaining
public Logtrans(ITValuePublisher source) : this()
{
@@ -132,4 +135,4 @@ public sealed class Logtrans : AbstractBase
_p_state = default;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/numerics/lowest/Lowest.cs b/lib/numerics/lowest/Lowest.cs
index 6f08914b..11bf164d 100644
--- a/lib/numerics/lowest/Lowest.cs
+++ b/lib/numerics/lowest/Lowest.cs
@@ -26,6 +26,9 @@ public sealed class Lowest : AbstractBase
public override bool IsHot => _buffer.Count >= _period;
+ ///
+ /// Initializes a new Lowest indicator with specified lookback period.
+ ///
/// Lookback window size (must be >= 1)
public Lowest(int period)
{
@@ -38,6 +41,9 @@ public sealed class Lowest : AbstractBase
WarmupPeriod = period;
}
+ ///
+ /// Initializes a new Lowest indicator with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Lookback window size
public Lowest(ITValuePublisher source, int period) : this(period)
@@ -192,4 +198,4 @@ public sealed class Lowest : AbstractBase
_p_state = default;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/numerics/midpoint/Midpoint.cs b/lib/numerics/midpoint/Midpoint.cs
index b02680bf..16f3b047 100644
--- a/lib/numerics/midpoint/Midpoint.cs
+++ b/lib/numerics/midpoint/Midpoint.cs
@@ -26,6 +26,9 @@ public sealed class Midpoint : AbstractBase
public override bool IsHot => _highest.IsHot && _lowest.IsHot;
+ ///
+ /// Initializes a new Midpoint indicator with specified lookback period.
+ ///
/// Lookback window size (must be >= 1)
public Midpoint(int period)
{
@@ -38,6 +41,9 @@ public sealed class Midpoint : AbstractBase
WarmupPeriod = period;
}
+ ///
+ /// Initializes a new Midpoint indicator with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Lookback window size
public Midpoint(ITValuePublisher source, int period) : this(period)
@@ -157,4 +163,4 @@ public sealed class Midpoint : AbstractBase
_lowest.Reset();
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/numerics/normalize/Normalize.cs b/lib/numerics/normalize/Normalize.cs
index 65a5d4aa..81b505b0 100644
--- a/lib/numerics/normalize/Normalize.cs
+++ b/lib/numerics/normalize/Normalize.cs
@@ -30,6 +30,9 @@ public sealed class Normalize : AbstractBase
public override bool IsHot => _buffer.Count >= _period;
+ ///
+ /// Initializes a new Normalize indicator with specified lookback period.
+ ///
/// Lookback period for min/max calculation (default 14)
public Normalize(int period = 14)
{
@@ -44,6 +47,9 @@ public sealed class Normalize : AbstractBase
_p_state = _state;
}
+ ///
+ /// Initializes a new Normalize indicator with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Lookback period (default 14)
public Normalize(ITValuePublisher source, int period = 14) : this(period)
diff --git a/lib/numerics/relu/Relu.cs b/lib/numerics/relu/Relu.cs
index 2f585fd1..3d3f3755 100644
--- a/lib/numerics/relu/Relu.cs
+++ b/lib/numerics/relu/Relu.cs
@@ -34,6 +34,9 @@ public sealed class Relu : AbstractBase
WarmupPeriod = 0;
}
+ ///
+ ///
+ ///
/// Source indicator for chaining
public Relu(ITValuePublisher source) : this()
{
diff --git a/lib/numerics/sigmoid/Sigmoid.cs b/lib/numerics/sigmoid/Sigmoid.cs
index dbfde68a..f9b70307 100644
--- a/lib/numerics/sigmoid/Sigmoid.cs
+++ b/lib/numerics/sigmoid/Sigmoid.cs
@@ -30,6 +30,9 @@ public sealed class Sigmoid : AbstractBase
public override bool IsHot => true; // No warmup needed
+ ///
+ /// Initializes a new Sigmoid indicator with specified steepness and midpoint.
+ ///
/// Steepness factor (default 1.0). Higher values create steeper transitions.
/// Midpoint value where output equals 0.5 (default 0.0).
public Sigmoid(double k = 1.0, double x0 = 0.0)
@@ -43,6 +46,9 @@ public sealed class Sigmoid : AbstractBase
WarmupPeriod = 0;
}
+ ///
+ /// Initializes a new Sigmoid indicator with source for event-based chaining.
+ ///
/// Source indicator for chaining
/// Steepness factor (default 1.0)
/// Midpoint value (default 0.0)
diff --git a/lib/numerics/sqrttrans/Sqrttrans.cs b/lib/numerics/sqrttrans/Sqrttrans.cs
index e5d71460..4939f2eb 100644
--- a/lib/numerics/sqrttrans/Sqrttrans.cs
+++ b/lib/numerics/sqrttrans/Sqrttrans.cs
@@ -30,6 +30,9 @@ public sealed class Sqrttrans : AbstractBase
WarmupPeriod = 0;
}
+ ///
+ /// Creates a Square Root transformer with source for event-based chaining.
+ ///
/// Source indicator for chaining
public Sqrttrans(ITValuePublisher source) : this()
{
@@ -131,4 +134,4 @@ public sealed class Sqrttrans : AbstractBase
_p_state = default;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/trends_FIR/hamma/Hamma.cs b/lib/trends_FIR/hamma/Hamma.cs
index 675e81a8..d627c045 100644
--- a/lib/trends_FIR/hamma/Hamma.cs
+++ b/lib/trends_FIR/hamma/Hamma.cs
@@ -75,6 +75,9 @@ public sealed class Hamma : AbstractBase
_state.LastValidValue = double.NaN;
}
+ ///
+ /// Creates HAMMA with source for event-based chaining.
+ ///
/// Data source for event-based updates
/// Lookback period for the Hamming window (default: 10)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -391,4 +394,4 @@ public sealed class Hamma : AbstractBase
_p_state = _state;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/trends_FIR/hanma/Hanma.cs b/lib/trends_FIR/hanma/Hanma.cs
index f144391b..868310bf 100644
--- a/lib/trends_FIR/hanma/Hanma.cs
+++ b/lib/trends_FIR/hanma/Hanma.cs
@@ -70,6 +70,9 @@ public sealed class Hanma : AbstractBase
_state = new State(double.NaN, IsInitialized: false);
}
+ ///
+ ///
+ ///
/// Data source for event-based updates
/// Lookback period for the Hanning window (default: 10)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/lib/trends_FIR/hwma/Hwma.cs b/lib/trends_FIR/hwma/Hwma.cs
index 2ff79ec8..83f1cee6 100644
--- a/lib/trends_FIR/hwma/Hwma.cs
+++ b/lib/trends_FIR/hwma/Hwma.cs
@@ -109,6 +109,9 @@ public sealed class Hwma : AbstractBase
_state = new State(double.NaN, 0, 0, double.NaN, IsInitialized: false);
}
+ ///
+ /// Creates HWMA with source for event-based chaining.
+ ///
/// Data source for event-based updates
/// Period for smoothing factor calculation (default: 10)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -339,4 +342,4 @@ public sealed class Hwma : AbstractBase
_p_state = _state;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/trends_FIR/sgma/Sgma.cs b/lib/trends_FIR/sgma/Sgma.cs
index ac0aaecc..812b1cf9 100644
--- a/lib/trends_FIR/sgma/Sgma.cs
+++ b/lib/trends_FIR/sgma/Sgma.cs
@@ -101,7 +101,7 @@ public sealed class Sgma : AbstractBase
weights[3] = 0.3429;
weights[4] = -0.0857;
double sum5 = weights[0] + weights[1] + weights[2] + weights[3] + weights[4];
- invWeightSum = sum5 != 0.0 ? 1.0 / sum5 : 0.0;
+ invWeightSum = Math.Abs(sum5) > double.Epsilon ? 1.0 / sum5 : 0.0;
return;
}
@@ -116,7 +116,7 @@ public sealed class Sgma : AbstractBase
weights[6] = -0.0476;
double sum7 = 0.0;
for (int i = 0; i < 7; i++) sum7 += weights[i];
- invWeightSum = sum7 != 0.0 ? 1.0 / sum7 : 0.0;
+ invWeightSum = Math.Abs(sum7) > double.Epsilon ? 1.0 / sum7 : 0.0;
return;
}
@@ -133,7 +133,7 @@ public sealed class Sgma : AbstractBase
weights[8] = -0.0281;
double sum9 = 0.0;
for (int i = 0; i < 9; i++) sum9 += weights[i];
- invWeightSum = sum9 != 0.0 ? 1.0 / sum9 : 0.0;
+ invWeightSum = Math.Abs(sum9) > double.Epsilon ? 1.0 / sum9 : 0.0;
return;
}
}
@@ -376,7 +376,7 @@ public sealed class Sgma : AbstractBase
continue;
}
- if (invWeightSum == 0.0)
+ if (Math.Abs(invWeightSum) < double.Epsilon)
{
output[i] = val;
continue;
@@ -399,7 +399,7 @@ public sealed class Sgma : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double CalculateWeightedSumFull(RingBuffer buffer, double[] weights, double invWeightSum, double fallbackValue)
{
- if (invWeightSum == 0.0)
+ if (Math.Abs(invWeightSum) < double.Epsilon)
return fallbackValue;
ReadOnlySpan internalBuf = buffer.InternalBuffer;
@@ -435,7 +435,7 @@ public sealed class Sgma : AbstractBase
Math.FusedMultiplyAdd(window[3], w3, window[4] * w4))));
double weightSum = w0 + w1 + w2 + w3 + w4;
- return weightSum != 0.0 ? sum / weightSum : fallbackValue;
+ return Math.Abs(weightSum) > double.Epsilon ? sum / weightSum : fallbackValue;
}
if (p == 7)
@@ -458,7 +458,7 @@ public sealed class Sgma : AbstractBase
sum = Math.FusedMultiplyAdd(window[6], w6, sum);
double weightSum = w0 + w1 + w2 + w3 + w4 + w5 + w6;
- return weightSum != 0.0 ? sum / weightSum : fallbackValue;
+ return Math.Abs(weightSum) > double.Epsilon ? sum / weightSum : fallbackValue;
}
if (p == 9)
@@ -485,7 +485,7 @@ public sealed class Sgma : AbstractBase
sum = Math.FusedMultiplyAdd(window[8], w8, sum);
double weightSum = w0 + w1 + w2 + w3 + w4 + w5 + w6 + w7 + w8;
- return weightSum != 0.0 ? sum / weightSum : fallbackValue;
+ return Math.Abs(weightSum) > double.Epsilon ? sum / weightSum : fallbackValue;
}
}
@@ -522,4 +522,4 @@ public sealed class Sgma : AbstractBase
_p_lastValidValue = double.NaN;
Last = default;
}
-}
\ No newline at end of file
+}
diff --git a/lib/trends_FIR/sma/Sma.cs b/lib/trends_FIR/sma/Sma.cs
index 6bd55199..9b6659f4 100644
--- a/lib/trends_FIR/sma/Sma.cs
+++ b/lib/trends_FIR/sma/Sma.cs
@@ -189,7 +189,6 @@ public sealed class Sma : AbstractBase
double val = GetValidValue(input.Value);
UpdateState(val);
-
}
else
{
diff --git a/lib/trends_IIR/vama/Vama.cs b/lib/trends_IIR/vama/Vama.cs
index 8799cfa1..d5c5a7a0 100644
--- a/lib/trends_IIR/vama/Vama.cs
+++ b/lib/trends_IIR/vama/Vama.cs
@@ -39,8 +39,8 @@ public sealed class Vama : AbstractBase
{
public static VamaState New() => new()
{
- ShortAtr = new RmaState(0, 1.0, false),
- LongAtr = new RmaState(0, 1.0, false),
+ ShortAtr = new RmaState(Ema: 0, E: 1.0, IsCompensated: false),
+ LongAtr = new RmaState(Ema: 0, E: 1.0, IsCompensated: false),
PrevClose = double.NaN,
BufferHead = 0,
BufferSum = 0,
@@ -244,7 +244,7 @@ public sealed class Vama : AbstractBase
newHead,
bufferSum,
validCount,
- true);
+ IsInitialized: true);
Last = new TValue(input.Time, result);
PubEvent(Last, isNew);
@@ -285,7 +285,7 @@ public sealed class Vama : AbstractBase
for (int i = 0; i < len; i++)
{
var bar = source[i];
- var result = Update(bar, true);
+ var result = Update(bar, isNew: true);
tSpan[i] = bar.Time;
vSpan[i] = result.Value;
}
@@ -314,7 +314,7 @@ public sealed class Vama : AbstractBase
for (int i = 0; i < len; i++)
{
- var result = Update(new TValue(sourceTimes[i], sourceValues[i]), true);
+ var result = Update(new TValue(sourceTimes[i], sourceValues[i]), isNew: true);
tSpan[i] = sourceTimes[i];
vSpan[i] = result.Value;
}
@@ -330,7 +330,7 @@ public sealed class Vama : AbstractBase
Reset();
foreach (double val in source)
{
- Update(new TValue(DateTime.MinValue, val), true);
+ Update(new TValue(DateTime.MinValue, val), isNew: true);
}
}
diff --git a/lib/trends_IIR/yzvama/Yzvama.cs b/lib/trends_IIR/yzvama/Yzvama.cs
index 99aa0267..0a314a07 100644
--- a/lib/trends_IIR/yzvama/Yzvama.cs
+++ b/lib/trends_IIR/yzvama/Yzvama.cs
@@ -37,8 +37,8 @@ public sealed class Yzvama : AbstractBase
{
public static YzvamaState New() => new()
{
- ShortVar = new RmaState(0, 1.0, false),
- LongVar = new RmaState(0, 1.0, false),
+ ShortVar = new RmaState(Ema: 0, E: 1.0, IsCompensated: false),
+ LongVar = new RmaState(Ema: 0, E: 1.0, IsCompensated: false),
PrevClose = double.NaN,
SourceHead = 0,
SourceSum = 0,
@@ -390,7 +390,7 @@ public sealed class Yzvama : AbstractBase
validCount,
yzvHead,
yzvCount,
- true);
+ IsInitialized: true);
Last = new TValue(input.Time, result);
PubEvent(Last, isNew);
@@ -428,7 +428,7 @@ public sealed class Yzvama : AbstractBase
for (int i = 0; i < len; i++)
{
var bar = source[i];
- var result = Update(bar, true);
+ var result = Update(bar, isNew: true);
tSpan[i] = bar.Time;
vSpan[i] = result.Value;
}
@@ -457,7 +457,7 @@ public sealed class Yzvama : AbstractBase
for (int i = 0; i < len; i++)
{
- var result = Update(new TValue(sourceTimes[i], sourceValues[i]), true);
+ var result = Update(new TValue(sourceTimes[i], sourceValues[i]), isNew: true);
tSpan[i] = sourceTimes[i];
vSpan[i] = result.Value;
}
@@ -473,7 +473,7 @@ public sealed class Yzvama : AbstractBase
{
Reset();
foreach (double val in source)
- Update(new TValue(DateTime.MinValue, val), true);
+ Update(new TValue(DateTime.MinValue, val), isNew: true);
}
///
@@ -484,7 +484,7 @@ public sealed class Yzvama : AbstractBase
{
Reset();
foreach (TValue tv in source)
- Update(tv, true);
+ Update(tv, isNew: true);
}
///
diff --git a/lib/trends_IIR/zlema/Zlema.Validation.Tests.cs b/lib/trends_IIR/zlema/Zlema.Validation.Tests.cs
index 805ee2ef..c5fd6b57 100644
--- a/lib/trends_IIR/zlema/Zlema.Validation.Tests.cs
+++ b/lib/trends_IIR/zlema/Zlema.Validation.Tests.cs
@@ -7,7 +7,7 @@ public class ZlemaValidationTests
[Fact]
public void Zlema_Streaming_MatchesReference()
{
- int period = 20;
+ const int period = 20;
TSeries series = BuildSeries(300, seed: 5);
double[] reference = new double[series.Count];
@@ -24,7 +24,7 @@ public class ZlemaValidationTests
[Fact]
public void Zlema_Batch_MatchesReference()
{
- int period = 14;
+ const int period = 14;
TSeries series = BuildSeries(250, seed: 9);
double[] reference = new double[series.Count];
@@ -40,7 +40,7 @@ public class ZlemaValidationTests
[Fact]
public void Zlema_Span_MatchesReference()
{
- int period = 30;
+ const int period = 30;
TSeries series = BuildSeries(200, seed: 12);
double[] values = series.Values.ToArray();
var output = new double[values.Length];
diff --git a/lib/volatility/atrn/Atrn.Tests.cs b/lib/volatility/atrn/Atrn.Tests.cs
index b1f8eb05..bcdb1906 100644
--- a/lib/volatility/atrn/Atrn.Tests.cs
+++ b/lib/volatility/atrn/Atrn.Tests.cs
@@ -54,7 +54,7 @@ public class AtrnTests
public void Update_ReturnsValidTValue()
{
var atrn = new Atrn(DefaultPeriod);
- var result = atrn.Update(_bars[0], true);
+ var result = atrn.Update(_bars[0], isNew: true);
Assert.IsType(result);
Assert.Equal(_bars[0].Time, result.Time);
@@ -67,7 +67,7 @@ public class AtrnTests
for (int i = 0; i < _bars.Count; i++)
{
- var result = atrn.Update(_bars[i], true);
+ var result = atrn.Update(_bars[i], isNew: true);
Assert.True(result.Value >= 0 && result.Value <= 1,
$"Value {result.Value} at index {i} is outside [0,1] range");
}
@@ -447,4 +447,4 @@ public class AtrnTests
}
#endregion
-}
\ No newline at end of file
+}
diff --git a/lib/volatility/atrn/Atrn.cs b/lib/volatility/atrn/Atrn.cs
index 24620f70..ee9509a7 100644
--- a/lib/volatility/atrn/Atrn.cs
+++ b/lib/volatility/atrn/Atrn.cs
@@ -51,7 +51,7 @@ public sealed class Atrn : AbstractBase
Name = $"Atrn({period})";
WarmupPeriod = _rma.WarmupPeriod + _lookbackWindow;
- _state = new State(default, false, 0.0, 0.0);
+ _state = new State(PrevBar: default, IsInitialized: false, LastValidTr: 0.0, LastValidAtr: 0.0);
_p_state = _state;
}
@@ -95,7 +95,7 @@ public sealed class Atrn : AbstractBase
for (int i = 0; i < source.Length; i++)
{
double tr = source[i];
- TValue atr = _rma.Update(new TValue(DateTime.UtcNow.AddMinutes(i), tr), true);
+ TValue atr = _rma.Update(new TValue(DateTime.UtcNow.AddMinutes(i), tr), isNew: true);
_atrBuffer.Add(atr.Value);
}
@@ -117,7 +117,7 @@ public sealed class Atrn : AbstractBase
{
_rma.Reset();
_atrBuffer.Clear();
- _state = new State(default, false, 0.0, 0.0);
+ _state = new State(PrevBar: default, IsInitialized: false, LastValidTr: 0.0, LastValidAtr: 0.0);
_p_state = _state;
Last = default;
}
@@ -180,7 +180,7 @@ public sealed class Atrn : AbstractBase
// Update state
_state = isNew
- ? new State(input, true, tr, currentAtr)
+ ? new State(PrevBar: input, IsInitialized: true, LastValidTr: tr, LastValidAtr: currentAtr)
: _state with { LastValidTr = tr, LastValidAtr = currentAtr };
TValue result = new(input.Time, normalized);
@@ -246,7 +246,7 @@ public sealed class Atrn : AbstractBase
for (int i = 0; i < source.Count; i++)
{
- TValue result = Update(source[i], true);
+ TValue result = Update(source[i], isNew: true);
t.Add(result.Time);
v.Add(result.Value);
}
@@ -266,7 +266,7 @@ public sealed class Atrn : AbstractBase
for (int i = 0; i < source.Count; i++)
{
- TValue result = Update(source[i], true);
+ TValue result = Update(source[i], isNew: true);
t.Add(source[i].Time);
v.Add(result.Value);
}