Files
tradingview-pine/rsi_conbinined.pine
2025-08-02 04:03:35 +00:00

294 lines
13 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.

//@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)