如何在单脚本中回测多品种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
相关产品推荐
相关产品推荐

