主动领口策略

登录后收藏

Onsite backtest IDE

Quant Buffet 原生回测 IDE

Edit and run Quant Buffet Python for 主动领口策略 in the browser. Results update live with equity, drawdown, and metrics charts. Allowed: backtest.data, backtest.engine, backtest.metrics, numpy, pandas. Define ASSETS and make_on_day(prices). Shortcut: Ctrl+Enter. API docs →

Ready — edit code, then Run backtest.
IDE · 40 lines
Quant Buffet syntax cheat sheet (copy / insert)

Paste these fragments into the editor. The sandbox rejects QuantConnect, os, and network libraries.

Required imports
Only these libraries are allowed in the sandbox.
from __future__ import annotations

import numpy as np
import pandas as pd

from backtest.data import load_daily_prices
from backtest.engine import EngineConfig, PortfolioEngine
from backtest.metrics import compute_metrics
ASSETS list (whitelisted ETFs)
Module-level list. Tickers must be in the Quant Buffet whitelist.
ASSETS = ["SPY", "QQQ", "TLT", "GLD", "BIL"]
make_on_day contract
Must return (on_day, ready). on_day calls engine.set_target_weights.
def make_on_day(prices: pd.DataFrame):
    cols = [c for c in ASSETS if c in prices.columns]
    sma = prices[cols].rolling(200, min_periods=200).mean()
    state = {"last": None}

    def on_day(engine: PortfolioEngine, dt: pd.Timestamp) -> None:
        if sma.loc[dt].isna().all():
            return
        key = (dt.year, dt.month)
        if state["last"] == key:
            return
        state["last"] = key
        long = [
            s for s in cols
            if pd.notna(prices.at[dt, s]) and pd.notna(sma.at[dt, s])
            and prices.at[dt, s] > sma.at[dt, s]
        ]
        weights = {} if not long else {s: 1.0 / len(long) for s in long}
        engine.set_target_weights(dt, weights)

    ready = sma.dropna(how="all").index.min() if sma.notna().any().any() else None
    return on_day, ready
Set target weights
Weights should sum to about 1.0. Empty dict = 100% cash.
engine.set_target_weights(dt, {"SPY": 0.60, "BIL": 0.40})

Live backtest performance

CAGR
8.09%
Sharpe
0.68
Max DD
-23.02%
Vol
12.56%
Sortino
1.03
Beta
0.38
Up days
53%

Run the backtest to populate charts.

Export to your platform

Transform Quant Buffet lab code (ASSETS + make_on_day / PortfolioEngine) into native classes for a third-party IDE — then copy and paste.

Run in: QuantConnect Cloud or LEAN CLI · QCAlgorithm with Equity securities and monthly rebalance.

Detected pattern: SMA trendAssets: SPY, TLT, GLD, BIL
# Generated from Quant Buffet → QuantConnect LEAN
# Strategy: 主动领口策略
# Detected pattern: SMA trend
# Source uses Quant Buffet lab APIs (ASSETS + make_on_day / PortfolioEngine).
# Review fees, data, and risk before live trading — educational export only.

from AlgorithmImports import *


class QuantBuffetExport(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2010, 1, 1)
        self.SetCash(100000)
        tickers = ["SPY", "TLT", "GLD", "BIL"]
        self.symbols = []
        for t in tickers:
            if "-" in t:  # crypto proxy e.g. BTC-USD
                self.symbols.append(self.AddCrypto(t.replace("-USD", ""), Resolution.Daily).Symbol)
            else:
                self.symbols.append(self.AddEquity(t, Resolution.Daily).Symbol)
        self.Schedule.On(
            self.DateRules.MonthStart(self.symbols[0]),
            self.TimeRules.AfterMarketOpen(self.symbols[0], 30),
            self.Rebalance,
        )
        # Logic: Long assets where close > SMA(200); equal-weight; monthly.

    def Rebalance(self):
        longs = []
        for symbol in self.symbols:
            hist = self.History(symbol, 200 + 5, Resolution.Daily)
            if hist.empty: continue
            close = hist["close"].unstack(level=0).iloc[:, 0] if hasattr(hist["close"], "unstack") else hist["close"]
            if len(close) < 200: continue
            if float(close.iloc[-1]) > float(close.iloc[-200:].mean()):
                longs.append(symbol)
        weight = 1.0 / len(longs) if longs else 0.0
        for symbol in self.symbols:
            self.SetHoldings(symbol, weight if symbol in longs else 0.0)

导出代码使用目标平台的原生类与库。请在第三方 IDE 中安装依赖后运行;实盘前请自行验证。

学术论文

An Update of 'Loosening Your Collar: Alternative Implementations of QQQ Collars': Credit Crisis and Out-of-Sample Performance

作者“放松你的领口:QQQ领口的替代实现”:信用危机与样本外表现的更新 [点击查看论文]

机构
  • Providence College
  • University of Massachusetts Amherst
  • ?University of Massachusetts Amherst - Isenberg School of Management

原文论文截图

Screenshot from the original paper
Screenshot from the original paper

策略概要

该策略涉及100%纳斯达克指数头寸,以QQQ ETF为例。每个月,投资者卖出1个月期看涨期权,并利用所得权利金购买6个月期看跌期权。看涨期权、看跌期权与QQQ股票的比例,以及期权的实值程度,由三大信号决定:动量、波动率和宏观经济趋势。

动量:纳斯达克-100指数的移动平均交叉(1/50,5/150,1/200 SMA组合)用于识别趋势,买入信号时扩大保护区间,卖出信号时收紧保护区间。

波动性:VIX的日度收盘水平与其移动平均(50、150、250)比较,根据波动性调整看涨期权的写入强度(如果VIX > MA的标准差1倍,则每个头寸写入0.75份看涨期权,如果VIX低于MA,则写入1.25份)。

宏观经济趋势:初请失业金人数和NBER商业周期数据帮助调整期权的实值程度。在经济扩张期间,失业金人数上升时发出看涨信号(ATM看跌期权,OTM看涨期权),而在经济收缩期间,失业金人数上升时会反向调整行权价。

这些信号结合起来将期权的实值程度设置在ATM和5% OTM之间,并根据市场状况进行月度调整。

II. 策略合理性

跨式策略通过交换上行参与和下行保护来调整风险回报结构——该策略将标的资产的回报分布转化为具有更有利特征的新分布。通过使用系统性因素(如动量、波动性和宏观经济形势),该策略提升了风险/回报特征。

回测表现

年化收益8.09%
波动率12.56%
贝塔0.38
夏普比率0.68
索提诺比率1.03
最大回撤-23.02%
胜率53%