Blank lines were missing around $$ fences (bold labels or list items
glued directly to $$, and stacked $$ blocks with no separator),
causing GitHub to merge them into the surrounding paragraph and
misread underscores as italic markers instead of rendering math.
The 128-sample trimmed mean now uses Index-Linked Sorted Arrays instead of a per-bar sort. Updated operation counts (1,245 -> ~411 cycles), dropped the obsolete 65-value-sum SIMD row, and corrected the memory footprint.
snyk test --all-projects was resolving QuanTAlib.slnx to the whole solution, bypassing .dcignore and pulling the NativeAOT/benchmark projects. Exclude *.slnx so only lib/quantalib.csproj is scanned. Reverted the --file attempt, which cannot detect a package manager for a bare .csproj.
Both jobs built/scanned the whole solution, pulling the NativeAOT ILCompiler and benchmark packages and blowing their timeouts. ReSharper now restores/builds only lib/quantalib.csproj, and Snyk scans it explicitly instead of --all-projects (which detected QuanTAlib.slnx).
Restore only lib/quantalib.csproj instead of the whole solution, so the NativeAOT ILCompiler and benchmark native packages are no longer pulled. Raised the Snyk job timeout from 10 to 30 minutes.
snyk test --all-projects was scanning benchmarks, the NativeAOT wrapper, the Quantower adapter, and the test project, whose deps (MyGet feed, native/validation libs, a local Quantower DLL) failed dependency-graph enrichment. Added .dcignore to exclude them so Snyk scans only lib/quantalib.csproj.
Added wickra (Rust/PyO3) as a comparison library across all 7 indicators. Fixed the correlation export name mismatch (qtl_correlation -> qtl_correl) and the benchmark's qtl.correlation -> qtl.correl reference so Pearson correlation is benchmarkable.
Added PublicApiAnalyzers 5.6.0 with PublicAPI.Shipped baselines (net10.0/net48) so breaking API changes fail the build (RS0016/RS0017). Enabled snupkg symbol packages and CI push.
TA-Lib and Tulip produced near-identical numbers (both C libs via FFI), making Tulip redundant as a comparison. Swapped in Wickra (Rust-core) across the main and progressive harnesses (SMA/EMA/WMA/HMA/ADOSC).
Correl.Batch(span) previously looped the streaming Update path - Kahan sums,
RingBuffer, and DateTime.UtcNow per bar, with no SIMD. Replaced with sliding-window
delta sums and AVX-512/AVX2 prefix-sum cores, keeping a Kahan scalar fallback for
dirty/small inputs.
Correlation Span: 17,994 us -> 1,396 us (12.9x), now 1.6x faster than TA-Lib (2,157 us).
Drop stale version from README heading and remove build-time README stamping
Rewrite NuGet description/product and PyPI author and project_urls
Generate NuGet README with absolute URLs at pack time
Add net48 reference assemblies for Linux CI and publish NT8 net48 ZIP asset
Series arithmetic (lib/numerics):
- Add, Sub, Mul, Div, Lag, reusing BiInputIndicatorBase at period=1
- Div publishes 0.0 (not NaN) on a zero denominator, since a non-finite
ComputeError result permanently poisons the base's running sum
- BiInputIndicatorBase gains Subscribe(a, b) implementing the
strategy-primitives spec's time-join rule for event-chained two-input nodes
Phase 0 contracts (lib/core):
- TTradeContext, BracketFlags, ExitReason, TrendState, VolState
- SignalConstants (DefaultEpsilon, TruthThreshold), OutOfRangePolicy
- ConfirmOnClose: bar-confirmation wrapper (Section 8.6)
Signal predicates (lib/signals/predicates), Phase 1:
- Above, Below, Equal (ComparePredicateBase<TOp> generic comparison core)
- InsideChannel, OutsideChannel, ChannelPosition (new MultiInputBase,
3-input time-join)
- IsRising, IsFalling (exclude current bar, confirm-then-push window)
- AtHighest, AtLowest (include current bar, rebuild-on-correction,
mirrors channels/Dc)
- Hysteresis, PercentDistance
All new nodes ship with .cs, tests, and .md docs; indices and the
StrategyPrimitives.Spec.md are updated with placement decisions and
design notes. Full suite: 16730 tests, 0 failures, 0 warnings.
- MAMA: replace atan2+angle-wrapping with Ehlers/TA-Lib's atan(Q/I) signed-delta
discriminator for both phase and period calculations. Was diverging from
TA-Lib/Skender by up to 11%; now matches within 0.01 absolute tolerance.
- NATR: fix TA-Lib validation test dividing ATR by a close price ~14 bars
misaligned (TA-Lib's output array is offset-compact, not absolute-indexed).
Now passes at 1e-9 instead of masking the bug with a 0.10 tolerance.
- ValidationHelper: tighten default tolerances to match AGENTS.md (1e-9 for
Skender/TALib/Tulip, 1e-6 for Ooples, was 1e-7 uniformly). Added documented
per-test tolerance overrides where large-window/large-magnitude sums
(WMA/HMA/TRIMA/DWMA period=100, rolling StdDev/Variance, AD cumulative sum,
linear regression) genuinely exceed 1e-9 due to floating-point accumulation
order, not algorithmic divergence.
- ROC/ROCP/ROCR: old Roc (Price-Price[N]) was an exact duplicate of Mom;
removed. Old Rocp (100*(P-P[N])/P[N]) was actually TA-Lib's ROC formula;
renamed to Roc. New Rocp created with TA-Lib's real ROCP formula
((P-P[N])/P[N], no *100). Updated C#, Quantower, Python bindings, and
pandas-ta parity tests accordingly.
- Added Validation.Tests.cs for 12 previously-unvalidated indicators: Sarext
(TA-Lib SarExt), Minindex/Maxindex (TA-Lib MinIndex/MaxIndex, exact match),
Convexity (Skender GetBeta BetaType.All), Vwmacd (Vwma+Ema composition),
and independent formula re-derivations for Usi, Eeo, Net, Pta, Amfm, Hwc
(no external library implements these Ehlers indicators). Lpf validated
structurally (documented invariants) given its 5-stage adaptive algorithm.
- Updated docs/validation.md, Roc.md/Rocp.md/Mom.md/Mama.md accordingly.