You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

技术问询:如何在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

火山引擎 最新活动