Skip to content

Commit 99a2c31

Browse files
authored
Merge branch 'v3' into perf/refresh-perf-baselines
Signed-off-by: Dave Skender <8432125+DaveSkender@users.noreply.github.com>
2 parents b12b660 + d23a567 commit 99a2c31

788 files changed

Lines changed: 16601 additions & 16338 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/documentation/SKILL.md

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ Rules:
8787
```csharp
8888
// C# usage syntax
8989
IReadOnlyList<{Indicator}Result> results =
90-
quotes.To{Indicator}(param1, param2);
90+
bars.To{Indicator}(param1, param2);
9191
```
9292
````
9393

9494
- Use `// C# usage syntax` as the comment; add `(with Close price)` or similar qualifier when relevant
95-
- Show each meaningful overload on separate `quotes.To{Indicator}(...)` lines when multiple overloads exist
95+
- Show each meaningful overload on separate `bars.To{Indicator}(...)` lines when multiple overloads exist
9696
- Wrap long signatures to the next line for readability
9797

9898
### 4. Parameters section
@@ -113,16 +113,16 @@ Parameter description rules:
113113
- State validation constraints ("Must be greater than 0")
114114
- State default value when one exists ("Default is 14")
115115

116-
#### Historical quotes requirements subsection
116+
#### Historical price bars requirements subsection
117117

118118
Always present, even for parameter-free indicators:
119119

120120
```markdown
121-
### Historical quotes requirements
121+
### Historical price bars requirements
122122

123-
You must have at least `N` periods of `quotes` to cover the warmup periods.
123+
You must have at least `N` periods of `bars` to cover the warmup periods.
124124

125-
`quotes` is a collection of generic `TQuote` historical price quotes. It should have a consistent frequency (day, hour, minute, etc). See [the Guide](/guide/getting-started#historical-quotes) for more information.
125+
`bars` is a collection of generic `TBar` historical price bars. It should have a consistent frequency (day, hour, minute, etc). See [the Guide](/guide/getting-started#historical-bars) for more information.
126126
```
127127

128128
- Express the minimum in terms of formula variables (e.g., `N`, `2×(S+P)`, `S+P+100`)
@@ -137,8 +137,8 @@ You must have at least `N` periods of `quotes` to cover the warmup periods.
137137
IReadOnlyList<{Indicator}Result>
138138
```
139139

140-
- This method returns a time series of all available indicator values for the `quotes` provided.
141-
- It always returns the same number of elements as there are in the historical quotes.
140+
- This method returns a time series of all available indicator values for the `bars` provided.
141+
- It always returns the same number of elements as there are in the historical price bars.
142142
- It does not return a single incremental indicator value.
143143
- The first `N-1` periods will have `null` values since there's not enough data to calculate.
144144
````
@@ -164,7 +164,7 @@ Adjust the period count and percentage to match the indicator's actual convergen
164164

165165
| property | type | description |
166166
| -------- | ---- | ----------- |
167-
| `Timestamp` | DateTime | Date from evaluated `TQuote` |
167+
| `Timestamp` | DateTime | Date from evaluated `TBar` |
168168
| `PropertyName` | double | What this value represents |
169169
```
170170

@@ -196,7 +196,7 @@ This indicator may be generated from any chain-enabled indicator or method.
196196

197197
```csharp
198198
// example
199-
var results = quotes
199+
var results = bars
200200
.Use(CandlePart.HL2)
201201
.To{Indicator}(..);
202202
```
@@ -205,15 +205,15 @@ Results can be further processed on `{PrimaryValue}` with additional chain-enabl
205205

206206
```csharp
207207
// example
208-
var results = quotes
208+
var results = bars
209209
.To{Indicator}(..)
210210
.ToRsi(..);
211211
```
212212
````
213213

214214
Variations:
215215

