documentation
Documentation skill
This skill covers writing and updating the VitePress documentation site located in the docs/ folder, with focus on indicator reference pages.
When to use this skill
- Adding a documentation page for a new indicator
- Updating an existing indicator page after API or behavioral changes
- Auditing indicator pages for structural consistency
- Adding chart panels, warnings, or special sections
Documentation site overview
The site is built with VitePress and Vue 3.
| Path | Purpose |
|---|---|
docs/indicators/ |
One .md file per indicator (the primary audience) |
docs/.vitepress/config.mts |
Site config — nav, sidebar, metadata |
docs/.vitepress/components/ |
Vue components used inside Markdown |
docs/.vitepress/public/assets/ |
Static images (webp, optimized) |
docs/.vitepress/public/data/ |
Chart JSON files (one per indicator key) |
docs/guide/getting-started.md |
Get started: install + first call |
docs/guide/index.md |
Guide overview + style comparison |
docs/guide/batch.md |
Batch (Series) style guide |
docs/guide/buffer.md |
Buffer list style guide |
docs/guide/stream.md |
Stream hub style guide |
docs/guide/customization.md |
Custom indicators guide |
docs/indicators.md |
Indicators landing/index page |
docs/utilities/ |
Utility API reference pages |
docs/performance.md |
Performance benchmarks reference |
Excluded from build: AGENTS.md, PRINCIPLES.md, and README.md are excluded via srcExclude in config.mts and must not be linked from indicator pages.
Local development
# from /docs folder
pnpm install
pnpm run docs:dev
# site opens at http://localhost:5173/
Indicator page structure
Every indicator page at docs/indicators/{Indicator}.md follows this section order exactly. Never omit sections; use judgment about which optional elements apply.
1. Frontmatter
---
title: Full Indicator Name (ABBR)
description: One-sentence description of what the indicator measures.
---
title: Human-readable name with abbreviation in parentheses when one existsdescription: Concise (≤160 characters), plain-text sentence — used for SEO and link previews
2. H1 heading block
# Full Indicator Name (ABBR)
Created by Author Name, [Indicator Name](https://en.wikipedia.org/wiki/...) is a brief description of what it measures.
[[Discuss] 💬](https://github.com/DaveSkender/Stock.Indicators/discussions/{id} "Community discussion about this indicator")
<IndicatorChartPanel indicator-key="{IndicatorKey}" />
Rules:
- Attribution ("Created by...") is required when a known author exists
- Include a Wikipedia link when one exists; otherwise link the most authoritative reference
- Always include the
[[Discuss]]link using the correct GitHub Discussions URL - Include
<IndicatorChartPanel>when a chart JSON file exists atdocs/.vitepress/public/data/{IndicatorKey}.json; omit when no chart data exists (e.g., simple primitives or secondary analysis pages) indicator-keymust match the JSON filename exactly (PascalCase, no extension)
3. Usage syntax
```csharp
// C# usage syntax
IReadOnlyList<{Indicator}Result> results =
quotes.To{Indicator}(param1, param2);
```
- Use
// C# usage syntaxas the comment; add(with Close price)or similar qualifier when relevant - Show each meaningful overload on separate
quotes.To{Indicator}(...)lines when multiple overloads exist - Wrap long signatures to the next line for readability
4. Parameters section
## Parameters
| param | type | description |
| ----- | ---- | ----------- |
| `paramName` | int | Description with constraints. Default is N. |
Omit this section entirely when the indicator has no parameters (e.g., ToAdl(), ToTr()).
Parameter description rules:
- State the variable name used in formulas (e.g., "
N" or "S") - State validation constraints ("Must be greater than 0")
- State default value when one exists ("Default is 14")
Historical quotes requirements subsection
Always present, even for parameter-free indicators:
### Historical quotes requirements
You must have at least `N` periods of `quotes` to cover the warmup periods.
`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.
- Express the minimum in terms of formula variables (e.g.,
N,2×(S+P),S+P+100) - When the indicator uses exponential smoothing or recursive formulas, include an additional sentence recommending more data (e.g., "we recommend you use at least
10×Ndata points prior to the intended usage date for better precision")
5. Response section
## Response
```csharp
IReadOnlyList<{Indicator}Result>
```
- This method returns a time series of all available indicator values for the `quotes` provided.
- It always returns the same number of elements as there are in the historical quotes.
- It does not return a single incremental indicator value.
- The first `N-1` periods will have `null` values since there's not enough data to calculate.
Adjust the null-period bullet to match the actual warmup (e.g., "The first S-1 slow periods...").
Convergence warning (conditional)
Add immediately after the bullet list when the indicator uses a smoothing/recursive algorithm that introduces convergence error:
::: warning ⚞ Convergence warning
The first `10×N` periods will have decreasing magnitude, convergence-related precision errors that can be as high as ~5% deviation in indicator values for earlier periods.
:::
Adjust the period count and percentage to match the indicator's actual convergence behavior.
Result type table
### `{Indicator}Result`
| property | type | description |
| -------- | ---- | ----------- |
| `Timestamp` | DateTime | Date from evaluated `TQuote` |
| `PropertyName` | double | What this value represents |
Timestampis always the first row- Use
doublefor computed values,decimalfor price-derived values (e.g., Ichimoku),intfor counts - Describe each property in plain language, including the formula when it aids understanding
Utilities subsection
### Utilities
- [.Condense()](/utilities/results/condense)
- [.Find(lookupDate)](/utilities/results/find-by-date)
- [.RemoveWarmupPeriods()](/utilities/results/remove-warmup-periods)
- [.RemoveWarmupPeriods(removePeriods)](/utilities/results/remove-warmup-periods)
See [Utilities and helpers](/utilities/results/) for more information.
Omit .RemoveWarmupPeriods(removePeriods) overload when the indicator does not support a custom count.
6. Chaining section
## Chaining
This indicator may be generated from any chain-enabled indicator or method.
```csharp
// example
var results = quotes
.Use(CandlePart.HL2)
.To{Indicator}(..);
```
Results can be further processed on `{PrimaryValue}` with additional chain-enabled indicators.
```csharp
// example
var results = quotes
.To{Indicator}(..)
.ToRsi(..);
```
Variations:
- 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.` - When the indicator can only output to chains (not read from them), describe that instead
- 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.")
End the section with a cross-reference to the usage guide:
See [Chaining indicators](/guide/batch#chaining-indicators) for more.
7. Streaming section
## Streaming
Use the buffer-style `List<T>` when you need incremental calculations without a hub:
```csharp
{Indicator}List {indicator}List = new(param1, param2);
foreach (IQuote quote in quotes) // simulating stream
{
{indicator}List.Add(quote);
}
// based on `ICollection<{Indicator}Result>`
IReadOnlyList<{Indicator}Result> results = {indicator}List;
```
Subscribe to a `QuoteHub` for advanced streaming scenarios:
```csharp
QuoteHub quoteHub = new();
{Indicator}Hub observer = quoteHub.To{Indicator}Hub(param1, param2);
foreach (IQuote quote in quotes) // simulating stream
{
quoteHub.Add(quote);
}
IReadOnlyList<{Indicator}Result> results = observer.Results;
```
When the hub subscribes to an upstream chain-enabled hub (not a QuoteHub), adjust the hub variable type and creation accordingly.
End the section with a cross-reference to the usage guides:
See [Buffer lists](/guide/buffer) and [Stream hubs](/guide/stream) for full usage guides.
7a. Streaming not applicable
When an indicator cannot support streaming due to an architectural constraint, include ## Streaming with this standard wording instead of examples:
## Streaming
Streaming is not supported for this indicator.
{One sentence stating the architectural reason.}
Use the Series (batch) implementation with periodic recalculation instead.
Standard reasons by category:
- Dual-series indicators (Beta, Correlation, Prs): "This indicator requires a second synchronized quote series, which cannot be expressed in the single-series streaming model."
- Lookahead/repaint indicators (ZigZag): "This indicator requires lookahead to confirm reversal points; output repaints as new data arrives, making incremental results undefined."
- Full-dataset algorithms (StdDevChannels): "This indicator recalculates the entire dataset on each new data point, making incremental streaming impractical."
Optional and conditional sections
Inline warnings
Use VitePress admonition containers for notable caveats that don't warrant a full section:
::: warning
Brief warning text here.
:::
Place these immediately after the content they qualify (e.g., after the result table).
Extended or secondary indicator pages
When an indicator has a secondary analysis variant (e.g., SmaAnalysis), create a separate page. Secondary pages:
- Omit the
<IndicatorChartPanel>(chart lives on the primary page) - Begin the H1 body with a cross-link to the primary page: "See also Simple Moving Average."
- Include the full Parameters, Response, Chaining, and Streaming sections for the variant
Multiple overloads shown together
When an indicator has multiple overloads worth showing upfront (e.g., Ichimoku), show all meaningful signatures in a single code block before the Parameters table, with brief comments distinguishing each:
// standard usage
IReadOnlyList<...> results = quotes.ToIndicator(a, b);
// usage with custom option
IReadOnlyList<...> results = quotes.ToIndicator(a, b, c);
Multi-variant indicators (substantially different parameter sets)
When two variants share the same result type but have distinct parameter sets and different streaming support (e.g., Renko fixed-brick vs. ATR-derived), merge them into one page with a shared structure:
- Show both signatures in the usage syntax block with distinguishing comments
- Use
## Parameterswith H3 subsections per variant (### Fixed brick size,### ATR-derived brick size) - Combine
## Responseinto one section (shared result type) - Combine
## Chaining— note any variant-specific restrictions - In
## Streaming, show full examples for the supported variant, then add awarningadmonition for the unsupported variant:
## Streaming
[Full buffer/hub examples for the supported variant]
::: warning
`ToVariantAtr()` does not support streaming. {One sentence reason.}
:::
Do not create a separate H2 section for the unsupported variant — keep all streaming content under one ## Streaming heading.
Image assets
Chart images for the <IndicatorChartPanel> component are rendered from JSON data files at docs/.vitepress/public/data/{IndicatorKey}.json. When adding a new indicator:
- Confirm whether a JSON data file exists for the indicator key
- If it exists, add
<IndicatorChartPanel indicator-key="{IndicatorKey}" />to the page - If it does not exist, omit the chart panel — do not add a placeholder
A second <IndicatorChartPanel> mid-page is valid when it illustrates a behaviorally distinct mode of the same indicator (e.g., StdDevChannels with null lookback renders differently than a fixed-period run; HtTrendline exposes both a trendline output and a dominant cycle period output). In that case, place the second panel immediately after the prose that introduces the distinct behavior, under its own H2 or H3 heading. Do not add a second panel merely to show the same output at different parameter values.
For static (non-chart) images referenced in prose:
- Store in
docs/.vitepress/public/assets/ - Optimize to
webpformat at 832px width:cwebp -resize 832 0 -q 100 examples.png -o examples-832.webp - Reference via absolute path from public root:
/assets/filename-832.webp
Checklist: adding a new indicator page
- Create
docs/indicators/{Indicator}.mdfollowing the page structure above - Frontmatter:
titleanddescriptionset - H1 block: attribution, reference link, Discuss link, optional chart panel
- Usage syntax: all meaningful overloads shown
- Parameters table present (or section omitted if none)
- Historical quotes requirements stated
- Response section: return type, bullet list, result table, Utilities links
- Chaining section: correct chainability direction described
- Streaming section: full examples present, or "not applicable" note with architectural reason
- Site builds without errors:
pnpm run docs:devfromdocs/
Checklist: updating an existing indicator page
- Identify sections affected by the code change
- Update parameter table if parameters added, removed, or renamed
- Update result table if result properties added, removed, or renamed
- Update usage syntax examples to match new signatures
- Update quotes requirements if warmup formula changed
- Add or remove convergence warning as appropriate
- Site builds without errors
Style conventions
- Use two spaces (not one) between sentences in prose — the existing pages do this consistently
- Backtick inline code for all: type names, property names, parameter names, method names, numeric expressions like
N-1 - Use
N,S,F,Pas single-letter formula variable shorthand — define them on first use - Tables use the three-column format with aligned pipes
- Do not add commentary, caveats, or editorializing beyond what the code behavior requires — keep descriptions factual and concise