pybroker-model-trainer
GitHub用于在PyBroker回测框架中注册、训练和调试机器学习模型。支持多种算法库,构建特征与预测函数,执行滚动窗口分析并确保无未来数据泄露。
Trigger Scenarios
Install
npx skills add edtechre/pybroker --skill pybroker-model-trainer -g -y
SKILL.md
Frontmatter
{
"name": "pybroker-model-trainer",
"description": "Register, train, wire, and debug machine learning models for PyBroker backtests using the bundled PyBroker wiki references generated from the local docs. Use when an agent needs to register a model with pybroker.model, write train_fn\/predict_fn code for scikit-learn, XGBoost, LightGBM, CatBoost, PyTorch, Keras, statsmodels (ARIMA\/SARIMAX), or arch models, build ensembles or regime models, run walkforward analysis, build time-series or lagged-feature models, train pooled multi-symbol models, load pretrained models, cache data and trained models, or prevent lookahead leakage in model-driven backtests."
}
PyBroker Model Trainer
Overview
Wire machine learning models into PyBroker backtests by registering training and prediction functions with pybroker.model, feeding them indicator features, and evaluating them with walkforward analysis while keeping the train/test flow free of lookahead leakage. Covers per-symbol, pooled multi-symbol, per-bar time-series, lagged-feature, and pretrained models across common libraries such as scikit-learn, XGBoost, and arch.
Workflow
- Extract the modeling spec: library, prediction target and horizon, features (indicators, lagged columns, custom columns), per-symbol vs pooled training, vectorized vs per-bar prediction, walkforward windows and lookahead, caching, and whether the model is trainable or pretrained.
- 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 model work, also readreferences/model-training-patterns.md. - Build a complete runnable model surface:
- define feature indicators with
pybroker.indicatoror built-ins, and register any non-OHLCV data columns withpybroker.register_columns - write a
train_fnthat builds the target from train data only and returns the model, or(model, input_cols)to pin prediction columns - register the model with
pybroker.model(name, train_fn, ...), choosingindicators,lags/lag_cols,per_bar,pooled,pretrained,input_data_fn, andpredict_fnas needed - consume predictions in an execution function via
ctx.preds(name)and pass the model source toStrategy.add_execution(models=...) - run
strategy.walkforward(windows, train_size, lookahead)for evaluation, orbacktest(train_size=...)for a single train/test pass
- define feature indicators with
- Validate the produced code as far as the environment allows. At minimum, run syntax checks for created Python files. Run a small local-data walkforward when the repo and data make that practical.
Implementation Rules
- Treat PyBroker as a backtesting framework, not a source of financial advice. Make modeling assumptions explicit and avoid performance claims that are not supported by the produced backtest, including model fit metrics.
- Use completed historical bar data only. Do not use future prices, future indicator values, or shuffled time series outside the supported train-split shuffle. An indicator value at bar
imay depend only on inputs at indexiand earlier: no backward shifts such asshift(-1)outside the sanctionedtrain_fntarget, and no negative indexing into full-length arrays inside indicator functions (a negative index silently wraps to the end of the series — the future). - Set
lookaheadto the number of bars ahead of the prediction target (default1for next-bar targets). Walkforward holds outlookaheadbars between each train and test split, so an understated value leaks train-adjacent bars into testing. - When registering with
lags, the current bar's value is the first feature of each lag block, so the training target must be the next bar's value (for examplefit(lag_train[:-1], target[1:])). The trainingfnmust acceptlag_trainandlag_testkeyword arguments. - Keep feature data out-of-band: never widen or mutate the input DataFrame. Work on a
.copy()insidetrain_fnwhen adding a target column. - An
input_data_fnmust return exactly one row per bar. A vectorizedpredict_fnmust return one prediction per input row; for classifiers, slice a singlepredict_probacolumn. Withper_bar=True,predict_fnis required, receives rows up to and including the current bar, must return a scalar, and cannot be combined withpooled=True. - A pooled
train_fnreceives a sortedsymbolstuple and combined frames with asymbolcolumn. Build targets with per-symbol operations such asgroupby("symbol")[col].shift(-1)so labels never cross a symbol boundary, and return(model, input_cols)to keepsymbolout of model input. - To train a model on a longer time interval, bind it with
model_source.intervals("weekly")when passing it toadd_execution(models=...); binding is exhaustive, so the base-timeframe model is trained only when"base"is included (e.g.model_source.intervals("base", "weekly")), and the bound interval is available throughctx.intervalwithout declaring it inintervals=(which provides bars only). For interval-bound models,lookaheadis measured in that interval's compressed bars, and predictions are read withctx.interval("...").preds(name).timeframe=is then required onbacktest/walkforward. strategy.optimizesupports pretrained models only. Tune trainable models insidetrain_fnwith a search over the train window, or compare registrations across walkforward runs;pybroker.hyperparamis for strategy-level parameters.- Fit scalers, encoders, and any early-stopping validation splits on train data only.
- Never use pandas to implement indicator or execution logic: write indicators as vectorized NumPy over
BarDataarrays (Numba@njitfor explicit loops) and readctx.*NumPy arrays in execution functions — nopd.Series/pd.DataFrameconstruction and no.rolling/.ewm/.shift/.applyin either. Pandas belongs only at thetrain_fn/input_data_fnboundary where PyBroker hands you DataFrames; building the target there withshift(-1)on a.copy()stays sanctioned. - Enable caching while iterating:
pybroker.enable_data_source_cache(name)to skip refetching data, orpybroker.enable_caches(name)to also cache indicators and trained models. - Call
pybroker.disable_progress_bar()in agent-run scripts; progress bar output floods AI token context. - 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 prediction, 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 out oftrade_count,win_rate,total_pnland every other trade-level metric, with its P&L stranded inunrealized_pnl. Setexit_on_last_bar=Truewhenever trade statistics are reported; inwalkforwardthe liquidation fires only on each symbol's true final bar, never at window boundaries.calc_bootstrapis awalkforward/backtestparameter defaulting toFalse, not aStrategyConfigfield, and it is the natural companion to walkforward analysis: it puts confidence intervals around a model's out-of-sample edge instead of a single point estimate. Passcalc_bootstrap=Trueto populateresult.bootstrapwithconf_intervals(BCa — bias corrected and accelerated — intervals for profit factor and Sharpe; 6x2, MultiIndexed onnamethenconf, columnslower/upper) anddrawdown_conf(percentile bounds on max drawdown; 4x2, indexed onconf, columnsamount/percent). A profit factor interval whoselowersits below1means the edge is not distinguishable from noise. It leavesmetrics_dfunchanged, staysNoneundertrain_only=True, costs roughlybars x StrategyConfig.bootstrap_samples(default10_000) once for the whole run rather than per window, and needsStrategyConfig.bars_per_yearor the Sharpe intervals are per-bar rather than annualized.- 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(signalscarries model predictions whenStrategyConfig(return_signals=True)). Do not replace themetrics_dfprint outright: the default JSON payload (trades plus orders) is usually larger than the metrics table. - On a Numba compilation or typing error in an
@njitindicator, re-run once with the environment variableNUMBA_DISABLE_JIT=1to get a readable Python traceback, fix the error, then re-run with JIT enabled. Never leave JIT disabled in the final script. - Self-test novel indicator logic for lookahead with the bump-last-bar check: recompute after changing only the final input bar and assert every earlier output is unchanged.
- Guard lookbacks with
ctx.barsorwarmup, and set at most one order side per symbol per bar. - Use
ctx.calc_target_shares(target_size)for allocation-based sizing. Use fixedctx.buy_sharesorctx.sell_sharesonly when the user asks for fixed share sizing. - Check
ctx.long_pos()orctx.short_pos()before entering or exiting positions. Usectx.sell_all_shares()andctx.cover_all_shares()for full exits. - Set entry-time stops on the same bar as the entry order:
hold_bars,stop_loss_pct,stop_profit_pct, orstop_trailing_pct. - Rank by model score with
ctx.long_score/ctx.short_scoreand cap positions withstrategy.set_max_long_positions(n)/set_max_short_positions(n); theStrategyConfigfields of the same names are deprecated. For score-driven rotation,strategy.enable_rotation(worst_rank_held=...)makes scores drive all trading and ignores order fields set in execution functions. - Use
strategy.set_before_execorstrategy.set_after_execfor cross-symbol portfolio logic instead of hiding global state inside a per-symbol execution function. - Optional packages are not PyBroker dependencies: name the required
pip installfor every model or data-source library the script imports (for examplepip install yfinance scikit-learnfor the template) and never assume one is importable. When the network or a data-source package is unavailable, validate with a tiny local DataFrame passed toStrategyinstead. - If exact API names, constructor parameters, or methods matter, read
references/api-public-surface.md. - For exact type signatures —
pybroker.model()andtrain_fn/predict_fnparameter types inreferences/pybroker_model.pyi,ExecContextprediction access and its writable order/stop attributes inreferences/pybroker_context.pyi— read the matchingreferences/pybroker_*.pyistub. - If the user wants a standalone file, copy and adapt
assets/model_training_template.py.
Common Deliverables
- Standalone
.pywalkforward backtest script with a trained model. train_fn/predict_fnpairs for a user's chosen library.- Conversion of an existing single-symbol model to pooled multi-symbol training.
- Debugging notes and patches for leaking targets, misaligned predictions, or invalid
pybroker.modelregistrations. - Notebook-ready PyBroker model training cells.
Resources
references/wiki-index.md: start here for topic routing across the bundled references.references/wiki-06-training-a-model.md: model registration, train/backtest flow, model caching, and walkforward analysis.references/wiki-16-time-series-models.md: GARCH withper_bar=Trueand Random Forest on lagged returns withlags/lag_cols.references/wiki-17-multi-symbol-models.md: pooled multi-symbol training withpooled=True.references/model-training-patterns.md: load when writing nontrivial train/predict code; library recipes, session hygiene, and the leakage checklist.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_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/pybroker_types.pyi: generated type stubs for enums,BarData,Portfolio, order/trade/position records, and evaluation result types.assets/model_training_template.py: copy and adapt when creating a new standalone model training script.
Version History
- db53c67 Current 2026-08-20 08:26


