1190 lines
90 KiB
Plaintext
1190 lines
90 KiB
Plaintext
|
||
// █▀▀▄ ──▀ █▀▀█ █▀▀█ █▀▀▀ █──█ █▀▄▀█
|
||
// █▀▀▄ ──█ █──█ █▄▄▀ █─▀█ █──█ █─▀─█
|
||
// ▀▀▀─ █▄█ ▀▀▀▀ ▀─▀▀ ▀▀▀▀ ─▀▀▀ ▀───▀
|
||
|
||
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
|
||
// © Bjorgum
|
||
|
||
//@version=6
|
||
indicator('BjorgumKeyLevels', 'BjKeyLevels', overlay = true, max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500)
|
||
|
||
import Bjorgum/BjCandlePatterns/3 as bj
|
||
|
||
// ================================== //
|
||
// ------------> 提示信息 <-------------- //
|
||
// ================================== //
|
||
|
||
leftTip = '向左查找摆动高低点的K线数量以形成枢轴点。数值越高,脚本向左查找最高/最低点的范围越大'
|
||
rightTip = '向右查找摆动高低点的K线数量以形成枢轴点。数值越高,脚本向右查找最高/最低点的范围越大'
|
||
nPivTip = '设置数组大小,即同时跟踪的枢轴点数量(x个高点和x个低点)'
|
||
atrLenTip = '平均K线数量。ATR用于标准化不同资产和时间框架之间的区域宽度'
|
||
multTip = 'ATR乘数设置区域宽度。默认为从区域底部到顶部的半个ATR'
|
||
perTip = '区域大小占价格的最大百分比。某些资产在低价位时可能过于波动,会创建不合理大小的区域'
|
||
maxTip = '历史跟踪蜡烛图形态的最大框数。注意:数值越高,由于同时允许的框元素数量限制,回顾时跟踪的枢轴区域越少'
|
||
futTip = '价格水平标签的偏移K线数'
|
||
srcTip = '枢轴点的源输入。默认跟踪HA蜡烛的最高和最低实体以平均价格行为,这可能导致水平位于支撑和阻力重叠区域'
|
||
alignZonesTip = '对齐边缘重叠现有区域的重复区域,创建随时间老化并在视觉上增强的区域'
|
||
extendTip = '向右延伸当前区域'
|
||
lLabTip = '显示从关键水平延伸的价格水平标签'
|
||
|
||
dhighsTip = '禁用将阻止跟踪高点'
|
||
dlowsTip = '禁用将阻止跟踪低点'
|
||
detectBOTip = '显示价格突破所有枢轴点的位置。显示来自下方的箭头'
|
||
detectBDTip = '显示价格跌破所有枢轴点的位置。显示来自上方的箭头'
|
||
breakUpTip = '显示价格突破阻力的位置。显示来自下方的箭头'
|
||
breakDnTip = '显示价格跌破支撑的位置。显示来自上方的箭头'
|
||
falseBullTip = '显示价格最初跌破支撑后反转的位置。假突破可能导致相反方向的快速移动(空头陷阱)。显示来自下方的大箭头'
|
||
falseBearTip = '显示价格最初突破阻力后反转的位置。假突破可能导致相反方向的快速移动(多头陷阱)。显示来自上方的大箭头'
|
||
supPushTip = '显示在支撑区域内检测到的上涨蜡烛。可以显示支撑被尊重的点。显示来自下方的三角形'
|
||
resPushTip = '显示在阻力区域内检测到的下跌蜡烛。可以显示阻力被尊重的点。显示来自上方的三角形'
|
||
curlTip = '当在关键区域范围内检测到蜡烛时显示Bjorgum TSI\'卷曲\'。可以显示关键水平的动量转换。(与Bjorgum TSI指标相关)'
|
||
|
||
// 添加标签大小配置的提示信息
|
||
labelSizeTip = '设置价格水平标签的字体大小'
|
||
|
||
repaintTip = '等待蜡烛结束后再检测形态。设为False将在确认前显示潜在形态'
|
||
labelsTip = '为检测到的蜡烛形态显示标签'
|
||
sBoxTip = '在检测到的蜡烛形态周围显示框'
|
||
dTip = '检测十字星蜡烛形态'
|
||
beTip = '检测吞没形态'
|
||
hsTip = '检测锤子线和流星线形态'
|
||
dgTip = '检测蜻蜓十字和墓碑十字形态'
|
||
twTip = '检测镊子顶和镊子底形态'
|
||
stTip = '检测纺锤顶形态'
|
||
pcTip = '检测刺透线和乌云盖顶形态'
|
||
bhTip = '检测孕线形态'
|
||
lsTip = '检测长上影线和长下影线形态'
|
||
|
||
ecWickTip = '确定吞没蜡烛是否必须吞没前一根蜡烛的影线或仅吞没实体'
|
||
colorMatchTip = '确定锤子线是否必须是阳线,流星线是否必须是阴线'
|
||
closeHalfTip = '确定镊子形态是否必须收盘超过前一根蜡烛的中点'
|
||
atrMaxTip = '设置蜡烛的最大尺寸(作为当前ATR的倍数)'
|
||
rejectWickTip = '形态解决蜡烛上拒绝影线允许的最大影线尺寸(占实体尺寸的百分比)。0禁用过滤器'
|
||
hammerFibTip = '锤子线和流星线的实体与蜡烛尺寸的关系(即实体占总蜡烛尺寸的33%)'
|
||
hsShadowPercTip = '允许的最大对立影线尺寸占实体尺寸的百分比(例如锤子形态的上影线等)'
|
||
hammerSizeTip = '锤子线、流星线或长影线的最小尺寸(ATR的倍数)。(用于过滤微小设置)'
|
||
dojiSizeTip = '实体与蜡烛尺寸的关系(即实体占总蜡烛尺寸的5%)'
|
||
dojiWickSizeTip = '相对于对立影线的最大影线尺寸。(例如2 = 下影线必须小于或等于上影线的2倍)'
|
||
luRatioTip = '上影线与整体蜡烛尺寸的关系,以百分比表示'
|
||
|
||
lookbackTip = '可包含在假突破信号中的蜡烛数量'
|
||
swingTip = '摆动检测用于过滤突破类型信号。数值越高意味着更重要的点,但数量更少'
|
||
reflectTip = '过滤以确保设置是重要的摆动点。回顾这么远'
|
||
offsetTip = '蜡烛形态高/低点与绝对摆动高/低点的距离。例如:0将过滤仅为最高/最低的形态,1过滤重要长度内的第二高等'
|
||
|
||
bullPivotTip = '看涨关键水平的颜色\n(边框,背景)'
|
||
bearPivotTip = '看跌关键水平的颜色\n(边框,背景)'
|
||
breakoutTip = '突破箭头的颜色\n(看涨,看跌)'
|
||
SnRTip = '支撑或阻力突破三角形的颜色\n(看涨,看跌)'
|
||
falseBreakTip = '假突破箭头的颜色\n(看涨,看跌,箭头最大高度像素)'
|
||
moveTip = '在区域内检测到的蜡烛三角形的颜色\n(看涨,看跌)'
|
||
patTip = '包围蜡烛图形态的框颜色\n背景:(看涨,中性,看跌)\n边框:(看涨,中性,看跌)'
|
||
labTip = '标记蜡烛图形态的标签颜色\n文本:(看涨,中性,看跌)\n标签:(看涨,中性,看跌)'
|
||
stratTip = 'TSI速度控制预设。两种速度都与Bjorgum TSI指标相关'
|
||
|
||
// ================================== //
|
||
// ---------> 用户输入 <----------- //
|
||
// ================================== //
|
||
|
||
left = input.int(20, '向左查找', group = '区域设置', tooltip = leftTip)
|
||
right = input.int(15, '向右查找', group = '区域设置', tooltip = rightTip)
|
||
nPiv = input.int(4, '枢轴点数量', group = '区域设置', tooltip = nPivTip)
|
||
atrLen = input.int(30, 'ATR长度', group = '区域设置', tooltip = atrLenTip)
|
||
mult = input.float(0.5, '区域宽度(ATR)', group = '区域设置', tooltip = multTip, step = 0.1)
|
||
per = input.float(5, '最大区域百分比', group = '区域设置', tooltip = perTip)
|
||
max = input.float(10, '形态最大框数', group = '区域设置', tooltip = maxTip)
|
||
fut = input.int(30, '标签偏移量', group = '区域设置', tooltip = futTip)
|
||
src = input.string('HA', '枢轴点源', group = '区域设置', tooltip = srcTip, options = ['HA', 'High/Low Body', 'High/Low'])
|
||
alignZones = input.bool(true, '对齐区域', group = '区域设置', tooltip = alignZonesTip)
|
||
extend = input.bool(false, '向右延伸', group = '区域设置', tooltip = extendTip)
|
||
lLab = input.bool(false, '显示水平标签', group = '区域设置', tooltip = lLabTip)
|
||
|
||
dhighs = input.bool(true, '检测枢轴高点', group = '检测设置', tooltip = dhighsTip)
|
||
dlows = input.bool(true, '检测枢轴低点', group = '检测设置', tooltip = dlowsTip)
|
||
detectBO = input.bool(false, '检测突破', group = '检测设置', tooltip = detectBOTip)
|
||
detectBD = input.bool(false, '检测跌破', group = '检测设置', tooltip = detectBDTip)
|
||
breakUp = input.bool(false, '检测阻力突破', group = '检测设置', tooltip = breakUpTip)
|
||
breakDn = input.bool(false, '检测支撑跌破', group = '检测设置', tooltip = breakDnTip)
|
||
falseBull = input.bool(false, '检测假跌破', group = '检测设置', tooltip = falseBullTip)
|
||
falseBear = input.bool(false, '检测假突破', group = '检测设置', tooltip = falseBearTip)
|
||
supPush = input.bool(false, '检测支撑反弹', group = '检测设置', tooltip = supPushTip)
|
||
resPush = input.bool(false, '检测阻力回落', group = '检测设置', tooltip = resPushTip)
|
||
curl = input.bool(false, '检测TSI卷曲', group = '检测设置', tooltip = curlTip)
|
||
|
||
repaint = input.bool(true, '等待确认K线', group = '蜡烛形态', tooltip = repaintTip)
|
||
labels = input.bool(false, '显示标签', group = '蜡烛形态', tooltip = labelsTip)
|
||
sBox = input.bool(false, '显示形态框', group = '蜡烛形态', tooltip = sBoxTip)
|
||
d_ = input.bool(false, '检测十字星', group = '蜡烛形态', tooltip = dTip)
|
||
be_ = input.bool(false, '检测吞没形态', group = '蜡烛形态', tooltip = beTip)
|
||
hs_ = input.bool(false, '检测锤子线和流星线', group = '蜡烛形态', tooltip = hsTip)
|
||
dg_ = input.bool(false, '检测蜻蜓和墓碑十字', group = '蜡烛形态', tooltip = dgTip)
|
||
tw_ = input.bool(false, '检测镊子形态', group = '蜡烛形态', tooltip = twTip)
|
||
st_ = input.bool(false, '检测纺锤顶', group = '蜡烛形态', tooltip = stTip)
|
||
pc_ = input.bool(false, '检测刺透线和乌云盖顶', group = '蜡烛形态', tooltip = pcTip)
|
||
bh_ = input.bool(false, '检测孕线', group = '蜡烛形态', tooltip = bhTip)
|
||
ls_ = input.bool(false, '检测长影线', group = '蜡烛形态', tooltip = lsTip)
|
||
|
||
alertMode = input.string(alert.freq_once_per_bar_close, '警报模式', group = '警报频率', options = [alert.freq_once_per_bar, alert.freq_once_per_bar_close])
|
||
|
||
ecWick = input.bool(false, '吞没必须包含影线', group = '蜡烛过滤器', tooltip = ecWickTip)
|
||
colorMatch = input.bool(false, '锤子线必须匹配颜色', group = '蜡烛过滤器', tooltip = colorMatchTip)
|
||
closeHalf = input.bool(false, '镊子收盘超过一半', group = '蜡烛过滤器', tooltip = closeHalfTip)
|
||
atrMax = input.float(0.0, '最大蜡烛尺寸(× ATR)', group = '蜡烛过滤器', tooltip = atrMaxTip, step = 0.1)
|
||
rejectWickMax = input.float(0.0, '[吞没]最大拒绝影线尺寸', group = '蜡烛过滤器', tooltip = rejectWickTip, step = 1)
|
||
hammerFib = input.float(33, '[锤子]锤子线比例(%)', group = '蜡烛过滤器', tooltip = hammerFibTip, step = 1)
|
||
hsShadowPerc = input.float(5, '[锤子]对立影线百分比(%)', group = '蜡烛过滤器', tooltip = hsShadowPercTip, step = 1)
|
||
hammerSize = input.float(0.1, '[锤子]最小尺寸(× ATR)', group = '蜡烛过滤器', tooltip = hammerSizeTip, step = 0.1)
|
||
dojiSize = input.float(5, '[十字]十字星尺寸(%)', group = '蜡烛过滤器', tooltip = dojiSizeTip, step = 1)
|
||
dojiWickSize = input.float(2, '[十字]最大影线尺寸', group = '蜡烛过滤器', tooltip = dojiWickSizeTip, step = 1)
|
||
luRatio = input.float(75, '[长影]长影线比例(%)', group = '蜡烛过滤器', tooltip = luRatioTip, step = 1)
|
||
|
||
lookback = input.int(2, '突破回顾期', group = '回顾设置', tooltip = lookbackTip)
|
||
swing = input.int(5, '摆动高低点', group = '回顾设置', tooltip = swingTip)
|
||
reflect = input.int(10, '重要高低点', group = '回顾设置', tooltip = reflectTip)
|
||
offset = input.int(1, '距离高低点K线数', group = '回顾设置', tooltip = offsetTip)
|
||
|
||
// 添加标签大小配置
|
||
labelSize = input.string('small', '标签字体大小', group = '显示设置', tooltip = labelSizeTip, options = ['tiny', 'small', 'normal', 'large', 'huge'])
|
||
|
||
bullBorder = input.color(color.new(#64b5f6, 60), '', inline = '0', group = '枢轴颜色')
|
||
bullBgCol = input.color(color.new(#64b5f6, 95), '', inline = '0', group = '枢轴颜色', tooltip = bullPivotTip)
|
||
bearBorder = input.color(color.new(#ffeb3b, 60), '', inline = '1', group = '枢轴颜色')
|
||
bearBgCol = input.color(color.new(#ffeb3b, 95), '', inline = '1', group = '枢轴颜色', tooltip = bearPivotTip)
|
||
|
||
upCol = input.color(color.new(#ff6d00, 25), '', inline = '2', group = '突破颜色')
|
||
dnCol = input.color(color.new(#ff00ff, 25), '', inline = '2', group = '突破颜色', tooltip = breakoutTip)
|
||
|
||
supCol = input.color(color.new(#17ff00, 25), '', inline = '3', group = '支撑阻力突破颜色')
|
||
resCol = input.color(color.new(#ff0000, 25), '', inline = '3', group = '支撑阻力突破颜色', tooltip = SnRTip)
|
||
|
||
fBull = input.color(color.new(#17ff00, 25), '', inline = '4', group = '假突破颜色')
|
||
fBear = input.color(color.new(#ff0000, 25), '', inline = '4', group = '假突破颜色')
|
||
arrowMax = input.int(75, '', inline = '4', group = '假突破颜色', tooltip = falseBreakTip)
|
||
|
||
moveBullCol = input.color(color.new(#64b5f6, 25), '', inline = '5', group = '支撑阻力反弹颜色')
|
||
moveBearCol = input.color(color.new(#ffeb3b, 25), '', inline = '5', group = '支撑阻力反弹颜色', tooltip = moveTip)
|
||
|
||
curlBullCol = input.color(color.new(#17ff00, 40), '', inline = '6', group = '动量卷曲颜色')
|
||
curlBearCol = input.color(color.new(#f3ff00, 40), '', inline = '6', group = '动量卷曲颜色', tooltip = curlTip)
|
||
|
||
patBullBg = input.color(color.new(#17ff00, 90), '', inline = '7', group = '形态框颜色')
|
||
patNeutBg = input.color(color.new(#b2b5be, 90), '', inline = '7', group = '形态框颜色')
|
||
patBearBg = input.color(color.new(#ff0000, 90), '', inline = '7', group = '形态框颜色')
|
||
patBullBo = input.color(color.new(#17ff00, 80), '', inline = '8', group = '形态框颜色')
|
||
patNeutBo = input.color(color.new(#b2b5be, 80), '', inline = '8', group = '形态框颜色')
|
||
patBearBo = input.color(color.new(#ff0000, 80), '', inline = '8', group = '形态框颜色', tooltip = patTip)
|
||
|
||
textBullCol = input.color(color.new(#17ff00, 0), '', inline = '9', group = '标签颜色(文本/背景)')
|
||
textNeutCol = input.color(color.new(#b2b5be, 0), '', inline = '9', group = '标签颜色(文本/背景)')
|
||
textBearCol = input.color(color.new(#ff0000, 0), '', inline = '9', group = '标签颜色(文本/背景)')
|
||
labBullCol = input.color(color.new(#17ff00, 80), '', inline = '10', group = '标签颜色(文本/背景)')
|
||
labNeutCol = input.color(color.new(#b2b5be, 80), '', inline = '10', group = '标签颜色(文本/背景)')
|
||
labBearCol = input.color(color.new(#ff0000, 80), '', inline = '10', group = '标签颜色(文本/背景)', tooltip = labTip)
|
||
|
||
strat = input.string('Fast', '选择速度', group = 'TSI速度控制', tooltip = stratTip, options = ['Fast', 'Slow'])
|
||
|
||
longf = input.int(25, '长周期长度', group = 'TSI快速设置')
|
||
shortf = input.int(5, '短周期长度', group = 'TSI快速设置')
|
||
signalf = input.int(14, '信号长度', group = 'TSI快速设置')
|
||
|
||
longs = input.int(25, '长周期长度', group = 'TSI慢速设置')
|
||
shorts = input.int(13, '短周期长度', group = 'TSI慢速设置')
|
||
signals = input.int(13, '信号长度', group = 'TSI慢速设置')
|
||
|
||
// ================================== //
|
||
// -----> 不可变常量 <------ //
|
||
// ================================== //
|
||
|
||
sync = bar_index
|
||
labUp = label.style_label_up
|
||
labDn = label.style_label_down
|
||
confirmed = barstate.isconfirmed
|
||
extrap = extend ? extend.right : extend.none
|
||
|
||
// 标签大小常量定义
|
||
labelSizeValue = labelSize == 'tiny' ? size.tiny : labelSize == 'small' ? size.small : labelSize == 'normal' ? size.normal : labelSize == 'large' ? size.large : size.huge
|
||
|
||
var pivotHigh = array.new_box(nPiv)
|
||
var pivotLows = array.new_box(nPiv)
|
||
var highBull = array.new_bool(nPiv)
|
||
var lowsBull = array.new_bool(nPiv)
|
||
var boxes = array.new_box()
|
||
|
||
haSrc = src == 'HA'
|
||
hiLoSrc = src == 'High/Low'
|
||
tsifast = strat == 'Fast'
|
||
tsislow = strat == 'Slow'
|
||
|
||
// ================================== //
|
||
// ---> Functional Declarations <---- //
|
||
// ================================== //
|
||
|
||
atr = ta.atr(atrLen)
|
||
perMax = close * 0.02
|
||
min = math.min(perMax, atr * 0.3)
|
||
|
||
_haBody() =>
|
||
haClose = (open + high + low + close) / 4
|
||
haOpen = float(na)
|
||
haOpen := na(haOpen[1]) ? (open + close) / 2 : (nz(haOpen[1]) + nz(haClose[1])) / 2
|
||
|
||
[haOpen, haClose]
|
||
|
||
_extend(_x) =>
|
||
for i = 0 to array.size(_x) - 1 by 1
|
||
box.set_right(array.get(_x, i), sync)
|
||
|
||
_arrayLoad(_x, _max, _val) =>
|
||
array.unshift(_x, _val)
|
||
if array.size(_x) > _max
|
||
array.pop(_x)
|
||
|
||
_arrayBox(_x, _max, _val) =>
|
||
array.unshift(_x, _val)
|
||
if array.size(_x) > _max
|
||
_b = array.pop(_x)
|
||
if extend
|
||
box.set_extend(_b, extend.none)
|
||
|
||
_arrayWrap(_x, _max, _val) =>
|
||
array.unshift(_x, _val)
|
||
if array.size(_x) > _max
|
||
box.delete(array.pop(_x))
|
||
|
||
_delLab(_x) =>
|
||
if array.size(_x) > 0
|
||
label.delete(array.pop(_x))
|
||
|
||
_delLine(_x) =>
|
||
if array.size(_x) > 0
|
||
line.delete(array.pop(_x))
|
||
|
||
_delLevels(_x, _y) =>
|
||
for i = 0 to array.size(_x) - 1 by 1
|
||
_delLab(_x)
|
||
_delLine(_y)
|
||
|
||
_box(_x1, _t, _r, _b, _boCol, _bgCol, _e) =>
|
||
box.new(_x1, _t, _r, _b, xloc = xloc.bar_index, extend = _e, border_color = _boCol, bgcolor = _bgCol)
|
||
|
||
_wrap(_cond, _x, _bb, _bc, _bgc) =>
|
||
_t = ta.highest(high, _bb) + min
|
||
_b = ta.lowest(low, _bb) - min
|
||
_l = bar_index - _bb
|
||
_r = bar_index + 1
|
||
if _cond
|
||
_arrayWrap(_x, max, _box(_l, _t, _r, _b, _bc, _bgc, extend.none))
|
||
|
||
_getBox(_x, _i) =>
|
||
_box = array.get(_x, _i)
|
||
_t = box.get_top(_box)
|
||
_b = box.get_bottom(_box)
|
||
[_t, _b]
|
||
|
||
_align(_x, _y) =>
|
||
for i = 0 to array.size(_x) - 1 by 1
|
||
[_T, _B] = _getBox(_y, 0)
|
||
[_t, _b] = _getBox(_x, i)
|
||
if _T > _b and _T < _t or _B < _t and _B > _b or _T > _t and _B < _b or _B > _b and _T < _t
|
||
box.set_top(array.get(_y, 0), _t)
|
||
box.set_bottom(array.get(_y, 0), _b)
|
||
|
||
_color(_x, _y) =>
|
||
var int _track = nPiv
|
||
for i = 0 to array.size(_x) - 1 by 1
|
||
[t_, b_] = _getBox(_x, i)
|
||
_isBull = array.get(_y, i)
|
||
if close > t_ and not _isBull
|
||
box.set_extend(array.get(_x, i), extend.none)
|
||
array.set(_x, i, _box(sync, t_, sync, b_, bullBorder, bullBgCol, extrap))
|
||
array.set(_y, i, true)
|
||
_track := _track + 1
|
||
_track
|
||
if close < b_ and _isBull
|
||
box.set_extend(array.get(_x, i), extend.none)
|
||
array.set(_x, i, _box(sync, t_, sync, b_, bearBorder, bearBgCol, extrap))
|
||
array.set(_y, i, false)
|
||
_track := _track - 1
|
||
_track
|
||
_track
|
||
|
||
_detect(_x, _y) =>
|
||
int _i = 0
|
||
bool _found = false
|
||
bool _isBull = false
|
||
while not _found and _i < array.size(_x)
|
||
[t_, b_] = _getBox(_x, _i)
|
||
if low < t_ and high > b_
|
||
_isBull := array.get(_y, _i)
|
||
_found := true
|
||
_found
|
||
_i := _i + 1
|
||
_i
|
||
[_found, _isBull]
|
||
|
||
_falseBreak(_l) =>
|
||
bool _d = false
|
||
bool _u = false
|
||
for i = 1 to lookback by 1
|
||
if _l[i] < _l and _l[i + 1] >= _l and _l[1] < _l
|
||
_d := true
|
||
_d
|
||
if _l[i] > _l and _l[i + 1] <= _l and _l[1] > _l
|
||
_u := true
|
||
_u
|
||
[_d, _u]
|
||
|
||
_numLevel(_x, _y) =>
|
||
int _above = 0
|
||
int _fill = 0
|
||
for i = 0 to array.size(_x) - 1 by 1
|
||
if i < array.size(_x)
|
||
_isBull = array.get(_x, i)
|
||
if _isBull == true
|
||
_above := _above + 1
|
||
_above
|
||
if _isBull == true or _isBull == false // Only count if it's a valid boolean (not na)
|
||
_fill := _fill + 1
|
||
_fill
|
||
for i = 0 to array.size(_y) - 1 by 1
|
||
if i < array.size(_y)
|
||
_isBull = array.get(_y, i)
|
||
if _isBull == true
|
||
_above := _above + 1
|
||
_above
|
||
if _isBull == true or _isBull == false // Only count if it's a valid boolean (not na)
|
||
_fill := _fill + 1
|
||
_fill
|
||
[_above, _fill]
|
||
|
||
_check(_src, _l) =>
|
||
bool _check = false
|
||
for i = 0 to _l by 1
|
||
if _src[i]
|
||
_check := true
|
||
_check
|
||
_check
|
||
|
||
_count(_src, _l) =>
|
||
int _result = 0
|
||
for i = 0 to _l by 1
|
||
if _src > _src[i]
|
||
_result := _result + 1
|
||
_result
|
||
_result
|
||
|
||
// 修改 _label 函数
|
||
// 添加 x_offset_adjust 参数,默认为0
|
||
_label(_x, _y, y_price, _s, _col1, _col2, x_offset_adjust = 0) =>
|
||
transp = math.min(color.t(_col1), color.t(_col2))
|
||
// 将 x_offset_adjust 添加到标签和线的 x 坐标计算中
|
||
label_x_position = sync + fut + x_offset_adjust
|
||
line_x2_position = sync + fut + x_offset_adjust
|
||
|
||
array.unshift(_x, label.new(label_x_position, y_price, text = str.tostring(math.round_to_mintick(y_price)), color = color.new(_col1, transp), style = _s, textcolor = color.white, size = labelSizeValue))
|
||
if not extend and fut > 0 // 只有当 fut > 0 且不向右无限延长时才绘制连接线
|
||
// 线的起点是 sync (当前K线),终点是标签的 x 位置
|
||
array.unshift(_y, line.new(sync, y_price, line_x2_position, y_price, color = color.new(_col1, transp)))
|
||
|
||
// 修改 _level 函数
|
||
// 添加 isHighPivotZone 参数 (true 表示是 pivotHigh 区域, false 表示是 pivotLows 区域)
|
||
_level(_x, _y, isHighPivotZone) =>
|
||
var array<label> lab = array.new_label()
|
||
var array<line> lines = array.new_line()
|
||
|
||
if barstate.islast and lLab
|
||
while array.size(lab) > 0
|
||
label.delete(array.pop(lab))
|
||
while array.size(lines) > 0
|
||
line.delete(array.pop(lines))
|
||
|
||
for i = 0 to array.size(_x) - 1 by 1
|
||
current_box_id = array.get(_x, i)
|
||
if not na(current_box_id)
|
||
[_t, _b] = _getBox(_x, i)
|
||
_isBull_val = array.get(_y, i)
|
||
bool currentIsBull = _isBull_val != true and _isBull_val != false ? isHighPivotZone ? false : true : _isBull_val // pivotHigh 默认为熊区(false), pivotLows默认为牛区(true)
|
||
|
||
_col1 = currentIsBull ? bullBgCol : bearBgCol
|
||
_col2 = currentIsBull ? bullBorder : bearBorder
|
||
|
||
// 定义错开的偏移量
|
||
// 可以根据需要调整这些值,甚至可以将它们作为输入参数
|
||
int top_label_offset_adj = 0
|
||
int bottom_label_offset_adj = 0
|
||
|
||
if isHighPivotZone // 如果是阻力区 (来自 pivotHigh)
|
||
// 阻力区的顶线标签稍微向左偏一点 (或不偏),底线标签向右偏一点
|
||
top_label_offset_adj := 0 // 例如,顶部标签不额外偏移或轻微向左
|
||
bottom_label_offset_adj := 2 // 例如,底部标签向右偏移2个单位(K线)
|
||
bottom_label_offset_adj
|
||
// 如果是支撑区 (来自 pivotLows)
|
||
else // 支撑区的顶线标签稍微向右偏一点,底线标签向左偏一点 (或不偏)
|
||
top_label_offset_adj := 2 // 例如,顶部标签向右偏移2个单位
|
||
bottom_label_offset_adj := 0 // 例如,底部标签不额外偏移或轻微向左
|
||
bottom_label_offset_adj
|
||
|
||
// 另一种错开方式:都向右偏,但偏移量不同
|
||
// if isHighPivotZone
|
||
// top_label_offset_adj = 0
|
||
// bottom_label_offset_adj = 1 // 阻力区底部标签偏移量小
|
||
// else
|
||
// top_label_offset_adj = 2 // 支撑区顶部标签偏移量大
|
||
// bottom_label_offset_adj = 3
|
||
|
||
|
||
// 绘制顶线标签
|
||
_label(lab, lines, _t, labDn, _col1, _col2, top_label_offset_adj)
|
||
|
||
// 绘制底线标签
|
||
_label(lab, lines, _b, labUp, _col1, _col2, bottom_label_offset_adj)
|
||
|
||
_alert(_x, _y) =>
|
||
if _x
|
||
alert(_y + timeframe.period + ' chart. Price is ' + str.tostring(close), alertMode)
|
||
|
||
// ================================== //
|
||
// ----> Variable Calculations <----- //
|
||
// ================================== //
|
||
|
||
shortvar = tsifast ? shortf : shorts
|
||
longvar = tsifast ? longf : longs
|
||
signalvar = tsifast ? signalf : signals
|
||
|
||
tsi = ta.tsi(close, shortvar, longvar)
|
||
tsl = ta.ema(tsi, signalvar)
|
||
|
||
highest = close == ta.highest(close, right)
|
||
lowest = close == ta.lowest(close, right)
|
||
|
||
closeLows = ta.lowest(close, swing)
|
||
closeHigh = ta.highest(close, swing)
|
||
|
||
numLows = _count(low, reflect)
|
||
numHigh = _count(high, reflect)
|
||
|
||
[open_, close_] = _haBody()
|
||
|
||
hiHaBod = math.max(close_, open_)
|
||
loHaBod = math.min(close_, open_)
|
||
|
||
hiBod = math.max(close, open)
|
||
loBod = math.min(close, open)
|
||
|
||
srcHigh = haSrc ? hiHaBod : hiLoSrc ? high : hiBod
|
||
srcLow = haSrc ? loHaBod : hiLoSrc ? low : loBod
|
||
|
||
pivot_high = ta.pivothigh(srcHigh, left, right)
|
||
pivot_low = ta.pivotlow(srcLow, left, right)
|
||
|
||
perc = close * (per / 100)
|
||
|
||
band = math.min(atr * mult, perc)[right] / 2
|
||
|
||
HH = pivot_high + band
|
||
HL = pivot_high - band
|
||
|
||
LH = pivot_low + band
|
||
LL = pivot_low - band
|
||
|
||
coDiff = close - open
|
||
|
||
// ================================== //
|
||
// --------> Logical Order <--------- //
|
||
// ================================== //
|
||
|
||
if not na(pivot_high) and dhighs and confirmed
|
||
_arrayLoad(highBull, nPiv, false)
|
||
_arrayBox(pivotHigh, nPiv, _box(sync[right], HH, sync, HL, bearBorder, bearBgCol, extrap))
|
||
|
||
if not na(pivot_low) and dlows and confirmed
|
||
_arrayLoad(lowsBull, nPiv, true)
|
||
_arrayBox(pivotLows, nPiv, _box(sync[right], LH, sync, LL, bullBorder, bullBgCol, extrap))
|
||
|
||
if alignZones
|
||
_align(pivotHigh, pivotHigh)
|
||
_align(pivotHigh, pivotLows)
|
||
_align(pivotLows, pivotLows)
|
||
_align(pivotLows, pivotHigh)
|
||
|
||
_extend(pivotHigh)
|
||
_extend(pivotLows)
|
||
|
||
trackHigh = _color(pivotHigh, highBull)
|
||
trackLows = _color(pivotLows, lowsBull)
|
||
|
||
// ================================== //
|
||
// ----> Conditional Parameters <---- //
|
||
// ================================== //
|
||
|
||
isLows = closeLows == close
|
||
isHigh = closeHigh == close
|
||
|
||
wasLows = _check(isLows, lookback)
|
||
wasHigh = _check(isHigh, lookback)
|
||
|
||
[above, total] = _numLevel(highBull, lowsBull)
|
||
|
||
moveAbove = trackHigh > trackHigh[1]
|
||
moveBelow = trackLows < trackLows[1]
|
||
|
||
resBreak = trackLows > trackLows[1] or moveAbove
|
||
supBreak = trackHigh < trackHigh[1] or moveBelow
|
||
|
||
breakOut = moveAbove and highest and above == total
|
||
breakDwn = moveBelow and lowest and above == 0
|
||
|
||
[dh, uh] = _falseBreak(trackHigh)
|
||
[dl, ul] = _falseBreak(trackLows)
|
||
|
||
falseBreakBull = wasLows and (dh or dl)
|
||
falseBreakBear = wasHigh and (uh or ul)
|
||
|
||
[fh, hb] = _detect(pivotHigh, highBull)
|
||
[fl, lb] = _detect(pivotLows, lowsBull)
|
||
|
||
bull = (fh or fl) and (hb or lb)
|
||
bear = (fh or fl) and not(hb or lb)
|
||
|
||
bullCheck = not resBreak and not resBreak[1] and (fh or fl) and close > open and (hb or lb)
|
||
bearCheck = not supBreak and not supBreak[1] and (fh or fl) and close < open and not(hb or lb)
|
||
|
||
highrange = reflect - offset
|
||
lowsrange = offset
|
||
|
||
sigLows = numLows <= lowsrange
|
||
sigHigh = numHigh >= highrange
|
||
|
||
isBull1 = sigLows and bull
|
||
isBear1 = sigHigh and bear
|
||
|
||
isBull2 = (sigLows or sigLows[1]) and (bull or bull[1])
|
||
isBear2 = (sigHigh or sigHigh[1]) and (bear or bear[1])
|
||
|
||
data = tsi > tsi[1] and tsi < tsl
|
||
dtat = tsi < tsi[1] and tsi > tsl
|
||
|
||
hMatch = not colorMatch or close > open
|
||
sMatch = not colorMatch or close < open
|
||
|
||
hsFilter = bj.barRange() >= hammerSize * atr
|
||
atrMaxSize = bj.barRange() <= atrMax * atr or atrMax == 0.0
|
||
|
||
rp = confirmed or not repaint
|
||
|
||
// ================================== //
|
||
// -----> Pattern Recognition <------ //
|
||
// ================================== //
|
||
|
||
dw = isBull1 and rp and d_ and atrMaxSize and bj.doji(dojiSize = dojiSize, dojiWickSize = dojiWickSize)
|
||
db = isBear1 and rp and d_ and atrMaxSize and bj.doji(dojiSize = dojiSize, dojiWickSize = dojiWickSize)
|
||
bew = isBull2 and rp and be_ and atrMaxSize and bj.bullEngulf(maxRejectWick = rejectWickMax, mustEngulfWick = ecWick)
|
||
beb = isBear2 and rp and be_ and atrMaxSize and bj.bearEngulf(maxRejectWick = rejectWickMax, mustEngulfWick = ecWick)
|
||
h = isBull1 and rp and hs_ and atrMaxSize and bj.hammer(ratio = hammerFib, shadowPercent = hsShadowPerc) and hsFilter and hMatch
|
||
ss = isBear1 and rp and hs_ and atrMaxSize and bj.star(ratio = hammerFib, shadowPercent = hsShadowPerc) and hsFilter and sMatch
|
||
dd = isBull1 and rp and dg_ and atrMaxSize and bj.dragonflyDoji()
|
||
gd = isBear1 and rp and dg_ and atrMaxSize and bj.gravestoneDoji()
|
||
tb = isBull2 and rp and tw_ and atrMaxSize and bj.tweezerBottom(closeUpperHalf = closeHalf)
|
||
tt = isBear2 and rp and tw_ and atrMaxSize and bj.tweezerTop(closeLowerHalf = closeHalf)
|
||
stw = isBull1 and rp and st_ and atrMaxSize and bj.spinningTop()
|
||
stb = isBear1 and rp and st_ and atrMaxSize and bj.spinningTop()
|
||
p = isBull1 and rp and pc_ and atrMaxSize and bj.piercing()
|
||
dcc = isBear1 and rp and pc_ and atrMaxSize and bj.darkCloudCover()
|
||
bhw = isBull1 and rp and bh_ and atrMaxSize and bj.haramiBull()
|
||
bhb = isBear1 and rp and bh_ and atrMaxSize and bj.haramiBear()
|
||
ll = isBull1 and rp and ls_ and atrMaxSize and bj.lls(ratio = luRatio) and hsFilter
|
||
lu = isBear1 and rp and ls_ and atrMaxSize and bj.lus(ratio = luRatio) and hsFilter
|
||
|
||
// ================================== //
|
||
// ------> Graphical Display <------- //
|
||
// ================================== //
|
||
|
||
// 添加显示警报名称的输入选项
|
||
showAlertNames = input.bool(true, '显示警报名称', group = '警报标签设置')
|
||
alertTextSize = input.string('tiny', '警报名称字体大小', group = '警报标签设置', options = ['tiny', 'small', 'normal'])
|
||
|
||
plotFalseDn = falseBull and falseBreakBull
|
||
plotFalseUp = falseBear and falseBreakBear
|
||
|
||
falseUpCol = plotFalseUp ? upCol : na
|
||
falseDnCol = plotFalseDn ? dnCol : na
|
||
|
||
plotBreakOut = breakOut and detectBO and not plotFalseDn
|
||
plotBreakDn = breakDwn and detectBD and not plotFalseUp
|
||
|
||
plotResBreak = resBreak and breakUp and not(plotBreakOut or plotFalseDn)
|
||
plotSupBreak = supBreak and breakDn and not(plotBreakDn or plotFalseUp)
|
||
|
||
plotBullCheck = bullCheck and supPush
|
||
plotBearCheck = bearCheck and resPush
|
||
|
||
plotCurlBull = curl and data and bull
|
||
plotCurlBear = curl and dtat and bear
|
||
|
||
// 获取字体大小
|
||
textSizeValue = alertTextSize == 'tiny' ? size.tiny : alertTextSize == 'small' ? size.small : size.normal
|
||
|
||
plotarrow(plotFalseUp ? coDiff : na, colorup = fBull, colordown = fBear, maxheight = arrowMax)
|
||
plotarrow(plotFalseDn ? coDiff : na, colorup = fBull, colordown = fBear, maxheight = arrowMax)
|
||
|
||
plotshape(plotBreakOut, style = shape.arrowup, location = location.belowbar, color = upCol, size = size.small)
|
||
plotshape(plotBreakDn, style = shape.arrowdown, location = location.abovebar, color = dnCol, size = size.small)
|
||
|
||
plotshape(plotResBreak, style = shape.arrowup, location = location.belowbar, color = supCol, size = size.small)
|
||
plotshape(plotSupBreak, style = shape.arrowdown, location = location.abovebar, color = resCol, size = size.small)
|
||
|
||
plotshape(plotBullCheck, style = shape.triangleup, location = location.belowbar, color = moveBullCol)
|
||
plotshape(plotBearCheck, style = shape.triangledown, location = location.abovebar, color = moveBearCol)
|
||
|
||
plotshape(plotCurlBull, style = shape.triangleup, location = location.belowbar, color = curlBullCol)
|
||
plotshape(plotCurlBear, style = shape.triangledown, location = location.abovebar, color = curlBearCol)
|
||
|
||
// 添加警报名称标签
|
||
if showAlertNames
|
||
// 假突破警报标签
|
||
if plotFalseUp
|
||
label.new(bar_index, high + atr * 0.3, '假突破↑', style = label.style_none, textcolor = fBull, size = labelSizeValue)
|
||
if plotFalseDn
|
||
label.new(bar_index, low - atr * 0.3, '假突破↓', style = label.style_none, textcolor = fBear, size = labelSizeValue)
|
||
|
||
// 突破警报标签
|
||
if plotBreakOut
|
||
label.new(bar_index, low - atr * 0.2, '突破', style = label.style_none, textcolor = upCol, size = labelSizeValue)
|
||
if plotBreakDn
|
||
label.new(bar_index, high + atr * 0.2, '跌破', style = label.style_none, textcolor = dnCol, size = labelSizeValue)
|
||
|
||
// 阻力/支撑突破标签
|
||
if plotResBreak
|
||
label.new(bar_index, low - atr * 0.2, '阻力突破', style = label.style_none, textcolor = supCol, size = labelSizeValue)
|
||
if plotSupBreak
|
||
label.new(bar_index, high + atr * 0.2, '支撑跌破', style = label.style_none, textcolor = resCol, size = labelSizeValue)
|
||
|
||
// 支撑阻力反弹标签
|
||
if plotBullCheck
|
||
label.new(bar_index, low - atr * 0.15, '支撑反弹', style = label.style_none, textcolor = moveBullCol, size = labelSizeValue)
|
||
if plotBearCheck
|
||
label.new(bar_index, high + atr * 0.15, '阻力回落', style = label.style_none, textcolor = moveBearCol, size = labelSizeValue)
|
||
|
||
// TSI动量转向标签
|
||
if plotCurlBull
|
||
label.new(bar_index, low - atr * 0.1, '动量转多', style = label.style_none, textcolor = curlBullCol, size = labelSizeValue)
|
||
if plotCurlBear
|
||
label.new(bar_index, high + atr * 0.1, '动量转空', style = label.style_none, textcolor = curlBearCol, size = labelSizeValue)
|
||
|
||
bj.dLab(dw and labels, labNeutCol, textNeutCol)
|
||
_wrap(dw and sBox, boxes, 1, patNeutBo, patNeutBg)
|
||
bj.bewLab(bew and labels, labBullCol, textBullCol)
|
||
_wrap(bew and sBox, boxes, 2, patBullBo, patBullBg)
|
||
bj.hLab(h and labels, labBullCol, textBullCol)
|
||
_wrap(h and sBox, boxes, 1, patBullBo, patBullBg)
|
||
bj.ddLab(dd and labels, labBullCol, textBullCol)
|
||
_wrap(dd and sBox, boxes, 1, patBullBo, patBullBg)
|
||
bj.tbLab(tb and labels, labBullCol, textBullCol)
|
||
_wrap(tb and sBox, boxes, 2, patBullBo, patBullBg)
|
||
bj.stwLab(stw and labels, labNeutCol, textNeutCol)
|
||
_wrap(stw and sBox, boxes, 1, patBullBo, patNeutBg)
|
||
bj.pLab(p and labels, labBullCol, textBullCol)
|
||
_wrap(p and sBox, boxes, 2, patBullBo, patBullBg)
|
||
bj.hwLab(bhw and labels, labBullCol, textBullCol)
|
||
_wrap(bhw and sBox, boxes, 2, patBullBo, patBullBg)
|
||
bj.llsLab(ll and labels, labBullCol, textBullCol)
|
||
_wrap(ll and sBox, boxes, 1, patBullBo, patBullBg)
|
||
|
||
bj.dLab(db and labels, labNeutCol, textNeutCol)
|
||
_wrap(db and sBox, boxes, 1, patNeutBo, patNeutBg)
|
||
bj.bebLab(beb and labels, labBearCol, textBearCol)
|
||
_wrap(beb and sBox, boxes, 2, patBearBo, patBearBg)
|
||
bj.ssLab(ss and labels, labBearCol, textBearCol)
|
||
_wrap(ss and sBox, boxes, 1, patBearBo, patBearBg)
|
||
bj.gdLab(gd and labels, labBearCol, textBearCol)
|
||
_wrap(gd and sBox, boxes, 1, patBearBo, patBearBg)
|
||
bj.ttLab(tt and labels, labBearCol, textBearCol)
|
||
_wrap(tt and sBox, boxes, 2, patBearBo, patBearBg)
|
||
bj.stbLab(stb and labels, labNeutCol, textNeutCol)
|
||
_wrap(stb and sBox, boxes, 1, patBearBo, patBearBg)
|
||
bj.dccLab(dcc and labels, labBearCol, textBearCol)
|
||
_wrap(dcc and sBox, boxes, 2, patBearBo, patBearBg)
|
||
bj.hbLab(bhb and labels, labBearCol, textBearCol)
|
||
_wrap(bhb and sBox, boxes, 2, patBearBo, patBearBg)
|
||
bj.lusLab(lu and labels, labBearCol, textBearCol)
|
||
_wrap(lu and sBox, boxes, 1, patBearBo, patBearBg)
|
||
|
||
// 添加蜡烛图形态名称标签
|
||
if showAlertNames
|
||
// 看涨形态标签
|
||
if dw
|
||
label.new(bar_index, low - atr * 0.05, '十字星', style = label.style_none, textcolor = textNeutCol, size = labelSizeValue)
|
||
if bew
|
||
label.new(bar_index, low - atr * 0.05, '看涨吞没', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
if h
|
||
label.new(bar_index, low - atr * 0.05, '锤子线', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
if dd
|
||
label.new(bar_index, low - atr * 0.05, '蜻蜓十字', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
if tb
|
||
label.new(bar_index, low - atr * 0.05, '镊子底', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
if stw
|
||
label.new(bar_index, low - atr * 0.05, '纺锤顶', style = label.style_none, textcolor = textNeutCol, size = labelSizeValue)
|
||
if p
|
||
label.new(bar_index, low - atr * 0.05, '刺透线', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
if bhw
|
||
label.new(bar_index, low - atr * 0.05, '看涨孕线', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
if ll
|
||
label.new(bar_index, low - atr * 0.05, '长下影', style = label.style_none, textcolor = textBullCol, size = labelSizeValue)
|
||
|
||
// 看跌形态标签
|
||
if db
|
||
label.new(bar_index, high + atr * 0.05, '十字星', style = label.style_none, textcolor = textNeutCol, size = labelSizeValue)
|
||
if beb
|
||
label.new(bar_index, high + atr * 0.05, '看跌吞没', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
if ss
|
||
label.new(bar_index, high + atr * 0.05, '流星线', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
if gd
|
||
label.new(bar_index, high + atr * 0.05, '墓碑十字', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
if tt
|
||
label.new(bar_index, high + atr * 0.05, '镊子顶', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
if stb
|
||
label.new(bar_index, high + atr * 0.05, '纺锤顶', style = label.style_none, textcolor = textNeutCol, size = labelSizeValue)
|
||
if dcc
|
||
label.new(bar_index, high + atr * 0.05, '乌云盖顶', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
if bhb
|
||
label.new(bar_index, high + atr * 0.05, '看跌孕线', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
if lu
|
||
label.new(bar_index, high + atr * 0.05, '长上影', style = label.style_none, textcolor = textBearCol, size = labelSizeValue)
|
||
|
||
// ... 其他代码 ...
|
||
|
||
_level(pivotHigh, highBull, true) // true 表示这是 highPivotZone
|
||
_level(pivotLows, lowsBull, false) // false 表示这是 lowPivotZone (即支撑区)
|
||
|
||
// 添加价格变化的plot,用于警报消息中的占位符
|
||
plot(close - open, title = '价格变化', display = display.none)
|
||
|
||
// ... 其他代码 ...
|
||
|
||
// ================================== //
|
||
// -----> Alert Functionality <------ //
|
||
// ================================== //
|
||
|
||
// 获取最近的支撑位和阻力位价格(移动到这里以便在警报中使用)
|
||
_getNearestLevels() =>
|
||
var float nearestSupport = na
|
||
var float nearestResistance = na
|
||
var float supportDistance = na
|
||
var float resistanceDistance = na
|
||
|
||
// 初始化最近距离为无穷大
|
||
float minSupportDist = 999999.0
|
||
float minResistanceDist = 999999.0
|
||
|
||
// 检查所有支撑区域(pivotLows)
|
||
if array.size(pivotLows) > 0
|
||
for i = 0 to array.size(pivotLows) - 1 by 1
|
||
current_box = array.get(pivotLows, i)
|
||
if not na(current_box)
|
||
[top_price, bottom_price] = _getBox(pivotLows, i)
|
||
// 计算当前价格到支撑区域的距离
|
||
float distToSupport = na
|
||
if close > top_price
|
||
distToSupport := close - top_price
|
||
distToSupport
|
||
else if close < bottom_price
|
||
distToSupport := bottom_price - close
|
||
distToSupport
|
||
else
|
||
distToSupport := 0.0 // 价格在支撑区域内
|
||
distToSupport
|
||
|
||
// 更新最近的支撑位
|
||
if distToSupport < minSupportDist
|
||
minSupportDist := distToSupport
|
||
nearestSupport := (top_price + bottom_price) / 2
|
||
supportDistance := distToSupport
|
||
supportDistance
|
||
|
||
// 检查所有阻力区域(pivotHigh)
|
||
if array.size(pivotHigh) > 0
|
||
for i = 0 to array.size(pivotHigh) - 1 by 1
|
||
current_box = array.get(pivotHigh, i)
|
||
if not na(current_box)
|
||
[top_price, bottom_price] = _getBox(pivotHigh, i)
|
||
// 计算当前价格到阻力区域的距离
|
||
float distToResistance = na
|
||
if close > top_price
|
||
distToResistance := close - top_price
|
||
distToResistance
|
||
else if close < bottom_price
|
||
distToResistance := bottom_price - close
|
||
distToResistance
|
||
else
|
||
distToResistance := 0.0 // 价格在阻力区域内
|
||
distToResistance
|
||
|
||
// 更新最近的阻力位
|
||
if distToResistance < minResistanceDist
|
||
minResistanceDist := distToResistance
|
||
nearestResistance := (top_price + bottom_price) / 2
|
||
resistanceDistance := distToResistance
|
||
resistanceDistance
|
||
|
||
[nearestSupport, nearestResistance, supportDistance, resistanceDistance]
|
||
|
||
// 为了在警报中包含支撑阻力位信息,我们需要创建plot变量
|
||
// 因为alertcondition只接受const string,不能使用动态函数
|
||
|
||
// 创建用于警报的plot变量
|
||
[nearestSupportPrice, nearestResistancePrice, supportDistance, resistanceDistance] = _getNearestLevels()
|
||
|
||
// 计算百分比
|
||
supportPercent = not na(supportDistance) and not na(nearestSupportPrice) ? supportDistance / close * 100 : na
|
||
resistancePercent = not na(resistanceDistance) and not na(nearestResistancePrice) ? resistanceDistance / close * 100 : na
|
||
|
||
// 创建plot用于在警报中引用
|
||
plot(nearestSupportPrice, title = '最近支撑价格', display = display.none)
|
||
plot(nearestResistancePrice, title = '最近阻力价格', display = display.none)
|
||
plot(supportDistance, title = '支撑距离', display = display.none)
|
||
plot(resistanceDistance, title = '阻力距离', display = display.none)
|
||
plot(supportPercent, title = '支撑距离百分比', display = display.none)
|
||
plot(resistancePercent, title = '阻力距离百分比', display = display.none)
|
||
|
||
// ===== 统一警报系统 =====
|
||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||
|
||
// 警报频率限制 - 每分钟只触发一次
|
||
var int last_alert_resistance_break = 0
|
||
var int last_alert_support_break = 0
|
||
var int last_alert_support_found = 0
|
||
var int last_alert_resistance_found = 0
|
||
var int last_alert_resistance_rejection = 0
|
||
var int last_alert_support_bounce = 0
|
||
var int last_alert_false_breakdown = 0
|
||
var int last_alert_false_breakout = 0
|
||
var int last_alert_strong_breakout_up = 0
|
||
var int last_alert_strong_breakdown = 0
|
||
var int last_alert_bullish_engulfing = 0
|
||
var int last_alert_bearish_engulfing = 0
|
||
var int last_alert_hammer = 0
|
||
var int last_alert_shooting_star = 0
|
||
var int last_alert_tsi_bullish = 0
|
||
var int last_alert_tsi_bearish = 0
|
||
|
||
// 获取当前时间(分钟级别)
|
||
current_minute = math.floor(timenow / 60000)
|
||
|
||
// 检测所有警报条件并生成对应的JSON消息
|
||
alert_message = ""
|
||
|
||
// 支撑阻力突破警报 - 每分钟限制
|
||
if resBreak and current_minute > last_alert_resistance_break
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"阻力突破","位置":"阻力位上方","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"resistance_break"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_resistance_break := current_minute
|
||
|
||
if supBreak and current_minute > last_alert_support_break
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"支撑跌破","位置":"支撑位下方","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"support_break"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_support_break := current_minute
|
||
|
||
// 关键位置发现警报 - 每分钟限制
|
||
if bullCheck and current_minute > last_alert_support_found
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"发现支撑","位置":"关键支撑位","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"support_found"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_support_found := current_minute
|
||
|
||
if bearCheck and current_minute > last_alert_resistance_found
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"发现阻力","位置":"关键阻力位","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"resistance_found"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_resistance_found := current_minute
|
||
|
||
// 支撑阻力反弹回落警报 - 每分钟限制
|
||
if plotBearCheck and current_minute > last_alert_resistance_rejection
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"阻力回落","位置":"阻力区域内","形态类型":"看跌信号","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"resistance_rejection"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_resistance_rejection := current_minute
|
||
|
||
if plotBullCheck and current_minute > last_alert_support_bounce
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"支撑反弹","位置":"支撑区域内","形态类型":"看涨信号","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"support_bounce"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_support_bounce := current_minute
|
||
|
||
// 假突破警报 - 每分钟限制
|
||
if falseBreakBull and current_minute > last_alert_false_breakdown
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"假跌破","位置":"支撑位反弹","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"false_breakdown"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_false_breakdown := current_minute
|
||
|
||
if falseBreakBear and current_minute > last_alert_false_breakout
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"假突破","位置":"阻力位回落","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"false_breakout"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_false_breakout := current_minute
|
||
|
||
// 强势突破警报 - 每分钟限制
|
||
if breakOut and current_minute > last_alert_strong_breakout_up
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"向上突破","位置":"所有阻力位上方","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"strong_breakout_up"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_strong_breakout_up := current_minute
|
||
|
||
if breakDwn and current_minute > last_alert_strong_breakdown
|
||
alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"向下跌破","位置":"所有支撑位下方","成交量":"' + str.tostring(volume, '#') + '","价格变化":"' + str.tostring(close - open, '#.####') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"strong_breakdown"}'
|
||
alert(alert_message, alert.freq_once_per_bar_close)
|
||
last_alert_strong_breakdown := current_minute
|
||
|
||
// 主要蜡烛图形态警报 - 每分钟限制
|
||
// if bew and current_minute > last_alert_bullish_engulfing // 看涨吞没
|
||
// alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"看涨吞没","位置":"关键位置","形态类型":"强烈看涨","成交量":"' + str.tostring(volume, '#') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"bullish_engulfing"}'
|
||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||
// last_alert_bullish_engulfing := current_minute
|
||
|
||
// if beb and current_minute > last_alert_bearish_engulfing // 看跌吞没
|
||
// alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"看跌吞没","位置":"关键位置","形态类型":"强烈看跌","成交量":"' + str.tostring(volume, '#') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"bearish_engulfing"}'
|
||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||
// last_alert_bearish_engulfing := current_minute
|
||
|
||
// if h and current_minute > last_alert_hammer // 锤子线
|
||
// alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"锤子线","位置":"支撑位","形态类型":"看涨反转","成交量":"' + str.tostring(volume, '#') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"hammer"}'
|
||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||
// last_alert_hammer := current_minute
|
||
|
||
// if ss and current_minute > last_alert_shooting_star // 流星线
|
||
// alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"流星线","位置":"阻力位","形态类型":"看跌反转","成交量":"' + str.tostring(volume, '#') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"shooting_star"}'
|
||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||
// last_alert_shooting_star := current_minute
|
||
|
||
// TSI动量转向警报 - 每分钟限制
|
||
// if plotCurlBull and current_minute > last_alert_tsi_bullish
|
||
// alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"TSI动量转多","位置":"关键位置","成交量":"' + str.tostring(volume, '#') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"tsi_bullish"}'
|
||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||
// last_alert_tsi_bullish := current_minute
|
||
|
||
// if plotCurlBear and current_minute > last_alert_tsi_bearish
|
||
// alert_message := '{"指标名称":"BjorgumKeyLevels","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"TSI动量转空","位置":"关键位置","成交量":"' + str.tostring(volume, '#') + '","最近支撑价格":"' + str.tostring(nearestSupportPrice, '#.####') + '","支撑距离":"' + str.tostring(supportDistance, '#.####') + '","支撑距离百分比":"' + str.tostring(supportPercent, '#.##') + '","最近阻力价格":"' + str.tostring(nearestResistancePrice, '#.####') + '","阻力距离":"' + str.tostring(resistanceDistance, '#.####') + '","阻力距离百分比":"' + str.tostring(resistancePercent, '#.##') + '","信号":"tsi_bearish"}'
|
||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||
// last_alert_tsi_bearish := current_minute
|
||
|
||
// ===== 传统警报条件(保留兼容性)=====
|
||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||
|
||
// 阻力突破警报
|
||
alertcondition(resBreak, title = '阻力突破', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力突破","位置":"阻力位上方","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 支撑跌破警报
|
||
alertcondition(supBreak, title = '支撑跌破', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑跌破","位置":"支撑位下方","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 发现支撑警报
|
||
alertcondition(bullCheck, title = '发现支撑', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"发现支撑","位置":"关键支撑位","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 发现阻力警报
|
||
alertcondition(bearCheck, title = '发现阻力', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"发现阻力","位置":"关键阻力位","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 阻力回落警报
|
||
alertcondition(plotBearCheck, title = '阻力回落', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力回落","位置":"阻力区域内","形态类型":"看跌信号","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 支撑反弹警报
|
||
alertcondition(plotBullCheck, title = '支撑反弹', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑反弹","位置":"支撑区域内","形态类型":"看涨信号","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 假跌破警报
|
||
alertcondition(falseBreakBull, title = '假跌破', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"假跌破","位置":"支撑位反弹","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 假突破警报
|
||
alertcondition(falseBreakBear, title = '假突破', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"假突破","位置":"阻力位回落","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 向上突破警报
|
||
alertcondition(breakOut, title = '向上突破', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"向上突破","位置":"所有阻力位上方","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 向下跌破警报
|
||
alertcondition(breakDwn, title = '向下跌破', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"向下跌破","位置":"所有支撑位下方","成交量":"{{volume}}","价格变化":"{{plot("价格变化")}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 蜡烛图形态警报 - 看涨形态
|
||
// alertcondition(dw, title = '十字星-支撑', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"十字星","位置":"支撑位","形态类型":"中性反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(bew, title = '看涨吞没', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"看涨吞没","位置":"关键位置","形态类型":"强烈看涨","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(h, title = '锤子线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"锤子线","位置":"支撑位","形态类型":"看涨反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(dd, title = '蜻蜓十字', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"蜻蜓十字","位置":"支撑位","形态类型":"看涨反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(tb, title = '镊子底', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"镊子底","位置":"关键位置","形态类型":"看涨反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(p, title = '刺透线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"刺透线","位置":"关键位置","形态类型":"看涨反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(bhw, title = '看涨孕线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"看涨孕线","位置":"关键位置","形态类型":"看涨反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(ll, title = '长下影线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"长下影线","位置":"支撑位","形态类型":"看涨信号","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// // 蜡烛图形态警报 - 看跌形态
|
||
// alertcondition(db, title = '十字星-阻力', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"十字星","位置":"阻力位","形态类型":"中性反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(beb, title = '看跌吞没', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"看跌吞没","位置":"关键位置","形态类型":"强烈看跌","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(ss, title = '流星线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"流星线","位置":"阻力位","形态类型":"看跌反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(gd, title = '墓碑十字', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"墓碑十字","位置":"阻力位","形态类型":"看跌反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(tt, title = '镊子顶', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"镊子顶","位置":"关键位置","形态类型":"看跌反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(dcc, title = '乌云盖顶', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"乌云盖顶","位置":"关键位置","形态类型":"看跌反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(bhb, title = '看跌孕线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"看跌孕线","位置":"关键位置","形态类型":"看跌反转","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(lu, title = '长上影线', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"长上影线","位置":"阻力位","形态类型":"看跌信号","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// // 纺锤顶形态警报
|
||
// alertcondition(stw, title = '白色纺锤顶', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"白色纺锤顶","位置":"关键位置","形态类型":"中性信号","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// alertcondition(stb, title = '黑色纺锤顶', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"黑色纺锤顶","位置":"关键位置","形态类型":"中性信号","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// TSI动量转向警报
|
||
alertcondition(plotCurlBull, title = 'TSI动量转多', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"TSI动量转多","位置":"关键位置","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
alertcondition(plotCurlBear, title = 'TSI动量转空', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"TSI动量转空","位置":"关键位置","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// 综合警报 - 价格在关键位置的行为
|
||
alertcondition(close > ta.highest(high, 20), title = '价格创新高', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格创新高","位置":"20周期新高","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
alertcondition(close < ta.lowest(low, 20), title = '价格创新低', message = '{"指标名称":"BjorgumKeyLevels","交易对":"{{ticker}}","周期":"{{interval}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格创新低","位置":"20周期新低","成交量":"{{volume}}","最近支撑价格":"{{plot("最近支撑价格")}}","支撑距离":"{{plot("支撑距离")}}","支撑距离百分比":"{{plot("支撑距离百分比")}}","最近阻力价格":"{{plot("最近阻力价格")}}","阻力距离":"{{plot("阻力距离")}}","阻力距离百分比":"{{plot("阻力距离百分比")}}"}')
|
||
|
||
// ===== 统一警报系统说明 =====
|
||
// 本指标已经包含了完整的JSON格式警报消息,支持统一警报系统
|
||
// 所有警报条件都使用了JSON格式的消息,包含了详细的市场信息
|
||
// 在TradingView中添加警报时,选择任意一个警报条件即可获得对应的JSON消息
|
||
//
|
||
// 主要警报类型:
|
||
// 1. 关键位置突破:阻力突破、支撑跌破
|
||
// 2. 关键位置发现:发现支撑、发现阻力
|
||
// 3. 价格反应:支撑反弹、阻力回落
|
||
// 4. 假突破信号:假跌破、假突破
|
||
// 5. 趋势突破:向上突破、向下跌破
|
||
// 6. 蜡烛图形态:各种看涨看跌形态
|
||
// 7. 动量信号:TSI动量转向
|
||
// 8. 价格极值:创新高、创新低
|
||
//
|
||
// 所有警报消息都包含:
|
||
// - 指标名称、交易对、周期
|
||
// - OHLC价格数据
|
||
// - 触发时间信息
|
||
// - 最近支撑阻力位价格和距离
|
||
// - 成交量信息
|
||
// - 具体事件描述
|
||
|
||
// ================================== //
|
||
// -----> 仪表盘功能 <------ //
|
||
// ================================== //
|
||
|
||
// 添加仪表盘显示设置
|
||
showDashboard = input.bool(true, '显示价格距离仪表盘', group = '仪表盘设置')
|
||
dashboardPos = input.string('左下', '仪表盘位置', group = '仪表盘设置', options = ['左上', '右上', '左下', '右下'])
|
||
dashboardSize = input.string('small', '仪表盘字体大小', group = '仪表盘设置', options = ['tiny', 'small', 'normal', 'large'])
|
||
|
||
|
||
|
||
// 获取仪表盘位置
|
||
_getDashboardPosition() =>
|
||
switch dashboardPos
|
||
'左上' => [position.top_left, position.top_left]
|
||
'右上' => [position.top_right, position.top_right]
|
||
'左下' => [position.bottom_left, position.bottom_left]
|
||
'右下' => [position.bottom_right, position.bottom_right]
|
||
=> [position.top_right, position.top_right]
|
||
|
||
// 获取仪表盘字体大小
|
||
_getDashboardSize() =>
|
||
switch dashboardSize
|
||
'tiny' => size.tiny
|
||
'small' => size.small
|
||
'normal' => size.normal
|
||
'large' => size.large
|
||
=> size.normal
|
||
|
||
// 显示仪表盘
|
||
if showDashboard and barstate.islast
|
||
[nearestSup, nearestRes, supDist, resDist] = _getNearestLevels()
|
||
[dashPos, _] = _getDashboardPosition()
|
||
dashSize = _getDashboardSize()
|
||
|
||
// 创建表格式仪表盘 (4行4列)
|
||
var table dashboard = table.new(dashPos, 4, 4, bgcolor = color.new(color.gray, 90), border_width = 1, border_color = color.new(color.white, 70))
|
||
|
||
// 表格标题行
|
||
table.cell(dashboard, 0, 0, '项目', text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.blue, 80))
|
||
table.cell(dashboard, 1, 0, '价格', text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.blue, 80))
|
||
table.cell(dashboard, 2, 0, '距离', text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.blue, 80))
|
||
table.cell(dashboard, 3, 0, '百分比', text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.blue, 80))
|
||
|
||
// 当前价格行
|
||
table.cell(dashboard, 0, 1, '当前价格', text_color = color.new(color.black, 30), text_size = dashSize, bgcolor = color.new(color.white, 85))
|
||
table.cell(dashboard, 1, 1, str.tostring(close, '#.####'), text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.white, 85))
|
||
table.cell(dashboard, 2, 1, '-', text_color = color.new(color.black, 50), text_size = dashSize, bgcolor = color.new(color.white, 85))
|
||
table.cell(dashboard, 3, 1, '-', text_color = color.new(color.black, 50), text_size = dashSize, bgcolor = color.new(color.white, 85))
|
||
|
||
// 支撑位行
|
||
table.cell(dashboard, 0, 2, '最近支撑', text_color = color.new(color.black, 30), text_size = dashSize, bgcolor = color.new(color.green, 85))
|
||
|
||
var string supPriceText = ''
|
||
var string supDistText = ''
|
||
var string supPercText = ''
|
||
|
||
if not na(nearestSup)
|
||
supPriceText := str.tostring(nearestSup, '#.####')
|
||
if not na(supDist)
|
||
supDistPercent = supDist / close * 100
|
||
if close >= nearestSup
|
||
supDistText := '+' + str.tostring(supDist, '#.####')
|
||
supPercText := '+' + str.tostring(supDistPercent, '#.##') + '%'
|
||
supPercText
|
||
else
|
||
supDistText := '-' + str.tostring(supDist, '#.####')
|
||
supPercText := '-' + str.tostring(supDistPercent, '#.##') + '%'
|
||
supPercText
|
||
else
|
||
supDistText := '-'
|
||
supPercText := '-'
|
||
supPercText
|
||
else
|
||
supPriceText := '未找到'
|
||
supDistText := '-'
|
||
supPercText := '-'
|
||
supPercText
|
||
|
||
table.cell(dashboard, 1, 2, supPriceText, text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.green, 85))
|
||
table.cell(dashboard, 2, 2, supDistText, text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.green, 85))
|
||
table.cell(dashboard, 3, 2, supPercText, text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.green, 85))
|
||
|
||
// 阻力位行
|
||
table.cell(dashboard, 0, 3, '最近阻力', text_color = color.new(color.black, 30), text_size = dashSize, bgcolor = color.new(color.red, 85))
|
||
|
||
var string resPriceText = ''
|
||
var string resDistText = ''
|
||
var string resPercText = ''
|
||
|
||
if not na(nearestRes)
|
||
resPriceText := str.tostring(nearestRes, '#.####')
|
||
if not na(resDist)
|
||
resDistPercent = resDist / close * 100
|
||
if close >= nearestRes
|
||
resDistText := '+' + str.tostring(resDist, '#.####')
|
||
resPercText := '+' + str.tostring(resDistPercent, '#.##') + '%'
|
||
resPercText
|
||
else
|
||
resDistText := '-' + str.tostring(resDist, '#.####')
|
||
resPercText := '-' + str.tostring(resDistPercent, '#.##') + '%'
|
||
resPercText
|
||
else
|
||
resDistText := '-'
|
||
resPercText := '-'
|
||
resPercText
|
||
else
|
||
resPriceText := '未找到'
|
||
resDistText := '-'
|
||
resPercText := '-'
|
||
resPercText
|
||
|
||
table.cell(dashboard, 1, 3, resPriceText, text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.red, 85))
|
||
table.cell(dashboard, 2, 3, resDistText, text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.red, 85))
|
||
table.cell(dashboard, 3, 3, resPercText, text_color = color.new(color.black, 20), text_size = dashSize, bgcolor = color.new(color.red, 85))
|
||
|
||
// ____ __ _ ____
|
||
// ( __)( ( \( \
|
||
// ) _) / / ) D (
|
||
// (____)\_)__)(____/
|