添加新的indicator
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
//@version=6
|
||||
indicator("多周期EMA52_Pro", 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="显示")
|
||||
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="显示")
|
||||
|
||||
// 固定 12 周期开关(本级别也会跟随对应周期开关)
|
||||
showRes1 = input.bool(true, "显示 1m", group="级别开关")
|
||||
showRes2 = input.bool(true, "显示 3m", group="级别开关")
|
||||
showRes3 = input.bool(true, "显示 5m", group="级别开关")
|
||||
showRes4 = input.bool(true, "显示 15m", group="级别开关")
|
||||
showRes5 = input.bool(true, "显示 30m", group="级别开关")
|
||||
showRes6 = input.bool(true, "显示 45m", group="级别开关")
|
||||
showRes7 = input.bool(true, "显示 1h", group="级别开关")
|
||||
showRes8 = input.bool(true, "显示 2h", group="级别开关")
|
||||
showRes9 = input.bool(true, "显示 4h", group="级别开关")
|
||||
showRes10 = input.bool(true, "显示 6h", group="级别开关")
|
||||
showRes11 = input.bool(true, "显示 8h", group="级别开关")
|
||||
showRes12 = input.bool(true, "显示 12h", 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(2, "本级别线宽", 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
|
||||
|
||||
f_showRes(string tf) => switch tf
|
||||
"1" => showRes1
|
||||
"3" => showRes2
|
||||
"5" => showRes3
|
||||
"15" => showRes4
|
||||
"30" => showRes5
|
||||
"45" => showRes6
|
||||
"60" => showRes7
|
||||
"120" => showRes8
|
||||
"240" => showRes9
|
||||
"360" => showRes10
|
||||
"480" => showRes11
|
||||
"720" => showRes12
|
||||
=> true
|
||||
|
||||
// 颜色调色板(循环使用)
|
||||
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)
|
||||
|
||||
// 计算可视范围边界(近 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"...;
|
||||
// 仅保留分钟与小时级别。
|
||||
var string[] ALL_RES = array.new_string()
|
||||
if barstate.isfirst and array.size(ALL_RES) == 0
|
||||
// 由低到高,便于筛选
|
||||
// 分钟
|
||||
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")
|
||||
|
||||
// ======================== 周期间关系与选择 ========================
|
||||
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)
|
||||
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)
|
||||
|
||||
// ======================== 计算各周期 EMA52 ========================
|
||||
// 预分配数值数组(保持固定最大长度)
|
||||
var float[] htfVals = array.new_float()
|
||||
var float[] ltfVals = array.new_float()
|
||||
var float[] htfLabelVals = array.new_float()
|
||||
var float[] ltfLabelVals = array.new_float()
|
||||
float ctfVal = na
|
||||
float ctfLabelVal = na
|
||||
if barstate.isfirst
|
||||
for _i = 0 to MAX_HTF - 1
|
||||
array.push(htfVals, na)
|
||||
array.push(htfLabelVals, na)
|
||||
for _j = 0 to MAX_LTF - 1
|
||||
array.push(ltfVals, na)
|
||||
array.push(ltfLabelVals, na)
|
||||
|
||||
// 填充长级别数值
|
||||
for i = 0 to MAX_HTF - 1
|
||||
float val = na
|
||||
float labelVal = na
|
||||
if enableHTF and i < htfCountSelected
|
||||
tfStr = array.get(htfRes, i)
|
||||
if f_showRes(tfStr)
|
||||
// 计算该长级别的 EMA52
|
||||
val := request.security(syminfo.tickerid, tfStr, ta.ema(close, 52), barmerge.gaps_off, barmerge.lookahead_off)
|
||||
// 标签不跟随虚线断续,仅跟随级别开关与可视区间
|
||||
labelVal := f_gate(f_smooth(val, smoothLenHTF))
|
||||
array.set(htfVals, i, val)
|
||||
array.set(htfLabelVals, i, labelVal)
|
||||
|
||||
// 填充次级别数值
|
||||
for i = 0 to MAX_LTF - 1
|
||||
float val = na
|
||||
float labelVal = na
|
||||
if enableLTF and i < ltfCountSelected
|
||||
tfStr = array.get(ltfSel, i)
|
||||
if f_showRes(tfStr)
|
||||
// 计算该次级别的 EMA52(低级别向上合成,注意其更频繁更新)
|
||||
val := request.security(syminfo.tickerid, tfStr, ta.ema(close, 52), barmerge.gaps_off, barmerge.lookahead_off)
|
||||
// 标签不跟随虚线断续,仅跟随级别开关与可视区间
|
||||
labelVal := f_gate(f_smooth(val, smoothLenLTF))
|
||||
array.set(ltfVals, i, val)
|
||||
array.set(ltfLabelVals, i, labelVal)
|
||||
|
||||
// 本级别 EMA52
|
||||
if enableCTF and f_showRes(curResStr)
|
||||
ctfVal := ta.ema(close, 52)
|
||||
ctfLabelVal := (enableCTF and f_showRes(curResStr)) ? f_gate(f_smooth(ctfVal, smoothLenCTF)) : na
|
||||
|
||||
// ======================== 绘制(虚线 + 标签) ========================
|
||||
// 顶层固定 plot(避免在局部/循环中调用 plot)
|
||||
plot((enableCTF and f_showRes(curResStr)) ? f_gate(f_smooth(ctfVal, smoothLenCTF)) : na, title='CTF EMA52', color=color.new(color.white, 0), linewidth=lineWidthCTF, style=plot.style_line)
|
||||
plot((enableHTF and 0 < htfCountSelected and not na(array.get(htfVals, 0))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 0), smoothLenHTF), 0 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 1', color=f_paletteColor(0), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 1 < htfCountSelected and not na(array.get(htfVals, 1))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 1), smoothLenHTF), 1 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 2', color=f_paletteColor(1), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 2 < htfCountSelected and not na(array.get(htfVals, 2))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 2), smoothLenHTF), 2 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 3', color=f_paletteColor(2), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 3 < htfCountSelected and not na(array.get(htfVals, 3))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 3), smoothLenHTF), 3 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 4', color=f_paletteColor(3), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 4 < htfCountSelected and not na(array.get(htfVals, 4))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 4), smoothLenHTF), 4 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 5', color=f_paletteColor(4), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 5 < htfCountSelected and not na(array.get(htfVals, 5))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 5), smoothLenHTF), 5 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 6', color=f_paletteColor(5), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 6 < htfCountSelected and not na(array.get(htfVals, 6))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 6), smoothLenHTF), 6 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 7', color=f_paletteColor(6), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 7 < htfCountSelected and not na(array.get(htfVals, 7))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 7), smoothLenHTF), 7 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 8', color=f_paletteColor(7), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 8 < htfCountSelected and not na(array.get(htfVals, 8))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 8), smoothLenHTF), 8 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 9', color=f_paletteColor(8), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 9 < htfCountSelected and not na(array.get(htfVals, 9))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 9), smoothLenHTF), 9 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 10', color=f_paletteColor(9), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 10 < htfCountSelected and not na(array.get(htfVals, 10))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 10), smoothLenHTF), 10 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 11', color=f_paletteColor(10), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
plot((enableHTF and 11 < htfCountSelected and not na(array.get(htfVals, 11))) ? f_gate(f_dash(f_smooth(array.get(htfVals, 11), smoothLenHTF), 11 * 2, dashLenHTF, dashGapHTF)) : na, title='HTF EMA52 12', color=f_paletteColor(11), linewidth=lineWidthHTF, style=plot.style_line)
|
||||
|
||||
plot((enableLTF and 0 < ltfCountSelected and not na(array.get(ltfVals, 0))) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 0), smoothLenLTF), 0 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF EMA52 1', color=color.new(f_paletteColor(0), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||||
plot((enableLTF and 1 < ltfCountSelected and not na(array.get(ltfVals, 1))) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 1), smoothLenLTF), 1 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF EMA52 2', color=color.new(f_paletteColor(1), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||||
plot((enableLTF and 2 < ltfCountSelected and not na(array.get(ltfVals, 2))) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 2), smoothLenLTF), 2 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF EMA52 3', color=color.new(f_paletteColor(2), 30), linewidth=lineWidthLTF, style=plot.style_line)
|
||||
plot((enableLTF and 3 < ltfCountSelected and not na(array.get(ltfVals, 3))) ? f_gate(f_dash(f_smooth(array.get(ltfVals, 3), smoothLenLTF), 3 * 3 + 1, dashLenLTF, dashGapLTF)) : na, title='LTF EMA52 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(htfLabelVals, i)
|
||||
col = f_paletteColor(i)
|
||||
txt = f_prettyTf(tfStr) + ' ' + str.tostring(v, format.mintick)
|
||||
// 与曲线显示条件同步:平滑后且可视区间内才显示标签
|
||||
if na(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(ltfLabelVals, i)
|
||||
base = f_paletteColor(i)
|
||||
col = color.new(base, 0)
|
||||
txt = f_prettyTf(tfStr) + ' ' + str.tostring(v, format.mintick)
|
||||
if na(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 and f_showRes(curResStr)
|
||||
v = ctfLabelVal
|
||||
col = color.new(color.white, 0)
|
||||
txt = f_prettyTf(curResStr) + ' ' + str.tostring(v, format.mintick)
|
||||
if na(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) 次级别(低于当前)EMA52 也计算并显示,更新频率更高,默认更淡。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user