mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-22 04:28:04 +00:00
Fixes
This commit is contained in:
@@ -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
@@ -1,17 +1,37 @@
|
|||||||
name: Publish Workflow
|
name: Publish Workflow
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push: # Triggers on push events to any branch
|
push:
|
||||||
pull_request: # Triggers on pull request events targeting any branch
|
paths-ignore:
|
||||||
workflow_dispatch: # Allows manual triggering of the workflow
|
- '**.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:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
pull-requests: read # Allows SonarCloud to decorate PRs with analysis results
|
pull-requests: read # Allows SonarCloud to decorate PRs with analysis results
|
||||||
security-events: write # Required for CodeQL analysis and uploading SARIF 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:
|
jobs:
|
||||||
Code_Coverage:
|
Code_Coverage:
|
||||||
|
timeout-minutes: 30
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
@@ -22,7 +42,20 @@ jobs:
|
|||||||
- name: Setup .NET SDK
|
- name: Setup .NET SDK
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
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
|
- name: Set up JDK 17
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
@@ -69,6 +102,8 @@ jobs:
|
|||||||
/d:sonar.verbose="true"
|
/d:sonar.verbose="true"
|
||||||
|
|
||||||
- name: Build Projects
|
- name: Build Projects
|
||||||
|
id: build
|
||||||
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
dotnet build --no-restore --configuration Debug
|
dotnet build --no-restore --configuration Debug
|
||||||
dotnet build ./lib/quantalib.csproj --configuration Release --nologo
|
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/Statistics/_Statistics.csproj --configuration Release --nologo
|
||||||
dotnet build ./quantower/Volatility/_Volatility.csproj --configuration Release --nologo
|
dotnet build ./quantower/Volatility/_Volatility.csproj --configuration Release --nologo
|
||||||
dotnet build ./SyntheticVendor/SyntheticVendor.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
|
- name: Run Tests with Coverage
|
||||||
|
id: tests
|
||||||
|
continue-on-error: true
|
||||||
run: |
|
run: |
|
||||||
dotnet test --no-build --configuration Debug /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
|
dotnet test --no-build --configuration Debug /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
|
||||||
dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
|
dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
|
||||||
@@ -87,9 +129,21 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate Coverage Report
|
- name: Generate Coverage Report
|
||||||
run: |
|
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
|
- name: End SonarCloud Analysis
|
||||||
|
if: always()
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
@@ -109,7 +163,13 @@ jobs:
|
|||||||
verbose: true
|
verbose: true
|
||||||
|
|
||||||
CodeQL:
|
CodeQL:
|
||||||
|
timeout-minutes: 30
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -119,12 +179,22 @@ jobs:
|
|||||||
- name: Setup .NET SDK
|
- name: Setup .NET SDK
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
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
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: 'csharp'
|
languages: 'csharp'
|
||||||
|
queries: security-and-quality
|
||||||
|
config-file: ./.github/codeql/codeql-config.yml
|
||||||
|
tools: latest
|
||||||
|
|
||||||
- name: Restore dependencies
|
- name: Restore dependencies
|
||||||
run: dotnet restore
|
run: dotnet restore
|
||||||
@@ -132,63 +202,51 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: dotnet build --no-restore --configuration Debug
|
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
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v3
|
||||||
|
|
||||||
- name: Upload SARIF results file
|
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
output: results
|
||||||
|
upload: true
|
||||||
|
|
||||||
SecurityCodeScan:
|
- name: Run Snyk to check for vulnerabilities
|
||||||
runs-on: windows-latest
|
uses: snyk/actions/dotnet@master
|
||||||
steps:
|
continue-on-error: true
|
||||||
- name: Checkout repository
|
env:
|
||||||
uses: actions/checkout@v4
|
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||||
|
LD_PRELOAD: '' # Clear the LD_PRELOAD to avoid CodeQL conflicts
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
args: |
|
||||||
|
--file=./lib/quantalib.csproj
|
||||||
|
--severity-threshold=low
|
||||||
|
--detection-depth=4
|
||||||
|
--package-manager=nuget
|
||||||
|
|
||||||
- name: Setup NuGet
|
- name: Run Snyk on Solution
|
||||||
uses: nuget/setup-nuget@v2
|
uses: snyk/actions/dotnet@master
|
||||||
|
if: always()
|
||||||
- name: Setup MSBuild
|
continue-on-error: true
|
||||||
uses: microsoft/setup-msbuild@v1
|
env:
|
||||||
|
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||||
- name: Setup .NET SDK
|
LD_PRELOAD: ''
|
||||||
uses: actions/setup-dotnet@v4
|
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
args: |
|
||||||
8.x
|
--file=QuanTAlib.sln
|
||||||
3.1.x
|
--all-projects
|
||||||
dotnet-quality: 'preview'
|
--detection-depth=4
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
|
- 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:
|
build_publish:
|
||||||
needs: [Code_Coverage, CodeQL, SecurityCodeScan]
|
timeout-minutes: 20
|
||||||
|
needs: [Code_Coverage, CodeQL]
|
||||||
if: |
|
if: |
|
||||||
success() &&
|
success() &&
|
||||||
(github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) ||
|
(github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev')) ||
|
||||||
@@ -203,7 +261,14 @@ jobs:
|
|||||||
- name: Setup .NET SDK
|
- name: Setup .NET SDK
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v4
|
||||||
with:
|
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
|
- name: Install GitVersion
|
||||||
uses: gittools/actions/gitversion/setup@v0
|
uses: gittools/actions/gitversion/setup@v0
|
||||||
@@ -227,8 +292,6 @@ jobs:
|
|||||||
dotnet build ./quantower/Volatility/_Volatility.csproj --configuration Release --nologo
|
dotnet build ./quantower/Volatility/_Volatility.csproj --configuration Release --nologo
|
||||||
dotnet build ./SyntheticVendor/SyntheticVendor.csproj --configuration Release --nologo
|
dotnet build ./SyntheticVendor/SyntheticVendor.csproj --configuration Release --nologo
|
||||||
|
|
||||||
############# Publish dev release
|
|
||||||
|
|
||||||
- name: Create or Update Development Release
|
- name: Create or Update Development Release
|
||||||
if: github.ref == 'refs/heads/dev'
|
if: github.ref == 'refs/heads/dev'
|
||||||
env:
|
env:
|
||||||
@@ -248,16 +311,16 @@ jobs:
|
|||||||
|
|
||||||
- name: Push prerelease package to myget.org
|
- name: Push prerelease package to myget.org
|
||||||
if: github.ref == 'refs/heads/dev'
|
if: github.ref == 'refs/heads/dev'
|
||||||
|
continue-on-error: true
|
||||||
|
id: myget-push
|
||||||
run: |
|
run: |
|
||||||
dotnet nuget push 'lib/bin/Release/QuanTAlib.*.nupkg' \
|
dotnet nuget push 'lib/bin/Release/QuanTAlib.*.nupkg' \
|
||||||
--source https://www.myget.org/F/quantalib/api/v3/index.json \
|
--source https://www.myget.org/F/quantalib/api/v3/index.json \
|
||||||
--force-english-output \
|
--force-english-output \
|
||||||
--api-key ${{ secrets.MYGET_DEPLOY_KEY_QUANTALIB }}
|
--api-key ${{ secrets.MYGET_DEPLOY_KEY_QUANTALIB }}
|
||||||
|
|
||||||
############## Publish main release
|
|
||||||
|
|
||||||
- name: Create GitHub Release
|
- name: Create GitHub Release
|
||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
if: github.ref == 'refs/heads/main'
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -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)
|
private HistoryItemBar GenerateTriangleWave(DateTime time, TimeSpan slice)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace QuanTAlib;
|
|||||||
public class Dsma : AbstractBase
|
public class Dsma : AbstractBase
|
||||||
{
|
{
|
||||||
private readonly CircularBuffer _buffer;
|
private readonly CircularBuffer _buffer;
|
||||||
private readonly double _c1, _c2, _c3;
|
private readonly double _c2, _c3;
|
||||||
private readonly double _scaleFactor;
|
private readonly double _scaleFactor;
|
||||||
private readonly double _periodRecip; // 1/_period
|
private readonly double _periodRecip; // 1/_period
|
||||||
private readonly double _scaleByPeriod; // 5/_period
|
private readonly double _scaleByPeriod; // 5/_period
|
||||||
@@ -59,7 +59,7 @@ public class Dsma : AbstractBase
|
|||||||
|
|
||||||
_c2 = b1;
|
_c2 = b1;
|
||||||
_c3 = -a1 * a1;
|
_c3 = -a1 * a1;
|
||||||
_c1 = 1.0 - _c2 - _c3;
|
double _c1 = 1.0 - _c2 - _c3;
|
||||||
_c1Half = _c1 * 0.5;
|
_c1Half = _c1 * 0.5;
|
||||||
_scaleByPeriod = 5.0 / period;
|
_scaleByPeriod = 5.0 / period;
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ public sealed class Cv : AbstractBase
|
|||||||
private readonly double _omega;
|
private readonly double _omega;
|
||||||
private double _prevClose;
|
private double _prevClose;
|
||||||
private double _prevVariance;
|
private double _prevVariance;
|
||||||
private double _longTermVariance;
|
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -82,7 +81,6 @@ public sealed class Cv : AbstractBase
|
|||||||
base.Init();
|
base.Init();
|
||||||
_prevClose = 0;
|
_prevClose = 0;
|
||||||
_prevVariance = 0;
|
_prevVariance = 0;
|
||||||
_longTermVariance = 0;
|
|
||||||
_isInitialized = false;
|
_isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +114,7 @@ public sealed class Cv : AbstractBase
|
|||||||
// Initialize with first available data if not done
|
// Initialize with first available data if not done
|
||||||
if (!_isInitialized && _index > _period)
|
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;
|
_prevVariance = _longTermVariance;
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ namespace QuanTAlib;
|
|||||||
public sealed class Cvi : AbstractBase
|
public sealed class Cvi : AbstractBase
|
||||||
{
|
{
|
||||||
private readonly int _period;
|
private readonly int _period;
|
||||||
private readonly int _smoothPeriod;
|
|
||||||
private readonly CircularBuffer _smoothed;
|
private readonly CircularBuffer _smoothed;
|
||||||
private readonly double _alpha;
|
private readonly double _alpha;
|
||||||
private double _ema;
|
private double _ema;
|
||||||
@@ -50,10 +49,9 @@ public sealed class Cvi : AbstractBase
|
|||||||
public Cvi(int period = 10, int smoothPeriod = 10)
|
public Cvi(int period = 10, int smoothPeriod = 10)
|
||||||
{
|
{
|
||||||
_period = period;
|
_period = period;
|
||||||
_smoothPeriod = smoothPeriod;
|
_alpha = 2.0 / (smoothPeriod + 1);
|
||||||
_alpha = 2.0 / (_smoothPeriod + 1);
|
WarmupPeriod = _period + smoothPeriod;
|
||||||
WarmupPeriod = _period + _smoothPeriod;
|
Name = $"CVI({_period},{smoothPeriod})";
|
||||||
Name = $"CVI({_period},{_smoothPeriod})";
|
|
||||||
_smoothed = new CircularBuffer(_period);
|
_smoothed = new CircularBuffer(_period);
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-13
@@ -42,7 +42,6 @@ namespace QuanTAlib;
|
|||||||
[SkipLocalsInit]
|
[SkipLocalsInit]
|
||||||
public sealed class Fcb : AbstractBase
|
public sealed class Fcb : AbstractBase
|
||||||
{
|
{
|
||||||
private readonly int _period;
|
|
||||||
private readonly double _smoothing;
|
private readonly double _smoothing;
|
||||||
private readonly CircularBuffer _highs;
|
private readonly CircularBuffer _highs;
|
||||||
private readonly CircularBuffer _lows;
|
private readonly CircularBuffer _lows;
|
||||||
@@ -56,11 +55,10 @@ public sealed class Fcb : AbstractBase
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public Fcb(int period = 20, double smoothing = 0.5)
|
public Fcb(int period = 20, double smoothing = 0.5)
|
||||||
{
|
{
|
||||||
_period = period;
|
|
||||||
_smoothing = smoothing;
|
_smoothing = smoothing;
|
||||||
_alpha = 2.0 / (_period + 1);
|
_alpha = 2.0 / (period + 1);
|
||||||
WarmupPeriod = period + 4; // Need extra periods for fractal identification
|
WarmupPeriod = period + 4; // Need extra periods for fractal identification
|
||||||
Name = $"FCB({_period},{_smoothing})";
|
Name = $"FCB({period},{_smoothing})";
|
||||||
_highs = new CircularBuffer(period);
|
_highs = new CircularBuffer(period);
|
||||||
_lows = new CircularBuffer(period);
|
_lows = new CircularBuffer(period);
|
||||||
Init();
|
Init();
|
||||||
@@ -116,16 +114,14 @@ public sealed class Fcb : AbstractBase
|
|||||||
bool isFractalHigh = false;
|
bool isFractalHigh = false;
|
||||||
bool isFractalLow = 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] &&
|
||||||
// Fractal high: current high is higher than 2 bars before and after
|
_highs[2] > _highs[3] && _highs[2] > _highs[4];
|
||||||
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
|
// Update EMAs with fractal points
|
||||||
if (isFractalHigh)
|
if (isFractalHigh)
|
||||||
|
|||||||
Reference in New Issue
Block a user