Files
QuanTAlib/.clinerules/AGENTS.md
T
86fe32a682 SIMD Refactor: Merge simd-dev into dev (#55)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat>
Co-authored-by: Warp <agent@warp.dev>
2026-01-18 19:02:03 -08:00

408 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QuanTAlib Master Protocol (AI Agents)
WARN: repo laws/physics. Read relevant sections bf code. Noncompliance→reject.
DCT{
1:Hot paths allocation-free (no heap alloc); GC pressure enemy;
2:Streaming updates O(1) when math allows;
3:Dual API: stateful Update + stateless static Calculate;
4:Bar correction via isNew rollback (same timestamp rewrite);
5:Robustness: handle NaN/Infinity via last-valid-value substitution; never propagate invalids;
6:SoA: store primitives in concrete List<T> fields + expose spans via CollectionsMarshal.AsSpan;
7:SIMD in Calculate where possible; scalar fallback else;
8:Docs: technical correctness + measurable evidence + skeptical-architect tone; markdownlint strict.
}
QUICKSTART: DO:{Create Indicator}#p1; DO:{Create Adapters for Quantower + other platforms}#p1; DO:{Write comprehensive Tests + validations}#p1; DO:{Write Stylistically + Structurally correct Docs}#p2; DO:{Performance Tuning}#p1.
CRIT_PATTERNS:
- State: use `private record struct State`
- Stack-only: prefer `readonly ref struct` when something should absolutely never leave the stack
- Imports: prefer `using static` for math-heavy/pure helper classes to reduce ceremony and keep expressions readable
- Types: prefer nullable annotations for optional refs; prefer `record`/`record struct` for value-like models/state
- Code clarity: prioritize self-documenting names/structure; use comments for “why”, not “what”
- Encapsulation: prefer `file` types for internal-only helpers
- Closures: prefer `static` local functions to avoid accidental captures
- Discards: use explicit discard (`_ = expr;`) when intentionally ignoring a return value
- Lifetimes: use `scoped ref` parameters for internal APIs to constrain lifetimes
- Events: `source.Pub += Handle;`
- Args: `ArgumentException` + `nameof(param)`
- FMA: `Math.FusedMultiplyAdd(a, b, c)` for `a*b+c`
- Storage: `List<T>` fields for SoA (suppress MA0016 narrowly around those fields)
- Time: always `DateTime.UtcNow` (never `DateTime.Now`)
- Tests: use `GBM` for data; never `System.Random`
1) IDENTITY & MISSION
- QuanTAlib: high-perf, ^1 C# lib for quantitative technical analysis.
- Model: IF PineScript exists in same indicator dir → use as foundation.
- Target: Quantower + custom C# trading engines.
- Philosophy: Speed + Correctness + Memory Efficiency.
2) ARCHITECTURE & PHYSICS
2.1 Memory model (^6)
- No objects-in-lists; primitives-in-arrays.
- TSeries internal: `List<long> _t` (timestamps), `List<double> _v` (values).
- Access: expose `ReadOnlySpan<double>` for SIMD.
- Analyzer note: MA0016 suggests abstractions; suppress only around core List<T> fields by design.
2.2 Core types
- `TValue` struct (16 bytes): `DateTime Time`, `double Value`.
- `TBar` struct (48 bytes): `DateTime Time`, `double Open, High, Low, Close, Volume`.
- `TSeries` primary time-series DS; `ITValuePublisher` reactive flow.
2.3 Design principles
- Source material: PineScript at [U1].
- ^1: use `Span<T>`, `stackalloc`, pinned mem where needed.
- ^2: running sums/products or RingBuffer; avoid history re-iter.
- ^3: Update + Calculate.
- ^4: isNew rollback required.
- ^5: NaN/Infinity safe.
- Reactive: implement `ITValuePublisher`.
- Time handling: `DateTime.UtcNow`.
2.4 Performance rules (hard constraints)
- Update MUST satisfy ^1 and ^2.
- SIMD: Calculate should use `System.Runtime.Intrinsics` (AVX2) or `System.Numerics.Vector<T>`; use `Vector.ConditionalSelect` for branchless edge handling (eg div0). If recursion blocks SIMD → prefer `stackalloc` buffers.
- Hot methods: `[MethodImpl(MethodImplOptions.AggressiveInlining)]`.
- Tight loops: `[SkipLocalsInit]`.
2.5 FMA patterns (use in hot paths)
- EMA smoothing: `x + alpha * (y - x)``Math.FusedMultiplyAdd(x, decay, alpha * y)` where `decay = 1 - alpha`
- Weighted sum: `a*w1 + b*w2``Math.FusedMultiplyAdd(a, w1, b * w2)`
- Linear combo: `3.0*a - b``Math.FusedMultiplyAdd(3.0, a, -b)`
- Cross product: `(a*b) + (c*d)``Math.FusedMultiplyAdd(a, b, c * d)`
- IIR: `coef*input + feedback*state``Math.FusedMultiplyAdd(coef, input, feedback * state)`
Use FMA for EMA-style smoothing, IIR (Butterworth/Chebyshev/SSF), HTIT/MAMA-style homodyne, any `a*b+c`.
Avoid FMA for simple ops, when intermediate rounding required, or in SIMD paths (use `Fma.MultiplyAdd` / `Avx512F.FusedMultiplyAdd` / `AdvSimd.Arm64.FusedMultiplyAdd`).
Precompute decay constants:
`private readonly double _alpha; private readonly double _decay; // = 1 - _alpha`
Hot path: `result = Math.FusedMultiplyAdd(prevState, _decay, _alpha * newInput);`
3) IMPLEMENTATION STANDARDS (every indicator)
3.1 File layout
DIR: `lib/[category]/[name]/` (eg `lib/trends/sma/`)
REQ files:
- `[Name].cs` (main impl, `public sealed class`)
- `[Name].Tests.cs` (xUnit)
- `[Name].Validation.Tests.cs` (vs TA-Lib/Skender/Tulip/Ooples)
- `[Name].md` (docs + formulas)
- `[Name].Quantower.cs` (adapter)
- `[Name].Quantower.Tests.cs` (adapter tests)
3.2 Class definition
- Namespace `QuanTAlib`; `[SkipLocalsInit]`; `public sealed class`; implements `ITValuePublisher`.
3.3 State mgmt
- Scalar state: `private record struct State` grouping all scalar vars.
- Maintain `_state` (current) + `_p_state` (prev valid).
- Buffers: `RingBuffer` for sliding windows.
- Resync: periodic full recalculation (eg every 1000 ticks) to limit floating drift in running sums.
3.4 Constructor rules
- Validate params: throw `ArgumentException` + `nameof()`.
- Set Name: eg `$\"Sma({period})\"`.
- Support chaining ctor: `public [Name](ITValuePublisher source, ...)`.
- Event subscribe: `source.Pub += Handle;` (no defensive null checks when source is non-nullable).
3.5 Update(TValue) contract
SIG: `public TValue Update(TValue input, bool isNew = true)` w/ `[MethodImpl(MethodImplOptions.AggressiveInlining)]`
FLOW:
- IF isNew→ `_p_state=_state` then advance counters; ELSE rollback `_state=_p_state`.
- Validate input: if `!double.IsFinite` → substitute last-valid (stored in State).
- Compute (apply FMA where relevant).
- Publish: update `Last`, invoke `Pub`, return `Last`.
3.6 Update(TSeries)
SIG: `public TSeries Update(TSeries source)` adjacent to Update(TValue)
- Create output series
- Call static `Calculate(ReadOnlySpan<double>, Span<double>, ...)`
- Restore internal state by replaying last Period bars (or full series if recursive).
3.7 Static Calculate(TSeries)
- Create indicator instance
- Iterate source series
- Return output TSeries
3.8 Static Calculate(Span) (perf-critical)
SIG: `public static void Calculate(ReadOnlySpan<double> source, Span<double> output, ...)`
RULES:
- Validate args w/ `ArgumentException` incl `nameof(output)` etc (MA0015-friendly).
- SIMD path optional-but-recommended for simple/non-recursive; check `Avx2.IsSupported`.
- Use `stackalloc` for small buffers (threshold ~256) + internal state buffers when SIMD not applicable.
- Scalar fallback must handle NaN safely.
4) DOCUMENTATION STANDARDS (^8)
Mission: persuade skeptical architects via correctness + architecture evidence + benevolent curmudgeon wit; ruthless w/ math, kind to humans.
Audience: practitioners who value implementation + trade-offs.
Voice: GRINGE blend (Bryson warmth; Roach curiosity; Sedaris self-own; O'Rourke cynicism).
Argumentation: steel-man opponents, rebut w/ data; Evidence chain: Why→How→Proof→So what; Feel-Felt-Found ok.
Language: direct cadence; precise nums; avoid "we"; deliberate sentence-length variation; "code as evidence".
Humor: allowed for complexity/context; NOT in perf/security/math correctness claims.
Anti-slop:
- Forbidden words SET{Delve|leverage|pivotal|tapestry|landscape|furthermore|\"is all about\"|\"unlock the power\"|transformative|foster|seamless|ecosystem}
- Avoid em-dashes; avoid formulaic perfectly balanced pro/con tropes.
Markdown: strict CommonMark + markdownlint; watch MD022/MD031, MD030, MD032; include perf env specs (AVX2, Turbo status, sample sizes).
4.1 DOC_TMPL (required sections)
Reference: `lib/trends_IIR/jma/Jma.md` as canonical exemplar.
```markdown
# [ABBREV]: [Full Name]
> "[Memorable quote that captures the indicator's essence or challenges common assumptions]"
[Opening paragraph: What it is + key differentiator. State what makes THIS implementation unique vs common approximations. Include measurable claims (e.g., "within floating-point tolerance", "3-4% divergence during 3-sigma events").]
## Historical Context
[Origin story: Who created it, when, why. Address the knowledge gap: what was publicly known vs actual implementation details. Acknowledge prior approximations and explain how/why this implementation differs. 2-4 paragraphs.]
## Architecture & Physics
[System overview: Describe the indicator as interconnected components. Use numbered subsections for each major component.]
### 1. [Component Name]
[Describe component purpose + behavior. Include conditional logic with mathematical notation:]
$$
X_t = \begin{cases}
P_t & \text{if condition A} \\
f(X_{t-1}, P_t) & \text{otherwise}
\end{cases}
$$
[Explain WHY this design choice matters. Note alternative naming conventions if applicable.]
### 2. [Component Name]
[Continue pattern for each component. Include epsilon guards, buffer sizes, smoothing mechanisms.]
### N. [Final Component / Core Filter]
[For IIR/FIR filters, include transfer function in z-domain if applicable:]
$$
H(z) = \frac{...}{...}
$$
[Explain state-space form and coupled recursions.]
## Mathematical Foundation
[Detailed derivations for each calculation step. Use subsections for logical groupings.]
### [Calculation Name] (e.g., Dynamic Exponent Calculation)
$$
r_t = \frac{|\Delta_t|}{\hat{V}_t}
$$
$$
d_t = \text{clamp}(r_t^{P_{exp}}, 1, \text{logParam})
$$
where:
- $P_{exp} = ...$
- $\text{logParam} = ...$
[Continue for each derived quantity: coefficients, decay rates, recursions.]
### [Recursion Name] (e.g., IIR Recursion)
[State equations in sequence:]
$$
C_{0,t} = (1 - \alpha_t) \cdot P_t + \alpha_t \cdot C_{0,t-1}
$$
[Include parameter mappings (e.g., phase [-100,100] → [0.5,2.5]).]
## Performance Profile
### Operation Count (Streaming Mode, Scalar)
[Itemize computational cost per bar:]
| Operation | Count | Cost (cycles) | Subtotal |
| :--- | :---: | :---: | :---: |
| ADD/SUB | N | 1 | N |
| MUL | N | 3 | 3N |
| DIV | N | 15 | 15N |
| CMP/ABS | N | 1 | N |
| SQRT | N | 15 | 15N |
| EXP/POW | N | 50-80 | ... |
| SORT (if applicable) | 1 | ~O(n log n) | ... |
| **Total** | **sum** | — | **~X cycles** |
[Identify dominant cost contributor with percentage.]
### Batch Mode (512 values, SIMD/FMA)
[Explain SIMD applicability. For recursive indicators, acknowledge limitations:]
| Operation | Scalar Ops | SIMD Ops (AVX2) | Speedup |
| :--- | :---: | :---: | :---: |
| [Vectorizable op] | N | N/8 | 8× |
| FMA operations | N | N/3 | 3× |
**Per-bar savings with SIMD/FMA:**
| Optimization | Cycles Saved | New Total |
| :--- | :---: | :---: |
| [Optimization 1] | ~X | Y |
| **Total SIMD/FMA savings** | **~X cycles** | **~Y cycles** |
**Batch efficiency (512 bars):**
| Mode | Cycles/bar | Total (512 bars) | Overhead |
| :--- | :---: | :---: | :---: |
| Scalar streaming | X | 512X | — |
| SIMD/FMA streaming | Y | 512Y | — |
| **Improvement** | **Z%** | **N saved** | — |
[Explain why improvement is modest/significant based on algorithm characteristics.]
### Quality Metrics
| Metric | Score | Notes |
| :--- | :---: | :--- |
| **Accuracy** | N/10 | [Brief justification] |
| **Timeliness** | N/10 | [Brief justification] |
| **Overshoot** | N/10 | [Brief justification] |
| **Smoothness** | N/10 | [Brief justification] |
| **[Custom metric if applicable]** | N/10 | [Brief justification] |
## Validation
[State validation context: proprietary, open-source availability, reference sources.]
| Library | Status | Notes |
| :--- | :---: | :--- |
| **TA-Lib** | ✅/N/A | [Implementation status or match notes] |
| **Skender** | ✅/N/A | [Implementation status or match notes] |
| **Tulip** | ✅/N/A | [Implementation status or match notes] |
| **Ooples** | ✅/N/A | [Implementation status or match notes] |
| **[Other reference]** | ✅ | [Match notes] |
## Common Pitfalls
1. **[Pitfall Category]**: [Specific issue + quantified impact. Include formulas for warmup periods, memory footprints, etc.]
2. **[Pitfall Category]**: [Parameter confusion, default behaviors, migration gotchas.]
3. **[Pitfall Category]**: [Computational cost awareness with concrete numbers.]
4. **[Pitfall Category]**: [Memory footprint with per-instance and scaled estimates.]
5. **[Pitfall Category]**: [Edge case limitations.]
6. **[Pitfall Category]**: [API usage (isNew, Reset, etc.).]
## References
- [Author]. ([Year]). "[Title]." *[Source]*.
- [Author]. ([Year]). "[Title]." *[Source]*.
```
4.2 Section requirements checklist
- [ ] Title: `# ABBREV: Full Name` + memorable quote
- [ ] Intro: 1 paragraph, key differentiator, measurable claims
- [ ] Historical Context: origin, knowledge gap, prior art, this impl's difference
- [ ] Architecture & Physics: numbered subsections per component, conditional math, z-domain transfer functions
- [ ] Mathematical Foundation: all derivations with LaTeX, parameter mappings
- [ ] Performance Profile: operation count table, SIMD analysis, quality metrics (1-10 scale)
- [ ] Validation: library comparison table with status + notes
- [ ] Common Pitfalls: 5-7 numbered items with quantified impacts
- [ ] References: academic/forum sources
4.3 Doc linking reqs when adding indicator
Update: `lib/[category]/_index.md`, `lib/_index.md`, `docs/_sidebar.md`, `docs/integration.md`, `docs/indicators.md`, `docs/validation.md`.
5) TESTING PROTOCOL
REQ test files: `[Name].Tests.cs`, `[Name].Validation.Tests.cs`, `[Name].Quantower.Tests.cs`.
5.2 Unit tests (xUnit)
- Data: MUST use `GBM` helper. Never `System.Random`.
- Required coverage buckets:
A) ctor validation (throws `ArgumentException` w/ ParamName)
B) basic calc (Update returns TValue; Last/IsHot/Name accessible; known-value check)
C) state + bar correction (critical): isNew true advances; isNew false rewrites; iterative corrections restore; Reset clears state + last-valid tracking
D) warmup/convergence: IsHot flips when buffer full; WarmupPeriod period-dependent
E) robustness (critical): NaN + Infinity use last-valid; batch NaN safe
F) consistency (critical): BatchCalc == streaming == span == eventing (All 4 modes match)
G) span API tests: validates lengths w/ ParamName; matches TSeries; handles NaN; avoid stack overflow large data
H) chainability: `Pub` fires; event-based chaining works
5.3 Validation tests
- Compare vs Skender.Stock.Indicators, TA-Lib (TALib.NETCore), Tulip (Tulip.NETCore), OoplesFinance.
- For each external lib: validate Batch + Streaming + Span where supported.
- Tolerances: `ValidationHelper.SkenderTolerance`=1e-9; `TalibTolerance`=1e-9; `TulipTolerance`=1e-9; `OoplesTolerance`=1e-6.
5.4 Quantower adapter tests (req):
Constructor defaults; MinHistoryDepths; Initialize creates internal indicator; ProcessUpdate historical/new; different OHLC source types.
5.5 Checklists
- Mandatory unit tests include ctor validation, isNew behavior, iterative correction restore, Reset, IsHot warmup, NaN/Infinity handling, mode consistency, span validation.
- At least one full validation suite (Skender batch/stream/span) + Quantower minimal set.
6) QUANTOWER ADAPTER
6.1 File locations
- **Preferred:** Place `[Name].Quantower.cs` + `[Name].Quantower.Tests.cs` in `lib/[category]/[name]/` alongside the indicator.
- **Alternative:** Place in `quantower/[Category]/` subdirectory (legacy pattern).
- Both locations are auto-included in `quantower/Quantower.Tests.csproj`.
6.2 Test project inclusion (automatic)
The `quantower/Quantower.Tests.csproj` includes:
- `<Compile Include="..\lib\**\*.Quantower.cs" />` - all adapters from lib
- `<Compile Include="..\lib\**\*.Quantower.Tests.cs" />` - all adapter tests from lib
- `<Compile Include="[Category]\*.cs" />` - adapters from quantower folder per category
- `<Compile Include="**\*.Tests.cs" />` - all tests from quantower folder
6.3 Implementation requirements
- Inherit from Quantower's `Indicator` base class.
- Use `IndicatorExtensions` helpers for OHLC source mapping.
- Implement `MinHistoryDepths` for warmup period.
- Handle both historical and streaming updates in `ProcessUpdate`.
- Use mocks from `quantower/Mocks/` for unit tests.
6.4 Adding new adapter checklist
1. Create `[Name].Quantower.cs` (in lib or quantower folder)
2. Create `[Name].Quantower.Tests.cs` (same folder as adapter)
3. Verify tests compile: `dotnet build quantower/Quantower.Tests.csproj`
4. Run tests: `dotnet test quantower/Quantower.Tests.csproj --filter "[Name]"`
5. Add to category-specific csproj if adapter in quantower folder (eg `quantower/Trends.csproj`)
7) WORKFLOW & TOOLS
Tools:
- seq-think-mcp: decomposition/planning
- tavily-mcp: fresh API/lib info, .NET updates, perf patterns
- ref-tools-mcp: .NET docs, API specs, SIMD intrinsics
- wolfram-mcp: math validation
- git-mcp: codebase search + conventions
- qdrant-mcp: persist decisions/benchmarks/patterns (no secrets)
Priority: ref-tools → tavily for .NET specifics; seq-think for complex; qdrant for context.
Dev cycle (compact):
1 Recall(qdrant)→2 Analyze(profile)→3 Investigate(git+debug)→4 Research(ref-tools+tavily)→5 Plan(seq-think, STS)→6 Implement(C# 13, SIMD/Span/stackalloc, minimal comments, no regions, no XML in impl)→7 Debug(BenchmarkDotNet, codegen verify)→8 Test(edge cases)→9 Validate(correct+perf, store bench)→10 Memorize(qdrant JSON record).
Git policy:
- No auto-commit; explicit user command only.
- Pre-commit: tests pass; verify no hotpath alloc; verify SIMD codegen.
Commit msg:
`<type>: <imperative verb> <what> [scope]` + why + perf delta + refs + benchmarks.
Types SET{feat|perf|fix|refactor|test|docs}.
Comms: concise tech; bullets for lists; code blocks for examples; perf nums include baseline+optimized+%.
8) CONTEXT MGMT (qdrant)
Store: arch decisions, benchmarks, proven patterns, deprecated approaches.
Record format: `{decision, benchmark, pattern, src, date, tags}`.
Query strategy: Before/During/After work.
Event flow (commit d7dbd70):
For `ITValuePublisher` indicators: subscribe in ctor w/ `source.Pub += Handle;` (dont store source solely for subscription). Use struct-based event args (`TBarEventArgs`, `TValueEventArgs`). If MA0046 flags non-EventArgs signature, suppress locally w/ targeted pragma + perf rationale.
9) REFERENCE (pitfalls + prohibitions + done criteria)
Common pitfalls: LINQ in hot paths; `new` inside Update; ignore NaN; inconsistent 4 API modes; missing ParamName in `ArgumentException`; missing Quantower adapter/tests; forgetting `docs/validation.md`; using `System.Random` in tests.
Forbidden actions:
- DO NOT LINQ in Update/Calculate
- DO NOT `new` inside Update
- DO NOT change `Directory.Build.props` w/o explicit instruction
- DO NOT remove `[SkipLocalsInit]` / `[MethodImpl]`
- DO NOT ignore NaN/Infinity
- DO NOT skip `[Name].Quantower.cs` + `[Name].Quantower.Tests.cs`
- DO NOT skip updating `docs/validation.md`
Done checklist (condensed):
Source verified (PineScript or equiv); C# 13 optimized; O(1) where possible; SIMD where possible; FMA in hot paths where applicable; all 6 files exist; Update handles isNew + NaN; Update alloc-free; Calculate(Span) implemented + ParamName validation; unit+validation+adapter tests pass; docs complete + markdownlint; all required indices updated; CodeRabbit issues resolved; benchmarks run + stored in qdrant.