You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单脚本中回测多品种MA交叉策略指标并精简代码?

在Pine Script中用单指标回测多标的投资组合的最优方案

核心结论

没错,用request.security配合自定义函数是最简洁的解决方案,能彻底避免重复编写MA计算、信号判断这类冗余代码。


步骤1:封装策略逻辑到自定义函数

把MA计算、金叉死叉判断、仓位状态这些核心逻辑打包成一个可复用的函数,输入标的价格和MA参数,直接输出你需要的信号与仓位状态。

// 自定义函数:计算MA策略的仓位与信号
getStrategyStatus(src, fastLength, slowLength) =>
    fastMA = ta.sma(src, fastLength)
    slowMA = ta.sma(src, slowLength)
    // 金叉/死叉信号
    longSignal = ta.crossover(fastMA, slowMA)
    shortSignal = ta.crossunder(fastMA, slowMA)
    // 仓位状态:1=持有,0=空仓
    inPosition = ta.barssince(longSignal) < ta.barssince(shortSignal) or longSignal
    [inPosition, longSignal, shortSignal]

步骤2:用request.security拉取多标的数据并调用函数

先定义要测试的5个标的列表,再逐个通过request.security获取标的数据,调用上面的函数得到每个标的的仓位和信号。

// 替换成你需要测试的标的代码
symbols = ["BTCUSDT", "ETHUSDT", "BNBUSDT", "ADAUSDT", "SOLUSDT"]
// MA参数(可自行调整)
fastMA = input.int(50, title="快速MA周期")
slowMA = input.int(200, title="慢速MA周期")

// 逐个获取标的策略状态
[btcPos, btcLong, btcShort] = request.security(symbols[0], timeframe.period, getStrategyStatus(close, fastMA, slowMA))
[ethPos, ethLong, ethShort] = request.security(symbols[1], timeframe.period, getStrategyStatus(close, fastMA, slowMA))
[bnbPos, bnbLong, bnbShort] = request.security(symbols[2], timeframe.period, getStrategyStatus(close, fastMA, slowMA))
[adaPos, adaLong, adaShort] = request.security(symbols[3], timeframe.period, getStrategyStatus(close, fastMA, slowMA))
[solPos, solLong, solShort] = request.security(symbols[4], timeframe.period, getStrategyStatus(close, fastMA, slowMA))

步骤3:计算组合整体表现(指标可视化)

因为是指标而非策略,无法直接使用Pine Script的策略绩效报告,但可以计算组合累计收益率来验证表现。比如按等权重分配资金:

// 计算单个标的的每日收益率(仅持有期间生效)
btcReturn = request.security(symbols[0], timeframe.period, ta.change(close)/close[1]) * btcPos
ethReturn = request.security(symbols[1], timeframe.period, ta.change(close)/close[1]) * ethPos
bnbReturn = request.security(symbols[2], timeframe.period, ta.change(close)/close[1]) * bnbPos
adaReturn = request.security(symbols[3], timeframe.period, ta.change(close)/close[1]) * adaPos
solReturn = request.security(symbols[4], timeframe.period, ta.change(close)/close[1]) * solPos

// 等权重组合每日收益率
portfolioReturn = (btcReturn + ethReturn + bnbReturn + adaReturn + solReturn) / 5
// 组合累计收益率
cumPortfolioReturn = ta.cum(1 + portfolioReturn) - 1

// 绘制组合累计收益率曲线
plot(cumPortfolioReturn, title="组合累计收益率", color=color.blue, linewidth=2)

// 可选:给单个标的添加信号标记
plotshape(btcLong, title="BTC金叉", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(btcShort, title="BTC死叉", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)

补充细节

  • 新手优先用逐个调用的方式,避免循环带来的变量作用域问题;熟练后可以用for循环遍历标的列表进一步简化代码。
  • request.security的第二个参数timeframe.period表示和当前图表时间框架一致,如需跨时间框架测试,改成对应周期字符串即可(比如"D"代表日线)。

内容的提问来源于stack exchange,提问作者Adrian Stangell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 05:22:57