216-
- When the indicator can only read from `quotes` (not chains), replace the first block with: `This indicator must be generated from \`quotes\` and **cannot** be generated from results of another chain-enabled indicator or method.`
216+
- When the indicator can only read from `bars` (not chains), replace the first block with: `This indicator must be generated from \`bars\` and **cannot** be generated from results of another chain-enabled indicator or method.`
217217
- When the indicator can only output to chains (not read from them), describe that instead
218218
- When chaining outputs to a specific property, note which property is the chainable value (e.g., "Note: \`TenkanSen\` is the primary reusable value for chaining purposes.")
219219

@@ -233,31 +233,31 @@ Use the buffer-style `List<T>` when you need incremental calculations without a
233233
```csharp
234234
{Indicator}List {indicator}List = new(param1, param2);
235235

236-
foreach (IQuote quote in quotes) // simulating stream
236+
foreach (IBar bar in bars) // simulating stream
237237
{
238-
{indicator}List.Add(quote);
238+
{indicator}List.Add(bar);
239239
}
240240

241241
// based on `ICollection<{Indicator}Result>`
242242
IReadOnlyList<{Indicator}Result> results = {indicator}List;
243243
```
244244

245-
Subscribe to a `QuoteHub` for advanced streaming scenarios:
245+
Subscribe to a `BarHub` for advanced streaming scenarios:
246246

247247
```csharp
248-
QuoteHub quoteHub = new();
249-
{Indicator}Hub observer = quoteHub.To{Indicator}Hub(param1, param2);
248+
BarHub barHub = new();
249+
{Indicator}Hub observer = barHub.To{Indicator}Hub(param1, param2);
250250

251-
foreach (IQuote quote in quotes) // simulating stream
251+
foreach (IBar bar in bars) // simulating stream
252252
{
253-
quoteHub.Add(quote);
253+
barHub.Add(bar);
254254
}
255255

256256
IReadOnlyList<{Indicator}Result> results = observer.Results;
257257
```
258258
````
259259

260-
When the hub subscribes to an upstream chain-enabled hub (not a `QuoteHub`), adjust the hub variable type and creation accordingly.
260+
When the hub subscribes to an upstream chain-enabled hub (not a `BarHub`), adjust the hub variable type and creation accordingly.
261261

262262
End the section with a cross-reference to the usage guides:
263263

@@ -279,7 +279,7 @@ Use the Series (batch) implementation with periodic recalculation instead.
279279

280280
Standard reasons by category:
281281

282-
- **Dual-series indicators** (Beta, Correlation, Prs): "This indicator requires a second synchronized quote series, which cannot be expressed in the single-series streaming model."
282+
- **Dual-series indicators** (Beta, Correlation, Prs): "This indicator requires a second synchronized bar series, which cannot be expressed in the single-series streaming model."
283283
- **Lookahead/repaint indicators** (ZigZag): "This indicator requires lookahead to confirm reversal points; output repaints as new data arrives, making incremental results undefined."
284284
- **Full-dataset algorithms** (StdDevChannels): "This indicator recalculates the entire dataset on each new data point, making incremental streaming impractical."
285285

@@ -311,10 +311,10 @@ When an indicator has multiple overloads worth showing upfront (e.g., Ichimoku),
311311

312312
```csharp
313313
// standard usage
314-
IReadOnlyList<...> results = quotes.ToIndicator(a, b);
314+
IReadOnlyList<...> results = bars.ToIndicator(a, b);
315315

316316
// usage with custom option
317-
IReadOnlyList<...> results = quotes.ToIndicator(a, b, c);
317+
IReadOnlyList<...> results = bars.ToIndicator(a, b, c);
318318
```
319319

