chore: repo cleanup and code quality improvements

- Remove global.json (SDK pinning unnecessary)

- Remove nuget.config, move MyGet source to .csproj RestoreAdditionalProjectSources

- Gitignore ndepend/ entirely, move badges to docs/img/

- Update README.md and docs/ndepend.md badge paths

- Add NDepend project property to QuanTAlib.slnx

- Expand .editorconfig ReSharper/diagnostic suppressions

- Use ArgumentOutOfRangeException instead of ArgumentException

- Use discard _ for unused event sender parameters

- Remove quantalib.code-workspace and sonar-suppressions.json

- Add filter signature SVGs
This commit is contained in:
Miha Kralj
2026-03-03 09:22:55 -08:00
parent e1a6743bda
commit 1910fdca93
131 changed files with 216046 additions and 2027 deletions
+35
View File
@@ -20,12 +20,43 @@ resharper_for_can_be_converted_to_foreach_highlighting = none
resharper_unused_parameter_local_highlighting = none
resharper_conditional_access_qualifier_is_non_nullable_according_to_api_contract_highlighting = none
resharper_redundant_lambda_parameter_type_highlighting = none
resharper_not_accessed_positional_property_local_highlighting = none
resharper_possible_loss_of_fraction_highlighting = hint
# Suppress JB InspectCode false positives / intentional patterns
resharper_unused_method_return_value_local_highlighting = none
resharper_member_initializer_value_ignored_highlighting = none
resharper_redundant_explicit_array_creation_highlighting = hint
resharper_with_expression_modifies_all_members_highlighting = hint
resharper_redundant_delegate_creation_highlighting = hint
resharper_redundant_default_member_initializer_highlighting = hint
resharper_redundant_empty_switch_section_highlighting = hint
resharper_empty_for_statement_highlighting = hint
resharper_using_statement_resource_initialization_highlighting = hint
resharper_unused_member_local_highlighting = hint
resharper_not_accessed_variable_highlighting = hint
resharper_private_field_can_be_converted_to_local_variable_highlighting = hint
resharper_collection_never_queried_local_highlighting = hint
resharper_unused_auto_property_accessor_local_highlighting = hint
resharper_unused_tuple_component_in_return_value_highlighting = hint
resharper_convert_type_check_to_null_check_highlighting = hint
resharper_redundant_name_qualifier_highlighting = hint
resharper_redundant_suppress_nullable_warning_expression_highlighting = hint
resharper_possible_null_reference_exception_highlighting = hint
resharper_assign_null_to_not_null_attribute_highlighting = hint
resharper_default_struct_equality_is_used_global_highlighting = hint
dotnet_diagnostic.CS0628.severity = none
dotnet_diagnostic.CS8602.severity = none
dotnet_diagnostic.CS8601.severity = none
dotnet_diagnostic.CS0660.severity = none
dotnet_diagnostic.CS0661.severity = none
resharper_redundant_cast_highlighting = hint
resharper_redundant_assignment_highlighting = hint
resharper_not_accessed_field_local_highlighting = hint
resharper_unused_auto_property_accessor_global_highlighting = hint
resharper_condition_is_always_true_or_false_highlighting = hint
resharper_condition_is_always_true_or_false_according_to_nullable_api_contract_highlighting = hint
resharper_access_to_modified_closure_highlighting = hint
resharper_generic_enumerator_not_disposed_highlighting = hint
@@ -85,6 +116,10 @@ csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = false:silent
[python/src/**.cs]
resharper_enforce_if_statement_braces_highlighting = none
csharp_prefer_braces = false:silent
[ndepend/**]
dotnet_analyzer_diagnostic.severity = none
generated_code = true
+3 -4
View File
@@ -36,9 +36,8 @@ bld/
*.coverage
*.coveragexml
# NDepend
ndepend/NDependOut/
ndepend/coverage/
# NDepend (entire directory — tooling + generated output)
ndepend/
# BenchmarkDotNet
BenchmarkDotNet.Artifacts/
@@ -49,7 +48,7 @@ BenchmarkDotNet.Artifacts/
# Temporary files and agent workspace
temp/
temp_pandas_ta/
pandas_ta/
temp_decompile/
Invoke-WebRequest/
.temp/
+3
View File
@@ -10,4 +10,7 @@
<Folder Name="/python/">
<Project Path="python/python.csproj" />
</Folder>
<Properties Name="NDepend">
<Property Name="Project" Value="&quot;.\ndepend\quantalib.ndproj&quot;" />
</Properties>
</Solution>
+7 -7
View File
@@ -8,14 +8,14 @@
[![.NET](https://img.shields.io/badge/.NET-8.0%20|%2010.0-blue?style=flat-square)](https://dotnet.microsoft.com/en-us/download/dotnet)
[![Indicators](https://img.shields.io/badge/%23%20Indicators-393-blue?style=flat-square)](lib/_index.md)
[![Classes](ndepend/badges/classes.svg)](ndepend/ndependout/ndependreport.html)
[![Files](ndepend/badges/files.svg)](ndepend/ndependout/ndependreport.html)
[![Methods](ndepend/badges/methods.svg)](ndepend/ndependout/ndependreport.html)
[![Lines of Code](ndepend/badges/loc.svg)](ndepend/ndependout/ndependreport.html)
[![Public APIs](ndepend/badges/public-api.svg)](ndepend/ndependout/ndependreport.html)
[![Comments](ndepend/badges/comments.svg)](ndepend/ndependout/ndependreport.html)
[![Classes](docs/img/classes.svg)](docs/ndepend.md)
[![Files](docs/img/files.svg)](docs/ndepend.md)
[![Methods](docs/img/methods.svg)](docs/ndepend.md)
[![Lines of Code](docs/img/loc.svg)](docs/ndepend.md)
[![Public APIs](docs/img/public-api.svg)](docs/ndepend.md)
[![Comments](docs/img/comments.svg)](docs/ndepend.md)
Static code analysis provided by [ndepend](https://www.ndepend.com/)
Static code analysis provided by [ndepend](https://www.ndepend.com/)
# QuanTAlib - Quantitative Technical Indicators Without Compromises
@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='101.38281' height='20' role='img' aria-label='languages: 5'>
<title># Classes: 1583</title>
<title># Classes: 1126</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='526.875'># Classes</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='526.875'># Classes</text>
<text aria-hidden='true' x='666.875' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1583</text>
<text x='666.875' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1583</text>
<text aria-hidden='true' x='666.875' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1126</text>
<text x='666.875' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1126</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='188.0957' height='20' role='img' aria-label='languages: 5'>
<title>Percentage of Comments: 31.22</title>
<title>Percentage of Comments: 33.35</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='1360.6641'>Percentage of Comments</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='1360.6641'>Percentage of Comments</text>
<text aria-hidden='true' x='1500.6641' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='300.29297'>31.22</text>
<text x='1500.6641' y='140' transform='scale(.1)' fill='#FFF' textLength='300.29297'>31.22</text>
<text aria-hidden='true' x='1500.6641' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='300.29297'>33.35</text>
<text x='1500.6641' y='140' transform='scale(.1)' fill='#FFF' textLength='300.29297'>33.35</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='281.4414' height='20' role='img' aria-label='languages: 5'>
<title>Average Cyclomatic Complexity for Methods: 2.08</title>
<title>Average Cyclomatic Complexity for Methods: 2.16</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='2360.8594'>Average Cyclomatic Complexity for Methods</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='2360.8594'>Average Cyclomatic Complexity for Methods</text>
<text aria-hidden='true' x='2500.8594' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='233.55469'>2.08</text>
<text x='2500.8594' y='140' transform='scale(.1)' fill='#FFF' textLength='233.55469'>2.08</text>
<text aria-hidden='true' x='2500.8594' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='233.55469'>2.16</text>
<text x='2500.8594' y='140' transform='scale(.1)' fill='#FFF' textLength='233.55469'>2.16</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='125.39453' height='20' role='img' aria-label='languages: 5'>
<title># Source Files: 1685</title>
<title># Source Files: 1812</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='766.9922'># Source Files</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='766.9922'># Source Files</text>
<text aria-hidden='true' x='906.9922' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1685</text>
<text x='906.9922' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1685</text>
<text aria-hidden='true' x='906.9922' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1812</text>
<text x='906.9922' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1812</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

+3 -3
View File
@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='146.10156' height='20' role='img' aria-label='languages: 5'>
<title># Lines of Code: 182513</title>
<title># Lines of Code: 145378</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='840.58594'># Lines of Code</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='840.58594'># Lines of Code</text>
<text aria-hidden='true' x='980.58594' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='400.4297'>182513</text>
<text x='980.58594' y='140' transform='scale(.1)' fill='#FFF' textLength='400.4297'>182513</text>
<text aria-hidden='true' x='980.58594' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='400.4297'>145378</text>
<text x='980.58594' y='140' transform='scale(.1)' fill='#FFF' textLength='400.4297'>145378</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='111.40234' height='20' role='img' aria-label='languages: 5'>
<title># Methods: 20231</title>
<title># Methods: 14666</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='560.33203'># Methods</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='560.33203'># Methods</text>
<text aria-hidden='true' x='700.33203' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='333.6914'>20231</text>
<text x='700.33203' y='140' transform='scale(.1)' fill='#FFF' textLength='333.6914'>20231</text>
<text aria-hidden='true' x='700.33203' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='333.6914'>14666</text>
<text x='700.33203' y='140' transform='scale(.1)' fill='#FFF' textLength='333.6914'>14666</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,6 +1,6 @@
<svg xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink' width='127.39844' height='20' role='img' aria-label='languages: 5'>
<title># Public Types: 1731</title>
<title># Public Types: 1165</title>
<linearGradient id='s' x2='0' y2='100%'>
<stop offset='0' stop-color='#bbb' stop-opacity='.1'/>
<stop offset='1' stop-opacity='.1'/>
@@ -16,7 +16,7 @@
<g fill='#FFF' text-anchor='center' font-family='Verdana,Geneva,DejaVu Sans,sans-serif' text-rendering='geometricPrecision' font-size='110'>
<text aria-hidden='true' x='40' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='787.03125'># Public Types</text>
<text x='40' y='140' transform='scale(.1)' fill='#FFF' textLength='787.03125'># Public Types</text>
<text aria-hidden='true' x='927.03125' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1731</text>
<text x='927.03125' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1731</text>
<text aria-hidden='true' x='927.03125' y='150' fill='#010101' fill-opacity='.3' transform='scale(.1)' textLength='266.95312'>1165</text>
<text x='927.03125' y='140' transform='scale(.1)' fill='#FFF' textLength='266.95312'>1165</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

+1 -1
View File
@@ -73,7 +73,7 @@ This script:
1. Builds the solution in Release configuration
2. Runs NDepend analysis against the compiled assemblies
3. Generates the HTML report at `ndepend/NDependOut/NDependReport.html`
4. Updates quality gate badges in `ndepend/badges/`
4. Updates quality gate badges in `docs/img/`
**Prerequisites:** NDepend license (set `NDEPEND_LICENSE` environment variable). Without a license, the script runs but produces warnings instead of full analysis.
-6
View File
@@ -1,6 +0,0 @@
{
"sdk": {
"version": "10.0.103",
"allowPrerelease": false
}
}
+1
View File
@@ -8,6 +8,7 @@
<IsTestProject>true</IsTestProject>
<NoWarn>$(NoWarn);CS8892</NoWarn>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<RestoreAdditionalProjectSources>https://www.myget.org/F/ooplesfinance_stockindicators/api/v3/index.json</RestoreAdditionalProjectSources>
</PropertyGroup>
<ItemGroup>
+16 -14
View File
@@ -96,12 +96,12 @@ public sealed class Aberr : ITValuePublisher, IDisposable
{
if (period <= 0)
{
throw new ArgumentException("Period must be greater than 0", nameof(period));
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than 0");
}
if (multiplier <= 0)
{
throw new ArgumentException("Multiplier must be greater than 0", nameof(multiplier));
throw new ArgumentOutOfRangeException(nameof(multiplier), "Multiplier must be greater than 0");
}
_period = period;
@@ -132,13 +132,13 @@ public sealed class Aberr : ITValuePublisher, IDisposable
_source.Pub += _handler;
}
private void HandleValue(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
private void HandleValue(object? _, in TValueEventArgs e) => Update(e.Value, e.IsNew);
/// <summary>
/// Helper to invoke the Pub event.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void PubEvent(TValue value, bool isNew = true)
private void PubEvent(TValue value, bool isNew)
{
Pub?.Invoke(this, new TValueEventArgs { Value = value, IsNew = isNew });
}
@@ -301,7 +301,8 @@ public sealed class Aberr : ITValuePublisher, IDisposable
}
else
{
double recalcSumSource = 0, recalcSumDeviation = 0;
double recalcSumSource = 0;
double recalcSumDeviation = 0;
for (int k = 0; k < period; k++)
{
recalcSumSource += buffers.Source[k];
@@ -439,11 +440,11 @@ public sealed class Aberr : ITValuePublisher, IDisposable
[StructLayout(LayoutKind.Auto)]
private ref struct ScalarState
{
public double SumSource;
public double SumDeviation;
public double LastValidValue;
public int BufferIndex;
public int TickCount;
internal double SumSource;
internal double SumDeviation;
internal double LastValidValue;
internal int BufferIndex;
internal int TickCount;
}
/// <summary>
@@ -452,8 +453,8 @@ public sealed class Aberr : ITValuePublisher, IDisposable
[StructLayout(LayoutKind.Auto)]
private readonly ref struct WorkBuffers(Span<double> source, Span<double> deviation)
{
public readonly Span<double> Source = source;
public readonly Span<double> Deviation = deviation;
internal readonly Span<double> Source = source;
internal readonly Span<double> Deviation = deviation;
}
/// <summary>
@@ -510,12 +511,12 @@ public sealed class Aberr : ITValuePublisher, IDisposable
if (period <= 0)
{
throw new ArgumentException("Period must be greater than 0", nameof(period));
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than 0");
}
if (multiplier <= 0)
{
throw new ArgumentException("Multiplier must be greater than 0", nameof(multiplier));
throw new ArgumentOutOfRangeException(nameof(multiplier), "Multiplier must be greater than 0");
}
if (len == 0)
@@ -701,5 +702,6 @@ public sealed class Aberr : ITValuePublisher, IDisposable
}
_disposed = true;
}
GC.SuppressFinalize(this);
}
}
+11 -11
View File
@@ -528,14 +528,14 @@ public sealed class AccBands : ITValuePublisher, IDisposable
[StructLayout(LayoutKind.Auto)]
private ref struct ScalarState
{
public double SumAdjHigh;
public double SumAdjLow;
public double SumClose;
public double LastValidHigh;
public double LastValidLow;
public double LastValidClose;
public int BufferIndex;
public int TickCount;
internal double SumAdjHigh;
internal double SumAdjLow;
internal double SumClose;
internal double LastValidHigh;
internal double LastValidLow;
internal double LastValidClose;
internal int BufferIndex;
internal int TickCount;
}
/// <summary>
@@ -544,9 +544,9 @@ public sealed class AccBands : ITValuePublisher, IDisposable
[StructLayout(LayoutKind.Auto)]
private readonly ref struct WorkBuffers(Span<double> adjHigh, Span<double> adjLow, Span<double> close)
{
public readonly Span<double> AdjHigh = adjHigh;
public readonly Span<double> AdjLow = adjLow;
public readonly Span<double> Close = close;
internal readonly Span<double> AdjHigh = adjHigh;
internal readonly Span<double> AdjLow = adjLow;
internal readonly Span<double> Close = close;
}
/// <summary>
+9 -9
View File
@@ -439,15 +439,15 @@ public sealed class Apz : ITValuePublisher
[StructLayout(LayoutKind.Auto)]
private ref struct ScalarState
{
public double Ema1Price;
public double Ema2Price;
public double Ema1Range;
public double Ema2Range;
public double E;
public double LastValidPrice;
public double LastValidHigh;
public double LastValidLow;
public bool IsHot;
internal double Ema1Price;
internal double Ema2Price;
internal double Ema1Range;
internal double Ema2Range;
internal double E;
internal double LastValidPrice;
internal double LastValidHigh;
internal double LastValidLow;
internal bool IsHot;
}
/// <summary>
+2 -2
View File
@@ -269,8 +269,8 @@ public sealed class Dchannel : ITValuePublisher
try
{
QuanTAlib.Highest.Batch(high, top.AsSpan(0, len), period);
QuanTAlib.Lowest.Batch(low, bot.AsSpan(0, len), period);
Highest.Batch(high, top.AsSpan(0, len), period);
Lowest.Batch(low, bot.AsSpan(0, len), period);
for (int i = 0; i < len; i++)
{
+25 -25
View File
@@ -16,8 +16,8 @@ public sealed class Decaychannel : ITValuePublisher
private readonly double _decayLambda;
private readonly double[] _hBuf;
private readonly double[] _lBuf;
private readonly double[] _hBuf_prev;
private readonly double[] _lBuf_prev;
private readonly double[] _hBufPrev;
private readonly double[] _lBufPrev;
private int _count;
private long _index;
@@ -42,7 +42,7 @@ public sealed class Decaychannel : ITValuePublisher
long Index);
private State _state;
private State _p_state;
private State _pState;
private readonly TBarPublishedHandler _barHandler;
@@ -66,8 +66,8 @@ public sealed class Decaychannel : ITValuePublisher
_decayLambda = Math.Log(2.0) / period;
_hBuf = new double[_period];
_lBuf = new double[_period];
_hBuf_prev = new double[_period];
_lBuf_prev = new double[_period];
_hBufPrev = new double[_period];
_lBufPrev = new double[_period];
_count = 0;
_index = -1;
_currentMax = double.NaN;
@@ -78,7 +78,7 @@ public sealed class Decaychannel : ITValuePublisher
_minAge = 0;
_state = new State(double.NaN, double.NaN, double.NaN, double.NaN, 0, 0, double.NaN, double.NaN, 0, -1);
_p_state = _state;
_pState = _state;
Name = $"Decaychannel({period})";
WarmupPeriod = period;
@@ -135,25 +135,25 @@ public sealed class Decaychannel : ITValuePublisher
_index);
// Save buffer contents
Array.Copy(_hBuf, _hBuf_prev, _period);
Array.Copy(_lBuf, _lBuf_prev, _period);
Array.Copy(_hBuf, _hBufPrev, _period);
Array.Copy(_lBuf, _lBufPrev, _period);
}
private void RestoreState()
{
_currentMax = _p_state.CurrentMax;
_currentMin = _p_state.CurrentMin;
_maxAge = _p_state.MaxAge;
_minAge = _p_state.MinAge;
_rawMax = _p_state.RawMax;
_rawMin = _p_state.RawMin;
_count = _p_state.Count;
_index = _p_state.Index;
_state = _p_state;
_currentMax = _pState.CurrentMax;
_currentMin = _pState.CurrentMin;
_maxAge = _pState.MaxAge;
_minAge = _pState.MinAge;
_rawMax = _pState.RawMax;
_rawMin = _pState.RawMin;
_count = _pState.Count;
_index = _pState.Index;
_state = _pState;
// Restore buffer contents
Array.Copy(_hBuf_prev, _hBuf, _period);
Array.Copy(_lBuf_prev, _lBuf, _period);
Array.Copy(_hBufPrev, _hBuf, _period);
Array.Copy(_lBufPrev, _lBuf, _period);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -200,7 +200,7 @@ public sealed class Decaychannel : ITValuePublisher
{
// Save state BEFORE advancing (this is state from end of previous bar)
SaveState();
_p_state = _state;
_pState = _state;
// Now advance to new bar
_index++;
@@ -379,8 +379,8 @@ public sealed class Decaychannel : ITValuePublisher
{
Array.Clear(_hBuf);
Array.Clear(_lBuf);
Array.Clear(_hBuf_prev);
Array.Clear(_lBuf_prev);
Array.Clear(_hBufPrev);
Array.Clear(_lBufPrev);
_count = 0;
_index = -1;
_currentMax = double.NaN;
@@ -390,7 +390,7 @@ public sealed class Decaychannel : ITValuePublisher
_maxAge = 0;
_minAge = 0;
_state = new State(double.NaN, double.NaN, double.NaN, double.NaN, 0, 0, double.NaN, double.NaN, 0, -1);
_p_state = _state;
_pState = _state;
Last = default;
Upper = default;
Lower = default;
@@ -436,8 +436,8 @@ public sealed class Decaychannel : ITValuePublisher
try
{
QuanTAlib.Highest.Batch(high, rawMaxArr.AsSpan(0, len), period);
QuanTAlib.Lowest.Batch(low, rawMinArr.AsSpan(0, len), period);
Highest.Batch(high, rawMaxArr.AsSpan(0, len), period);
Lowest.Batch(low, rawMinArr.AsSpan(0, len), period);
double currentMax = double.NaN;
double currentMin = double.NaN;
-12
View File
@@ -58,18 +58,6 @@ public class VwapsdIndicator : Indicator, IWatchlistIndicator
base.OnInit();
}
private void UpdateSeriesNames()
{
if (UpperSeries != null)
{
UpperSeries.Name = $"Upper (+{NumDevs:F1}σ)";
}
if (LowerSeries != null)
{
LowerSeries.Name = $"Lower (-{NumDevs:F1}σ)";
}
}
protected override void OnUpdate(UpdateArgs args)
{
var item = HistoricalData[0, SeekOriginHistory.End];
-6
View File
@@ -132,8 +132,6 @@ public sealed class Avgprice : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -201,8 +199,6 @@ public sealed class Avgprice : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -210,8 +206,6 @@ public sealed class Avgprice : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 0, 0, 0);
-6
View File
@@ -117,8 +117,6 @@ public sealed class Ha : AbstractBase
return result;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -204,8 +202,6 @@ public sealed class Ha : AbstractBase
PubEvent(Last, isNew);
return LastBar;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -213,8 +209,6 @@ public sealed class Ha : AbstractBase
Update(new TValue(DateTime.UtcNow.Ticks, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = default;
-6
View File
@@ -130,8 +130,6 @@ public sealed class Medprice : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -197,8 +195,6 @@ public sealed class Medprice : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -206,8 +202,6 @@ public sealed class Medprice : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 0);
-6
View File
@@ -130,8 +130,6 @@ public sealed class Midbody : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -197,8 +195,6 @@ public sealed class Midbody : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -206,8 +202,6 @@ public sealed class Midbody : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 0);
-6
View File
@@ -135,8 +135,6 @@ public sealed class Midprice : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
var result = new TSeries(source.Count);
@@ -178,8 +176,6 @@ public sealed class Midprice : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
TimeSpan interval = step ?? TimeSpan.FromSeconds(1);
@@ -191,8 +187,6 @@ public sealed class Midprice : AbstractBase
time += interval;
}
}
/// <inheritdoc/>
public override void Reset()
{
_highBuffer.Clear();
-6
View File
@@ -132,8 +132,6 @@ public sealed class Typprice : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -200,8 +198,6 @@ public sealed class Typprice : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -209,8 +205,6 @@ public sealed class Typprice : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 0, 0);
-6
View File
@@ -131,8 +131,6 @@ public sealed class Wclprice : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -199,8 +197,6 @@ public sealed class Wclprice : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -208,8 +204,6 @@ public sealed class Wclprice : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 0, 0);
-7
View File
@@ -287,13 +287,6 @@ public class CcycTests
Assert.Equal(source.Count, batchResults.Count);
// Compare last 50 values
for (int i = source.Count - 50; i < source.Count; i++)
{
// Streaming processes all bars and streaming result is the last one
// But for exact comparison, batch results should match streaming approach
}
// The batch method creates a fresh indicator and calls Update(TSeries),
// which processes sequentially — should match streaming exactly
var ccyc2 = new Ccyc();
+6 -6
View File
@@ -208,8 +208,8 @@ public sealed class Ichimoku : ITValuePublisher
_p_state = _state;
Array.Fill(_highBuffer, double.NaN);
Array.Fill(_lowBuffer, double.NaN);
Array.Copy(_highBuffer, _p_highBuffer!, _highBuffer.Length);
Array.Copy(_lowBuffer, _p_lowBuffer!, _lowBuffer.Length);
Array.Copy(_highBuffer, _p_highBuffer, _highBuffer.Length);
Array.Copy(_lowBuffer, _p_lowBuffer, _lowBuffer.Length);
Tenkan = default;
Kijun = default;
SenkouA = default;
@@ -299,14 +299,14 @@ public sealed class Ichimoku : ITValuePublisher
if (isNew)
{
_p_state = _state;
Array.Copy(_highBuffer, _p_highBuffer!, _highBuffer.Length);
Array.Copy(_lowBuffer, _p_lowBuffer!, _lowBuffer.Length);
Array.Copy(_highBuffer, _p_highBuffer, _highBuffer.Length);
Array.Copy(_lowBuffer, _p_lowBuffer, _lowBuffer.Length);
}
else
{
_state = _p_state;
Array.Copy(_p_highBuffer!, _highBuffer, _highBuffer.Length);
Array.Copy(_p_lowBuffer!, _lowBuffer, _lowBuffer.Length);
Array.Copy(_p_highBuffer, _highBuffer, _highBuffer.Length);
Array.Copy(_p_lowBuffer, _lowBuffer, _lowBuffer.Length);
}
var (high, low, close) = GetValidHLC(bar);
-6
View File
@@ -198,8 +198,6 @@ public sealed class Pfe : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
if (source.Count == 0)
@@ -225,8 +223,6 @@ public sealed class Pfe : AbstractBase
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -457,8 +453,6 @@ public sealed class Pfe : AbstractBase
}
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Reset()
{
-6
View File
@@ -184,8 +184,6 @@ public sealed class Ravi : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
if (source.Count == 0)
@@ -211,8 +209,6 @@ public sealed class Ravi : AbstractBase
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -465,8 +461,6 @@ public sealed class Ravi : AbstractBase
}
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Reset()
{
@@ -49,7 +49,7 @@ public class TtmSqueezeValidationTests
}
// Momentum should be near zero since price = midline
Assert.True(System.Math.Abs(squeeze.Momentum.Value) < 1.0);
Assert.True(Math.Abs(squeeze.Momentum.Value) < 1.0);
}
[Fact]
@@ -250,7 +250,7 @@ public class TtmSqueezeValidationTests
for (int i = 0; i < 50; i++)
{
double price = 100 + System.Math.Sin(i * 0.2) * 10;
double price = 100 + Math.Sin(i * 0.2) * 10;
double high = price + 2;
double low = price - 2;
source.Add(new TBar(baseTime + i * 60000, price, high, low, price + 0.5, 1000));
@@ -306,7 +306,7 @@ public class TtmSqueezeValidationTests
Assert.True(double.IsFinite(squeeze.Momentum.Value));
// With constant price, donchian midline = price, so momentum should be near 0
Assert.True(System.Math.Abs(squeeze.Momentum.Value) < 0.01);
Assert.True(Math.Abs(squeeze.Momentum.Value) < 0.01);
}
[Fact]
-6
View File
@@ -184,8 +184,6 @@ public sealed class Vhf : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
if (source.Count == 0)
@@ -211,8 +209,6 @@ public sealed class Vhf : AbstractBase
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -461,8 +457,6 @@ public sealed class Vhf : AbstractBase
}
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Reset()
{
-8
View File
@@ -187,26 +187,18 @@ public sealed class Wrmse : AbstractBase
{
return Update(actual, predicted, DefaultWeight, isNew);
}
/// <inheritdoc/>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("WRMSE requires two inputs. Use Update(actual, predicted) or Update(actual, predicted, weight).");
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
throw new NotSupportedException("WRMSE requires two inputs. Use Batch(actualSeries, predictedSeries, period) or Batch(actualSeries, predictedSeries, weightsSeries, period).");
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("WRMSE requires two inputs.");
}
/// <inheritdoc/>
public override void Reset()
{
_weightedErrorBuffer.Clear();
+6 -6
View File
@@ -16,12 +16,12 @@ internal readonly record struct ParsedOhlcv(long Time, double Open, double High,
[StructLayout(LayoutKind.Auto)]
internal ref struct OhlcvParseState
{
public long Time;
public double Open;
public double High;
public double Low;
public double Close;
public double Volume;
internal long Time;
internal double Open;
internal double High;
internal double Low;
internal double Close;
internal double Volume;
}
/// <summary>
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 546 KiB

-10
View File
@@ -117,13 +117,9 @@ public sealed class ALaguerre : AbstractBase
}
source.Pub += Handle;
}
/// <inheritdoc/>
public override bool IsHot => _s.Count >= WarmupPeriod;
private const int StackAllocThreshold = 512;
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -203,8 +199,6 @@ public sealed class ALaguerre : AbstractBase
}
return _lastValidValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -230,8 +224,6 @@ public sealed class ALaguerre : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -571,8 +563,6 @@ public sealed class ALaguerre : AbstractBase
coeffBuf, ref cHead, ref cCount,
ref state, ref lastValid);
}
/// <inheritdoc/>
public override void Reset()
{
_s = State.New();
-3
View File
@@ -247,9 +247,6 @@ public sealed class BaxterKing : AbstractBase
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double SoftBandPass(double value) => value;
public static TSeries Batch(TSeries source, int pLow = 6, int pHigh = 32, int k = 12)
{
double[] input = source.Values.ToArray();
+1 -1
View File
@@ -34,7 +34,7 @@ public sealed class Butter2 : AbstractBase
CalculateCoefficients();
Name = $"Butter2({_period})";
WarmupPeriod = 4 * period;
_handler = new TValuePublishedHandler(Handle);
_handler = Handle;
Init();
}
+1 -1
View File
@@ -33,7 +33,7 @@ public sealed class Butter3 : AbstractBase
CalculateCoefficients();
Name = $"Butter3({_period})";
WarmupPeriod = 6 * period;
_handler = new TValuePublishedHandler(Handle);
_handler = Handle;
Init();
}
-13
View File
@@ -232,19 +232,6 @@ public sealed class Cfitz : AbstractBase
return weightedSum;
}
/// <summary>
/// Computes the ideal band-pass weight B_j for lag j.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double IdealWeight(double wl, double wh, int j)
{
if (j == 0)
{
return (wh - wl) / Math.PI;
}
return (Math.Sin(j * wh) - Math.Sin(j * wl)) / (Math.PI * j);
}
public static TSeries Batch(TSeries source, int pLow = 6, int pHigh = 32)
{
double[] input = source.Values.ToArray();
+2 -2
View File
@@ -65,7 +65,7 @@ public sealed class Cheby1 : AbstractBase
double wc = 2.0 * Math.PI / period;
double Wc = Math.Tan(wc * 0.5);
double epsilon = Math.Sqrt(Math.Pow(10.0, safeRipple * 0.1) - 1.0);
double mu = System.Math.Asinh(1.0 / epsilon) * 0.5;
double mu = Math.Asinh(1.0 / epsilon) * 0.5;
double sinhMu = Math.Sinh(mu);
double coshMu = Math.Cosh(mu);
double sigma = -sinhMu * Wc;
@@ -226,7 +226,7 @@ public sealed class Cheby1 : AbstractBase
double wc = 2.0 * Math.PI / period;
double Wc = Math.Tan(wc * 0.5);
double epsilon = Math.Sqrt(Math.Pow(10.0, safeRipple * 0.1) - 1.0);
double mu = System.Math.Asinh(1.0 / epsilon) * 0.5;
double mu = Math.Asinh(1.0 / epsilon) * 0.5;
double sinhMu = Math.Sinh(mu);
double coshMu = Math.Cosh(mu);
double sigma = -sinhMu * Wc;
+2 -2
View File
@@ -65,7 +65,7 @@ public sealed class Cheby2 : AbstractBase
double wc = 2.0 * Math.PI / period;
double Wc = 2.0 * Math.Tan(wc * 0.5);
double epsilon = 1.0 / Math.Sqrt(Math.Pow(10.0, safeAtten * 0.1) - 1.0);
double mu = System.Math.Asinh(1.0 / epsilon) * 0.5;
double mu = Math.Asinh(1.0 / epsilon) * 0.5;
double sinhMu = Math.Sinh(mu);
double coshMu = Math.Cosh(mu);
double sqrt2 = Math.Sqrt(2.0);
@@ -246,7 +246,7 @@ public sealed class Cheby2 : AbstractBase
double wc = 2.0 * Math.PI / period;
double Wc = 2.0 * Math.Tan(wc * 0.5);
double epsilon = 1.0 / Math.Sqrt(Math.Pow(10.0, safeAtten * 0.1) - 1.0);
double mu = System.Math.Asinh(1.0 / epsilon) * 0.5;
double mu = Math.Asinh(1.0 / epsilon) * 0.5;
double sinhMu = Math.Sinh(mu);
double coshMu = Math.Cosh(mu);
double sqrt2 = Math.Sqrt(2.0);
+40 -40
View File
@@ -278,53 +278,53 @@ public sealed class Gauss : AbstractBase
weights[i] *= invSum;
}
// Apply filter
for (int i = 0; i < source.Length; i++)
{
double result = 0;
double wSum = 0;
// Apply filter
for (int i = 0; i < source.Length; i++)
{
double result = 0;
double wSum = 0;
// This loop logic matches the RingBuffer partial fill logic.
// If i < kernelSize, we don't have enough history.
// The available history is source[0]...source[i].
// This history maps to the END of the kernel weights.
// E.g. if we have only 1 item (index i=0), it corresponds to weights[kernelSize-1].
// This loop logic matches the RingBuffer partial fill logic.
// If i < kernelSize, we don't have enough history.
// The available history is source[0]...source[i].
// This history maps to the END of the kernel weights.
// E.g. if we have only 1 item (index i=0), it corresponds to weights[kernelSize-1].
int count = Math.Min(i + 1, kernelSize);
int count = Math.Min(i + 1, kernelSize);
for (int j = 0; j < count; j++)
{
// Source index: i - (count - 1) + j
// if j=0, source index is i - count + 1.
// if count=kernelSize, init index is i - kernelSize + 1.
// if count=1 (i=0), init index is 0.
for (int j = 0; j < count; j++)
{
// Source index: i - (count - 1) + j
// if j=0, source index is i - count + 1.
// if count=kernelSize, init index is i - kernelSize + 1.
// if count=1 (i=0), init index is 0.
int srcIdx = i - (count - 1) + j;
double val = source[srcIdx];
int srcIdx = i - (count - 1) + j;
double val = source[srcIdx];
if (!double.IsNaN(val))
{
// Weight index:
// If full buffer, we use full weights 0..kernelSize-1.
// If partial, we align to end of weights.
// j=0 (oldest available) -> weights[kernelSize - count]
int weightIdx = kernelSize - count + j;
if (!double.IsNaN(val))
{
// Weight index:
// If full buffer, we use full weights 0..kernelSize-1.
// If partial, we align to end of weights.
// j=0 (oldest available) -> weights[kernelSize - count]
int weightIdx = kernelSize - count + j;
double w = weights[weightIdx];
result += val * w;
wSum += w;
}
}
double w = weights[weightIdx];
result += val * w;
wSum += w;
}
}
if (wSum > 0)
{
output[i] = result / wSum;
}
else
{
output[i] = double.NaN;
}
}
if (wSum > 0)
{
output[i] = result / wSum;
}
else
{
output[i] = double.NaN;
}
}
}
finally
{
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 543 KiB

+1 -4
View File
@@ -81,14 +81,11 @@ public sealed class Hann : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void GenerateWeights()
{
double coefSum = 0;
double denom = Length - 1;
for (int i = 0; i < Length; i++)
{
double w = 0.5 * (1.0 - Math.Cos(2.0 * Math.PI * i / denom));
_weights[i] = w;
coefSum += w;
_weights[i] = 0.5 * (1.0 - Math.Cos(2.0 * Math.PI * i / denom));
}
}
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 545 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 544 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 545 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 532 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 544 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 531 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 537 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 548 KiB

+1 -1
View File
@@ -33,7 +33,7 @@ public sealed class Ssf3 : AbstractBase
CalculateCoefficients();
Name = $"Ssf3({_period})";
WarmupPeriod = 6 * period;
_handler = new TValuePublishedHandler(Handle);
_handler = Handle;
Init();
}
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 546 KiB

+1 -1
View File
@@ -127,6 +127,6 @@ public class CciIndicatorTests
public void CciIndicator_ImplementsIWatchlistIndicator()
{
var indicator = new CciIndicator();
Assert.True(indicator is IWatchlistIndicator);
Assert.IsAssignableFrom<IWatchlistIndicator>(indicator);
}
}
-13
View File
@@ -36,8 +36,6 @@ public sealed class Cmo : AbstractBase
private readonly TValuePublishedHandler _handler;
private double _prevValue;
private double _p_prevValue;
/// <inheritdoc/>
public override bool IsHot => _upBuffer.IsFull;
/// <summary>
@@ -72,9 +70,6 @@ public sealed class Cmo : AbstractBase
{
source.Pub += _handler;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -131,8 +126,6 @@ public sealed class Cmo : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
if (source.Count == 0)
@@ -167,8 +160,6 @@ public sealed class Cmo : AbstractBase
{
Update(args.Value, args.IsNew);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
foreach (var value in source)
@@ -290,8 +281,6 @@ public sealed class Cmo : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <inheritdoc/>
public override void Reset()
{
_upBuffer.Clear();
@@ -300,8 +289,6 @@ public sealed class Cmo : AbstractBase
_p_prevValue = double.NaN;
Last = default;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (disposing)
-6
View File
@@ -145,15 +145,11 @@ public sealed class Prs : AbstractBase
{
return Update(new TValue(DateTime.UtcNow, baseValue), new TValue(DateTime.UtcNow, compValue), isNew);
}
/// <inheritdoc/>
/// <remarks>Not supported for bi-input indicator. Use Update(baseValue, compValue) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("PRS requires two inputs (base and comparison). Use Update(baseValue, compValue).");
}
/// <inheritdoc/>
/// <remarks>Not supported for bi-input indicator. Use Calculate(baseSeries, compSeries, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -240,8 +236,6 @@ public sealed class Prs : AbstractBase
return _ema;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("PRS requires two inputs. Use Prime(baseSource, compSource).");
-1
View File
@@ -36,7 +36,6 @@ public sealed class Sam : AbstractBase
private readonly double _ssC3;
private const double TwoPi = 2.0 * Math.PI;
private const double HalfPi = Math.PI / 2.0;
private const double Sqrt2 = 1.4142135623730951;
private const int MaxCyclePeriod = 50;
private const int MinCyclePeriod = 6;
-8
View File
@@ -94,8 +94,6 @@ public sealed class Bbb : AbstractBase
/// Standard deviation multiplier.
/// </summary>
public double Multiplier => _multiplier;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -167,8 +165,6 @@ public sealed class Bbb : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
Reset();
@@ -304,8 +300,6 @@ public sealed class Bbb : AbstractBase
_state.SumSq += v * v;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -313,8 +307,6 @@ public sealed class Bbb : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-8
View File
@@ -110,8 +110,6 @@ public sealed class Bbi : AbstractBase
/// <summary>True when enough bars have been processed for valid (full-window) output.</summary>
public override bool IsHot => _s.Index >= WarmupPeriod;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -202,8 +200,6 @@ public sealed class Bbi : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -227,8 +223,6 @@ public sealed class Bbi : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -236,8 +230,6 @@ public sealed class Bbi : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
Array.Clear(_buf1);
-8
View File
@@ -81,8 +81,6 @@ public sealed class Cfo : AbstractBase
/// Period of the indicator.
/// </summary>
public int Period => _period;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -153,8 +151,6 @@ public sealed class Cfo : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -191,8 +187,6 @@ public sealed class Cfo : AbstractBase
_state.SumXY += i * v;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -200,8 +194,6 @@ public sealed class Cfo : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-8
View File
@@ -118,8 +118,6 @@ public sealed class Crsi : AbstractBase
/// Percent rank lookback period.
/// </summary>
public int RankPeriod => _rankPeriod;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -224,8 +222,6 @@ public sealed class Crsi : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -250,8 +246,6 @@ public sealed class Crsi : AbstractBase
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -259,8 +253,6 @@ public sealed class Crsi : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_priceRsi.Reset();
-10
View File
@@ -77,14 +77,10 @@ public sealed class Cti : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
/// <inheritdoc/>
public override bool IsHot => _buffer.IsFull;
/// <summary>Period of the indicator.</summary>
public int Period => _period;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -151,8 +147,6 @@ public sealed class Cti : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -207,8 +201,6 @@ public sealed class Cti : AbstractBase
_s.SumXY = Math.FusedMultiplyAdd(i, v, _s.SumXY);
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -216,8 +208,6 @@ public sealed class Cti : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-2
View File
@@ -278,7 +278,6 @@ public sealed class Dem : ITValuePublisher
double prevHigh = double.NaN;
double prevLow = double.NaN;
int idx = 0;
int count = 0;
for (int i = 0; i < len; i++)
{
@@ -302,7 +301,6 @@ public sealed class Dem : ITValuePublisher
deMinSum += deMin;
idx = (idx + 1) % period;
count++;
prevHigh = h;
prevLow = l;
-10
View File
@@ -143,11 +143,7 @@ public sealed class Dosc : AbstractBase
}
source.Pub += Handle;
}
/// <inheritdoc/>
public override bool IsHot => _s.Count >= WarmupPeriod;
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -195,8 +191,6 @@ public sealed class Dosc : AbstractBase
}
return s.LastValidSrc;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -226,8 +220,6 @@ public sealed class Dosc : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -428,8 +420,6 @@ public sealed class Dosc : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <inheritdoc/>
public override void Reset()
{
_s = State.New();
-8
View File
@@ -78,8 +78,6 @@ public sealed class Dpo : AbstractBase
/// Displacement of the SMA lookback.
/// </summary>
public int Displacement => _displacement;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -141,8 +139,6 @@ public sealed class Dpo : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -164,8 +160,6 @@ public sealed class Dpo : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -173,8 +167,6 @@ public sealed class Dpo : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_smaBuffer.Clear();
-8
View File
@@ -143,8 +143,6 @@ public sealed class Dymoi : AbstractBase
/// <summary>Maximum allowable dynamic period.</summary>
public int MaxPeriod => _maxPeriod;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -276,8 +274,6 @@ public sealed class Dymoi : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -302,8 +298,6 @@ public sealed class Dymoi : AbstractBase
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -311,8 +305,6 @@ public sealed class Dymoi : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, true, double.NaN, double.NaN);
-8
View File
@@ -73,8 +73,6 @@ public sealed class Er : AbstractBase
/// Period of the indicator.
/// </summary>
public int Period => _period;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -141,8 +139,6 @@ public sealed class Er : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -164,8 +160,6 @@ public sealed class Er : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
TimeSpan interval = step ?? TimeSpan.FromTicks(1);
@@ -175,8 +169,6 @@ public sealed class Er : AbstractBase
Update(new TValue(baseTime + (interval * i), source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_closeBuf.Clear();
-8
View File
@@ -90,8 +90,6 @@ public sealed class Fisher : AbstractBase
/// Current Signal line value.
/// </summary>
public double Signal => _state.Signal;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -172,8 +170,6 @@ public sealed class Fisher : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -195,8 +191,6 @@ public sealed class Fisher : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
TimeSpan interval = step ?? TimeSpan.FromTicks(1);
@@ -206,8 +200,6 @@ public sealed class Fisher : AbstractBase
Update(new TValue(baseTime + (interval * i), source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-8
View File
@@ -88,8 +88,6 @@ public sealed class Fisher04 : AbstractBase
/// Current Signal line value.
/// </summary>
public double Signal => _state.Signal;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -168,8 +166,6 @@ public sealed class Fisher04 : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -191,8 +187,6 @@ public sealed class Fisher04 : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
TimeSpan interval = step ?? TimeSpan.FromTicks(1);
@@ -202,8 +196,6 @@ public sealed class Fisher04 : AbstractBase
Update(new TValue(baseTime + (interval * i), source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-6
View File
@@ -230,8 +230,6 @@ public sealed class Gator : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
if (source.Count == 0)
@@ -257,8 +255,6 @@ public sealed class Gator : AbstractBase
Last = new TValue(tSpan[len - 1], vSpan[len - 1]);
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -555,8 +551,6 @@ public sealed class Gator : AbstractBase
}
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override void Reset()
{
-8
View File
@@ -83,8 +83,6 @@ public sealed class Inertia : AbstractBase
/// Period of the indicator.
/// </summary>
public int Period => _period;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -155,8 +153,6 @@ public sealed class Inertia : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -193,8 +189,6 @@ public sealed class Inertia : AbstractBase
_state.SumXY += i * v;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -202,8 +196,6 @@ public sealed class Inertia : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-10
View File
@@ -59,14 +59,10 @@ public sealed class Kri : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
/// <inheritdoc/>
public override bool IsHot => _buffer.IsFull;
/// <summary>Period of the indicator.</summary>
public int Period => _period;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -120,8 +116,6 @@ public sealed class Kri : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -140,8 +134,6 @@ public sealed class Kri : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
TimeSpan interval = step ?? TimeSpan.FromTicks(1);
@@ -151,8 +143,6 @@ public sealed class Kri : AbstractBase
Update(new TValue(baseTime + (interval * i), source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-10
View File
@@ -62,14 +62,10 @@ public sealed class Psl : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
/// <inheritdoc/>
public override bool IsHot => _buffer.IsFull;
/// <summary>Period of the indicator.</summary>
public int Period => _period;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -126,8 +122,6 @@ public sealed class Psl : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -146,8 +140,6 @@ public sealed class Psl : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
TimeSpan interval = step ?? TimeSpan.FromTicks(1);
@@ -157,8 +149,6 @@ public sealed class Psl : AbstractBase
Update(new TValue(baseTime + (interval * i), source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-10
View File
@@ -108,11 +108,7 @@ public sealed class Reflex : AbstractBase
}
source.Pub += Handle;
}
/// <inheritdoc/>
public override bool IsHot => _s.Count >= _period;
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -160,8 +156,6 @@ public sealed class Reflex : AbstractBase
}
return s.LastValid;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -183,8 +177,6 @@ public sealed class Reflex : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -396,8 +388,6 @@ public sealed class Reflex : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <inheritdoc/>
public override void Reset()
{
_s = State.New();
-10
View File
@@ -122,11 +122,7 @@ public sealed class ReverseEma : AbstractBase
}
source.Pub += Handle;
}
/// <inheritdoc/>
public override bool IsHot => _s.IsHot;
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -185,8 +181,6 @@ public sealed class ReverseEma : AbstractBase
}
return _lastValidValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -213,8 +207,6 @@ public sealed class ReverseEma : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -415,8 +407,6 @@ public sealed class ReverseEma : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <inheritdoc/>
public override void Reset()
{
_s = State.New();
-10
View File
@@ -99,11 +99,7 @@ public sealed class Trendflex : AbstractBase
}
source.Pub += Handle;
}
/// <inheritdoc/>
public override bool IsHot => _s.Count >= _period;
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -148,8 +144,6 @@ public sealed class Trendflex : AbstractBase
}
return s.LastValid;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -171,8 +165,6 @@ public sealed class Trendflex : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -337,8 +329,6 @@ public sealed class Trendflex : AbstractBase
TSeries results = indicator.Update(source);
return (results, indicator);
}
/// <inheritdoc/>
public override void Reset()
{
_s = State.New();
-8
View File
@@ -96,8 +96,6 @@ public sealed class Trix : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void Handle(object? sender, in TValueEventArgs e) => Update(e.Value, e.IsNew);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -198,8 +196,6 @@ public sealed class Trix : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -223,8 +219,6 @@ public sealed class Trix : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -232,8 +226,6 @@ public sealed class Trix : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 0, 0, 1.0, 1.0, 1.0, 0, 0, 0);
@@ -114,15 +114,11 @@ public sealed class Cointegration : AbstractBase
{
return Update(new TValue(DateTime.MinValue, seriesA), new TValue(DateTime.MinValue, seriesB), isNew);
}
/// <inheritdoc/>
/// <remarks>Not supported for bi-input indicator. Use Update(seriesA, seriesB) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Cointegration requires two inputs (seriesA and seriesB). Use Update(seriesA, seriesB).");
}
/// <inheritdoc/>
/// <remarks>Not supported for bi-input indicator. Use Calculate(seriesA, seriesB, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -402,8 +398,6 @@ public sealed class Cointegration : AbstractBase
_sumDelta2 = FusedMultiplyAdd(delta, delta, _sumDelta2);
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Cointegration requires two inputs.");
@@ -113,15 +113,11 @@ public sealed class Correlation : AbstractBase
{
return Update(new TValue(DateTime.MinValue, seriesX), new TValue(DateTime.MinValue, seriesY), isNew);
}
/// <inheritdoc/>
/// <remarks>Not supported for bi-input indicator. Use Update(seriesX, seriesY) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Correlation requires two inputs (seriesX and seriesY). Use Update(seriesX, seriesY).");
}
/// <inheritdoc/>
/// <remarks>Not supported for bi-input indicator. Use Calculate(seriesX, seriesY, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -263,8 +259,6 @@ public sealed class Correlation : AbstractBase
_sumXY = FusedMultiplyAdd(x, y, _sumXY);
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Correlation requires two inputs.");
-6
View File
@@ -108,15 +108,11 @@ public sealed class Granger : AbstractBase
{
return Update(new TValue(DateTime.UtcNow, seriesY), new TValue(DateTime.UtcNow, seriesX), isNew);
}
/// <inheritdoc/>
/// <remarks>Not supported for dual-input indicator. Use Update(seriesY, seriesX) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Granger requires two inputs (seriesY and seriesX). Use Update(seriesY, seriesX).");
}
/// <inheritdoc/>
/// <remarks>Not supported for dual-input indicator. Use Batch(seriesY, seriesX, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -370,8 +366,6 @@ public sealed class Granger : AbstractBase
_sumYLagXLag = FusedMultiplyAdd(yLag, xLag, _sumYLagXLag);
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Granger requires two inputs.");
-6
View File
@@ -93,15 +93,11 @@ public sealed class Kendall : AbstractBase
{
return Update(new TValue(DateTime.UtcNow, seriesX), new TValue(DateTime.UtcNow, seriesY), isNew);
}
/// <inheritdoc/>
/// <remarks>Not supported for dual-input indicator. Use Update(seriesX, seriesY) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Kendall requires two inputs (seriesX and seriesY). Use Update(seriesX, seriesY).");
}
/// <inheritdoc/>
/// <remarks>Not supported for dual-input indicator. Use Batch(seriesX, seriesY, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -173,8 +169,6 @@ public sealed class Kendall : AbstractBase
return (concordant - discordant) / denominator;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Kendall requires two inputs.");
+1 -1
View File
@@ -279,7 +279,7 @@ public sealed class Pacf : AbstractBase
_sum = 0;
for (int i = 0; i < _buffer.Count; i++)
{
_sum += _buffer[i];
_sum += _buffer[i];
}
}
-6
View File
@@ -98,15 +98,11 @@ public sealed class Spearman : AbstractBase
{
return Update(new TValue(DateTime.UtcNow, seriesX), new TValue(DateTime.UtcNow, seriesY), isNew);
}
/// <inheritdoc/>
/// <remarks>Not supported for dual-input indicator. Use Update(seriesX, seriesY) instead.</remarks>
public override TValue Update(TValue input, bool isNew = true)
{
throw new NotSupportedException("Spearman requires two inputs (seriesX and seriesY). Use Update(seriesX, seriesY).");
}
/// <inheritdoc/>
/// <remarks>Not supported for dual-input indicator. Use Batch(seriesX, seriesY, period) instead.</remarks>
public override TSeries Update(TSeries source)
{
@@ -236,8 +232,6 @@ public sealed class Spearman : AbstractBase
ranks[i] = countSmaller + (countEqual - 1) * 0.5 + 1.0;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
throw new NotSupportedException("Spearman requires two inputs.");
+7 -7
View File
@@ -31,7 +31,7 @@ public sealed class Alma : AbstractBase
[StructLayout(LayoutKind.Auto)]
private record struct State(double LastValidValue, bool IsInitialized);
private State _state;
private State _p_state;
private State _pState;
public bool IsNew => _isNew;
public override bool IsHot => _buffer.IsFull;
@@ -139,11 +139,11 @@ public sealed class Alma : AbstractBase
{
if (isNew)
{
_p_state = _state;
_pState = _state;
}
else
{
_state = _p_state;
_state = _pState;
}
if (double.IsFinite(input.Value))
@@ -213,7 +213,7 @@ public sealed class Alma : AbstractBase
// Reset state
_buffer.Clear();
_state = default;
_p_state = default;
_pState = default;
int warmupLength = Math.Min(source.Length, WarmupPeriod);
int startIndex = source.Length - warmupLength;
@@ -254,7 +254,7 @@ public sealed class Alma : AbstractBase
Update(new TValue(DateTime.MinValue, source[i]), isNew: true, publish: false);
}
_p_state = _state;
_pState = _state;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -449,7 +449,7 @@ public sealed class Alma : AbstractBase
{
_buffer.Clear();
_state = new State(double.NaN, IsInitialized: false);
_p_state = _state;
_pState = _state;
Last = default;
}
}
}
-8
View File
@@ -90,8 +90,6 @@ public sealed class Nlma : AbstractBase
_isNew = isNew;
return UpdateCore(input, isNew, publish: true);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
if (source.Count == 0)
@@ -326,8 +324,6 @@ public sealed class Nlma : AbstractBase
}
// ── Prime / Batch / Calculate ──────────────────────────────────────
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
foreach (var value in source)
@@ -489,8 +485,6 @@ public sealed class Nlma : AbstractBase
}
// ── Reset / Dispose ────────────────────────────────────────────────
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
@@ -498,8 +492,6 @@ public sealed class Nlma : AbstractBase
_p_lastValidValue = double.NaN;
Last = default;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (!_disposed)
+5 -4
View File
@@ -1,9 +1,10 @@
using System.Reflection;
using System.Runtime.Intrinsics.X86;
using Xunit.Abstractions;
namespace QuanTAlib.Tests;
public class WmaCoverageTests
public class WmaCoverageTests(ITestOutputHelper output)
{
[Fact]
public void Cover_Scalar_Fallback_SmallData()
@@ -41,7 +42,7 @@ public class WmaCoverageTests
source[i] = i;
}
double[] output = new double[len];
double[] result = new double[len];
// Use reflection to invoke private static CalculateSimdCore
var method = typeof(Wma).GetMethod("CalculateSimdCore", BindingFlags.NonPublic | BindingFlags.Static);
@@ -73,12 +74,12 @@ public class WmaCoverageTests
// Maybe I can use `MethodInfo.CreateDelegate`?
// Delegates can take Spans if defined correctly.
InvokePrivateStaticMethod_WithSpans("CalculateSimdCore", source, output, period);
InvokePrivateStaticMethod_WithSpans("CalculateSimdCore", source, result, period);
}
catch (Exception ex)
{
// If reflection fails, we can't cover it.
Console.WriteLine($"Could not invoke AVX2 core: {ex.Message}");
output.WriteLine($"Could not invoke AVX2 core: {ex.Message}");
}
}
-10
View File
@@ -87,13 +87,9 @@ public sealed class Rema : AbstractBase
}
source.Pub += Handle;
}
/// <inheritdoc/>
public override bool IsHot => _state.IsHot;
private const int StackAllocThreshold = 512;
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -162,8 +158,6 @@ public sealed class Rema : AbstractBase
}
return _lastValidValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -184,8 +178,6 @@ public sealed class Rema : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -450,8 +442,6 @@ public sealed class Rema : AbstractBase
TSeries results = rema.Update(source);
return (results, rema);
}
/// <inheritdoc/>
public override void Reset()
{
_state = State.New();
-12
View File
@@ -47,8 +47,6 @@ public sealed class Rgma : AbstractBase
private const double COVERAGE_THRESHOLD = 0.05;
private const int ResyncInterval = 10000;
private const int StackAllocThreshold = 512;
/// <inheritdoc/>
public override bool IsHot => _state.IsHot;
/// <summary>
@@ -112,8 +110,6 @@ public sealed class Rgma : AbstractBase
}
return _lastValidValue;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
if (source.Length == 0)
@@ -190,8 +186,6 @@ public sealed class Rgma : AbstractBase
}
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -234,8 +228,6 @@ public sealed class Rgma : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public override TSeries Update(TSeries source)
{
@@ -463,8 +455,6 @@ public sealed class Rgma : AbstractBase
TSeries results = rgma.Update(source);
return (results, rgma);
}
/// <inheritdoc/>
public override void Reset()
{
_state = State.New();
@@ -475,8 +465,6 @@ public sealed class Rgma : AbstractBase
Array.Fill(_p_filters, double.NaN);
Last = default;
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (!_disposed)
-8
View File
@@ -95,8 +95,6 @@ public sealed class Bbw : AbstractBase
/// Standard deviation multiplier.
/// </summary>
public double Multiplier => _multiplier;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -159,8 +157,6 @@ public sealed class Bbw : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -196,8 +192,6 @@ public sealed class Bbw : AbstractBase
_state.SumSq += v * v;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -205,8 +199,6 @@ public sealed class Bbw : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-8
View File
@@ -107,8 +107,6 @@ public sealed class Bbwn : AbstractBase
/// Historical lookback period for normalization.
/// </summary>
public int Lookback => _lookback;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -212,8 +210,6 @@ public sealed class Bbwn : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -249,8 +245,6 @@ public sealed class Bbwn : AbstractBase
_state.SumSq += v * v;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -258,8 +252,6 @@ public sealed class Bbwn : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-8
View File
@@ -108,8 +108,6 @@ public sealed class Bbwp : AbstractBase
/// Historical lookback period for percentile calculation.
/// </summary>
public int Lookback => _lookback;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -205,8 +203,6 @@ public sealed class Bbwp : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -242,8 +238,6 @@ public sealed class Bbwp : AbstractBase
_state.SumSq += v * v;
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -251,8 +245,6 @@ public sealed class Bbwp : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_buffer.Clear();
-8
View File
@@ -100,8 +100,6 @@ public sealed class Ccv : AbstractBase
/// Smoothing method (1=SMA, 2=EMA, 3=WMA).
/// </summary>
public int Method => _method;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -242,8 +240,6 @@ public sealed class Ccv : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -276,8 +272,6 @@ public sealed class Ccv : AbstractBase
_state.Sum += _returnBuffer[i];
}
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -285,8 +279,6 @@ public sealed class Ccv : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_returnBuffer.Clear();
-8
View File
@@ -117,8 +117,6 @@ public sealed class Cv : AbstractBase
/// Beta coefficient (persistence weight).
/// </summary>
public double Beta => _beta;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -241,8 +239,6 @@ public sealed class Cv : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -265,8 +261,6 @@ public sealed class Cv : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -274,8 +268,6 @@ public sealed class Cv : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0.0, 0.0, 0.0, 0.0, double.NaN, 0.0, 0);
-6
View File
@@ -152,8 +152,6 @@ public sealed class Cvi : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -254,8 +252,6 @@ public sealed class Cvi : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -263,8 +259,6 @@ public sealed class Cvi : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_emaBuffer.Clear();
-8
View File
@@ -103,8 +103,6 @@ public sealed class Ewma : AbstractBase
/// Number of periods per year for annualization.
/// </summary>
public int AnnualPeriods => _annualPeriods;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override TValue Update(TValue input, bool isNew = true)
{
@@ -193,8 +191,6 @@ public sealed class Ewma : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -217,8 +213,6 @@ public sealed class Ewma : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -226,8 +220,6 @@ public sealed class Ewma : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0.0, 1.0, double.NaN, 0.0, 0);
-6
View File
@@ -226,8 +226,6 @@ public sealed class Gkv : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -324,8 +322,6 @@ public sealed class Gkv : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -333,8 +329,6 @@ public sealed class Gkv : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 1.0, 0, 0, 0);
-6
View File
@@ -211,8 +211,6 @@ public sealed class Hlv : AbstractBase
return new TSeries(t, v);
}
/// <inheritdoc/>
public override TSeries Update(TSeries source)
{
int len = source.Count;
@@ -309,8 +307,6 @@ public sealed class Hlv : AbstractBase
PubEvent(Last, isNew);
return Last;
}
/// <inheritdoc/>
public override void Prime(ReadOnlySpan<double> source, TimeSpan? step = null)
{
for (int i = 0; i < source.Length; i++)
@@ -318,8 +314,6 @@ public sealed class Hlv : AbstractBase
Update(new TValue(DateTime.UtcNow, source[i]), isNew: true);
}
}
/// <inheritdoc/>
public override void Reset()
{
_s = new State(0, 1.0, 0, 0, 0);

Some files were not shown because too many files have changed in this diff Show More