Quant Buffet API
模板
backtest.templates 中的九个 make_* 工厂函数,含精确参数名与调仓节奏。
`backtest.templates` 提供可复用的 **make_*** 工厂函数,它们返回 (on_day, ready) —— 与你自己的 make_on_day 完全相同的契约。直接导入并委托,胜过重写常见模式。
调用模式
python
from backtest.templates import make_sma_trend
ASSETS = ["SPY", "QQQ", "IWM"]
def make_on_day(prices: pd.DataFrame):
return make_sma_trend(prices, ASSETS, {"sma_days": 200})所有工厂函数签名完全一致:make_x(prices, assets, params) -> (on_day, ready)。params 是普通字典,且未知键会被静默忽略 —— 这使得参数名拼错时毫无提示,运行照常成功,只是用了默认值。
完整参数参考
| 工厂函数 | 参数(默认值) | 调仓频率 | 行为 |
|---|---|---|---|
make_sma_trend | sma_days(200) | 按月 | 等权持有价格高于自身 SMA 的标的;无标的合格时持有现金。 |
make_dual_ma | fast(50)、slow(200) | 每日 | 等权持有快线高于慢线的标的。 |
make_abs_momentum | lookback(252) | 按月 | 等权持有过去收益为正的标的。 |
make_dual_momentum | lookback(252)、cash_symbol("BIL") | 按月 | 若最强标的收益为正则满仓持有它,否则 100% 现金。 |
make_momentum_rotation | lookback(126)、top_n(1)、invert(假值) | 按月 | 按过去收益取前 N 名;负动量标的会被剔除,除非那样会导致空仓。 |
make_equal_weight | rebalance(设为 "once" 即买入持有) | 按月,或仅一次 | 等权持有当日有价格的所有标的。 |
make_mean_reversion | lookback(20)、entry_z(-1.0)、exit_z(0.0) | 每日 | 有状态:z 值跌至 entry_z 及以下时买入,回升至 exit_z 及以上时卖出。 |
make_vol_target | target_vol(0.10)、vol_lookback(63) | 按月 | 每个标的权重为 min(1, target / vol);总和超过 1 时按比例缩减。 |
make_risk_parity | vol_lookback(63) | 按月 | 波动率倒数权重,归一化为总和 1。 |
各工厂如何计算 `ready`
| 工厂函数 | ready 取值 |
|---|---|
make_sma_trend、make_dual_ma | 任一(慢线)SMA 首次非 NaN 的日期 |
make_abs_momentum、make_dual_momentum、make_momentum_rotation | 任一过去收益首次非 NaN 的日期 |
make_mean_reversion | 任一 z-score 首次非 NaN 的日期 |
make_vol_target、make_risk_parity | 任一波动率估计首次非 NaN 的日期 |
make_equal_weight | 至少一半标的有价格的首个日期 |
按名称分派
python
from backtest.templates import TEMPLATES, build_strategy
sorted(TEMPLATES)
# ['abs_momentum', 'dual_ma', 'dual_momentum', 'equal_weight',
# 'mean_reversion', 'momentum_rotation', 'risk_parity',
# 'sma_trend', 'vol_target']
ASSETS = ["SPY", "EFA", "TLT", "GLD", "BIL"]
def make_on_day(prices: pd.DataFrame):
# build_strategy(name, prices, assets, params) -> (on_day, ready)
return build_strategy("dual_momentum", prices, ASSETS,
{"lookback": 252, "cash_symbol": "BIL"})build_strategy(template, prices, assets, params) 会在 TEMPLATES 字典中查找名称,未识别时抛出 ValueError: Unknown template: …。批量目录运行器正是通过它用 JSON 配置驱动全部九个工厂。
在模板之上叠加自己的逻辑
因为工厂返回的是普通可调用对象,你可以先调用它、再拦截它的决策 —— 这是给成熟模式添加市场过滤、波动率上限或现金下限的最干净方式。
python
from backtest.templates import make_momentum_rotation
ASSETS = ["XLK", "XLF", "XLE", "XLV", "XLI", "XLP", "XLU", "XLY", "BIL"]
def make_on_day(prices: pd.DataFrame):
base_on_day, ready = make_momentum_rotation(
prices, ASSETS, {"lookback": 126, "top_n": 3}
)
# Add your own risk overlay on top of a template
spy_sma = prices["XLK"].rolling(200, min_periods=200).mean()
def on_day(engine: PortfolioEngine, dt: pd.Timestamp) -> None:
m = spy_sma.at[dt] if dt in spy_sma.index else np.nan
if pd.notna(m) and prices.at[dt, "XLK"] < m:
engine.set_target_weights(dt, {"BIL": 1.0}) # market filter: risk off
return
base_on_day(engine, dt)
return on_day, ready自定义参数
python
from backtest.templates import make_abs_momentum
ASSETS = ["SPY", "EFA", "EEM", "TLT", "GLD", "BIL"]
def make_on_day(prices: pd.DataFrame):
# make_abs_momentum 只读取 'lookback',top_n / cash_symbol 会被忽略
return make_abs_momentum(prices, ASSETS, {"lookback": 126})