320320
### Multi-variant indicators (substantially different parameter sets)
@@ -362,7 +362,7 @@ For static (non-chart) images referenced in prose:
362362
- [ ] H1 block: attribution, reference link, Discuss link, optional chart panel
363363
- [ ] Usage syntax: all meaningful overloads shown
364364
- [ ] Parameters table present (or section omitted if none)
365-
- [ ] Historical quotes requirements stated
365+
- [ ] Historical price bars requirements stated
366366
- [ ] Response section: return type, bullet list, result table, Utilities links
367367
- [ ] Chaining section: correct chainability direction described
368368
- [ ] Streaming section: full examples present, or "not applicable" note with architectural reason
@@ -374,7 +374,7 @@ For static (non-chart) images referenced in prose:
374374
- [ ] Update parameter table if parameters added, removed, or renamed
375375
- [ ] Update result table if result properties added, removed, or renamed
376376
- [ ] Update usage syntax examples to match new signatures
377-
- [ ] Update quotes requirements if warmup formula changed
377+
- [ ] Update bars requirements if warmup formula changed
378378
- [ ] Add or remove convergence warning as appropriate
379379
- [ ] Site builds without errors
380380

.agents/skills/indicator-buffer/SKILL.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: indicator-buffer
3-
description: Implement BufferList incremental indicators with efficient state management. Use for IIncrementFromChain or IIncrementFromQuote implementations. Covers interface selection, constructor patterns, and BufferListTestBase testing requirements.
3+
description: Implement BufferList incremental indicators with efficient state management. Use for IIncrementFromChain or IIncrementFromBar implementations. Covers interface selection, constructor patterns, and BufferListTestBase testing requirements.
44
---
55

66
# BufferList indicator development
@@ -10,7 +10,7 @@ description: Implement BufferList incremental indicators with efficient state ma
1010
| Interface | Additional Inputs | Use Case |
1111
| --------- | ----------------- | -------- |
1212
| `IIncrementFromChain` | `IReusable`, `(DateTime, double)` | Chainable single-value indicators |
13-
| `IIncrementFromQuote` | (none — only IQuote from base) | Requires OHLCV properties |
13+
| `IIncrementFromBar` | (none — only IBar from base) | Requires OHLCV properties |
1414

1515
See [references/interface-selection.md](references/interface-selection.md) for decision tree.
1616

