为了进行量化对比,我们设定以下两个常见策略的规则:
无脑定投(DCA 策略):每个月固定存入 $1000,并在当月第一个交易日全仓买入标普500。
低估值买入(逢低买入策略):每个月同样攒下 $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.80 | 0.66 |
1. 资金年化收益率(IRR)—— 你的“平均赚钱速度”简单来说,它衡量的是你资金的综合赚钱效率。假设你有 100 万进行全部投入,年化收益率为 13.55%,这就代表在长期的投资复利下,你平均每年大约可以赚到 13.55 万元。
2. 最大回撤(Max Drawdown)—— 极端情况下的“最差体验”想获得高收益,必然要承受波动的代价。最大回撤代表了你在“最倒霉”的顶点买入后,一路跌到最低谷时经历的最大账面亏损幅度。 比如最大回撤为 33.92% 时,就代表如果你投入了 100 万,在遇到像疫情或股灾这种极端暴跌情况时,你的账面曾一度缩水(浮亏)了 33.92 万元。这个指标直接反映了该策略需要多大的“强心脏”才能抗住不卖。
3. 夏普比率(Sharpe Ratio)—— 投资的“性价比”它衡量的是**你每多承担 1 份风险(波动),能换来多少份收益**。
在长达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, "低估值买入策略")