From 9f3f23e50e3bf967a6bab5aad4d1482716260362 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 4 Nov 2024 07:21:19 -0800 Subject: [PATCH 1/6] semver fix --- Directory.Build.props | 1 + lib/quantalib.csproj | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Directory.Build.props b/Directory.Build.props index a6c4ab71..4f95bc86 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -44,6 +44,7 @@ true false true + S1944,S2053,S2222,S2259,S2583,S2589,S3329,S3655,S3900,S3949,S3966,S4158,S4347,S5773,S6781 diff --git a/lib/quantalib.csproj b/lib/quantalib.csproj index a5bae0db..8841bb97 100644 --- a/lib/quantalib.csproj +++ b/lib/quantalib.csproj @@ -22,6 +22,11 @@ https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png True false + $(GitVersion_MajorMinorPatch) + $(GitVersion_MajorMinorPatch) + $(GitVersion_AssemblySemVer) + $(GitVersion_AssemblySemFileVer) + $(GitVersion_InformationalVersion) From 1df0dff12adda59518781c31c4a533ceebfafe37 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 4 Nov 2024 07:21:19 -0800 Subject: [PATCH 2/6] semver fix --- .github/workflows/Publish.yml | 25 ++++++------------------- Directory.Build.props | 8 +++----- GitVersion.yml | 12 +++++++++--- lib/oscillators/Stc.cs | 24 ++++++++++++++++++++++-- lib/quantalib.csproj | 5 +++-- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/.github/workflows/Publish.yml b/.github/workflows/Publish.yml index 4293fa8b..0dd68721 100644 --- a/.github/workflows/Publish.yml +++ b/.github/workflows/Publish.yml @@ -194,7 +194,7 @@ jobs: languages: 'csharp' queries: security-and-quality config-file: ./.github/codeql/codeql-config.yml - tools: latest + tools: linked - name: Restore dependencies run: dotnet restore @@ -270,23 +270,10 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} restore-keys: ${{ runner.os }}-nuget- - - 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 restore + 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 @@ -324,9 +311,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release create v${{ steps.gitversion.outputs.MajorMinorPatch }} \ - --title "Release ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ - --notes "Release notes for version ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ + gh release create v${{ github.sha }} \ + --title "Release from commit ${{ github.sha }}" \ + --notes "Release notes for this version." \ quantower/Averages/bin/Release/Averages.dll \ quantower/Statistics/bin/Release/Statistics.dll \ quantower/Volatility/bin/Release/Volatility.dll \ diff --git a/Directory.Build.props b/Directory.Build.props index a6c4ab71..ecf9344f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,9 +20,6 @@ snupkg AnyCPU true - true - true - true @@ -45,13 +42,14 @@ false true - + + S1944,S2053,S2222,S2259,S2583,S2589,S3329,S3655,S3900,S3949,S3966,S4158,S4347,S5773,S6781 + - diff --git a/GitVersion.yml b/GitVersion.yml index 1fa72ce7..ee6175d4 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,18 +1,24 @@ -next-version: 0.6.1 mode: ContinuousDelivery major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' no-bump-message: '\+semver:\s?(none|skip)' +tag-prefix: '[vV]' + branches: main: regex: ^main$ mode: ContinuousDelivery increment: Patch + track-merge-target: true + is-release-branch: true dev: regex: ^dev(elop)?(ment)?$ - mode: ContinuousDeployment - increment: Inherit + mode: ContinuousDelivery + increment: Minor + track-merge-target: true + is-release-branch: false + source-branches: ['main'] ignore: sha: [] merge-message-formats: {} diff --git a/lib/oscillators/Stc.cs b/lib/oscillators/Stc.cs index feb544c5..b1ab2560 100644 --- a/lib/oscillators/Stc.cs +++ b/lib/oscillators/Stc.cs @@ -62,8 +62,28 @@ public sealed class Stc : AbstractBase int slowPeriod = DefaultSlowPeriod, int d1Period = DefaultD1Period, int stcPeriod = DefaultStcPeriod) { - if (cyclePeriod < 1 || fastPeriod < 1 || slowPeriod < 1 || d1Period < 1 || stcPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(cyclePeriod), "All periods must be greater than 0"); + string err = "All periods must be greater than 0"; + + if (cyclePeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(cyclePeriod), err); + } + if (fastPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(fastPeriod), err); + } + if (slowPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(slowPeriod), err); + } + if (d1Period < 1) + { + throw new ArgumentOutOfRangeException(nameof(d1Period), err); + } + if (stcPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(stcPeriod), err); + } if (fastPeriod >= slowPeriod) { throw new ArgumentOutOfRangeException(nameof(fastPeriod), "Fast period must be less than slow period"); diff --git a/lib/quantalib.csproj b/lib/quantalib.csproj index a5bae0db..051f3d1b 100644 --- a/lib/quantalib.csproj +++ b/lib/quantalib.csproj @@ -10,8 +10,8 @@ readme.md QuanTAlib QuanTAlib - True - True + true + true QuanTAlib2.png Apache-2.0 @@ -25,6 +25,7 @@ + From 8a47ee4cb5d0c93f32bcb735e140f658120d98c8 Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 4 Nov 2024 07:21:19 -0800 Subject: [PATCH 3/6] semver fix --- .github/workflows/Publish.yml | 25 ++++++------------------- Directory.Build.props | 8 +++----- GitVersion.yml | 29 +++++++++++++++++++++++++---- lib/oscillators/Stc.cs | 24 ++++++++++++++++++++++-- lib/quantalib.csproj | 5 +++-- 5 files changed, 59 insertions(+), 32 deletions(-) diff --git a/.github/workflows/Publish.yml b/.github/workflows/Publish.yml index 4293fa8b..0dd68721 100644 --- a/.github/workflows/Publish.yml +++ b/.github/workflows/Publish.yml @@ -194,7 +194,7 @@ jobs: languages: 'csharp' queries: security-and-quality config-file: ./.github/codeql/codeql-config.yml - tools: latest + tools: linked - name: Restore dependencies run: dotnet restore @@ -270,23 +270,10 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} restore-keys: ${{ runner.os }}-nuget- - - 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 restore + 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 @@ -324,9 +311,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release create v${{ steps.gitversion.outputs.MajorMinorPatch }} \ - --title "Release ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ - --notes "Release notes for version ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ + gh release create v${{ github.sha }} \ + --title "Release from commit ${{ github.sha }}" \ + --notes "Release notes for this version." \ quantower/Averages/bin/Release/Averages.dll \ quantower/Statistics/bin/Release/Statistics.dll \ quantower/Volatility/bin/Release/Volatility.dll \ diff --git a/Directory.Build.props b/Directory.Build.props index a6c4ab71..ecf9344f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,9 +20,6 @@ snupkg AnyCPU true - true - true - true @@ -45,13 +42,14 @@ false true - + + S1944,S2053,S2222,S2259,S2583,S2589,S3329,S3655,S3900,S3949,S3966,S4158,S4347,S5773,S6781 + - diff --git a/GitVersion.yml b/GitVersion.yml index 1fa72ce7..5bbf9593 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,18 +1,39 @@ -next-version: 0.6.1 -mode: ContinuousDelivery +workflow: GitHubFlow/v1 +assembly-versioning-scheme: MajorMinorPatch +assembly-file-versioning-scheme: MajorMinorPatch major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' no-bump-message: '\+semver:\s?(none|skip)' +tag-prefix: '[vV]' +semantic-version-format: Strict + branches: main: + label: '' regex: ^main$ mode: ContinuousDelivery increment: Patch + prevent-increment: + of-merged-branch: true + track-merge-target: false + track-merge-message: true + is-release-branch: true + pre-release-weight: 55000 + + dev: + label: beta regex: ^dev(elop)?(ment)?$ - mode: ContinuousDeployment - increment: Inherit + mode: ContinuousDelivery + increment: Patch + prevent-increment: + when-current-commit-tagged: false + track-merge-target: true + is-release-branch: false + source-branches: ['main'] + pre-release-weight: 30000 + ignore: sha: [] merge-message-formats: {} diff --git a/lib/oscillators/Stc.cs b/lib/oscillators/Stc.cs index feb544c5..b1ab2560 100644 --- a/lib/oscillators/Stc.cs +++ b/lib/oscillators/Stc.cs @@ -62,8 +62,28 @@ public sealed class Stc : AbstractBase int slowPeriod = DefaultSlowPeriod, int d1Period = DefaultD1Period, int stcPeriod = DefaultStcPeriod) { - if (cyclePeriod < 1 || fastPeriod < 1 || slowPeriod < 1 || d1Period < 1 || stcPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(cyclePeriod), "All periods must be greater than 0"); + string err = "All periods must be greater than 0"; + + if (cyclePeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(cyclePeriod), err); + } + if (fastPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(fastPeriod), err); + } + if (slowPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(slowPeriod), err); + } + if (d1Period < 1) + { + throw new ArgumentOutOfRangeException(nameof(d1Period), err); + } + if (stcPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(stcPeriod), err); + } if (fastPeriod >= slowPeriod) { throw new ArgumentOutOfRangeException(nameof(fastPeriod), "Fast period must be less than slow period"); diff --git a/lib/quantalib.csproj b/lib/quantalib.csproj index a5bae0db..051f3d1b 100644 --- a/lib/quantalib.csproj +++ b/lib/quantalib.csproj @@ -10,8 +10,8 @@ readme.md QuanTAlib QuanTAlib - True - True + true + true QuanTAlib2.png Apache-2.0 @@ -25,6 +25,7 @@ + From 4f62bd10e2c3c1ae2606e392f44458e804dddceb Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 4 Nov 2024 07:21:19 -0800 Subject: [PATCH 4/6] semver fix --- .github/workflows/Publish.yml | 25 ++++++------------------- Directory.Build.props | 8 +++----- GitVersion.yml | 33 +++++++++++++++++++++++++++------ lib/oscillators/Stc.cs | 24 ++++++++++++++++++++++-- lib/quantalib.csproj | 5 +++-- 5 files changed, 61 insertions(+), 34 deletions(-) diff --git a/.github/workflows/Publish.yml b/.github/workflows/Publish.yml index 4293fa8b..0dd68721 100644 --- a/.github/workflows/Publish.yml +++ b/.github/workflows/Publish.yml @@ -194,7 +194,7 @@ jobs: languages: 'csharp' queries: security-and-quality config-file: ./.github/codeql/codeql-config.yml - tools: latest + tools: linked - name: Restore dependencies run: dotnet restore @@ -270,23 +270,10 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} restore-keys: ${{ runner.os }}-nuget- - - 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 restore + 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 @@ -324,9 +311,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release create v${{ steps.gitversion.outputs.MajorMinorPatch }} \ - --title "Release ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ - --notes "Release notes for version ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ + gh release create v${{ github.sha }} \ + --title "Release from commit ${{ github.sha }}" \ + --notes "Release notes for this version." \ quantower/Averages/bin/Release/Averages.dll \ quantower/Statistics/bin/Release/Statistics.dll \ quantower/Volatility/bin/Release/Volatility.dll \ diff --git a/Directory.Build.props b/Directory.Build.props index a6c4ab71..ecf9344f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,9 +20,6 @@ snupkg AnyCPU true - true - true - true @@ -45,13 +42,14 @@ false true - + + S1944,S2053,S2222,S2259,S2583,S2589,S3329,S3655,S3900,S3949,S3966,S4158,S4347,S5773,S6781 + - diff --git a/GitVersion.yml b/GitVersion.yml index 1fa72ce7..d89b5d96 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,18 +1,39 @@ -next-version: 0.6.1 -mode: ContinuousDelivery +workflow: GitHubFlow/v1 +assembly-versioning-scheme: MajorMinorPatch +assembly-file-versioning-scheme: MajorMinorPatch major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' no-bump-message: '\+semver:\s?(none|skip)' +tag-prefix: '[vV]' +semantic-version-format: Strict + branches: main: + label: '' regex: ^main$ + mode: ContinuousDeployment + increment: Patch + prevent-increment: + of-merged-branch: true + track-merge-target: false + track-merge-message: true + is-release-branch: true + pre-release-weight: 0 + + + dev: + label: beta + regex: ^dev(elop)?(ment)?$ mode: ContinuousDelivery increment: Patch - dev: - regex: ^dev(elop)?(ment)?$ - mode: ContinuousDeployment - increment: Inherit + prevent-increment: + when-current-commit-tagged: false + track-merge-target: true + is-release-branch: false + source-branches: ['main'] + pre-release-weight: 30000 + ignore: sha: [] merge-message-formats: {} diff --git a/lib/oscillators/Stc.cs b/lib/oscillators/Stc.cs index feb544c5..b1ab2560 100644 --- a/lib/oscillators/Stc.cs +++ b/lib/oscillators/Stc.cs @@ -62,8 +62,28 @@ public sealed class Stc : AbstractBase int slowPeriod = DefaultSlowPeriod, int d1Period = DefaultD1Period, int stcPeriod = DefaultStcPeriod) { - if (cyclePeriod < 1 || fastPeriod < 1 || slowPeriod < 1 || d1Period < 1 || stcPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(cyclePeriod), "All periods must be greater than 0"); + string err = "All periods must be greater than 0"; + + if (cyclePeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(cyclePeriod), err); + } + if (fastPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(fastPeriod), err); + } + if (slowPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(slowPeriod), err); + } + if (d1Period < 1) + { + throw new ArgumentOutOfRangeException(nameof(d1Period), err); + } + if (stcPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(stcPeriod), err); + } if (fastPeriod >= slowPeriod) { throw new ArgumentOutOfRangeException(nameof(fastPeriod), "Fast period must be less than slow period"); diff --git a/lib/quantalib.csproj b/lib/quantalib.csproj index a5bae0db..051f3d1b 100644 --- a/lib/quantalib.csproj +++ b/lib/quantalib.csproj @@ -10,8 +10,8 @@ readme.md QuanTAlib QuanTAlib - True - True + true + true QuanTAlib2.png Apache-2.0 @@ -25,6 +25,7 @@ + From d711ecccc74385a251106b1a0e9886674947f63a Mon Sep 17 00:00:00 2001 From: Miha Kralj Date: Mon, 4 Nov 2024 07:21:19 -0800 Subject: [PATCH 5/6] semver fix --- .github/workflows/Publish.yml | 25 ++++++------------------- Directory.Build.props | 12 +++++------- GitVersion.yml | 33 +++++++++++++++++++++++++++------ lib/oscillators/Stc.cs | 24 ++++++++++++++++++++++-- lib/quantalib.csproj | 5 +++-- 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/.github/workflows/Publish.yml b/.github/workflows/Publish.yml index 4293fa8b..0dd68721 100644 --- a/.github/workflows/Publish.yml +++ b/.github/workflows/Publish.yml @@ -194,7 +194,7 @@ jobs: languages: 'csharp' queries: security-and-quality config-file: ./.github/codeql/codeql-config.yml - tools: latest + tools: linked - name: Restore dependencies run: dotnet restore @@ -270,23 +270,10 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }} restore-keys: ${{ runner.os }}-nuget- - - 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 restore + 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 @@ -324,9 +311,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - gh release create v${{ steps.gitversion.outputs.MajorMinorPatch }} \ - --title "Release ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ - --notes "Release notes for version ${{ steps.gitversion.outputs.MajorMinorPatch }}" \ + gh release create v${{ github.sha }} \ + --title "Release from commit ${{ github.sha }}" \ + --notes "Release notes for this version." \ quantower/Averages/bin/Release/Averages.dll \ quantower/Statistics/bin/Release/Statistics.dll \ quantower/Volatility/bin/Release/Volatility.dll \ diff --git a/Directory.Build.props b/Directory.Build.props index a6c4ab71..e556c1a6 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,9 +20,6 @@ snupkg AnyCPU true - true - true - true @@ -31,11 +28,11 @@ true true true - none + portable true true true - false + true true false false @@ -45,13 +42,14 @@ false true - + + S1944,S2053,S2222,S2259,S2583,S2589,S3329,S3655,S3900,S3949,S3966,S4158,S4347,S5773,S6781 + - diff --git a/GitVersion.yml b/GitVersion.yml index 1fa72ce7..d89b5d96 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,18 +1,39 @@ -next-version: 0.6.1 -mode: ContinuousDelivery +workflow: GitHubFlow/v1 +assembly-versioning-scheme: MajorMinorPatch +assembly-file-versioning-scheme: MajorMinorPatch major-version-bump-message: '\+semver:\s?(breaking|major)' minor-version-bump-message: '\+semver:\s?(feature|minor)' patch-version-bump-message: '\+semver:\s?(fix|patch)' no-bump-message: '\+semver:\s?(none|skip)' +tag-prefix: '[vV]' +semantic-version-format: Strict + branches: main: + label: '' regex: ^main$ + mode: ContinuousDeployment + increment: Patch + prevent-increment: + of-merged-branch: true + track-merge-target: false + track-merge-message: true + is-release-branch: true + pre-release-weight: 0 + + + dev: + label: beta + regex: ^dev(elop)?(ment)?$ mode: ContinuousDelivery increment: Patch - dev: - regex: ^dev(elop)?(ment)?$ - mode: ContinuousDeployment - increment: Inherit + prevent-increment: + when-current-commit-tagged: false + track-merge-target: true + is-release-branch: false + source-branches: ['main'] + pre-release-weight: 30000 + ignore: sha: [] merge-message-formats: {} diff --git a/lib/oscillators/Stc.cs b/lib/oscillators/Stc.cs index feb544c5..b1ab2560 100644 --- a/lib/oscillators/Stc.cs +++ b/lib/oscillators/Stc.cs @@ -62,8 +62,28 @@ public sealed class Stc : AbstractBase int slowPeriod = DefaultSlowPeriod, int d1Period = DefaultD1Period, int stcPeriod = DefaultStcPeriod) { - if (cyclePeriod < 1 || fastPeriod < 1 || slowPeriod < 1 || d1Period < 1 || stcPeriod < 1) - throw new ArgumentOutOfRangeException(nameof(cyclePeriod), "All periods must be greater than 0"); + string err = "All periods must be greater than 0"; + + if (cyclePeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(cyclePeriod), err); + } + if (fastPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(fastPeriod), err); + } + if (slowPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(slowPeriod), err); + } + if (d1Period < 1) + { + throw new ArgumentOutOfRangeException(nameof(d1Period), err); + } + if (stcPeriod < 1) + { + throw new ArgumentOutOfRangeException(nameof(stcPeriod), err); + } if (fastPeriod >= slowPeriod) { throw new ArgumentOutOfRangeException(nameof(fastPeriod), "Fast period must be less than slow period"); diff --git a/lib/quantalib.csproj b/lib/quantalib.csproj index a5bae0db..051f3d1b 100644 --- a/lib/quantalib.csproj +++ b/lib/quantalib.csproj @@ -10,8 +10,8 @@ readme.md QuanTAlib QuanTAlib - True - True + true + true QuanTAlib2.png Apache-2.0 @@ -25,6 +25,7 @@ + From c58a054a2873b4118e668b24b63e938dada4f257 Mon Sep 17 00:00:00 2001 From: Miha Kralj <31756078+mihakralj@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:28:47 -0800 Subject: [PATCH 6/6] Add DOSC - Derivative Oscillator --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/mihakralj/QuanTAlib?shareId=XXXX-XXXX-XXXX-XXXX). --- Tests/test_eventing.cs | 3 +- Tests/test_updates_oscillators.cs | 632 +++++++++++++++--------------- docs/indicators/indicators.md | 6 +- lib/oscillators/Dosc.cs | 74 ++++ lib/oscillators/_list.md | 64 +-- 5 files changed, 435 insertions(+), 344 deletions(-) create mode 100644 lib/oscillators/Dosc.cs diff --git a/Tests/test_eventing.cs b/Tests/test_eventing.cs index d997b81b..5406876e 100644 --- a/Tests/test_eventing.cs +++ b/Tests/test_eventing.cs @@ -113,7 +113,8 @@ public class EventingTests // Volatility indicators (bar-based) ("Atr", new Atr(14), new Atr(barInput, 14)), // Oscillators (bar-based) - ("Chop", new Chop(14), new Chop(barInput, 14)) + ("Chop", new Chop(14), new Chop(barInput, 14)), + ("Dosc", new Dosc(), new Dosc(barInput)) }; // Generate 200 random values and feed them to indicators diff --git a/Tests/test_updates_oscillators.cs b/Tests/test_updates_oscillators.cs index cbc20ec1..b2e369e5 100644 --- a/Tests/test_updates_oscillators.cs +++ b/Tests/test_updates_oscillators.cs @@ -1,308 +1,324 @@ -using Xunit; -using System.Security.Cryptography; - -namespace QuanTAlib.Tests; - -public class OscillatorsUpdateTests -{ - private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); - private const int RandomUpdates = 100; - private const double ReferenceValue = 100.0; - private const int precision = 8; - - private double GetRandomDouble() - { - byte[] bytes = new byte[8]; - rng.GetBytes(bytes); - return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 - } - - private TBar GetRandomBar(bool IsNew) - { - double open = GetRandomDouble(); - double high = open + Math.Abs(GetRandomDouble()); - double low = open - Math.Abs(GetRandomDouble()); - double close = low + ((high - low) * GetRandomDouble()); - return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew); - } - - [Fact] - public void Rsi_Update() - { - var indicator = new Rsi(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Rsx_Update() - { - var indicator = new Rsx(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Cmo_Update() - { - var indicator = new Cmo(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Ao_Update() - { - var indicator = new Ao(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Ac_Update() - { - var indicator = new Ac(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Aroon_Update() - { - var indicator = new Aroon(period: 25); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Bop_Update() - { - var indicator = new Bop(); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Cci_Update() - { - var indicator = new Cci(period: 20); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Cfo_Update() - { - var indicator = new Cfo(period: 14); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Chop_Update() - { - var indicator = new Chop(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Cog_Update() - { - var indicator = new Cog(period: 10); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Smi_Update() - { - var indicator = new Smi(period: 10, smooth1: 3, smooth2: 3); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Srsi_Update() - { - var indicator = new Srsi(rsiPeriod: 14, stochPeriod: 14, smoothK: 3, smoothD: 3); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Stc_Update() - { - var indicator = new Stc(cyclePeriod: 10, fastPeriod: 23, slowPeriod: 50); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Stoch_Update() - { - var indicator = new Stoch(period: 14, smoothK: 3, smoothD: 3); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Tsi_Update() - { - var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13); - double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); - } - double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Uo_Update() - { - var indicator = new Uo(period1: 7, period2: 14, period3: 28); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } - - [Fact] - public void Willr_Update() - { - var indicator = new Willr(period: 14); - TBar r = GetRandomBar(true); - double initialValue = indicator.Calc(r); - - for (int i = 0; i < RandomUpdates; i++) - { - indicator.Calc(GetRandomBar(IsNew: false)); - } - double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); - - Assert.Equal(initialValue, finalValue, precision); - } -} +using Xunit; +using System.Security.Cryptography; + +namespace QuanTAlib.Tests; + +public class OscillatorsUpdateTests +{ + private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create(); + private const int RandomUpdates = 100; + private const double ReferenceValue = 100.0; + private const int precision = 8; + + private double GetRandomDouble() + { + byte[] bytes = new byte[8]; + rng.GetBytes(bytes); + return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100 + } + + private TBar GetRandomBar(bool IsNew) + { + double open = GetRandomDouble(); + double high = open + Math.abs(GetRandomDouble()); + double low = open - Math.abs(GetRandomDouble()); + double close = low + ((high - low) * GetRandomDouble()); + return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew); + } + + [Fact] + public void Rsi_Update() + { + var indicator = new Rsi(period: 14); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Rsx_Update() + { + var indicator = new Rsx(period: 14); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Cmo_Update() + { + var indicator = new Cmo(period: 14); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Ao_Update() + { + var indicator = new Ao(); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Ac_Update() + { + var indicator = new Ac(); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Aroon_Update() + { + var indicator = new Aroon(period: 25); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Bop_Update() + { + var indicator = new Bop(); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Cci_Update() + { + var indicator = new Cci(period: 20); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Cfo_Update() + { + var indicator = new Cfo(period: 14); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Chop_Update() + { + var indicator = new Chop(period: 14); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Cog_Update() + { + var indicator = new Cog(period: 10); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Smi_Update() + { + var indicator = new Smi(period: 10, smooth1: 3, smooth2: 3); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Srsi_Update() + { + var indicator = new Srsi(rsiPeriod: 14, stochPeriod: 14, smoothK: 3, smoothD: 3); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Stc_Update() + { + var indicator = new Stc(cyclePeriod: 10, fastPeriod: 23, slowPeriod: 50); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Stoch_Update() + { + var indicator = new Stoch(period: 14, smoothK: 3, smoothD: 3); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Tsi_Update() + { + var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13); + double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true)); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false)); + } + double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Uo_Update() + { + var indicator = new Uo(period1: 7, period2: 14, period3: 28); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Willr_Update() + { + var indicator = new Willr(period: 14); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } + + [Fact] + public void Dosc_Update() + { + var indicator = new Dosc(); + TBar r = GetRandomBar(true); + double initialValue = indicator.Calc(r); + + for (int i = 0; i < RandomUpdates; i++) + { + indicator.Calc(GetRandomBar(IsNew: false)); + } + double finalValue = indicator.Calc(new TBar(r.Time, r.Open, r.High, r.Low, r.Close, r.Volume, IsNew: false)); + + Assert.Equal(initialValue, finalValue, precision); + } +} diff --git a/docs/indicators/indicators.md b/docs/indicators/indicators.md index 8c607e10..3916949a 100644 --- a/docs/indicators/indicators.md +++ b/docs/indicators/indicators.md @@ -5,12 +5,12 @@ | Basic Transforms | 6 of 6 | 100% | | Averages & Trends | 33 of 33 | 100% | | Momentum | 16 of 16 | 100% | -| Oscillators | 20 of 29 | 69% | +| Oscillators | 21 of 29 | 72% | | Volatility | 24 of 35 | 69% | | Volume | 15 of 19 | 79% | | Numerical Analysis | 13 of 19 | 68% | | Errors | 16 of 16 | 100% | -| **Total** | **143 of 173** | **83%** | +| **Total** | **144 of 173** | **83%** | |Technical Indicator Name| Class Name| |-----------|:----------:| @@ -85,7 +85,6 @@ |COPPOCK - Coppock Curve|`Coppock`| |CRSI - Connor RSI|`Crsi`| |🚧 CTI - Ehler's Correlation Trend Indicator|`Cti`| -|🚧 DOSC - Derivative Oscillator|`Dosc`| |🚧 EFI - Elder Ray's Force Index|`Efi`| |🚧 FISHER - Fisher Transform|`Fisher`| |🚧 FOSC - Forecast Oscillator|`Fosc`| @@ -102,6 +101,7 @@ |TSI - True Strength Index|`Tsi`| |UO - Ultimate Oscillator|`Uo`| |WILLR - Larry Williams' %R|`Willr`| +|DOSC - Derivative Oscillator|`Dosc`| |**VOLATILITY INDICATORS**|| |ADR - Average Daily Range|`Adr`| |AP - Andrew's Pitchfork|`Ap`| diff --git a/lib/oscillators/Dosc.cs b/lib/oscillators/Dosc.cs new file mode 100644 index 00000000..906b2288 --- /dev/null +++ b/lib/oscillators/Dosc.cs @@ -0,0 +1,74 @@ +using System.Runtime.CompilerServices; +namespace QuanTAlib; + +/// +/// DOSC: Derivative Oscillator +/// A momentum indicator that combines the Relative Strength Index (RSI) and the Moving Average Convergence Divergence (MACD) to identify potential trend reversals. +/// +/// +/// The DOSC calculation process: +/// 1. Calculate the RSI +/// 2. Calculate the MACD of the RSI +/// 3. Calculate the signal line (SMA) of the MACD +/// 4. Subtract the signal line from the MACD to get the DOSC +/// +/// Key characteristics: +/// - Combines RSI and MACD +/// - Oscillates above and below zero +/// - Positive values indicate bullish momentum +/// - Negative values indicate bearish momentum +/// - Crosses above zero suggest buying opportunities +/// - Crosses below zero suggest selling opportunities +/// +/// Formula: +/// DOSC = MACD(RSI) - Signal(MACD(RSI)) +/// +/// Sources: +/// Original development +/// https://www.investopedia.com/terms/d/derivativeoscillator.asp +/// +[SkipLocalsInit] +public sealed class Dosc : AbstractBase +{ + private readonly Rsi _rsi; + private readonly Macd _macd; + private readonly Sma _signal; + + /// The data source object that publishes updates. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dosc(object source) : this() + { + var pubEvent = source.GetType().GetEvent("Pub"); + pubEvent?.AddEventHandler(source, new BarSignal(Sub)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Dosc() + { + _rsi = new Rsi(); + _macd = new Macd(); + _signal = new Sma(9); + WarmupPeriod = 34; // RSI requires 14 periods + MACD requires 26 periods + 9 for signal line + Name = "DOSC"; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override void ManageState(bool isNew) + { + if (isNew) + { + _index++; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected override double Calculation() + { + ManageState(BarInput.IsNew); + var rsi = _rsi.Calc(BarInput.Close, BarInput.IsNew); + var macd = _macd.Calc(rsi, BarInput.IsNew); + _signal.Calc(macd, BarInput.IsNew); + + return macd - _signal.Value; + } +} diff --git a/lib/oscillators/_list.md b/lib/oscillators/_list.md index 0cd477ee..72b74c86 100644 --- a/lib/oscillators/_list.md +++ b/lib/oscillators/_list.md @@ -1,32 +1,32 @@ -# Oscillators indicators -Done: 20, Todo: 9 - -✔️ AC - Acceleration Oscillator -✔️ AO - Awesome Oscillator -✔️ AROON - Aroon oscillator (Up, Down) -✔️ BOP - Balance of Power -✔️ CCI - Commodity Channel Index -✔️ CFO - Chande Forcast Oscillator -✔️ CHOP - Choppiness Index -✔️ CMO - Chande Momentum Oscillator -✔️ COG - Ehler's Center of Gravity -✔️ COPPOCK - Coppock Curve -✔️ CRSI - Connor RSI -CTI - Ehler's Correlation Trend Indicator -DOSC - Derivative Oscillator -EFI - Elder Ray's Force Index -FISHER - Fisher Transform -FOSC - Forecast Oscillator -*GATOR - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth) -*KDJ - KDJ Indicator (K, D, J lines) -KRI - Kairi Relative Index -✔️ RSI - Relative Strength Index -✔️ RSX - Jurik Trend Strength Index -*RVGI - Relative Vigor Index (RVGI, Signal) -✔️ SMI - Stochastic Momentum Index -✔️ SRSI - Stochastic RSI (SRSI, Signal) -✔️ STC - Schaff Trend Cycle -✔️ STOCH - Stochastic Oscillator (%K, %D) -✔️ TSI - True Strength Index -✔️ UO - Ultimate Oscillator -✔️ WILLR - Larry Williams' %R +# Oscillators indicators +Done: 21, Todo: 8 + +✔️ AC - Acceleration Oscillator +✔️ AO - Awesome Oscillator +✔️ AROON - Aroon oscillator (Up, Down) +✔️ BOP - Balance of Power +✔️ CCI - Commodity Channel Index +✔️ CFO - Chande Forcast Oscillator +✔️ CHOP - Choppiness Index +✔️ CMO - Chande Momentum Oscillator +✔️ COG - Ehler's Center of Gravity +✔️ COPPOCK - Coppock Curve +✔️ CRSI - Connor RSI +CTI - Ehler's Correlation Trend Indicator +✔️ DOSC - Derivative Oscillator +EFI - Elder Ray's Force Index +FISHER - Fisher Transform +FOSC - Forecast Oscillator +*GATOR - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth) +*KDJ - KDJ Indicator (K, D, J lines) +KRI - Kairi Relative Index +✔️ RSI - Relative Strength Index +✔️ RSX - Jurik Trend Strength Index +*RVGI - Relative Vigor Index (RVGI, Signal) +✔️ SMI - Stochastic Momentum Index +✔️ SRSI - Stochastic RSI (SRSI, Signal) +✔️ STC - Schaff Trend Cycle +✔️ STOCH - Stochastic Oscillator (%K, %D) +✔️ TSI - True Strength Index +✔️ UO - Ultimate Oscillator +✔️ WILLR - Larry Williams' %R