pybroker-indicator-creator
GitHub用于编写、注册和调试PyBroker自定义技术指标。支持NumPy/Numba向量化计算、第三方库封装、超参数优化及多时间框架处理,确保无未来函数偏差并生成可运行代码。
Trigger Scenarios
Install
npx skills add edtechre/pybroker --skill pybroker-indicator-creator -g -y
SKILL.md
Frontmatter
{
"name": "pybroker-indicator-creator",
"description": "Write, register, and debug PyBroker indicators using the bundled PyBroker wiki references generated from the local docs. Use when an agent needs to write custom indicator functions with pybroker.indicator, vectorize indicator logic with NumPy and Numba @njit kernels, wrap third-party technical analysis libraries such as TA-Lib, pandas-ta, ta, tulipy, or finta, use the built-in indicator factories and vector helpers, compute indicators standalone with IndicatorSet, parameterize indicators with hyperparams for optimization, compute indicators on multiple time intervals, feed custom data columns into indicators, cache indicator computations, or debug Numba compilation errors and parallel indicator failures."
}
PyBroker Indicator Creator
Overview
Write fast, correct PyBroker indicators by registering vectorized NumPy/Numba functions with pybroker.indicator, wiring them into strategy executions and models, and keeping every value free of lookahead bias. Covers the built-in indicator factories and vector helpers, custom Numba @njit kernels, wrapping third-party technical analysis libraries such as TA-Lib and pandas-ta, standalone computation with IndicatorSet, hyperparam-driven indicators, and multi-timeframe interval indicators.
Workflow
- Extract the indicator spec: formula or source library, input fields (OHLCV or registered custom columns), lookback lengths, fixed kwargs versus
hyperparamparameterization, interval/timeframe needs, consumers (execution functions, models, or standalone DataFrame output), and desired output file/notebook. - Ask only for missing blockers. If details are absent but noncritical, make conservative assumptions and state them in the final answer or code comments.
- Read
references/wiki-index.mdto choose the smallest relevant wiki page. For nontrivial indicator work, also readreferences/indicator-patterns.md. - Build a complete runnable indicator surface:
- start scripts with
pybroker.disable_progress_bar()andpybroker.enable_data_source_cache("<name>"), addingpybroker.enable_indicator_cache("<name>")(orpybroker.enable_caches) when indicator computation is expensive - prefer built-ins first:
highest,lowest, andreturnsat top level, then the factories in thepybroker.indicatormodule (such asatr,adx,macd,close_minus_ma), then the vectorized helpers (highv,lowv,sumv,returnv,cross,atr) - write custom functions as
fn(bar_data, **kwargs)over NumPy arrays — never pandas — that return a full-length one-dimensional array with NaN warmup bars, JIT-compiling explicit loops with a nested Numba@njitkernel - wrap third-party TA libraries (TA-Lib, pandas-ta,
ta, tulipy, finta) at the wrapper boundary only, padding outputs to full length and registering one indicator per output column - register with
pybroker.indicator(name, fn, **kwargs), then attach withStrategy.add_execution(..., indicators=[...])and read withctx.indicator("name"), or compute standalone withind(df)/IndicatorSet - pass
pybroker.hyperparamvalues as indicator kwargs for parameter search, and bind multi-timeframe indicators withadd_execution(..., indicators=ind.intervals("weekly")), read withctx.interval("weekly").indicator("name")(timeframe=is then required onbacktest/walkforward)
- start scripts with
- Validate the produced code as far as the environment allows. At minimum, run syntax checks for created Python files. When practical, compute the indicators on a small local DataFrame and check output length, NaN warmup, and the bump-last-bar lookahead test from
references/indicator-patterns.md.
Implementation Rules
- Treat PyBroker as a backtesting framework, not a source of financial advice. Make indicator assumptions explicit and avoid performance claims that are not supported by a produced backtest.
- Use completed historical bar data only. An indicator value at bar
imay depend only on inputs at indexiand earlier: no centered or forward-shifted windows, no normalization over the full series, and no negative indexing into full-length arrays inside kernels (a negative index silently wraps to the end of the series — the future). - An indicator function receives a
BarDataargument plus its registered kwargs and must return a one-dimensional array with one value per input bar. Left-pad warmup bars with NaN and never return a shortened array (pad libraries such as tulipy that drop warmup rows); a returnedpd.Seriesis converted automatically. - Prefer built-ins before custom code:
highest,lowest, andreturnsat top level, and the factories in thepybroker.indicatormodule (atr,adx,macd,stochastic,close_minus_ma,laguerre_rsi, and more). Watch the name collision: top-levelpybroker.atris the vectorized functionatr(high, low, close, lookback), while the factory ispybroker.indicator.atr(name, lookback). - Indicator names must not contain
@(reserved for interval-suffixed names such assma_20@weekly), and re-registering a name silently overwrites the previous indicator. - Never use pandas to implement indicator or execution logic. Write indicator logic with vectorized NumPy over
BarDataarrays, prefer the vectorized helpers (highv,lowv,sumv,returnv,cross,atr) when they fit, and JIT-compile explicit loops with a nested Numba@njitkernel that takes plain NumPy arrays —BarDatacannot cross the@njitboundary. Never construct apd.Seriesorpd.DataFrameand never call pandas methods such as.rolling,.ewm,.shift, or.applyinside an indicator function or a per-bar execution function; the only sanctioned pandas is the third-party wrapper boundary in the next rule. - Wrap third-party TA libraries at the wrapper boundary only: NumPy-native libraries (TA-Lib, tulipy) consume
BarDataarrays directly, while pandas-based libraries (pandas-ta,ta, finta) get a minimalpd.Series/pd.DataFramebuilt fromBarDataarrays — the only sanctioned pandas in indicator code. Register one indicator per output column for multi-output functions (thetalib.MACDtuple, pandas-ta DataFrames). None of these libraries is a PyBroker dependency: state the requiredpip installand never assume one is importable. - Compute indicators standalone with
ind(df)on a single-symbol DataFrame (returns a date-indexedpd.Series) or withIndicatorSetfor multi-symbol frames (requires asymbolcolumn; output columns aresymbol,date, then sorted indicator names).IndicatorSetnever uses the disk cache. - For parameter search, pass
pybroker.hyperparam(name, default=..., low=..., high=..., step=...)objects as indicator kwargs and runstrategy.optimize(...); override standalone computation withind(df, hyperparams={...}). Hyperparam-driven indicators are never disk-cached. - For multi-timeframe indicators, do not pass an interval to
indicator(); bind the registered indicator withind.intervals("weekly")when passing it toadd_execution(indicators=...), and read it withctx.interval("weekly").indicator("name")over completed compressed bars. Binding is exhaustive: include"base"(e.g.ind.intervals("base", "weekly")) to keep the base-timeframe variant; unbound indicators default to base. The bound interval is available throughctx.intervalwithout declaring it inintervals=(which provides bars only).backtest/walkforwardthen requiretimeframe=, and each interval must be strictly coarser than the base timeframe. - Register non-OHLCV columns with
pybroker.register_columnsbefore an indicator reads them; they appear asBarDataattributes and areNonewhen the input data lacks them, so guard for that. - In execution functions read values with
ctx.indicator("name")(arrays are truncated to completed bars; pass a symbol for another symbol's values) and guard lookbacks withctx.barsorwarmup=. - Start generated scripts with
pybroker.disable_progress_bar()so progress output does not flood agent context, andpybroker.enable_data_source_cache("<name>")so repeated runs do not refetch data; addpybroker.disable_logging()when running many backtests, such as parameter optimization. - Orders fill at
PriceType.MIDDLE— the midpoint of the low and high of the execution bar, which under the defaultbuy_delay/sell_delayof1is the bar after the indicator fired, soPriceType.CLOSEmeans the next bar's close. Override withctx.buy_fill_price/ctx.sell_fill_price, which take aPriceType(OPEN,HIGH,LOW,CLOSE,MIDDLE,AVERAGE), a number, or a(symbol, bar_data)callable, and read back asNonerather thanMIDDLEuntil set. A limit price only gates the fill: the order still fills at the fill price, never at the limit. StrategyConfig.exit_on_last_bardefaults toFalse, which leaves any position still open when the data ends. That position never becomes aTrade, sotrade_count,win_rate,total_pnland every other trade-level metric silently exclude it while its P&L sits inunrealized_pnl— an easy way to under-report an indicator's hit rate. Setexit_on_last_bar=Truewhenever trade statistics are reported.calc_bootstrapis abacktest/walkforwardparameter defaulting toFalse, not aStrategyConfigfield; passcalc_bootstrap=Trueto populateresult.bootstrapwith BCa confidence intervals for profit factor and Sharpe plus percentile bounds on max drawdown, which is what to reach for when comparing indicator variants with error bars instead of point estimates.- Report
result.metrics_dfas the human-readable summary. When structured output is needed (agent parsing, saved report files, downstream tools), useresult.to_json()/result.to_json_str(): the default payload serializes metrics, trades, orders, and bootstrap capped atmax_rows=100rows per table,symbols=filters to specific tickers, andinclude=opts intoportfolio/positions/metrics_df/signals/stops. Do not replace themetrics_dfprint outright: the default JSON payload (trades plus orders) is usually larger than the metrics table. - If a Numba
@njitfunction fails to compile or raises a cryptic error such as aTypingError, re-run once with theNUMBA_DISABLE_JIT=1environment variable to get a readable Python traceback, fix the underlying code, then remove the variable so the backtest runs compiled. Never leave JIT disabled in the final script. - Debug indicator failures serially before parallelizing: exceptions surface raw (there is no error handling on the indicator compute path), and under
parallel_indicators=Truethey arrive wrapped in joblib worker tracebacks, so reproduce with the default serial path first. - Self-test novel indicator logic for lookahead with the bump-last-bar check in
references/indicator-patterns.md: recompute after changing only the final input bar and assert every earlier output is unchanged. - If exact API names, constructor parameters, or methods matter, read
references/api-public-surface.md. - For exact type signatures —
indicator(),Indicator,IndicatorSet, the vector helpers, and the cache and parallel functions inreferences/pybroker_model.pyi;BarDatafields and the column/indicator scopes inreferences/pybroker_types.pyi— read the matchingreferences/pybroker_*.pyistub. - If the user wants a standalone file, copy and adapt
assets/indicator_template.py.
Common Deliverables
- Standalone
.pyscript that registers indicators and computes or backtests them. - Wrapper modules that register TA-Lib, pandas-ta,
ta, tulipy, or finta outputs as PyBroker indicators. - Conversion of a pandas-based indicator into vectorized NumPy/Numba.
- Debugging notes and patches for Numba compile errors, output-length mismatches, and lookahead leaks.
- Notebook-ready PyBroker indicator cells.
Resources
references/wiki-index.md: start here for topic routing across the bundled references.references/wiki-05-writing-indicators.md: custom indicators, vector helpers, TA-Lib, built-in indicators, and indicator sets.references/wiki-11-configuring-parallelization.md: worker counts, parallel indicators and model training, and the Ray backend.references/wiki-15-multiple-time-intervals.md: interval types, compressing bars, and multi-timeframe strategies.references/api-public-surface.md: generated public API signatures and first docstring sentences from local source.references/pybroker_model.pyi: generated type stubs formodel(),indicator(), vector helpers, data sources, and top-level module functions.references/pybroker_types.pyi: generated type stubs for enums,BarData,Portfolio, order/trade/position records, and evaluation result types.references/pybroker_context.pyi: generated type stubs forExecContext(including its writable order/stop attributes),IntervalContext,RotationContext,ExecResult, and the slippage models.references/pybroker_strategy.pyi: generated type stubs forStrategy,StrategyConfig,TestResult, and the optimization types.references/indicator-patterns.md: load when writing nontrivial indicator code; vectorization patterns, third-party library recipes, session hygiene, and the validation checklist.assets/indicator_template.py: copy and adapt when creating a new standalone indicator script.
Version History
- db53c67 Current 2026-08-20 08:26


