Merge branch 'dev'

This commit is contained in:
Miha Kralj
2024-10-05 23:56:59 -07:00
13 changed files with 1389 additions and 1159 deletions
+20
View File
@@ -0,0 +1,20 @@
version = 1
[[analyzers]]
name = "csharp"
enabled = true
[analyzers.meta]
language_version = "11.0"
[[analyzers]]
name = "test-coverage"
enabled = true
[[analyzers]]
name = "secrets"
enabled = true
[[transformers]]
name = "dotnet-format"
enabled = true
+306
View File
@@ -0,0 +1,306 @@
# This workflow integrates SonarCloud analysis, coverage reporting,
# CodeQL analysis, SecurityCodeScan, and Codacy Security Scan
# for code scanning and vulnerability detection.
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
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
jobs:
SonarCloud:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Install JDK11 for Sonar Scanner
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'zulu'
- name: Install dotnet-sonarscanner
run: |
dotnet tool install --global dotnet-sonarscanner
dotnet tool install JetBrains.dotCover.GlobalTool --global
dotnet tool install dotnet-coverage --global
dotnet restore
- name: SonarCloud Scanner Start
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
dotnet sonarscanner begin \
/k:"mihakralj_QuanTAlib" \
/o:"mihakralj" \
/d:sonar.login="${{ secrets.SONAR_TOKEN }}" \
/d:sonar.host.url="https://sonarcloud.io" \
/d:sonar.cs.dotcover.reportsPaths=dotcover*
- name: Build
run: |
dotnet build --no-restore --configuration Debug
dotnet build ./lib/quantalib.csproj --configuration Release --nologo
dotnet build ./quantower/Averages/Averages.csproj --configuration Release --nologo
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
dotnet dotcover test Tests/Tests.csproj --dcReportType=HTML --dcoutput=./dotcover.html
- name: SonarCloud Scanner End
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: dotnet sonarscanner end /d:sonar.login="${{ secrets.SONAR_TOKEN }}"
Code_Coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Install dotnet tools
run: |
dotnet tool install JetBrains.dotCover.GlobalTool --global
dotnet tool install dotnet-sonarscanner --global
dotnet tool install dotnet-coverage --global
dotnet tool install --global coverlet.console
dotnet tool install --global dotnet-reportgenerator-globaltool
dotnet restore
- name: Build Projects
run: |
dotnet build --no-restore --configuration Debug
dotnet build ./lib/quantalib.csproj --configuration Release --nologo
dotnet build ./quantower/Averages/Averages.csproj --configuration Release --nologo
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
- name: Run Tests with Coverage
run: |
dotnet test --no-build --configuration Debug /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
dotnet dotcover test Tests/Tests.csproj --dcReportType=HTML --dcoutput=./dotcover.html
dotnet dotcover test Tests/Tests.csproj --dcReportType=DetailedXML --dcoutput=./dotcover.xml --verbosity=Detailed
dotnet test -p:CollectCoverage=true --collect:"XPlat Code Coverage" --results-directory "./"
- name: Generate Coverage Report
run: |
reportgenerator -reports:*cover*.xml -targetdir:.
- name: Upload Coverage to Codacy
uses: codacy/codacy-coverage-reporter-action@v1
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: '*cover*.xml'
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: 'cover*'
verbose: true
CodeQL:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: 'csharp'
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Debug
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
SecurityCodeScan:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup NuGet
uses: nuget/setup-nuget@v1
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '3.1.x'
- name: Set up projects for analysis
uses: security-code-scan/security-code-scan-add-action@v1
- name: Restore dependencies
run: dotnet restore
- name: Build
run: 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
Codacy_Scan:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- 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: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
build_publish:
needs: [SonarCloud, Code_Coverage, CodeQL, SecurityCodeScan, Codacy_Scan]
if: success()
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
- name: Install GitVersion
uses: gittools/actions/gitversion/setup@v0
with:
versionSpec: '6.x'
includePrerelease: true
- name: Determine Version
id: gitversion
uses: gittools/actions/gitversion/execute@v0
with:
useConfigFile: true
updateAssemblyInfo: true
- name: Build projects
run: |
dotnet build ./lib/quantalib.csproj --configuration Release --nologo \
-p:PackageVersion=${{ steps.gitversion.outputs.MajorMinorPatch }}
dotnet build ./quantower/Averages/Averages.csproj --configuration Release --nologo
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
############# Publish dev release
- name: Update Development Release
if: github.ref == 'refs/heads/dev'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MYGET_URL: https://www.myget.org/feed/quantalib/package/nuget/QuanTAlib
PACKAGE_VERSION: ${{ steps.gitversion.outputs.NuGetVersion }}
run: |
tag_name="development"
release_name="Development Build"
gh release delete $tag_name --yes || true
git push origin :refs/tags/$tag_name || true
gh release create $tag_name \
--title "$release_name" \
--notes "Latest development build from commit ${{ github.sha }}
MyGet Package: [$MYGET_URL/$PACKAGE_VERSION]($MYGET_URL/$PACKAGE_VERSION) \n" \
--prerelease \
--target ${{ github.sha }} \
quantower/Averages/bin/Release/Averages.dll \
quantower/Statistics/bin/Release/Statistics.dll \
quantower/Volatility/bin/Release/Volatility.dll \
SyntheticVendor/bin/Release/SyntheticVendor.dll
- name: Push prerelease package to myget.org
if: github.ref == 'refs/heads/dev'
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
- name: Publish release assets
if: ${{ github.ref == 'refs/heads/main' }}
uses: SourceSprint/upload-multiple-releases@1.0.7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
prerelease: false
overwrite: true
release_name: ${{ steps.gitversion.outputs.MajorMinorPatch }}
tag_name: latest
release_config: |
quantower/Averages/bin/Release/Averages.dll
quantower/Statistics/bin/Release/Statistics.dll
quantower/Volatility/bin/Release/Volatility.dll
SyntheticVendor/bin/Release/SyntheticVendor.dll
- name: Push release package to nuget.org
if: ${{ github.ref == 'refs/heads/main' }}
run: dotnet nuget push 'lib/bin/Release/QuanTAlib.*.nupkg' \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate \
--api-key ${{ secrets.NUGET_DEPLOY_KEY_QUANTLIB }}
-61
View File
@@ -1,61 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '17 22 * * 0'
permissions:
contents: read
jobs:
codacy-security-scan:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
-92
View File
@@ -1,92 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '40 12 * * 1'
jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write
# required to fetch internal or private CodeQL packs
packages: read
# only required for workflows in private repositories
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: csharp
build-mode: autobuild
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
+29
View File
@@ -20,6 +20,33 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat> <SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<IsLocalBuild Condition="'$(GITHUB_ACTIONS)' == ''">true</IsLocalBuild> <IsLocalBuild Condition="'$(GITHUB_ACTIONS)' == ''">true</IsLocalBuild>
<!-- GitVersion Properties -->
<Version>$(GitVersion_NuGetVersion)</Version>
<AssemblyVersion>$(GitVersion_AssemblySemVer)</AssemblyVersion>
<FileVersion>$(GitVersion_AssemblySemFileVer)</FileVersion>
<InformationalVersion>$(GitVersion_InformationalVersion)</InformationalVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<PublishAot>true</PublishAot>
<PublishReadyToRun>true</PublishReadyToRun>
<TieredCompilation>true</TieredCompilation>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<PublishSingleFile>true</PublishSingleFile>
<DebugSymbols>false</DebugSymbols>
<Deterministic>true</Deterministic>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<InvariantGlobalization>true</InvariantGlobalization>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
@@ -36,3 +63,5 @@
</PropertyGroup> </PropertyGroup>
</Project> </Project>
+13 -4
View File
@@ -18,19 +18,28 @@ branches:
source-branches: [] source-branches: []
tracks-release-branches: false tracks-release-branches: false
is-release-branch: true is-release-branch: true
is-main-branch: true
pre-release-weight: 55000 pre-release-weight: 55000
dev: dev:
regex: ^dev(elop)?(ment)?$ regex: ^dev$
mode: ContinuousDelivery mode: ContinuousDelivery
label: dev label: ''
increment: Patch
track-merge-target: true
source-branches: ['main']
tracks-release-branches: true
is-release-branch: false
pre-release-weight: 0
develop:
regex: ^develop$
mode: ContinuousDelivery
label: ''
increment: Patch increment: Patch
track-merge-target: true track-merge-target: true
source-branches: ['main'] source-branches: ['main']
tracks-release-branches: true tracks-release-branches: true
is-release-branch: false is-release-branch: false
is-main-branch: false
pre-release-weight: 0 pre-release-weight: 0
ignore: ignore:
+40 -37
View File
@@ -3,11 +3,15 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using TradingPlatform.BusinessLayer; using TradingPlatform.BusinessLayer;
using TradingPlatform.BusinessLayer.Integration; using TradingPlatform.BusinessLayer.Integration;
using System.Diagnostics.CodeAnalysis;
namespace SyntheticVendorNamespace
namespace SyntheticVendorNamespace;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class SyntheticVendor : Vendor
{ {
public class SyntheticVendor : Vendor
{
private readonly List<MessageExchange> exchanges; private readonly List<MessageExchange> exchanges;
private readonly List<MessageAsset> assets; private readonly List<MessageAsset> assets;
private readonly List<MessageSymbol> symbols; private readonly List<MessageSymbol> symbols;
@@ -73,7 +77,7 @@ namespace SyntheticVendorNamespace
CreateMessageSymbol("W17", "2 Geometric Brownian motion", "QT", "USD", SymbolType.Synthetic) CreateMessageSymbol("W17", "2 Geometric Brownian motion", "QT", "USD", SymbolType.Synthetic)
}; };
/* /*
Bond, Bond,
CFD, CFD,
Crypto, Crypto,
@@ -91,7 +95,7 @@ namespace SyntheticVendorNamespace
Swap, Swap,
Warrants, Warrants,
*/ */
@@ -173,7 +177,7 @@ namespace SyntheticVendorNamespace
LotStep = 0.01, LotStep = 0.01,
MaxLot = 1000000, MaxLot = 1000000,
SymbolType = type SymbolType = type
/* /*
SymbolType.Unknown, SymbolType.Unknown,
[EnumMember] Forex, [EnumMember] Forex,
[EnumMember] Equities, [EnumMember] Equities,
@@ -192,7 +196,7 @@ namespace SyntheticVendorNamespace
[EnumMember] Debentures, [EnumMember] Debentures,
[EnumMember] Bond, [EnumMember] Bond,
[EnumMember] Swap, [EnumMember] Swap,
*/ */
}; };
} }
@@ -360,13 +364,13 @@ namespace SyntheticVendorNamespace
} }
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
/*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/
private HistoryItemBar GenerateSpike(DateTime time, TimeSpan slice) private HistoryItemBar GenerateSpike(DateTime time, TimeSpan slice)
{ {
@@ -497,7 +501,7 @@ namespace SyntheticVendorNamespace
double value = 50 + 50 * Math.Sin(cyclePosition * frequency); // Oscillate between 0 and 100 double value = 50 + 50 * Math.Sin(cyclePosition * frequency); // Oscillate between 0 and 100
double nextValue = 50 + 50 * Math.Sin((cyclePosition + slice.TotalMinutes) * frequency); double nextValue = 50 + 50 * Math.Sin((cyclePosition + slice.TotalMinutes) * frequency);
double factor = 0.6 * Math.Abs (nextValue - value); double factor = 0.6 * Math.Abs(nextValue - value);
return new HistoryItemBar return new HistoryItemBar
{ {
@@ -505,8 +509,8 @@ namespace SyntheticVendorNamespace
TicksRight = time.Add(slice).Ticks - 1, TicksRight = time.Add(slice).Ticks - 1,
Open = value, Open = value,
High = Math.Max(value, nextValue)+factor, High = Math.Max(value, nextValue) + factor,
Low = Math.Min(value, nextValue)-factor, Low = Math.Min(value, nextValue) - factor,
Close = nextValue, Close = nextValue,
Volume = Math.Abs(nextValue - value) * 100, // Volume proportional to price change Volume = Math.Abs(nextValue - value) * 100, // Volume proportional to price change
@@ -921,11 +925,11 @@ namespace SyntheticVendorNamespace
private double previousClose = 50; private double previousClose = 50;
private const double meanPrice = 50; private const double meanPrice = 50;
private HistoryItemBar GeneratePinkNoise(DateTime time, TimeSpan slice) private HistoryItemBar GeneratePinkNoise(DateTime time, TimeSpan slice)
{ {
double volatility = 2; double volatility = 2;
double meanReversionStrength = 0.1; double meanReversionStrength = 0.1;
@@ -964,7 +968,7 @@ private HistoryItemBar GeneratePinkNoise(DateTime time, TimeSpan slice)
Volume = volume, Volume = volume,
Ticks = slice.Ticks Ticks = slice.Ticks
}; };
} }
private const int NumOctaves = 6; private const int NumOctaves = 6;
@@ -986,10 +990,10 @@ private HistoryItemBar GeneratePinkNoise(DateTime time, TimeSpan slice)
private double lastValue = 0; private double lastValue = 0;
private HistoryItemBar GenerateBrownNoise(DateTime time, TimeSpan slice) private HistoryItemBar GenerateBrownNoise(DateTime time, TimeSpan slice)
{ {
double dt = slice.TotalDays / 365.0; // Time step in years double dt = slice.TotalDays / 365.0; // Time step in years
double sigma = 25.0; // Annual volatility double sigma = 25.0; // Annual volatility
@@ -1016,24 +1020,24 @@ private HistoryItemBar GenerateBrownNoise(DateTime time, TimeSpan slice)
Volume = Math.Abs(close - open) * 1000, // Simplified volume calculation Volume = Math.Abs(close - open) * 1000, // Simplified volume calculation
Ticks = slice.Ticks Ticks = slice.Ticks
}; };
} }
// Helper method to generate Gaussian distributed random numbers // Helper method to generate Gaussian distributed random numbers
private double GenerateGaussian(double mean, double stdDev) private double GenerateGaussian(double mean, double stdDev)
{ {
double u1 = 1.0 - random.NextDouble(); // Uniform(0,1] random doubles double u1 = 1.0 - random.NextDouble(); // Uniform(0,1] random doubles
double u2 = 1.0 - random.NextDouble(); double u2 = 1.0 - random.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2); double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
return mean + stdDev * randStdNormal; return mean + stdDev * randStdNormal;
} }
private double GBMLastClose = 100; // Starting price private double GBMLastClose = 100; // Starting price
private double GBMMu = 0.05; // Annual drift private double GBMMu = 0.05; // Annual drift
private double GBMSigma = 0.2; // Annual volatility private double GBMSigma = 0.2; // Annual volatility
private HistoryItemBar GenerateGBM(DateTime time, TimeSpan slice) private HistoryItemBar GenerateGBM(DateTime time, TimeSpan slice)
{ {
// Convert time slice to years // Convert time slice to years
double dt = slice.TotalDays / 365.0; double dt = slice.TotalDays / 365.0;
@@ -1074,7 +1078,7 @@ private HistoryItemBar GenerateGBM(DateTime time, TimeSpan slice)
Volume = volume, Volume = volume,
Ticks = slice.Ticks Ticks = slice.Ticks
}; };
} }
private double FBMLastClose = 100; // Starting price private double FBMLastClose = 100; // Starting price
private double FBMHurst = 0.85; // Hurst parameter (0.5 < H < 1 for persistent fBm) private double FBMHurst = 0.85; // Hurst parameter (0.5 < H < 1 for persistent fBm)
@@ -1135,5 +1139,4 @@ private HistoryItemBar GenerateGBM(DateTime time, TimeSpan slice)
// Add other necessary overrides and implementations as needed // Add other necessary overrides and implementations as needed
}
} }
+5 -1
View File
@@ -2,7 +2,11 @@ using Xunit;
using Trady.Analysis.Indicator; using Trady.Analysis.Indicator;
using Trady.Core; using Trady.Core;
using Trady.Core.Infrastructure; using Trady.Core.Infrastructure;
using QuanTAlib; using System.Diagnostics.CodeAnalysis;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class TradyTests public class TradyTests
{ {
+4 -4
View File
@@ -1,7 +1,10 @@
using Xunit; using Xunit;
using Tulip; using Tulip;
using QuanTAlib; using System.Diagnostics.CodeAnalysis;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class TulipTests public class TulipTests
{ {
private readonly TBarSeries bars; private readonly TBarSeries bars;
@@ -71,10 +74,7 @@ public class TulipTests
double QL_item = QL[i].Value; double QL_item = QL[i].Value;
double TU = arrout[0][i]; double TU = arrout[0][i];
Assert.True(Math.Abs(TU - QL_item) <= range, $"Assertion failed at index {i} for period {period}: TU = {TU}, QL_item = {QL_item}, delta = {TU - QL_item}"); Assert.True(Math.Abs(TU - QL_item) <= range, $"Assertion failed at index {i} for period {period}: TU = {TU}, QL_item = {QL_item}, delta = {TU - QL_item}");
} }
} }
} }
} }
+7 -5
View File
@@ -1,10 +1,13 @@
using Xunit; using Xunit;
using System.Reflection; using System.Reflection;
using System.Diagnostics.CodeAnalysis;
namespace QuanTAlib namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class BarIndicatorTests
{ {
public class BarIndicatorTests
{
private readonly Random rnd; private readonly Random rnd;
private const int SeriesLen = 1000; private const int SeriesLen = 1000;
private const int Corrections = 100; private const int Corrections = 100;
@@ -43,7 +46,7 @@ namespace QuanTAlib
calcMethod.Invoke(indicator1, new object[] { item1 }); calcMethod.Invoke(indicator1, new object[] { item1 });
} }
var item2 = new TBar (item1.Time, item1.Open, item1.High, item1.Low, item1.Close, item1.Volume , IsNew: true); var item2 = new TBar(item1.Time, item1.Open, item1.High, item1.Low, item1.Close, item1.Volume, IsNew: true);
calcMethod.Invoke(indicator2, new object[] { item2 }); calcMethod.Invoke(indicator2, new object[] { item2 });
Assert.Equal(indicator1.Value, indicator2.Value); Assert.Equal(indicator1.Value, indicator2.Value);
@@ -54,5 +57,4 @@ namespace QuanTAlib
{ {
return indicators.Select(indicator => new object[] { indicator }); return indicators.Select(indicator => new object[] { indicator });
} }
}
} }
+6 -4
View File
@@ -1,10 +1,13 @@
using Xunit; using Xunit;
using System.Reflection; using System.Reflection;
using System.Diagnostics.CodeAnalysis;
namespace QuanTAlib namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class IndicatorTests
{ {
public class IndicatorTests
{
private readonly Random rnd; private readonly Random rnd;
private const int SeriesLen = 1000; private const int SeriesLen = 1000;
private const int Corrections = 100; private const int Corrections = 100;
@@ -94,5 +97,4 @@ namespace QuanTAlib
{ {
return indicators.Select(indicator => new object[] { indicator }); return indicators.Select(indicator => new object[] { indicator });
} }
}
} }
+5 -1
View File
@@ -1,6 +1,10 @@
using Xunit; using Xunit;
using Skender.Stock.Indicators; using Skender.Stock.Indicators;
using QuanTAlib; using System.Diagnostics.CodeAnalysis;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class SkenderTests public class SkenderTests
{ {
+5 -1
View File
@@ -1,6 +1,10 @@
using Xunit; using Xunit;
using TALib; using TALib;
using QuanTAlib; using System.Diagnostics.CodeAnalysis;
namespace QuanTAlib;
[SuppressMessage("Security", "SCS0005:Weak random number generator.", Justification = "Acceptable for tests")]
public class TAlibTests public class TAlibTests
{ {