1978 lines
131 KiB
Plaintext
1978 lines
131 KiB
Plaintext
//@version=6
|
||
indicator('MRC+MA200+RSI 综合指标4', shorttitle='MRC+MA200+RSI4', overlay=true, max_labels_count=500)
|
||
|
||
//************************************************************************************************************
|
||
// 参数设置区域
|
||
//************************************************************************************************************
|
||
|
||
// ═════════ MRC 参数 ════════
|
||
mrcSet = input(false, '═════════ MRC Parameter ════════')
|
||
source = input(hlc3, title='Price Source', group='MRC')
|
||
type = input.string('SuperSmoother', title='Filter Type', options=['SuperSmoother', 'Ehlers EMA', 'Gaussian', 'Butterworth', 'BandStop', 'SMA', 'EMA', 'RMA'], group='MRC')
|
||
length = input.int(200, title='Lookback Period', minval=1, group='MRC')
|
||
innermult = input.float(1.0, title='Inner Channel Size Multiplier', minval=0.1, group='MRC')
|
||
outermult = input.float(2.415, title='Outer Channel Size Multiplier', minval=0.1, group='MRC')
|
||
|
||
// ═════════ MA200 参数 ════════
|
||
maSet = input(false, '═════════ MA200 Parameter ════════')
|
||
exponential = input.bool(true, title='使用指数移动平均线 (EMA)', group='MA200')
|
||
show_ma_lines = input.bool(true, title='显示MA线条', group='MA200')
|
||
|
||
// ═════════ MA200距离判定参数(参考原MA200代码) ════════
|
||
distanceSet = input(false, '═════════ MA200 Distance Analysis Parameter ════════')
|
||
default_dist = input.float(3.0, title='默认 MA200 距离阈值', minval=0.1, step=0.1, group='Distance')
|
||
btc_dist = input.float(300.0, title='BTCUSD MA200 距离阈值', minval=0.1, step=0.1, group='Distance')
|
||
xau_dist = input.float(3.5, title='XAUUSD MA200 距离阈值', minval=0.1, step=0.1, group='Distance')
|
||
eth_dist = input.float(9.0, title='ETHUSD MA200 距离阈值', minval=0.1, step=0.1, group='Distance')
|
||
gbp_dist = input.float(0.3, title='GBPJPY MA200 距离阈值', minval=0.1, step=0.1, group='Distance')
|
||
|
||
flatness_period = input.int(20, title='MA200 波动回看周期', minval=1, group='Distance')
|
||
flatness_threshold = input.float(0.5, title='MA200 平坦度阈值', minval=0.01, step=0.01, group='Distance')
|
||
oscillation_bars = input.int(10, title='价格波动回看周期', minval=1, group='Distance')
|
||
oscillation_threshold = input.float(5.0, title='价格波动范围阈值', minval=0.1, step=0.1, group='Distance')
|
||
|
||
// ═════════ R1/S1距离判定参数 ════════
|
||
r1s1DistanceSet = input(false, '═════════ R1/S1 Distance Analysis Parameter ════════')
|
||
default_r1s1_dist = input.float(3.0, title='默认 R1/S1 距离阈值', minval=0.1, step=0.1, group='R1S1Distance')
|
||
btc_r1s1_dist = input.float(300.0, title='BTCUSD R1/S1 距离阈值', minval=0.1, step=0.1, group='R1S1Distance')
|
||
xau_r1s1_dist = input.float(3.5, title='XAUUSD R1/S1 距离阈值', minval=0.1, step=0.1, group='R1S1Distance')
|
||
eth_r1s1_dist = input.float(9.0, title='ETHUSD R1/S1 距离阈值', minval=0.1, step=0.1, group='R1S1Distance')
|
||
gbp_r1s1_dist = input.float(0.3, title='GBPJPY R1/S1 距离阈值', minval=0.1, step=0.1, group='R1S1Distance')
|
||
|
||
// ═════════ K线标记配置 ════════
|
||
signalSet = input(false, '═════════ Signal Marks Configuration ════════')
|
||
show_long_marks = input.bool(true, title='显示做多标记', group='Signals')
|
||
show_short_marks = input.bool(true, title='显示做空标记', group='Signals')
|
||
show_oscillation_marks = input.bool(false, title='显示震荡标记', group='Signals')
|
||
show_advanced_alerts = input.bool(true, title='显示高级警报标记', group='Signals')
|
||
advanced_alert_style = input.string('超级突出', title='高级警报样式', options=['普通', '突出', '超级突出'], group='Signals')
|
||
arrow_size = input.string('small', title='图形标记大小', options=['tiny', 'small', 'normal', 'large', 'huge'], group='Signals')
|
||
|
||
// ═════════ 高级警报配置 ════════
|
||
advancedAlertSet = input(false, '═════════ Advanced Alert Configuration ════════')
|
||
enable_advanced_alerts = input.bool(true, title='启用高级警报系统', group='AdvancedAlerts')
|
||
time_window_5min = input.int(5, title='条件2时间窗口(分钟)', minval=1, maxval=30, group='AdvancedAlerts')
|
||
time_window_15min = input.int(15, title='条件3时间窗口(分钟)', minval=5, maxval=60, group='AdvancedAlerts')
|
||
time_window_10min = input.int(10, title='条件4时间窗口(分钟)', minval=5, maxval=30, group='AdvancedAlerts')
|
||
require_all_conditions = input.bool(true, title='要求所有条件都满足', group='AdvancedAlerts')
|
||
alert_cooldown_minutes = input.int(30, title='警报冷却时间(分钟)', minval=1, maxval=120, group='AdvancedAlerts')
|
||
|
||
// ═════════ 价格标签配置 ════════
|
||
labelSet = input(false, '═════════ Price Labels Configuration ════════')
|
||
show_mean_label = input.bool(true, title='显示MEAN价格标签', group='Labels')
|
||
show_r1_label = input.bool(true, title='显示R1价格标签', group='Labels')
|
||
show_s1_label = input.bool(true, title='显示S1价格标签', group='Labels')
|
||
show_r2_label = input.bool(false, title='显示R2价格标签', group='Labels')
|
||
show_s2_label = input.bool(false, title='显示S2价格标签', group='Labels')
|
||
show_ma50_label = input.bool(true, title='显示MA50价格标签', group='Labels')
|
||
show_ma100_label = input.bool(false, title='显示MA100价格标签', group='Labels')
|
||
show_ma200_label = input.bool(true, title='显示MA200价格标签', group='Labels')
|
||
|
||
// ═════════ 线条粗细配置 ════════
|
||
lineSet = input(false, '═════════ Line Width Configuration ════════')
|
||
mean_width = input.int(3, title='MEAN线宽度', minval=1, maxval=5, group='Lines')
|
||
r1_s1_width = input.int(3, title='R1/S1线宽度', minval=1, maxval=5, group='Lines')
|
||
r2_s2_width = input.int(2, title='R2/S2线宽度', minval=1, maxval=5, group='Lines')
|
||
|
||
// ═════════ 表格大小配置 ════════
|
||
tableSet = input(false, '═════════ Table Size Configuration ════════')
|
||
table_text_size = input.string('tiny', title='表格文字大小', options=['auto', 'tiny', 'small', 'normal', 'large', 'huge'], group='Table')
|
||
table_rows = input.int(15, title='信息表格行数', minval=10, maxval=20, group='Table')
|
||
table_columns = input.int(4, title='信息表格列数', minval=2, maxval=6, group='Table')
|
||
mtf_table_rows = input.int(9, title='多时间框架表格行数', minval=6, maxval=12, group='Table')
|
||
mtf_table_columns = input.int(12, title='多时间框架表格列数', minval=8, maxval=14, group='Table')
|
||
|
||
// 删除不再使用的斜率阈值计算
|
||
|
||
// ═════════ RSI 参数 ════════
|
||
rsiSet = input(false, '═════════ RSI Parameter ════════')
|
||
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')
|
||
|
||
// ═════════ 多时间框架设置 ════════
|
||
mtfSet = input(false, '═════════ Multi-Timeframe Settings ════════')
|
||
show_mtf_table = input.bool(true, title='显示多时间框架表格', group='MTF')
|
||
mtf_1m = input.bool(true, title='显示1分钟数据', group='MTF')
|
||
mtf_5m = input.bool(true, title='显示5分钟数据', group='MTF')
|
||
mtf_15m = input.bool(true, title='显示15分钟数据', group='MTF')
|
||
mtf_30m = input.bool(true, title='显示30分钟数据', group='MTF')
|
||
mtf_45m = input.bool(true, title='显示45分钟数据', group='MTF')
|
||
mtf_1h = input.bool(true, title='显示1小时数据', group='MTF')
|
||
mtf_4h = input.bool(true, title='显示4小时数据', group='MTF')
|
||
|
||
// ═════════ 显示设置 ════════
|
||
displaySet = input(false, '═════════ Display Settings ════════')
|
||
show_info_table = input.bool(false, title='显示信息表格', group='Display')
|
||
show_rsi_table = input.bool(false, title='显示RSI表格', group='Display')
|
||
table_position = input.string('top_right', title='表格位置', options=['top_left', 'top_center', 'top_right', 'middle_left', 'middle_center', 'middle_right', 'bottom_left', 'bottom_center', 'bottom_right'], group='Display')
|
||
|
||
//************************************************************************************************************
|
||
// 辅助函数定义
|
||
//************************************************************************************************************
|
||
|
||
// ═════════ 距离阈值切换(参考原MA200代码) ════════
|
||
get_distance_threshold() =>
|
||
sym = ticker.standard(syminfo.tickerid)
|
||
switch sym
|
||
'TICKMILL:BTCUSD' => btc_dist
|
||
'TICKMILL:XAUUSD' => xau_dist
|
||
'TICKMILL:ETHUSD' => eth_dist
|
||
'TICKMILL:GBPJPY' => gbp_dist
|
||
=> default_dist
|
||
|
||
// ═════════ R1/S1距离阈值切换 ════════
|
||
get_r1s1_distance_threshold() =>
|
||
sym = ticker.standard(syminfo.tickerid)
|
||
switch sym
|
||
'TICKMILL:BTCUSD' => btc_r1s1_dist
|
||
'TICKMILL:XAUUSD' => xau_r1s1_dist
|
||
'TICKMILL:ETHUSD' => eth_r1s1_dist
|
||
'TICKMILL:GBPJPY' => gbp_r1s1_dist
|
||
=> default_r1s1_dist
|
||
|
||
// ═════════ 表格文字大小转换 ════════
|
||
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.tiny
|
||
|
||
// ═════════ 距离背景颜色函数 ════════
|
||
get_distance_bg_color(distance_value, threshold) =>
|
||
if na(distance_value)
|
||
color.new(color.gray, 80) // 无数据时为灰色
|
||
else if distance_value > threshold
|
||
color.new(color.green, 80) // 距离大于阈值时为浅绿色
|
||
else
|
||
color.new(color.red, 80) // 距离小于阈值时为浅红色
|
||
|
||
// ═════════ 箭头大小转换 ════════
|
||
get_arrow_size() =>
|
||
switch arrow_size
|
||
'tiny' => size.tiny
|
||
'small' => size.small
|
||
'normal' => size.normal
|
||
'large' => size.large
|
||
'huge' => size.huge
|
||
=> size.large
|
||
|
||
// ═════════ 多时间框架辅助函数 ════════
|
||
// 获取信号颜色
|
||
get_signal_color(osc_sig, long_sig, short_sig) =>
|
||
osc_sig ? color.new(color.yellow, 60) : long_sig ? color.new(color.green, 40) : short_sig ? color.new(color.red, 40) : color.new(color.gray, 80)
|
||
|
||
// 获取信号文本
|
||
get_signal_text(osc_sig, long_sig, short_sig) =>
|
||
osc_sig ? "震荡⚡" : long_sig ? "做多🚀" : short_sig ? "做空🔻" : "观望"
|
||
|
||
// 获取最终判断
|
||
get_final_judgment(osc_sig, long_sig, short_sig) =>
|
||
osc_sig ? "✓震荡" : long_sig ? "✓做多" : short_sig ? "✓做空" : "观望"
|
||
|
||
// 获取RSI状态颜色(根据条件标记)
|
||
get_rsi_color(rsi_val, long_threshold, short_threshold, is_neutral, is_overbought, is_oversold) =>
|
||
if is_neutral
|
||
color.new(color.orange, 40) // 震荡条件
|
||
else if is_overbought
|
||
color.new(color.green, 40) // 做多条件
|
||
else if is_oversold
|
||
color.new(color.red, 40) // 做空条件
|
||
else
|
||
color.white
|
||
|
||
// 获取价格位置颜色(根据条件标记)
|
||
get_price_color(close_val, upband1_val, loband1_val, in_channel, above_r1, below_s1) =>
|
||
if in_channel
|
||
color.new(color.orange, 40) // 震荡条件
|
||
else if above_r1
|
||
color.new(color.green, 40) // 做多条件
|
||
else if below_s1
|
||
color.new(color.red, 40) // 做空条件
|
||
else
|
||
color.white
|
||
|
||
// 获取MA50位置颜色(根据条件标记)
|
||
get_ma50_color(ma50_val, meanline_val, above_mean, below_mean) =>
|
||
if above_mean
|
||
color.new(color.green, 40) // 做多条件
|
||
else if below_mean
|
||
color.new(color.red, 40) // 做空条件
|
||
else
|
||
color.white
|
||
|
||
// 获取MA200距离颜色(根据条件标记)
|
||
get_ma200_distance_color(distance_val, threshold_val, is_near, is_far) =>
|
||
if is_near
|
||
color.new(color.orange, 40) // 震荡条件
|
||
else if is_far
|
||
color.new(color.gray, 60) // 趋势条件(做多/做空都需要远离MA200)
|
||
else
|
||
color.white
|
||
|
||
// 获取价格位置文本
|
||
get_price_position(close_val, upband1_val, loband1_val) =>
|
||
if na(close_val) or na(upband1_val) or na(loband1_val)
|
||
"N/A"
|
||
else if close_val > upband1_val
|
||
"R1上"
|
||
else if close_val < loband1_val
|
||
"S1下"
|
||
else
|
||
"通道内"
|
||
|
||
// 获取价格与MEAN位置关系文本
|
||
get_price_mean_position(close_val, meanline_val) =>
|
||
if na(close_val) or na(meanline_val)
|
||
"N/A"
|
||
else if close_val > meanline_val
|
||
"偏多"
|
||
else if close_val < meanline_val
|
||
"偏空"
|
||
else
|
||
"平衡"
|
||
|
||
// 获取价格与MEAN位置关系颜色
|
||
get_price_mean_color(close_val, meanline_val) =>
|
||
if na(close_val) or na(meanline_val)
|
||
color.white
|
||
else if close_val > meanline_val
|
||
color.new(color.green, 40) // 偏多 - 绿色
|
||
else if close_val < meanline_val
|
||
color.new(color.red, 40) // 偏空 - 红色
|
||
else
|
||
color.new(color.gray, 40) // 平衡 - 灰色
|
||
|
||
// 获取MA50位置文本
|
||
get_ma50_position(ma50_val, meanline_val) =>
|
||
if na(ma50_val) or na(meanline_val)
|
||
"N/A"
|
||
else if ma50_val > meanline_val
|
||
"MEAN上"
|
||
else if ma50_val < meanline_val
|
||
"MEAN下"
|
||
else
|
||
"MEAN附近"
|
||
|
||
// 获取RSI状态文本
|
||
get_rsi_status(rsi_val, long_threshold, short_threshold) =>
|
||
if na(rsi_val)
|
||
"N/A"
|
||
else if rsi_val > long_threshold
|
||
"超买"
|
||
else if rsi_val < short_threshold
|
||
"超卖"
|
||
else
|
||
"震荡"
|
||
|
||
|
||
|
||
// SuperSmoother 函数(与原始MRC保持一致)
|
||
supersmoother(src, len) =>
|
||
pi = 2 * math.asin(1)
|
||
s_a1 = math.exp(-math.sqrt(2) * pi / len)
|
||
s_b1 = 2 * s_a1 * math.cos(math.sqrt(2) * pi / len)
|
||
s_c3 = -math.pow(s_a1, 2)
|
||
s_c2 = s_b1
|
||
s_c1 = 1 - s_c2 - s_c3
|
||
ss = 0.0
|
||
ss := s_c1 * src + s_c2 * nz(ss[1], src[1]) + s_c3 * nz(ss[2], src[2])
|
||
ss
|
||
|
||
// SAK 平滑函数
|
||
SAK_smoothing(type, src, len) =>
|
||
switch type
|
||
'SMA' => ta.sma(src, len)
|
||
'EMA' => ta.ema(src, len)
|
||
'RMA' => ta.rma(src, len)
|
||
'Gaussian' => ta.sma(src, len) // 简化版本
|
||
'Butterworth' => ta.sma(src, len) // 简化版本
|
||
'BandStop' => ta.sma(src, len) // 简化版本
|
||
'Ehlers EMA' => ta.ema(src, len) // 简化版本
|
||
=> ta.sma(src, len)
|
||
|
||
// MRC 计算函数
|
||
get_mrc() =>
|
||
v_condition = 0
|
||
v_meanline = source
|
||
v_meanrange = supersmoother(ta.tr, length)
|
||
|
||
// 计算π乘数(与原始MRC保持一致)
|
||
pi = 2 * math.asin(1)
|
||
mult = pi * innermult
|
||
mult2 = pi * outermult
|
||
|
||
// 获取均线值
|
||
if type == 'SuperSmoother'
|
||
v_meanline := supersmoother(source, length)
|
||
else
|
||
v_meanline := SAK_smoothing(type, source, length)
|
||
|
||
// 计算通道(使用π乘数)
|
||
upband1 = v_meanline + v_meanrange * mult
|
||
loband1 = v_meanline - v_meanrange * mult
|
||
upband2 = v_meanline + v_meanrange * mult2
|
||
loband2 = v_meanline - v_meanrange * mult2
|
||
|
||
[v_meanline, v_meanrange, upband1, loband1, upband2, loband2, v_condition]
|
||
|
||
// 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穿越次数计算函数
|
||
mtf_rsi_segment_count(long_threshold, short_threshold) =>
|
||
var int rsi_state = 0
|
||
var int extreme_type = 0
|
||
var int segment_count = 0
|
||
|
||
rsi_val = smooth ? ma(ta.rsi(rsi_src, rsiLength), smoothP, maType, sig) : ta.rsi(rsi_src, rsiLength)
|
||
current_state = rsi_val > long_threshold ? 1 : rsi_val < short_threshold ? -1 : 0
|
||
|
||
if current_state != rsi_state and not na(rsi_val)
|
||
if current_state == 1
|
||
if extreme_type != 1
|
||
extreme_type := 1
|
||
segment_count := 1
|
||
else
|
||
segment_count := segment_count + 1
|
||
else if current_state == -1
|
||
if extreme_type != -1
|
||
extreme_type := -1
|
||
segment_count := -1
|
||
else
|
||
segment_count := segment_count - 1
|
||
|
||
rsi_state := current_state
|
||
|
||
math.abs(segment_count)
|
||
|
||
// 计算多时间框架RSI穿越次数
|
||
get_mtf_rsi_crossover_count(tf, long_threshold, short_threshold) =>
|
||
request.security(syminfo.tickerid, tf, mtf_rsi_segment_count(long_threshold, short_threshold), lookahead=barmerge.lookahead_off)
|
||
|
||
//************************************************************************************************************
|
||
// 多时间框架计算函数
|
||
//************************************************************************************************************
|
||
|
||
// 多时间框架MRC计算函数
|
||
get_mtf_mrc(tf) =>
|
||
request.security(syminfo.tickerid, tf, get_mrc(), lookahead=barmerge.lookahead_off)
|
||
|
||
// 多时间框架MA计算函数
|
||
get_mtf_ma(tf) =>
|
||
ma50_mtf = request.security(syminfo.tickerid, tf, exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off)
|
||
ma100_mtf = request.security(syminfo.tickerid, tf, exponential ? ta.ema(close, 100) : ta.sma(close, 100), lookahead=barmerge.lookahead_off)
|
||
ma200_mtf = request.security(syminfo.tickerid, tf, exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off)
|
||
close_mtf = request.security(syminfo.tickerid, tf, close, lookahead=barmerge.lookahead_off)
|
||
[ma50_mtf, ma100_mtf, ma200_mtf, close_mtf]
|
||
|
||
// 多时间框架RSI计算函数
|
||
get_mtf_rsi(tf) =>
|
||
rsi_mtf = request.security(syminfo.tickerid, tf, ta.rsi(rsi_src, rsiLength), lookahead=barmerge.lookahead_off)
|
||
if smooth
|
||
rsi_mtf := request.security(syminfo.tickerid, tf, ma(ta.rsi(rsi_src, rsiLength), smoothP, maType, sig), lookahead=barmerge.lookahead_off)
|
||
rsi_mtf
|
||
|
||
//************************************************************************************************************
|
||
// 指标计算
|
||
//************************************************************************************************************
|
||
|
||
// ═════════ MA 计算 ═════════
|
||
src = close
|
||
ma50 = exponential ? ta.ema(src, 50) : ta.sma(src, 50)
|
||
ma100 = exponential ? ta.ema(src, 100) : ta.sma(src, 100)
|
||
ma200 = exponential ? ta.ema(src, 200) : ta.sma(src, 200)
|
||
|
||
// ═════════ MRC 计算 ═════════
|
||
[meanline, meanrange, upband1, loband1, upband2, loband2, condition] = get_mrc()
|
||
|
||
// ═════════ 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穿越次数(避免在条件块内调用) ═════════
|
||
cross_count_1m = mtf_1m ? get_mtf_rsi_crossover_count("1", long_S, short_S) : na
|
||
cross_count_5m = mtf_5m ? get_mtf_rsi_crossover_count("5", long_S, short_S) : na
|
||
cross_count_15m = mtf_15m ? get_mtf_rsi_crossover_count("15", long_S, short_S) : na
|
||
cross_count_30m = mtf_30m ? get_mtf_rsi_crossover_count("30", long_S, short_S) : na
|
||
cross_count_45m = mtf_45m ? get_mtf_rsi_crossover_count("45", long_S, short_S) : na
|
||
cross_count_1h = mtf_1h ? get_mtf_rsi_crossover_count("60", long_S, short_S) : na
|
||
cross_count_4h = mtf_4h ? get_mtf_rsi_crossover_count("240", long_S, short_S) : na
|
||
|
||
// RSI 状态和计数逻辑
|
||
var int 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)
|
||
if current_state == 1
|
||
if extreme_type != 1
|
||
extreme_type := 1
|
||
segment_count := 1
|
||
else
|
||
segment_count := segment_count + 1
|
||
else if current_state == -1
|
||
if extreme_type != -1
|
||
extreme_type := -1
|
||
segment_count := -1
|
||
else
|
||
segment_count := segment_count - 1
|
||
|
||
rsi_state := current_state
|
||
|
||
// ═════════ 多时间框架数据获取 ═════════
|
||
// 直接获取多时间框架数据(简化方法)
|
||
|
||
// 1分钟数据
|
||
rsi_1m = mtf_1m ? get_mtf_rsi("1") : na
|
||
close_1m = mtf_1m ? request.security(syminfo.tickerid, "1", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_1m = mtf_1m ? request.security(syminfo.tickerid, "1", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_1m = mtf_1m ? request.security(syminfo.tickerid, "1", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_1m = mtf_1m ? request.security(syminfo.tickerid, "1", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_1m = mtf_1m ? request.security(syminfo.tickerid, "1", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_1m = mtf_1m and not na(meanline_1m) and not na(meanrange_1m) ? meanline_1m + meanrange_1m * (2 * math.asin(1) * innermult) : na
|
||
loband1_1m = mtf_1m and not na(meanline_1m) and not na(meanrange_1m) ? meanline_1m - meanrange_1m * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 5分钟数据
|
||
rsi_5m = mtf_5m ? get_mtf_rsi("5") : na
|
||
close_5m = mtf_5m ? request.security(syminfo.tickerid, "5", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_5m = mtf_5m ? request.security(syminfo.tickerid, "5", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_5m = mtf_5m ? request.security(syminfo.tickerid, "5", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_5m = mtf_5m ? request.security(syminfo.tickerid, "5", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_5m = mtf_5m ? request.security(syminfo.tickerid, "5", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_5m = mtf_5m and not na(meanline_5m) and not na(meanrange_5m) ? meanline_5m + meanrange_5m * (2 * math.asin(1) * innermult) : na
|
||
loband1_5m = mtf_5m and not na(meanline_5m) and not na(meanrange_5m) ? meanline_5m - meanrange_5m * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 15分钟数据
|
||
rsi_15m = mtf_15m ? get_mtf_rsi("15") : na
|
||
close_15m = mtf_15m ? request.security(syminfo.tickerid, "15", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_15m = mtf_15m ? request.security(syminfo.tickerid, "15", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_15m = mtf_15m ? request.security(syminfo.tickerid, "15", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_15m = mtf_15m ? request.security(syminfo.tickerid, "15", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_15m = mtf_15m ? request.security(syminfo.tickerid, "15", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_15m = mtf_15m and not na(meanline_15m) and not na(meanrange_15m) ? meanline_15m + meanrange_15m * (2 * math.asin(1) * innermult) : na
|
||
loband1_15m = mtf_15m and not na(meanline_15m) and not na(meanrange_15m) ? meanline_15m - meanrange_15m * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 30分钟数据
|
||
rsi_30m = mtf_30m ? get_mtf_rsi("30") : na
|
||
close_30m = mtf_30m ? request.security(syminfo.tickerid, "30", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_30m = mtf_30m ? request.security(syminfo.tickerid, "30", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_30m = mtf_30m ? request.security(syminfo.tickerid, "30", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_30m = mtf_30m ? request.security(syminfo.tickerid, "30", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_30m = mtf_30m ? request.security(syminfo.tickerid, "30", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_30m = mtf_30m and not na(meanline_30m) and not na(meanrange_30m) ? meanline_30m + meanrange_30m * (2 * math.asin(1) * innermult) : na
|
||
loband1_30m = mtf_30m and not na(meanline_30m) and not na(meanrange_30m) ? meanline_30m - meanrange_30m * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 45分钟数据
|
||
rsi_45m = mtf_45m ? get_mtf_rsi("45") : na
|
||
close_45m = mtf_45m ? request.security(syminfo.tickerid, "45", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_45m = mtf_45m ? request.security(syminfo.tickerid, "45", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_45m = mtf_45m ? request.security(syminfo.tickerid, "45", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_45m = mtf_45m ? request.security(syminfo.tickerid, "45", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_45m = mtf_45m ? request.security(syminfo.tickerid, "45", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_45m = mtf_45m and not na(meanline_45m) and not na(meanrange_45m) ? meanline_45m + meanrange_45m * (2 * math.asin(1) * innermult) : na
|
||
loband1_45m = mtf_45m and not na(meanline_45m) and not na(meanrange_45m) ? meanline_45m - meanrange_45m * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 1小时数据
|
||
rsi_1h = mtf_1h ? get_mtf_rsi("60") : na
|
||
close_1h = mtf_1h ? request.security(syminfo.tickerid, "60", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_1h = mtf_1h ? request.security(syminfo.tickerid, "60", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_1h = mtf_1h ? request.security(syminfo.tickerid, "60", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_1h = mtf_1h ? request.security(syminfo.tickerid, "60", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_1h = mtf_1h ? request.security(syminfo.tickerid, "60", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_1h = mtf_1h and not na(meanline_1h) and not na(meanrange_1h) ? meanline_1h + meanrange_1h * (2 * math.asin(1) * innermult) : na
|
||
loband1_1h = mtf_1h and not na(meanline_1h) and not na(meanrange_1h) ? meanline_1h - meanrange_1h * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 4小时数据
|
||
rsi_4h = mtf_4h ? get_mtf_rsi("240") : na
|
||
close_4h = mtf_4h ? request.security(syminfo.tickerid, "240", close, lookahead=barmerge.lookahead_off) : na
|
||
ma50_4h = mtf_4h ? request.security(syminfo.tickerid, "240", exponential ? ta.ema(close, 50) : ta.sma(close, 50), lookahead=barmerge.lookahead_off) : na
|
||
ma200_4h = mtf_4h ? request.security(syminfo.tickerid, "240", exponential ? ta.ema(close, 200) : ta.sma(close, 200), lookahead=barmerge.lookahead_off) : na
|
||
meanline_4h = mtf_4h ? request.security(syminfo.tickerid, "240", supersmoother(source, length), lookahead=barmerge.lookahead_off) : na
|
||
meanrange_4h = mtf_4h ? request.security(syminfo.tickerid, "240", supersmoother(ta.tr, length), lookahead=barmerge.lookahead_off) : na
|
||
upband1_4h = mtf_4h and not na(meanline_4h) and not na(meanrange_4h) ? meanline_4h + meanrange_4h * (2 * math.asin(1) * innermult) : na
|
||
loband1_4h = mtf_4h and not na(meanline_4h) and not na(meanrange_4h) ? meanline_4h - meanrange_4h * (2 * math.asin(1) * innermult) : na
|
||
|
||
// 计算多时间框架信号(修正版本,与原指标逻辑一致)
|
||
// 1分钟信号
|
||
distance_1m = mtf_1m and not na(close_1m) and not na(ma200_1m) ? math.abs(close_1m - ma200_1m) : na
|
||
distance_threshold_1m = get_distance_threshold()
|
||
|
||
// 1分钟R1/S1/MEAN距离计算
|
||
distance_to_r1_1m = mtf_1m and not na(close_1m) and not na(upband1_1m) ? math.abs(close_1m - upband1_1m) : na
|
||
distance_to_s1_1m = mtf_1m and not na(close_1m) and not na(loband1_1m) ? math.abs(close_1m - loband1_1m) : na
|
||
distance_to_mean_1m = mtf_1m and not na(close_1m) and not na(meanline_1m) ? math.abs(close_1m - meanline_1m) : na
|
||
|
||
// 1分钟完整信号判断
|
||
rsi_neutral_1m = mtf_1m and not na(rsi_1m) ? (rsi_1m >= short_S and rsi_1m <= long_S) : false
|
||
price_in_channel_1m = mtf_1m and not na(close_1m) and not na(upband1_1m) and not na(loband1_1m) ? (close_1m >= loband1_1m and close_1m <= upband1_1m) : false
|
||
ma200_near_1m = mtf_1m and not na(distance_1m) ? (distance_1m <= distance_threshold_1m) : false
|
||
osc_1m = rsi_neutral_1m or price_in_channel_1m or ma200_near_1m
|
||
|
||
rsi_overbought_1m = mtf_1m and not na(rsi_1m) ? (rsi_1m > long_S) : false
|
||
price_above_r1_1m = mtf_1m and not na(close_1m) and not na(upband1_1m) ? (close_1m > upband1_1m) : false
|
||
ma200_far_1m = mtf_1m and not na(distance_1m) ? (distance_1m > distance_threshold_1m) : false
|
||
ma50_above_mean_1m = mtf_1m and not na(ma50_1m) and not na(meanline_1m) ? (ma50_1m > meanline_1m) : false
|
||
long_1m = rsi_overbought_1m and price_above_r1_1m and ma200_far_1m and ma50_above_mean_1m
|
||
|
||
rsi_oversold_1m = mtf_1m and not na(rsi_1m) ? (rsi_1m < short_S) : false
|
||
price_below_s1_1m = mtf_1m and not na(close_1m) and not na(loband1_1m) ? (close_1m < loband1_1m) : false
|
||
ma50_below_mean_1m = mtf_1m and not na(ma50_1m) and not na(meanline_1m) ? (ma50_1m < meanline_1m) : false
|
||
short_1m = rsi_oversold_1m and price_below_s1_1m and ma200_far_1m and ma50_below_mean_1m
|
||
|
||
// 5分钟信号
|
||
distance_5m = mtf_5m and not na(close_5m) and not na(ma200_5m) ? math.abs(close_5m - ma200_5m) : na
|
||
|
||
// 5分钟R1/S1/MEAN距离计算
|
||
distance_to_r1_5m = mtf_5m and not na(close_5m) and not na(upband1_5m) ? math.abs(close_5m - upband1_5m) : na
|
||
distance_to_s1_5m = mtf_5m and not na(close_5m) and not na(loband1_5m) ? math.abs(close_5m - loband1_5m) : na
|
||
distance_to_mean_5m = mtf_5m and not na(close_5m) and not na(meanline_5m) ? math.abs(close_5m - meanline_5m) : na
|
||
|
||
rsi_neutral_5m = mtf_5m and not na(rsi_5m) ? (rsi_5m >= short_S and rsi_5m <= long_S) : false
|
||
price_in_channel_5m = mtf_5m and not na(close_5m) and not na(upband1_5m) and not na(loband1_5m) ? (close_5m >= loband1_5m and close_5m <= upband1_5m) : false
|
||
ma200_near_5m = mtf_5m and not na(distance_5m) ? (distance_5m <= distance_threshold_1m) : false
|
||
osc_5m = rsi_neutral_5m or price_in_channel_5m or ma200_near_5m
|
||
|
||
rsi_overbought_5m = mtf_5m and not na(rsi_5m) ? (rsi_5m > long_S) : false
|
||
price_above_r1_5m = mtf_5m and not na(close_5m) and not na(upband1_5m) ? (close_5m > upband1_5m) : false
|
||
price_above_mean_5m = mtf_5m and not na(close_5m) and not na(meanline_5m) ? (close_5m >= meanline_5m or math.abs(close_5m - meanline_5m) <= get_r1s1_distance_threshold()) : false
|
||
ma200_far_5m = mtf_5m and not na(distance_5m) ? (distance_5m > distance_threshold_1m) : false
|
||
ma50_above_mean_5m = mtf_5m and not na(ma50_5m) and not na(meanline_5m) ? (ma50_5m > meanline_5m) : false
|
||
long_5m = rsi_overbought_5m and price_above_r1_5m and ma200_far_5m and ma50_above_mean_5m
|
||
|
||
rsi_oversold_5m = mtf_5m and not na(rsi_5m) ? (rsi_5m < short_S) : false
|
||
price_below_s1_5m = mtf_5m and not na(close_5m) and not na(loband1_5m) ? (close_5m < loband1_5m) : false
|
||
price_below_mean_5m = mtf_5m and not na(close_5m) and not na(meanline_5m) ? (close_5m <= meanline_5m or math.abs(close_5m - meanline_5m) <= get_r1s1_distance_threshold()) : false
|
||
ma50_below_mean_5m = mtf_5m and not na(ma50_5m) and not na(meanline_5m) ? (ma50_5m < meanline_5m) : false
|
||
short_5m = rsi_oversold_5m and price_below_s1_5m and ma200_far_5m and ma50_below_mean_5m
|
||
|
||
// 15分钟信号
|
||
distance_15m = mtf_15m and not na(close_15m) and not na(ma200_15m) ? math.abs(close_15m - ma200_15m) : na
|
||
|
||
// 15分钟R1/S1/MEAN距离计算
|
||
distance_to_r1_15m = mtf_15m and not na(close_15m) and not na(upband1_15m) ? math.abs(close_15m - upband1_15m) : na
|
||
distance_to_s1_15m = mtf_15m and not na(close_15m) and not na(loband1_15m) ? math.abs(close_15m - loband1_15m) : na
|
||
distance_to_mean_15m = mtf_15m and not na(close_15m) and not na(meanline_15m) ? math.abs(close_15m - meanline_15m) : na
|
||
|
||
rsi_neutral_15m = mtf_15m and not na(rsi_15m) ? (rsi_15m >= short_S and rsi_15m <= long_S) : false
|
||
price_in_channel_15m = mtf_15m and not na(close_15m) and not na(upband1_15m) and not na(loband1_15m) ? (close_15m >= loband1_15m and close_15m <= upband1_15m) : false
|
||
ma200_near_15m = mtf_15m and not na(distance_15m) ? (distance_15m <= distance_threshold_1m) : false
|
||
osc_15m = rsi_neutral_15m or price_in_channel_15m or ma200_near_15m
|
||
|
||
rsi_overbought_15m = mtf_15m and not na(rsi_15m) ? (rsi_15m > long_S) : false
|
||
price_above_r1_15m = mtf_15m and not na(close_15m) and not na(upband1_15m) ? (close_15m > upband1_15m) : false
|
||
ma200_far_15m = mtf_15m and not na(distance_15m) ? (distance_15m > distance_threshold_1m) : false
|
||
ma50_above_mean_15m = mtf_15m and not na(ma50_15m) and not na(meanline_15m) ? (ma50_15m > meanline_15m) : false
|
||
long_15m = rsi_overbought_15m and price_above_r1_15m and ma200_far_15m and ma50_above_mean_15m
|
||
|
||
rsi_oversold_15m = mtf_15m and not na(rsi_15m) ? (rsi_15m < short_S) : false
|
||
price_below_s1_15m = mtf_15m and not na(close_15m) and not na(loband1_15m) ? (close_15m < loband1_15m) : false
|
||
ma50_below_mean_15m = mtf_15m and not na(ma50_15m) and not na(meanline_15m) ? (ma50_15m < meanline_15m) : false
|
||
short_15m = rsi_oversold_15m and price_below_s1_15m and ma200_far_15m and ma50_below_mean_15m
|
||
|
||
// 30分钟信号
|
||
distance_30m = mtf_30m and not na(close_30m) and not na(ma200_30m) ? math.abs(close_30m - ma200_30m) : na
|
||
|
||
// 30分钟R1/S1/MEAN距离计算
|
||
distance_to_r1_30m = mtf_30m and not na(close_30m) and not na(upband1_30m) ? math.abs(close_30m - upband1_30m) : na
|
||
distance_to_s1_30m = mtf_30m and not na(close_30m) and not na(loband1_30m) ? math.abs(close_30m - loband1_30m) : na
|
||
distance_to_mean_30m = mtf_30m and not na(close_30m) and not na(meanline_30m) ? math.abs(close_30m - meanline_30m) : na
|
||
|
||
rsi_neutral_30m = mtf_30m and not na(rsi_30m) ? (rsi_30m >= short_S and rsi_30m <= long_S) : false
|
||
price_in_channel_30m = mtf_30m and not na(close_30m) and not na(upband1_30m) and not na(loband1_30m) ? (close_30m >= loband1_30m and close_30m <= upband1_30m) : false
|
||
ma200_near_30m = mtf_30m and not na(distance_30m) ? (distance_30m <= distance_threshold_1m) : false
|
||
osc_30m = rsi_neutral_30m or price_in_channel_30m or ma200_near_30m
|
||
|
||
rsi_overbought_30m = mtf_30m and not na(rsi_30m) ? (rsi_30m > long_S) : false
|
||
price_above_r1_30m = mtf_30m and not na(close_30m) and not na(upband1_30m) ? (close_30m > upband1_30m) : false
|
||
ma200_far_30m = mtf_30m and not na(distance_30m) ? (distance_30m > distance_threshold_1m) : false
|
||
ma50_above_mean_30m = mtf_30m and not na(ma50_30m) and not na(meanline_30m) ? (ma50_30m > meanline_30m) : false
|
||
long_30m = rsi_overbought_30m and price_above_r1_30m and ma200_far_30m and ma50_above_mean_30m
|
||
|
||
rsi_oversold_30m = mtf_30m and not na(rsi_30m) ? (rsi_30m < short_S) : false
|
||
price_below_s1_30m = mtf_30m and not na(close_30m) and not na(loband1_30m) ? (close_30m < loband1_30m) : false
|
||
ma50_below_mean_30m = mtf_30m and not na(ma50_30m) and not na(meanline_30m) ? (ma50_30m < meanline_30m) : false
|
||
short_30m = rsi_oversold_30m and price_below_s1_30m and ma200_far_30m and ma50_below_mean_30m
|
||
|
||
// 45分钟信号
|
||
distance_45m = mtf_45m and not na(close_45m) and not na(ma200_45m) ? math.abs(close_45m - ma200_45m) : na
|
||
|
||
// 45分钟R1/S1/MEAN距离计算
|
||
distance_to_r1_45m = mtf_45m and not na(close_45m) and not na(upband1_45m) ? math.abs(close_45m - upband1_45m) : na
|
||
distance_to_s1_45m = mtf_45m and not na(close_45m) and not na(loband1_45m) ? math.abs(close_45m - loband1_45m) : na
|
||
distance_to_mean_45m = mtf_45m and not na(close_45m) and not na(meanline_45m) ? math.abs(close_45m - meanline_45m) : na
|
||
|
||
rsi_neutral_45m = mtf_45m and not na(rsi_45m) ? (rsi_45m >= short_S and rsi_45m <= long_S) : false
|
||
price_in_channel_45m = mtf_45m and not na(close_45m) and not na(upband1_45m) and not na(loband1_45m) ? (close_45m >= loband1_45m and close_45m <= upband1_45m) : false
|
||
ma200_near_45m = mtf_45m and not na(distance_45m) ? (distance_45m <= distance_threshold_1m) : false
|
||
osc_45m = rsi_neutral_45m or price_in_channel_45m or ma200_near_45m
|
||
|
||
rsi_overbought_45m = mtf_45m and not na(rsi_45m) ? (rsi_45m > long_S) : false
|
||
price_above_r1_45m = mtf_45m and not na(close_45m) and not na(upband1_45m) ? (close_45m > upband1_45m) : false
|
||
ma200_far_45m = mtf_45m and not na(distance_45m) ? (distance_45m > distance_threshold_1m) : false
|
||
ma50_above_mean_45m = mtf_45m and not na(ma50_45m) and not na(meanline_45m) ? (ma50_45m > meanline_45m) : false
|
||
long_45m = rsi_overbought_45m and price_above_r1_45m and ma200_far_45m and ma50_above_mean_45m
|
||
|
||
rsi_oversold_45m = mtf_45m and not na(rsi_45m) ? (rsi_45m < short_S) : false
|
||
price_below_s1_45m = mtf_45m and not na(close_45m) and not na(loband1_45m) ? (close_45m < loband1_45m) : false
|
||
ma50_below_mean_45m = mtf_45m and not na(ma50_45m) and not na(meanline_45m) ? (ma50_45m < meanline_45m) : false
|
||
short_45m = rsi_oversold_45m and price_below_s1_45m and ma200_far_45m and ma50_below_mean_45m
|
||
|
||
// 1小时信号
|
||
distance_1h = mtf_1h and not na(close_1h) and not na(ma200_1h) ? math.abs(close_1h - ma200_1h) : na
|
||
|
||
// 1小时R1/S1/MEAN距离计算
|
||
distance_to_r1_1h = mtf_1h and not na(close_1h) and not na(upband1_1h) ? math.abs(close_1h - upband1_1h) : na
|
||
distance_to_s1_1h = mtf_1h and not na(close_1h) and not na(loband1_1h) ? math.abs(close_1h - loband1_1h) : na
|
||
distance_to_mean_1h = mtf_1h and not na(close_1h) and not na(meanline_1h) ? math.abs(close_1h - meanline_1h) : na
|
||
|
||
rsi_neutral_1h = mtf_1h and not na(rsi_1h) ? (rsi_1h >= short_S and rsi_1h <= long_S) : false
|
||
price_in_channel_1h = mtf_1h and not na(close_1h) and not na(upband1_1h) and not na(loband1_1h) ? (close_1h >= loband1_1h and close_1h <= upband1_1h) : false
|
||
ma200_near_1h = mtf_1h and not na(distance_1h) ? (distance_1h <= distance_threshold_1m) : false
|
||
osc_1h = rsi_neutral_1h or price_in_channel_1h or ma200_near_1h
|
||
|
||
rsi_overbought_1h = mtf_1h and not na(rsi_1h) ? (rsi_1h > long_S) : false
|
||
price_above_r1_1h = mtf_1h and not na(close_1h) and not na(upband1_1h) ? (close_1h > upband1_1h) : false
|
||
ma200_far_1h = mtf_1h and not na(distance_1h) ? (distance_1h > distance_threshold_1m) : false
|
||
ma50_above_mean_1h = mtf_1h and not na(ma50_1h) and not na(meanline_1h) ? (ma50_1h > meanline_1h) : false
|
||
long_1h = rsi_overbought_1h and price_above_r1_1h and ma200_far_1h and ma50_above_mean_1h
|
||
|
||
rsi_oversold_1h = mtf_1h and not na(rsi_1h) ? (rsi_1h < short_S) : false
|
||
price_below_s1_1h = mtf_1h and not na(close_1h) and not na(loband1_1h) ? (close_1h < loband1_1h) : false
|
||
ma50_below_mean_1h = mtf_1h and not na(ma50_1h) and not na(meanline_1h) ? (ma50_1h < meanline_1h) : false
|
||
short_1h = rsi_oversold_1h and price_below_s1_1h and ma200_far_1h and ma50_below_mean_1h
|
||
|
||
// 4小时信号
|
||
distance_4h = mtf_4h and not na(close_4h) and not na(ma200_4h) ? math.abs(close_4h - ma200_4h) : na
|
||
|
||
// 4小时R1/S1/MEAN距离计算
|
||
distance_to_r1_4h = mtf_4h and not na(close_4h) and not na(upband1_4h) ? math.abs(close_4h - upband1_4h) : na
|
||
distance_to_s1_4h = mtf_4h and not na(close_4h) and not na(loband1_4h) ? math.abs(close_4h - loband1_4h) : na
|
||
distance_to_mean_4h = mtf_4h and not na(close_4h) and not na(meanline_4h) ? math.abs(close_4h - meanline_4h) : na
|
||
|
||
rsi_neutral_4h = mtf_4h and not na(rsi_4h) ? (rsi_4h >= short_S and rsi_4h <= long_S) : false
|
||
price_in_channel_4h = mtf_4h and not na(close_4h) and not na(upband1_4h) and not na(loband1_4h) ? (close_4h >= loband1_4h and close_4h <= upband1_4h) : false
|
||
ma200_near_4h = mtf_4h and not na(distance_4h) ? (distance_4h <= distance_threshold_1m) : false
|
||
osc_4h = rsi_neutral_4h or price_in_channel_4h or ma200_near_4h
|
||
|
||
rsi_overbought_4h = mtf_4h and not na(rsi_4h) ? (rsi_4h > long_S) : false
|
||
price_above_r1_4h = mtf_4h and not na(close_4h) and not na(upband1_4h) ? (close_4h > upband1_4h) : false
|
||
ma200_far_4h = mtf_4h and not na(distance_4h) ? (distance_4h > distance_threshold_1m) : false
|
||
ma50_above_mean_4h = mtf_4h and not na(ma50_4h) and not na(meanline_4h) ? (ma50_4h > meanline_4h) : false
|
||
long_4h = rsi_overbought_4h and price_above_r1_4h and ma200_far_4h and ma50_above_mean_4h
|
||
|
||
rsi_oversold_4h = mtf_4h and not na(rsi_4h) ? (rsi_4h < short_S) : false
|
||
price_below_s1_4h = mtf_4h and not na(close_4h) and not na(loband1_4h) ? (close_4h < loband1_4h) : false
|
||
ma50_below_mean_4h = mtf_4h and not na(ma50_4h) and not na(meanline_4h) ? (ma50_4h < meanline_4h) : false
|
||
short_4h = rsi_oversold_4h and price_below_s1_4h and ma200_far_4h and ma50_below_mean_4h
|
||
|
||
//************************************************************************************************************
|
||
// 计算实时数值
|
||
//************************************************************************************************************
|
||
|
||
// MA50 和 MEAN 的关系
|
||
ma50_vs_mean = ma50 > meanline ? "上方" : ma50 < meanline ? "下方" : "重合"
|
||
ma50_mean_distance = math.abs(ma50 - meanline)
|
||
|
||
// MA50 和 MA200 的关系
|
||
ma50_vs_ma200 = ma50 > ma200 ? "上方" : ma50 < ma200 ? "下方" : "重合"
|
||
ma50_ma200_distance = math.abs(ma50 - ma200)
|
||
|
||
// 价格和 MA200 的关系
|
||
price_vs_ma200 = close > ma200 ? "上方" : close < ma200 ? "下方" : "重合"
|
||
price_ma200_distance = math.abs(close - ma200)
|
||
|
||
// MA200 历史值
|
||
ma200_current = ma200
|
||
ma200_4bars_ago = ma200[4]
|
||
ma200_10bars_ago = ma200[10]
|
||
ma200_14bars_ago = ma200[14]
|
||
|
||
// MA200 斜率计算
|
||
ma200_slope_4 = not na(ma200_4bars_ago) ? (ma200_current - ma200_4bars_ago) / 4 : 0
|
||
ma200_slope_10 = not na(ma200_10bars_ago) ? (ma200_current - ma200_10bars_ago) / 10 : 0
|
||
ma200_slope_14 = not na(ma200_14bars_ago) ? (ma200_10bars_ago - ma200_14bars_ago) / 4 : 0
|
||
|
||
// MA200 斜率变化计算
|
||
ma200_slope_change_4 = not na(ma200_slope_4[1]) ? ma200_slope_4 - ma200_slope_4[1] : 0
|
||
ma200_slope_change_10 = not na(ma200_slope_10[1]) ? ma200_slope_10 - ma200_slope_10[1] : 0
|
||
|
||
// 删除不再使用的角度计算
|
||
|
||
// 保留原有斜率计算(用于其他功能)
|
||
ma200_slope_segment1 = not na(ma200_4bars_ago) ? (ma200_current - ma200_4bars_ago) / 4 : 0
|
||
ma200_slope_segment2 = not na(ma200_14bars_ago) and not na(ma200_10bars_ago) ? (ma200_10bars_ago - ma200_14bars_ago) / 4 : 0
|
||
|
||
// 删除不再使用的角度和百分比相关代码
|
||
|
||
// ═════════ MA200距离分析(参考原MA200代码) ════════
|
||
distance_threshold = get_distance_threshold()
|
||
distance_usd = math.abs(close - ma200_current)
|
||
is_near_ma200 = distance_usd <= distance_threshold
|
||
|
||
// ═════════ R1/S1距离分析 ════════
|
||
r1s1_distance_threshold = get_r1s1_distance_threshold()
|
||
distance_to_r1 = math.abs(close - upband1)
|
||
distance_to_s1 = math.abs(close - loband1)
|
||
is_near_r1 = distance_to_r1 <= r1s1_distance_threshold
|
||
is_near_s1 = distance_to_s1 <= r1s1_distance_threshold
|
||
|
||
// MA200平坦度分析
|
||
ma200_max = ta.highest(ma200_current, flatness_period)
|
||
ma200_min = ta.lowest(ma200_current, flatness_period)
|
||
ma200_flatness = ma200_max - ma200_min
|
||
is_flat = ma200_flatness < flatness_threshold
|
||
|
||
// 价格波动分析
|
||
price_max = ta.highest(close, oscillation_bars)
|
||
price_min = ta.lowest(close, oscillation_bars)
|
||
price_range = price_max - price_min
|
||
cross_above = ta.crossover(close, ma200_current)
|
||
cross_below = ta.crossunder(close, ma200_current)
|
||
is_oscillating_price = price_range < oscillation_threshold and (cross_above or cross_below)
|
||
|
||
// 删除重复的百分比计算(已在前面定义)
|
||
|
||
// 删除残留的旧代码片段
|
||
|
||
// 删除不再使用的斜率变化方向计算
|
||
|
||
// ═════════ 基于距离的MA200分析逻辑(参考原MA200代码) ════════
|
||
|
||
// 1. 基础状态判断
|
||
is_above_ma200 = close > ma200_current
|
||
is_below_ma200 = close < ma200_current
|
||
|
||
// 2. MA200趋势方向判断(基于MA200自身变化)
|
||
ma200_change_4 = not na(ma200_4bars_ago) ? ma200_current - ma200_4bars_ago : 0
|
||
ma200_change_10 = not na(ma200_10bars_ago) ? ma200_current - ma200_10bars_ago : 0
|
||
|
||
ma200_direction = ma200_change_10 > flatness_threshold ? "上升" : ma200_change_10 < -flatness_threshold ? "下降" : "横盘"
|
||
|
||
// 3. 趋势强度判断(基于MA200变化幅度)
|
||
ma200_change_abs = math.abs(ma200_change_10)
|
||
ma200_strength = ma200_change_abs >= flatness_threshold * 4 ? "强" : ma200_change_abs >= flatness_threshold * 2 ? "中" : ma200_change_abs >= flatness_threshold ? "弱" : "微弱"
|
||
|
||
// 4. 振荡判断(参考原MA200逻辑)
|
||
// 条件1:MA200本身比较平坦
|
||
condition1_ma200_flat = is_flat
|
||
|
||
// 条件2:价格在MA200附近波动
|
||
condition2_price_oscillating = is_oscillating_price
|
||
|
||
// 条件3:价格靠近MA200
|
||
condition3_near_ma200 = is_near_ma200
|
||
|
||
// 综合振荡判断
|
||
is_oscillating = condition1_ma200_flat or condition2_price_oscillating or (condition3_near_ma200 and ma200_direction == "横盘")
|
||
|
||
// 5. 最终趋势判断
|
||
ma200_trend_strength = is_oscillating ? "震荡" : ma200_strength + "趋势"
|
||
ma200_trend_direction = is_oscillating ? "横盘" : ma200_direction
|
||
|
||
// 6. 趋势变化分析(基于距离变化)
|
||
distance_change = not na(distance_usd[1]) ? distance_usd - distance_usd[1] : 0
|
||
trend_acceleration = math.abs(distance_change) > distance_threshold * 0.1 ? (distance_change > 0 ? "远离" : "靠近") : "稳定"
|
||
|
||
// 综合趋势状态
|
||
ma200_trend_status = ma200_trend_direction + ma200_trend_strength
|
||
|
||
// 市场活跃度判断(基于距离和波动)
|
||
volatility_indicator = distance_usd + price_range
|
||
market_activity = volatility_indicator > distance_threshold * 2 ? "活跃" : volatility_indicator > distance_threshold ? "一般" : "平静"
|
||
|
||
// ═════════ 交易信号判断系统 ════════
|
||
|
||
// 1. 震荡条件判断(修改为OR逻辑:满足任一条件即为震荡)
|
||
rsi_neutral = rsi >= short_S and rsi <= long_S // RSI处于中性区间
|
||
price_in_channel = close >= loband1 and close <= upband1 // 价格在MRC通道内(S1-R1)
|
||
ma200_near = distance_usd <= distance_threshold // 距离MA200小于等于阈值
|
||
|
||
oscillation_signal = rsi_neutral or price_in_channel or ma200_near
|
||
|
||
// 2. 做多条件判断
|
||
rsi_overbought_signal = rsi > long_S // RSI超买
|
||
price_above_r1 = close > upband1 // 价格在R1以上
|
||
ma200_far = distance_usd > distance_threshold // 距离MA200大于阈值
|
||
ma50_above_mean = ma50 > meanline // MA50在MEAN以上
|
||
|
||
long_signal = rsi_overbought_signal and price_above_r1 and ma200_far and ma50_above_mean
|
||
|
||
// 3. 做空条件判断
|
||
rsi_oversold_signal = rsi < short_S // RSI超卖
|
||
price_below_s1 = close < loband1 // 价格在S1以下
|
||
ma50_below_mean = ma50 < meanline // MA50在MEAN以下
|
||
|
||
short_signal = rsi_oversold_signal and price_below_s1 and ma200_far and ma50_below_mean
|
||
|
||
// ═════════ 时间窗口警报系统 ════════
|
||
|
||
// 存储启动条件的时间戳和冷却时间
|
||
var int long_trigger_time = na
|
||
var int short_trigger_time = na
|
||
var int last_long_alert_time = na
|
||
var int last_short_alert_time = na
|
||
|
||
// 1分钟时间周期数据获取(用于启动条件检测)
|
||
close_1m_current = request.security(syminfo.tickerid, "1", close, lookahead=barmerge.lookahead_off)
|
||
close_1m_prev = request.security(syminfo.tickerid, "1", close[1], lookahead=barmerge.lookahead_off)
|
||
upband1_1m_current = request.security(syminfo.tickerid, "1", upband1, lookahead=barmerge.lookahead_off)
|
||
loband1_1m_current = request.security(syminfo.tickerid, "1", loband1, lookahead=barmerge.lookahead_off)
|
||
|
||
// 启动条件检测
|
||
long_trigger = ta.crossover(close_1m_current, upband1_1m_current) // 价格上穿R1
|
||
short_trigger = ta.crossunder(close_1m_current, loband1_1m_current) // 价格下穿S1
|
||
|
||
// 记录启动时间
|
||
if long_trigger
|
||
long_trigger_time := time
|
||
if short_trigger
|
||
short_trigger_time := time
|
||
|
||
// 时间窗口检查函数
|
||
in_time_window(trigger_time, window_minutes) =>
|
||
if na(trigger_time)
|
||
false
|
||
else
|
||
time_diff = math.abs(time - trigger_time) / 60000 // 转换为分钟
|
||
time_diff <= window_minutes
|
||
|
||
// 冷却时间检查函数
|
||
is_cooldown_over(last_alert_time, cooldown_minutes) =>
|
||
if na(last_alert_time)
|
||
true
|
||
else
|
||
time_diff = (time - last_alert_time) / 60000 // 转换为分钟
|
||
time_diff >= cooldown_minutes
|
||
|
||
// 做多条件检查(时间窗口内)
|
||
check_long_conditions() =>
|
||
if not enable_advanced_alerts
|
||
false
|
||
else
|
||
// 条件2(1分钟时间框架确认,5分钟时间窗口):快速技术指标验证
|
||
// - 时间窗口:启动信号后5分钟内必须满足所有子条件
|
||
// - RSI超买确认:1分钟RSI > 超买阈值,确认短期多头动能
|
||
// - 价格突破确认:1分钟价格突破R1阻力线,确认突破有效性
|
||
// - MA200距离确认:1分钟价格距离MA200足够远,避免长期均线阻力
|
||
// - MA50趋势确认:1分钟MA50在MEAN线上方,确认短期趋势一致性
|
||
condition2_1m = in_time_window(long_trigger_time, time_window_5min) and rsi_overbought_1m and price_above_r1_1m and ma200_far_1m and ma50_above_mean_1m
|
||
|
||
// 条件3(5分钟时间框架确认,15分钟时间窗口):多重技术指标综合验证
|
||
// - 时间窗口:启动信号后15分钟内必须满足所有子条件
|
||
// - RSI超买确认:5分钟RSI > 超买阈值,确认多头动能充足
|
||
// - 价格位置确认:5分钟价格在MEAN线上方或附近,确认趋势方向
|
||
// - MA200距离确认:5分钟价格距离MA200足够远,避免长期均线阻力
|
||
// - MA50趋势确认:1分钟MA50在MEAN线上方,确认短期趋势向上
|
||
condition3_5m = in_time_window(long_trigger_time, time_window_15min) and rsi_overbought_5m and price_above_mean_5m and ma200_far_5m and ma50_above_mean_1m
|
||
|
||
// 条件4(15分钟时间框架确认,10分钟时间窗口):长期趋势距离验证
|
||
// - 时间窗口:启动信号后10分钟内必须满足距离条件
|
||
// - 距离确认:15分钟价格与S1支撑线距离 > 品种特定阈值
|
||
// - 目的:确保价格远离重要支撑位,避免假突破风险
|
||
// - 意义:长期时间框架的距离验证,提高信号可靠性
|
||
condition4_15m = in_time_window(long_trigger_time, time_window_10min) and distance_to_s1_15m > get_r1s1_distance_threshold()
|
||
|
||
// 根据配置决定是否需要所有条件都满足
|
||
conditions_met = require_all_conditions ? (condition2_1m and condition3_5m and condition4_15m) : (condition2_1m or condition3_5m or condition4_15m)
|
||
|
||
// 检查冷却时间
|
||
cooldown_ok = is_cooldown_over(last_long_alert_time, alert_cooldown_minutes)
|
||
|
||
conditions_met and cooldown_ok
|
||
|
||
// 做空条件检查(时间窗口内)
|
||
check_short_conditions() =>
|
||
if not enable_advanced_alerts
|
||
false
|
||
else
|
||
// 条件2(1分钟时间框架确认,5分钟时间窗口):快速技术指标验证
|
||
// - 时间窗口:启动信号后5分钟内必须满足所有子条件
|
||
// - RSI超卖确认:1分钟RSI < 超卖阈值,确认短期空头动能
|
||
// - 价格突破确认:1分钟价格跌破S1支撑线,确认突破有效性
|
||
// - MA200距离确认:1分钟价格距离MA200足够远,避免长期均线支撑
|
||
// - MA50趋势确认:1分钟MA50在MEAN线下方,确认短期趋势一致性
|
||
condition2_1m = in_time_window(short_trigger_time, time_window_5min) and rsi_oversold_1m and price_below_s1_1m and ma200_far_1m and ma50_below_mean_1m
|
||
|
||
// 条件3(5分钟时间框架确认,15分钟时间窗口):多重技术指标综合验证
|
||
// - 时间窗口:启动信号后15分钟内必须满足所有子条件
|
||
// - RSI超卖确认:5分钟RSI < 超卖阈值,确认空头动能充足
|
||
// - 价格位置确认:5分钟价格在MEAN线下方或附近,确认趋势方向
|
||
// - MA200距离确认:5分钟价格距离MA200足够远,避免长期均线支撑
|
||
// - MA50趋势确认:1分钟MA50在MEAN线下方,确认短期趋势向下
|
||
condition3_5m = in_time_window(short_trigger_time, time_window_15min) and rsi_oversold_5m and price_below_mean_5m and ma200_far_5m and ma50_below_mean_1m
|
||
|
||
// 条件4(15分钟时间框架确认,10分钟时间窗口):长期趋势距离验证
|
||
// - 时间窗口:启动信号后10分钟内必须满足距离条件
|
||
// - 距离确认:15分钟价格与R1阻力线距离 > 品种特定阈值
|
||
// - 目的:确保价格远离重要阻力位,避免假突破风险
|
||
// - 意义:长期时间框架的距离验证,提高信号可靠性
|
||
condition4_15m = in_time_window(short_trigger_time, time_window_10min) and distance_to_r1_15m > get_r1s1_distance_threshold()
|
||
|
||
// 根据配置决定是否需要所有条件都满足
|
||
conditions_met = require_all_conditions ? (condition2_1m and condition3_5m and condition4_15m) : (condition2_1m or condition3_5m or condition4_15m)
|
||
|
||
// 检查冷却时间
|
||
cooldown_ok = is_cooldown_over(last_short_alert_time, alert_cooldown_minutes)
|
||
|
||
conditions_met and cooldown_ok
|
||
|
||
// 最终警报条件
|
||
advanced_long_alert = check_long_conditions()
|
||
advanced_short_alert = check_short_conditions()
|
||
|
||
// 更新最后警报时间
|
||
if advanced_long_alert
|
||
last_long_alert_time := time
|
||
if advanced_short_alert
|
||
last_short_alert_time := time
|
||
|
||
// ═════════ 警报系统(包含原有和新增) ════════
|
||
|
||
// 传统警报条件(使用常量消息)
|
||
alertcondition(oscillation_signal, title="震荡信号", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"震荡信号","信号":"oscillation","时间":"{{time}}","描述":"震荡"}')
|
||
|
||
alertcondition(long_signal, title="做多信号", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"做多信号","信号":"long","时间":"{{time}}","描述":"做多信号"}')
|
||
|
||
alertcondition(short_signal, title="做空信号", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"做空信号","信号":"short","时间":"{{time}}","描述":"做空信号"}')
|
||
|
||
// 新增时间窗口警报
|
||
alertcondition(advanced_long_alert, title="高级做多警报", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"高级做多警报","信号":"advanced_long","时间":"{{time}}","描述":"多时间周期做多确认信号"}')
|
||
|
||
alertcondition(advanced_short_alert, title="高级做空警报", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"高级做空警报","信号":"advanced_short","时间":"{{time}}","描述":"多时间周期做空确认信号"}')
|
||
|
||
// R1/S1距离警报
|
||
alertcondition(is_near_r1, title="价格接近R1线", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"价格接近R1线","信号":"near_r1","时间":"{{time}}","描述":"价格接近R1阻力线"}')
|
||
|
||
alertcondition(is_near_s1, title="价格接近S1线", message='{"指标名称":"cobinined","交易对":"{{ticker}}","周期":"{{interval}}","价格":"{{close}}","事件":"价格接近S1线","信号":"near_s1","时间":"{{time}}","描述":"价格接近S1支撑线"}')
|
||
|
||
// ═════════ K线标记系统(TradingView内置箭头,可配置大小) ════════
|
||
|
||
// 做多信号标记(向上三角形)- 根据配置大小
|
||
plotshape(series=long_signal and show_long_marks and arrow_size == 'tiny', title="做多信号-tiny", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.tiny)
|
||
plotshape(series=long_signal and show_long_marks and arrow_size == 'small', title="做多信号-small", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
|
||
plotshape(series=long_signal and show_long_marks and arrow_size == 'normal', title="做多信号-normal", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.normal)
|
||
plotshape(series=long_signal and show_long_marks and arrow_size == 'large', title="做多信号-large", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.large)
|
||
plotshape(series=long_signal and show_long_marks and arrow_size == 'huge', title="做多信号-huge", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.huge)
|
||
|
||
// 做空信号标记(向下三角形)- 根据配置大小
|
||
plotshape(series=short_signal and show_short_marks and arrow_size == 'tiny', title="做空信号-tiny", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.tiny)
|
||
plotshape(series=short_signal and show_short_marks and arrow_size == 'small', title="做空信号-small", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
|
||
plotshape(series=short_signal and show_short_marks and arrow_size == 'normal', title="做空信号-normal", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.normal)
|
||
plotshape(series=short_signal and show_short_marks and arrow_size == 'large', title="做空信号-large", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.large)
|
||
plotshape(series=short_signal and show_short_marks and arrow_size == 'huge', title="做空信号-huge", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.huge)
|
||
|
||
// 震荡信号标记(黄色圆点标记)- 注释掉避免黄色横条问题
|
||
// plotshape(series=oscillation_signal and show_oscillation_marks and arrow_size == 'tiny', title="震荡信号-tiny", location=location.top, color=color.yellow, style=shape.circle, size=size.tiny)
|
||
// plotshape(series=oscillation_signal and show_oscillation_marks and arrow_size == 'small', title="震荡信号-small", location=location.top, color=color.yellow, style=shape.circle, size=size.small)
|
||
// plotshape(series=oscillation_signal and show_oscillation_marks and arrow_size == 'normal', title="震荡信号-normal", location=location.top, color=color.yellow, style=shape.circle, size=size.normal)
|
||
// plotshape(series=oscillation_signal and show_oscillation_marks and arrow_size == 'large', title="震荡信号-large", location=location.top, color=color.yellow, style=shape.circle, size=size.large)
|
||
// plotshape(series=oscillation_signal and show_oscillation_marks and arrow_size == 'huge', title="震荡信号-huge", location=location.top, color=color.yellow, style=shape.circle, size=size.huge)
|
||
|
||
// ═════════ 高级警报标记(超级突出版本) ════════
|
||
|
||
// 高级做多警报 - 根据样式参数显示不同突出效果
|
||
// 第1层:大背景圆圈(金色光晕效果)- 仅超级突出模式
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and advanced_alert_style == '超级突出', title="高级做多背景", location=location.belowbar, color=color.new(color.yellow, 70), style=shape.circle, size=size.huge)
|
||
|
||
// 第2层:中等背景圆圈(绿色强调)- 突出和超级突出模式
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and (advanced_alert_style == '突出' or advanced_alert_style == '超级突出'), title="高级做多中层", location=location.belowbar, color=color.new(color.lime, 30), style=shape.circle, size=size.large)
|
||
|
||
// 第3层:主要标记(根据配置大小)
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and arrow_size == 'tiny', title="高级做多主标记-tiny", location=location.belowbar, color=color.new(color.white, 0), style=shape.labelup, size=size.small, text="🚀", textcolor=color.black)
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and arrow_size == 'small', title="高级做多主标记-small", location=location.belowbar, color=color.new(color.white, 0), style=shape.labelup, size=size.normal, text="🚀", textcolor=color.black)
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and arrow_size == 'normal', title="高级做多主标记-normal", location=location.belowbar, color=color.new(color.white, 0), style=shape.labelup, size=size.large, text="🚀", textcolor=color.black)
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and arrow_size == 'large', title="高级做多主标记-large", location=location.belowbar, color=color.new(color.white, 0), style=shape.labelup, size=size.huge, text="🚀", textcolor=color.black)
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and arrow_size == 'huge', title="高级做多主标记-huge", location=location.belowbar, color=color.new(color.white, 0), style=shape.labelup, size=size.huge, text="🚀🚀", textcolor=color.black)
|
||
|
||
// 第4层:闪烁边框效果(使用动态颜色)- 仅超级突出模式
|
||
flash_color_long = advanced_long_alert and advanced_alert_style == '超级突出' ? (bar_index % 2 == 0 ? color.new(color.red, 0) : color.new(color.orange, 0)) : na
|
||
plotshape(series=advanced_long_alert and show_advanced_alerts and advanced_alert_style == '超级突出', title="高级做多闪烁", location=location.belowbar, color=flash_color_long, style=shape.diamond, size=size.tiny)
|
||
|
||
// 高级做空警报 - 根据样式参数显示不同突出效果
|
||
// 第1层:大背景圆圈(紫色光晕效果)- 仅超级突出模式
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and advanced_alert_style == '超级突出', title="高级做空背景", location=location.abovebar, color=color.new(color.purple, 70), style=shape.circle, size=size.huge)
|
||
|
||
// 第2层:中等背景圆圈(红色强调)- 突出和超级突出模式
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and (advanced_alert_style == '突出' or advanced_alert_style == '超级突出'), title="高级做空中层", location=location.abovebar, color=color.new(color.fuchsia, 30), style=shape.circle, size=size.large)
|
||
|
||
// 第3层:主要标记(根据配置大小)
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and arrow_size == 'tiny', title="高级做空主标记-tiny", location=location.abovebar, color=color.new(color.white, 0), style=shape.labeldown, size=size.small, text="🔻", textcolor=color.black)
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and arrow_size == 'small', title="高级做空主标记-small", location=location.abovebar, color=color.new(color.white, 0), style=shape.labeldown, size=size.normal, text="🔻", textcolor=color.black)
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and arrow_size == 'normal', title="高级做空主标记-normal", location=location.abovebar, color=color.new(color.white, 0), style=shape.labeldown, size=size.large, text="🔻", textcolor=color.black)
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and arrow_size == 'large', title="高级做空主标记-large", location=location.abovebar, color=color.new(color.white, 0), style=shape.labeldown, size=size.huge, text="🔻", textcolor=color.black)
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and arrow_size == 'huge', title="高级做空主标记-huge", location=location.abovebar, color=color.new(color.white, 0), style=shape.labeldown, size=size.huge, text="🔻🔻", textcolor=color.black)
|
||
|
||
// 第4层:闪烁边框效果(使用动态颜色)- 仅超级突出模式
|
||
flash_color_short = advanced_short_alert and advanced_alert_style == '超级突出' ? (bar_index % 2 == 0 ? color.new(color.red, 0) : color.new(color.orange, 0)) : na
|
||
plotshape(series=advanced_short_alert and show_advanced_alerts and advanced_alert_style == '超级突出', title="高级做空闪烁", location=location.abovebar, color=flash_color_short, style=shape.diamond, size=size.tiny)
|
||
|
||
// ═════════ 高级警报文本标签(额外突出) ════════
|
||
|
||
// 高级做多警报文本标签 - 仅突出和超级突出模式
|
||
if advanced_long_alert and show_advanced_alerts and (advanced_alert_style == '突出' or advanced_alert_style == '超级突出') and barstate.islast
|
||
var label advanced_long_label = na
|
||
label_text = advanced_alert_style == '超级突出' ? "⚡HIGH LEVEL LONG⚡" : "🚀 HIGH LEVEL LONG 🚀"
|
||
if na(advanced_long_label)
|
||
advanced_long_label := label.new(bar_index, low - (high - low) * 0.1, label_text, xloc=xloc.bar_index, style=label.style_label_up, color=color.new(color.lime, 0), textcolor=color.black, size=size.large)
|
||
else
|
||
label.set_xy(advanced_long_label, bar_index, low - (high - low) * 0.1)
|
||
label.set_text(advanced_long_label, label_text)
|
||
|
||
// 高级做空警报文本标签 - 仅突出和超级突出模式
|
||
if advanced_short_alert and show_advanced_alerts and (advanced_alert_style == '突出' or advanced_alert_style == '超级突出') and barstate.islast
|
||
var label advanced_short_label = na
|
||
label_text = advanced_alert_style == '超级突出' ? "⚡HIGH LEVEL SHORT⚡" : "🔻 HIGH LEVEL SHORT 🔻"
|
||
if na(advanced_short_label)
|
||
advanced_short_label := label.new(bar_index, high + (high - low) * 0.1, label_text, xloc=xloc.bar_index, style=label.style_label_down, color=color.new(color.fuchsia, 0), textcolor=color.white, size=size.large)
|
||
else
|
||
label.set_xy(advanced_short_label, bar_index, high + (high - low) * 0.1)
|
||
label.set_text(advanced_short_label, label_text)
|
||
|
||
// ═════════ K线背景高亮(高级警报时) ════════
|
||
|
||
// 高级警报时的K线背景高亮 - 根据样式强度调整
|
||
bg_transparency = advanced_alert_style == '超级突出' ? 85 : advanced_alert_style == '突出' ? 92 : 95
|
||
bgcolor(advanced_long_alert and (advanced_alert_style == '突出' or advanced_alert_style == '超级突出') ? color.new(color.lime, bg_transparency) : advanced_short_alert and (advanced_alert_style == '突出' or advanced_alert_style == '超级突出') ? color.new(color.fuchsia, bg_transparency) : na, title="高级警报背景")
|
||
|
||
// 启动条件标记(增强版)
|
||
plotshape(series=long_trigger and show_advanced_alerts, title="做多启动", location=location.belowbar, color=color.new(color.aqua, 0), style=shape.arrowup, size=size.small)
|
||
plotshape(series=short_trigger and show_advanced_alerts, title="做空启动", location=location.abovebar, color=color.new(color.orange, 0), style=shape.arrowdown, size=size.small)
|
||
|
||
// 启动条件文本提示
|
||
plotchar(series=long_trigger and show_advanced_alerts, title="做多启动提示", location=location.belowbar, char="START", color=color.aqua, size=size.tiny)
|
||
plotchar(series=short_trigger and show_advanced_alerts, title="做空启动提示", location=location.abovebar, char="START", color=color.orange, size=size.tiny)
|
||
|
||
// RSI 状态
|
||
rsi_position = rsi > long_S ? "超买区" : rsi < short_S ? "超卖区" : "中性区"
|
||
rsi_cross_count = math.abs(segment_count)
|
||
|
||
//************************************************************************************************************
|
||
// 绘图部分
|
||
//************************************************************************************************************
|
||
|
||
// ═════════ 窗口一:MRC 和 MA 线条 ═════════
|
||
plot(meanline, color=color.new(color.black, 0), style=plot.style_line, title='MEAN', linewidth=mean_width)
|
||
plot(upband1, color=color.new(color.red, 0), style=plot.style_line, title='R1', linewidth=r1_s1_width)
|
||
plot(loband1, color=color.new(color.green, 0), style=plot.style_line, title='S1', linewidth=r1_s1_width)
|
||
plot(upband2, color=color.new(color.red, 50), style=plot.style_line, title='R2', linewidth=r2_s2_width)
|
||
plot(loband2, color=color.new(color.green, 50), style=plot.style_line, title='S2', linewidth=r2_s2_width)
|
||
|
||
// MA 线条
|
||
maColor(ma, ref) => ma > ref ? color.lime : color.red
|
||
plot(show_ma_lines ? ma50 : na, color=maColor(ma50, ma100), linewidth=2, title='MA50')
|
||
plot(show_ma_lines ? ma100 : na, color=maColor(ma100, ma200), linewidth=2, title='MA100')
|
||
plot(show_ma_lines ? ma200 : na, color=color.rgb(25, 58, 243), linewidth=4, title='MA200')
|
||
|
||
//************************************************************************************************************
|
||
// 信息表格显示
|
||
//************************************************************************************************************
|
||
|
||
if show_info_table and barstate.islast
|
||
// 创建扩展的信息表格(包含高级警报状态)
|
||
var table info_table = table.new(
|
||
position = position.bottom_right, // 固定在右下角
|
||
columns = 10, // 扩展为10列:原6列 + 高级警报启动 + 条件2 + 条件3 + 条件4
|
||
rows = 4, // 4行:标题 + 数值 + 状态 + 信号
|
||
bgcolor = color.new(color.white, 85),
|
||
border_width = 1)
|
||
|
||
// 清空表格
|
||
table.clear(info_table, 0, 0, 9, 3)
|
||
|
||
// 获取配置的文字大小
|
||
text_size = get_text_size()
|
||
|
||
// ═════════ 扩展表格标题行(原6列 + 高级警报4列) ═════════
|
||
table.cell(info_table, 0, 0, "RSI", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(info_table, 1, 0, "价格位置", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(info_table, 2, 0, "MA50位置", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(info_table, 3, 0, "MA200距离", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(info_table, 4, 0, "信号汇总", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(info_table, 5, 0, "综合判断", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
// 高级警报相关列
|
||
table.cell(info_table, 6, 0, "高级启动", text_color=color.white, bgcolor=color.new(color.lime, 30), text_size=text_size)
|
||
table.cell(info_table, 7, 0, "条件2(1m)", text_color=color.white, bgcolor=color.new(color.lime, 30), text_size=text_size)
|
||
table.cell(info_table, 8, 0, "条件3(5m)", text_color=color.white, bgcolor=color.new(color.lime, 30), text_size=text_size)
|
||
table.cell(info_table, 9, 0, "条件4(15m)", text_color=color.white, bgcolor=color.new(color.lime, 30), text_size=text_size)
|
||
|
||
// ═════════ 多列紧凑数据 ═════════
|
||
// 计算各指标的背景颜色(类似combined_mrc_ma200_rsi.pine)
|
||
rsi_color = rsi_neutral ? color.new(color.orange, 40) : rsi_overbought_signal ? color.new(color.green, 40) : rsi_oversold_signal ? color.new(color.red, 40) : color.white
|
||
price_color = price_in_channel ? color.new(color.orange, 40) : price_above_r1 ? color.new(color.green, 40) : price_below_s1 ? color.new(color.red, 40) : color.white
|
||
ma50_color = ma50_above_mean ? color.new(color.green, 40) : ma50_below_mean ? color.new(color.red, 40) : color.white
|
||
ma200_color = ma200_near ? color.new(color.orange, 40) : color.new(color.gray, 60)
|
||
|
||
// 高级警报条件状态计算
|
||
condition2_1m_long = not na(long_trigger_time) and in_time_window(long_trigger_time, time_window_5min) and rsi_overbought_1m and price_above_r1_1m and ma200_far_1m and ma50_above_mean_1m
|
||
condition3_5m_long = not na(long_trigger_time) and in_time_window(long_trigger_time, time_window_15min) and rsi_overbought_5m and price_above_mean_5m and ma200_far_5m and ma50_above_mean_1m
|
||
condition4_15m_long = not na(long_trigger_time) and in_time_window(long_trigger_time, time_window_10min) and distance_to_s1_15m > get_r1s1_distance_threshold()
|
||
|
||
condition2_1m_short = not na(short_trigger_time) and in_time_window(short_trigger_time, time_window_5min) and rsi_oversold_1m and price_below_s1_1m and ma200_far_1m and ma50_below_mean_1m
|
||
condition3_5m_short = not na(short_trigger_time) and in_time_window(short_trigger_time, time_window_15min) and rsi_oversold_5m and price_below_mean_5m and ma200_far_5m and ma50_below_mean_1m
|
||
condition4_15m_short = not na(short_trigger_time) and in_time_window(short_trigger_time, time_window_10min) and distance_to_r1_15m > get_r1s1_distance_threshold()
|
||
|
||
// 高级警报颜色计算
|
||
trigger_color = (long_trigger or short_trigger) ? color.new(color.aqua, 40) : (not na(long_trigger_time) or not na(short_trigger_time)) ? color.new(color.yellow, 60) : color.new(color.gray, 80)
|
||
condition2_color = condition2_1m_long ? color.new(color.green, 40) : condition2_1m_short ? color.new(color.red, 40) : color.new(color.gray, 80)
|
||
condition3_color = condition3_5m_long ? color.new(color.green, 40) : condition3_5m_short ? color.new(color.red, 40) : color.new(color.gray, 80)
|
||
condition4_color = condition4_15m_long ? color.new(color.green, 40) : condition4_15m_short ? color.new(color.red, 40) : color.new(color.gray, 80)
|
||
|
||
// 综合信号颜色(包含高级警报)
|
||
signal_color = advanced_long_alert ? color.new(color.lime, 20) : advanced_short_alert ? color.new(color.fuchsia, 20) : oscillation_signal ? color.new(color.orange, 40) : long_signal ? color.new(color.green, 40) : short_signal ? color.new(color.red, 40) : color.new(color.gray, 80)
|
||
final_signal_color = advanced_long_alert ? color.new(color.lime, 20) : advanced_short_alert ? color.new(color.fuchsia, 20) : long_signal ? color.new(color.green, 30) : short_signal ? color.new(color.red, 30) : oscillation_signal ? color.new(color.orange, 30) : color.new(color.gray, 80)
|
||
|
||
// 第1行:数值
|
||
table.cell(info_table, 0, 1, str.tostring(rsi, '#.#'), text_color=color.black, bgcolor=rsi_color, text_size=text_size)
|
||
table.cell(info_table, 1, 1, str.tostring(close, '#.##'), text_color=color.black, bgcolor=price_color, text_size=text_size)
|
||
table.cell(info_table, 2, 1, str.tostring(ma50, '#.##'), text_color=color.black, bgcolor=ma50_color, text_size=text_size)
|
||
table.cell(info_table, 3, 1, str.tostring(distance_usd, '#.#'), text_color=color.black, bgcolor=ma200_color, text_size=text_size)
|
||
table.cell(info_table, 4, 1, advanced_long_alert ? "高级🚀" : advanced_short_alert ? "高级🔻" : oscillation_signal ? "震荡⚡" : long_signal ? "做多🚀" : short_signal ? "做空🔻" : "观望", text_color=color.black, bgcolor=signal_color, text_size=text_size)
|
||
table.cell(info_table, 5, 1, advanced_long_alert ? "✓高级做多" : advanced_short_alert ? "✓高级做空" : long_signal ? "✓做多" : short_signal ? "✓做空" : oscillation_signal ? "✓震荡" : "观望", text_color=color.black, bgcolor=final_signal_color, text_size=text_size)
|
||
// 高级警报数据
|
||
table.cell(info_table, 6, 1, long_trigger ? "🚀启动" : short_trigger ? "🔻启动" : not na(long_trigger_time) ? "🚀监控" : not na(short_trigger_time) ? "🔻监控" : "等待", text_color=color.black, bgcolor=trigger_color, text_size=text_size)
|
||
table.cell(info_table, 7, 1, condition2_1m_long ? "✓做多" : condition2_1m_short ? "✓做空" : "未满足", text_color=color.black, bgcolor=condition2_color, text_size=text_size)
|
||
table.cell(info_table, 8, 1, condition3_5m_long ? "✓做多" : condition3_5m_short ? "✓做空" : "未满足", text_color=color.black, bgcolor=condition3_color, text_size=text_size)
|
||
table.cell(info_table, 9, 1, condition4_15m_long ? "✓做多" : condition4_15m_short ? "✓做空" : "未满足", text_color=color.black, bgcolor=condition4_color, text_size=text_size)
|
||
|
||
// 第2行:状态
|
||
table.cell(info_table, 0, 2, rsi_neutral ? "中性" : rsi_overbought_signal ? "超买" : rsi_oversold_signal ? "超卖" : "正常", text_color=color.black, bgcolor=rsi_color, text_size=text_size)
|
||
table.cell(info_table, 1, 2, price_in_channel ? "通道内" : price_above_r1 ? "R1上" : price_below_s1 ? "S1下" : "其他", text_color=color.black, bgcolor=price_color, text_size=text_size)
|
||
table.cell(info_table, 2, 2, ma50_above_mean ? "MEAN上" : ma50_below_mean ? "MEAN下" : "MEAN附近", text_color=color.black, bgcolor=ma50_color, text_size=text_size)
|
||
table.cell(info_table, 3, 2, ma200_near ? "≤阈值" : ">阈值", text_color=color.black, bgcolor=ma200_color, text_size=text_size)
|
||
table.cell(info_table, 4, 2, advanced_long_alert ? "高级AND" : advanced_short_alert ? "高级AND" : oscillation_signal ? "OR逻辑" : long_signal ? "AND逻辑" : short_signal ? "AND逻辑" : "无信号", text_color=color.black, bgcolor=signal_color, text_size=text_size)
|
||
table.cell(info_table, 5, 2, advanced_long_alert ? "🚀" : advanced_short_alert ? "🔻" : long_signal ? "🚀" : short_signal ? "🔻" : oscillation_signal ? "⚡" : "⚪", text_color=color.black, bgcolor=final_signal_color, text_size=text_size)
|
||
// 高级警报状态
|
||
trigger_window_status = not na(long_trigger_time) ? (in_time_window(long_trigger_time, time_window_15min) ? "窗口内" : "已过期") : not na(short_trigger_time) ? (in_time_window(short_trigger_time, time_window_15min) ? "窗口内" : "已过期") : "未启动"
|
||
cooldown_status = is_cooldown_over(last_long_alert_time, alert_cooldown_minutes) and is_cooldown_over(last_short_alert_time, alert_cooldown_minutes) ? "可用" : "冷却中"
|
||
table.cell(info_table, 6, 2, trigger_window_status, text_color=color.black, bgcolor=trigger_color, text_size=text_size)
|
||
table.cell(info_table, 7, 2, condition2_1m_long ? "5分钟内" : condition2_1m_short ? "5分钟内" : "窗口外", text_color=color.black, bgcolor=condition2_color, text_size=text_size)
|
||
table.cell(info_table, 8, 2, condition3_5m_long ? "15分钟内" : condition3_5m_short ? "15分钟内" : "窗口外", text_color=color.black, bgcolor=condition3_color, text_size=text_size)
|
||
table.cell(info_table, 9, 2, condition4_15m_long ? "10分钟内" : condition4_15m_short ? "10分钟内" : "窗口外", text_color=color.black, bgcolor=condition4_color, text_size=text_size)
|
||
|
||
// 第3行:条件说明
|
||
table.cell(info_table, 0, 3, rsi_neutral ? "震荡条件" : rsi_overbought_signal ? "做多条件" : rsi_oversold_signal ? "做空条件" : "中性", text_color=color.black, bgcolor=rsi_color, text_size=text_size)
|
||
table.cell(info_table, 1, 3, price_in_channel ? "震荡条件" : price_above_r1 ? "做多条件" : price_below_s1 ? "做空条件" : "中性", text_color=color.black, bgcolor=price_color, text_size=text_size)
|
||
table.cell(info_table, 2, 3, ma50_above_mean ? "做多条件" : ma50_below_mean ? "做空条件" : "中性", text_color=color.black, bgcolor=ma50_color, text_size=text_size)
|
||
table.cell(info_table, 3, 3, ma200_near ? "震荡条件" : "趋势条件", text_color=color.black, bgcolor=ma200_color, text_size=text_size)
|
||
table.cell(info_table, 4, 3, advanced_long_alert ? "高级做多" : advanced_short_alert ? "高级做空" : oscillation_signal ? "满足震荡" : long_signal ? "满足做多" : short_signal ? "满足做空" : "无满足", text_color=color.black, bgcolor=signal_color, text_size=text_size)
|
||
table.cell(info_table, 5, 3, advanced_long_alert ? "执行高级做多" : advanced_short_alert ? "执行高级做空" : long_signal ? "执行做多" : short_signal ? "执行做空" : oscillation_signal ? "保持震荡" : "继续观望", text_color=color.black, bgcolor=final_signal_color, text_size=text_size)
|
||
// 高级警报条件说明
|
||
table.cell(info_table, 6, 3, long_trigger ? "价格上穿R1" : short_trigger ? "价格下穿S1" : not na(long_trigger_time) ? "做多监控中" : not na(short_trigger_time) ? "做空监控中" : "等待穿越", text_color=color.black, bgcolor=trigger_color, text_size=text_size)
|
||
table.cell(info_table, 7, 3, condition2_1m_long ? "1m做多就绪" : condition2_1m_short ? "1m做空就绪" : "1m条件未满足", text_color=color.black, bgcolor=condition2_color, text_size=text_size)
|
||
table.cell(info_table, 8, 3, condition3_5m_long ? "5m做多就绪" : condition3_5m_short ? "5m做空就绪" : "5m条件未满足", text_color=color.black, bgcolor=condition3_color, text_size=text_size)
|
||
table.cell(info_table, 9, 3, condition4_15m_long ? "15m距离满足" : condition4_15m_short ? "15m距离满足" : "15m距离不足", text_color=color.black, bgcolor=condition4_color, text_size=text_size)
|
||
|
||
// ═════════ 关键数值表格(右中位置,避免与主表格重叠) ═════════
|
||
// 创建关键数值表格
|
||
var table key_values_table = table.new(
|
||
position = position.middle_right, // 改为右中位置
|
||
columns = 4, // 4列:R1阻力 + S1支撑 + MEAN中线 + 距离阈值
|
||
rows = 3, // 3行:标题 + 数值 + 通道信息
|
||
bgcolor = color.new(color.white, 85),
|
||
border_width = 1)
|
||
|
||
// 清空表格
|
||
table.clear(key_values_table, 0, 0, 3, 2)
|
||
|
||
// 关键数值标题行
|
||
table.cell(key_values_table, 0, 0, "R1阻力", text_color=color.white, bgcolor=color.new(color.red, 40), text_size=text_size)
|
||
table.cell(key_values_table, 1, 0, "S1支撑", text_color=color.white, bgcolor=color.new(color.green, 40), text_size=text_size)
|
||
table.cell(key_values_table, 2, 0, "MEAN中线", text_color=color.white, bgcolor=color.new(color.blue, 40), text_size=text_size)
|
||
table.cell(key_values_table, 3, 0, "距离阈值", text_color=color.white, bgcolor=color.new(color.gray, 40), text_size=text_size)
|
||
|
||
// 关键数值数据行
|
||
table.cell(key_values_table, 0, 1, str.tostring(upband1, '#.####'), text_color=color.black, bgcolor=color.new(color.red, 20), text_size=text_size)
|
||
table.cell(key_values_table, 1, 1, str.tostring(loband1, '#.####'), text_color=color.black, bgcolor=color.new(color.green, 20), text_size=text_size)
|
||
table.cell(key_values_table, 2, 1, str.tostring(meanline, '#.####'), text_color=color.black, bgcolor=color.new(color.blue, 20), text_size=text_size)
|
||
table.cell(key_values_table, 3, 1, str.tostring(distance_threshold, '#.##'), text_color=color.black, bgcolor=color.new(color.gray, 20), text_size=text_size)
|
||
|
||
// 通道距离信息行
|
||
channel_width = upband1 - loband1 // R1-S1通道宽度
|
||
r1_r2_distance = upband2 - upband1 // R1到R2距离
|
||
s1_s2_distance = loband1 - loband2 // S1到S2距离
|
||
|
||
table.cell(key_values_table, 0, 2, "R1-R2:" + str.tostring(r1_r2_distance, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 10), text_size=text_size)
|
||
table.cell(key_values_table, 1, 2, "S1-S2:" + str.tostring(s1_s2_distance, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 10), text_size=text_size)
|
||
table.cell(key_values_table, 2, 2, "通道宽度:" + str.tostring(channel_width, '#.##'), text_color=color.black, bgcolor=color.new(color.blue, 10), text_size=text_size)
|
||
table.cell(key_values_table, 3, 2, "当前距离:" + str.tostring(distance_usd, '#.#'), text_color=color.black, bgcolor=color.new(color.gray, 10), text_size=text_size)
|
||
|
||
// ═════════ 多时间框架表格显示 ═════════
|
||
if show_mtf_table and barstate.islast
|
||
// 创建多时间框架表格(右上角)- 增加MEAN距离列
|
||
var table mtf_table = table.new(
|
||
position = position.top_right,
|
||
columns = 13, // 增加到13列:时间框架 + RSI + RSI状态 + 穿越次数 + 价格位置 + 价格MEAN位置 + MA50位置 + MA200距离 + MEAN距离 + R1距离 + S1距离 + 信号 + 判断
|
||
rows = mtf_table_rows,
|
||
bgcolor = color.new(color.white, 85),
|
||
border_width = 1)
|
||
|
||
// 清空表格
|
||
table.clear(mtf_table, 0, 0, 12, mtf_table_rows - 1)
|
||
|
||
// 获取配置的文字大小
|
||
text_size = get_text_size()
|
||
|
||
// 获取距离阈值
|
||
r1s1_threshold = get_r1s1_distance_threshold()
|
||
|
||
// ═════════ 多时间框架表格标题行 ═════════
|
||
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, "RSI", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 2, 0, "RSI状态", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 3, 0, "穿越次数", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 4, 0, "价格位置", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 5, 0, "价格MEAN", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 6, 0, "MA50位置", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 7, 0, "MA200距离", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 8, 0, "MEAN距离", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 9, 0, "R1距离", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 10, 0, "S1距离", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 11, 0, "信号", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(mtf_table, 12, 0, "判断", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
|
||
// ═════════ 1分钟时间框架数据 ═════════
|
||
if mtf_1m and not na(rsi_1m)
|
||
signal_color_1m = get_signal_color(osc_1m, long_1m, short_1m)
|
||
rsi_status_1m = get_rsi_status(rsi_1m, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_1m = get_rsi_color(rsi_1m, long_S, short_S, rsi_neutral_1m, rsi_overbought_1m, rsi_oversold_1m)
|
||
price_color_1m = get_price_color(close_1m, upband1_1m, loband1_1m, price_in_channel_1m, price_above_r1_1m, price_below_s1_1m)
|
||
price_mean_color_1m = get_price_mean_color(close_1m, meanline_1m)
|
||
ma50_color_1m = get_ma50_color(ma50_1m, meanline_1m, ma50_above_mean_1m, ma50_below_mean_1m)
|
||
ma200_distance_color_1m = get_ma200_distance_color(distance_1m, distance_threshold_1m, ma200_near_1m, ma200_far_1m)
|
||
|
||
table.cell(mtf_table, 0, 1, "1分钟", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 1, str.tostring(rsi_1m, '#.#'), text_color=color.black, bgcolor=rsi_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 2, 1, rsi_status_1m, text_color=color.black, bgcolor=rsi_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 3, 1, na(cross_count_1m) ? "N/A" : str.tostring(cross_count_1m), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 1, get_price_position(close_1m, upband1_1m, loband1_1m), text_color=color.black, bgcolor=price_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 5, 1, get_price_mean_position(close_1m, meanline_1m), text_color=color.black, bgcolor=price_mean_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 6, 1, get_ma50_position(ma50_1m, meanline_1m), text_color=color.black, bgcolor=ma50_color_1m, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_1m = get_distance_bg_color(distance_1m, distance_threshold_1m)
|
||
mean_bg_color_1m = get_distance_bg_color(distance_to_mean_1m, r1s1_threshold)
|
||
r1_bg_color_1m = get_distance_bg_color(distance_to_r1_1m, r1s1_threshold)
|
||
s1_bg_color_1m = get_distance_bg_color(distance_to_s1_1m, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 1, str.tostring(distance_1m, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 8, 1, na(distance_to_mean_1m) ? "N/A" : str.tostring(distance_to_mean_1m, '#.##'), text_color=color.black, bgcolor=mean_bg_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 9, 1, na(distance_to_r1_1m) ? "N/A" : str.tostring(distance_to_r1_1m, '#.##'), text_color=color.black, bgcolor=r1_bg_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 10, 1, na(distance_to_s1_1m) ? "N/A" : str.tostring(distance_to_s1_1m, '#.##'), text_color=color.black, bgcolor=s1_bg_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 11, 1, get_signal_text(osc_1m, long_1m, short_1m), text_color=color.black, bgcolor=signal_color_1m, text_size=text_size)
|
||
table.cell(mtf_table, 12, 1, get_final_judgment(osc_1m, long_1m, short_1m), text_color=color.black, bgcolor=signal_color_1m, text_size=text_size)
|
||
|
||
// ═════════ 5分钟时间框架数据 ═════════
|
||
if mtf_5m and not na(rsi_5m)
|
||
signal_color_5m = get_signal_color(osc_5m, long_5m, short_5m)
|
||
rsi_status_5m = get_rsi_status(rsi_5m, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_5m = get_rsi_color(rsi_5m, long_S, short_S, rsi_neutral_5m, rsi_overbought_5m, rsi_oversold_5m)
|
||
price_color_5m = get_price_color(close_5m, upband1_5m, loband1_5m, price_in_channel_5m, price_above_r1_5m, price_below_s1_5m)
|
||
price_mean_color_5m = get_price_mean_color(close_5m, meanline_5m)
|
||
ma50_color_5m = get_ma50_color(ma50_5m, meanline_5m, ma50_above_mean_5m, ma50_below_mean_5m)
|
||
ma200_distance_color_5m = get_ma200_distance_color(distance_5m, distance_threshold_1m, ma200_near_5m, ma200_far_5m)
|
||
|
||
table.cell(mtf_table, 0, 2, "5分钟", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 2, str.tostring(rsi_5m, '#.#'), text_color=color.black, bgcolor=rsi_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 2, 2, rsi_status_5m, text_color=color.black, bgcolor=rsi_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 3, 2, na(cross_count_5m) ? "N/A" : str.tostring(cross_count_5m), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 2, get_price_position(close_5m, upband1_5m, loband1_5m), text_color=color.black, bgcolor=price_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 5, 2, get_price_mean_position(close_5m, meanline_5m), text_color=color.black, bgcolor=price_mean_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 6, 2, get_ma50_position(ma50_5m, meanline_5m), text_color=color.black, bgcolor=ma50_color_5m, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_5m = get_distance_bg_color(distance_5m, distance_threshold_1m)
|
||
mean_bg_color_5m = get_distance_bg_color(distance_to_mean_5m, r1s1_threshold)
|
||
r1_bg_color_5m = get_distance_bg_color(distance_to_r1_5m, r1s1_threshold)
|
||
s1_bg_color_5m = get_distance_bg_color(distance_to_s1_5m, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 2, str.tostring(distance_5m, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 8, 2, na(distance_to_mean_5m) ? "N/A" : str.tostring(distance_to_mean_5m, '#.##'), text_color=color.black, bgcolor=mean_bg_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 9, 2, na(distance_to_r1_5m) ? "N/A" : str.tostring(distance_to_r1_5m, '#.##'), text_color=color.black, bgcolor=r1_bg_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 10, 2, na(distance_to_s1_5m) ? "N/A" : str.tostring(distance_to_s1_5m, '#.##'), text_color=color.black, bgcolor=s1_bg_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 11, 2, get_signal_text(osc_5m, long_5m, short_5m), text_color=color.black, bgcolor=signal_color_5m, text_size=text_size)
|
||
table.cell(mtf_table, 12, 2, get_final_judgment(osc_5m, long_5m, short_5m), text_color=color.black, bgcolor=signal_color_5m, text_size=text_size)
|
||
|
||
// ═════════ 15分钟时间框架数据 ═════════
|
||
if mtf_15m and not na(rsi_15m)
|
||
signal_color_15m = get_signal_color(osc_15m, long_15m, short_15m)
|
||
rsi_status_15m = get_rsi_status(rsi_15m, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_15m = get_rsi_color(rsi_15m, long_S, short_S, rsi_neutral_15m, rsi_overbought_15m, rsi_oversold_15m)
|
||
price_color_15m = get_price_color(close_15m, upband1_15m, loband1_15m, price_in_channel_15m, price_above_r1_15m, price_below_s1_15m)
|
||
price_mean_color_15m = get_price_mean_color(close_15m, meanline_15m)
|
||
ma50_color_15m = get_ma50_color(ma50_15m, meanline_15m, ma50_above_mean_15m, ma50_below_mean_15m)
|
||
ma200_distance_color_15m = get_ma200_distance_color(distance_15m, distance_threshold_1m, ma200_near_15m, ma200_far_15m)
|
||
|
||
table.cell(mtf_table, 0, 3, "15分钟", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 3, str.tostring(rsi_15m, '#.#'), text_color=color.black, bgcolor=rsi_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 2, 3, rsi_status_15m, text_color=color.black, bgcolor=rsi_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 3, 3, na(cross_count_15m) ? "N/A" : str.tostring(cross_count_15m), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 3, get_price_position(close_15m, upband1_15m, loband1_15m), text_color=color.black, bgcolor=price_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 5, 3, get_price_mean_position(close_15m, meanline_15m), text_color=color.black, bgcolor=price_mean_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 6, 3, get_ma50_position(ma50_15m, meanline_15m), text_color=color.black, bgcolor=ma50_color_15m, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_15m = get_distance_bg_color(distance_15m, distance_threshold_1m)
|
||
mean_bg_color_15m = get_distance_bg_color(distance_to_mean_15m, r1s1_threshold)
|
||
r1_bg_color_15m = get_distance_bg_color(distance_to_r1_15m, r1s1_threshold)
|
||
s1_bg_color_15m = get_distance_bg_color(distance_to_s1_15m, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 3, str.tostring(distance_15m, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 8, 3, na(distance_to_mean_15m) ? "N/A" : str.tostring(distance_to_mean_15m, '#.##'), text_color=color.black, bgcolor=mean_bg_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 9, 3, na(distance_to_r1_15m) ? "N/A" : str.tostring(distance_to_r1_15m, '#.##'), text_color=color.black, bgcolor=r1_bg_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 10, 3, na(distance_to_s1_15m) ? "N/A" : str.tostring(distance_to_s1_15m, '#.##'), text_color=color.black, bgcolor=s1_bg_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 11, 3, get_signal_text(osc_15m, long_15m, short_15m), text_color=color.black, bgcolor=signal_color_15m, text_size=text_size)
|
||
table.cell(mtf_table, 12, 3, get_final_judgment(osc_15m, long_15m, short_15m), text_color=color.black, bgcolor=signal_color_15m, text_size=text_size)
|
||
|
||
// ═════════ 30分钟时间框架数据 ═════════
|
||
if mtf_30m and not na(rsi_30m)
|
||
signal_color_30m = get_signal_color(osc_30m, long_30m, short_30m)
|
||
rsi_status_30m = get_rsi_status(rsi_30m, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_30m = get_rsi_color(rsi_30m, long_S, short_S, rsi_neutral_30m, rsi_overbought_30m, rsi_oversold_30m)
|
||
price_color_30m = get_price_color(close_30m, upband1_30m, loband1_30m, price_in_channel_30m, price_above_r1_30m, price_below_s1_30m)
|
||
price_mean_color_30m = get_price_mean_color(close_30m, meanline_30m)
|
||
ma50_color_30m = get_ma50_color(ma50_30m, meanline_30m, ma50_above_mean_30m, ma50_below_mean_30m)
|
||
ma200_distance_color_30m = get_ma200_distance_color(distance_30m, distance_threshold_1m, ma200_near_30m, ma200_far_30m)
|
||
|
||
table.cell(mtf_table, 0, 4, "30分钟", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 4, str.tostring(rsi_30m, '#.#'), text_color=color.black, bgcolor=rsi_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 2, 4, rsi_status_30m, text_color=color.black, bgcolor=rsi_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 3, 4, na(cross_count_30m) ? "N/A" : str.tostring(cross_count_30m), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 4, get_price_position(close_30m, upband1_30m, loband1_30m), text_color=color.black, bgcolor=price_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 5, 4, get_price_mean_position(close_30m, meanline_30m), text_color=color.black, bgcolor=price_mean_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 6, 4, get_ma50_position(ma50_30m, meanline_30m), text_color=color.black, bgcolor=ma50_color_30m, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_30m = get_distance_bg_color(distance_30m, distance_threshold_1m)
|
||
mean_bg_color_30m = get_distance_bg_color(distance_to_mean_30m, r1s1_threshold)
|
||
r1_bg_color_30m = get_distance_bg_color(distance_to_r1_30m, r1s1_threshold)
|
||
s1_bg_color_30m = get_distance_bg_color(distance_to_s1_30m, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 4, str.tostring(distance_30m, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 8, 4, na(distance_to_mean_30m) ? "N/A" : str.tostring(distance_to_mean_30m, '#.##'), text_color=color.black, bgcolor=mean_bg_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 9, 4, na(distance_to_r1_30m) ? "N/A" : str.tostring(distance_to_r1_30m, '#.##'), text_color=color.black, bgcolor=r1_bg_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 10, 4, na(distance_to_s1_30m) ? "N/A" : str.tostring(distance_to_s1_30m, '#.##'), text_color=color.black, bgcolor=s1_bg_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 11, 4, get_signal_text(osc_30m, long_30m, short_30m), text_color=color.black, bgcolor=signal_color_30m, text_size=text_size)
|
||
table.cell(mtf_table, 12, 4, get_final_judgment(osc_30m, long_30m, short_30m), text_color=color.black, bgcolor=signal_color_30m, text_size=text_size)
|
||
|
||
// ═════════ 45分钟时间框架数据 ═════════
|
||
if mtf_45m and not na(rsi_45m)
|
||
signal_color_45m = get_signal_color(osc_45m, long_45m, short_45m)
|
||
rsi_status_45m = get_rsi_status(rsi_45m, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_45m = get_rsi_color(rsi_45m, long_S, short_S, rsi_neutral_45m, rsi_overbought_45m, rsi_oversold_45m)
|
||
price_color_45m = get_price_color(close_45m, upband1_45m, loband1_45m, price_in_channel_45m, price_above_r1_45m, price_below_s1_45m)
|
||
price_mean_color_45m = get_price_mean_color(close_45m, meanline_45m)
|
||
ma50_color_45m = get_ma50_color(ma50_45m, meanline_45m, ma50_above_mean_45m, ma50_below_mean_45m)
|
||
ma200_distance_color_45m = get_ma200_distance_color(distance_45m, distance_threshold_1m, ma200_near_45m, ma200_far_45m)
|
||
|
||
table.cell(mtf_table, 0, 5, "45分钟", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 5, str.tostring(rsi_45m, '#.#'), text_color=color.black, bgcolor=rsi_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 2, 5, rsi_status_45m, text_color=color.black, bgcolor=rsi_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 3, 5, na(cross_count_45m) ? "N/A" : str.tostring(cross_count_45m), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 5, get_price_position(close_45m, upband1_45m, loband1_45m), text_color=color.black, bgcolor=price_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 5, 5, get_price_mean_position(close_45m, meanline_45m), text_color=color.black, bgcolor=price_mean_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 6, 5, get_ma50_position(ma50_45m, meanline_45m), text_color=color.black, bgcolor=ma50_color_45m, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_45m = get_distance_bg_color(distance_45m, distance_threshold_1m)
|
||
mean_bg_color_45m = get_distance_bg_color(distance_to_mean_45m, r1s1_threshold)
|
||
r1_bg_color_45m = get_distance_bg_color(distance_to_r1_45m, r1s1_threshold)
|
||
s1_bg_color_45m = get_distance_bg_color(distance_to_s1_45m, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 5, str.tostring(distance_45m, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 8, 5, na(distance_to_mean_45m) ? "N/A" : str.tostring(distance_to_mean_45m, '#.##'), text_color=color.black, bgcolor=mean_bg_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 9, 5, na(distance_to_r1_45m) ? "N/A" : str.tostring(distance_to_r1_45m, '#.##'), text_color=color.black, bgcolor=r1_bg_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 10, 5, na(distance_to_s1_45m) ? "N/A" : str.tostring(distance_to_s1_45m, '#.##'), text_color=color.black, bgcolor=s1_bg_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 11, 5, get_signal_text(osc_45m, long_45m, short_45m), text_color=color.black, bgcolor=signal_color_45m, text_size=text_size)
|
||
table.cell(mtf_table, 12, 5, get_final_judgment(osc_45m, long_45m, short_45m), text_color=color.black, bgcolor=signal_color_45m, text_size=text_size)
|
||
|
||
// ═════════ 1小时时间框架数据 ═════════
|
||
if mtf_1h and not na(rsi_1h)
|
||
signal_color_1h = get_signal_color(osc_1h, long_1h, short_1h)
|
||
rsi_status_1h = get_rsi_status(rsi_1h, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_1h = get_rsi_color(rsi_1h, long_S, short_S, rsi_neutral_1h, rsi_overbought_1h, rsi_oversold_1h)
|
||
price_color_1h = get_price_color(close_1h, upband1_1h, loband1_1h, price_in_channel_1h, price_above_r1_1h, price_below_s1_1h)
|
||
price_mean_color_1h = get_price_mean_color(close_1h, meanline_1h)
|
||
ma50_color_1h = get_ma50_color(ma50_1h, meanline_1h, ma50_above_mean_1h, ma50_below_mean_1h)
|
||
ma200_distance_color_1h = get_ma200_distance_color(distance_1h, distance_threshold_1m, ma200_near_1h, ma200_far_1h)
|
||
|
||
table.cell(mtf_table, 0, 6, "1小时", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 6, str.tostring(rsi_1h, '#.#'), text_color=color.black, bgcolor=rsi_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 2, 6, rsi_status_1h, text_color=color.black, bgcolor=rsi_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 3, 6, na(cross_count_1h) ? "N/A" : str.tostring(cross_count_1h), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 6, get_price_position(close_1h, upband1_1h, loband1_1h), text_color=color.black, bgcolor=price_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 5, 6, get_price_mean_position(close_1h, meanline_1h), text_color=color.black, bgcolor=price_mean_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 6, 6, get_ma50_position(ma50_1h, meanline_1h), text_color=color.black, bgcolor=ma50_color_1h, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_1h = get_distance_bg_color(distance_1h, distance_threshold_1m)
|
||
mean_bg_color_1h = get_distance_bg_color(distance_to_mean_1h, r1s1_threshold)
|
||
r1_bg_color_1h = get_distance_bg_color(distance_to_r1_1h, r1s1_threshold)
|
||
s1_bg_color_1h = get_distance_bg_color(distance_to_s1_1h, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 6, str.tostring(distance_1h, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 8, 6, na(distance_to_mean_1h) ? "N/A" : str.tostring(distance_to_mean_1h, '#.##'), text_color=color.black, bgcolor=mean_bg_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 9, 6, na(distance_to_r1_1h) ? "N/A" : str.tostring(distance_to_r1_1h, '#.##'), text_color=color.black, bgcolor=r1_bg_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 10, 6, na(distance_to_s1_1h) ? "N/A" : str.tostring(distance_to_s1_1h, '#.##'), text_color=color.black, bgcolor=s1_bg_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 11, 6, get_signal_text(osc_1h, long_1h, short_1h), text_color=color.black, bgcolor=signal_color_1h, text_size=text_size)
|
||
table.cell(mtf_table, 12, 6, get_final_judgment(osc_1h, long_1h, short_1h), text_color=color.black, bgcolor=signal_color_1h, text_size=text_size)
|
||
|
||
// ═════════ 4小时时间框架数据 ═════════
|
||
if mtf_4h and not na(rsi_4h)
|
||
signal_color_4h = get_signal_color(osc_4h, long_4h, short_4h)
|
||
rsi_status_4h = get_rsi_status(rsi_4h, long_S, short_S)
|
||
|
||
// 计算各个条件的颜色
|
||
rsi_color_4h = get_rsi_color(rsi_4h, long_S, short_S, rsi_neutral_4h, rsi_overbought_4h, rsi_oversold_4h)
|
||
price_color_4h = get_price_color(close_4h, upband1_4h, loband1_4h, price_in_channel_4h, price_above_r1_4h, price_below_s1_4h)
|
||
price_mean_color_4h = get_price_mean_color(close_4h, meanline_4h)
|
||
ma50_color_4h = get_ma50_color(ma50_4h, meanline_4h, ma50_above_mean_4h, ma50_below_mean_4h)
|
||
ma200_distance_color_4h = get_ma200_distance_color(distance_4h, distance_threshold_1m, ma200_near_4h, ma200_far_4h)
|
||
|
||
table.cell(mtf_table, 0, 7, "4小时", text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 1, 7, str.tostring(rsi_4h, '#.#'), text_color=color.black, bgcolor=rsi_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 2, 7, rsi_status_4h, text_color=color.black, bgcolor=rsi_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 3, 7, na(cross_count_4h) ? "N/A" : str.tostring(cross_count_4h), text_color=color.black, text_size=text_size)
|
||
table.cell(mtf_table, 4, 7, get_price_position(close_4h, upband1_4h, loband1_4h), text_color=color.black, bgcolor=price_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 5, 7, get_price_mean_position(close_4h, meanline_4h), text_color=color.black, bgcolor=price_mean_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 6, 7, get_ma50_position(ma50_4h, meanline_4h), text_color=color.black, bgcolor=ma50_color_4h, text_size=text_size)
|
||
// 计算距离背景颜色
|
||
ma200_bg_color_4h = get_distance_bg_color(distance_4h, distance_threshold_1m)
|
||
mean_bg_color_4h = get_distance_bg_color(distance_to_mean_4h, r1s1_threshold)
|
||
r1_bg_color_4h = get_distance_bg_color(distance_to_r1_4h, r1s1_threshold)
|
||
s1_bg_color_4h = get_distance_bg_color(distance_to_s1_4h, r1s1_threshold)
|
||
|
||
table.cell(mtf_table, 7, 7, str.tostring(distance_4h, '#.##'), text_color=color.black, bgcolor=ma200_bg_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 8, 7, na(distance_to_mean_4h) ? "N/A" : str.tostring(distance_to_mean_4h, '#.##'), text_color=color.black, bgcolor=mean_bg_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 9, 7, na(distance_to_r1_4h) ? "N/A" : str.tostring(distance_to_r1_4h, '#.##'), text_color=color.black, bgcolor=r1_bg_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 10, 7, na(distance_to_s1_4h) ? "N/A" : str.tostring(distance_to_s1_4h, '#.##'), text_color=color.black, bgcolor=s1_bg_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 11, 7, get_signal_text(osc_4h, long_4h, short_4h), text_color=color.black, bgcolor=signal_color_4h, text_size=text_size)
|
||
table.cell(mtf_table, 12, 7, get_final_judgment(osc_4h, long_4h, short_4h), text_color=color.black, bgcolor=signal_color_4h, text_size=text_size)
|
||
|
||
|
||
|
||
|
||
// ═════════ RSI详细表格(左下角,可配置显示) ═════════
|
||
|
||
if show_rsi_table and barstate.islast
|
||
var table rsi_table = table.new(
|
||
position = position.bottom_left, // 左下角
|
||
columns = 2,
|
||
rows = 10,
|
||
bgcolor = color.new(color.white, 85),
|
||
border_width = 1)
|
||
|
||
table.clear(rsi_table, 0, 0, 1, 9)
|
||
|
||
// 获取RSI表格的文字大小
|
||
rsi_text_size = get_text_size()
|
||
|
||
// RSI详细信息表格内容(预留)
|
||
table.cell(rsi_table, 0, 0, "RSI详细分析", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=rsi_text_size)
|
||
table.cell(rsi_table, 1, 0, "", text_color=color.black, text_size=rsi_text_size)
|
||
|
||
// ═════════ 高级警报状态表格(已禁用,整合到信息表格中) ═════════
|
||
|
||
if false // 禁用独立的高级警报表格
|
||
var table alert_status_table = table.new(
|
||
position = position.top_right,
|
||
columns = 2,
|
||
rows = 12,
|
||
bgcolor = color.new(color.white, 85),
|
||
border_width = 1)
|
||
|
||
table.clear(alert_status_table, 0, 0, 1, 11)
|
||
|
||
text_size = get_text_size()
|
||
|
||
// 标题
|
||
table.cell(alert_status_table, 0, 0, "高级警报状态", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
table.cell(alert_status_table, 1, 0, "当前状态", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||
|
||
// 启动条件状态
|
||
long_trigger_status = long_trigger ? "✓ 已触发" : na(long_trigger_time) ? "等待中" : "监控中"
|
||
short_trigger_status = short_trigger ? "✓ 已触发" : na(short_trigger_time) ? "等待中" : "监控中"
|
||
|
||
table.cell(alert_status_table, 0, 1, "做多启动", text_color=color.black, text_size=text_size)
|
||
table.cell(alert_status_table, 1, 1, long_trigger_status, text_color=color.black, bgcolor=long_trigger ? color.new(color.green, 60) : color.white, text_size=text_size)
|
||
|
||
table.cell(alert_status_table, 0, 2, "做空启动", text_color=color.black, text_size=text_size)
|
||
table.cell(alert_status_table, 1, 2, short_trigger_status, text_color=color.black, bgcolor=short_trigger ? color.new(color.red, 60) : color.white, text_size=text_size)
|
||
|
||
// 时间窗口状态
|
||
long_window_status = not na(long_trigger_time) ? (in_time_window(long_trigger_time, time_window_15min) ? "窗口内" : "已过期") : "未启动"
|
||
short_window_status = not na(short_trigger_time) ? (in_time_window(short_trigger_time, time_window_15min) ? "窗口内" : "已过期") : "未启动"
|
||
|
||
table.cell(alert_status_table, 0, 3, "做多窗口", text_color=color.black, text_size=text_size)
|
||
table.cell(alert_status_table, 1, 3, long_window_status, text_color=color.black, text_size=text_size)
|
||
|
||
table.cell(alert_status_table, 0, 4, "做空窗口", text_color=color.black, text_size=text_size)
|
||
table.cell(alert_status_table, 1, 4, short_window_status, text_color=color.black, text_size=text_size)
|
||
|
||
// 冷却状态
|
||
long_cooldown_status = is_cooldown_over(last_long_alert_time, alert_cooldown_minutes) ? "可用" : "冷却中"
|
||
short_cooldown_status = is_cooldown_over(last_short_alert_time, alert_cooldown_minutes) ? "可用" : "冷却中"
|
||
|
||
table.cell(alert_status_table, 0, 5, "做多冷却", text_color=color.black, text_size=text_size)
|
||
table.cell(alert_status_table, 1, 5, long_cooldown_status, text_color=color.black, text_size=text_size)
|
||
|
||
table.cell(alert_status_table, 0, 6, "做空冷却", text_color=color.black, text_size=text_size)
|
||
table.cell(alert_status_table, 1, 6, short_cooldown_status, text_color=color.black, text_size=text_size)
|
||
|
||
// 条件状态检查
|
||
condition2_1m_long = not na(long_trigger_time) and in_time_window(long_trigger_time, time_window_5min) and rsi_overbought_1m and price_above_r1_1m and ma200_far_1m and ma50_above_mean_1m
|
||
condition3_5m_long = not na(long_trigger_time) and in_time_window(long_trigger_time, time_window_15min) and rsi_overbought_5m and price_above_mean_5m and ma200_far_5m and ma50_above_mean_1m
|
||
condition4_15m_long = not na(long_trigger_time) and in_time_window(long_trigger_time, time_window_10min) and distance_to_s1_15m > get_r1s1_distance_threshold()
|
||
|
||
condition2_1m_short = not na(short_trigger_time) and in_time_window(short_trigger_time, time_window_5min) and rsi_oversold_1m and price_below_s1_1m and ma200_far_1m and ma50_below_mean_1m
|
||
condition3_5m_short = not na(short_trigger_time) and in_time_window(short_trigger_time, time_window_15min) and rsi_oversold_5m and price_below_mean_5m and ma200_far_5m and ma50_below_mean_1m
|
||
condition4_15m_short = not na(short_trigger_time) and in_time_window(short_trigger_time, time_window_10min) and distance_to_r1_15m > get_r1s1_distance_threshold()
|
||
|
||
// 条件状态显示
|
||
table.cell(alert_status_table, 0, 7, "条件2(1m)", text_color=color.black, text_size=text_size)
|
||
condition2_status = condition2_1m_long ? "✓做多" : condition2_1m_short ? "✓做空" : "未满足"
|
||
condition2_color = condition2_1m_long ? color.new(color.green, 60) : condition2_1m_short ? color.new(color.red, 60) : color.white
|
||
table.cell(alert_status_table, 1, 7, condition2_status, text_color=color.black, bgcolor=condition2_color, text_size=text_size)
|
||
|
||
table.cell(alert_status_table, 0, 8, "条件3(5m)", text_color=color.black, text_size=text_size)
|
||
condition3_status = condition3_5m_long ? "✓做多" : condition3_5m_short ? "✓做空" : "未满足"
|
||
condition3_color = condition3_5m_long ? color.new(color.green, 60) : condition3_5m_short ? color.new(color.red, 60) : color.white
|
||
table.cell(alert_status_table, 1, 8, condition3_status, text_color=color.black, bgcolor=condition3_color, text_size=text_size)
|
||
|
||
table.cell(alert_status_table, 0, 9, "条件4(15m)", text_color=color.black, text_size=text_size)
|
||
condition4_status = condition4_15m_long ? "✓做多" : condition4_15m_short ? "✓做空" : "未满足"
|
||
condition4_color = condition4_15m_long ? color.new(color.green, 60) : condition4_15m_short ? color.new(color.red, 60) : color.white
|
||
table.cell(alert_status_table, 1, 9, condition4_status, text_color=color.black, bgcolor=condition4_color, text_size=text_size)
|
||
|
||
// 综合条件状态
|
||
all_long_conditions = condition2_1m_long and condition3_5m_long and condition4_15m_long
|
||
all_short_conditions = condition2_1m_short and condition3_5m_short and condition4_15m_short
|
||
|
||
table.cell(alert_status_table, 0, 10, "综合条件", text_color=color.black, text_size=text_size)
|
||
combined_status = all_long_conditions ? "✓做多就绪" : all_short_conditions ? "✓做空就绪" : "未就绪"
|
||
combined_color = all_long_conditions ? color.new(color.lime, 60) : all_short_conditions ? color.new(color.fuchsia, 60) : color.white
|
||
table.cell(alert_status_table, 1, 10, combined_status, text_color=color.black, bgcolor=combined_color, text_size=text_size)
|
||
|
||
// 最终警报状态
|
||
final_long_status = advanced_long_alert ? "🚀 警报!" : "等待中"
|
||
final_short_status = advanced_short_alert ? "🔻 警报!" : "等待中"
|
||
|
||
table.cell(alert_status_table, 0, 11, "警报状态", text_color=color.black, text_size=text_size)
|
||
alert_status_text = advanced_long_alert ? final_long_status : advanced_short_alert ? final_short_status : "无警报"
|
||
alert_status_color = advanced_long_alert ? color.new(color.lime, 40) : advanced_short_alert ? color.new(color.fuchsia, 40) : color.white
|
||
table.cell(alert_status_table, 1, 11, alert_status_text, text_color=color.black, bgcolor=alert_status_color, text_size=text_size)
|
||
|
||
// ═════════ 实时价格标签显示信号结论 ═════════
|
||
|
||
// 确定当前主要信号(包含高级警报)
|
||
current_signal = advanced_long_alert ? "🚀高级做多" : advanced_short_alert ? "🔻高级做空" : long_signal ? "🚀做多" : short_signal ? "🔻做空" : oscillation_signal ? "⚡震荡" : "观望"
|
||
signal_color = advanced_long_alert ? color.lime : advanced_short_alert ? color.fuchsia : long_signal ? color.green : short_signal ? color.red : oscillation_signal ? color.orange : color.gray
|
||
|
||
// 创建唯一的实时价格标签(避免重复)
|
||
var label price_signal_label = na
|
||
|
||
// 在最后一根K线上显示实时价格标签
|
||
if barstate.islast
|
||
// 删除之前的标签
|
||
if not na(price_signal_label)
|
||
label.delete(price_signal_label)
|
||
|
||
// 计算标签位置:使用时间坐标,右偏移避免重叠
|
||
label_time = time + (time - time[1]) * 3 // 右偏移3个时间单位
|
||
|
||
// 创建新的实时价格标签
|
||
price_label_text = str.tostring(close, '#.####') + " | " + current_signal
|
||
price_signal_label := label.new(x=label_time, y=close, text=price_label_text, style=label.style_label_left, color=color.new(signal_color, 20), textcolor=color.white, size=size.normal, xloc=xloc.bar_time)
|
||
|
||
// 删除超出表格范围的残留代码
|
||
|
||
//************************************************************************************************************
|
||
// RSI 窗口二显示
|
||
//************************************************************************************************************
|
||
|
||
// RSI 数据输出(用于在单独的RSI指标中显示)
|
||
// 注意:由于TradingView限制,RSI需要在单独的指标中显示
|
||
// 这里我们输出RSI数据供外部使用,同时在表格中显示数值
|
||
|
||
// 为了在主图中也能看到RSI信息,我们将RSI数据通过plot输出(但不显示)
|
||
plot(rsi, 'RSI_Data', display=display.none)
|
||
plot(long_S, 'RSI_Long_Threshold', display=display.none)
|
||
plot(short_S, 'RSI_Short_Threshold', display=display.none)
|
||
plot(segment_count, 'RSI_Segment_Count', display=display.none)
|
||
|
||
// RSI 信息表格(可选显示,计算始终保留用于警报)
|
||
if show_rsi_table and barstate.islast
|
||
// 创建RSI表格
|
||
var table rsi_table = table.new(
|
||
position = position.bottom_right,
|
||
columns = 2,
|
||
rows = 8,
|
||
bgcolor = color.new(color.yellow, 80),
|
||
border_width = 1)
|
||
|
||
// 清空表格
|
||
table.clear(rsi_table, 0, 0, 1, 7)
|
||
|
||
// 添加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 穿越类型
|
||
cross_type = segment_count > 0 ? "超买穿越" : segment_count < 0 ? "超卖穿越" : "无穿越"
|
||
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)
|
||
|
||
//************************************************************************************************************
|
||
// 趋势判断逻辑
|
||
//************************************************************************************************************
|
||
|
||
// 综合趋势判断
|
||
trend_signal = ""
|
||
market_type = ""
|
||
|
||
// 删除不再使用的角度趋势判断(已在前面重新定义)
|
||
|
||
// 价格相对MA200位置
|
||
price_above_ma200 = close > ma200
|
||
price_below_ma200 = close < ma200
|
||
|
||
// RSI 趋势确认
|
||
rsi_bullish = rsi > 50 and rsi < long_S
|
||
rsi_bearish = rsi < 50 and rsi > short_S
|
||
rsi_overbought = rsi > long_S
|
||
rsi_oversold = rsi < short_S
|
||
|
||
// 重新设计的综合判断逻辑
|
||
// 首先判断是否为震荡
|
||
if is_oscillating
|
||
trend_signal := "震荡行情"
|
||
market_type := "震荡"
|
||
// 然后判断趋势强度和方向
|
||
else if ma200_trend_direction == "上升"
|
||
if ma200_strength == "强" and price_above_ma200 and (rsi_bullish or rsi_overbought)
|
||
trend_signal := "强多头趋势"
|
||
market_type := "强趋势"
|
||
else if (ma200_strength == "中" or ma200_strength == "弱") and price_above_ma200
|
||
trend_signal := "弱多头趋势"
|
||
market_type := "弱趋势"
|
||
else
|
||
trend_signal := "多头整理"
|
||
market_type := "整理"
|
||
else if ma200_trend_direction == "下降"
|
||
if ma200_strength == "强" and price_below_ma200 and (rsi_bearish or rsi_oversold)
|
||
trend_signal := "强空头趋势"
|
||
market_type := "强趋势"
|
||
else if (ma200_strength == "中" or ma200_strength == "弱") and price_below_ma200
|
||
trend_signal := "弱空头趋势"
|
||
market_type := "弱趋势"
|
||
else
|
||
trend_signal := "空头整理"
|
||
market_type := "整理"
|
||
else // 横盘
|
||
trend_signal := "横盘整理"
|
||
market_type := "整理"
|
||
|
||
// 在图表上显示趋势判断
|
||
if barstate.islast and show_info_table
|
||
// 创建趋势判断表格
|
||
var table trend_table = table.new(
|
||
position = position.top_left,
|
||
columns = 2,
|
||
rows = 4,
|
||
bgcolor = color.new(color.green, 80),
|
||
border_width = 2)
|
||
|
||
// 清空表格
|
||
table.clear(trend_table, 0, 0, 1, 3)
|
||
|
||
// 添加趋势标题
|
||
table.cell(trend_table, 0, 0, "市场分析", text_color=color.white, bgcolor=color.new(color.purple, 50), text_size=size.normal)
|
||
table.cell(trend_table, 1, 0, "判断结果", text_color=color.white, bgcolor=color.new(color.purple, 50), text_size=size.normal)
|
||
|
||
// 趋势方向
|
||
trend_color = trend_signal == "多头趋势" ? color.green : trend_signal == "空头趋势" ? color.red : color.orange
|
||
table.cell(trend_table, 0, 1, "趋势方向", text_color=color.black, text_size=size.small)
|
||
table.cell(trend_table, 1, 1, trend_signal, text_color=color.white, bgcolor=trend_color, text_size=size.small)
|
||
|
||
// 市场类型
|
||
table.cell(trend_table, 0, 2, "市场类型", text_color=color.black, text_size=size.small)
|
||
table.cell(trend_table, 1, 2, market_type, text_color=color.black, text_size=size.small)
|
||
|
||
// MA200趋势
|
||
table.cell(trend_table, 0, 3, "MA200趋势", text_color=color.black, text_size=size.small)
|
||
table.cell(trend_table, 1, 3, ma200_trend_direction, text_color=color.black, text_size=size.small)
|
||
|
||
//************************************************************************************************************
|
||
// RSI 分段线显示(已禁用 - 使用独立的RSI窗口)
|
||
//************************************************************************************************************
|
||
|
||
// 注释:由于使用了独立的RSI窗口2.c,这里不再绘制RSI相关的线条和标签
|
||
// 避免在主图表K线0附近出现橙黄色横条
|
||
|
||
// RSI 状态变化时绘制分段线(已禁用)
|
||
var int prev_rsi_state = 0
|
||
|
||
// 禁用RSI分段线绘制,因为有独立的RSI窗口
|
||
if false // 原条件: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) // 超卖区内的重复进入
|
||
|
||
// 在RSI窗口绘制垂直分段线(已禁用)
|
||
// line.new(bar_index, 0, bar_index, 100,
|
||
// color = segment_color,
|
||
// width = 2,
|
||
// style = line.style_solid,
|
||
// extend = extend.none)
|
||
|
||
// 显示计数标签(已禁用)
|
||
if current_state == 1 and segment_count > 0
|
||
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 and segment_count < 0
|
||
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
|
||
|
||
//************************************************************************************************************
|
||
// 价格格式化函数
|
||
//************************************************************************************************************
|
||
|
||
format_price(price) =>
|
||
str.tostring(price, '#.####')
|
||
|
||
//************************************************************************************************************
|
||
// 价格标签显示(参考MRC原始实现)
|
||
//************************************************************************************************************
|
||
|
||
// 声明标签变量
|
||
var label mean_label = na
|
||
var label res1_label = na
|
||
var label sup1_label = na
|
||
var label res2_label = na
|
||
var label sup2_label = na
|
||
var label lbl50 = na
|
||
var label lbl100 = na
|
||
var label lbl200 = na
|
||
|
||
if barstate.islast
|
||
// MEAN 标签(独立控制)
|
||
if show_mean_label
|
||
if na(mean_label)
|
||
mean_label := label.new(bar_index, meanline, "MEAN: " + format_price(meanline), xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.black, 0), textcolor=color.white)
|
||
else
|
||
label.set_xy(mean_label, bar_index, meanline)
|
||
label.set_text(mean_label, "MEAN: " + format_price(meanline))
|
||
|
||
// R1 标签(独立控制)
|
||
if show_r1_label
|
||
if na(res1_label)
|
||
res1_label := label.new(bar_index, upband1, "R1: " + format_price(upband1), xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.red, 0), textcolor=color.white)
|
||
else
|
||
label.set_xy(res1_label, bar_index, upband1)
|
||
label.set_text(res1_label, "R1: " + format_price(upband1))
|
||
|
||
// S1 标签(独立控制)
|
||
if show_s1_label
|
||
if na(sup1_label)
|
||
sup1_label := label.new(bar_index, loband1, "S1: " + format_price(loband1), xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.green, 0), textcolor=color.white)
|
||
else
|
||
label.set_xy(sup1_label, bar_index, loband1)
|
||
label.set_text(sup1_label, "S1: " + format_price(loband1))
|
||
|
||
// R2 标签(独立控制)
|
||
if show_r2_label
|
||
if na(res2_label)
|
||
res2_label := label.new(bar_index, upband2, "R2: " + format_price(upband2), xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.red, 50), textcolor=color.white)
|
||
else
|
||
label.set_xy(res2_label, bar_index, upband2)
|
||
label.set_text(res2_label, "R2: " + format_price(upband2))
|
||
|
||
// S2 标签(独立控制)
|
||
if show_s2_label
|
||
if na(sup2_label)
|
||
sup2_label := label.new(bar_index, loband2, "S2: " + format_price(loband2), xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.red, 50), textcolor=color.white)
|
||
else
|
||
label.set_xy(sup2_label, bar_index, loband2)
|
||
label.set_text(sup2_label, "S2: " + format_price(loband2))
|
||
|
||
// MA50 标签(独立控制)
|
||
if show_ma50_label
|
||
if na(lbl50)
|
||
lbl50 := label.new(x=time, y=ma50, text='MA50: ' + format_price(ma50), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=maColor(ma50, ma100), textcolor=color.white)
|
||
else
|
||
label.set_xy(lbl50, x=time, y=ma50)
|
||
label.set_text(lbl50, 'MA50: ' + format_price(ma50))
|
||
|
||
// MA100 标签(独立控制)
|
||
if show_ma100_label
|
||
if na(lbl100)
|
||
lbl100 := label.new(x=time, y=ma100, text='MA100: ' + format_price(ma100), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=maColor(ma100, ma200), textcolor=color.white)
|
||
else
|
||
label.set_xy(lbl100, x=time, y=ma100)
|
||
label.set_text(lbl100, 'MA100: ' + format_price(ma100))
|
||
|
||
// MA200 标签(独立控制,包含斜率变化信息)
|
||
if show_ma200_label
|
||
ma200_label_text = 'MA200: ' + format_price(ma200) + ' [' + ma200_trend_status + '] 距离:' + str.tostring(distance_usd, '#.##') + ' 变化:' + str.tostring(ma200_change_10, '#.##') + ' (' + trend_acceleration + ')'
|
||
if na(lbl200)
|
||
lbl200 := label.new(x=time, y=ma200, text=ma200_label_text, xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.blue, textcolor=color.white)
|
||
else
|
||
label.set_xy(lbl200, x=time, y=ma200)
|
||
label.set_text(lbl200, ma200_label_text)
|
||
|
||
//************************************************************************************************************
|
||
// 功能对比说明(注释)
|
||
//************************************************************************************************************
|
||
|
||
// ═════════ 原始功能保留对比 ═════════
|
||
//
|
||
// MRC 指标功能:
|
||
// ✓ SuperSmoother 和其他滤波器类型支持
|
||
// ✓ MEAN 线计算和显示
|
||
// ✓ R1/S1 通道计算和显示
|
||
// ✓ 价格标签显示
|
||
// ✓ 多时间框架支持(简化版)
|
||
// ✓ 所有原始参数设置
|
||
//
|
||
// MA200 指标功能:
|
||
// ✓ MA50/MA100/MA200 计算
|
||
// ✓ EMA/SMA 选择
|
||
// ✓ MA 线条颜色逻辑
|
||
// ✓ 价格标签显示
|
||
// ✓ 距离计算
|
||
// ✓ 斜率计算
|
||
//
|
||
// RSI 指标功能:
|
||
// ✓ 机器学习动态阈值
|
||
// ✓ RSI 平滑处理
|
||
// ✓ 多种移动平均类型
|
||
// ✓ 分段计数逻辑
|
||
// ✓ 穿越次数统计
|
||
// ✓ 状态变化检测
|
||
// ✓ 分段线颜色编码
|
||
//
|
||
// 新增综合功能:
|
||
// ✓ 三指标统一显示
|
||
// ✓ 实时数值表格
|
||
// ✓ 趋势综合判断
|
||
// ✓ 震荡/趋势识别
|
||
// ✓ 窗口一:K线+MRC+MA
|
||
// ✓ 窗口二:RSI独立显示
|
||
// ✓ 表格化数值显示 |