@@ -35,17 +35,17 @@ public class EmaList : BufferList<EmaResult>, IIncrementFromChain, IEma
3535
```
3636

3737
```csharp
38-
// IIncrementFromQuote — chaining ctor takes IReadOnlyList<IQuote>
39-
public class AdxList : BufferList<AdxResult>, IIncrementFromQuote, IAdx
38+
// IIncrementFromBar — chaining ctor takes IReadOnlyList<IBar>
39+
public class AdxList : BufferList<AdxResult>, IIncrementFromBar, IAdx
4040
{
4141
public AdxList(int lookbackPeriods)
4242
{
4343
Adx.Validate(lookbackPeriods);
4444
LookbackPeriods = lookbackPeriods;
4545
}
4646

47-
public AdxList(int lookbackPeriods, IReadOnlyList<IQuote> quotes)
48-
: this(lookbackPeriods) => Add(quotes);
47+
public AdxList(int lookbackPeriods, IReadOnlyList<IBar> bars)
48+
: this(lookbackPeriods) => Add(bars);
4949
}
5050
```
5151

@@ -71,7 +71,7 @@ public override void Clear()
7171

7272
- Inherit `BufferListTestBase`
7373
- `IIncrementFromChain` → implement `ITestChainBufferList`
74-
- `IIncrementFromQuote` → implement `ITestQuoteBufferList`
74+
- `IIncrementFromBar` → implement `ITestBarBufferList`
7575
- Series parity: `bufferResults.IsExactly(seriesResults)`
7676

7777
## Required implementation

.agents/skills/indicator-buffer/references/interface-selection.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,28 @@
55
```text
66
Can indicator work with single chainable IReusable values?
77
├─ Yes → IIncrementFromChain (SMA, EMA, RSI, MACD)
8-
└─ No → IIncrementFromQuote (Stoch, ATR, VWAP, ADX)
9-
Only supports IQuote inputs
8+
└─ No → IIncrementFromBar (Stoch, ATR, VWAP, ADX)
9+
Only supports IBar inputs
1010
```
1111

1212
## IIncrementFromChain
1313

1414
**Critical rules**:
1515

16-
- ✅ Constructor accepts `IReadOnlyList<IReusable>` (NOT `IQuote`)
16+
- ✅ Constructor accepts `IReadOnlyList<IReusable>` (NOT `IBar`)
1717
- ✅ Extension uses generic constraint with `IReusable`
1818
- ✅ Most indicators use `value.Value` directly
1919
- ✅ Some indicators use `value.Hl2OrValue()` for price (e.g., Alligator)
20-
- ❌ No `Add(IQuote)` methods in this interface
20+
- ❌ No `Add(IBar)` methods in this interface
2121

2222
**Examples**: SMA, EMA, RSI, MACD, TEMA, DEMA, Trix
2323

24-
## IIncrementFromQuote
24+
## IIncrementFromBar
2525

2626
**Critical rules**:
2727

28-
- ✅ Constructor accepts `IReadOnlyList<IQuote>` (standard pattern)
29-
- ✅ Extension uses `IQuote` constraint only
28+
- ✅ Constructor accepts `IReadOnlyList<IBar>` (standard pattern)
29+
- ✅ Extension uses `IBar` constraint only
3030
- ✅ No chainable `Add(IReusable)` methods
3131

3232
**Examples**: Stochastic, ATR, ADX, VWAP, Chandelier, Aroon
@@ -36,7 +36,7 @@ Can indicator work with single chainable IReusable values?
3636
| Buffer Interface | Test Interface |
3737
| ---------------- | -------------- |
3838
| `IIncrementFromChain` | `ITestChainBufferList` |
39-
| `IIncrementFromQuote` | `ITestQuoteBufferList` |
39+
| `IIncrementFromBar` | `ITestBarBufferList` |
4040

4141
Additional test interface for custom caches:
4242

.agents/skills/indicator-catalog/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public static partial class Ema
9292
| `PriceChannel` | Bollinger Bands, Keltner, Donchian, VWAP |
9393
| `PriceCharacteristic` | ATR, Beta, Standard Deviation, True Range |
9494
| `PricePattern` | Fractal, Pivot Points |
95-
| `PriceTransform` | Quote Part, ZigZag |
95+
| `PriceTransform` | Bar Part, ZigZag |
9696
| `PriceTrend` | ADX, Aroon, Alligator, AtrStop, SuperTrend, Vortex |
9797
| `StopAndReverse` | Chandelier, Parabolic SAR, Volatility Stop |
9898
| `VolumeBased` | OBV, Chaikin Money Flow, Chaikin Oscillator |

.agents/skills/indicator-series/references/decision-tree.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public record MacdResult
4646

4747
| Input Type | Use Case | Examples |
4848
| ---------- | -------- | -------- |
49-
| `IQuote` | Requires OHLCV data | ATR, ADX, Stochastic, Chandelier |
49+
| `IBar` | Requires OHLCV data | ATR, ADX, Stochastic, Chandelier |
5050
| `IReusable` | Chains from another indicator | EMA-of-EMA, SMA-of-RSI |
5151

52-
Most indicators accept `IQuote`. Use `IReusable` only for indicators explicitly designed to chain.
52+
Most indicators accept `IBar`. Use `IReusable` only for indicators explicitly designed to chain.

.agents/skills/indicator-stream/SKILL.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: indicator-stream
3-
description: Implement StreamHub real-time indicators with O(1) performance. Use for ChainHub or QuoteProvider implementations. Covers provider selection, RollbackState patterns, performance anti-patterns, and comprehensive testing with StreamHubTestBase.
3+
description: Implement StreamHub real-time indicators with O(1) performance. Use for ChainHub or BarProvider implementations. Covers provider selection, RollbackState patterns, performance anti-patterns, and comprehensive testing with StreamHubTestBase.
44
---
55

66
# StreamHub indicator development
@@ -10,18 +10,18 @@ description: Implement StreamHub real-time indicators with O(1) performance. Use
1010
| Provider Base | Input | Output | Use Case |
1111
| ------------- | ----- | ------ | -------- |
1212
| `ChainHub<IReusable, TResult>` | Single value | IReusable | Chainable indicators |
13-
| `ChainHub<IQuote, TResult>` | OHLCV | IReusable | Quote-driven, chainable output |
14-
| `QuoteProvider<IQuote, TResult>` | OHLCV | IQuote | Quote-to-quote transformation |
15-
| `QuoteProvider<TIn, TOut>` (self-rooted) | None | TOut | Source hubs with no upstream — bootstrap with an inert sentinel provider |
13+
| `ChainHub<IBar, TResult>` | OHLCV | IReusable | Bar-driven, chainable output |
14+
| `BarProvider<IBar, TResult>` | OHLCV | IBar | Bar-to-bar transformation |
15+
| `BarProvider<TIn, TOut>` (self-rooted) | None | TOut | Source hubs with no upstream — bootstrap with an inert sentinel provider |
1616
| `StreamHub<TProviderResult, TResult>` | Any hub result | Any result | Compound hubs (internal hub dependency) |
1717

1818
Self-rooted source hubs (those that originate a stream rather than transform another hub's output) take an inert sentinel provider so the base-class constructor has something to subscribe to; the sentinel rejects subscriptions and carries no cache.
1919

2020
## Aggregator / quantizer hubs
2121

22-
Hubs that bucket small bars (or raw ticks) into larger time periods derive from `QuoteProvider<TIn, IQuote>`. Conventions:
22+
Hubs that bucket small bars (or raw ticks) into larger time periods derive from `BarProvider<TIn, IBar>`. Conventions:
2323

24-
- Constructors accept a `PeriodSize` enum **and** a custom `TimeSpan` overload; the enum overload throws for month-or-longer periods (use `TimeSpan` instead) since calendar arithmetic is not a fixed `TimeSpan`.
24+
- Constructors accept a `BarInterval` enum **and** a custom `TimeSpan` overload; the enum overload throws for month-or-longer periods (use `TimeSpan` instead) since calendar arithmetic is not a fixed `TimeSpan`.
2525
- Take an optional `fillGaps` flag. Default `false` (silent buckets are simply omitted from the output stream); `true` synthesizes zero-volume bars whose `Open`/`High`/`Low`/`Close` all carry forward the prior bar's close through the silent period.
2626
- Round the input timestamp down to the current bucket on every `OnAdd`, then either update the current bar in place or emit a new bucket.
2727
- Override `Rebuild(DateTime)` to align the requested rebuild timestamp to the bucket boundary before delegating to base — an upstream rebuild whose timestamp is mid-bucket must clear the in-cache partial bar, not duplicate it.
@@ -40,7 +40,7 @@ Use the project's performance-analysis document as the source of truth for measu
4040
| Review | 3x – framework floor | ⚠️ investigate |
4141
| Critical | indicator-specific algorithmic issue (e.g. O(n²)) | 🔴 fix |
4242

43-
The "framework floor" is the per-tick overhead inherent to the observer pattern, cache management, and read-only collection wrappers. Simple stateless indicators routinely measure 6–11x against Series while still achieving tens of thousands of quotes per second; this is acceptable. Optimization effort should target indicator-specific algorithmic issues, not the framework floor.
43+
The "framework floor" is the per-tick overhead inherent to the observer pattern, cache management, and read-only collection wrappers. Simple stateless indicators routinely measure 6–11x against Series while still achieving tens of thousands of bars per second; this is acceptable. Optimization effort should target indicator-specific algorithmic issues, not the framework floor.
4444

4545
Forbid O(n²) recalculation — rebuild entire history on each tick:
4646

@@ -91,14 +91,14 @@ Replay up to `restoreIndex` (inclusive). The item at the rollback timestamp is r
9191
- Inherit `StreamHubTestBase`
9292
- Abstract method (compile error if missing): `ToStringOverride_ReturnsExpectedName()`
9393
- Implement ONE observer interface:
94-
- `ITestChainObserver` (most indicators — chain input): inherits `ITestQuoteObserver`, adds `ChainObserver_ChainedProvider_MatchesSeriesExactly()`
95-
- `ITestQuoteObserver` (direct quote input only): `QuoteObserver_WithWarmupLateArrivalAndRemoval_MatchesSeriesExactly()`, `WithCachePruning_MatchesSeriesExactly()`
94+
- `ITestChainObserver` (most indicators — chain input): inherits `ITestBarObserver`, adds `ChainObserver_ChainedProvider_MatchesSeriesExactly()`
95+
- `ITestBarObserver` (direct bar input only): `BarObserver_WithWarmupLateArrivalAndRemoval_MatchesSeriesExactly()`, `WithCachePruning_MatchesSeriesExactly()`
9696
- If hub acts as chain provider, also implement `ITestChainProvider`: `ChainProvider_MatchesSeriesExactly()`
9797

9898
## Required implementation
9999

100100
- [ ] Source code: `src/**/{IndicatorName}.StreamHub.cs` file exists
101-
- [ ] Uses appropriate provider base (ChainHub or QuoteProvider)
101+
- [ ] Uses appropriate provider base (ChainHub or BarProvider)
102102
- [ ] Validates parameters in constructor; calls Reinitialize() as needed
103103
- [ ] Implements O(1) state updates; avoids O(n²) recalculation
104104
- [ ] Overrides RollbackState() when maintaining stateful fields

.agents/skills/indicator-stream/references/compound-hubs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ protected override void RollbackState(DateTime timestamp)
169169
```csharp
170170
// WRONG - Creates new hub on every tick
171171
protected override (GatorResult result, int index)
172-
ToIndicator(IQuote item, int? indexHint)
172+
ToIndicator(IBar item, int? indexHint)
173173
{
174174
var alligator = item.ToAlligatorHub(); // FORBIDDEN - O(n²) disaster
175175
var alligatorResult = alligator.GetNext(item);

.agents/skills/indicator-stream/references/performance-patterns.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ for (int p = i - LookbackPeriods; p < i; p++)
7272
private readonly RollingWindowMax<decimal> _highWindow;
7373
private readonly RollingWindowMin<decimal> _lowWindow;
7474

75-
internal DonchianHub(IQuoteProvider<IQuote> provider, int lookbackPeriods)
75+
internal DonchianHub(IBarProvider<IBar> provider, int lookbackPeriods)
7676
: base(provider)
7777
{
7878
_highWindow = new RollingWindowMax<decimal>(lookbackPeriods);
7979
_lowWindow = new RollingWindowMin<decimal>(lookbackPeriods);
8080
Reinitialize();
8181
}
8282

83-
protected override (DonchianResult result, int index) ToIndicator(IQuote item, int? indexHint)
83+
protected override (DonchianResult result, int index) ToIndicator(IBar item, int? indexHint)
8484
{
8585
// O(1) amortized add operation
8686
_highWindow.Add(item.High);
@@ -167,7 +167,7 @@ Add benchmark to `tools/performance/Perf.Stream.cs`:
167167

168168
```csharp
169169
[Benchmark]
170-
public object MyIndicatorHub() => quoteHub.ToMyIndicatorHub(14).Results;
170+
public object MyIndicatorHub() => barHub.ToMyIndicatorHub(14).Results;
171171
```
172172

173173
Run benchmarks:

0 commit comments

Comments
 (0)