5月27日 14:01

TradingView 怎么做策略回测?Strategy Tester 怎么用?

为什么你的策略在脑子里赚钱,在实盘里亏钱?

大多数交易者都有过这样的经历:一套逻辑清晰的交易规则,在脑海中推演时百发百中,一旦实盘执行却频频翻车。问题不在于策略本身,而在于你跳过了最关键的一步——用历史数据验证它。TradingView 的 Strategy Tester 就是做这件事的工具,而 Pine Script 则是你和它对话的语言。

Strategy Tester 面板:回测的控制中心

在 TradingView 图表底部点击 Strategy Tester 标签页,即可打开回测面板。它由四个子标签组成:

  • Overview:策略的整体盈亏曲线和关键绩效摘要
  • Performance Summary:按多/空/全部拆分的详细指标表
  • List of Trades:每一笔交易的入场价、出场价、盈亏、持仓时间
  • Properties:策略的参数设置(初始资金、手续费、数据范围等)

加载策略有三种途径:内置策略(如 Supertrend Strategy)、社区公开策略、以及你自己用 Pine Script 编写的策略。只有声明为 strategy() 的脚本才会出现在 Strategy Tester 中,indicator() 不会。

用 Pine Script 编写可回测的策略

strategy() 声明:回测的起点

pinescript
strategy("均线交叉策略", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)

关键参数说明:

参数作用建议值
initial_capital初始资金与你实盘资金接近
default_qty_type仓位计算方式percent_of_equity 按资金比例
commission_value手续费率至少设为 0.1%(实盘往往更高)
pyramid同方向最大加仓次数默认 1,即不加仓
slippage滑点(跳)至少设 2-3 跳

手续费和滑点是回测与实盘最大的差距来源。很多策略在零手续费下表现出色,加上 0.1% 双边成本后直接亏损。

strategy.entry / exit / close:交易指令三件套

pinescript
// 均线计算 fastMA = ta.sma(close, 10) slowMA = ta.sma(close, 30) // 入场条件 longCondition = ta.crossover(fastMA, slowMA) shortCondition = ta.crossunder(fastMA, slowMA) // 开仓 if longCondition strategy.entry("多头", strategy.long) if shortCondition strategy.entry("空头", strategy.short) // 止损止盈:从入场价偏移 strategy.exit("多头退出", "多头", stop=strategy.position_avg_price * 0.97, limit=strategy.position_avg_price * 1.06) // 强制平仓(无条件出场) // strategy.close("多头", when=某个条件)

三者的区别:

  • strategy.entry:开仓或反手,如果已有同方向持仓则忽略,已有反方向持仓则先平再开
  • strategy.exit:设定止损/止盈价位,是挂单逻辑,价格触及才会触发
  • strategy.close:当前 bar 满足条件时立即平仓,适合条件出场

一个常见错误是在 strategy.exit 中同时用了 when 参数——exit 本身是挂单,不需要条件判断,条件出场应该用 strategy.close

回测参数设置:别让默认值骗了你

Strategy Tester 面板的 Settings 齿轮图标里藏着几个严重影响结果的设置:

时间范围

默认是图表上所有可用数据。建议手动指定起止日期,并确保覆盖至少一个完整的牛熊周期。日线策略至少用 2-3 年数据,日内策略至少覆盖不同波动率阶段。

免费账户只能回测 5000 根 K 线,Pro 账户 15000 根,Premium 不限。数据量不足会导致统计结果不可靠。

初始资金与仓位

初始资金设为你实际可投入的金额。仓位管理用 strategy.percent_of_equity 比固定手数更贴近真实——随着账户增长,仓位也相应放大。

手续费与滑点

strategy() 声明中设置 commission_value,同时别忘了 slippage 参数。滑点在流动性差的市场中影响巨大,加密货币小币种的实际滑点可能远超 3 跳。

看懂绩效指标:数字背后的真实含义

盈利能力

  • 净利润(Net Profit):扣除手续费后的总盈亏。单独看这个数字没意义,需要和最大回撤一起看
  • 盈利因子(Profit Factor):总盈利 / 总亏损。低于 1.5 的策略风险偏高,1.5-2.0 属于中等,2.0 以上在实盘中很少见
  • 胜率(Win Rate):单独看胜率没有意义。60% 胜率 + 1:0.5 盈亏比 可能不如 40% 胜率 + 1:3 盈亏比

