mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-23 04:58:08 +00:00
chore: Update project files and configurations; enhance .gitignore, add Qodana and SonarScanner scripts, and improve test project references
This commit is contained in:
@@ -0,0 +1,85 @@
|
|||||||
|
#Requires -Version 7.0
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Static Analysis Scanner for QuanTAlib
|
||||||
|
.DESCRIPTION
|
||||||
|
Runs SonarCloud and Qodana with code coverage on Windows
|
||||||
|
#>
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
# Load tokens from User environment if not in process environment
|
||||||
|
if (-not $env:SONAR_TOKEN) {
|
||||||
|
$env:SONAR_TOKEN = [System.Environment]::GetEnvironmentVariable("SONAR_TOKEN", "User")
|
||||||
|
}
|
||||||
|
if (-not $env:QODANA_TOKEN) {
|
||||||
|
$env:QODANA_TOKEN = [System.Environment]::GetEnvironmentVariable("QODANA_TOKEN", "User")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verify tokens are available
|
||||||
|
if (-not $env:SONAR_TOKEN) {
|
||||||
|
Write-Error "SONAR_TOKEN environment variable not set"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if (-not $env:QODANA_TOKEN) {
|
||||||
|
Write-Error "QODANA_TOKEN environment variable not set"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Coverage output directory for Qodana
|
||||||
|
$CoverageDir = ".qodana/code-coverage"
|
||||||
|
New-Item -ItemType Directory -Force -Path $CoverageDir | Out-Null
|
||||||
|
|
||||||
|
# Start SonarScanner analysis context
|
||||||
|
Write-Host "==> Starting SonarScanner analysis..." -ForegroundColor Cyan
|
||||||
|
dotnet-sonarscanner begin `
|
||||||
|
/o:"mihakralj-quantalib" `
|
||||||
|
/k:"mihakralj_QuanTAlib" `
|
||||||
|
/d:sonar.token="$env:SONAR_TOKEN" `
|
||||||
|
/d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml"
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
# Build solution (within SonarScanner context)
|
||||||
|
Write-Host "==> Building solution..." -ForegroundColor Cyan
|
||||||
|
dotnet build --no-incremental
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
# Run tests with coverage (opencover format works for both SonarCloud and can be converted)
|
||||||
|
Write-Host "==> Running tests with coverage..." -ForegroundColor Cyan
|
||||||
|
dotnet test --no-build --collect:"XPlat Code Coverage" `
|
||||||
|
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover,lcov
|
||||||
|
# Continue even if tests fail - we still want coverage data for analysis
|
||||||
|
|
||||||
|
# Copy coverage files to Qodana directory with unique names
|
||||||
|
Write-Host "==> Copying coverage files to Qodana directory..." -ForegroundColor Cyan
|
||||||
|
$coverageFiles = Get-ChildItem -Recurse -Filter "coverage.info" -ErrorAction SilentlyContinue
|
||||||
|
if ($coverageFiles) {
|
||||||
|
$index = 0
|
||||||
|
foreach ($file in $coverageFiles) {
|
||||||
|
$destName = "coverage_$index.info"
|
||||||
|
Copy-Item $file.FullName -Destination (Join-Path $CoverageDir $destName) -Force
|
||||||
|
Write-Host " Copied: $($file.FullName) -> $destName" -ForegroundColor Gray
|
||||||
|
$index++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host " WARNING: No coverage.info files found" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
# End SonarScanner analysis
|
||||||
|
Write-Host "==> Completing SonarScanner analysis..." -ForegroundColor Cyan
|
||||||
|
dotnet-sonarscanner end /d:sonar.token="$env:SONAR_TOKEN"
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
Write-Host "==> SonarCloud: https://sonarcloud.io/project/overview?id=mihakralj_QuanTAlib" -ForegroundColor Green
|
||||||
|
|
||||||
|
# Run Qodana
|
||||||
|
Write-Host "==> Starting Qodana analysis..." -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Set CI environment to suppress interactive prompts
|
||||||
|
$env:CI = "true"
|
||||||
|
qodana scan --within-docker=false -l qodana-dotnet --coverage-dir $CoverageDir
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
Write-Host "==> Qodana analysis complete" -ForegroundColor Green
|
||||||
|
Write-Host "==> Done!" -ForegroundColor Green
|
||||||
@@ -413,3 +413,7 @@ ilspy/
|
|||||||
|
|
||||||
#Ignore insiders AI rules
|
#Ignore insiders AI rules
|
||||||
.github/instructions/codacy.instructions.md
|
.github/instructions/codacy.instructions.md
|
||||||
|
|
||||||
|
|
||||||
|
#Ignore vscode AI rules
|
||||||
|
.github\instructions\codacy.instructions.md
|
||||||
|
|||||||
Vendored
+3
-1
@@ -170,7 +170,9 @@
|
|||||||
"sonarlint.connectedMode.project": {
|
"sonarlint.connectedMode.project": {
|
||||||
"connectionId": "mihakralj-quantalib",
|
"connectionId": "mihakralj-quantalib",
|
||||||
"projectKey": "mihakralj_QuanTAlib"
|
"projectKey": "mihakralj_QuanTAlib"
|
||||||
}
|
},
|
||||||
|
"qodana.projectId": "KbxmN"
|
||||||
|
// Note: Native mode is configured in qodana.yaml with withinDocker: false
|
||||||
|
|
||||||
// ???????????????????????????????????????????????????????????????????
|
// ???????????????????????????????????????????????????????????????????
|
||||||
// Keyboard Shortcuts Reference
|
// Keyboard Shortcuts Reference
|
||||||
|
|||||||
@@ -44,12 +44,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<NoWarn>S1144,S1944,S2053,S2222,S2259,S2583,S2589,S3329,S3655,S3776,S3900,S3949,S3966,S4158,S4347,S5773,S6781</NoWarn>
|
<NoWarn>S1144,S1944,S2053,S2222,S2245,S2259,S2583,S2589,S3329,S3655,S3776,S3900,S3949,S3966,S4158,S4347,S5773,S6781</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All"/>
|
||||||
<PackageReference Include="Microsoft.DotNet.Interactive.Formatting" Version="1.0.0-beta.25323.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(IsLocalBuild)' == 'true' AND $([MSBuild]::IsOSPlatform('Windows'))">
|
<PropertyGroup Condition="'$(IsLocalBuild)' == 'true' AND $([MSBuild]::IsOSPlatform('Windows'))">
|
||||||
|
|||||||
+11
-5
@@ -1,25 +1,31 @@
|
|||||||
|
workflow: GitHubFlow/v1
|
||||||
assembly-versioning-scheme: MajorMinorPatch
|
assembly-versioning-scheme: MajorMinorPatch
|
||||||
assembly-file-versioning-scheme: MajorMinorPatch
|
assembly-file-versioning-scheme: MajorMinorPatch
|
||||||
|
tag-prefix: '[vV]'
|
||||||
major-version-bump-message: '\+semver:\s?(breaking|major)'
|
major-version-bump-message: '\+semver:\s?(breaking|major)'
|
||||||
minor-version-bump-message: '\+semver:\s?(feature|minor)'
|
minor-version-bump-message: '\+semver:\s?(feature|minor)'
|
||||||
patch-version-bump-message: '\+semver:\s?(fix|patch)'
|
patch-version-bump-message: '\+semver:\s?(fix|patch)'
|
||||||
no-bump-message: '\+semver:\s?(none|skip)'
|
no-bump-message: '\+semver:\s?(none|skip)'
|
||||||
tag-prefix: '[vV]'
|
|
||||||
branches:
|
branches:
|
||||||
main:
|
main:
|
||||||
regex: ^main$
|
|
||||||
mode: ContinuousDeployment
|
mode: ContinuousDeployment
|
||||||
|
label: ''
|
||||||
increment: Patch
|
increment: Patch
|
||||||
|
prevent-increment:
|
||||||
|
of-merged-branch: true
|
||||||
track-merge-target: false
|
track-merge-target: false
|
||||||
is-release-branch: true
|
is-release-branch: true
|
||||||
|
is-main-branch: true
|
||||||
pre-release-weight: 0
|
pre-release-weight: 0
|
||||||
develop:
|
develop:
|
||||||
regex: ^dev(elop)?(ment)?$
|
|
||||||
mode: ContinuousDelivery
|
mode: ContinuousDelivery
|
||||||
|
label: alpha
|
||||||
increment: Patch
|
increment: Patch
|
||||||
track-merge-target: true
|
track-merge-target: true
|
||||||
is-release-branch: false
|
track-merge-message: true
|
||||||
source-branches: ['main']
|
regex: ^dev(elop)?(ment)?$
|
||||||
|
source-branches:
|
||||||
|
- main
|
||||||
pre-release-weight: 30000
|
pre-release-weight: 30000
|
||||||
ignore:
|
ignore:
|
||||||
sha: []
|
sha: []
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Using Include="Xunit" />
|
<Using Include="Xunit" />
|
||||||
|
<Using Include="QuanTAlib" />
|
||||||
|
<Using Include="System.Collections" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
public class EmaTests
|
public class EmaTests
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ using System.Linq;
|
|||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using TALib;
|
using TALib;
|
||||||
using Tulip;
|
using Tulip;
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
@@ -213,7 +211,7 @@ public class EmaValidationTests
|
|||||||
// Calculate Tulip EMA
|
// Calculate Tulip EMA
|
||||||
var emaIndicator = Tulip.Indicators.ema;
|
var emaIndicator = Tulip.Indicators.ema;
|
||||||
double[][] inputs = { tData };
|
double[][] inputs = { tData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
double[][] outputs = { new double[tData.Length] };
|
double[][] outputs = { new double[tData.Length] };
|
||||||
|
|
||||||
emaIndicator.Run(inputs, options, outputs);
|
emaIndicator.Run(inputs, options, outputs);
|
||||||
@@ -246,7 +244,7 @@ public class EmaValidationTests
|
|||||||
// Calculate Tulip EMA
|
// Calculate Tulip EMA
|
||||||
var emaIndicator = Tulip.Indicators.ema;
|
var emaIndicator = Tulip.Indicators.ema;
|
||||||
double[][] inputs = { tData };
|
double[][] inputs = { tData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
double[][] outputs = { new double[tData.Length] };
|
double[][] outputs = { new double[tData.Length] };
|
||||||
|
|
||||||
emaIndicator.Run(inputs, options, outputs);
|
emaIndicator.Run(inputs, options, outputs);
|
||||||
@@ -275,7 +273,7 @@ public class EmaValidationTests
|
|||||||
// Calculate Tulip EMA
|
// Calculate Tulip EMA
|
||||||
var emaIndicator = Tulip.Indicators.ema;
|
var emaIndicator = Tulip.Indicators.ema;
|
||||||
double[][] inputs = { sourceData };
|
double[][] inputs = { sourceData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
double[][] outputs = { new double[sourceData.Length] };
|
double[][] outputs = { new double[sourceData.Length] };
|
||||||
|
|
||||||
emaIndicator.Run(inputs, options, outputs);
|
emaIndicator.Run(inputs, options, outputs);
|
||||||
|
|||||||
+16
-3
@@ -25,12 +25,25 @@ namespace QuanTAlib;
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class Ema
|
public class Ema
|
||||||
{
|
{
|
||||||
private struct State
|
private struct State : IEquatable<State>
|
||||||
{
|
{
|
||||||
public double Ema;
|
public double Ema;
|
||||||
public double E;
|
public double E;
|
||||||
public bool IsHot;
|
public bool IsHot;
|
||||||
|
|
||||||
public static State New() => new() { Ema = 0, E = 1.0, IsHot = false };
|
public static State New() => new() { Ema = 0, E = 1.0, IsHot = false };
|
||||||
|
|
||||||
|
public readonly bool Equals(State other) =>
|
||||||
|
Ema == other.Ema && E == other.E && IsHot == other.IsHot;
|
||||||
|
|
||||||
|
public override readonly bool Equals(object? obj) =>
|
||||||
|
obj is State other && Equals(other);
|
||||||
|
|
||||||
|
public override readonly int GetHashCode() =>
|
||||||
|
HashCode.Combine(Ema, E, IsHot);
|
||||||
|
|
||||||
|
public static bool operator ==(State left, State right) => left.Equals(right);
|
||||||
|
public static bool operator !=(State left, State right) => !left.Equals(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly double _alpha;
|
private readonly double _alpha;
|
||||||
@@ -60,7 +73,7 @@ public class Ema
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates EMA with specified alpha smoothing factor.
|
/// Creates EMA with specified alpha smoothing factor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="alpha">Smoothing factor (0 < alpha <= 1)</param>
|
/// <param name="alpha">Smoothing factor (0 < alpha <= 1)</param>
|
||||||
public Ema(double alpha)
|
public Ema(double alpha)
|
||||||
{
|
{
|
||||||
if (alpha <= 0 || alpha > 1)
|
if (alpha <= 0 || alpha > 1)
|
||||||
@@ -217,7 +230,7 @@ public class Ema
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source">Input values</param>
|
/// <param name="source">Input values</param>
|
||||||
/// <param name="output">Output span (must be same length as source)</param>
|
/// <param name="output">Output span (must be same length as source)</param>
|
||||||
/// <param name="alpha">Smoothing factor (0 < alpha <= 1)</param>
|
/// <param name="alpha">Smoothing factor (0 < alpha <= 1)</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha)
|
public static void Calculate(ReadOnlySpan<double> source, Span<double> output, double alpha)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
public class SmaTests
|
public class SmaTests
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ using System.Linq;
|
|||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using TALib;
|
using TALib;
|
||||||
using Tulip;
|
using Tulip;
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
@@ -213,7 +211,7 @@ public class SmaValidationTests
|
|||||||
// Calculate Tulip SMA
|
// Calculate Tulip SMA
|
||||||
var smaIndicator = Tulip.Indicators.sma;
|
var smaIndicator = Tulip.Indicators.sma;
|
||||||
double[][] inputs = { tData };
|
double[][] inputs = { tData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
int lookback = period - 1;
|
int lookback = period - 1;
|
||||||
double[][] outputs = { new double[tData.Length - lookback] };
|
double[][] outputs = { new double[tData.Length - lookback] };
|
||||||
|
|
||||||
@@ -247,7 +245,7 @@ public class SmaValidationTests
|
|||||||
// Calculate Tulip SMA
|
// Calculate Tulip SMA
|
||||||
var smaIndicator = Tulip.Indicators.sma;
|
var smaIndicator = Tulip.Indicators.sma;
|
||||||
double[][] inputs = { tData };
|
double[][] inputs = { tData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
int lookback = period - 1;
|
int lookback = period - 1;
|
||||||
double[][] outputs = { new double[tData.Length - lookback] };
|
double[][] outputs = { new double[tData.Length - lookback] };
|
||||||
|
|
||||||
@@ -277,7 +275,7 @@ public class SmaValidationTests
|
|||||||
// Calculate Tulip SMA
|
// Calculate Tulip SMA
|
||||||
var smaIndicator = Tulip.Indicators.sma;
|
var smaIndicator = Tulip.Indicators.sma;
|
||||||
double[][] inputs = { sourceData };
|
double[][] inputs = { sourceData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
int lookback = period - 1;
|
int lookback = period - 1;
|
||||||
double[][] outputs = { new double[sourceData.Length - lookback] };
|
double[][] outputs = { new double[sourceData.Length - lookback] };
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System.Linq;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
public class WmaTests
|
public class WmaTests
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ using System.Linq;
|
|||||||
using Skender.Stock.Indicators;
|
using Skender.Stock.Indicators;
|
||||||
using TALib;
|
using TALib;
|
||||||
using Tulip;
|
using Tulip;
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
@@ -213,7 +211,7 @@ public class WmaValidationTests
|
|||||||
// Calculate Tulip WMA
|
// Calculate Tulip WMA
|
||||||
var wmaIndicator = Tulip.Indicators.wma;
|
var wmaIndicator = Tulip.Indicators.wma;
|
||||||
double[][] inputs = { tData };
|
double[][] inputs = { tData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
int lookback = period - 1;
|
int lookback = period - 1;
|
||||||
double[][] outputs = { new double[tData.Length - lookback] };
|
double[][] outputs = { new double[tData.Length - lookback] };
|
||||||
|
|
||||||
@@ -247,7 +245,7 @@ public class WmaValidationTests
|
|||||||
// Calculate Tulip WMA
|
// Calculate Tulip WMA
|
||||||
var wmaIndicator = Tulip.Indicators.wma;
|
var wmaIndicator = Tulip.Indicators.wma;
|
||||||
double[][] inputs = { tData };
|
double[][] inputs = { tData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
int lookback = period - 1;
|
int lookback = period - 1;
|
||||||
double[][] outputs = { new double[tData.Length - lookback] };
|
double[][] outputs = { new double[tData.Length - lookback] };
|
||||||
|
|
||||||
@@ -277,7 +275,7 @@ public class WmaValidationTests
|
|||||||
// Calculate Tulip WMA
|
// Calculate Tulip WMA
|
||||||
var wmaIndicator = Tulip.Indicators.wma;
|
var wmaIndicator = Tulip.Indicators.wma;
|
||||||
double[][] inputs = { sourceData };
|
double[][] inputs = { sourceData };
|
||||||
double[] options = { (double)period };
|
double[] options = { period };
|
||||||
int lookback = period - 1;
|
int lookback = period - 1;
|
||||||
double[][] outputs = { new double[sourceData.Length - lookback] };
|
double[][] outputs = { new double[sourceData.Length - lookback] };
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System.Linq;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ public sealed class RingBuffer : IEnumerable<double>
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// High-performance enumerator for the RingBuffer.
|
/// High-performance enumerator for the RingBuffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct Enumerator : IEnumerator<double>
|
public struct Enumerator : IEnumerator<double>, IEquatable<Enumerator>
|
||||||
{
|
{
|
||||||
private readonly RingBuffer _buffer;
|
private readonly RingBuffer _buffer;
|
||||||
private readonly int _start;
|
private readonly int _start;
|
||||||
@@ -453,8 +453,8 @@ public sealed class RingBuffer : IEnumerable<double>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double Current => _current;
|
public readonly double Current => _current;
|
||||||
object IEnumerator.Current => Current;
|
readonly object IEnumerator.Current => Current;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public void Reset()
|
public void Reset()
|
||||||
@@ -463,6 +463,22 @@ public sealed class RingBuffer : IEnumerable<double>
|
|||||||
_current = default;
|
_current = default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public readonly void Dispose() { }
|
||||||
|
|
||||||
|
public readonly bool Equals(Enumerator other) =>
|
||||||
|
ReferenceEquals(_buffer, other._buffer) &&
|
||||||
|
_start == other._start &&
|
||||||
|
_count == other._count &&
|
||||||
|
_index == other._index &&
|
||||||
|
_current == other._current;
|
||||||
|
|
||||||
|
public override readonly bool Equals(object? obj) =>
|
||||||
|
obj is Enumerator other && Equals(other);
|
||||||
|
|
||||||
|
public override readonly int GetHashCode() =>
|
||||||
|
HashCode.Combine(RuntimeHelpers.GetHashCode(_buffer), _start, _count, _index, _current);
|
||||||
|
|
||||||
|
public static bool operator ==(Enumerator left, Enumerator right) => left.Equals(right);
|
||||||
|
public static bool operator !=(Enumerator left, Enumerator right) => !left.Equals(right);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
@@ -550,11 +547,13 @@ public class SimdExtensionsTests
|
|||||||
Assert.True(avg > 0);
|
Assert.True(avg > 0);
|
||||||
Assert.True(min > 0);
|
Assert.True(min > 0);
|
||||||
Assert.True(max > min);
|
Assert.True(max > min);
|
||||||
|
Assert.Equal(min, minAlt);
|
||||||
|
Assert.Equal(max, maxAlt);
|
||||||
Assert.True(variance > 0);
|
Assert.True(variance > 0);
|
||||||
Assert.True(stdDev > 0);
|
Assert.True(stdDev > 0);
|
||||||
|
|
||||||
Assert.True(sw.ElapsedMilliseconds < 10,
|
Assert.True(sw.ElapsedMilliseconds < 50,
|
||||||
$"SIMD operations took {sw.ElapsedMilliseconds}ms, expected < 10ms");
|
$"SIMD operations took {sw.ElapsedMilliseconds}ms, expected < 50ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests
|
namespace QuanTAlib.Tests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests
|
namespace QuanTAlib.Tests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests
|
namespace QuanTAlib.Tests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests
|
namespace QuanTAlib.Tests
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
using System;
|
|
||||||
using Xunit;
|
|
||||||
using QuanTAlib;
|
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -32,17 +32,17 @@
|
|||||||
<UserSecretsId>6afc11a7-4355-4f5e-9fdf-22431e5b03cb</UserSecretsId>
|
<UserSecretsId>6afc11a7-4355-4f5e-9fdf-22431e5b03cb</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InternalsVisibleTo Include="QuanTAlib.Tests" />
|
<InternalsVisibleTo Include="QuanTAlib.Tests" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="**\*.cs" Exclude="**\*.Tests.cs;**\*.Quantower.cs;obj\**\*.cs" />
|
<Compile Include="**\*.cs" Exclude="**\*.Tests.cs;**\*.Quantower.cs;obj\**\*.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
|
<PackageReference Include="GitVersion.MsBuild" Version="6.5.1">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
#-------------------------------------------------------------------------------#
|
||||||
|
# Qodana analysis is configured by qodana.yaml file #
|
||||||
|
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
|
||||||
|
#-------------------------------------------------------------------------------#
|
||||||
|
version: "1.0"
|
||||||
|
|
||||||
|
#Specify inspection profile for code analysis
|
||||||
|
profile:
|
||||||
|
name: qodana.starter
|
||||||
|
|
||||||
|
#Enable inspections
|
||||||
|
#include:
|
||||||
|
# - name: <SomeEnabledInspectionId>
|
||||||
|
|
||||||
|
#Disable inspections
|
||||||
|
exclude:
|
||||||
|
# Disable XML documentation comment validation (allows unescaped < > in comments)
|
||||||
|
- name: XmlDocAnalyzer
|
||||||
|
- name: InvalidXmlDocComment
|
||||||
|
# Library project - public API properties are intentionally unused internally
|
||||||
|
- name: UnusedAutoPropertyAccessor.Global
|
||||||
|
# Style preference - fully qualified names used intentionally for clarity
|
||||||
|
- name: RedundantNameQualifier
|
||||||
|
- name: RCS1036 # Roslyn: Remove redundant empty line
|
||||||
|
- name: IDE0001 # Simplify name
|
||||||
|
- name: IDE0002 # Simplify member access
|
||||||
|
|
||||||
|
# HIGH-PERFORMANCE LIBRARY EXCLUSIONS
|
||||||
|
# ------------------------------------
|
||||||
|
# Flat namespace structure is intentional for this library
|
||||||
|
- name: CheckNamespace
|
||||||
|
|
||||||
|
# Float comparisons are intentional in financial calculations (checking 0.0, NaN, sentinel values)
|
||||||
|
- name: CompareOfFloatsByEqualityOperator
|
||||||
|
|
||||||
|
# Explicit default args improve code clarity and self-documentation
|
||||||
|
- name: RedundantArgumentDefaultValue
|
||||||
|
|
||||||
|
# Platform-specific optimizations (SIMD, intrinsics) are intentional
|
||||||
|
- name: CA1416 # Validate platform compatibility
|
||||||
|
|
||||||
|
# Public API unused internally - this is a library
|
||||||
|
- name: UnusedMember.Global
|
||||||
|
- name: MemberCanBePrivate.Global
|
||||||
|
- name: ClassNeverInstantiated.Global
|
||||||
|
- name: UnusedType.Global
|
||||||
|
|
||||||
|
# Redundant using directives - managed by IDE/build, not critical for library
|
||||||
|
- name: RedundantUsingDirective
|
||||||
|
- name: IDE0005 # Remove unnecessary using directives
|
||||||
|
- name: CS8019 # Unnecessary using directive
|
||||||
|
|
||||||
|
# Nullable warning suppressions - used intentionally for null safety patterns
|
||||||
|
- name: RedundantSuppressNullableWarningExpression
|
||||||
|
|
||||||
|
# Redundant type specifications - explicit types used for clarity/documentation
|
||||||
|
- name: RedundantTypeArgumentsOfMethod
|
||||||
|
- name: RedundantCast
|
||||||
|
- name: RedundantExplicitArrayCreation
|
||||||
|
|
||||||
|
# Unused local variables - often used in test setup or placeholder code (includes false positives for tuple deconstruction)
|
||||||
|
- name: UnusedVariable
|
||||||
|
- name: UnusedVariable.Compiler # False positive for tuple deconstruction
|
||||||
|
- name: CS0219 # Variable is assigned but never used
|
||||||
|
|
||||||
|
# Object initializer in using statement - false positive for simple property setters
|
||||||
|
- name: CA2000 # Dispose objects before losing scope (overly cautious for simple cases)
|
||||||
|
- name: UseObjectOrCollectionInitializerWhenPossible
|
||||||
|
- name: DoNotUseObjectInitializerForUsingVariable
|
||||||
|
- name: ObjectInitializerMightCauseException
|
||||||
|
- name: ObjectCreationAsStatement
|
||||||
|
- name: UseObjectOrCollectionInitializer
|
||||||
|
- name: UsingStatementResourceInitialization # "Do not use object initializer for 'using' variable"
|
||||||
|
|
||||||
|
# Private field can be local variable - test fixtures often use fields for clarity/organization
|
||||||
|
- name: PrivateFieldCanBeConvertedToLocalVariable
|
||||||
|
- name: ConvertToLocalFunction
|
||||||
|
|
||||||
|
# Code coverage checks - SonarCloud handles coverage, Qodana coverage unreliable
|
||||||
|
- name: CoverageCheck
|
||||||
|
- name: ClassCoverageCheck
|
||||||
|
- name: MethodCoverageCheck
|
||||||
|
- name: CodeCoverageCheck
|
||||||
|
|
||||||
|
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
||||||
|
#bootstrap: sh ./prepare-qodana.sh
|
||||||
|
|
||||||
|
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
|
||||||
|
#plugins:
|
||||||
|
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
||||||
|
|
||||||
|
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
||||||
|
linter: qodana-dotnet
|
||||||
|
|
||||||
|
# Use native mode instead of Docker (avoids Unix socket issues on Windows)
|
||||||
|
withinDocker: false
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.0">
|
||||||
|
|||||||
Reference in New Issue
Block a user