This commit is contained in:
Miha Kralj
2024-11-03 11:55:39 -08:00
parent 7b41d84c66
commit 7f6c29151c
7 changed files with 162 additions and 104 deletions
+22
View File
@@ -0,0 +1,22 @@
name: "CodeQL Config"
queries:
- uses: security-and-quality
- uses: security-extended
paths-ignore:
- '**/test/**'
- '**/tests/**'
- '**/*.test.cs'
- '**/obj/**'
- '**/bin/**'
- '**/docs/**'
query-filters:
- exclude:
problem.severity:
- warning
- recommendation
paths:
- src
+125 -62
View File
@@ -1,17 +1,37 @@
name: Publish Workflow
on:
push: # Triggers on push events to any branch
pull_request: # Triggers on pull request events targeting any branch
workflow_dispatch: # Allows manual triggering of the workflow
push:
paths-ignore:
- '**.md'
- 'docs/**'
- '.gitignore'
- 'LICENSE'
pull_request:
paths-ignore:
- '**.md'
- 'docs/**'
- '.gitignore'
- 'LICENSE'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: read # Allows SonarCloud to decorate PRs with analysis results
security-events: write # Required for CodeQL analysis and uploading SARIF results
env:
DOTNET_VERSION: '8.x'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
jobs:
Code_Coverage:
timeout-minutes: 30
runs-on: windows-latest
steps:
- name: Checkout repository
@@ -22,7 +42,20 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: ${{ runner.os }}-nuget-
- name: Cache dotnet tools
uses: actions/cache@v4
with:
path: ~/.dotnet/tools
key: ${{ runner.os }}-dotnet-tools-${{ hashFiles('**/*.csproj') }}
- name: Set up JDK 17
uses: actions/setup-java@v4
@@ -69,6 +102,8 @@ jobs:
/d:sonar.verbose="true"
- name: Build Projects
id: build
continue-on-error: true
run: |
dotnet build --no-restore --configuration Debug
dotnet build ./lib/quantalib.csproj --configuration Release --nologo
@@ -76,8 +111,15 @@ jobs:
dotnet build ./quantower/Statistics/_Statistics.csproj --configuration Release --nologo
dotnet build ./quantower/Volatility/_Volatility.csproj --configuration Release --nologo
dotnet build ./SyntheticVendor/SyntheticVendor.csproj --configuration Release --nologo
if ($LASTEXITCODE -ne 0) { Write-Error "Build failed" }
- name: Check Build Status
if: steps.build.outcome == 'failure'
run: exit 1
- name: Run Tests with Coverage
id: tests
continue-on-error: true
run: |
dotnet test --no-build --configuration Debug /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
@@ -87,9 +129,21 @@ jobs:
- name: Generate Coverage Report
run: |
reportgenerator -reports:*cover*.xml -targetdir:.
reportgenerator -reports:*cover*.xml -targetdir:./coverage-report
- name: Upload Coverage Reports
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-reports
path: |
**/TestResults
**/coverage-report
**/*cover*.xml
**/dotcover.*
- name: End SonarCloud Analysis
if: always()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
@@ -109,7 +163,13 @@ jobs:
verbose: true
CodeQL:
timeout-minutes: 30
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -119,12 +179,22 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: ${{ runner.os }}-nuget-
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: 'csharp'
queries: security-and-quality
config-file: ./.github/codeql/codeql-config.yml
tools: latest
- name: Restore dependencies
run: dotnet restore
@@ -132,63 +202,51 @@ jobs:
- name: Build
run: dotnet build --no-restore --configuration Debug
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@v4
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
gh-code-scanning-compat: true
max-allowed-issues: 2147483647
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
output: results
upload: true
SecurityCodeScan:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/dotnet@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
LD_PRELOAD: '' # Clear the LD_PRELOAD to avoid CodeQL conflicts
with:
fetch-depth: 0
args: |
--file=./lib/quantalib.csproj
--severity-threshold=low
--detection-depth=4
--package-manager=nuget
- name: Setup NuGet
uses: nuget/setup-nuget@v2
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
- name: Run Snyk on Solution
uses: snyk/actions/dotnet@master
if: always()
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
LD_PRELOAD: ''
with:
dotnet-version: |
8.x
3.1.x
dotnet-quality: 'preview'
- name: Set up projects for analysis
uses: security-code-scan/security-code-scan-add-action@v1
- name: Build
run: |
dotnet restore
dotnet build --no-restore --configuration Debug
- name: Convert SARIF for uploading to GitHub
uses: security-code-scan/security-code-scan-results-action@v1
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
args: |
--file=QuanTAlib.sln
--all-projects
--detection-depth=4
- name: Run Snyk IaC
uses: snyk/actions/iac@master
continue-on-error: true
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
LD_PRELOAD: ''
with:
args: |
--severity-threshold=low
build_publish:
needs: [Code_Coverage, CodeQL, SecurityCodeScan]
timeout-minutes: 20
needs: [Code_Coverage, CodeQL]
if: |
success() &&
(github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) ||
@@ -203,7 +261,14 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.x'
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
restore-keys: ${{ runner.os }}-nuget-
- name: Install GitVersion
uses: gittools/actions/gitversion/setup@v0
@@ -227,8 +292,6 @@ jobs:
dotnet build ./quantower/Volatility/_Volatility.csproj --configuration Release --nologo
dotnet build ./SyntheticVendor/SyntheticVendor.csproj --configuration Release --nologo
############# Publish dev release
- name: Create or Update Development Release
if: github.ref == 'refs/heads/dev'
env:
@@ -248,16 +311,16 @@ jobs:
- name: Push prerelease package to myget.org
if: github.ref == 'refs/heads/dev'
continue-on-error: true
id: myget-push
run: |
dotnet nuget push 'lib/bin/Release/QuanTAlib.*.nupkg' \
--source https://www.myget.org/F/quantalib/api/v3/index.json \
--force-english-output \
--api-key ${{ secrets.MYGET_DEPLOY_KEY_QUANTALIB }}
############## Publish main release
--source https://www.myget.org/F/quantalib/api/v3/index.json \
--force-english-output \
--api-key ${{ secrets.MYGET_DEPLOY_KEY_QUANTALIB }}
- name: Create GitHub Release
if: ${{ github.ref == 'refs/heads/main' }}
if: github.ref == 'refs/heads/main'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
-19
View File
@@ -597,25 +597,6 @@ public class SyntheticVendor : Vendor
};
}
private HistoryItemBar GeneratePulseWave(DateTime time, TimeSpan slice)
{
double hours = (time - DateTime.UnixEpoch).TotalHours;
double period = 24; // 24-hour period
double position = hours % period;
double value = position < period / 5 ? 100 : -100; // 20% duty cycle
return new HistoryItemBar
{
TicksLeft = time.Ticks,
TicksRight = time.Add(slice).Ticks - 1,
Open = value,
High = 100,
Low = -100,
Close = value,
Volume = 100,
Ticks = 100
};
}
private HistoryItemBar GenerateTriangleWave(DateTime time, TimeSpan slice)
{
+2 -2
View File
@@ -22,7 +22,7 @@ namespace QuanTAlib;
public class Dsma : AbstractBase
{
private readonly CircularBuffer _buffer;
private readonly double _c1, _c2, _c3;
private readonly double _c2, _c3;
private readonly double _scaleFactor;
private readonly double _periodRecip; // 1/_period
private readonly double _scaleByPeriod; // 5/_period
@@ -59,7 +59,7 @@ public class Dsma : AbstractBase
_c2 = b1;
_c3 = -a1 * a1;
_c1 = 1.0 - _c2 - _c3;
double _c1 = 1.0 - _c2 - _c3;
_c1Half = _c1 * 0.5;
_scaleByPeriod = 5.0 / period;
+1 -3
View File
@@ -53,7 +53,6 @@ public sealed class Cv : AbstractBase
private readonly double _omega;
private double _prevClose;
private double _prevVariance;
private double _longTermVariance;
private bool _isInitialized;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -82,7 +81,6 @@ public sealed class Cv : AbstractBase
base.Init();
_prevClose = 0;
_prevVariance = 0;
_longTermVariance = 0;
_isInitialized = false;
}
@@ -116,7 +114,7 @@ public sealed class Cv : AbstractBase
// Initialize with first available data if not done
if (!_isInitialized && _index > _period)
{
_longTermVariance = squaredReturn; // Use current squared return as initial estimate
double _longTermVariance = squaredReturn; // Use current squared return as initial estimate
_prevVariance = _longTermVariance;
_isInitialized = true;
}
+3 -5
View File
@@ -41,7 +41,6 @@ namespace QuanTAlib;
public sealed class Cvi : AbstractBase
{
private readonly int _period;
private readonly int _smoothPeriod;
private readonly CircularBuffer _smoothed;
private readonly double _alpha;
private double _ema;
@@ -50,10 +49,9 @@ public sealed class Cvi : AbstractBase
public Cvi(int period = 10, int smoothPeriod = 10)
{
_period = period;
_smoothPeriod = smoothPeriod;
_alpha = 2.0 / (_smoothPeriod + 1);
WarmupPeriod = _period + _smoothPeriod;
Name = $"CVI({_period},{_smoothPeriod})";
_alpha = 2.0 / (smoothPeriod + 1);
WarmupPeriod = _period + smoothPeriod;
Name = $"CVI({_period},{smoothPeriod})";
_smoothed = new CircularBuffer(_period);
Init();
}
+9 -13
View File
@@ -42,7 +42,6 @@ namespace QuanTAlib;
[SkipLocalsInit]
public sealed class Fcb : AbstractBase
{
private readonly int _period;
private readonly double _smoothing;
private readonly CircularBuffer _highs;
private readonly CircularBuffer _lows;
@@ -56,11 +55,10 @@ public sealed class Fcb : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Fcb(int period = 20, double smoothing = 0.5)
{
_period = period;
_smoothing = smoothing;
_alpha = 2.0 / (_period + 1);
_alpha = 2.0 / (period + 1);
WarmupPeriod = period + 4; // Need extra periods for fractal identification
Name = $"FCB({_period},{_smoothing})";
Name = $"FCB({period},{_smoothing})";
_highs = new CircularBuffer(period);
_lows = new CircularBuffer(period);
Init();
@@ -116,16 +114,14 @@ public sealed class Fcb : AbstractBase
bool isFractalHigh = false;
bool isFractalLow = false;
if (_index >= 5)
{
// Fractal high: current high is higher than 2 bars before and after
isFractalHigh = _highs[2] > _highs[0] && _highs[2] > _highs[1] &&
_highs[2] > _highs[3] && _highs[2] > _highs[4];
// Fractal high: current high is higher than 2 bars before and after
isFractalHigh = _highs[2] > _highs[0] && _highs[2] > _highs[1] &&
_highs[2] > _highs[3] && _highs[2] > _highs[4];
// Fractal low: current low is lower than 2 bars before and after
isFractalLow = _lows[2] < _lows[0] && _lows[2] < _lows[1] &&
_lows[2] < _lows[3] && _lows[2] < _lows[4];
// Fractal low: current low is lower than 2 bars before and after
isFractalLow = _lows[2] < _lows[0] && _lows[2] < _lows[1] &&
_lows[2] < _lows[3] && _lows[2] < _lows[4];
}
// Update EMAs with fractal points
if (isFractalHigh)