风险指标

  • 最大回撤(Max Drawdown):从账户峰值到谷底的最大跌幅。如果你无法承受 30% 的回撤,那最大回撤超过 30% 的策略就不适合你
  • 夏普比率(Sharpe Ratio):每承受一单位风险能获得多少超额收益。低于 0.5 几乎不值得运行,1.0 以上算优秀
  • 卡尔马比率(Calmar Ratio):年化收益 / 最大回撤。衡量"回撤换收益"的效率

交易统计

重点关注 平均持仓时间最大连续亏损次数。持仓时间过短(几分钟)的策略对滑点和延迟极其敏感;连续亏损 10 次以上时,大多数交易者会在第 6-7 次就手动止损出局,根本熬不到策略回本。

参数优化:找到最优解还是拟合历史?

Strategy Tester 支持对策略中声明为 input() 的参数进行穷举优化。点击面板中的 Optimize 按钮,设定参数范围和步长,系统会遍历所有组合并按净利润排序。

问题在于:10 个参数、每个 10 个取值 = 10 亿种组合。参数越多,过拟合的概率越高。优化结果的排名表里排第一的参数组合,在样本外数据上大概率不是第一。

前进式验证(Walk-Forward)

更可靠的做法:

  1. 将数据分为训练集(前 70%)和测试集(后 30%)
  2. 在训练集上优化参数
  3. 用最优参数在测试集上运行,看表现是否可接受
  4. 如果测试集表现差距过大,说明过拟合了

Pine Script 本身不支持自动前进式验证,但你可以手动修改回测的时间范围来模拟这个过程。

回测的致命陷阱

过拟合

表现:训练集上盈利因子 3.0+,测试集上低于 1.2。原因是参数被调到恰好契合历史走势的每一个转折。

应对:减少参数数量;参数优化后必须在样本外数据验证;如果微调参数就导致绩效剧烈变化,说明策略不稳定。

未来函数(Lookahead Bias)

Pine Script 中最容易犯的错误是在未确认的 bar 上做决策:

pinescript
// 错误:用当前 bar 的 close 做判断,但 close 还没确认 if close > ta.sma(close, 20) strategy.entry("买入", strategy.long) // 正确:用已确认的前一根 bar 的收盘价 if close[1] > ta.sma(close, 20)[1] strategy.entry("买入", strategy.long)

第一种写法在回测中会"偷看"当前 bar 的收盘价,导致虚高的绩效。解决方法是用 close[1] 引用已确认数据,或在 strategy() 中设置 calc_on_every_tick=false

忽视流动性

在低流动性品种上,你的限价单可能根本不会成交。回测引擎假设所有订单都能以指定价格成交,这和现实差距很大。如果你回测的是小市值加密货币或低成交量股票,绩效要打一个大折扣。

完整示例:双均线交叉 + ATR 止损

pinescript
strategy("双均线+ATR止损", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=95, commission_type=strategy.commission.percent, commission_value=0.1, slippage=3) // 参数 fastLen = input.int(10, "快线周期", minval=1) slowLen = input.int(30, "慢线周期", minval=1) atrLen = input.int(14, "ATR周期", minval=1) atrMult = input.float(2.0, "止损ATR倍数", minval=0.5, step=0.1) // 指标 fastMA = ta.sma(close, fastLen) slowMA = ta.sma(close, slowLen) atr = ta.atr(atrLen) // 入场条件(用已确认bar) longCond = ta.crossover(fastMA[1], slowMA[1]) shortCond = ta.crossunder(fastMA[1], slowMA[1]) // 多头入场 if longCond strategy.entry("多", strategy.long) // 空头入场 if shortCond strategy.entry("空", strategy.short) // 多头止损止盈 if strategy.position_size > 0 strategy.exit("多出", "多", stop=strategy.position_avg_price - atr * atrMult, limit=strategy.position_avg_price + atr * atrMult * 1.5) // 空头止损止盈 if strategy.position_size < 0 strategy.exit("空出", "空", stop=strategy.position_avg_price + atr * atrMult, limit=strategy.position_avg_price - atr * atrMult * 1.5)

这个策略用 ATR 动态计算止损距离,比固定百分比止损更贴合市场波动率。将 fastLenslowLenatrMult 声明为 input() 后可以在 Strategy Tester 中直接优化。

回测只是起点

Strategy Tester 给你的是一个概率参考,不是利润承诺。一个回测表现良好的策略,只说明"在过去的市场条件下,这套逻辑曾经有效"。市场结构会变,流动性会变,你的策略也需要迭代。

实盘前至少做三件事:在模拟盘跑 1-2 个月观察滑点,在不同品种上验证策略稳健性,以及确认自己能在最大回撤期间不手动干预。回测的价值不在于告诉你"能赚多少",而在于帮你排除"肯定会亏"的方案。

标签:Trading View