chore: Update .gitignore to exclude SonarQube files and add Codacy and SonarScanner scripts

refactor: Remove WarmupPeriod logging from SMA and WMA examples
This commit is contained in:
Miha Kralj
2025-11-30 17:17:55 -08:00
parent 4dd753f7c0
commit 626a2afa9b
7 changed files with 109 additions and 10 deletions
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
set -euo pipefail
# Codacy Coverage Upload for QuanTAlib
# Requires CODACY_PROJECT_TOKEN environment variable
if [[ -z "${CODACY_PROJECT_TOKEN:-}" ]]; then
echo "Error: CODACY_PROJECT_TOKEN environment variable not set"
exit 1
fi
echo "==> Building solution..."
dotnet build --no-incremental
echo "==> Running tests with coverage..."
dotnet test --no-build --collect:"XPlat Code Coverage" \
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
# Find the coverage file
COVERAGE_FILE=$(find . -name "coverage.opencover.xml" -type f | head -1)
if [[ -z "$COVERAGE_FILE" ]]; then
echo "Error: No coverage file found"
exit 1
fi
echo "==> Uploading coverage to Codacy..."
echo " Coverage file: $COVERAGE_FILE"
bash <(curl -Ls https://coverage.codacy.com/get.sh) report \
-r "$COVERAGE_FILE" \
--project-token "$CODACY_PROJECT_TOKEN"
echo "==> Done! View results at https://app.codacy.com/gh/mihakralj/QuanTAlib"
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
set -euo pipefail
# Static Analysis Scanner for QuanTAlib
# Runs SonarCloud and Qodana with code coverage
# Tokens must be set as environment variables
if [[ -z "${SONAR_TOKEN:-}" ]]; then
echo "Error: SONAR_TOKEN environment variable not set"
exit 1
fi
if [[ -z "${QODANA_TOKEN:-}" ]]; then
echo "Error: QODANA_TOKEN environment variable not set"
exit 1
fi
# Coverage output directory for Qodana
COVERAGE_DIR=".qodana/code-coverage"
echo "==> Building solution..."
dotnet build --no-incremental
echo "==> Running tests with coverage..."
mkdir -p "$COVERAGE_DIR"
dotnet test --no-build --collect:"XPlat Code Coverage" \
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=lcov
# Copy coverage to Qodana directory
find . -name "coverage.info" -exec cp {} "$COVERAGE_DIR/" \;
# Run SonarCloud
echo "==> Starting SonarScanner analysis..."
# Re-run tests with OpenCover format for SonarCloud
dotnet test --no-build --collect:"XPlat Code Coverage" \
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
dotnet sonarscanner begin \
/o:"mihakralj-quantalib" \
/k:"mihakralj_QuanTAlib" \
/d:sonar.token="$SONAR_TOKEN" \
/d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml"
dotnet build --no-incremental
dotnet sonarscanner end /d:sonar.token="$SONAR_TOKEN"
echo "==> SonarCloud: https://sonarcloud.io/project/overview?id=mihakralj_QuanTAlib"
# Run Qodana
echo "==> Starting Qodana analysis..."
QODANA_TOKEN="$QODANA_TOKEN" qodana scan \
--coverage-dir "$COVERAGE_DIR"
echo "==> Qodana analysis complete"
echo "==> Done!"
+8 -4
View File
@@ -396,6 +396,10 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
.idea/
# SonarQube/SonarCloud
.sonarqube/
# Cline Memory Bank - exclude from git
memory-bank/
@@ -405,7 +409,7 @@ memory-bank/
.DS_Store
.AppleDouble
.LSOverride
#Ignore insiders AI rules
.github/instructions/codacy.instructions.md
#Ignore insiders AI rules
.github/instructions/codacy.instructions.md
-1
View File
@@ -64,7 +64,6 @@ Console.WriteLine($"Current SMA: {result.Value}");
// Access properties
Console.WriteLine($"Name: {sma.Name}"); // "Sma(10)"
Console.WriteLine($"WarmupPeriod: {sma.WarmupPeriod}"); // 10
Console.WriteLine($"IsHot: {sma.IsHot}"); // true when buffer is full
// Batch calculation (TSeries API)
-1
View File
@@ -79,7 +79,6 @@ Console.WriteLine($"Current WMA: {result.Value}");
// Access properties
Console.WriteLine($"Name: {wma.Name}"); // "Wma(10)"
Console.WriteLine($"WarmupPeriod: {wma.WarmupPeriod}"); // 10
Console.WriteLine($"IsHot: {wma.IsHot}"); // true when buffer is full
// Batch calculation (TSeries API)
+2
View File
@@ -68,6 +68,7 @@ public readonly struct TBar : IEquatable<TBar>
public override string ToString() => $"[{AsDateTime:yyyy-MM-dd HH:mm:ss}: O={Open:F2}, H={High:F2}, L={Low:F2}, C={Close:F2}, V={Volume:F2}]";
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#pragma warning disable S1244 // Floating point equality is intentional for exact struct comparison
public bool Equals(TBar other) =>
Time == other.Time &&
Open == other.Open &&
@@ -75,6 +76,7 @@ public readonly struct TBar : IEquatable<TBar>
Low == other.Low &&
Close == other.Close &&
Volume == other.Volume;
#pragma warning restore S1244
public override bool Equals(object? obj) => obj is TBar other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Time, Open, High, Low, Close, Volume);
+7 -4
View File
@@ -8,7 +8,9 @@ namespace QuanTAlib;
/// Stateless design - only maintains minimal state needed for price continuity.
/// </summary>
[SkipLocalsInit]
#pragma warning disable S101 // Types should be named in PascalCase - GBM is a standard acronym
public class GBM : IFeed
#pragma warning restore S101
{
private readonly Random _rnd;
@@ -17,7 +19,6 @@ public class GBM : IFeed
private readonly double _mu;
private readonly double _sigma;
private readonly double _dt;
// Precomputed GBM constants
private readonly double _drift;
@@ -63,10 +64,10 @@ public class GBM : IFeed
// Calculate dt based on timeframe (assuming 252 trading days/year, 6.5 hours/day)
double minutesPerYear = 252.0 * 6.5 * 60.0;
_dt = timeframe.TotalMinutes / minutesPerYear;
double dt = timeframe.TotalMinutes / minutesPerYear;
_drift = (mu - 0.5 * sigma * sigma) * _dt;
_vol = sigma * Math.Sqrt(_dt);
_drift = (mu - 0.5 * sigma * sigma) * dt;
_vol = sigma * Math.Sqrt(dt);
}
/// <summary>
@@ -81,8 +82,10 @@ public class GBM : IFeed
return _cachedZ;
}
#pragma warning disable S2245 // Random is acceptable for simulation/testing purposes
double u1 = 1.0 - _rnd.NextDouble();
double u2 = 1.0 - _rnd.NextDouble();
#pragma warning restore S2245
double mag = Math.Sqrt(-2.0 * Math.Log(u1));
double angle = 2.0 * Math.PI * u2;