Merge remote-tracking branch 'origin/add-dosc' into dev

This commit is contained in:
Miha Kralj
2024-11-04 14:52:38 -08:00
7 changed files with 441 additions and 344 deletions
+1
View File
@@ -41,6 +41,7 @@
<InvariantGlobalization>true</InvariantGlobalization> <InvariantGlobalization>true</InvariantGlobalization>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport> <MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseSystemResourceKeys>true</UseSystemResourceKeys> <UseSystemResourceKeys>true</UseSystemResourceKeys>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
+2 -1
View File
@@ -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
+18 -2
View File
@@ -20,8 +20,8 @@ public class OscillatorsUpdateTests
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);
} }
@@ -305,4 +305,20 @@ public class OscillatorsUpdateTests
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);
}
} }
+3 -3
View File
@@ -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`|
+74
View File
@@ -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;
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
# Oscillators indicators # Oscillators indicators
Done: 20, Todo: 9 Done: 21, Todo: 8
✔️ AC - Acceleration Oscillator ✔️ AC - Acceleration Oscillator
✔️ AO - Awesome Oscillator ✔️ AO - Awesome Oscillator
@@ -13,7 +13,7 @@ Done: 20, Todo: 9
✔️ 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
+5
View File
@@ -22,6 +22,11 @@
<PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl> <PackageIconUrl>https://raw.githubusercontent.com/mihakralj/QuanTAlib/main/.github/QuanTAlib2.png</PackageIconUrl>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems> <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<Version>$(GitVersion_MajorMinorPatch)</Version>
<PackageVersion>$(GitVersion_MajorMinorPatch)</PackageVersion>
<AssemblyVersion>$(GitVersion_AssemblySemVer)</AssemblyVersion>
<FileVersion>$(GitVersion_AssemblySemFileVer)</FileVersion>
<InformationalVersion>$(GitVersion_InformationalVersion)</InformationalVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>