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_trendsma_days(200)按月等权持有价格高于自身 SMA 的标的;无标的合格时持有现金。
make_dual_mafast(50)、slow(200)每日等权持有快线高于慢线的标的。
make_abs_momentumlookback(252)按月等权持有过去收益为正的标的。
make_dual_momentumlookback(252)、cash_symbol"BIL"按月若最强标的收益为正则满仓持有它,否则 100% 现金。
make_momentum_rotationlookback(126)、top_n(1)、invert(假值)按月按过去收益取前 N 名;负动量标的会被剔除,除非那样会导致空仓。
make_equal_weightrebalance(设为 "once" 即买入持有)按月,或仅一次等权持有当日有价格的所有标的。
make_mean_reversionlookback(20)、entry_z(-1.0)、exit_z(0.0)每日有状态:z 值跌至 entry_z 及以下时买入,回升至 exit_z 及以上时卖出。
make_vol_targettarget_vol(0.10)、vol_lookback(63)按月每个标的权重为 min(1, target / vol);总和超过 1 时按比例缩减。
make_risk_parityvol_lookback(63)按月波动率倒数权重,归一化为总和 1。

各工厂如何计算 `ready`

工厂函数ready 取值
make_sma_trendmake_dual_ma任一(慢线)SMA 首次非 NaN 的日期
make_abs_momentummake_dual_momentummake_momentum_rotation任一过去收益首次非 NaN 的日期
make_mean_reversion任一 z-score 首次非 NaN 的日期
make_vol_targetmake_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})