custom-indicator
Create a custom technical indicator using vectorized NumPy on top of openalgo's Rust-core ta primitives. Generates production-grade, O(n) indicator functions with charting and benchmarking.
By marketcalls · 480 installs
npx skills add marketcalls/openalgo-indicator-skills --skill custom-indicator
Source repository · Upstream listing
Create a custom technical indicator by composing openalgo's Rust core ta primitives with vectorized NumPy.
Arguments
$0 = indicator name (e.g., zscore, squeeze, vwap bands, custom rsi, mean reversion). Required.
If no arguments, ask the user what indicator they want to build.
Instructions
1. Read the indicator expert rules, especially:
rules/custom indicators.md — NumPy + ta primitive patterns and templates
rules/performance.md — Rust core performance, O(n) guarantees, benchmarking
rules/indicator catalog.md — Check if indicator already exists in openalgo.ta
2. Check first : If the indicator already exists in openalgo.ta (100+ indicators), tell the user and show the existing API
3. Create custom indicators/{indicator name}/ directory (on demand)
4. Create {indicator name}.py with:
File Structure
5. Create chart.py for visualization:
6. Create benchmark.py for performance testing (no warmup needed — the Rust core runs at full speed from the first call):
NumPy Rules (CRITICAL)
MUST DO
Compose from ta primitives wherever possible — they run in the Rust core
np.full(n, np.nan) to initialize output arrays
Vectorize with array expressions, np.where , and boolean masks
Guard divisions: np.errstate(invalid="ignore", divide="ignore") plus a safe denominator mask
Respect NaN warm up periods from the primitives (mask on ~np.isnan(...) )
Float64 for all numeric arrays
O(n) algorithms only
MUST NOT
Never reimplement an indicator that already exists in openalgo.ta
Never write per bar Python loops over large arrays — vectorize instead
Never divide without masking zero/NaN denominators
If the indicator is genuinely path dependent (sequential state no primitive covers), check whether ta.ema / Wilder style primitives already provide the recursion first; a plain Python loop is a last resort — keep it O(n) and document the trade off
Available Building Blocks
Public ta methods that run in the Rust core:
Common Custom Indicator Patterns
Pattern Implementation
Z Score (value rolling mean) / rolling stdev
Squeeze Bollinger inside Keltner channel
VWAP Bands VWAP + N rolling stdev of (close vwap)
Momentum Score Weighted sum of RSI + MACD + ADX conditions
Mean Reversion Distance from SMA as % + threshold
Range Filter ATR based dynamic filter on close
Trend Strength ADX + directional movement composite
Example Usage
/custom indicator zscore
/custom indicator squeeze momentum
/custom indicator vwap bands
/custom indicator range filter