//@version=6 indicator('RSI 窗口二显示', shorttitle='RSI-W2', overlay=false, max_labels_count=500) //************************************************************************************************************ // RSI 参数设置 //************************************************************************************************************ // RSI 参数组 rsi_src = input.source(close, 'RSI Calculation Source', group='RSI') rsiLength = input.int(14, 'RSI Length', minval=2, group='RSI') smooth = input.bool(true, 'Smooth RSI?', group='RSI') maType = input.string('Ema', 'Moving Average Type', options=['SMA', 'Hull', 'Ema', 'Wma', 'DEMA', 'RMA', 'LINREG', 'TEMA', 'ALMA', 'T3'], group='RSI') smoothP = input.int(4, 'Smoothing Period', group='RSI') sig = input.int(6, 'Sigma for ALMA', group='RSI') // 显示设置 show_segments = input.bool(true, 'Show RSI Segments?', group='Display') show_counting = input.bool(true, 'Show Segment Counting?', group='Display') show_rsi_table = input.bool(true, 'Show RSI Info Table?', group='Display') show_price_labels = input.bool(true, 'Show Price Labels?', group='Display') //************************************************************************************************************ // RSI 辅助函数 //************************************************************************************************************ // 自定义移动平均函数 dema(src, length) => ema1 = ta.ema(src, length) ema2 = ta.ema(ema1, length) 2 * ema1 - ema2 tema(src, length) => ema1 = ta.ema(src, length) ema2 = ta.ema(ema1, length) ema3 = ta.ema(ema2, length) 3 * ema1 - 3 * ema2 + ema3 t3(src, length, vfactor) => ema1 = ta.ema(src, length) ema2 = ta.ema(ema1, length) ema3 = ta.ema(ema2, length) ema4 = ta.ema(ema3, length) ema5 = ta.ema(ema4, length) ema6 = ta.ema(ema5, length) c1 = -vfactor * vfactor * vfactor c2 = 3 * vfactor * vfactor + 3 * vfactor * vfactor * vfactor c3 = -6 * vfactor * vfactor - 3 * vfactor - 3 * vfactor * vfactor * vfactor c4 = 1 + 3 * vfactor + vfactor * vfactor * vfactor + 3 * vfactor * vfactor c1 * ema6 + c2 * ema5 + c3 * ema4 + c4 * ema3 ma(src, len, type, almaSig) => switch type 'SMA' => ta.sma(src, len) 'Hull' => ta.hma(src, len) 'Ema' => ta.ema(src, len) 'Wma' => ta.wma(src, len) 'DEMA' => dema(src, len) 'RMA' => ta.rma(src, len) 'LINREG' => ta.linreg(src, len, 0) 'TEMA' => tema(src, len) 'ALMA' => ta.alma(src, len, 0, almaSig) 'T3' => t3(src, len, 0.7) //************************************************************************************************************ // RSI 计算 //************************************************************************************************************ // 计算RSI rsi = ta.rsi(rsi_src, rsiLength) if smooth rsi := ma(rsi, smoothP, maType, sig) // RSI 机器学习阈值计算 var rsi_values = array.new_float(0) if last_bar_index - bar_index <= 1000 array.push(rsi_values, rsi) var centroids = array.new_float(3) if array.size(rsi_values) > 3 array.set(centroids, 0, array.percentile_linear_interpolation(rsi_values, 25)) array.set(centroids, 1, array.percentile_linear_interpolation(rsi_values, 50)) array.set(centroids, 2, array.percentile_linear_interpolation(rsi_values, 75)) long_S = array.get(centroids, 2) short_S = array.get(centroids, 0) // RSI 状态和计数逻辑 var int rsi_state = 0 var int prev_rsi_state = 0 var int extreme_type = 0 var int segment_count = 0 // 计数标签变量 - 不再使用全局变量,每次状态变化时创建新标签以保留历史 current_state = rsi > long_S ? 1 : rsi < short_S ? -1 : 0 if current_state != rsi_state and not na(rsi) // 确定分段线颜色 segment_color = color.black if prev_rsi_state == 0 and current_state == 1 segment_color := color.new(color.red, 0) // 从中性区进入超买区 else if prev_rsi_state == 0 and current_state == -1 segment_color := color.new(color.blue, 0) // 从中性区进入超卖区 else if prev_rsi_state == 1 and current_state == 0 segment_color := color.new(color.orange, 0) // 从超买区进入中性区 else if prev_rsi_state == -1 and current_state == 0 segment_color := color.new(color.green, 0) // 从超卖区进入中性区 else if prev_rsi_state == 1 and current_state == -1 segment_color := color.new(color.purple, 0) // 从超买区直接到超卖区 else if prev_rsi_state == -1 and current_state == 1 segment_color := color.new(color.yellow, 0) // 从超卖区直接到超买区 else if prev_rsi_state == 1 and current_state == 1 segment_color := color.new(color.maroon, 0) // 超买区内的重复进入 else if prev_rsi_state == -1 and current_state == -1 segment_color := color.new(color.navy, 0) // 超卖区内的重复进入 // 绘制分段线 if show_segments line.new(bar_index, 0, bar_index, 100, color = segment_color, width = 2, style = line.style_solid, extend = extend.none) // 更新计数逻辑 if current_state == 1 if extreme_type != 1 extreme_type := 1 segment_count := 1 else segment_count := segment_count + 1 // 显示超买计数标签(保留历史标签) if show_counting label.new(bar_index, rsi, text = str.tostring(segment_count), style = label.style_label_down, color = color.red, textcolor = color.white, size = size.small) else if current_state == -1 if extreme_type != -1 extreme_type := -1 segment_count := -1 else segment_count := segment_count - 1 // 显示超卖计数标签(保留历史标签) if show_counting label.new(bar_index, rsi, text = str.tostring(segment_count), style = label.style_label_up, color = color.blue, textcolor = color.white, size = size.small) // 更新前一个状态 prev_rsi_state := rsi_state rsi_state := current_state //************************************************************************************************************ // RSI 绘图 //************************************************************************************************************ // RSI 主线 rsi_color = rsi > long_S ? color.red : rsi < short_S ? color.blue : color.gray plot(rsi, 'RSI', color=rsi_color, linewidth=2) // 动态阈值线 plot(long_S, 'Long ML Threshold', color=color.red, linewidth=1) plot(short_S, 'Short ML Threshold', color=color.blue, linewidth=1) // 50中线 hline(50, 'RSI 50', color=color.gray, linestyle=hline.style_dashed) //************************************************************************************************************ // RSI 变化方向计算 //************************************************************************************************************ // 计算RSI变化 rsi_change = not na(rsi[1]) ? rsi - rsi[1] : 0 rsi_direction = rsi_change > 0.1 ? "↗" : rsi_change < -0.1 ? "↘" : "→" rsi_direction_text = rsi_change > 0.1 ? "上升" : rsi_change < -0.1 ? "下降" : "平稳" rsi_change_value = str.tostring(math.abs(rsi_change), '#.##') //************************************************************************************************************ // RSI 价格标签显示(参考MRC原始实现) //************************************************************************************************************ // 价格格式化函数 format_rsi_value(value) => str.tostring(value, '#.##') // 声明RSI标签变量 var label rsi_label = na var label long_threshold_label = na var label short_threshold_label = na var label midline_label = na if show_price_labels and barstate.islast // RSI 主线标签(包含变化方向) rsi_label_text = "RSI: " + format_rsi_value(rsi) + " " + rsi_direction + " (" + rsi_direction_text + " " + rsi_change_value + ")" if na(rsi_label) rsi_label := label.new(bar_index, rsi, rsi_label_text, xloc=xloc.bar_index, style=label.style_label_left, color=rsi_color, textcolor=color.white) else label.set_xy(rsi_label, bar_index, rsi) label.set_text(rsi_label, rsi_label_text) label.set_color(rsi_label, rsi_color) // 超买阈值标签 if na(long_threshold_label) long_threshold_label := label.new(bar_index, long_S, "超买: " + format_rsi_value(long_S), xloc=xloc.bar_index, style=label.style_label_left, color=color.red, textcolor=color.white) else label.set_xy(long_threshold_label, bar_index, long_S) label.set_text(long_threshold_label, "超买: " + format_rsi_value(long_S)) // 超卖阈值标签 if na(short_threshold_label) short_threshold_label := label.new(bar_index, short_S, "超卖: " + format_rsi_value(short_S), xloc=xloc.bar_index, style=label.style_label_left, color=color.blue, textcolor=color.white) else label.set_xy(short_threshold_label, bar_index, short_S) label.set_text(short_threshold_label, "超卖: " + format_rsi_value(short_S)) // 50中线标签 if na(midline_label) midline_label := label.new(bar_index, 50, "中线: 50.00", xloc=xloc.bar_index, style=label.style_label_left, color=color.gray, textcolor=color.white) else label.set_xy(midline_label, bar_index, 50) label.set_text(midline_label, "中线: 50.00") //************************************************************************************************************ // RSI 信息表格 //************************************************************************************************************ if show_rsi_table and barstate.islast // RSI 状态 rsi_position = rsi > long_S ? "超买区" : rsi < short_S ? "超卖区" : "中性区" rsi_cross_count = math.abs(segment_count) cross_type = segment_count > 0 ? "超买穿越" : segment_count < 0 ? "超卖穿越" : "无穿越" // 创建RSI表格(扩展为10行) var table rsi_table = table.new( position = position.bottom_right, columns = 2, rows = 10, bgcolor = color.new(color.yellow, 80), border_width = 1) // 清空表格 table.clear(rsi_table, 0, 0, 1, 9) // 添加RSI标题 table.cell(rsi_table, 0, 0, "RSI指标", text_color=color.black, bgcolor=color.new(color.orange, 70), text_size=size.small) table.cell(rsi_table, 1, 0, "实时数值", text_color=color.black, bgcolor=color.new(color.orange, 70), text_size=size.small) // RSI 值 table.cell(rsi_table, 0, 1, "RSI值", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 1, str.tostring(rsi, '#.##'), text_color=color.black, text_size=size.tiny) // RSI 位置 table.cell(rsi_table, 0, 2, "RSI位置", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 2, rsi_position, text_color=color.black, text_size=size.tiny) // RSI 阈值 table.cell(rsi_table, 0, 3, "超买阈值", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 3, str.tostring(long_S, '#.##'), text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 0, 4, "超卖阈值", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 4, str.tostring(short_S, '#.##'), text_color=color.black, text_size=size.tiny) // RSI 穿越次数 table.cell(rsi_table, 0, 5, "穿越次数", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 5, str.tostring(rsi_cross_count), text_color=color.black, text_size=size.tiny) // RSI 穿越类型 table.cell(rsi_table, 0, 6, "穿越类型", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 6, cross_type, text_color=color.black, text_size=size.tiny) // RSI 状态标记 table.cell(rsi_table, 0, 7, "状态标记", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 7, str.tostring(segment_count), text_color=color.black, text_size=size.tiny) // RSI 变化方向 table.cell(rsi_table, 0, 8, "变化方向", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 8, rsi_direction_text + " " + rsi_direction, text_color=color.black, text_size=size.tiny) // RSI 变化幅度 table.cell(rsi_table, 0, 9, "变化幅度", text_color=color.black, text_size=size.tiny) table.cell(rsi_table, 1, 9, rsi_change_value, text_color=color.black, text_size=size.tiny)