TradingView Pine Script固定运行分辨率与多标的策略实现技术咨询
Pine Script 策略配置与多标的运行解决方案
针对你提出的两个Pine Script策略问题,我整理了具体的解决方案和修改后的代码,希望能帮到你:
一、固定策略运行分辨率,不受图表时间范围影响
你之前尝试用security函数但没达到预期效果,核心问题是没有把所有策略依赖的数据(收盘价、均线、标准差)都切换到指定分辨率上,同时还要注意避免未来函数的干扰,保证回测的准确性。
正确实现方案
- 使用
request.security()函数(Pine Script v4推荐用这个替代旧的security)获取指定分辨率的数据源,设置lookahead=barmerge.lookahead_off禁用未来数据,确保信号完全基于历史数据生成。 - 将所有用于计算指标和交易信号的变量,都基于这个固定分辨率的数据,而不是当前图表的分辨率。这样不管你查看1年、5年还是YTD的时间范围,策略都会严格按照你指定的分辨率(比如日线
1D)运行。
关键代码修改
// 定义运行分辨率,用户可自定义输入 res = input(title='运行分辨率', type=input.resolution, defval='1D') // 获取指定分辨率的收盘价、SMA、标准差,禁用未来数据 [closeRes, smaRes, stdRes] = request.security(syminfo.tickerid, res, [close, sma(close, smaLength), stdev(close, stdLength)], lookahead=barmerge.lookahead_off) // 基于固定分辨率数据计算布林带 upperBand = smaRes + stdRes * ubOffset lowerBand = smaRes - stdRes * lbOffset
二、实现多标的策略运行
TradingView和QuantConnect的多标的逻辑差异较大,这里给你两种实用的解决方案,适配不同的使用场景:
方案1:在同一策略中引入多标的数据,生成跨标的信号
通过request.security()引入其他标的的行情数据,在同一个策略中为每个标的编写独立的交易逻辑,同时设置资金分配规则,避免单标的占用过多资金。比如你可以给每个标的分配总资金的30%,这样最多同时持有3个标的,有效降低空仓时长。
方案2:使用TradingView内置的多标的策略测试功能
如果你不想修改代码,可以直接在策略测试器中添加多个标的:
- 打开策略测试器,切换到「设置」标签页
- 在「符号」选项中点击「添加符号」,选择你要测试的所有标的
- 在「资金」设置中,选择「每个符号使用单独的资金」或「共享资金池」(推荐共享资金池来模拟真实账户的资金分配)
- 运行策略即可查看多标的的整体回测结果
完整修改后的策略代码
这份代码整合了固定分辨率和多标的功能,你可以根据需要添加更多标的:
//@version=4 strategy(title="Multi-Asset Bollinger", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=30, initial_capital=100000) // 策略规则: // 1. 当价格上穿下轨时开多单 // 2. 当价格触碰上轨时平仓 // // 图表属性 testStartYear = input(2018, "回测起始年份") testStartMonth = input(1, "回测起始月份") testStartDay = input(1, "回测起始日期") testPeriodStart = timestamp(testStartYear, testStartMonth, testStartDay, 0, 0) testStopYear = input(2021, "回测结束年份") testStopMonth = input(1, "回测结束月份") testStopDay = input(1, "回测结束日期") testPeriodStop = timestamp(testStopYear, testStopMonth, testStopDay, 0, 0) // 控制回测时段背景色的开关 testPeriodBackground = input(title="是否显示背景色?", type=input.bool, defval=true) testPeriodBackgroundColor = testPeriodBackground and time >= testPeriodStart and time <= testPeriodStop ? #6c6f6c : na bgcolor(testPeriodBackgroundColor, transp=97) // 用户输入参数 smaLength = input(title="SMA周期", type=input.integer, defval=20) // 中轨周期(移动平均线) stdLength = input(title="标准差周期", type=input.integer, defval=20) // 计算布林带的周期 ubOffset = input(title="上轨偏移量", type=input.float, defval=2.0, step=0.5) // 均线之上的标准差倍数 lbOffset = input(title="下轨偏移量", type=input.float, defval=2.0, step=0.5) // 均线之下的标准差倍数 res = input(title='运行分辨率', type=input.resolution, defval='1D') // 分辨率 // 可选:添加更多标的,这里以第二个标的为例 ticker2 = input(title='第二个标的', type=input.symbol, defval='SPY') testPeriod() => time >= testPeriodStart and time <= testPeriodStop ? true : false // -------------------------- // 固定分辨率数据获取(当前标的) // -------------------------- [closeRes, smaRes, stdRes] = request.security(syminfo.tickerid, res, [close, sma(close, smaLength), stdev(close, stdLength)], lookahead=barmerge.lookahead_off) upperBand = smaRes + stdRes * ubOffset // 上轨 lowerBand = smaRes - stdRes * lbOffset // 下轨 // 绘制当前标的布林带 plot(series=smaRes, title="SMA", color=color.blue) plot(series=upperBand, title="UB", color=color.green, linewidth=2) plot(series=lowerBand, title="LB", color=color.red, linewidth=2) // 当前标的交易信号 longCondition = crossover(closeRes, lowerBand) closeLongCondition = closeRes >= upperBand if (longCondition and testPeriod()) strategy.entry(id="CALL", long=true) strategy.close(id="CALL", when=closeLongCondition) // -------------------------- // 第二个标的数据与交易逻辑 // -------------------------- [close2, sma2, std2] = request.security(ticker2, res, [close, sma(close, smaLength), stdev(close, stdLength)], lookahead=barmerge.lookahead_off) upperBand2 = sma2 + std2 * ubOffset lowerBand2 = sma2 - std2 * lbOffset longCondition2 = crossover(close2, lowerBand2) closeLongCondition2 = close2 >= upperBand2 // 第二个标的交易 if (longCondition2 and testPeriod()) strategy.entry(id="CALL_2", long=true, ticker=ticker2) strategy.close(id="CALL_2", when=closeLongCondition2, ticker=ticker2) // 设置资金分配,每个标的最多占用30%总资金 strategy.risk.allow_entry_in(strategy.long, qty_percent=30)
内容的提问来源于stack exchange,提问作者Deemo




