技术问询:如何在Excel中使用VBA进行股票回测
嘿,刚好我之前折腾过用Excel VBA做股票回测,给你整理一套具体的实现步骤和可复用的代码示例,应该能直接上手!
第一步:先把股票数据准备好
- 先在Excel里整理好你的股票历史数据,建议列格式:
- A列:交易日期(格式设为日期类型,确保排序正确)
- B列:收盘价(核心数据,用来计算收益和信号)
- C列及以后:可以提前算好策略需要的技术指标,比如5日均线、20日均线(当然也可以用VBA实时计算,提前算好能提升回测速度)
- 记得开启Excel的「开发工具」选项卡,然后启用宏(文件→选项→自定义功能区,勾选开发工具)
第二步:编写VBA回测核心代码
我以均线金叉死叉策略为例(5日均线上穿20日均线买入,下穿卖出),给你写个完整的代码:
Sub StockBacktest() ' 关闭屏幕更新,提升回测速度 Application.ScreenUpdating = False Dim ws As Worksheet Set ws = ThisWorkbook.Sheets("Sheet1") ' 替换成你的数据工作表名 ' 定义变量 Dim lastRow As Long lastRow = ws.Cells(Rows.Count, "A").End(xlUp).Row ' 获取数据最后一行 Dim i As Long Dim position As Integer ' 仓位:0空仓,1持仓 Dim initCapital As Double ' 初始资金 Dim currentCapital As Double Dim shareCount As Double ' 持股数量 Dim feeRate As Double ' 手续费率,比如0.001就是千分之一 ' 初始化参数 initCapital = 100000 ' 初始资金10万 currentCapital = initCapital position = 0 shareCount = 0 feeRate = 0.001 ' 新增列存放回测结果 ws.Cells(1, "E").Value = "信号" ws.Cells(1, "F").Value = "仓位" ws.Cells(1, "G").Value = "账户资金" ' 遍历数据(从第6行开始,因为前5天算不出5日均线) For i = 6 To lastRow Dim ma5 As Double, ma20 As Double ma5 = ws.Cells(i, "C").Value ' 假设C列是5日均线 ma20 = ws.Cells(i, "D").Value ' 假设D列是20日均线 ' 金叉信号:5日均线上穿20日均线,且当前空仓 If ma5 > ma20 And ws.Cells(i-1, "C").Value <= ws.Cells(i-1, "D").Value And position = 0 Then ' 计算可买股数(扣除手续费) shareCount = Int(currentCapital * (1 - feeRate) / ws.Cells(i, "B").Value) currentCapital = currentCapital - shareCount * ws.Cells(i, "B").Value * (1 + feeRate) position = 1 ws.Cells(i, "E").Value = "买入" ' 死叉信号:5日均线下穿20日均线,且当前持仓 ElseIf ma5 < ma20 And ws.Cells(i-1, "C").Value >= ws.Cells(i-1, "D").Value And position = 1 Then ' 卖出股票,计算收益 currentCapital = currentCapital + shareCount * ws.Cells(i, "B").Value * (1 - feeRate) shareCount = 0 position = 0 ws.Cells(i, "E").Value = "卖出" Else ws.Cells(i, "E").Value = "持有" End If ' 记录仓位和账户资金 ws.Cells(i, "F").Value = position If position = 1 Then ' 持仓时账户资金=现金+股票市值 ws.Cells(i, "G").Value = currentCapital + shareCount * ws.Cells(i, "B").Value Else ws.Cells(i, "G").Value = currentCapital End If Next i ' 计算最终收益 Dim finalReturn As Double finalReturn = (ws.Cells(lastRow, "G").Value - initCapital) / initCapital * 100 MsgBox "回测完成!初始资金:" & initCapital & vbCrLf & _ "最终资金:" & Round(ws.Cells(lastRow, "G").Value, 2) & vbCrLf & _ "总收益率:" & Round(finalReturn, 2) & "%" ' 恢复屏幕更新 Application.ScreenUpdating = True End Sub
- 代码里的注释已经写得很清楚了,你可以根据自己的策略修改信号判断逻辑,比如改成MACD、RSI策略
- 手续费率、初始资金这些参数都可以根据实际情况调整
第三步:回测结果的统计与可视化
- 统计关键指标:除了总收益率,你还可以在代码里加统计胜率(盈利交易次数/总交易次数)、最大回撤(账户资金从峰值到谷底的最大跌幅)、夏普比率这些
- 可视化:选中G列的账户资金数据,插入「折线图」,就能直观看到账户资金的波动情况;也可以把买卖信号标记在K线图上(如果有K线数据的话)
一些实用的注意事项
- 数据完整性:确保你的股票数据没有缺失日期,否则回测会出现错误信号
- 滑点模拟:如果要更贴近实盘,可以在买卖价格上加减几个点模拟滑点,比如买入价用
ws.Cells(i, "B").Value * 1.0005,卖出价用ws.Cells(i, "B").Value * 0.9995 - 性能优化:如果数据量很大(比如几年的日K),可以把数据读到数组里再处理,比直接读写单元格快很多
- 策略逻辑验证:先手动算几个交易日的信号和收益,确保代码逻辑是对的,再跑完整回测
要是你有特定的策略需求,或者运行代码时遇到报错,随时说细节我再帮你调整!
内容的提问来源于stack exchange,提问作者Lau Shun Nin Nigel




