如何计算TradingView中过去200根K线偏离20 SMA的最大百分比?
问题:获取价格偏离20周期SMA的最大静态值
尝试通过编程确定某资产价格偏离20周期简单移动平均线(20 SMA)最大的时刻。编写代码循环遍历过去200根K线,计算收盘价与20 SMA的百分比差值并存入数组,再通过array.max()计算最大百分比变化。预期maxOverMA为静态值,但实际该值是动态的,无法正确获取价格偏离20 SMA的最大时刻。
原代码:
//@version=5 indicator("Secret Algo", overlay=true, max_labels_count=500) // Functions pine_sma(source, length) => sum = 0.0 for i = 0 to length - 1 sum += source[i] / length sum // Variables MA = ta.sma(close, 20) maPercentage = (close - MA) / MA * 100 maHistory = array.new_float(0) // Determine historical max, min and avg deviation from MA for i = 1 to 200 tempMA = pine_sma(close, 20) tempMaPercentage = (close - tempMA) / tempMA * 100 maHistory.push(tempMaPercentage) // Set MA ranges maxOverMA = array.max(maHistory) maxUnderMA = array.min(maHistory) label.new(bar_index, close, str.tostring(maxOverMA), textcolor=color.red, style=label.style_none)
问题分析
- 数组未持久化:每根K线都会重新创建
maHistory数组,导致每次都要重新填充数据,无法累积历史值。 - 历史数据回溯错误:循环中计算的始终是当前K线的20周期SMA,没有偏移到过去的K线,数组里存的都是当前K线的偏离值,而非历史200根K线的各自偏离值。
- 循环逻辑无效:
for i=1 to 200只是重复200次添加当前K线的偏离值,并没有遍历过去200根K线。
优化方案
方案1:用内置函数直接计算历史极值(最简)
利用Pine Script内置的ta.highest()和ta.lowest(),直接计算过去200根K线中偏离值的最大/最小值:
//@version=5 indicator("Secret Algo", overlay=true, max_labels_count=500) // 计算当前K线的价格偏离20SMA百分比 ma20 = ta.sma(close, 20) deviation_pct = (close - ma20) / ma20 * 100 // 计算过去200根K线中的最大/最小偏离值(200根K线后变为静态值) lookback_length = 200 maxOverMA = ta.highest(deviation_pct, lookback_length) maxUnderMA = ta.lowest(deviation_pct, lookback_length) // 仅在最后一根K线显示标签,避免重复绘制 if barstate.islast label.new(bar_index, close, str.tostring(maxOverMA, "#.##"), textcolor=color.red, style=label.style_none)
方案2:手动维护历史数组(适合自定义逻辑)
用var声明数组确保只初始化一次,通过偏移i获取过去每根K线的偏离值:
//@version=5 indicator("Secret Algo", overlay=true, max_labels_count=500) // 计算每根K线的偏离值序列 ma20 = ta.sma(close, 20) deviation_pct = (close - ma20) / ma20 * 100 // var声明数组,确保仅初始化一次 var float[] maHistory = array.new_float() lookback_length = 200 // 当K线数足够时,填充过去200根K线的偏离值(仅执行一次) if bar_index == lookback_length - 1 for i = 0 to lookback_length - 1 // 偏移i获取过去第i根K线的偏离值 array.push(maHistory, deviation_pct[i]) // 获取数组中的极值 maxOverMA = array.size(maHistory) > 0 ? array.max(maHistory) : na maxUnderMA = array.size(maHistory) > 0 ? array.min(maHistory) : na // 最后一根K线显示结果 if barstate.islast label.new(bar_index, close, str.tostring(maxOverMA, "#.##"), textcolor=color.red, style=label.style_none)
关键优化点说明
var关键字:声明持久化变量,避免数组在每根K线重新创建,保留历史数据。- 历史数据偏移:通过
deviation_pct[i]获取过去第i根K线的偏离值,而非重复使用当前值。 barstate.islast:仅在最后一根K线绘制标签,避免重复创建标签,提升性能。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

