当前位置:首页>python>Python量化回测标普500十年数据:“无脑定投”为何完胜“逢低抄底”?

Python量化回测标普500十年数据:“无脑定投”为何完胜“逢低抄底”?

  • 2026-09-04 22:56:00
Python量化回测标普500十年数据:“无脑定投”为何完胜“逢低抄底”?

为了进行量化对比,我们设定以下两个常见策略的规则:

  1. 无脑定投(DCA 策略):每个月固定存入 $1000,并在当月第一个交易日全仓买入标普500。

  2. 低估值买入(逢低买入策略):每个月同样攒下 $1000 放入现金池,但只有当标普500处于“低估”状态时(此处定义为跌破200日均线(SMA200)),才将手头的现金池全部买入。

数据来源: macrotrends网站提供的 标普500 - 日线数据CSV文件 

回测数据对比 (2016 - 2026)

该策略没有计算- 股息再投入 

统计项无脑定投策略 低估值买入策略 
总投入本金$121,000$121,000
期末总资产$246,084$234,381
累计收益率103.38%93.70%
资金年化收益率 13.55%12.65%
最大回撤 -33.92%-32.70%
夏普比率 0.800.66
ps: 给不清楚量化指标的读者解释下 

1. 资金年化收益率(IRR)—— 你的“平均赚钱速度”简单来说,它衡量的是你资金的综合赚钱效率。假设你有 100 万进行全部投入,年化收益率为 13.55%,这就代表在长期的投资复利下,你平均每年大约可以赚到 13.55 万元。

2. 最大回撤(Max Drawdown)—— 极端情况下的“最差体验”想获得高收益,必然要承受波动的代价。最大回撤代表了你在“最倒霉”的顶点买入后,一路跌到最低谷时经历的最大账面亏损幅度。 比如最大回撤为 33.92% 时,就代表如果你投入了 100 万,在遇到像疫情或股灾这种极端暴跌情况时,你的账面曾一度缩水(浮亏)了 33.92 万元。这个指标直接反映了该策略需要多大的“强心脏”才能抗住不卖。

3. 夏普比率(Sharpe Ratio)—— 投资的“性价比”它衡量的是**你每多承担 1 份风险(波动),能换来多少份收益**。

  • 在投资里,夏普比率越高越好。

  • 如果一个策略能让你赚 10 万,但每天上蹿下跳让你心惊胆战(风险极大),那么它的夏普比率就会很低;反之,如果稳稳当当地赚 10 万,夏普比率就会很高。

  • 以刚才定投策略 0.80 的夏普比率为例,意味着你每承受 1% 的账户波动风险,就能获得 0.80% 的回报。作为参考,宽基指数的夏普比率长期保持在 0.5 ~ 1.0 之间就已经是非常优秀的表现了。


💡 核心结论分析
在长达10年的美股大牛市中,定投策略的最终收益往往跑赢了低估值买入策略。因为标普500大部分时间都在上涨,导致“低估值买入”策略在长达几个月甚至几年的时间里都在空仓等待(持有现金),这产生了严重的“现金拖累(Cash Drag)”,错失了指数复利上涨的红利。

💻 Backtrader 回测完整代码

import pandas as pdimport backtrader as btimport matplotlib.pyplot as plt# ==========================================# 1. 定义无脑定投策略 (DCA)# ==========================================class DCAStrategy(bt.Strategy):    def __init__(self):        self.current_month = None    def next(self):        # 获取当前交易日的月份        date = self.data.datetime.date(0)        # 跨月时,发工资存入 1000 美金        if self.current_month != date.month:            self.current_month = date.month            self.broker.add_cash(1000)            # 每月固定买入,市价全仓            cash = self.broker.get_cash()            size = int(cash / self.data.close[0])            if size > 0:                self.buy(size=size)# ==========================================# 2. 定义低估值买入策略 (Value Dip Buying)# ==========================================class ValueStrategy(bt.Strategy):    params = (('sma_period', 200),)    def __init__(self):        # 采用200日均线作为价值中枢判断        self.sma = bt.indicators.SimpleMovingAverage(self.data, period=self.p.sma_period)        self.current_month = None    def next(self):        date = self.data.datetime.date(0)        # 同样跨月存入 1000 美金到现金池        if self.current_month != date.month:            self.current_month = date.month            self.broker.add_cash(1000)        # 低估值判断条件:当收盘价跌破200日均线时,认为处于低估区间        if self.data.close[0] < self.sma[0]:            cash = self.broker.get_cash()            # 如果现金池够买哪怕1股,就全仓抄底买入            if cash > self.data.close[0]:                size = int(cash / self.data.close[0])                self.buy(size=size)# ==========================================# 回测引擎启动函数# ==========================================def run_backtest(strategy_class, data, name):    cerebro = bt.Cerebro()    cerebro.addstrategy(strategy_class)    # 将初始本金设为 0 (通过按月发工资注入资金)    cerebro.broker.setcash(0)    cerebro.adddata(data)    print(f"[{name}] 开始回测...")    cerebro.run()    final_value = cerebro.broker.getvalue()    print(f"[{name}] 期末总资产: ${final_value:.2f}\n")    return cerebroif __name__ == '__main__':    # 1. 加载和预处理数据    df = pd.read_csv('chart_20260223T025055.csv', parse_dates=['Date'])    df.rename(columns={'Value': 'close'}, inplace=True)    # Backtrader 需要 OHLC 数据结构,这里使用收盘价填充    df['open'] = df['high'] = df['low'] = df['close']    df['volume'] = 0    df.set_index('Date', inplace=True)    df.sort_index(inplace=True)    # 转换为 Backtrader 数据格式    bt_data = bt.feeds.PandasData(dataname=df)    # 2. 运行对比    run_backtest(DCAStrategy, bt_data, "无脑定投策略")    run_backtest(ValueStrategy, bt_data, "低估值买入策略")

最新文章

随机文章