Pine Script如何调用低周期指标日终值绘制高时间框架指标
Pine Script 跨周期取60分钟指标日终值实现方案
问题背景
当前编写的ATR归一化相对强度指标,核心逻辑是计算个股相对于基准指数的ATR归一化收益率差值,原脚本代码如下:
//@version=5 indicator("Normalized (ATR - wise) Relative strength of a stock compared to an index (daily close comparison)", "Normalized (ATR - wise) Relative strength of a stock",precision = 2) //Input comparativeTickerId = input.symbol("VNINDEX",title = "Comparative Symbol" ) smoothing = input.string(title="Smoothing", defval="RMA", options=["RMA", "SMA", "EMA", "WMA"]) lengthFastMA = input.int(5,minval=1, title="Fast MA") lengthSlowMA = input.int(25,minval=1, title="Slow MA") //Calculation baseSymbol = request.security(syminfo.tickerid, "60", close) fixSymbolBar = request.security(syminfo.tickerid, "D", close[1],barmerge.gaps_off, barmerge.lookahead_on) atr_baseSymbol = request.security(syminfo.tickerid, "60", ta.atr(25)) normalizeSymbolBar = (baseSymbol-fixSymbolBar)/atr_baseSymbol comparativeSymbol = request.security(comparativeTickerId, "60", close) fixComparativeSymbolbar = request.security(comparativeTickerId, "D", close[1],barmerge.gaps_off, barmerge.lookahead_on) // correct atrComparativeSymbol = request.security(comparativeTickerId,"60",ta.atr(25)) normalizeComparativeSymbol = (comparativeSymbol - fixComparativeSymbolbar)/atrComparativeSymbol ma_function(source, length) => switch smoothing "RMA" => ta.rma(source, length) "SMA" => ta.sma(source, length) "EMA" => ta.ema(source, length) => ta.wma(source, length) res = (normalizeSymbolBar - normalizeComparativeSymbol)*100 //plot plot(res,style = plot.style_columns, color = res > 0 ? color.blue : color.orange) plot(ma_function(res,lengthFastMA), color = ma_function(res,lengthFastMA) > 0 ? #0c5847 : color.red, title = "Fast MA", linewidth = 2) plot(ma_function(res,lengthSlowMA), style = plot.style_area, title = 'Slow MA', color = color.gray)
核心需求
- 指标运行在日线时间框架
- 绘图使用的
ta.ema(res,lengthFastMA)取值,必须是60分钟周期上滚动计算得到的每日最后一根K线(日终)值 - 取值对齐规则:若2022年6月30日23点对应的60分钟K线(当日最后一根60分钟K线)上
ta.ema(res,lengthFastMA)取值为50,则2022年6月30日对应的日线指标取值同样为50
实现方法
原脚本的问题在于零散调用request.security拉取60分钟周期的单值数据,再在当前周期计算EMA,这种写法既无法保证60分钟序列的连续性,会导致EMA计算结果偏差,也无法精准对齐每日最后一根60分钟K线的取值。正确实现逻辑如下:
- 把60分钟周期下从原始行情读取、归一化计算、到EMA计算的全链路逻辑封装为独立函数,确保EMA是在连续的60分钟K线序列上滚动计算,结果准确
- 调用
request.security时传入封装好的计算函数,指定60分钟周期,搭配正确的K线合并参数,直接拉取每日收盘时(即当日最后一根60分钟K线走完后)的EMA值,无未来函数、无重绘。
修改后的完整可运行代码如下:
//@version=5 indicator("Normalized (ATR - wise) Relative strength of a stock compared to an index (Daily end 60m EMA)", "Normalized RS (60m EMA daily)",precision = 2) // 输入参数 comparativeTickerId = input.symbol("VNINDEX",title = "Comparative Symbol" ) smoothing = input.string(title="Smoothing", defval="EMA", options=["RMA", "SMA", "EMA", "WMA"]) lengthFastMA = input.int(5,minval=1, title="Fast MA") lengthSlowMA = input.int(25,minval=1, title="Slow MA") // 通用MA计算函数 ma_function(source, length) => switch smoothing "RMA" => ta.rma(source, length) "SMA" => ta.sma(source, length) "EMA" => ta.ema(source, length) => ta.wma(source, length) // 封装60分钟周期全量计算逻辑,返回需要的日终值 calc_60m_rs() => // 60分钟周期下基础标的计算 base_60m_close = close base_d_prev_close = request.security(syminfo.tickerid, "D", close[1], barmerge.gaps_off, barmerge.lookahead_on) base_60m_atr = ta.atr(25) norm_base = (base_60m_close - base_d_prev_close)/base_60m_atr // 60分钟周期下对比指数计算 comp_60m_close = request.security(comparativeTickerId, "60", close, barmerge.gaps_off, barmerge.lookahead_off) comp_d_prev_close = request.security(comparativeTickerId, "D", close[1], barmerge.gaps_off, barmerge.lookahead_on) comp_60m_atr = request.security(comparativeTickerId, "60", ta.atr(25), barmerge.gaps_off, barmerge.lookahead_off) norm_comp = (comp_60m_close - comp_d_prev_close)/comp_60m_atr res_60m = (norm_base - norm_comp)*100 fast_ma_60m = ma_function(res_60m, lengthFastMA) slow_ma_60m = ma_function(res_60m, lengthSlowMA) // 返回三个需要的序列:60分钟res值、快速MA、慢速MA [res_60m, fast_ma_60m, slow_ma_60m] // 日线级别拉取60分钟周期的计算结果,仅取每日最后一根60分钟bar的收盘值,无未来函数 [res_daily, fast_ma_daily, slow_ma_daily] = request.security(syminfo.tickerid, "60", calc_60m_rs(), barmerge.gaps_off, barmerge.lookahead_off) // 绘图 plot(res_daily, style = plot.style_columns, color = res_daily > 0 ? color.blue : color.orange, title="RS Value") plot(fast_ma_daily, color = fast_ma_daily > 0 ? #0c5847 : color.red, title = "Fast MA (60m daily end)", linewidth = 2) plot(slow_ma_daily, style = plot.style_area, title = 'Slow MA (60m daily end)', color = color.new(color.gray, 70))
注意:代码中
barmerge.lookahead_off参数确保不会引入未来数据,只有当一根60分钟K线完全走完后,对应的值才会被日线周期引用,完全符合要求的取值对齐规则。
内容的提问来源于stack exchange,提问作者Quang Son Ma
相关产品推荐
相关产品推荐

