mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-21 12:08:05 +00:00
Dosc
This commit is contained in:
@@ -252,6 +252,7 @@ jobs:
|
|||||||
(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')) ||
|
||||||
github.event_name == 'workflow_dispatch'
|
github.event_name == 'workflow_dispatch'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -324,15 +325,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
<<<<<<<
|
|
||||||
gh release create v${{ github.sha }} \
|
|
||||||
--title "Release from commit ${{ github.sha }}" \
|
|
||||||
--notes "Release notes for this version." \
|
|
||||||
=======
|
|
||||||
gh release create v${{ steps.gitversion.outputs.MajorMinorPatch }} \
|
gh release create v${{ steps.gitversion.outputs.MajorMinorPatch }} \
|
||||||
--title "Release from commit ${{ steps.gitversion.outputs.MajorMinorPatch }}" \
|
--title "Release from commit ${{ steps.gitversion.outputs.MajorMinorPatch }}" \
|
||||||
--notes "Release notes for this version." \
|
--notes "Release notes for this version." \
|
||||||
>>>>>>>
|
|
||||||
quantower/Averages/bin/Release/Averages.dll \
|
quantower/Averages/bin/Release/Averages.dll \
|
||||||
quantower/Statistics/bin/Release/Statistics.dll \
|
quantower/Statistics/bin/Release/Statistics.dll \
|
||||||
quantower/Volatility/bin/Release/Volatility.dll \
|
quantower/Volatility/bin/Release/Volatility.dll \
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ public class EventingTests
|
|||||||
// Volatility indicators (bar-based)
|
// Volatility indicators (bar-based)
|
||||||
("Atr", new Atr(14), new Atr(barInput, 14)),
|
("Atr", new Atr(14), new Atr(barInput, 14)),
|
||||||
// Oscillators (bar-based)
|
// 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
|
// Generate 200 random values and feed them to indicators
|
||||||
|
|||||||
+324
-308
@@ -1,308 +1,324 @@
|
|||||||
using Xunit;
|
using Xunit;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace QuanTAlib.Tests;
|
namespace QuanTAlib.Tests;
|
||||||
|
|
||||||
public class OscillatorsUpdateTests
|
public class OscillatorsUpdateTests
|
||||||
{
|
{
|
||||||
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
private readonly RandomNumberGenerator rng = RandomNumberGenerator.Create();
|
||||||
private const int RandomUpdates = 100;
|
private const int RandomUpdates = 100;
|
||||||
private const double ReferenceValue = 100.0;
|
private const double ReferenceValue = 100.0;
|
||||||
private const int precision = 8;
|
private const int precision = 8;
|
||||||
|
|
||||||
private double GetRandomDouble()
|
private double GetRandomDouble()
|
||||||
{
|
{
|
||||||
byte[] bytes = new byte[8];
|
byte[] bytes = new byte[8];
|
||||||
rng.GetBytes(bytes);
|
rng.GetBytes(bytes);
|
||||||
return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100
|
return ((double)BitConverter.ToUInt64(bytes, 0) / ulong.MaxValue * 200) - 100; // Range: -100 to 100
|
||||||
}
|
}
|
||||||
|
|
||||||
private TBar GetRandomBar(bool IsNew)
|
private TBar GetRandomBar(bool IsNew)
|
||||||
{
|
{
|
||||||
double open = GetRandomDouble();
|
double open = GetRandomDouble();
|
||||||
double high = open + Math.Abs(GetRandomDouble());
|
double high = open + Math.Abs(GetRandomDouble());
|
||||||
double low = open - Math.Abs(GetRandomDouble());
|
double low = open - Math.Abs(GetRandomDouble());
|
||||||
double close = low + ((high - low) * GetRandomDouble());
|
double close = low + ((high - low) * GetRandomDouble());
|
||||||
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
|
return new TBar(DateTime.Now, open, high, low, close, 1000, IsNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Rsi_Update()
|
public void Rsi_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Rsi(period: 14);
|
var indicator = new Rsi(period: 14);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Rsx_Update()
|
public void Rsx_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Rsx(period: 14);
|
var indicator = new Rsx(period: 14);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Cmo_Update()
|
public void Cmo_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Cmo(period: 14);
|
var indicator = new Cmo(period: 14);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Ao_Update()
|
public void Ao_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Ao();
|
var indicator = new Ao();
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Ac_Update()
|
public void Ac_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Ac();
|
var indicator = new Ac();
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Aroon_Update()
|
public void Aroon_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Aroon(period: 25);
|
var indicator = new Aroon(period: 25);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Bop_Update()
|
public void Bop_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Bop();
|
var indicator = new Bop();
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Cci_Update()
|
public void Cci_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Cci(period: 20);
|
var indicator = new Cci(period: 20);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Cfo_Update()
|
public void Cfo_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Cfo(period: 14);
|
var indicator = new Cfo(period: 14);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Chop_Update()
|
public void Chop_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Chop(period: 14);
|
var indicator = new Chop(period: 14);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Cog_Update()
|
public void Cog_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Cog(period: 10);
|
var indicator = new Cog(period: 10);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Smi_Update()
|
public void Smi_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Smi(period: 10, smooth1: 3, smooth2: 3);
|
var indicator = new Smi(period: 10, smooth1: 3, smooth2: 3);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Srsi_Update()
|
public void Srsi_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Srsi(rsiPeriod: 14, stochPeriod: 14, smoothK: 3, smoothD: 3);
|
var indicator = new Srsi(rsiPeriod: 14, stochPeriod: 14, smoothK: 3, smoothD: 3);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Stc_Update()
|
public void Stc_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Stc(cyclePeriod: 10, fastPeriod: 23, slowPeriod: 50);
|
var indicator = new Stc(cyclePeriod: 10, fastPeriod: 23, slowPeriod: 50);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Stoch_Update()
|
public void Stoch_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Stoch(period: 14, smoothK: 3, smoothD: 3);
|
var indicator = new Stoch(period: 14, smoothK: 3, smoothD: 3);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Tsi_Update()
|
public void Tsi_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13);
|
var indicator = new Tsi(firstPeriod: 25, secondPeriod: 13);
|
||||||
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
double initialValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: true));
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
indicator.Calc(new TValue(DateTime.Now, GetRandomDouble(), IsNew: false));
|
||||||
}
|
}
|
||||||
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
double finalValue = indicator.Calc(new TValue(DateTime.Now, ReferenceValue, IsNew: false));
|
||||||
|
|
||||||
Assert.Equal(initialValue, finalValue, precision);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Uo_Update()
|
public void Uo_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Uo(period1: 7, period2: 14, period3: 28);
|
var indicator = new Uo(period1: 7, period2: 14, period3: 28);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
Assert.Equal(initialValue, finalValue, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Willr_Update()
|
public void Willr_Update()
|
||||||
{
|
{
|
||||||
var indicator = new Willr(period: 14);
|
var indicator = new Willr(period: 14);
|
||||||
TBar r = GetRandomBar(true);
|
TBar r = GetRandomBar(true);
|
||||||
double initialValue = indicator.Calc(r);
|
double initialValue = indicator.Calc(r);
|
||||||
|
|
||||||
for (int i = 0; i < RandomUpdates; i++)
|
for (int i = 0; i < RandomUpdates; i++)
|
||||||
{
|
{
|
||||||
indicator.Calc(GetRandomBar(IsNew: false));
|
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));
|
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);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
| Basic Transforms | 6 of 6 | 100% |
|
| Basic Transforms | 6 of 6 | 100% |
|
||||||
| Averages & Trends | 33 of 33 | 100% |
|
| Averages & Trends | 33 of 33 | 100% |
|
||||||
| Momentum | 16 of 16 | 100% |
|
| Momentum | 16 of 16 | 100% |
|
||||||
| Oscillators | 20 of 29 | 69% |
|
| Oscillators | 21 of 29 | 72% |
|
||||||
| Volatility | 24 of 35 | 69% |
|
| Volatility | 24 of 35 | 69% |
|
||||||
| Volume | 15 of 19 | 79% |
|
| Volume | 15 of 19 | 79% |
|
||||||
| Numerical Analysis | 13 of 19 | 68% |
|
| Numerical Analysis | 13 of 19 | 68% |
|
||||||
| Errors | 16 of 16 | 100% |
|
| Errors | 16 of 16 | 100% |
|
||||||
| **Total** | **143 of 173** | **83%** |
|
| **Total** | **144 of 173** | **83%** |
|
||||||
|
|
||||||
|Technical Indicator Name| Class Name|
|
|Technical Indicator Name| Class Name|
|
||||||
|-----------|:----------:|
|
|-----------|:----------:|
|
||||||
@@ -85,7 +85,6 @@
|
|||||||
|COPPOCK - Coppock Curve|`Coppock`|
|
|COPPOCK - Coppock Curve|`Coppock`|
|
||||||
|CRSI - Connor RSI|`Crsi`|
|
|CRSI - Connor RSI|`Crsi`|
|
||||||
|🚧 CTI - Ehler's Correlation Trend Indicator|`Cti`|
|
|🚧 CTI - Ehler's Correlation Trend Indicator|`Cti`|
|
||||||
|🚧 DOSC - Derivative Oscillator|`Dosc`|
|
|
||||||
|🚧 EFI - Elder Ray's Force Index|`Efi`|
|
|🚧 EFI - Elder Ray's Force Index|`Efi`|
|
||||||
|🚧 FISHER - Fisher Transform|`Fisher`|
|
|🚧 FISHER - Fisher Transform|`Fisher`|
|
||||||
|🚧 FOSC - Forecast Oscillator|`Fosc`|
|
|🚧 FOSC - Forecast Oscillator|`Fosc`|
|
||||||
@@ -102,6 +101,7 @@
|
|||||||
|TSI - True Strength Index|`Tsi`|
|
|TSI - True Strength Index|`Tsi`|
|
||||||
|UO - Ultimate Oscillator|`Uo`|
|
|UO - Ultimate Oscillator|`Uo`|
|
||||||
|WILLR - Larry Williams' %R|`Willr`|
|
|WILLR - Larry Williams' %R|`Willr`|
|
||||||
|
|DOSC - Derivative Oscillator|`Dosc`|
|
||||||
|**VOLATILITY INDICATORS**||
|
|**VOLATILITY INDICATORS**||
|
||||||
|ADR - Average Daily Range|`Adr`|
|
|ADR - Average Daily Range|`Adr`|
|
||||||
|AP - Andrew's Pitchfork|`Ap`|
|
|AP - Andrew's Pitchfork|`Ap`|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
namespace QuanTAlib;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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
|
||||||
|
/// </remarks>
|
||||||
|
[SkipLocalsInit]
|
||||||
|
public sealed class Dosc : AbstractBase
|
||||||
|
{
|
||||||
|
private readonly Rsi _rsi;
|
||||||
|
private readonly Macd _macd;
|
||||||
|
private readonly Sma _signal;
|
||||||
|
|
||||||
|
/// <param name="source">The data source object that publishes updates.</param>
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
-32
@@ -1,32 +1,32 @@
|
|||||||
# Oscillators indicators
|
# Oscillators indicators
|
||||||
Done: 20, Todo: 9
|
Done: 21, Todo: 8
|
||||||
|
|
||||||
✔️ AC - Acceleration Oscillator
|
✔️ AC - Acceleration Oscillator
|
||||||
✔️ AO - Awesome Oscillator
|
✔️ AO - Awesome Oscillator
|
||||||
✔️ AROON - Aroon oscillator (Up, Down)
|
✔️ AROON - Aroon oscillator (Up, Down)
|
||||||
✔️ BOP - Balance of Power
|
✔️ BOP - Balance of Power
|
||||||
✔️ CCI - Commodity Channel Index
|
✔️ CCI - Commodity Channel Index
|
||||||
✔️ CFO - Chande Forcast Oscillator
|
✔️ CFO - Chande Forcast Oscillator
|
||||||
✔️ CHOP - Choppiness Index
|
✔️ CHOP - Choppiness Index
|
||||||
✔️ CMO - Chande Momentum Oscillator
|
✔️ CMO - Chande Momentum Oscillator
|
||||||
✔️ COG - Ehler's Center of Gravity
|
✔️ COG - Ehler's Center of Gravity
|
||||||
✔️ COPPOCK - Coppock Curve
|
✔️ COPPOCK - Coppock Curve
|
||||||
✔️ CRSI - Connor RSI
|
✔️ CRSI - Connor RSI
|
||||||
CTI - Ehler's Correlation Trend Indicator
|
CTI - Ehler's Correlation Trend Indicator
|
||||||
DOSC - Derivative Oscillator
|
✔️ DOSC - Derivative Oscillator
|
||||||
EFI - Elder Ray's Force Index
|
EFI - Elder Ray's Force Index
|
||||||
FISHER - Fisher Transform
|
FISHER - Fisher Transform
|
||||||
FOSC - Forecast Oscillator
|
FOSC - Forecast Oscillator
|
||||||
*GATOR - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth)
|
*GATOR - Williams Alliator Oscillator (Upper Jaw, Lower Jaw, Teeth)
|
||||||
*KDJ - KDJ Indicator (K, D, J lines)
|
*KDJ - KDJ Indicator (K, D, J lines)
|
||||||
KRI - Kairi Relative Index
|
KRI - Kairi Relative Index
|
||||||
✔️ RSI - Relative Strength Index
|
✔️ RSI - Relative Strength Index
|
||||||
✔️ RSX - Jurik Trend Strength Index
|
✔️ RSX - Jurik Trend Strength Index
|
||||||
*RVGI - Relative Vigor Index (RVGI, Signal)
|
*RVGI - Relative Vigor Index (RVGI, Signal)
|
||||||
✔️ SMI - Stochastic Momentum Index
|
✔️ SMI - Stochastic Momentum Index
|
||||||
✔️ SRSI - Stochastic RSI (SRSI, Signal)
|
✔️ SRSI - Stochastic RSI (SRSI, Signal)
|
||||||
✔️ STC - Schaff Trend Cycle
|
✔️ STC - Schaff Trend Cycle
|
||||||
✔️ STOCH - Stochastic Oscillator (%K, %D)
|
✔️ STOCH - Stochastic Oscillator (%K, %D)
|
||||||
✔️ TSI - True Strength Index
|
✔️ TSI - True Strength Index
|
||||||
✔️ UO - Ultimate Oscillator
|
✔️ UO - Ultimate Oscillator
|
||||||
✔️ WILLR - Larry Williams' %R
|
✔️ WILLR - Larry Williams' %R
|
||||||
|
|||||||
Reference in New Issue
Block a user