Files
tradingview-pine/参考/srbr.pine
2025-08-02 04:21:30 +00:00

715 lines
39 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ChartPrime
//@version=6
indicator('SRBR 支撑阻力突破回测 [多时间周期表格]', shorttitle = 'SRBR MTF', overlay = true, max_boxes_count = 50)
// ---------------------------------------------------------------------------------------------------------------------}
// 𝙐𝙎𝙀𝙍 𝙄𝙉𝙋𝙐𝙏𝙎
// ---------------------------------------------------------------------------------------------------------------------{
int lookbackPeriod = input.int(20, 'Lookback Period', minval = 1, group = 'Settings')
int vol_len = input.int(2, 'Delta Volume Filter Length', tooltip = 'Higher input, will filter low volume boxes', group = 'Settings')
float box_withd = input.float(1, 'Adjust Box Width', maxval = 1000, minval = 0, step = 0.1, group = 'Settings')
// ═════════ 多时间周期表格设置 ════════
mtfSet = input(false, '═════════ 多时间周期表格设置 ════════')
show_mtf_table = input.bool(true, title='显示多时间周期表格', group='MTF Table')
mtf_1m = input.bool(true, title='显示1分钟数据', group='MTF Table')
mtf_5m = input.bool(true, title='显示5分钟数据', group='MTF Table')
mtf_15m = input.bool(true, title='显示15分钟数据', group='MTF Table')
mtf_30m = input.bool(true, title='显示30分钟数据', group='MTF Table')
mtf_45m = input.bool(true, title='显示45分钟数据', group='MTF Table')
mtf_1h = input.bool(true, title='显示1小时数据', group='MTF Table')
mtf_4h = input.bool(true, title='显示4小时数据', group='MTF Table')
// ═════════ 表格显示设置 ════════
tableSet = input(false, '═════════ 表格显示设置 ════════')
table_position = input.string('bottom_right', title='表格位置', options=['top_left', 'top_center', 'top_right', 'middle_left', 'middle_center', 'middle_right', 'bottom_left', 'bottom_center', 'bottom_right'], group='Table Display')
table_text_size = input.string('small', title='表格文字大小', options=['auto', 'tiny', 'small', 'normal', 'large', 'huge'], group='Table Display')
mtf_table_rows = input.int(9, title='多时间框架表格行数', minval=6, maxval=12, group='Table Display')
mtf_table_columns = input.int(8, title='多时间框架表格列数', minval=6, maxval=10, group='Table Display')
//************************************************************************************************************
// 辅助函数定义
//************************************************************************************************************
// ═════════ 表格文字大小转换 ════════
get_text_size() =>
switch table_text_size
'auto' => size.auto
'tiny' => size.tiny
'small' => size.small
'normal' => size.normal
'large' => size.large
'huge' => size.huge
=> size.small
// ═════════ 表格位置转换 ════════
get_table_position() =>
switch table_position
'top_left' => position.top_left
'top_center' => position.top_center
'top_right' => position.top_right
'middle_left' => position.middle_left
'middle_center' => position.middle_center
'middle_right' => position.middle_right
'bottom_left' => position.bottom_left
'bottom_center' => position.bottom_center
'bottom_right' => position.bottom_right
=> position.bottom_left
// ═════════ 价格状态判断函数 ════════
get_price_status(price_val, support_val, resistance_val) =>
if na(price_val) or na(support_val) or na(resistance_val)
"N/A"
else if price_val > resistance_val
"看多"
else if price_val < support_val
"看空"
else
"震荡"
// ═════════ 价格状态颜色函数 ════════
get_price_status_color(price_val, support_val, resistance_val) =>
if na(price_val) or na(support_val) or na(resistance_val)
color.new(color.gray, 60)
else if price_val > resistance_val
color.new(color.green, 40) // 看多 - 绿色
else if price_val < support_val
color.new(color.red, 40) // 看空 - 红色
else
color.new(color.orange, 40) // 震荡 - 橙色
// ═════════ 距离计算函数 ════════
get_distance_to_levels(price_val, support_val, resistance_val) =>
if na(price_val) or na(support_val) or na(resistance_val)
[na, na]
else
distance_to_support = math.abs(price_val - support_val)
distance_to_resistance = math.abs(price_val - resistance_val)
[distance_to_support, distance_to_resistance]
// ---------------------------------------------------------------------------------------------------------------------}
// 𝙄𝙉𝘿𝙄𝘾𝘼𝙏𝙊𝙍 𝘾𝘼𝙇𝘾𝙐𝙇𝘼𝙏𝙄𝙊𝙉𝙎
// ---------------------------------------------------------------------------------------------------------------------{
// Delta Volume Function
upAndDownVolume() =>
posVol = 0.0
negVol = 0.0
var isBuyVolume = true
switch
close > open =>
isBuyVolume := true
isBuyVolume
close < open =>
isBuyVolume := false
isBuyVolume
if isBuyVolume
posVol := posVol + volume
posVol
else
negVol := negVol - volume
negVol
posVol + negVol
// Function to identify support and resistance boxes
calcSupportResistance(src, lookbackPeriod) =>
// Volume
Vol = upAndDownVolume()
vol_hi = ta.highest(Vol / 2.5, vol_len)
vol_lo = ta.lowest(Vol / 2.5, vol_len)
var float supportLevel = na
var float supportLevel_1 = na
var float resistanceLevel = na
var float resistanceLevel_1 = na
var box sup = na
var box res = na
var color res_color = na
var color sup_color = na
var float multi = na
var bool brekout_res = false
var bool brekout_sup = false
var bool res_holds = false
var bool sup_holds = false
// Find pivot points
pivotHigh = ta.pivothigh(src, lookbackPeriod, lookbackPeriod)
pivotLow = ta.pivotlow(src, lookbackPeriod, lookbackPeriod)
// Box width
atr = ta.atr(200)
withd = atr * box_withd
// Volume range for color gradient
vol_highest = ta.highest(Vol, 25)
vol_lowest = ta.lowest(Vol, 25)
// Find support levels with Positive Volume
if not na(pivotLow) and Vol > vol_hi
supportLevel := pivotLow
supportLevel_1 := supportLevel - withd
topLeft = chart.point.from_index(bar_index - lookbackPeriod, supportLevel)
bottomRight = chart.point.from_index(bar_index, supportLevel_1)
sup_color := color.from_gradient(Vol, 0, vol_highest, color(na), color.new(color.green, 30))
// 注释掉支撑位box绘图保留计算逻辑
// sup := box.new(top_left = topLeft, bottom_right = bottomRight, border_color = color.green, border_width = 1, bgcolor = sup_color, text = 'Vol: ' + str.tostring(math.round(Vol, 2)), text_color = chart.fg_color, text_size = size.small)
// sup
na
// Find resistance levels with Negative Volume
if not na(pivotHigh) and Vol < vol_lo
resistanceLevel := pivotHigh
resistanceLevel_1 := resistanceLevel + withd
topLeft = chart.point.from_index(bar_index - lookbackPeriod, resistanceLevel)
bottomRight = chart.point.from_index(bar_index, resistanceLevel_1)
res_color := color.from_gradient(Vol, vol_lowest, 0, color.new(color.red, 30), color(na))
// 注释掉阻力位box绘图保留计算逻辑
// res := box.new(top_left = topLeft, bottom_right = bottomRight, border_color = color.red, border_width = 1, bgcolor = res_color, text = 'Vol: ' + str.tostring(math.round(Vol, 2)), text_color = chart.fg_color, text_size = size.small)
// res
na
// Adaptive Box Len - 已注释掉box操作
// sup.set_right(bar_index + 1)
// res.set_right(bar_index + 1)
// Break of support or resistance conditions
brekout_res := ta.crossover(low, resistanceLevel_1)
res_holds := ta.crossunder(high, resistanceLevel)
sup_holds := ta.crossover(low, supportLevel)
brekout_sup := ta.crossunder(high, supportLevel_1)
// Change Color of Support to red if it was break, change color of resistance to green if it was break - 已注释掉box操作
// if brekout_sup
// sup.set_bgcolor(color.new(color.red, 80))
// sup.set_border_color(color.red)
// sup.set_border_style(line.style_dashed)
// if sup_holds
// sup.set_bgcolor(sup_color)
// sup.set_border_color(color.green)
// sup.set_border_style(line.style_solid)
// if brekout_res
// res.set_bgcolor(color.new(color.green, 80))
// res.set_border_color(color.new(color.green, 0))
// res.set_border_style(line.style_dashed)
// if res_holds
// res.set_bgcolor(res_color)
// res.set_border_color(color.new(color.red, 0))
// res.set_border_style(line.style_solid)
[supportLevel, resistanceLevel, brekout_res, res_holds, sup_holds, brekout_sup]
// Calculate support and resistance levels and their breakouts
[supportLevel, resistanceLevel, brekout_res, res_holds, sup_holds, brekout_sup] = calcSupportResistance(close, lookbackPeriod)
// Check if Resistance become Support or Support Become Resistance
var bool res_is_sup = false
var bool sup_is_res = false
switch
brekout_res =>
res_is_sup := true
res_is_sup
res_holds =>
res_is_sup := false
res_is_sup
switch
brekout_sup =>
sup_is_res := true
sup_is_res
sup_holds =>
sup_is_res := false
sup_is_res
// ---------------------------------------------------------------------------------------------------------------------}
// 𝙑𝙄𝙎𝙐𝘼𝙇𝙄𝙕𝘼𝙏𝙄𝙊𝙉
// ---------------------------------------------------------------------------------------------------------------------{
// Plot Res and Sup breakouts and holds - 已注释掉图形显示
// plotchar(res_holds, 'Resistance Holds', '◆', color = #e92929, size = size.tiny, location = location.abovebar, offset = -1)
// plotchar(sup_holds, 'Support Holds', '◆', color = #20ca26, size = size.tiny, location = location.belowbar, offset = -1)
// plotchar(brekout_res and res_is_sup[1], 'Resistance as Support Holds', '◆', color = #20ca26, size = size.tiny, location = location.belowbar, offset = -1)
// plotchar(brekout_sup and sup_is_res[1], 'Support as Resistance Holds', '◆', color = #e92929, size = size.tiny, location = location.abovebar, offset = -1)
// Break Out Labels - 已注释掉图形显示
// if brekout_sup and not sup_is_res[1]
// label.new(bar_index[1], supportLevel[1], text = 'Break Sup', style = label.style_label_down, color = #7e1e1e, textcolor = chart.fg_color, size = size.small)
// if brekout_res and not res_is_sup[1]
// label.new(bar_index[1], resistanceLevel[1], text = 'Break Res', style = label.style_label_up, color = #2b6d2d, textcolor = chart.fg_color, size = size.small)
// 警报标记 - 醒目的视觉提示 - 已注释掉图形显示
// 支撑位保持警报标记
// if sup_holds
// label.new(bar_index, low, text = '🔔SUP', style = label.style_label_down, color = color.new(color.lime, 0), textcolor = color.black, size = size.large, tooltip = '支撑位保持警报')
// 阻力位保持警报标记
// if res_holds
// label.new(bar_index, high, text = '🔔RES', style = label.style_label_up, color = color.new(color.red, 0), textcolor = color.white, size = size.large, tooltip = '阻力位保持警报')
// 支撑位突破警报标记
// if brekout_sup
// label.new(bar_index[1], supportLevel[1], text = '🚨SUP⬇', style = label.style_label_down, color = color.new(color.orange, 0), textcolor = color.black, size = size.large, tooltip = '支撑位突破警报')
// 阻力位突破警报标记
// if brekout_res
// label.new(bar_index[1], resistanceLevel[1], text = '🚨RES⬆', style = label.style_label_up, color = color.new(color.aqua, 0), textcolor = color.black, size = size.large, tooltip = '阻力位突破警报')
// 阻力转支撑警报标记
// if brekout_res and res_is_sup[1]
// label.new(bar_index[1], resistanceLevel[1], text = '⭐R→S', style = label.style_label_down, color = color.new(color.purple, 0), textcolor = color.white, size = size.large, tooltip = '阻力转支撑保持警报')
// 支撑转阻力警报标记
// if brekout_sup and sup_is_res[1]
// label.new(bar_index[1], supportLevel[1], text = '⭐S→R', style = label.style_label_up, color = color.new(color.maroon, 0), textcolor = color.white, size = size.large, tooltip = '支撑转阻力保持警报')
// 全局作用域的plotshape - 警报形状标记 - 已注释掉图形显示
// plotshape(sup_holds, title = '支撑保持警报', style = shape.triangleup, location = location.belowbar, color = color.new(color.lime, 0), size = size.large)
// plotshape(res_holds, title = '阻力保持警报', style = shape.triangledown, location = location.abovebar, color = color.new(color.red, 0), size = size.large)
// plotshape(brekout_sup, title = '支撑突破警报', style = shape.xcross, location = location.belowbar, color = color.new(color.orange, 0), size = size.large)
// plotshape(brekout_res, title = '阻力突破警报', style = shape.xcross, location = location.abovebar, color = color.new(color.aqua, 0), size = size.large)
// plotshape(brekout_res and res_is_sup[1], title = '阻力转支撑警报', style = shape.diamond, location = location.belowbar, color = color.new(color.purple, 0), size = size.large)
// plotshape(brekout_sup and sup_is_res[1], title = '支撑转阻力警报', style = shape.diamond, location = location.abovebar, color = color.new(color.maroon, 0), size = size.large)
//************************************************************************************************************
// 多时间周期计算
//************************************************************************************************************
// ═════════ 多时间周期专用计算函数(无绘图操作) ════════
// 为了避免request.security()中的绘图函数错误,创建简化版本
calcSRForMTF(src, lookback) =>
// 使用简化的支撑阻力计算基于pivot点但无绘图
pivotHigh = ta.pivothigh(src, lookback, lookback)
pivotLow = ta.pivotlow(src, lookback, lookback)
// 简化的支撑阻力位识别
var float mtf_support = na
var float mtf_resistance = na
if not na(pivotLow)
mtf_support := pivotLow
if not na(pivotHigh)
mtf_resistance := pivotHigh
// 简化的突破判断
mtf_brekout_res = src > mtf_resistance
mtf_res_holds = src <= mtf_resistance and src >= mtf_resistance * 0.995
mtf_sup_holds = src >= mtf_support and src <= mtf_support * 1.005
mtf_brekout_sup = src < mtf_support
[mtf_support, mtf_resistance, mtf_brekout_res, mtf_res_holds, mtf_sup_holds, mtf_brekout_sup]
// ═════════ 多时间周期数据获取函数 ════════
get_mtf_data(tf) =>
request.security(syminfo.tickerid, tf, calcSRForMTF(close, lookbackPeriod), lookahead=barmerge.lookahead_off)
get_mtf_close(tf) =>
request.security(syminfo.tickerid, tf, close, lookahead=barmerge.lookahead_off)
// ═════════ 多时间周期数据获取 ═════════
// 1分钟数据
var float supportLevel_1m = na
var float resistanceLevel_1m = na
var bool brekout_res_1m = false
var bool res_holds_1m = false
var bool sup_holds_1m = false
var bool brekout_sup_1m = false
var float close_1m = na
if mtf_1m
[sup_1m, res_1m, br_res_1m, r_holds_1m, s_holds_1m, br_sup_1m] = get_mtf_data("1")
supportLevel_1m := sup_1m
resistanceLevel_1m := res_1m
brekout_res_1m := br_res_1m
res_holds_1m := r_holds_1m
sup_holds_1m := s_holds_1m
brekout_sup_1m := br_sup_1m
close_1m := get_mtf_close("1")
// 5分钟数据
var float supportLevel_5m = na
var float resistanceLevel_5m = na
var bool brekout_res_5m = false
var bool res_holds_5m = false
var bool sup_holds_5m = false
var bool brekout_sup_5m = false
var float close_5m = na
if mtf_5m
[sup_5m, res_5m, br_res_5m, r_holds_5m, s_holds_5m, br_sup_5m] = get_mtf_data("5")
supportLevel_5m := sup_5m
resistanceLevel_5m := res_5m
brekout_res_5m := br_res_5m
res_holds_5m := r_holds_5m
sup_holds_5m := s_holds_5m
brekout_sup_5m := br_sup_5m
close_5m := get_mtf_close("5")
// 15分钟数据
var float supportLevel_15m = na
var float resistanceLevel_15m = na
var bool brekout_res_15m = false
var bool res_holds_15m = false
var bool sup_holds_15m = false
var bool brekout_sup_15m = false
var float close_15m = na
if mtf_15m
[sup_15m, res_15m, br_res_15m, r_holds_15m, s_holds_15m, br_sup_15m] = get_mtf_data("15")
supportLevel_15m := sup_15m
resistanceLevel_15m := res_15m
brekout_res_15m := br_res_15m
res_holds_15m := r_holds_15m
sup_holds_15m := s_holds_15m
brekout_sup_15m := br_sup_15m
close_15m := get_mtf_close("15")
// 30分钟数据
var float supportLevel_30m = na
var float resistanceLevel_30m = na
var bool brekout_res_30m = false
var bool res_holds_30m = false
var bool sup_holds_30m = false
var bool brekout_sup_30m = false
var float close_30m = na
if mtf_30m
[sup_30m, res_30m, br_res_30m, r_holds_30m, s_holds_30m, br_sup_30m] = get_mtf_data("30")
supportLevel_30m := sup_30m
resistanceLevel_30m := res_30m
brekout_res_30m := br_res_30m
res_holds_30m := r_holds_30m
sup_holds_30m := s_holds_30m
brekout_sup_30m := br_sup_30m
close_30m := get_mtf_close("30")
// 45分钟数据
var float supportLevel_45m = na
var float resistanceLevel_45m = na
var bool brekout_res_45m = false
var bool res_holds_45m = false
var bool sup_holds_45m = false
var bool brekout_sup_45m = false
var float close_45m = na
if mtf_45m
[sup_45m, res_45m, br_res_45m, r_holds_45m, s_holds_45m, br_sup_45m] = get_mtf_data("45")
supportLevel_45m := sup_45m
resistanceLevel_45m := res_45m
brekout_res_45m := br_res_45m
res_holds_45m := r_holds_45m
sup_holds_45m := s_holds_45m
brekout_sup_45m := br_sup_45m
close_45m := get_mtf_close("45")
// 1小时数据
var float supportLevel_1h = na
var float resistanceLevel_1h = na
var bool brekout_res_1h = false
var bool res_holds_1h = false
var bool sup_holds_1h = false
var bool brekout_sup_1h = false
var float close_1h = na
if mtf_1h
[sup_1h, res_1h, br_res_1h, r_holds_1h, s_holds_1h, br_sup_1h] = get_mtf_data("60")
supportLevel_1h := sup_1h
resistanceLevel_1h := res_1h
brekout_res_1h := br_res_1h
res_holds_1h := r_holds_1h
sup_holds_1h := s_holds_1h
brekout_sup_1h := br_sup_1h
close_1h := get_mtf_close("60")
// 4小时数据
var float supportLevel_4h = na
var float resistanceLevel_4h = na
var bool brekout_res_4h = false
var bool res_holds_4h = false
var bool sup_holds_4h = false
var bool brekout_sup_4h = false
var float close_4h = na
if mtf_4h
[sup_4h, res_4h, br_res_4h, r_holds_4h, s_holds_4h, br_sup_4h] = get_mtf_data("240")
supportLevel_4h := sup_4h
resistanceLevel_4h := res_4h
brekout_res_4h := br_res_4h
res_holds_4h := r_holds_4h
sup_holds_4h := s_holds_4h
brekout_sup_4h := br_sup_4h
close_4h := get_mtf_close("240")
//************************************************************************************************************
// 多时间周期表格显示
//************************************************************************************************************
if show_mtf_table and barstate.islast
// 创建多时间周期表格
var table mtf_table = table.new(
position = get_table_position(),
columns = mtf_table_columns,
rows = mtf_table_rows,
bgcolor = color.new(color.white, 85),
border_width = 1)
// 清空表格
table.clear(mtf_table, 0, 0, mtf_table_columns-1, mtf_table_rows-1)
// 获取配置的文字大小
text_size = get_text_size()
// ═════════ 表格标题行 ═════════
table.cell(mtf_table, 0, 0, "时间周期", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
table.cell(mtf_table, 1, 0, "当前价格", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
table.cell(mtf_table, 2, 0, "支撑位", text_color=color.white, bgcolor=color.new(color.green, 30), text_size=text_size)
table.cell(mtf_table, 3, 0, "阻力位", text_color=color.white, bgcolor=color.new(color.red, 30), text_size=text_size)
table.cell(mtf_table, 4, 0, "距支撑", text_color=color.white, bgcolor=color.new(color.green, 30), text_size=text_size)
table.cell(mtf_table, 5, 0, "距阻力", text_color=color.white, bgcolor=color.new(color.red, 30), text_size=text_size)
table.cell(mtf_table, 6, 0, "价格状态", text_color=color.white, bgcolor=color.new(color.blue, 30), text_size=text_size)
table.cell(mtf_table, 7, 0, "市场观点", text_color=color.white, bgcolor=color.new(color.orange, 30), text_size=text_size)
// ═════════ 数据行 ═════════
row = 1
// 1分钟数据行
if mtf_1m and row < mtf_table_rows
[dist_to_sup_1m, dist_to_res_1m] = get_distance_to_levels(close_1m, supportLevel_1m, resistanceLevel_1m)
status_1m = get_price_status(close_1m, supportLevel_1m, resistanceLevel_1m)
status_color_1m = get_price_status_color(close_1m, supportLevel_1m, resistanceLevel_1m)
table.cell(mtf_table, 0, row, "1分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_1m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_1m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_1m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_1m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_1m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_1m, text_color=color.white, bgcolor=status_color_1m, text_size=text_size)
table.cell(mtf_table, 7, row, status_1m, text_color=color.white, bgcolor=status_color_1m, text_size=text_size)
row := row + 1
// 5分钟数据行
if mtf_5m and row < mtf_table_rows
[dist_to_sup_5m, dist_to_res_5m] = get_distance_to_levels(close_5m, supportLevel_5m, resistanceLevel_5m)
status_5m = get_price_status(close_5m, supportLevel_5m, resistanceLevel_5m)
status_color_5m = get_price_status_color(close_5m, supportLevel_5m, resistanceLevel_5m)
table.cell(mtf_table, 0, row, "5分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_5m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_5m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_5m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_5m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_5m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_5m, text_color=color.white, bgcolor=status_color_5m, text_size=text_size)
table.cell(mtf_table, 7, row, status_5m, text_color=color.white, bgcolor=status_color_5m, text_size=text_size)
row := row + 1
// 15分钟数据行
if mtf_15m and row < mtf_table_rows
[dist_to_sup_15m, dist_to_res_15m] = get_distance_to_levels(close_15m, supportLevel_15m, resistanceLevel_15m)
status_15m = get_price_status(close_15m, supportLevel_15m, resistanceLevel_15m)
status_color_15m = get_price_status_color(close_15m, supportLevel_15m, resistanceLevel_15m)
table.cell(mtf_table, 0, row, "15分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_15m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_15m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_15m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_15m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_15m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_15m, text_color=color.white, bgcolor=status_color_15m, text_size=text_size)
table.cell(mtf_table, 7, row, status_15m, text_color=color.white, bgcolor=status_color_15m, text_size=text_size)
row := row + 1
// 30分钟数据行
if mtf_30m and row < mtf_table_rows
[dist_to_sup_30m, dist_to_res_30m] = get_distance_to_levels(close_30m, supportLevel_30m, resistanceLevel_30m)
status_30m = get_price_status(close_30m, supportLevel_30m, resistanceLevel_30m)
status_color_30m = get_price_status_color(close_30m, supportLevel_30m, resistanceLevel_30m)
table.cell(mtf_table, 0, row, "30分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_30m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_30m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_30m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_30m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_30m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_30m, text_color=color.white, bgcolor=status_color_30m, text_size=text_size)
table.cell(mtf_table, 7, row, status_30m, text_color=color.white, bgcolor=status_color_30m, text_size=text_size)
row := row + 1
// 45分钟数据行
if mtf_45m and row < mtf_table_rows
[dist_to_sup_45m, dist_to_res_45m] = get_distance_to_levels(close_45m, supportLevel_45m, resistanceLevel_45m)
status_45m = get_price_status(close_45m, supportLevel_45m, resistanceLevel_45m)
status_color_45m = get_price_status_color(close_45m, supportLevel_45m, resistanceLevel_45m)
table.cell(mtf_table, 0, row, "45分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_45m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_45m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_45m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_45m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_45m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_45m, text_color=color.white, bgcolor=status_color_45m, text_size=text_size)
table.cell(mtf_table, 7, row, status_45m, text_color=color.white, bgcolor=status_color_45m, text_size=text_size)
row := row + 1
// 1小时数据行
if mtf_1h and row < mtf_table_rows
[dist_to_sup_1h, dist_to_res_1h] = get_distance_to_levels(close_1h, supportLevel_1h, resistanceLevel_1h)
status_1h = get_price_status(close_1h, supportLevel_1h, resistanceLevel_1h)
status_color_1h = get_price_status_color(close_1h, supportLevel_1h, resistanceLevel_1h)
table.cell(mtf_table, 0, row, "1小时", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_1h, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_1h, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_1h, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_1h, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_1h, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_1h, text_color=color.white, bgcolor=status_color_1h, text_size=text_size)
table.cell(mtf_table, 7, row, status_1h, text_color=color.white, bgcolor=status_color_1h, text_size=text_size)
row := row + 1
// 4小时数据行
if mtf_4h and row < mtf_table_rows
[dist_to_sup_4h, dist_to_res_4h] = get_distance_to_levels(close_4h, supportLevel_4h, resistanceLevel_4h)
status_4h = get_price_status(close_4h, supportLevel_4h, resistanceLevel_4h)
status_color_4h = get_price_status_color(close_4h, supportLevel_4h, resistanceLevel_4h)
table.cell(mtf_table, 0, row, "4小时", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
table.cell(mtf_table, 1, row, str.tostring(close_4h, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
table.cell(mtf_table, 2, row, str.tostring(supportLevel_4h, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_4h, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_4h, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_4h, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
table.cell(mtf_table, 6, row, status_4h, text_color=color.white, bgcolor=status_color_4h, text_size=text_size)
table.cell(mtf_table, 7, row, status_4h, text_color=color.white, bgcolor=status_color_4h, text_size=text_size)
// ═════════ 输出支撑阻力位数据供webhook使用 ════════
plot(supportLevel, title="supportLevel", display=display.none)
plot(resistanceLevel, title="resistanceLevel", display=display.none)
// ◆
// ---------------------------------------------------------------------------------------------------------------------}
// <20>𝙍𝙄𝘾𝙀 𝙎𝙏𝘼𝙏𝙐𝙎 & 𝙈𝘼𝙍𝙆𝙀𝙏 𝙊𝙐𝙏𝙇𝙊𝙊𝙆
// ---------------------------------------------------------------------------------------------------------------------{
// ═════════ 当前图表时间周期价格状态分析 ════════
get_current_price_status() =>
current_price = close
support_level = supportLevel
resistance_level = resistanceLevel
// 计算价格相对位置
if na(support_level) and na(resistance_level)
"无明确支撑阻力"
else if na(support_level)
if current_price > resistance_level
"突破阻力位上方"
else if current_price >= resistance_level * 0.995
"接近阻力位"
else
"阻力位下方"
else if na(resistance_level)
if current_price < support_level
"跌破支撑位下方"
else if current_price <= support_level * 1.005
"接近支撑位"
else
"支撑位上方"
else
range_size = resistance_level - support_level
price_position = (current_price - support_level) / range_size
if current_price > resistance_level
"突破阻力位上方"
else if current_price < support_level
"跌破支撑位下方"
else if price_position >= 0.8
"接近阻力位"
else if price_position <= 0.2
"接近支撑位"
else
"区间中部运行"
// ═════════ 市场观点生成 ════════
get_market_outlook() =>
current_status = get_current_price_status()
// 基于价格状态和突破情况生成观点
if brekout_res and res_is_sup[1]
"看涨:阻力转支撑确认,建议关注回调买入机会"
else if brekout_sup and sup_is_res[1]
"看跌:支撑转阻力确认,建议关注反弹卖出机会"
else if brekout_res
"看涨:突破阻力位,建议关注回踩确认后的追涨机会"
else if brekout_sup
"看跌:跌破支撑位,建议关注反弹确认后的追跌机会"
else if res_holds
"中性偏空:阻力位有效,短期上涨受阻"
else if sup_holds
"中性偏多:支撑位有效,短期下跌受限"
else if current_status == "接近阻力位"
"谨慎:接近关键阻力位,注意突破或回落"
else if current_status == "接近支撑位"
"谨慎:接近关键支撑位,注意反弹或破位"
else if current_status == "区间中部运行"
"中性:价格在支撑阻力区间内震荡"
else if current_status == "突破阻力位上方"
"看涨:已突破阻力位,关注持续性"
else if current_status == "跌破支撑位下方"
"看跌:已跌破支撑位,关注反弹力度"
else
"观望:等待明确的支撑阻力信号"
// 获取当前价格状态和市场观点
current_price_status = get_current_price_status()
market_outlook = get_market_outlook()
// ---------------------------------------------------------------------------------------------------------------------}
// <20>𝘼𝙇𝙀𝙍𝙏 𝘾𝙊𝙉𝘿𝙄𝙏𝙄𝙊𝙉𝙎
// ---------------------------------------------------------------------------------------------------------------------{
// 支撑位保持警报
alertcondition(sup_holds, title = '支撑位保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑位保持","位置":"支撑位","信号":"support_holds","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
// 阻力位保持警报
alertcondition(res_holds, title = '阻力位保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力位保持","位置":"阻力位","信号":"resistance_holds","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
// 支撑位突破警报
alertcondition(brekout_sup, title = '支撑位突破', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑位突破","位置":"支撑位下方","信号":"support_breakout","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
// 阻力位突破警报
alertcondition(brekout_res, title = '阻力位突破', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力位突破","位置":"阻力位上方","信号":"resistance_breakout","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
// 阻力转支撑警报
alertcondition(brekout_res and res_is_sup[1], title = '阻力转支撑保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力转支撑保持","位置":"前阻力位","信号":"resistance_as_support","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
// 支撑转阻力警报
alertcondition(brekout_sup and sup_is_res[1], title = '支撑转阻力保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑转阻力保持","位置":"前支撑位","信号":"support_as_resistance","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
// ---------------------------------------------------------------------------------------------------------------------}