389 lines
19 KiB
Plaintext
389 lines
19 KiB
Plaintext
//@version=6
|
||
indicator("多周期WMA52 (HTF/LTF)", overlay=true, max_labels_count=500, max_lines_count=500)
|
||
|
||
// ======================== 配置输入 ========================
|
||
// 主控
|
||
enableCTF = input.bool(true, "启用本级别", group="显示")
|
||
enableHTF = input.bool(true, "启用长级别", group="显示")
|
||
enableLTF = input.bool(true, "启用次级别", group="显示")
|
||
maxHTFInput = input.int(10, "最多显示长级别数量", minval=1, maxval=12, group="显示")
|
||
maxLTFInput = input.int(3, "最多显示次级别数量", minval=1, maxval=4, group="显示")
|
||
includeSeconds = input.bool(false, "包含秒级别(需高级套餐)", group="显示")
|
||
protectAutoscale = input.bool(true, "防拉伸: 仅绘制可视区间内", group="显示")
|
||
lookbackBars = input.int(300, "可视区间近多少根K线", minval=50, maxval=5000, group="显示")
|
||
padPercent = input.float(2.0, "可视边界留白(%)", minval=0.0, maxval=20.0, step=0.1, group="显示")
|
||
|
||
// 视觉(虚线效果)
|
||
dashLenHTF = input.int(6, "长级别虚线段长度", minval=1, maxval=50, group="线型")
|
||
dashGapHTF = input.int(4, "长级别虚线间隔", minval=1, maxval=50, group="线型")
|
||
dashLenLTF = input.int(2, "次级别虚线段长度", minval=1, maxval=50, group="线型")
|
||
dashGapLTF = input.int(3, "次级别虚线间隔", minval=1, maxval=50, group="线型")
|
||
lineWidthHTF = input.int(1, "长级别线宽", minval=1, maxval=4, group="线型")
|
||
lineWidthLTF = input.int(1, "次级别线宽", minval=1, maxval=4, group="线型")
|
||
lineWidthCTF = input.int(1, "本级别线宽", minval=1, maxval=4, group="线型")
|
||
enableSmooth = input.bool(true, "平滑显示(EMA)", group="线型")
|
||
smoothLenHTF = input.int(3, "长级别平滑长度", minval=1, maxval=50, group="线型")
|
||
smoothLenLTF = input.int(3, "次级别平滑长度", minval=1, maxval=50, group="线型")
|
||
smoothLenCTF = input.int(3, "本级别平滑长度", minval=1, maxval=50, group="线型")
|
||
smoothMethod = input.string("ALMA", "平滑方法", options=["EMA","DEMA","TEMA","WMA","HMA","ALMA","LinReg"], group="线型")
|
||
almaOffset = input.float(0.85, "ALMA偏移(0-1)", minval=0.0, maxval=1.0, step=0.05, group="线型")
|
||
almaSigma = input.float(6.0, "ALMA Sigma", minval=0.5, maxval=10.0, step=0.5, group="线型")
|
||
labelBgAlpha = input.int(85, "标签背景透明(0-100)", minval=0, maxval=100, group="标注")
|
||
labelSize = input.string("normal", "标签字号", options=["tiny","small","normal","large","huge"], group="标注")
|
||
labelOffsetBars = input.int(2, "标签右移K线的距离(根数)", minval=0, maxval=50, group="标注")
|
||
|
||
// 常量上限(编译期固定,用于生成固定数量的 plot 位)
|
||
const int MAX_HTF = 12
|
||
const int MAX_LTF = 4
|
||
|
||
// ======================== 工具函数 ========================
|
||
f_dash(series float v, int phase, int dashLen, int dashGap) =>
|
||
// 通过丢弃部分柱来营造虚线效果
|
||
isShow = (bar_index + phase) % (dashLen + dashGap) < dashLen
|
||
isShow ? v : na
|
||
|
||
// 自定义 DEMA / TEMA(Pine 无内置 dema/tema)
|
||
f_dema(series float v, int len) =>
|
||
ema1 = ta.ema(v, len)
|
||
ema2 = ta.ema(ema1, len)
|
||
2.0 * ema1 - ema2
|
||
|
||
f_tema(series float v, int len) =>
|
||
ema1 = ta.ema(v, len)
|
||
ema2 = ta.ema(ema1, len)
|
||
ema3 = ta.ema(ema2, len)
|
||
3.0 * (ema1 - ema2) + ema3
|
||
|
||
// 通用平滑(仅用于显示)
|
||
f_smooth(series float v, int len) =>
|
||
not enableSmooth or len <= 1 ? v :
|
||
smoothMethod == "EMA" ? ta.ema(v, len) :
|
||
smoothMethod == "DEMA" ? f_dema(v, len) :
|
||
smoothMethod == "TEMA" ? f_tema(v, len) :
|
||
smoothMethod == "WMA" ? ta.wma(v, len) :
|
||
smoothMethod == "HMA" ? ta.hma(v, len) :
|
||
smoothMethod == "ALMA" ? ta.alma(v, len, almaOffset, almaSigma) :
|
||
ta.linreg(v, len, 0)
|
||
|
||
f_strToSize(string s) => switch s
|
||
"tiny" => size.tiny
|
||
"small" => size.small
|
||
"normal" => size.normal
|
||
"large" => size.large
|
||
=> size.huge
|
||
|
||
// 颜色调色板(循环使用)
|
||
var color[] PALETTE = array.new_color()
|
||
if barstate.isfirst and array.size(PALETTE) == 0
|
||
array.push(PALETTE, color.new(color.teal, 0))
|
||
array.push(PALETTE, color.new(color.orange, 0))
|
||
array.push(PALETTE, color.new(color.fuchsia,0))
|
||
array.push(PALETTE, color.new(color.aqua, 0))
|
||
array.push(PALETTE, color.new(color.yellow, 0))
|
||
array.push(PALETTE, color.new(color.purple, 0))
|
||
array.push(PALETTE, color.new(color.lime, 0))
|
||
array.push(PALETTE, color.new(color.red, 0))
|
||
array.push(PALETTE, color.new(color.blue, 0))
|
||
array.push(PALETTE, color.new(color.navy, 0))
|
||
array.push(PALETTE, color.new(color.maroon, 0))
|
||
array.push(PALETTE, color.new(color.silver, 0))
|
||
|
||
f_paletteColor(int idx) =>
|
||
sz = math.max(1, array.size(PALETTE))
|
||
array.get(PALETTE, idx % sz)
|
||
|
||
// 是否为秒级分辨率,如 "1S","5S"
|
||
f_isSecondsTf(string tf) =>
|
||
ln = str.length(tf)
|
||
ln > 0 and str.substring(tf, ln - 1, ln) == 'S'
|
||
|
||
// 计算可视范围边界(近 N 根 K 线 + 百分比留白)
|
||
rangeHi = ta.highest(high, lookbackBars)
|
||
rangeLo = ta.lowest(low, lookbackBars)
|
||
rangeSpan = rangeHi - rangeLo
|
||
pad = rangeSpan * padPercent * 0.01
|
||
minY = rangeLo - pad
|
||
maxY = rangeHi + pad
|
||
|
||
// 仅在可视区间内绘制(超出返回 na,以避免影响自动缩放)。
|
||
f_gate(series float v) => protectAutoscale ? (v >= minY and v <= maxY ? v : na) : v
|
||
|
||
// 检查是否在可视区间内
|
||
f_inRange(series float v) => protectAutoscale ? (v >= minY and v <= maxY) : true
|
||
|
||
// 周期字符串美化(如 1 -> 1m, 60 -> 1h, D -> 1D, W -> 1W, 3M -> 3M)
|
||
f_prettyTf(string tf) =>
|
||
s = timeframe.in_seconds(tf)
|
||
string out = tf
|
||
if not na(s)
|
||
if s < 3600
|
||
mins = math.max(1, math.round(s / 60))
|
||
out := str.tostring(mins) + 'm'
|
||
else if s % 3600 == 0 and s < 86400
|
||
hrs = math.round(s / 3600)
|
||
out := str.tostring(hrs) + 'h'
|
||
else if s % 86400 == 0 and s < 7 * 86400
|
||
days = math.round(s / 86400)
|
||
out := str.tostring(days) + 'D'
|
||
else if s % (7 * 86400) == 0 and s < 30 * 86400
|
||
weeks = math.round(s / (7 * 86400))
|
||
out := str.tostring(weeks) + 'W'
|
||
else
|
||
out := tf
|
||
else
|
||
// 月等返回 na 的分辨率保持原样(M/3M)
|
||
out := tf
|
||
out
|
||
|
||
// ======================== 标准时间周期表 ========================
|
||
// 备注:TradingView 分辨率字符串 —— 分钟: "1","3","5"...;小时: "60","120"...;
|
||
// 天: "D","2D";周: "W","2W";月: "M","3M";秒级可能为 "1S","5S" 等。
|
||
var string[] ALL_RES = array.new_string()
|
||
if barstate.isfirst and array.size(ALL_RES) == 0
|
||
// 由低到高,便于筛选
|
||
// 秒级(若品种/权限不支持,请忽略,筛选时会自动排除)
|
||
array.push(ALL_RES, "1S")
|
||
array.push(ALL_RES, "5S")
|
||
array.push(ALL_RES, "15S")
|
||
array.push(ALL_RES, "30S")
|
||
// 分钟
|
||
array.push(ALL_RES, "1")
|
||
array.push(ALL_RES, "3")
|
||
array.push(ALL_RES, "5")
|
||
array.push(ALL_RES, "15")
|
||
array.push(ALL_RES, "30")
|
||
array.push(ALL_RES, "45")
|
||
// 小时(以分钟表示)
|
||
array.push(ALL_RES, "60")
|
||
array.push(ALL_RES, "120")
|
||
array.push(ALL_RES, "240")
|
||
array.push(ALL_RES, "360")
|
||
array.push(ALL_RES, "480")
|
||
array.push(ALL_RES, "720")
|
||
// 日/周/月
|
||
array.push(ALL_RES, "D")
|
||
array.push(ALL_RES, "2D")
|
||
array.push(ALL_RES, "3D")
|
||
array.push(ALL_RES, "W")
|
||
array.push(ALL_RES, "2W")
|
||
array.push(ALL_RES, "M")
|
||
array.push(ALL_RES, "3M")
|
||
|
||
// ======================== 周期间关系与选择 ========================
|
||
curResStr = timeframe.period
|
||
curResSec = timeframe.in_seconds(curResStr)
|
||
|
||
// 构建长/次级别列表
|
||
var string[] htfRes = array.new_string()
|
||
var string[] ltfRes = array.new_string()
|
||
array.clear(htfRes)
|
||
array.clear(ltfRes)
|
||
for i = 0 to array.size(ALL_RES) - 1
|
||
res = array.get(ALL_RES, i)
|
||
// 非高级用户默认不包含秒级周期
|
||
if not includeSeconds and f_isSecondsTf(res)
|
||
continue
|
||
rsec = timeframe.in_seconds(res)
|
||
// timeframe.in_seconds 不支持时返回 na,需跳过
|
||
if na(rsec)
|
||
continue
|
||
if rsec > curResSec
|
||
array.push(htfRes, res)
|
||
else if rsec < curResSec
|
||
array.push(ltfRes, res)
|
||
|
||
// 选取靠近当前周期的若干次级别(更有参考意义):取 ltfRes 的末尾(更接近当前)
|
||
var string[] ltfSel = array.new_string()
|
||
array.clear(ltfSel)
|
||
ltfsz = array.size(ltfRes)
|
||
if ltfsz > 0
|
||
take = math.min(maxLTFInput, MAX_LTF, ltfsz)
|
||
for k = 0 to take - 1
|
||
array.push(ltfSel, array.get(ltfRes, ltfsz - 1 - k))
|
||
|
||
// 限制长级别数量
|
||
htfCountSelected = math.min(array.size(htfRes), maxHTFInput, MAX_HTF)
|
||
ltfCountSelected = math.min(array.size(ltfSel), MAX_LTF)
|
||
|
||
// ======================== 计算各周期 WMA52 ========================
|
||
// 预分配数值数组(保持固定最大长度)
|
||
var float[] htfVals = array.new_float()
|
||
var float[] ltfVals = array.new_float()
|
||
float ctfVal = na
|
||
if barstate.isfirst
|
||
for _i = 0 to MAX_HTF - 1
|
||
array.push(htfVals, na)
|
||
for _j = 0 to MAX_LTF - 1
|
||
array.push(ltfVals, na)
|
||
|
||
// 填充长级别数值
|
||
for i = 0 to MAX_HTF - 1
|
||
float val = na
|
||
if enableHTF and i < htfCountSelected
|
||
tfStr = array.get(htfRes, i)
|
||
// 计算该长级别的 WMA52
|
||
val := request.security(syminfo.tickerid, tfStr, ta.wma(close, 52), barmerge.gaps_off, barmerge.lookahead_off)
|
||
array.set(htfVals, i, val)
|
||
|
||
// 填充次级别数值
|
||
for i = 0 to MAX_LTF - 1
|
||
float val = na
|
||
if enableLTF and i < ltfCountSelected
|
||
tfStr = array.get(ltfSel, i)
|
||
// 计算该次级别的 WMA52(低级别向上合成,注意其更频繁更新)
|
||
val := request.security(syminfo.tickerid, tfStr, ta.wma(close, 52), barmerge.gaps_off, barmerge.lookahead_off)
|
||
array.set(ltfVals, i, val)
|
||
|
||
// 本级别 WMA52
|
||
if enableCTF
|
||
ctfVal := ta.wma(close, 52)
|
||
|
||
// ======================== 绘制(虚线 + 标签) ========================
|
||
// 顶层固定 plot(避免在局部/循环中调用 plot)
|
||
plot(enableCTF ? f_gate(f_smooth(ctfVal, smoothLenCTF)) : na, title='CTF WMA52', color=color.new(color.white, 0), linewidth=lineWidthCTF, style=plot.style_line)
|
||
plot((enableHTF and 0 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 0), smoothLenHTF), 0 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 1', color=f_paletteColor(0), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 1 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 1), smoothLenHTF), 1 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 2', color=f_paletteColor(1), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 2 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 2), smoothLenHTF), 2 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 3', color=f_paletteColor(2), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 3 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 3), smoothLenHTF), 3 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 4', color=f_paletteColor(3), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 4 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 4), smoothLenHTF), 4 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 5', color=f_paletteColor(4), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 5 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 5), smoothLenHTF), 5 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 6', color=f_paletteColor(5), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 6 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 6), smoothLenHTF), 6 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 7', color=f_paletteColor(6), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 7 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 7), smoothLenHTF), 7 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 8', color=f_paletteColor(7), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 8 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 8), smoothLenHTF), 8 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 9', color=f_paletteColor(8), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 9 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 9), smoothLenHTF), 9 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 10', color=f_paletteColor(9), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 10 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 10), smoothLenHTF), 10 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 11', color=f_paletteColor(10), linewidth=lineWidthHTF, style=plot.style_line)
|
||
plot((enableHTF and 11 < htfCountSelected) ? f_gate(f_dash(f_smooth(array.get(htfVals, 11), smoothLenHTF), 11 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF WMA52 12', color=f_paletteColor(11), linewidth=lineWidthHTF, style=plot.style_line)
|
||
|
||
plot((enableLTF and 0 < ltfCountSelected) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 0), smoothLenLTF), 0 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF WMA52 1', color=color.new(f_paletteColor(0), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||
plot((enableLTF and 1 < ltfCountSelected) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 1), smoothLenLTF), 1 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF WMA52 2', color=color.new(f_paletteColor(1), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||
plot((enableLTF and 2 < ltfCountSelected) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 2), smoothLenLTF), 2 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF WMA52 3', color=color.new(f_paletteColor(2), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||
plot((enableLTF and 3 < ltfCountSelected) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 3), smoothLenLTF), 3 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF WMA52 4', color=color.new(f_paletteColor(3), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||
|
||
// 右侧标签(仅在最后一根柱更新,避免重复创建)
|
||
var label[] htfLabels = array.new_label()
|
||
var label[] ltfLabels = array.new_label()
|
||
var label ctfLabel = na
|
||
var string lastTicker = na
|
||
var string lastTf = na
|
||
if barstate.isfirst
|
||
for _i = 0 to MAX_HTF - 1
|
||
array.push(htfLabels, na)
|
||
for _j = 0 to MAX_LTF - 1
|
||
array.push(ltfLabels, na)
|
||
lastTicker := syminfo.tickerid
|
||
lastTf := timeframe.period
|
||
|
||
// 更新/清理标签
|
||
// 如果品种或周期变化,清理旧标签
|
||
symbolChanged = lastTicker != syminfo.tickerid
|
||
tfChanged = lastTf != timeframe.period
|
||
if symbolChanged or tfChanged
|
||
for i = 0 to MAX_HTF - 1
|
||
lab = array.get(htfLabels, i)
|
||
if not na(lab)
|
||
label.delete(lab)
|
||
array.set(htfLabels, i, na)
|
||
for i = 0 to MAX_LTF - 1
|
||
lab = array.get(ltfLabels, i)
|
||
if not na(lab)
|
||
label.delete(lab)
|
||
array.set(ltfLabels, i, na)
|
||
if not na(ctfLabel)
|
||
label.delete(ctfLabel)
|
||
ctfLabel := na
|
||
lastTicker := syminfo.tickerid
|
||
lastTf := timeframe.period
|
||
|
||
if barstate.islast
|
||
// 长级别
|
||
for i = 0 to MAX_HTF - 1
|
||
lab = array.get(htfLabels, i)
|
||
if enableHTF and i < htfCountSelected
|
||
tfStr = array.get(htfRes, i)
|
||
v = array.get(htfVals, i)
|
||
col = f_paletteColor(i)
|
||
txt = f_prettyTf(tfStr) + ' ' + str.tostring(v, format.mintick)
|
||
// 可视区间外则隐藏标签;区间内按真实价格绘制,确保与标尺一致
|
||
if protectAutoscale and not f_inRange(v)
|
||
if not na(lab)
|
||
label.delete(lab)
|
||
array.set(htfLabels, i, na)
|
||
else
|
||
if na(lab)
|
||
lab := label.new(bar_index + labelOffsetBars, v, txt, xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left, textcolor=col, color=color.new(col, labelBgAlpha), size=f_strToSize(labelSize))
|
||
array.set(htfLabels, i, lab)
|
||
else
|
||
label.set_xy(lab, bar_index + labelOffsetBars, v)
|
||
label.set_text(lab, txt)
|
||
label.set_textcolor(lab, col)
|
||
label.set_color(lab, color.new(col, labelBgAlpha))
|
||
label.set_style(lab, label.style_label_left)
|
||
label.set_size(lab, f_strToSize(labelSize))
|
||
else
|
||
if not na(lab)
|
||
label.delete(lab)
|
||
array.set(htfLabels, i, na)
|
||
|
||
// 次级别
|
||
for i = 0 to MAX_LTF - 1
|
||
lab = array.get(ltfLabels, i)
|
||
if enableLTF and i < ltfCountSelected
|
||
tfStr = array.get(ltfSel, i)
|
||
v = array.get(ltfVals, i)
|
||
base = f_paletteColor(i)
|
||
col = color.new(base, 0)
|
||
txt = f_prettyTf(tfStr) + ' ' + str.tostring(v, format.mintick)
|
||
if protectAutoscale and not f_inRange(v)
|
||
if not na(lab)
|
||
label.delete(lab)
|
||
array.set(ltfLabels, i, na)
|
||
else
|
||
if na(lab)
|
||
lab := label.new(bar_index + labelOffsetBars, v, txt, xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left, textcolor=col, color=color.new(col, labelBgAlpha + 10 > 100 ? 100 : labelBgAlpha + 10), size=f_strToSize(labelSize))
|
||
array.set(ltfLabels, i, lab)
|
||
else
|
||
label.set_xy(lab, bar_index + labelOffsetBars, v)
|
||
label.set_text(lab, txt)
|
||
label.set_textcolor(lab, col)
|
||
label.set_color(lab, color.new(col, labelBgAlpha + 10 > 100 ? 100 : labelBgAlpha + 10))
|
||
label.set_style(lab, label.style_label_left)
|
||
label.set_size(lab, f_strToSize(labelSize))
|
||
else
|
||
if not na(lab)
|
||
label.delete(lab)
|
||
array.set(ltfLabels, i, na)
|
||
|
||
// 本级别
|
||
if enableCTF
|
||
v = ctfVal
|
||
col = color.new(color.white, 0)
|
||
txt = f_prettyTf(curResStr) + ' ' + str.tostring(v, format.mintick)
|
||
if protectAutoscale and not f_inRange(v)
|
||
if not na(ctfLabel)
|
||
label.delete(ctfLabel)
|
||
ctfLabel := na
|
||
else
|
||
if na(ctfLabel)
|
||
ctfLabel := label.new(bar_index + labelOffsetBars, v, txt, xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left, textcolor=col, color=color.new(col, labelBgAlpha), size=f_strToSize(labelSize))
|
||
else
|
||
label.set_xy(ctfLabel, bar_index + labelOffsetBars, v)
|
||
label.set_text(ctfLabel, txt)
|
||
label.set_textcolor(ctfLabel, col)
|
||
label.set_color(ctfLabel, color.new(col, labelBgAlpha))
|
||
label.set_style(ctfLabel, label.style_label_left)
|
||
label.set_size(ctfLabel, f_strToSize(labelSize))
|
||
else
|
||
if not na(ctfLabel)
|
||
label.delete(ctfLabel)
|
||
ctfLabel := na
|
||
|
||
// ======================== 备注 ========================
|
||
// 1) 当前周期通过 timeframe.period 自动识别,并用 timeframe.in_seconds(
|
||
// ) 转换成秒以进行相对大小比较。
|
||
// 2) 长级别/次级别集合从标准分辨率表中过滤得出,绘图数量受 MAX_* 与输入上限控制。
|
||
// 3) 虚线效果通过在 plot 中周期性输出 na 实现,性能优于逐柱绘制 line 对象。
|
||
// 4) 标签在最后一根柱更新,避免过量对象;颜色与曲线一致。
|
||
// 5) 次级别(低于当前)WMA52 也计算并显示,更新频率更高,默认更淡。
|
||
|
||
|