up
This commit is contained in:
307
MaxTrendPoints.pine
Normal file
307
MaxTrendPoints.pine
Normal file
@@ -0,0 +1,307 @@
|
||||
// This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
||||
// https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// © BigBeluga
|
||||
|
||||
//@version=6
|
||||
indicator("Max Trend Points [BigBeluga]", overlay = true, max_lines_count = 500, max_labels_count = 500)
|
||||
|
||||
// INPUTS ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
|
||||
var line_up = line(na)
|
||||
var line_dn = line(na)
|
||||
var lbl_up = label(na)
|
||||
var lbl_dn = label(na)
|
||||
|
||||
var highest = array.new_float(0)
|
||||
var lowest = array.new_float(0)
|
||||
|
||||
var int start = na
|
||||
var int last_trend_change = 0
|
||||
var float last_trend_price = 0.0
|
||||
|
||||
// Trend Factor Inputs
|
||||
factor_default = input.float(2.5, step = 0.1, title="默认趋势因子")
|
||||
factor_btc = input.float(3.0, step = 0.1, title="BTCUSD 趋势因子")
|
||||
factor_xau = input.float(2.5, step = 0.1, title="XAUUSD 趋势因子")
|
||||
factor_eth = input.float(2.8, step = 0.1, title="ETHUSD 趋势因子")
|
||||
factor_gbp = input.float(2.5, step = 0.1, title="GBPJPY 趋势因子")
|
||||
|
||||
// Consolidation Bars Inputs
|
||||
consolidation_bars_default = input.int(20, title="默认震荡检测周期", minval=10)
|
||||
consolidation_bars_btc = input.int(25, title="BTCUSD 震荡检测周期", minval=10)
|
||||
consolidation_bars_xau = input.int(25, title="XAUUSD 震荡检测周期", minval=10)
|
||||
consolidation_bars_eth = input.int(20, title="ETHUSD 震荡检测周期", minval=10)
|
||||
consolidation_bars_gbp = input.int(18, title="GBPJPY 震荡检测周期", minval=10)
|
||||
|
||||
// Consolidation Threshold Inputs
|
||||
consolidation_threshold_default = input.float(0.1, title="默认震荡阈值(%)", minval=0.1, step=0.02)
|
||||
consolidation_threshold_btc = input.float(0.2, title="BTCUSD 震荡阈值(%)", minval=0.1, step=0.02)
|
||||
consolidation_threshold_xau = input.float(0.3, title="XAUUSD 震荡阈值(%)", minval=0.1, step=0.02)
|
||||
consolidation_threshold_eth = input.float(0.15, title="ETHUSD 震荡阈值(%)", minval=0.1, step=0.02)
|
||||
consolidation_threshold_gbp = input.float(0.16, title="GBPJPY 震荡阈值(%)", minval=0.1, step=0.02)
|
||||
|
||||
// Activity Period Inputs
|
||||
activity_period_default = input.int(14, title="默认活跃度检测周期", minval=5)
|
||||
activity_period_btc = input.int(20, title="BTCUSD 活跃度检测周期", minval=5)
|
||||
activity_period_xau = input.int(20, title="XAUUSD 活跃度检测周期", minval=5)
|
||||
activity_period_eth = input.int(20, title="ETHUSD 活跃度检测周期", minval=5)
|
||||
activity_period_gbp = input.int(12, title="GBPJPY 活跃度检测周期", minval=5)
|
||||
|
||||
// Activity Threshold Inputs
|
||||
activity_threshold_default = input.float(1.3, title="默认活跃度阈值(ATR倍数)", minval=0.1, step=0.1)
|
||||
activity_threshold_btc = input.float(1.5, title="BTCUSD 活跃度阈值(ATR倍数)", minval=0.1, step=0.1)
|
||||
activity_threshold_xau = input.float(1.4, title="XAUUSD 活跃度阈值(ATR倍数)", minval=0.1, step=0.1)
|
||||
activity_threshold_eth = input.float(1.4, title="ETHUSD 活跃度阈值(ATR倍数)", minval=0.1, step=0.1)
|
||||
activity_threshold_gbp = input.float(1.3, title="GBPJPY 活跃度阈值(ATR倍数)", minval=0.1, step=0.1)
|
||||
|
||||
// Colors
|
||||
col_up = input.color(color.rgb(28, 194, 216), "上涨颜色")
|
||||
col_dn = input.color(color.rgb(228, 144, 19), "下跌颜色")
|
||||
|
||||
// Alert Settings
|
||||
alert_group = "警报设置"
|
||||
enable_trend_alert = input.bool(true, "启用趋势变化警报", group=alert_group)
|
||||
enable_consolidation_alert = input.bool(true, "启用震荡警报", group=alert_group)
|
||||
enable_activity_alert = input.bool(true, "启用市场活跃度警报", group=alert_group)
|
||||
|
||||
// Select Parameters Based on Trading Pair
|
||||
sym = syminfo.tickerid
|
||||
factor =
|
||||
sym == "TICKMILL:BTCUSD" ? factor_btc :
|
||||
sym == "TICKMILL:XAUUSD" ? factor_xau :
|
||||
sym == "TICKMILL:ETHUSD" ? factor_eth :
|
||||
sym == "TICKMILL:GBPJPY" ? factor_gbp :
|
||||
factor_default
|
||||
|
||||
consolidation_bars =
|
||||
sym == "TICKMILL:BTCUSD" ? consolidation_bars_btc :
|
||||
sym == "TICKMILL:XAUUSD" ? consolidation_bars_xau :
|
||||
sym == "TICKMILL:ETHUSD" ? consolidation_bars_eth :
|
||||
sym == "TICKMILL:GBPJPY" ? consolidation_bars_gbp :
|
||||
consolidation_bars_default
|
||||
|
||||
consolidation_threshold =
|
||||
sym == "TICKMILL:BTCUSD" ? consolidation_threshold_btc :
|
||||
sym == "TICKMILL:XAUUSD" ? consolidation_threshold_xau :
|
||||
sym == "TICKMILL:ETHUSD" ? consolidation_threshold_eth :
|
||||
sym == "TICKMILL:GBPJPY" ? consolidation_threshold_gbp :
|
||||
consolidation_threshold_default
|
||||
|
||||
activity_period =
|
||||
sym == "TICKMILL:BTCUSD" ? activity_period_btc :
|
||||
sym == "TICKMILL:XAUUSD" ? activity_period_xau :
|
||||
sym == "TICKMILL:ETHUSD" ? activity_period_eth :
|
||||
sym == "TICKMILL:GBPJPY" ? activity_period_gbp :
|
||||
activity_period_default
|
||||
|
||||
activity_threshold =
|
||||
sym == "TICKMILL:BTCUSD" ? activity_threshold_btc :
|
||||
sym == "TICKMILL:XAUUSD" ? activity_threshold_xau :
|
||||
sym == "TICKMILL:ETHUSD" ? activity_threshold_eth :
|
||||
sym == "TICKMILL:GBPJPY" ? activity_threshold_gbp :
|
||||
activity_threshold_default
|
||||
// }
|
||||
|
||||
// CALCULATIONS――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
|
||||
trend_line(factor)=>
|
||||
src = hl2
|
||||
dist = ta.hma(high-low, 200)
|
||||
upperBand = src + factor * dist
|
||||
lowerBand = src - factor * dist
|
||||
prevLowerBand = nz(lowerBand[1])
|
||||
prevUpperBand = nz(upperBand[1])
|
||||
|
||||
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
|
||||
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
|
||||
|
||||
int _direction = na
|
||||
float trend_line = na
|
||||
prevTrendLine = nz(trend_line[1])
|
||||
if na(dist[1])
|
||||
_direction := 1
|
||||
else if prevTrendLine == prevUpperBand
|
||||
_direction := close > upperBand ? -1 : 1
|
||||
else
|
||||
_direction := close < lowerBand ? 1 : -1
|
||||
|
||||
trend_line := _direction == -1 ? lowerBand : upperBand
|
||||
|
||||
[trend_line, _direction]
|
||||
|
||||
[trend_line, _direction] = trend_line(factor)
|
||||
|
||||
t_change = ta.cross(_direction, 0)
|
||||
|
||||
// Oscillation Detection
|
||||
highest_recent = ta.highest(high, consolidation_bars)
|
||||
lowest_recent = ta.lowest(low, consolidation_bars)
|
||||
price_range = (highest_recent - lowest_recent) / lowest_recent * 100
|
||||
is_consolidating = price_range < consolidation_threshold
|
||||
|
||||
// Market Activity Detection
|
||||
atr_current = ta.atr(activity_period)
|
||||
atr_avg = ta.sma(atr_current, activity_period * 2)
|
||||
is_active = atr_current > atr_avg * activity_threshold
|
||||
|
||||
// Calculate Trend Strength
|
||||
trend_strength = math.abs(close - trend_line) / trend_line * 100
|
||||
|
||||
if t_change
|
||||
array.clear(highest)
|
||||
array.clear(lowest)
|
||||
start := bar_index
|
||||
last_trend_change := bar_index
|
||||
last_trend_price := close
|
||||
|
||||
if t_change and _direction == 1
|
||||
line_dn := line.new(bar_index, close, na, na, color = chart.fg_color, style = line.style_dashed)
|
||||
lbl_dn := label.new(bar_index, low, color = color.new(col_dn, 50), textcolor = chart.fg_color, size = size.small, style = label.style_label_up)
|
||||
|
||||
if t_change and _direction == -1
|
||||
lbl_up := label.new(bar_index, high, color = color.new(col_up, 50), textcolor = chart.fg_color, size = size.small, style = label.style_label_down)
|
||||
line_up := line.new(bar_index, close, na, na, color = chart.fg_color, style = line.style_dashed)
|
||||
|
||||
if not t_change and _direction == -1
|
||||
array.push(highest, high)
|
||||
label.set_xy(lbl_up, start + array.indexof(highest, array.max(highest))+1, array.max(highest))
|
||||
line.set_xy2(line_up, start + array.indexof(highest, array.max(highest))+1, array.max(highest))
|
||||
|
||||
if not t_change and _direction == 1
|
||||
array.push(lowest, low)
|
||||
label.set_xy(lbl_dn, start + array.indexof(lowest, array.min(lowest))+1, array.min(lowest))
|
||||
line.set_xy2(line_dn, start + array.indexof(lowest, array.min(lowest))+1, array.min(lowest))
|
||||
|
||||
if line.get_y2(line_up) > line.get_y1(line_up)
|
||||
label.set_text(lbl_up, str.tostring((line.get_y2(line_up) - line.get_y1(line_up)) / line.get_y1(line_up) * 100, format.percent))
|
||||
if line.get_y2(line_dn) < line.get_y1(line_dn)
|
||||
label.set_text(lbl_dn, str.tostring((line.get_y2(line_dn) - line.get_y1(line_dn)) / line.get_y1(line_dn) * 100, format.percent))
|
||||
|
||||
t_color = _direction == -1 ? col_up : col_dn
|
||||
|
||||
// Track previous states for state change detection
|
||||
var bool was_consolidating = false
|
||||
var bool was_active = false
|
||||
was_consolidating := is_consolidating
|
||||
was_active := is_active
|
||||
// }
|
||||
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 趋势变化警报
|
||||
if enable_trend_alert and t_change and _direction == -1
|
||||
alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格转为上涨趋势","方向":"上涨趋势","信号":"trend_up"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
if enable_trend_alert and t_change and _direction == 1
|
||||
alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格转为下跌趋势","方向":"下跌趋势","信号":"trend_down"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// 震荡状态变化警报
|
||||
// if enable_consolidation_alert and is_consolidating and not was_consolidating[1]
|
||||
// alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"市场进入震荡状态","状态":"震荡","信号":"consolidation_start"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if enable_consolidation_alert and not is_consolidating and was_consolidating[1]
|
||||
// direction_text = _direction == -1 ? "上涨趋势" : "下跌趋势"
|
||||
// alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"市场突破震荡状态","方向":"' + direction_text + '","信号":"consolidation_break"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// // 活跃度变化警报
|
||||
// if enable_activity_alert and is_active and not was_active[1]
|
||||
// alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"市场活跃度增加","活跃状态":"活跃","信号":"activity_increase"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if enable_activity_alert and not is_active and was_active[1]
|
||||
// alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"市场活跃度降低","活跃状态":"不活跃","信号":"activity_decrease"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// 综合市场分析警报
|
||||
// if t_change and (enable_trend_alert or enable_consolidation_alert or enable_activity_alert)
|
||||
// direction_text = _direction == -1 ? "上涨趋势" : "下跌趋势"
|
||||
// status_text = is_consolidating ? "震荡" : (is_active ? "活跃" : "正常")
|
||||
// alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"综合市场分析","方向":"' + direction_text + '","状态":"' + status_text + '","信号":"market_analysis"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// 状态监控警报(频率较低)
|
||||
if enable_trend_alert and _direction == -1
|
||||
alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于上涨趋势","方向":"上涨趋势","信号":"trend_up_status"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
if enable_trend_alert and _direction == 1
|
||||
alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于下跌趋势","方向":"下跌趋势","信号":"trend_down_status"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
if enable_consolidation_alert and is_consolidating
|
||||
alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于震荡状态","状态":"震荡","信号":"consolidation_status"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
if enable_activity_alert and is_active
|
||||
alert_message := '{"指标名称":"MaxTrendPoints","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","趋势线":"' + str.tostring(trend_line, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.##') + '","价格范围":"' + str.tostring(price_range, '#.####') + '","当前ATR":"' + str.tostring(atr_current, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于活跃状态","活跃状态":"活跃","信号":"activity_status"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(trend_line, title = '趋势线', display = display.none)
|
||||
plot(trend_strength, title = '趋势强度', display = display.none)
|
||||
plot(price_range, title = '价格范围', display = display.none)
|
||||
plot(atr_current, title = '当前ATR', display = display.none)
|
||||
|
||||
// 趋势变化警报
|
||||
alertcondition(enable_trend_alert and t_change and _direction == -1, title = '价格转为上涨趋势', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格转为上涨趋势","方向":"上涨趋势","信号":"trend_up"}')
|
||||
|
||||
alertcondition(enable_trend_alert and t_change and _direction == 1, title = '价格转为下跌趋势', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格转为下跌趋势","方向":"下跌趋势","信号":"trend_down"}')
|
||||
|
||||
// 震荡状态变化警报
|
||||
alertcondition(enable_consolidation_alert and is_consolidating and not was_consolidating[1], title = '市场进入震荡状态', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"市场进入震荡状态","状态":"震荡","信号":"consolidation_start"}')
|
||||
|
||||
alertcondition(enable_consolidation_alert and not is_consolidating and was_consolidating[1], title = '市场突破震荡状态', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"市场突破震荡状态","信号":"consolidation_break"}')
|
||||
|
||||
// 活跃度变化警报
|
||||
alertcondition(enable_activity_alert and is_active and not was_active[1], title = '市场活跃度增加', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"市场活跃度增加","活跃状态":"活跃","信号":"activity_increase"}')
|
||||
|
||||
alertcondition(enable_activity_alert and not is_active and was_active[1], title = '市场活跃度降低', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"市场活跃度降低","活跃状态":"不活跃","信号":"activity_decrease"}')
|
||||
|
||||
// 综合市场分析警报
|
||||
alertcondition(t_change and (enable_trend_alert or enable_consolidation_alert or enable_activity_alert), title = '综合市场分析', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"综合市场分析","信号":"market_analysis"}')
|
||||
|
||||
// 状态监控警报
|
||||
alertcondition(enable_trend_alert and _direction == -1, title = '价格处于上涨趋势', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于上涨趋势","方向":"上涨趋势","信号":"trend_up_status"}')
|
||||
|
||||
alertcondition(enable_trend_alert and _direction == 1, title = '价格处于下跌趋势', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于下跌趋势","方向":"下跌趋势","信号":"trend_down_status"}')
|
||||
|
||||
alertcondition(enable_consolidation_alert and is_consolidating, title = '价格处于震荡状态', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于震荡状态","状态":"震荡","信号":"consolidation_status"}')
|
||||
|
||||
alertcondition(enable_activity_alert and is_active, title = '价格处于活跃状态', message = '{"指标名称":"MaxTrendPoints","交易对":"{{ticker}}","周期":"{{interval}}","趋势线":"{{plot("趋势线")}}","趋势强度":"{{plot("趋势强度")}}","价格范围":"{{plot("价格范围")}}","当前ATR":"{{plot("当前ATR")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于活跃状态","活跃状态":"活跃","信号":"activity_status"}')
|
||||
|
||||
// PLOT ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――{
|
||||
plotshape(t_change ? trend_line : na, "趋势变化", style = shape.circle, location = location.absolute, color = t_color, size = size.tiny)
|
||||
|
||||
t_p = plot(trend_line, "趋势线", color = t_change ? color.new(t_color, 100) : t_color, linewidth = 2)
|
||||
m_p = plot(hl2, color = color.new(color.gray, 100), editable = false)
|
||||
|
||||
fill(t_p, m_p, hl2, trend_line, color.new(t_color, 95), color.new(t_color, 90))
|
||||
|
||||
// Status Panel
|
||||
var table panel = table.new(position.top_right, 3, 4, bgcolor=color.new(color.black, 80))
|
||||
if barstate.islast
|
||||
table.cell(panel, 0, 0, "市场状态", text_color=color.white, text_size=size.small)
|
||||
table.cell(panel, 1, 0, "当前值", text_color=color.white, text_size=size.small)
|
||||
|
||||
table.cell(panel, 0, 1, "趋势方向", text_color=color.gray, text_size=size.small)
|
||||
table.cell(panel, 1, 1, _direction == -1 ? "↑ 上涨" : "↓ 下跌",
|
||||
text_color=_direction == -1 ? col_up : col_dn, text_size=size.small)
|
||||
|
||||
table.cell(panel, 0, 2, "市场状态", text_color=color.gray, text_size=size.small)
|
||||
table.cell(panel, 1, 2, is_consolidating ? "震荡中" : "趋势中",
|
||||
text_color=is_consolidating ? color.rgb(43, 43, 39) : color.green, text_size=size.small)
|
||||
|
||||
table.cell(panel, 0, 3, "活跃度", text_color=color.gray, text_size=size.small)
|
||||
table.cell(panel, 1, 3, is_active ? "活跃" : "平静",
|
||||
text_color=is_active ? color.rgb(60, 60, 60) : color.blue, text_size=size.small)
|
||||
// }
|
||||
399
Swing Failure Pattern.pine
Normal file
399
Swing Failure Pattern.pine
Normal file
@@ -0,0 +1,399 @@
|
||||
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// © LuxAlgo
|
||||
|
||||
//@version=5
|
||||
indicator( 'SwingFailurePattern [LuxAlgo]', 'LuxAlgo - Swing Failure Pattern', max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500, overlay = true)
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Settings
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
sp = ' '
|
||||
len = input.int ( 5 , 'Swings' , minval= 1 )
|
||||
bull = input.bool ( true , 'Bullish SFP' )
|
||||
bear = input.bool ( true , 'Bearish SFP' )
|
||||
|
||||
iVal = input.string ('None', 'Validation'+sp+ ' ', group='Volume Validation'
|
||||
, options = ['Volume outside swing < Threshold' ,'Volume outside swing > Threshold','None'])
|
||||
percent = input.float (25, 'Volume Threshold %' , inline='valy', group='Volume Validation'
|
||||
, tooltip = '% of Total Volume' , minval= 0 , maxval=100 )
|
||||
auto = input.bool (true, '' , inline='auto', group='Volume Validation' )
|
||||
mlt = input.int (50 , ' Auto' + sp , inline='auto', group='Volume Validation' )
|
||||
res = input.timeframe('1' , sp +' LTF' + sp +' ', inline='ltf' , group='Volume Validation' )
|
||||
prem = input.bool (false ,' Premium' , group='Volume Validation'
|
||||
, tooltip = 'Premium Plan or higher' )
|
||||
showDash = input.bool (true , 'Show Dashboard' , group= 'Dashboard' )
|
||||
dashLoc = input.string ( 'Top Right' , 'Location'
|
||||
, options = ['Top Right', 'Bottom Right', 'Bottom Left'] , group= 'Dashboard' )
|
||||
textSize = input.string ( 'Normal' , 'Size'
|
||||
, options = ['Tiny', 'Small', 'Normal'] , group= 'Dashboard' )
|
||||
dSwingLine = input.bool (true , 'Swing Lines' , group= 'Style' )
|
||||
dOpposLine = input.bool (true , 'Confirmation Lines' , group= 'Style' )
|
||||
dSFP_Line = input.bool (true , 'Swing Failure Wick' , group= 'Style' )
|
||||
dSFP_Label = input.bool (true , 'Swing Failure Label' , group= 'Style' )
|
||||
showAlerts = input.bool (true , 'Show Alert Markers' , group= 'Style' )
|
||||
alertSize = input.string ('Normal', 'Alert Marker Size' , group= 'Style'
|
||||
, options = ['Small', 'Normal', 'Large'] )
|
||||
colBl = input.color (#089981 , 'Lines / Labels' , inline='lin' , group= 'Style' )
|
||||
colBr = input.color (#f23645 , '' , inline='lin' , group= 'Style'
|
||||
, tooltip = 'Bullish/Bearish' )
|
||||
colBl2 = input.color (#08998180, 'SFP Wicks ', inline='wic' , group= 'Style' )
|
||||
colBr2 = input.color (#f2364580, '' , inline='wic' , group= 'Style'
|
||||
, tooltip = 'Wick outside Swing, Bullish/Bearish' )
|
||||
|
||||
//-----------------------------------------------------------------------------}
|
||||
//UDT
|
||||
//-----------------------------------------------------------------------------{
|
||||
type piv
|
||||
float swing_prc // price
|
||||
int swing_bix // bar_index
|
||||
float oppos_prc // price
|
||||
int oppos_bix // bar_index
|
||||
bool active
|
||||
bool confirmed
|
||||
line swing_line
|
||||
line oppos_line
|
||||
line wicky_line
|
||||
label wicky_label
|
||||
|
||||
type swing
|
||||
int bix
|
||||
float prc
|
||||
|
||||
//-----------------------------------------------------------------------------}
|
||||
//Variables
|
||||
//-----------------------------------------------------------------------------{
|
||||
n = bar_index
|
||||
INV = color(na)
|
||||
FGc = chart.fg_color
|
||||
|
||||
table_position = dashLoc == 'Bottom Left' ? position.bottom_left
|
||||
: dashLoc == 'Top Right' ? position.top_right
|
||||
: position.bottom_right
|
||||
|
||||
table_size = textSize == 'Tiny' ? size.tiny
|
||||
: textSize == 'Small' ? size.small
|
||||
: size.normal
|
||||
|
||||
alert_marker_size = alertSize == 'Small' ? size.small
|
||||
: alertSize == 'Large' ? size.large
|
||||
: size.normal
|
||||
|
||||
var tb = table.new(table_position, 2, 3
|
||||
, bgcolor = #1e222d
|
||||
, border_color = #373a46
|
||||
, border_width = 1
|
||||
, frame_color = #373a46
|
||||
, frame_width = 1)
|
||||
|
||||
var swing swingH = swing.new()
|
||||
var swing swingL = swing.new()
|
||||
var piv pivH = piv.new()
|
||||
var piv pivL = piv.new()
|
||||
|
||||
validate = iVal != 'None'
|
||||
valHigher= iVal == 'Volume outside swing > Threshold'
|
||||
valLower = iVal == 'Volume outside swing < Threshold'
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Method
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
method n(float piv) => bool out = not na(piv)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Execution
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
tfS = timeframe.in_seconds( res )
|
||||
tfC = timeframe.in_seconds(timeframe.period)
|
||||
rs = auto ? tfC / mlt : tfS
|
||||
if not validate
|
||||
res := timeframe.period
|
||||
else
|
||||
rs := prem ? rs : math.max(60, rs)
|
||||
res := timeframe.from_seconds(math.min(tfC, rs))
|
||||
|
||||
ph = ta.pivothigh(len, 1)
|
||||
pl = ta.pivotlow (len, 1)
|
||||
|
||||
[ltf_close, ltf_volume] = request.security_lower_tf(syminfo.tickerid, res, [close, volume])
|
||||
|
||||
ltf_size = ltf_close.size()
|
||||
|
||||
if validate
|
||||
if ltf_size > 0 and ltf_size[1] == 0
|
||||
line.new(n, close, n, close + syminfo.mintick, color=color.silver, style=line.style_dotted, extend=extend.both)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Bearish Pattern
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
if bear
|
||||
|
||||
if ph.n()
|
||||
swingH.bix := n-1
|
||||
swingH.prc := ph
|
||||
|
||||
sw = swingH.prc
|
||||
bx = swingH.bix
|
||||
if high > sw
|
||||
and open < sw
|
||||
and close < sw
|
||||
valid = true
|
||||
if validate
|
||||
if ltf_close.size() > 0
|
||||
outsideVolume = 0.
|
||||
totalVolume = ltf_volume.sum()
|
||||
for j = 0 to ltf_close.size() -1
|
||||
if ltf_close.get(j) > sw
|
||||
outsideVolume += ltf_volume.get(j)
|
||||
if (valHigher ? 100 / totalVolume * outsideVolume < percent
|
||||
: 100 / totalVolume * outsideVolume > percent
|
||||
)
|
||||
valid := false
|
||||
|
||||
//if valid
|
||||
// label.new(n, high, text=str.format("Total Volume: {0}\nWick Volume: {1}", totalVolume, outsideVolume))
|
||||
|
||||
if valid
|
||||
|
||||
opposL = sw
|
||||
opposB = n
|
||||
|
||||
for i = 1 to n - bx -1
|
||||
if low [i] < opposL
|
||||
opposL := low [i]
|
||||
opposB := n - i
|
||||
|
||||
if not pivH.confirmed
|
||||
pivH.swing_line .delete()
|
||||
pivH.oppos_line .delete()
|
||||
pivH.wicky_line .delete()
|
||||
pivH.wicky_label.delete()
|
||||
|
||||
pivH := piv.new(sw, bx, opposL, opposB, true, false)
|
||||
|
||||
if dSwingLine
|
||||
pivH.swing_line := line.new (bx , sw , n, sw , color=colBr)
|
||||
if dOpposLine
|
||||
pivH.oppos_line := line.new (opposB, opposL, n, opposL, color=colBr, style=line.style_dotted)
|
||||
if dSFP_Line
|
||||
pivH.wicky_line := line.new (n , high , n, sw , color=colBr2, width=3)
|
||||
if dSFP_Label
|
||||
pivH.wicky_label := label.new(n , high
|
||||
, style=label.style_label_down
|
||||
, text='SFP', textcolor=colBr
|
||||
, color=INV, size=size.normal
|
||||
)
|
||||
|
||||
if pivH.active and not pivH.confirmed
|
||||
|
||||
pivH.swing_line.set_x2(n)
|
||||
pivH.oppos_line.set_x2(n)
|
||||
|
||||
if close < pivH.oppos_prc
|
||||
pivH.confirmed := true
|
||||
|
||||
if pivH.wicky_label.get_x() == n
|
||||
pivH.wicky_label.set_text('SFP\n▼')
|
||||
else
|
||||
label.new(n, high, style=label.style_label_down, text='▼', textcolor=colBr, color=INV, size=size.normal)
|
||||
|
||||
if n - pivH.swing_bix > 500
|
||||
or close > pivH.swing_prc
|
||||
pivH.active := false
|
||||
if not pivH.confirmed
|
||||
pivH.swing_line .delete()
|
||||
pivH.oppos_line .delete()
|
||||
pivH.wicky_line .delete()
|
||||
pivH.wicky_label.delete()
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Bullish Pattern
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
if bull
|
||||
|
||||
if pl.n()
|
||||
swingL.bix := n-1
|
||||
swingL.prc := pl
|
||||
|
||||
sw = swingL.prc
|
||||
bx = swingL.bix
|
||||
if low < sw
|
||||
and open > sw
|
||||
and close > sw
|
||||
valid = true
|
||||
if validate
|
||||
if ltf_close.size() > 0
|
||||
outsideVolume = 0.
|
||||
totalVolume = ltf_volume.sum()
|
||||
for j = 0 to ltf_close.size() -1
|
||||
if ltf_close.get(j) < sw
|
||||
outsideVolume += ltf_volume.get(j)
|
||||
if (valHigher ? 100 / totalVolume * outsideVolume < percent
|
||||
: 100 / totalVolume * outsideVolume > percent
|
||||
)
|
||||
valid := false
|
||||
if valid
|
||||
|
||||
opposH = sw
|
||||
opposB = n
|
||||
|
||||
for i = 1 to n - bx -1
|
||||
if high[i] > opposH
|
||||
opposH := high[i]
|
||||
opposB := n - i
|
||||
|
||||
if not pivL.confirmed
|
||||
pivL.swing_line .delete()
|
||||
pivL.oppos_line .delete()
|
||||
pivL.wicky_line .delete()
|
||||
pivL.wicky_label.delete()
|
||||
|
||||
pivL := piv.new(sw, bx, opposH, opposB, true, false)
|
||||
|
||||
if dSwingLine
|
||||
pivL.swing_line := line.new (bx , sw , n, sw , color=colBl )
|
||||
if dOpposLine
|
||||
pivL.oppos_line := line.new (opposB, opposH, n, opposH, color=colBl , style=line.style_dotted)
|
||||
if dSFP_Line
|
||||
pivL.wicky_line := line.new (n , low , n, sw , color=colBl2, width=3)
|
||||
if dSFP_Label
|
||||
pivL.wicky_label := label.new(n , low
|
||||
, style=label.style_label_up
|
||||
, text='SFP', textcolor=colBl
|
||||
, color=INV, size=size.normal
|
||||
)
|
||||
|
||||
if pivL.active and not pivL.confirmed
|
||||
|
||||
pivL.swing_line.set_x2(n)
|
||||
pivL.oppos_line.set_x2(n)
|
||||
|
||||
if close > pivL.oppos_prc
|
||||
pivL.confirmed := true
|
||||
|
||||
if pivL.wicky_label.get_x() == n
|
||||
pivL.wicky_label.set_text('▲\nSFP')
|
||||
else
|
||||
label.new(n, low, style=label.style_label_up, text='▲', textcolor=colBl, color=INV, size=size.normal)
|
||||
|
||||
if n - pivL.swing_bix > 500
|
||||
or close < pivL.swing_prc
|
||||
pivL.active := false
|
||||
if not pivL.confirmed
|
||||
pivL.swing_line .delete()
|
||||
pivL.oppos_line .delete()
|
||||
pivL.wicky_line .delete()
|
||||
pivL.wicky_label.delete()
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Dashboard
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
if barstate.islast and validate and showDash
|
||||
tb.cell(0, 0, str.format("LTF: {0}", res), text_color=color.white, text_size=table_size)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Alert System
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_bearish_sfp = 0
|
||||
var int last_alert_bullish_sfp = 0
|
||||
var int last_alert_bearish_sfp_confirmed = 0
|
||||
var int last_alert_bullish_sfp_confirmed = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 看跌SFP信号检测 - 每分钟限制
|
||||
bearish_sfp_signal = bear and high > swingH.prc and open < swingH.prc and close < swingH.prc and not pivH.confirmed
|
||||
if bearish_sfp_signal and current_minute > last_alert_bearish_sfp
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动高点":"' + str.tostring(swingH.prc, '#.####') + '","事件":"看跌摆动失败模式触发","信号":"bearish_sfp","备注":"突破高点后看跌回落"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bearish_sfp := current_minute
|
||||
|
||||
// 在K线上绘制看跌SFP信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, high + (high - low) * 0.1,
|
||||
text='🔻SFP',
|
||||
style=label.style_label_down,
|
||||
color=color.new(color.red, 20),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='突破高点后看跌回落\n摆动高点: ' + str.tostring(swingH.prc, '#.####'))
|
||||
|
||||
// 看涨SFP信号检测 - 每分钟限制
|
||||
bullish_sfp_signal = bull and low < swingL.prc and open > swingL.prc and close > swingL.prc and not pivL.confirmed
|
||||
if bullish_sfp_signal and current_minute > last_alert_bullish_sfp
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动低点":"' + str.tostring(swingL.prc, '#.####') + '","事件":"看涨摆动失败模式触发","信号":"bullish_sfp","备注":"跌破低点后看涨反弹"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bullish_sfp := current_minute
|
||||
|
||||
// 在K线上绘制看涨SFP信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, low - (high - low) * 0.1,
|
||||
text='🔺SFP',
|
||||
style=label.style_label_up,
|
||||
color=color.new(color.green, 20),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='跌破低点后看涨反弹\n摆动低点: ' + str.tostring(swingL.prc, '#.####'))
|
||||
|
||||
// 看跌SFP确认信号 - 每分钟限制
|
||||
bearish_sfp_confirmed = pivH.active and not pivH.confirmed[1] and pivH.confirmed and close < pivH.oppos_prc
|
||||
if bearish_sfp_confirmed and current_minute > last_alert_bearish_sfp_confirmed
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动高点":"' + str.tostring(pivH.swing_prc, '#.####') + '","对立价格":"' + str.tostring(pivH.oppos_prc, '#.####') + '","事件":"看跌摆动失败模式确认","信号":"bearish_sfp_confirmed","备注":"跌破对立低点确认看跌"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bearish_sfp_confirmed := current_minute
|
||||
|
||||
// 在K线上绘制看跌SFP确认信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, high + (high - low) * 0.15,
|
||||
text='✅🔻',
|
||||
style=label.style_label_down,
|
||||
color=color.new(color.maroon, 10),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='跌破对立低点确认看跌\n摆动高点: ' + str.tostring(pivH.swing_prc, '#.####') + '\n对立价格: ' + str.tostring(pivH.oppos_prc, '#.####'))
|
||||
|
||||
// 看涨SFP确认信号 - 每分钟限制
|
||||
bullish_sfp_confirmed = pivL.active and not pivL.confirmed[1] and pivL.confirmed and close > pivL.oppos_prc
|
||||
if bullish_sfp_confirmed and current_minute > last_alert_bullish_sfp_confirmed
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动低点":"' + str.tostring(pivL.swing_prc, '#.####') + '","对立价格":"' + str.tostring(pivL.oppos_prc, '#.####') + '","事件":"看涨摆动失败模式确认","信号":"bullish_sfp_confirmed","备注":"突破对立高点确认看涨"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bullish_sfp_confirmed := current_minute
|
||||
|
||||
// 在K线上绘制看涨SFP确认信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, low - (high - low) * 0.15,
|
||||
text='✅🔺',
|
||||
style=label.style_label_up,
|
||||
color=color.new(color.teal, 10),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='突破对立高点确认看涨\n摆动低点: ' + str.tostring(pivL.swing_prc, '#.####') + '\n对立价格: ' + str.tostring(pivL.oppos_prc, '#.####'))
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(swingH.prc, title = '摆动高点', display = display.none)
|
||||
plot(swingL.prc, title = '摆动低点', display = display.none)
|
||||
plot(pivH.oppos_prc, title = '看跌对立价格', display = display.none)
|
||||
plot(pivL.oppos_prc, title = '看涨对立价格', display = display.none)
|
||||
|
||||
// SFP信号警报
|
||||
alertcondition(bearish_sfp_signal, title = '看跌摆动失败模式', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动高点":"{{plot("摆动高点")}}","事件":"看跌摆动失败模式触发","信号":"bearish_sfp","备注":"突破高点后看跌回落"}')
|
||||
|
||||
alertcondition(bullish_sfp_signal, title = '看涨摆动失败模式', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动低点":"{{plot("摆动低点")}}","事件":"看涨摆动失败模式触发","信号":"bullish_sfp","备注":"跌破低点后看涨反弹"}')
|
||||
|
||||
// SFP确认信号警报
|
||||
alertcondition(bearish_sfp_confirmed, title = '看跌摆动失败模式确认', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动高点":"{{plot("摆动高点")}}","对立价格":"{{plot("看跌对立价格")}}","事件":"看跌摆动失败模式确认","信号":"bearish_sfp_confirmed","备注":"跌破对立低点确认看跌"}')
|
||||
|
||||
alertcondition(bullish_sfp_confirmed, title = '看涨摆动失败模式确认', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动低点":"{{plot("摆动低点")}}","对立价格":"{{plot("看涨对立价格")}}","事件":"看涨摆动失败模式确认","信号":"bullish_sfp_confirmed","备注":"突破对立高点确认看涨"}')
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
844
mrc copy.pine
Normal file
844
mrc copy.pine
Normal file
@@ -0,0 +1,844 @@
|
||||
//@version=6
|
||||
indicator('Mean Reversion Channel - 带价格标签 -ma200', shorttitle = 'MRC2ma200', overlay = true, format = format.inherit)
|
||||
|
||||
//************************************************************************************************************
|
||||
// Parameter
|
||||
//************************************************************************************************************
|
||||
|
||||
indiSet = input(false, '═════════ MRC Parameter ════════')
|
||||
source = input(hlc3, title = 'Price Source')
|
||||
type = input.string('SuperSmoother', title = 'Filter Type', options = ['SuperSmoother', 'Ehlers EMA', 'Gaussian', 'Butterworth', 'BandStop', 'SMA', 'EMA', 'RMA'])
|
||||
length = input.int(200, title = 'Lookback Period', minval = 1)
|
||||
innermult = input.float(1.0, title = 'Inner Channel Size Multiplier', minval = 0.1)
|
||||
outermult = input.float(2.415, title = 'Outer Channel Size Multiplier', minval = 0.1)
|
||||
|
||||
// ————————————— MA200 参数 —————————————
|
||||
maSet = input(false, '═════════ MA200 Parameter ════════')
|
||||
exponential = input.bool(true, title='使用指数移动平均线 (EMA)')
|
||||
show_ma_lines = input.bool(true, title='显示MA线条')
|
||||
show_ma_labels = input.bool(true, title='显示MA价格标签')
|
||||
|
||||
ChartSet = input(false, '═════════ Chart Setting ════════')
|
||||
drawchannel = input(true, title = 'Draw Channel')
|
||||
displayzone = input(true, title = 'Draw Zone (With Channel)')
|
||||
zonetransp = input.int(60, title = 'Zone Transparency', minval = 0, maxval = 100)
|
||||
displayline = input(true, title = 'Display Line Extension')
|
||||
|
||||
MTFSet = input(false, '═════════ MTF Setting ════════')
|
||||
enable_mtf = input(true, title = 'Enable Multiple TimeFrame Analysis')
|
||||
mtf_disp_typ = input.string('On Hover', title = 'MTF Display Type', options = ['Always Display', 'On Hover'])
|
||||
mtf_typ = input.string('Auto', title = 'Multiple TimeFrame Type', options = ['Auto', 'Custom'])
|
||||
mtf_lvl1 = input.timeframe('D', title = 'Custom MTF Level 1')
|
||||
mtf_lvl2 = input.timeframe('W', title = 'Custom MTF Level 2')
|
||||
|
||||
//************************************************************************************************************
|
||||
// Functions Start {
|
||||
//************************************************************************************************************
|
||||
var pi = 2 * math.asin(1)
|
||||
var mult = pi * innermult
|
||||
var mult2 = pi * outermult
|
||||
var gradsize = 0.5
|
||||
var gradtransp = zonetransp
|
||||
|
||||
//-----------------------
|
||||
// Ehler SwissArmyKnife Function
|
||||
//-----------------------
|
||||
SAK_smoothing(_type, _src, _length) =>
|
||||
c0 = 1.0
|
||||
c1 = 0.0
|
||||
b0 = 1.0
|
||||
b1 = 0.0
|
||||
b2 = 0.0
|
||||
a1 = 0.0
|
||||
a2 = 0.0
|
||||
alpha = 0.0
|
||||
beta = 0.0
|
||||
gamma = 0.0
|
||||
cycle = 2 * pi / _length
|
||||
|
||||
if _type == 'Ehlers EMA'
|
||||
alpha := (math.cos(cycle) + math.sin(cycle) - 1) / math.cos(cycle)
|
||||
b0 := alpha
|
||||
a1 := 1 - alpha
|
||||
a1
|
||||
if _type == 'Gaussian'
|
||||
beta := 2.415 * (1 - math.cos(cycle))
|
||||
alpha := -beta + math.sqrt(beta * beta + 2 * beta)
|
||||
c0 := alpha * alpha
|
||||
a1 := 2 * (1 - alpha)
|
||||
a2 := -(1 - alpha) * (1 - alpha)
|
||||
a2
|
||||
if _type == 'Butterworth'
|
||||
beta := 2.415 * (1 - math.cos(cycle))
|
||||
alpha := -beta + math.sqrt(beta * beta + 2 * beta)
|
||||
c0 := alpha * alpha / 4
|
||||
b1 := 2
|
||||
b2 := 1
|
||||
a1 := 2 * (1 - alpha)
|
||||
a2 := -(1 - alpha) * (1 - alpha)
|
||||
a2
|
||||
if _type == 'BandStop'
|
||||
beta := math.cos(cycle)
|
||||
gamma := 1 / math.cos(cycle * 2 * 0.1) // delta default to 0.1. Acceptable delta -- 0.05<d<0.5
|
||||
alpha := gamma - math.sqrt(gamma * gamma - 1)
|
||||
c0 := (1 + alpha) / 2
|
||||
b1 := -2 * beta
|
||||
b2 := 1
|
||||
a1 := beta * (1 + alpha)
|
||||
a2 := -alpha
|
||||
a2
|
||||
if _type == 'SMA'
|
||||
c1 := 1 / _length
|
||||
b0 := 1 / _length
|
||||
a1 := 1
|
||||
a1
|
||||
if _type == 'EMA'
|
||||
alpha := 2 / (_length + 1)
|
||||
b0 := alpha
|
||||
a1 := 1 - alpha
|
||||
a1
|
||||
if _type == 'RMA'
|
||||
alpha := 1 / _length
|
||||
b0 := alpha
|
||||
a1 := 1 - alpha
|
||||
a1
|
||||
|
||||
_Input = _src
|
||||
_Output = 0.0
|
||||
_Output := c0 * (b0 * _Input + b1 * nz(_Input[1]) + b2 * nz(_Input[2])) + a1 * nz(_Output[1]) + a2 * nz(_Output[2]) - c1 * nz(_Input[_length])
|
||||
_Output
|
||||
|
||||
//-----------------------
|
||||
// SuperSmoother Function
|
||||
//-----------------------
|
||||
supersmoother(_src, _length) =>
|
||||
s_a1 = math.exp(-math.sqrt(2) * pi / _length)
|
||||
s_b1 = 2 * s_a1 * math.cos(math.sqrt(2) * pi / _length)
|
||||
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
|
||||
|
||||
//-----------------------
|
||||
// Auto TimeFrame Function
|
||||
//-----------------------
|
||||
// ————— Converts current chart resolution into a float minutes value.
|
||||
f_resInMinutes() =>
|
||||
_resInMinutes = timeframe.multiplier * (timeframe.isseconds ? 1. / 60 : timeframe.isminutes ? 1. : timeframe.isdaily ? 60. * 24 : timeframe.isweekly ? 60. * 24 * 7 : timeframe.ismonthly ? 60. * 24 * 30.4375 : na)
|
||||
_resInMinutes
|
||||
|
||||
get_tf(_lvl) =>
|
||||
y = f_resInMinutes()
|
||||
z = timeframe.period
|
||||
if mtf_typ == 'Auto'
|
||||
if y < 1
|
||||
z := _lvl == 1 ? '1' : _lvl == 2 ? '5' : z
|
||||
z
|
||||
else if y <= 3
|
||||
z := _lvl == 1 ? '5' : _lvl == 2 ? '15' : z
|
||||
z
|
||||
else if y <= 10
|
||||
z := _lvl == 1 ? '15' : _lvl == 2 ? '60' : z
|
||||
z
|
||||
else if y <= 30
|
||||
z := _lvl == 1 ? '60' : _lvl == 2 ? '240' : z
|
||||
z
|
||||
else if y <= 120
|
||||
z := _lvl == 1 ? '240' : _lvl == 2 ? 'D' : z
|
||||
z
|
||||
else if y <= 240
|
||||
z := _lvl == 1 ? 'D' : _lvl == 2 ? 'W' : z
|
||||
z
|
||||
else if y <= 1440
|
||||
z := _lvl == 1 ? 'W' : _lvl == 2 ? 'M' : z
|
||||
z
|
||||
else if y <= 10080
|
||||
z := _lvl == 1 ? 'M' : z
|
||||
z
|
||||
else
|
||||
z := z
|
||||
z
|
||||
else
|
||||
z := _lvl == 1 ? mtf_lvl1 : _lvl == 2 ? mtf_lvl2 : z
|
||||
z
|
||||
|
||||
z
|
||||
|
||||
//-----------------------
|
||||
// Mean Reversion Channel Function
|
||||
//-----------------------
|
||||
get_mrc() =>
|
||||
v_condition = 0
|
||||
v_meanline = source
|
||||
v_meanrange = supersmoother(ta.tr, length)
|
||||
|
||||
//-- Get Line value
|
||||
if type == 'SuperSmoother'
|
||||
v_meanline := supersmoother(source, length)
|
||||
v_meanline
|
||||
|
||||
if type != 'SuperSmoother'
|
||||
v_meanline := SAK_smoothing(type, source, length)
|
||||
v_meanline
|
||||
|
||||
v_upband1 = v_meanline + v_meanrange * mult
|
||||
v_loband1 = v_meanline - v_meanrange * mult
|
||||
v_upband2 = v_meanline + v_meanrange * mult2
|
||||
v_loband2 = v_meanline - v_meanrange * mult2
|
||||
|
||||
//-- Check Condition
|
||||
if close > v_meanline
|
||||
v_upband2_1 = v_upband2 + v_meanrange * gradsize * 4
|
||||
v_upband2_9 = v_upband2 + v_meanrange * gradsize * -4
|
||||
if high >= v_upband2_9 and high < v_upband2
|
||||
v_condition := 1
|
||||
v_condition
|
||||
else if high >= v_upband2 and high < v_upband2_1
|
||||
v_condition := 2
|
||||
v_condition
|
||||
else if high >= v_upband2_1
|
||||
v_condition := 3
|
||||
v_condition
|
||||
else if close <= v_meanline + v_meanrange
|
||||
v_condition := 4
|
||||
v_condition
|
||||
else
|
||||
v_condition := 5
|
||||
v_condition
|
||||
|
||||
if close < v_meanline
|
||||
v_loband2_1 = v_loband2 - v_meanrange * gradsize * 4
|
||||
v_loband2_9 = v_loband2 - v_meanrange * gradsize * -4
|
||||
if low <= v_loband2_9 and low > v_loband2
|
||||
v_condition := -1
|
||||
v_condition
|
||||
else if low <= v_loband2 and low > v_loband2_1
|
||||
v_condition := -2
|
||||
v_condition
|
||||
else if low <= v_loband2_1
|
||||
v_condition := -3
|
||||
v_condition
|
||||
else if close >= v_meanline + v_meanrange
|
||||
v_condition := -4
|
||||
v_condition
|
||||
else
|
||||
v_condition := -5
|
||||
v_condition
|
||||
|
||||
[v_meanline, v_meanrange, v_upband1, v_loband1, v_upband2, v_loband2, v_condition]
|
||||
|
||||
//-----------------------
|
||||
// MTF Analysis
|
||||
//-----------------------
|
||||
|
||||
get_stat(_cond) =>
|
||||
ret = 'Price at Mean Line\n'
|
||||
if _cond == 1
|
||||
ret := 'Overbought (Weak)\n'
|
||||
ret
|
||||
else if _cond == 2
|
||||
ret := 'Overbought\n'
|
||||
ret
|
||||
else if _cond == 3
|
||||
ret := 'Overbought (Strong)\n'
|
||||
ret
|
||||
else if _cond == 4
|
||||
ret := 'Price Near Mean\n'
|
||||
ret
|
||||
else if _cond == 5
|
||||
ret := 'Price Above Mean\n'
|
||||
ret
|
||||
else if _cond == -1
|
||||
ret := 'Oversold (Weak)\n'
|
||||
ret
|
||||
else if _cond == -2
|
||||
ret := 'Oversold\n'
|
||||
ret
|
||||
else if _cond == -3
|
||||
ret := 'Oversold (Strong)\n'
|
||||
ret
|
||||
else if _cond == -4
|
||||
ret := 'Price Near Mean\n'
|
||||
ret
|
||||
else if _cond == -5
|
||||
ret := 'Price Below Mean\n'
|
||||
ret
|
||||
ret
|
||||
|
||||
//-----------------------
|
||||
// Chart Drawing Function
|
||||
//-----------------------
|
||||
format_price(x) =>
|
||||
y = str.tostring(x, '0.00000')
|
||||
if x > 10
|
||||
y := str.tostring(x, '0.000')
|
||||
y
|
||||
if x > 1000
|
||||
y := str.tostring(x, '0.00')
|
||||
y
|
||||
y
|
||||
|
||||
f_PriceLine(_ref, linecol) =>
|
||||
line.new(x1 = bar_index, x2 = bar_index - 1, y1 = _ref, y2 = _ref, extend = extend.left, color = linecol)
|
||||
|
||||
f_MTFLabel(_txt, _yloc) =>
|
||||
label.new(x = time + math.round(ta.change(time) * 20), y = _yloc, xloc = xloc.bar_time, text = mtf_disp_typ == 'Always Display' ? _txt : 'Check MTF', tooltip = mtf_disp_typ == 'Always Display' ? '' : _txt, color = color.black, textcolor = color.white, size = size.normal, style = mtf_disp_typ == 'On Hover' and displayline ? label.style_label_lower_left : label.style_label_left, textalign = text.align_left)
|
||||
|
||||
//} Function End
|
||||
|
||||
//************************************************************************************************************
|
||||
// Calculate MA200, MA100, MA50
|
||||
//************************************************************************************************************
|
||||
// ————————————— 计算移动平均线 —————————————
|
||||
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)
|
||||
|
||||
// ————————————— 移动平均线颜色函数 —————————————
|
||||
maColor(ma, ref) => ma > ref ? color.lime : color.red
|
||||
|
||||
//************************************************************************************************************
|
||||
// Calculate Channel
|
||||
//************************************************************************************************************
|
||||
var tf_0 = timeframe.period
|
||||
var tf_1 = get_tf(1)
|
||||
var tf_2 = get_tf(2)
|
||||
|
||||
[meanline, meanrange, upband1, loband1, upband2, loband2, condition] = get_mrc()
|
||||
[mtf1_meanline, mtf1_meanrange, mtf1_upband1, mtf1_loband1, mtf1_upband2, mtf1_loband2, mtf1_condition] = request.security(syminfo.tickerid, tf_1, get_mrc())
|
||||
[mtf2_meanline, mtf2_meanrange, mtf2_upband1, mtf2_loband1, mtf2_upband2, mtf2_loband2, mtf2_condition] = request.security(syminfo.tickerid, tf_2, get_mrc())
|
||||
|
||||
//************************************************************************************************************
|
||||
// Drawing Start {
|
||||
//************************************************************************************************************
|
||||
float p_meanline = drawchannel ? meanline : na
|
||||
float p_upband1 = drawchannel ? upband1 : na
|
||||
float p_loband1 = drawchannel ? loband1 : na
|
||||
float p_upband2 = drawchannel ? upband2 : na
|
||||
float p_loband2 = drawchannel ? loband2 : na
|
||||
|
||||
// 保留 MEAN、R1、S1 的绘制用于警报,注释掉 R2、S2
|
||||
z = plot(p_meanline, color = color.new(color.black, 0), style = plot.style_line, title = ' Mean', linewidth = 2)
|
||||
x1 = plot(p_upband1, color = color.new(color.black, 0), style = plot.style_line, title = ' R1', linewidth = 2)
|
||||
x2 = plot(p_loband1, color = color.new(color.black, 0), style = plot.style_line, title = ' S1', linewidth = 2)
|
||||
// 注释掉 R2、S2 的绘制以减少线条数量
|
||||
// y1 = plot(p_upband2, color = color.new(color.red, 50), style = plot.style_line, title = ' R2', linewidth = 1)
|
||||
// y2 = plot(p_loband2, color = color.new(color.red, 50), style = plot.style_line, title = ' S2', linewidth = 1)
|
||||
|
||||
// ————————————— 绘制 MA50/MA100/MA200 —————————————
|
||||
plot(show_ma_lines ? ma50 : na, color=maColor(ma50, ma100), linewidth=2, title='MA50', display=display.all)
|
||||
plot(show_ma_lines ? ma100 : na, color=maColor(ma100, ma200), linewidth=2, title='MA100', display=display.all)
|
||||
plot(show_ma_lines ? ma200 : na, color=color.rgb(25, 58, 243), linewidth=4, title='MA200', display=display.all)
|
||||
|
||||
//-----------------------
|
||||
// Draw zone
|
||||
//-----------------------
|
||||
//---
|
||||
var color1 = #FF0000
|
||||
var color2 = #FF4200
|
||||
var color3 = #FF5D00
|
||||
var color4 = #FF7400
|
||||
var color5 = #FF9700
|
||||
var color6 = #FFAE00
|
||||
var color7 = #FFC500
|
||||
var color8 = #FFCD00
|
||||
//---
|
||||
float upband2_1 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 4 : na
|
||||
float loband2_1 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 4 : na
|
||||
float upband2_2 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 3 : na
|
||||
float loband2_2 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 3 : na
|
||||
float upband2_3 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 2 : na
|
||||
float loband2_3 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 2 : na
|
||||
float upband2_4 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 1 : na
|
||||
float loband2_4 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 1 : na
|
||||
float upband2_5 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 0 : na
|
||||
float loband2_5 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 0 : na
|
||||
float upband2_6 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -1 : na
|
||||
float loband2_6 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -1 : na
|
||||
float upband2_7 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -2 : na
|
||||
float loband2_7 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -2 : na
|
||||
float upband2_8 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -3 : na
|
||||
float loband2_8 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -3 : na
|
||||
float upband2_9 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -4 : na
|
||||
float loband2_9 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -4 : na
|
||||
|
||||
//---
|
||||
// 注释掉扩展区域的 plot 以减少线条数量,避免超过 TradingView 64条线限制
|
||||
// 保留计算但不绘制,警报仍可使用这些值
|
||||
// plot_upband2_1 = plot(upband2_1, color = na, title = 'R2_1')
|
||||
// plot_loband2_1 = plot(loband2_1, color = na, title = 'S2_1')
|
||||
|
||||
// 注释掉其他隐藏的 plot
|
||||
// plot_upband2_2 = plot(upband2_2, color = na, display = display.none)
|
||||
// plot_loband2_2 = plot(loband2_2, color = na, display = display.none)
|
||||
// plot_upband2_3 = plot(upband2_3, color = na, display = display.none)
|
||||
// plot_loband2_3 = plot(loband2_3, color = na, display = display.none)
|
||||
// plot_upband2_4 = plot(upband2_4, color = na, display = display.none)
|
||||
// plot_loband2_4 = plot(loband2_4, color = na, display = display.none)
|
||||
// plot_upband2_5 = plot(upband2_5, color = na, display = display.none)
|
||||
// plot_loband2_5 = plot(loband2_5, color = na, display = display.none)
|
||||
// plot_upband2_6 = plot(upband2_6, color = na, display = display.none)
|
||||
// plot_loband2_6 = plot(loband2_6, color = na, display = display.none)
|
||||
// plot_upband2_7 = plot(upband2_7, color = na, display = display.none)
|
||||
// plot_loband2_7 = plot(loband2_7, color = na, display = display.none)
|
||||
// plot_upband2_8 = plot(upband2_8, color = na, display = display.none)
|
||||
// plot_loband2_8 = plot(loband2_8, color = na, display = display.none)
|
||||
|
||||
// 注释掉 R2_9 和 S2_9 的 plot
|
||||
// plot_upband2_9 = plot(upband2_9, color = na, title = 'R2_9')
|
||||
// plot_loband2_9 = plot(loband2_9, color = na, title = 'S2_9')
|
||||
|
||||
//---
|
||||
// 注释掉扩展区域的填充,减少绘制元素
|
||||
// fill(plot_upband2_1, plot_upband2_2, color = color1)
|
||||
// fill(plot_loband2_1, plot_loband2_2, color = color1)
|
||||
// fill(plot_upband2_2, plot_upband2_3, color = color2)
|
||||
// fill(plot_loband2_2, plot_loband2_3, color = color2)
|
||||
// fill(plot_upband2_3, plot_upband2_4, color = color3)
|
||||
// fill(plot_loband2_3, plot_loband2_4, color = color3)
|
||||
// fill(plot_upband2_4, plot_upband2_5, color = color4)
|
||||
// fill(plot_loband2_4, plot_loband2_5, color = color4)
|
||||
// fill(plot_upband2_5, plot_upband2_6, color = color5)
|
||||
// fill(plot_loband2_5, plot_loband2_6, color = color5)
|
||||
// fill(plot_upband2_6, plot_upband2_7, color = color6)
|
||||
// fill(plot_loband2_6, plot_loband2_7, color = color6)
|
||||
// fill(plot_upband2_7, plot_upband2_8, color = color7)
|
||||
// fill(plot_loband2_7, plot_loband2_8, color = color7)
|
||||
// fill(plot_upband2_8, plot_upband2_9, color = color8)
|
||||
// fill(plot_loband2_8, plot_loband2_9, color = color8)
|
||||
|
||||
//-----------------------
|
||||
// Plot Extension
|
||||
//-----------------------
|
||||
if displayline and enable_mtf and mtf_disp_typ == 'Always Display'
|
||||
displayline := false
|
||||
displayline
|
||||
|
||||
var line mean = na
|
||||
line.delete(mean)
|
||||
mean := displayline ? f_PriceLine(meanline, #FFCD00) : na
|
||||
var line res1 = na
|
||||
line.delete(res1)
|
||||
res1 := displayline ? f_PriceLine(upband1, color.green) : na
|
||||
var line sup1 = na
|
||||
line.delete(sup1)
|
||||
sup1 := displayline ? f_PriceLine(loband1, color.green) : na
|
||||
var line res2 = na
|
||||
line.delete(res2)
|
||||
res2 := displayline ? f_PriceLine(upband2, color.red) : na
|
||||
var line sup2 = na
|
||||
line.delete(sup2)
|
||||
sup2 := displayline ? f_PriceLine(loband2, color.red) : na
|
||||
|
||||
//--------------
|
||||
// Prep MTF Label
|
||||
//--------------
|
||||
var brl = '\n--------------------------------------'
|
||||
dist_0 = 'Distance from Mean: ' + str.tostring((close - meanline) / close * 100, '#.##') + ' %'
|
||||
dist_1 = 'Distance from Mean: ' + str.tostring((close - mtf1_meanline) / close * 100, '#.##') + ' %'
|
||||
dist_2 = 'Distance from Mean: ' + str.tostring((close - mtf2_meanline) / close * 100, '#.##') + ' %'
|
||||
|
||||
var title = 'Mean Reversion Channel\nMultiple TimeFrame Analysis' + brl
|
||||
tf0 = '\n\nTimeframe: ' + tf_0 + ' (Current)\n\nStatus: ' + get_stat(condition) + dist_0 + brl
|
||||
|
||||
tf1 = not timeframe.ismonthly ? '\n\nTimeframe: ' + tf_1 + '\n\nStatus: ' + get_stat(mtf1_condition) + dist_1 + brl : ''
|
||||
|
||||
tf2 = not timeframe.isweekly and not timeframe.ismonthly ? '\n\nTimeframe: ' + tf_2 + '\n\nStatus: ' + get_stat(mtf2_condition) + dist_2 + brl : ''
|
||||
|
||||
mtf_lbl = title + tf0 + tf1 + tf2
|
||||
var label label_mtf = na
|
||||
label.delete(label_mtf)
|
||||
label_mtf := enable_mtf ? f_MTFLabel(mtf_lbl, meanline) : na
|
||||
|
||||
//************************************************************************************************************
|
||||
// Real-time Price Labels for Extended Lines (Placed on the right side of the last candle)
|
||||
//************************************************************************************************************
|
||||
|
||||
// Define persistent label variables so that they update rather than create new labels each bar
|
||||
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 res2_9_label = na // Label for upband2_9
|
||||
var label sup2_9_label = na // Label for loband2_9
|
||||
var label res2_1_label = na // New label for upband2_1
|
||||
var label sup2_1_label = na // New label for loband2_1
|
||||
|
||||
if displayline and barstate.islast
|
||||
// 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 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.green, 0), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res1_label, bar_index, upband1)
|
||||
label.set_text(res1_label, "R1: " + format_price(upband1))
|
||||
// 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 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, 0), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res2_label, bar_index, upband2)
|
||||
label.set_text(res2_label, "R2: " + format_price(upband2))
|
||||
// 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, 0), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(sup2_label, bar_index, loband2)
|
||||
label.set_text(sup2_label, "S2: " + format_price(loband2))
|
||||
// R2_9 label (for upband2_9)
|
||||
if na(res2_9_label)
|
||||
res2_9_label := label.new(bar_index, upband2_9, "R2_9: " + format_price(upband2_9), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res2_9_label, bar_index, upband2_9)
|
||||
label.set_text(res2_9_label, "R2_9: " + format_price(upband2_9))
|
||||
// S2_9 label (for loband2_9)
|
||||
if na(sup2_9_label)
|
||||
sup2_9_label := label.new(bar_index, loband2_9, "S2_9: " + format_price(loband2_9), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(sup2_9_label, bar_index, loband2_9)
|
||||
label.set_text(sup2_9_label, "S2_9: " + format_price(loband2_9))
|
||||
// R2_1 label (New for upband2_1)
|
||||
if na(res2_1_label)
|
||||
res2_1_label := label.new(bar_index, upband2_1, "R2_1: " + format_price(upband2_1), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res2_1_label, bar_index, upband2_1)
|
||||
label.set_text(res2_1_label, "R2_1: " + format_price(upband2_1))
|
||||
// S2_1 label (New for loband2_1)
|
||||
if na(sup2_1_label)
|
||||
sup2_1_label := label.new(bar_index, loband2_1, "S2_1: " + format_price(loband2_1), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(sup2_1_label, bar_index, loband2_1)
|
||||
label.set_text(sup2_1_label, "S2_1: " + format_price(loband2_1))
|
||||
|
||||
//************************************************************************************************************
|
||||
// MA Price Labels (Placed on the right side of the last candle)
|
||||
//************************************************************************************************************
|
||||
// ————————————— MA价格标签(单行 label.new) —————————————
|
||||
var label lbl50 = na
|
||||
var label lbl100 = na
|
||||
var label lbl200 = na
|
||||
|
||||
if show_ma_labels and barstate.islast
|
||||
if na(lbl50)
|
||||
lbl50 := label.new(x=time, y=ma50, text='MA50: ' + str.tostring(ma50, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.lime, textcolor=color.white)
|
||||
else
|
||||
label.set_xy(lbl50, x=time, y=ma50), label.set_text(lbl50, 'MA50: ' + str.tostring(ma50, '#.####'))
|
||||
|
||||
if na(lbl100)
|
||||
lbl100 := label.new(x=time, y=ma100, text='MA100: ' + str.tostring(ma100, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.white, textcolor=color.black)
|
||||
else
|
||||
label.set_xy(lbl100, x=time, y=ma100), label.set_text(lbl100, 'MA100: ' + str.tostring(ma100, '#.####'))
|
||||
|
||||
if na(lbl200)
|
||||
lbl200 := label.new(x=time, y=ma200, text='MA200: ' + str.tostring(ma200, '#.####'), xloc=xloc.bar_time, yloc=yloc.price, style=label.style_label_left, color=color.white, textcolor=color.black)
|
||||
else
|
||||
label.set_xy(lbl200, x=time, y=ma200), label.set_text(lbl200, 'MA200: ' + str.tostring(ma200, '#.####'))
|
||||
//************************************************************************************************************
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
//************************************************************************************************************
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_r1_breakout_up = 0
|
||||
var int last_alert_s1_breakout_down = 0
|
||||
var int last_alert_range_r1_s1 = 0
|
||||
var int last_alert_above_r1 = 0
|
||||
var int last_alert_below_s1 = 0
|
||||
var int last_alert_above_mean = 0
|
||||
var int last_alert_below_mean = 0
|
||||
var int last_alert_mean_above_ma200 = 0
|
||||
var int last_alert_mean_below_ma200 = 0
|
||||
var int last_alert_mean_above_ma50 = 0
|
||||
var int last_alert_mean_below_ma50 = 0
|
||||
var int last_alert_mean_above_ma100 = 0
|
||||
var int last_alert_mean_below_ma100 = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 价格触碰关键位置警报
|
||||
// if ta.cross(close, meanline)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到MEAN","位置":"MEAN","信号":"mean_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, upband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到R1","位置":"R1","信号":"r1_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, loband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到S1","位置":"S1","信号":"s1_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, upband2)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到R2","位置":"R2","信号":"r2_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, loband2)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到S2","位置":"S2","信号":"s2_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// 价格区间警报
|
||||
// if close > meanline and close < upband1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN和R1之间","位置":"MEAN-R1","信号":"range_mean_r1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < meanline and close > loband1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN和S1之间","位置":"MEAN-S1","信号":"range_mean_s1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close > upband1 and close < upband2
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1和R2之间","位置":"R1-R2","信号":"range_r1_r2"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < loband1 and close > loband2
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S1和S2之间","位置":"S1-S2","信号":"range_s1_s2"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close > upband1 and close < upband2_9
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1和R2_9之间","位置":"R1-R2_9","信号":"range_r1_r2_9"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close > upband2_9 and close < upband2_1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R2_9和R2_1之间","位置":"R2_9-R2_1","信号":"range_r2_9_r2_1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < loband1 and close > loband2_9
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S1和S2_9之间","位置":"S1-S2_9","信号":"range_s1_s2_9"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < loband2_9 and close > loband2_1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S2_9和S2_1之间","位置":"S2_9-S2_1","信号":"range_s2_9_s2_1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// // 价格穿越警报 - 每分钟限制
|
||||
// if ta.crossover(close, upband1) and current_minute > last_alert_r1_breakout_up
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿R1","位置":"R1","信号":"r1_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_r1_breakout_up := current_minute
|
||||
|
||||
// if ta.crossunder(close, upband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿R1","位置":"R1","信号":"r1_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, loband1) and current_minute > last_alert_s1_breakout_down
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿S1","位置":"S1","信号":"s1_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_s1_breakout_down := current_minute
|
||||
|
||||
// if ta.crossover(close, loband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿S1","位置":"S1","信号":"s1_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossover(close, meanline)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿MEAN","位置":"MEAN","信号":"mean_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, meanline)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿MEAN","位置":"MEAN","信号":"mean_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossover(close, loband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿S2_9","位置":"S2_9","信号":"s2_9_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, loband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿S2_9","位置":"S2_9","信号":"s2_9_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossover(close, upband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿R2_9","位置":"R2_9","信号":"r2_9_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, upband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿R2_9","位置":"R2_9","信号":"r2_9_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// ===== 新增的5个警报条件 - 每分钟限制 =====
|
||||
// 1. 价格处于R1和S1之间时
|
||||
// if close <= upband1 and close >= loband1 and current_minute > last_alert_range_r1_s1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1和S1之间","位置":"R1-S1区间","信号":"range_r1_s1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
// last_alert_range_r1_s1 := current_minute
|
||||
|
||||
// // 2. 价格处于R1以上时
|
||||
// if close > upband1 and current_minute > last_alert_above_r1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1以上","位置":"R1以上","信号":"above_r1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
// last_alert_above_r1 := current_minute
|
||||
|
||||
// // 3. 价格处于S1以下时
|
||||
// if close < loband1 and current_minute > last_alert_below_s1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S1以下","位置":"S1以下","信号":"below_s1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
// last_alert_below_s1 := current_minute
|
||||
|
||||
// // 4. 价格处于MEAN以上时
|
||||
// if close > meanline and current_minute > last_alert_above_mean
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN以上","位置":"MEAN以上","信号":"above_mean"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
// last_alert_above_mean := current_minute
|
||||
|
||||
// // 5. 价格处于MEAN以下时
|
||||
// if close < meanline and current_minute > last_alert_below_mean
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN以下","位置":"MEAN以下","信号":"below_mean"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
// last_alert_below_mean := current_minute
|
||||
|
||||
// ===== 新增的MA相关警报条件 - 每分钟限制 =====
|
||||
// 计算MEAN线与各MA的距离
|
||||
mean_ma200_distance = math.abs(meanline - ma200)
|
||||
mean_ma50_distance = math.abs(meanline - ma50)
|
||||
mean_ma100_distance = math.abs(meanline - ma100)
|
||||
|
||||
// 6. MEAN线价格处于MA200以上时
|
||||
if meanline > ma200 and current_minute > last_alert_mean_above_ma200
|
||||
alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(mean_ma200_distance, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MEAN线处于MA200以上","位置":"MA200以上"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_mean_above_ma200 := current_minute
|
||||
|
||||
// 7. MEAN线价格处于MA200以下时
|
||||
if meanline < ma200 and current_minute > last_alert_mean_below_ma200
|
||||
alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(mean_ma200_distance, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MEAN线处于MA200以下","位置":"MA200以下"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_mean_below_ma200 := current_minute
|
||||
|
||||
// 8. MEAN线价格处于MA50以上时
|
||||
if meanline > ma50 and current_minute > last_alert_mean_above_ma50
|
||||
alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(mean_ma50_distance, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MEAN线处于MA50以上","位置":"MA50以上"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_mean_above_ma50 := current_minute
|
||||
|
||||
// 9. MEAN线价格处于MA50以下时
|
||||
if meanline < ma50 and current_minute > last_alert_mean_below_ma50
|
||||
alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(mean_ma50_distance, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MEAN线处于MA50以下","位置":"MA50以下"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_mean_below_ma50 := current_minute
|
||||
|
||||
// 10. MEAN线价格处于MA100以上时
|
||||
if meanline > ma100 and current_minute > last_alert_mean_above_ma100
|
||||
alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(mean_ma100_distance, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MEAN线处于MA100以上","位置":"MA100以上"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_mean_above_ma100 := current_minute
|
||||
|
||||
// 11. MEAN线价格处于MA100以下时
|
||||
if meanline < ma100 and current_minute > last_alert_mean_below_ma100
|
||||
alert_message := '{"指标名称":"MA200","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","MA50":"' + str.tostring(ma50, '#.####') + '","MA100":"' + str.tostring(ma100, '#.####') + '","MA200":"' + str.tostring(ma200, '#.####') + '","距离(美元)":"' + str.tostring(mean_ma100_distance, '#.##') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"MEAN线处于MA100以下","位置":"MA100以下"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_mean_below_ma100 := current_minute
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(ma50, title = 'MA50值', display = display.none)
|
||||
plot(ma100, title = 'MA100值', display = display.none)
|
||||
plot(ma200, title = 'MA200值', display = display.none)
|
||||
plot(mean_ma200_distance, title = 'MEAN距离MA200', display = display.none)
|
||||
plot(mean_ma50_distance, title = 'MEAN距离MA50', display = display.none)
|
||||
plot(mean_ma100_distance, title = 'MEAN距离MA100', display = display.none)
|
||||
|
||||
// 为传统警报创建隐藏的plot变量(不显示但支持警报引用)
|
||||
plot(upband2, title = ' R2', display = display.none) // R2 隐藏绘制用于警报
|
||||
plot(loband2, title = ' S2', display = display.none) // S2 隐藏绘制用于警报
|
||||
plot(upband2_1, title = 'R2_1', display = display.none)
|
||||
plot(loband2_1, title = 'S2_1', display = display.none)
|
||||
plot(upband2_9, title = 'R2_9', display = display.none)
|
||||
plot(loband2_9, title = 'S2_9', display = display.none)
|
||||
|
||||
// 价格穿越警报
|
||||
alertcondition(ta.crossover(close, upband1), title = '价格上穿R1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R1","位置":"R1","信号":"r1_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband1), title = '价格下穿R1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R1","位置":"R1","信号":"r1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband1), title = '价格下穿S1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S1","位置":"S1","信号":"s1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband1), title = '价格上穿S1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S1","位置":"S1","信号":"s1_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossover(close, meanline), title = '价格上穿MEAN', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿MEAN","位置":"MEAN","信号":"mean_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, meanline), title = '价格下穿MEAN', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿MEAN","位置":"MEAN","信号":"mean_breakout_down"}')
|
||||
|
||||
// R2和S2穿越警报
|
||||
alertcondition(ta.crossover(close, upband2), title = '价格上穿R2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R2","位置":"R2","信号":"r2_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband2), title = '价格下穿R2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R2","位置":"R2","信号":"r2_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband2), title = '价格下穿S2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S2","位置":"S2","信号":"s2_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband2), title = '价格上穿S2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S2","位置":"S2","信号":"s2_breakout_up"}')
|
||||
|
||||
// 扩展区域穿越警报
|
||||
alertcondition(ta.crossover(close, upband2_9), title = '价格上穿R2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R2_9","位置":"R2_9","信号":"r2_9_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband2_9), title = '价格下穿R2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R2_9","位置":"R2_9","信号":"r2_9_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband2_9), title = '价格下穿S2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S2_9","位置":"S2_9","信号":"s2_9_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband2_9), title = '价格上穿S2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S2_9","位置":"S2_9","信号":"s2_9_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossover(close, upband2_1), title = '价格上穿R2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R2_1","位置":"R2_1","信号":"r2_1_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband2_1), title = '价格下穿R2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R2_1","位置":"R2_1","信号":"r2_1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband2_1), title = '价格下穿S2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S2_1","位置":"S2_1","信号":"s2_1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband2_1), title = '价格上穿S2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S2_1","位置":"S2_1","信号":"s2_1_breakout_up"}')
|
||||
|
||||
// 价格区间状态警报
|
||||
alertcondition(close <= upband1 and close >= loband1, title = '价格处于R1和S1之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R1和S1之间","位置":"R1-S1区间","信号":"range_r1_s1"}')
|
||||
|
||||
alertcondition(close > upband1, title = '价格处于R1以上', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R1以上","位置":"R1以上","信号":"above_r1"}')
|
||||
|
||||
alertcondition(close < loband1, title = '价格处于S1以下', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S1以下","位置":"S1以下","信号":"below_s1"}')
|
||||
|
||||
alertcondition(close > meanline, title = '价格处于MEAN以上', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于MEAN以上","位置":"MEAN以上","信号":"above_mean"}')
|
||||
|
||||
alertcondition(close < meanline, title = '价格处于MEAN以下', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于MEAN以下","位置":"MEAN以下","信号":"below_mean"}')
|
||||
|
||||
// 区间范围警报
|
||||
alertcondition(close > upband1 and close < upband2, title = '价格处于R1和R2之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R1和R2之间","位置":"R1-R2","信号":"range_r1_r2"}')
|
||||
|
||||
alertcondition(close < loband1 and close > loband2, title = '价格处于S1和S2之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S1和S2之间","位置":"S1-S2","信号":"range_s1_s2"}')
|
||||
|
||||
alertcondition(close > upband2 and close < upband2_1, title = '价格处于R2和R2_1之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R2和R2_1之间","位置":"R2-R2_1","信号":"range_r2_r2_1"}')
|
||||
|
||||
alertcondition(close < loband2 and close > loband2_1, title = '价格处于S2和S2_1之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S2和S2_1之间","位置":"S2-S2_1","信号":"range_s2_s2_1"}')
|
||||
|
||||
// 极端区域警报
|
||||
alertcondition(close > upband2_1, title = '价格处于R2_1以上', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R2_1以上","位置":"R2_1以上","信号":"above_r2_1"}')
|
||||
|
||||
alertcondition(close < loband2_1, title = '价格处于S2_1以下', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S2_1以下","位置":"S2_1以下","信号":"below_s2_1"}')
|
||||
|
||||
// ===== 新增的MA200相关传统警报条件 =====
|
||||
// MEAN线与MA200关系警报
|
||||
alertcondition(meanline > ma200, title = 'MEAN线处于MA200以上', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("MEAN距离MA200")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MEAN线处于MA200以上","位置":"MA200以上","信号":"mean_above_ma200"}')
|
||||
|
||||
alertcondition(meanline < ma200, title = 'MEAN线处于MA200以下', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("MEAN距离MA200")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MEAN线处于MA200以下","位置":"MA200以下","信号":"mean_below_ma200"}')
|
||||
|
||||
// MEAN线与MA50关系警报
|
||||
alertcondition(meanline > ma50, title = 'MEAN线处于MA50以上', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("MEAN距离MA50")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MEAN线处于MA50以上","位置":"MA50以上","信号":"mean_above_ma50"}')
|
||||
|
||||
alertcondition(meanline < ma50, title = 'MEAN线处于MA50以下', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("MEAN距离MA50")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MEAN线处于MA50以下","位置":"MA50以下","信号":"mean_below_ma50"}')
|
||||
|
||||
// MEAN线与MA100关系警报
|
||||
alertcondition(meanline > ma100, title = 'MEAN线处于MA100以上', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("MEAN距离MA100")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MEAN线处于MA100以上","位置":"MA100以上","信号":"mean_above_ma100"}')
|
||||
|
||||
alertcondition(meanline < ma100, title = 'MEAN线处于MA100以下', message = '{"指标名称":"MA200","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","MA50":"{{plot("MA50值")}}","MA100":"{{plot("MA100值")}}","MA200":"{{plot("MA200值")}}","距离(美元)":"{{plot("MEAN距离MA100")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"MEAN线处于MA100以下","位置":"MA100以下","信号":"mean_below_ma100"}')
|
||||
715
mrc.pine
Normal file
715
mrc.pine
Normal file
@@ -0,0 +1,715 @@
|
||||
//@version=6
|
||||
indicator('Mean Reversion Channel - 带价格标签', shorttitle = 'MRC2', overlay = true, format = format.inherit)
|
||||
|
||||
//************************************************************************************************************
|
||||
// Parameter
|
||||
//************************************************************************************************************
|
||||
|
||||
indiSet = input(false, '═════════ MRC Parameter ════════')
|
||||
source = input(hlc3, title = 'Price Source')
|
||||
type = input.string('SuperSmoother', title = 'Filter Type', options = ['SuperSmoother', 'Ehlers EMA', 'Gaussian', 'Butterworth', 'BandStop', 'SMA', 'EMA', 'RMA'])
|
||||
length = input.int(200, title = 'Lookback Period', minval = 1)
|
||||
innermult = input.float(1.0, title = 'Inner Channel Size Multiplier', minval = 0.1)
|
||||
outermult = input.float(2.415, title = 'Outer Channel Size Multiplier', minval = 0.1)
|
||||
|
||||
ChartSet = input(false, '═════════ Chart Setting ════════')
|
||||
drawchannel = input(true, title = 'Draw Channel')
|
||||
displayzone = input(true, title = 'Draw Zone (With Channel)')
|
||||
zonetransp = input.int(60, title = 'Zone Transparency', minval = 0, maxval = 100)
|
||||
displayline = input(true, title = 'Display Line Extension')
|
||||
|
||||
MTFSet = input(false, '═════════ MTF Setting ════════')
|
||||
enable_mtf = input(true, title = 'Enable Multiple TimeFrame Analysis')
|
||||
mtf_disp_typ = input.string('On Hover', title = 'MTF Display Type', options = ['Always Display', 'On Hover'])
|
||||
mtf_typ = input.string('Auto', title = 'Multiple TimeFrame Type', options = ['Auto', 'Custom'])
|
||||
mtf_lvl1 = input.timeframe('D', title = 'Custom MTF Level 1')
|
||||
mtf_lvl2 = input.timeframe('W', title = 'Custom MTF Level 2')
|
||||
|
||||
//************************************************************************************************************
|
||||
// Functions Start {
|
||||
//************************************************************************************************************
|
||||
var pi = 2 * math.asin(1)
|
||||
var mult = pi * innermult
|
||||
var mult2 = pi * outermult
|
||||
var gradsize = 0.5
|
||||
var gradtransp = zonetransp
|
||||
|
||||
//-----------------------
|
||||
// Ehler SwissArmyKnife Function
|
||||
//-----------------------
|
||||
SAK_smoothing(_type, _src, _length) =>
|
||||
c0 = 1.0
|
||||
c1 = 0.0
|
||||
b0 = 1.0
|
||||
b1 = 0.0
|
||||
b2 = 0.0
|
||||
a1 = 0.0
|
||||
a2 = 0.0
|
||||
alpha = 0.0
|
||||
beta = 0.0
|
||||
gamma = 0.0
|
||||
cycle = 2 * pi / _length
|
||||
|
||||
if _type == 'Ehlers EMA'
|
||||
alpha := (math.cos(cycle) + math.sin(cycle) - 1) / math.cos(cycle)
|
||||
b0 := alpha
|
||||
a1 := 1 - alpha
|
||||
a1
|
||||
if _type == 'Gaussian'
|
||||
beta := 2.415 * (1 - math.cos(cycle))
|
||||
alpha := -beta + math.sqrt(beta * beta + 2 * beta)
|
||||
c0 := alpha * alpha
|
||||
a1 := 2 * (1 - alpha)
|
||||
a2 := -(1 - alpha) * (1 - alpha)
|
||||
a2
|
||||
if _type == 'Butterworth'
|
||||
beta := 2.415 * (1 - math.cos(cycle))
|
||||
alpha := -beta + math.sqrt(beta * beta + 2 * beta)
|
||||
c0 := alpha * alpha / 4
|
||||
b1 := 2
|
||||
b2 := 1
|
||||
a1 := 2 * (1 - alpha)
|
||||
a2 := -(1 - alpha) * (1 - alpha)
|
||||
a2
|
||||
if _type == 'BandStop'
|
||||
beta := math.cos(cycle)
|
||||
gamma := 1 / math.cos(cycle * 2 * 0.1) // delta default to 0.1. Acceptable delta -- 0.05<d<0.5
|
||||
alpha := gamma - math.sqrt(gamma * gamma - 1)
|
||||
c0 := (1 + alpha) / 2
|
||||
b1 := -2 * beta
|
||||
b2 := 1
|
||||
a1 := beta * (1 + alpha)
|
||||
a2 := -alpha
|
||||
a2
|
||||
if _type == 'SMA'
|
||||
c1 := 1 / _length
|
||||
b0 := 1 / _length
|
||||
a1 := 1
|
||||
a1
|
||||
if _type == 'EMA'
|
||||
alpha := 2 / (_length + 1)
|
||||
b0 := alpha
|
||||
a1 := 1 - alpha
|
||||
a1
|
||||
if _type == 'RMA'
|
||||
alpha := 1 / _length
|
||||
b0 := alpha
|
||||
a1 := 1 - alpha
|
||||
a1
|
||||
|
||||
_Input = _src
|
||||
_Output = 0.0
|
||||
_Output := c0 * (b0 * _Input + b1 * nz(_Input[1]) + b2 * nz(_Input[2])) + a1 * nz(_Output[1]) + a2 * nz(_Output[2]) - c1 * nz(_Input[_length])
|
||||
_Output
|
||||
|
||||
//-----------------------
|
||||
// SuperSmoother Function
|
||||
//-----------------------
|
||||
supersmoother(_src, _length) =>
|
||||
s_a1 = math.exp(-math.sqrt(2) * pi / _length)
|
||||
s_b1 = 2 * s_a1 * math.cos(math.sqrt(2) * pi / _length)
|
||||
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
|
||||
|
||||
//-----------------------
|
||||
// Auto TimeFrame Function
|
||||
//-----------------------
|
||||
// ————— Converts current chart resolution into a float minutes value.
|
||||
f_resInMinutes() =>
|
||||
_resInMinutes = timeframe.multiplier * (timeframe.isseconds ? 1. / 60 : timeframe.isminutes ? 1. : timeframe.isdaily ? 60. * 24 : timeframe.isweekly ? 60. * 24 * 7 : timeframe.ismonthly ? 60. * 24 * 30.4375 : na)
|
||||
_resInMinutes
|
||||
|
||||
get_tf(_lvl) =>
|
||||
y = f_resInMinutes()
|
||||
z = timeframe.period
|
||||
if mtf_typ == 'Auto'
|
||||
if y < 1
|
||||
z := _lvl == 1 ? '1' : _lvl == 2 ? '5' : z
|
||||
z
|
||||
else if y <= 3
|
||||
z := _lvl == 1 ? '5' : _lvl == 2 ? '15' : z
|
||||
z
|
||||
else if y <= 10
|
||||
z := _lvl == 1 ? '15' : _lvl == 2 ? '60' : z
|
||||
z
|
||||
else if y <= 30
|
||||
z := _lvl == 1 ? '60' : _lvl == 2 ? '240' : z
|
||||
z
|
||||
else if y <= 120
|
||||
z := _lvl == 1 ? '240' : _lvl == 2 ? 'D' : z
|
||||
z
|
||||
else if y <= 240
|
||||
z := _lvl == 1 ? 'D' : _lvl == 2 ? 'W' : z
|
||||
z
|
||||
else if y <= 1440
|
||||
z := _lvl == 1 ? 'W' : _lvl == 2 ? 'M' : z
|
||||
z
|
||||
else if y <= 10080
|
||||
z := _lvl == 1 ? 'M' : z
|
||||
z
|
||||
else
|
||||
z := z
|
||||
z
|
||||
else
|
||||
z := _lvl == 1 ? mtf_lvl1 : _lvl == 2 ? mtf_lvl2 : z
|
||||
z
|
||||
|
||||
z
|
||||
|
||||
//-----------------------
|
||||
// Mean Reversion Channel Function
|
||||
//-----------------------
|
||||
get_mrc() =>
|
||||
v_condition = 0
|
||||
v_meanline = source
|
||||
v_meanrange = supersmoother(ta.tr, length)
|
||||
|
||||
//-- Get Line value
|
||||
if type == 'SuperSmoother'
|
||||
v_meanline := supersmoother(source, length)
|
||||
v_meanline
|
||||
|
||||
if type != 'SuperSmoother'
|
||||
v_meanline := SAK_smoothing(type, source, length)
|
||||
v_meanline
|
||||
|
||||
v_upband1 = v_meanline + v_meanrange * mult
|
||||
v_loband1 = v_meanline - v_meanrange * mult
|
||||
v_upband2 = v_meanline + v_meanrange * mult2
|
||||
v_loband2 = v_meanline - v_meanrange * mult2
|
||||
|
||||
//-- Check Condition
|
||||
if close > v_meanline
|
||||
v_upband2_1 = v_upband2 + v_meanrange * gradsize * 4
|
||||
v_upband2_9 = v_upband2 + v_meanrange * gradsize * -4
|
||||
if high >= v_upband2_9 and high < v_upband2
|
||||
v_condition := 1
|
||||
v_condition
|
||||
else if high >= v_upband2 and high < v_upband2_1
|
||||
v_condition := 2
|
||||
v_condition
|
||||
else if high >= v_upband2_1
|
||||
v_condition := 3
|
||||
v_condition
|
||||
else if close <= v_meanline + v_meanrange
|
||||
v_condition := 4
|
||||
v_condition
|
||||
else
|
||||
v_condition := 5
|
||||
v_condition
|
||||
|
||||
if close < v_meanline
|
||||
v_loband2_1 = v_loband2 - v_meanrange * gradsize * 4
|
||||
v_loband2_9 = v_loband2 - v_meanrange * gradsize * -4
|
||||
if low <= v_loband2_9 and low > v_loband2
|
||||
v_condition := -1
|
||||
v_condition
|
||||
else if low <= v_loband2 and low > v_loband2_1
|
||||
v_condition := -2
|
||||
v_condition
|
||||
else if low <= v_loband2_1
|
||||
v_condition := -3
|
||||
v_condition
|
||||
else if close >= v_meanline + v_meanrange
|
||||
v_condition := -4
|
||||
v_condition
|
||||
else
|
||||
v_condition := -5
|
||||
v_condition
|
||||
|
||||
[v_meanline, v_meanrange, v_upband1, v_loband1, v_upband2, v_loband2, v_condition]
|
||||
|
||||
//-----------------------
|
||||
// MTF Analysis
|
||||
//-----------------------
|
||||
|
||||
get_stat(_cond) =>
|
||||
ret = 'Price at Mean Line\n'
|
||||
if _cond == 1
|
||||
ret := 'Overbought (Weak)\n'
|
||||
ret
|
||||
else if _cond == 2
|
||||
ret := 'Overbought\n'
|
||||
ret
|
||||
else if _cond == 3
|
||||
ret := 'Overbought (Strong)\n'
|
||||
ret
|
||||
else if _cond == 4
|
||||
ret := 'Price Near Mean\n'
|
||||
ret
|
||||
else if _cond == 5
|
||||
ret := 'Price Above Mean\n'
|
||||
ret
|
||||
else if _cond == -1
|
||||
ret := 'Oversold (Weak)\n'
|
||||
ret
|
||||
else if _cond == -2
|
||||
ret := 'Oversold\n'
|
||||
ret
|
||||
else if _cond == -3
|
||||
ret := 'Oversold (Strong)\n'
|
||||
ret
|
||||
else if _cond == -4
|
||||
ret := 'Price Near Mean\n'
|
||||
ret
|
||||
else if _cond == -5
|
||||
ret := 'Price Below Mean\n'
|
||||
ret
|
||||
ret
|
||||
|
||||
//-----------------------
|
||||
// Chart Drawing Function
|
||||
//-----------------------
|
||||
format_price(x) =>
|
||||
y = str.tostring(x, '0.00000')
|
||||
if x > 10
|
||||
y := str.tostring(x, '0.000')
|
||||
y
|
||||
if x > 1000
|
||||
y := str.tostring(x, '0.00')
|
||||
y
|
||||
y
|
||||
|
||||
f_PriceLine(_ref, linecol) =>
|
||||
line.new(x1 = bar_index, x2 = bar_index - 1, y1 = _ref, y2 = _ref, extend = extend.left, color = linecol)
|
||||
|
||||
f_MTFLabel(_txt, _yloc) =>
|
||||
label.new(x = time + math.round(ta.change(time) * 20), y = _yloc, xloc = xloc.bar_time, text = mtf_disp_typ == 'Always Display' ? _txt : 'Check MTF', tooltip = mtf_disp_typ == 'Always Display' ? '' : _txt, color = color.black, textcolor = color.white, size = size.normal, style = mtf_disp_typ == 'On Hover' and displayline ? label.style_label_lower_left : label.style_label_left, textalign = text.align_left)
|
||||
|
||||
//} Function End
|
||||
|
||||
//************************************************************************************************************
|
||||
// Calculate Channel
|
||||
//************************************************************************************************************
|
||||
var tf_0 = timeframe.period
|
||||
var tf_1 = get_tf(1)
|
||||
var tf_2 = get_tf(2)
|
||||
|
||||
[meanline, meanrange, upband1, loband1, upband2, loband2, condition] = get_mrc()
|
||||
[mtf1_meanline, mtf1_meanrange, mtf1_upband1, mtf1_loband1, mtf1_upband2, mtf1_loband2, mtf1_condition] = request.security(syminfo.tickerid, tf_1, get_mrc())
|
||||
[mtf2_meanline, mtf2_meanrange, mtf2_upband1, mtf2_loband1, mtf2_upband2, mtf2_loband2, mtf2_condition] = request.security(syminfo.tickerid, tf_2, get_mrc())
|
||||
|
||||
//************************************************************************************************************
|
||||
// Drawing Start {
|
||||
//************************************************************************************************************
|
||||
float p_meanline = drawchannel ? meanline : na
|
||||
float p_upband1 = drawchannel ? upband1 : na
|
||||
float p_loband1 = drawchannel ? loband1 : na
|
||||
float p_upband2 = drawchannel ? upband2 : na
|
||||
float p_loband2 = drawchannel ? loband2 : na
|
||||
|
||||
z = plot(p_meanline, color = color.new(color.black, 0), style = plot.style_line, title = ' Mean', linewidth = 2)
|
||||
x1 = plot(p_upband1, color = color.new(color.black, 0), style = plot.style_line, title = ' R1', linewidth = 2)
|
||||
x2 = plot(p_loband1, color = color.new(color.black, 0), style = plot.style_line, title = ' S1', linewidth = 2)
|
||||
y1 = plot(p_upband2, color = color.new(color.red, 50), style = plot.style_line, title = ' R2', linewidth = 1)
|
||||
y2 = plot(p_loband2, color = color.new(color.red, 50), style = plot.style_line, title = ' S2', linewidth = 1)
|
||||
|
||||
//-----------------------
|
||||
// Draw zone
|
||||
//-----------------------
|
||||
//---
|
||||
var color1 = #FF0000
|
||||
var color2 = #FF4200
|
||||
var color3 = #FF5D00
|
||||
var color4 = #FF7400
|
||||
var color5 = #FF9700
|
||||
var color6 = #FFAE00
|
||||
var color7 = #FFC500
|
||||
var color8 = #FFCD00
|
||||
//---
|
||||
float upband2_1 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 4 : na
|
||||
float loband2_1 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 4 : na
|
||||
float upband2_2 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 3 : na
|
||||
float loband2_2 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 3 : na
|
||||
float upband2_3 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 2 : na
|
||||
float loband2_3 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 2 : na
|
||||
float upband2_4 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 1 : na
|
||||
float loband2_4 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 1 : na
|
||||
float upband2_5 = drawchannel and displayzone ? upband2 + meanrange * gradsize * 0 : na
|
||||
float loband2_5 = drawchannel and displayzone ? loband2 - meanrange * gradsize * 0 : na
|
||||
float upband2_6 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -1 : na
|
||||
float loband2_6 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -1 : na
|
||||
float upband2_7 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -2 : na
|
||||
float loband2_7 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -2 : na
|
||||
float upband2_8 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -3 : na
|
||||
float loband2_8 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -3 : na
|
||||
float upband2_9 = drawchannel and displayzone ? upband2 + meanrange * gradsize * -4 : na
|
||||
float loband2_9 = drawchannel and displayzone ? loband2 - meanrange * gradsize * -4 : na
|
||||
|
||||
//---
|
||||
// 为了让警报消息能正确引用这些值,我们需要创建可见的 plot
|
||||
// R2_1 和 S2_1 (plot_5 和 plot_6)
|
||||
plot_upband2_1 = plot(upband2_1, color = na, title = 'R2_1')
|
||||
plot_loband2_1 = plot(loband2_1, color = na, title = 'S2_1')
|
||||
|
||||
// 其他隐藏的 plot 用于填充
|
||||
plot_upband2_2 = plot(upband2_2, color = na, display = display.none)
|
||||
plot_loband2_2 = plot(loband2_2, color = na, display = display.none)
|
||||
plot_upband2_3 = plot(upband2_3, color = na, display = display.none)
|
||||
plot_loband2_3 = plot(loband2_3, color = na, display = display.none)
|
||||
plot_upband2_4 = plot(upband2_4, color = na, display = display.none)
|
||||
plot_loband2_4 = plot(loband2_4, color = na, display = display.none)
|
||||
plot_upband2_5 = plot(upband2_5, color = na, display = display.none)
|
||||
plot_loband2_5 = plot(loband2_5, color = na, display = display.none)
|
||||
plot_upband2_6 = plot(upband2_6, color = na, display = display.none)
|
||||
plot_loband2_6 = plot(loband2_6, color = na, display = display.none)
|
||||
plot_upband2_7 = plot(upband2_7, color = na, display = display.none)
|
||||
plot_loband2_7 = plot(loband2_7, color = na, display = display.none)
|
||||
plot_upband2_8 = plot(upband2_8, color = na, display = display.none)
|
||||
plot_loband2_8 = plot(loband2_8, color = na, display = display.none)
|
||||
|
||||
// 在这里添加 R2_9 和 S2_9 的 plot,确保它们在正确的位置
|
||||
// 这些将成为 plot_19 和 plot_20
|
||||
plot_upband2_9 = plot(upband2_9, color = na, title = 'R2_9')
|
||||
plot_loband2_9 = plot(loband2_9, color = na, title = 'S2_9')
|
||||
|
||||
//---
|
||||
fill(plot_upband2_1, plot_upband2_2, color = color1)
|
||||
fill(plot_loband2_1, plot_loband2_2, color = color1)
|
||||
fill(plot_upband2_2, plot_upband2_3, color = color2)
|
||||
fill(plot_loband2_2, plot_loband2_3, color = color2)
|
||||
fill(plot_upband2_3, plot_upband2_4, color = color3)
|
||||
fill(plot_loband2_3, plot_loband2_4, color = color3)
|
||||
fill(plot_upband2_4, plot_upband2_5, color = color4)
|
||||
fill(plot_loband2_4, plot_loband2_5, color = color4)
|
||||
fill(plot_upband2_5, plot_upband2_6, color = color5)
|
||||
fill(plot_loband2_5, plot_loband2_6, color = color5)
|
||||
fill(plot_upband2_6, plot_upband2_7, color = color6)
|
||||
fill(plot_loband2_6, plot_loband2_7, color = color6)
|
||||
fill(plot_upband2_7, plot_upband2_8, color = color7)
|
||||
fill(plot_loband2_7, plot_loband2_8, color = color7)
|
||||
fill(plot_upband2_8, plot_upband2_9, color = color8)
|
||||
fill(plot_loband2_8, plot_loband2_9, color = color8)
|
||||
|
||||
//-----------------------
|
||||
// Plot Extension
|
||||
//-----------------------
|
||||
if displayline and enable_mtf and mtf_disp_typ == 'Always Display'
|
||||
displayline := false
|
||||
displayline
|
||||
|
||||
var line mean = na
|
||||
line.delete(mean)
|
||||
mean := displayline ? f_PriceLine(meanline, #FFCD00) : na
|
||||
var line res1 = na
|
||||
line.delete(res1)
|
||||
res1 := displayline ? f_PriceLine(upband1, color.green) : na
|
||||
var line sup1 = na
|
||||
line.delete(sup1)
|
||||
sup1 := displayline ? f_PriceLine(loband1, color.green) : na
|
||||
var line res2 = na
|
||||
line.delete(res2)
|
||||
res2 := displayline ? f_PriceLine(upband2, color.red) : na
|
||||
var line sup2 = na
|
||||
line.delete(sup2)
|
||||
sup2 := displayline ? f_PriceLine(loband2, color.red) : na
|
||||
|
||||
//--------------
|
||||
// Prep MTF Label
|
||||
//--------------
|
||||
var brl = '\n--------------------------------------'
|
||||
dist_0 = 'Distance from Mean: ' + str.tostring((close - meanline) / close * 100, '#.##') + ' %'
|
||||
dist_1 = 'Distance from Mean: ' + str.tostring((close - mtf1_meanline) / close * 100, '#.##') + ' %'
|
||||
dist_2 = 'Distance from Mean: ' + str.tostring((close - mtf2_meanline) / close * 100, '#.##') + ' %'
|
||||
|
||||
var title = 'Mean Reversion Channel\nMultiple TimeFrame Analysis' + brl
|
||||
tf0 = '\n\nTimeframe: ' + tf_0 + ' (Current)\n\nStatus: ' + get_stat(condition) + dist_0 + brl
|
||||
|
||||
tf1 = not timeframe.ismonthly ? '\n\nTimeframe: ' + tf_1 + '\n\nStatus: ' + get_stat(mtf1_condition) + dist_1 + brl : ''
|
||||
|
||||
tf2 = not timeframe.isweekly and not timeframe.ismonthly ? '\n\nTimeframe: ' + tf_2 + '\n\nStatus: ' + get_stat(mtf2_condition) + dist_2 + brl : ''
|
||||
|
||||
mtf_lbl = title + tf0 + tf1 + tf2
|
||||
var label label_mtf = na
|
||||
label.delete(label_mtf)
|
||||
label_mtf := enable_mtf ? f_MTFLabel(mtf_lbl, meanline) : na
|
||||
|
||||
//************************************************************************************************************
|
||||
// Real-time Price Labels for Extended Lines (Placed on the right side of the last candle)
|
||||
//************************************************************************************************************
|
||||
|
||||
// Define persistent label variables so that they update rather than create new labels each bar
|
||||
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 res2_9_label = na // Label for upband2_9
|
||||
var label sup2_9_label = na // Label for loband2_9
|
||||
var label res2_1_label = na // New label for upband2_1
|
||||
var label sup2_1_label = na // New label for loband2_1
|
||||
|
||||
if displayline and barstate.islast
|
||||
// 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 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.green, 0), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res1_label, bar_index, upband1)
|
||||
label.set_text(res1_label, "R1: " + format_price(upband1))
|
||||
// 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 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, 0), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res2_label, bar_index, upband2)
|
||||
label.set_text(res2_label, "R2: " + format_price(upband2))
|
||||
// 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, 0), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(sup2_label, bar_index, loband2)
|
||||
label.set_text(sup2_label, "S2: " + format_price(loband2))
|
||||
// R2_9 label (for upband2_9)
|
||||
if na(res2_9_label)
|
||||
res2_9_label := label.new(bar_index, upband2_9, "R2_9: " + format_price(upband2_9), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res2_9_label, bar_index, upband2_9)
|
||||
label.set_text(res2_9_label, "R2_9: " + format_price(upband2_9))
|
||||
// S2_9 label (for loband2_9)
|
||||
if na(sup2_9_label)
|
||||
sup2_9_label := label.new(bar_index, loband2_9, "S2_9: " + format_price(loband2_9), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(sup2_9_label, bar_index, loband2_9)
|
||||
label.set_text(sup2_9_label, "S2_9: " + format_price(loband2_9))
|
||||
// R2_1 label (New for upband2_1)
|
||||
if na(res2_1_label)
|
||||
res2_1_label := label.new(bar_index, upband2_1, "R2_1: " + format_price(upband2_1), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(res2_1_label, bar_index, upband2_1)
|
||||
label.set_text(res2_1_label, "R2_1: " + format_price(upband2_1))
|
||||
// S2_1 label (New for loband2_1)
|
||||
if na(sup2_1_label)
|
||||
sup2_1_label := label.new(bar_index, loband2_1, "S2_1: " + format_price(loband2_1), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(color.red, 50), textcolor = color.white)
|
||||
else
|
||||
label.set_xy(sup2_1_label, bar_index, loband2_1)
|
||||
label.set_text(sup2_1_label, "S2_1: " + format_price(loband2_1))
|
||||
//************************************************************************************************************
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
//************************************************************************************************************
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_r1_breakout_up = 0
|
||||
var int last_alert_s1_breakout_down = 0
|
||||
var int last_alert_range_r1_s1 = 0
|
||||
var int last_alert_above_r1 = 0
|
||||
var int last_alert_below_s1 = 0
|
||||
var int last_alert_above_mean = 0
|
||||
var int last_alert_below_mean = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 价格触碰关键位置警报
|
||||
// if ta.cross(close, meanline)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到MEAN","位置":"MEAN","信号":"mean_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, upband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到R1","位置":"R1","信号":"r1_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, loband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到S1","位置":"S1","信号":"s1_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, upband2)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到R2","位置":"R2","信号":"r2_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.cross(close, loband2)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow, "yyyy-MM-dd HH:mm:ss") + '","时间":"' + str.tostring(time, "yyyy-MM-dd HH:mm:ss") + '","事件":"碰到S2","位置":"S2","信号":"s2_touch"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// 价格区间警报
|
||||
// if close > meanline and close < upband1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN和R1之间","位置":"MEAN-R1","信号":"range_mean_r1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < meanline and close > loband1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN和S1之间","位置":"MEAN-S1","信号":"range_mean_s1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close > upband1 and close < upband2
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1和R2之间","位置":"R1-R2","信号":"range_r1_r2"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < loband1 and close > loband2
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S1和S2之间","位置":"S1-S2","信号":"range_s1_s2"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close > upband1 and close < upband2_9
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1和R2_9之间","位置":"R1-R2_9","信号":"range_r1_r2_9"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close > upband2_9 and close < upband2_1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R2_9和R2_1之间","位置":"R2_9-R2_1","信号":"range_r2_9_r2_1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < loband1 and close > loband2_9
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S1和S2_9之间","位置":"S1-S2_9","信号":"range_s1_s2_9"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// if close < loband2_9 and close > loband2_1
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S2_9和S2_1之间","位置":"S2_9-S2_1","信号":"range_s2_9_s2_1"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
|
||||
// 价格穿越警报 - 每分钟限制
|
||||
if ta.crossover(close, upband1) and current_minute > last_alert_r1_breakout_up
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿R1","位置":"R1","信号":"r1_breakout_up"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_r1_breakout_up := current_minute
|
||||
|
||||
// if ta.crossunder(close, upband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿R1","位置":"R1","信号":"r1_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
if ta.crossunder(close, loband1) and current_minute > last_alert_s1_breakout_down
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿S1","位置":"S1","信号":"s1_breakout_down"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_s1_breakout_down := current_minute
|
||||
|
||||
// if ta.crossover(close, loband1)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿S1","位置":"S1","信号":"s1_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossover(close, meanline)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿MEAN","位置":"MEAN","信号":"mean_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, meanline)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿MEAN","位置":"MEAN","信号":"mean_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossover(close, loband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿S2_9","位置":"S2_9","信号":"s2_9_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, loband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿S2_9","位置":"S2_9","信号":"s2_9_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossover(close, upband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格上穿R2_9","位置":"R2_9","信号":"r2_9_breakout_up"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// if ta.crossunder(close, upband2_9)
|
||||
// alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格下穿R2_9","位置":"R2_9","信号":"r2_9_breakout_down"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
|
||||
// ===== 新增的5个警报条件 - 每分钟限制 =====
|
||||
// 1. 价格处于R1和S1之间时
|
||||
if close <= upband1 and close >= loband1 and current_minute > last_alert_range_r1_s1
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1和S1之间","位置":"R1-S1区间","信号":"range_r1_s1"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_range_r1_s1 := current_minute
|
||||
|
||||
// 2. 价格处于R1以上时
|
||||
if close > upband1 and current_minute > last_alert_above_r1
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于R1以上","位置":"R1以上","信号":"above_r1"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_above_r1 := current_minute
|
||||
|
||||
// 3. 价格处于S1以下时
|
||||
if close < loband1 and current_minute > last_alert_below_s1
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于S1以下","位置":"S1以下","信号":"below_s1"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_below_s1 := current_minute
|
||||
|
||||
// 4. 价格处于MEAN以上时
|
||||
if close > meanline and current_minute > last_alert_above_mean
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN以上","位置":"MEAN以上","信号":"above_mean"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_above_mean := current_minute
|
||||
|
||||
// 5. 价格处于MEAN以下时
|
||||
if close < meanline and current_minute > last_alert_below_mean
|
||||
alert_message := '{"指标名称":"MRC","交易对":"' + syminfo.ticker + '","周期":"' + timeframe.period + '","MEAN":"' + str.tostring(meanline, '#.####') + '","R1":"' + str.tostring(upband1, '#.####') + '","S1":"' + str.tostring(loband1, '#.####') + '","R2":"' + str.tostring(upband2, '#.####') + '","S2":"' + str.tostring(loband2, '#.####') + '","R2_9":"' + str.tostring(upband2_9, '#.####') + '","S2_9":"' + str.tostring(loband2_9, '#.####') + '","R2_1":"' + str.tostring(upband2_1, '#.####') + '","S2_1":"' + str.tostring(loband2_1, '#.####') + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","事件":"价格处于MEAN以下","位置":"MEAN以下","信号":"below_mean"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_below_mean := current_minute
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 价格穿越警报
|
||||
alertcondition(ta.crossover(close, upband1), title = '价格上穿R1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R1","位置":"R1","信号":"r1_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband1), title = '价格下穿R1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R1","位置":"R1","信号":"r1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband1), title = '价格下穿S1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S1","位置":"S1","信号":"s1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband1), title = '价格上穿S1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S1","位置":"S1","信号":"s1_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossover(close, meanline), title = '价格上穿MEAN', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿MEAN","位置":"MEAN","信号":"mean_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, meanline), title = '价格下穿MEAN', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿MEAN","位置":"MEAN","信号":"mean_breakout_down"}')
|
||||
|
||||
// R2和S2穿越警报
|
||||
alertcondition(ta.crossover(close, upband2), title = '价格上穿R2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R2","位置":"R2","信号":"r2_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband2), title = '价格下穿R2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R2","位置":"R2","信号":"r2_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband2), title = '价格下穿S2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S2","位置":"S2","信号":"s2_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband2), title = '价格上穿S2', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S2","位置":"S2","信号":"s2_breakout_up"}')
|
||||
|
||||
// 扩展区域穿越警报
|
||||
alertcondition(ta.crossover(close, upband2_9), title = '价格上穿R2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R2_9","位置":"R2_9","信号":"r2_9_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband2_9), title = '价格下穿R2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R2_9","位置":"R2_9","信号":"r2_9_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband2_9), title = '价格下穿S2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S2_9","位置":"S2_9","信号":"s2_9_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband2_9), title = '价格上穿S2_9', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S2_9","位置":"S2_9","信号":"s2_9_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossover(close, upband2_1), title = '价格上穿R2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿R2_1","位置":"R2_1","信号":"r2_1_breakout_up"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, upband2_1), title = '价格下穿R2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿R2_1","位置":"R2_1","信号":"r2_1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, loband2_1), title = '价格下穿S2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格下穿S2_1","位置":"S2_1","信号":"s2_1_breakout_down"}')
|
||||
|
||||
alertcondition(ta.crossover(close, loband2_1), title = '价格上穿S2_1', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格上穿S2_1","位置":"S2_1","信号":"s2_1_breakout_up"}')
|
||||
|
||||
// 价格区间状态警报
|
||||
alertcondition(close <= upband1 and close >= loband1, title = '价格处于R1和S1之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R1和S1之间","位置":"R1-S1区间","信号":"range_r1_s1"}')
|
||||
|
||||
alertcondition(close > upband1, title = '价格处于R1以上', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R1以上","位置":"R1以上","信号":"above_r1"}')
|
||||
|
||||
alertcondition(close < loband1, title = '价格处于S1以下', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S1以下","位置":"S1以下","信号":"below_s1"}')
|
||||
|
||||
alertcondition(close > meanline, title = '价格处于MEAN以上', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于MEAN以上","位置":"MEAN以上","信号":"above_mean"}')
|
||||
|
||||
alertcondition(close < meanline, title = '价格处于MEAN以下', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于MEAN以下","位置":"MEAN以下","信号":"below_mean"}')
|
||||
|
||||
// 区间范围警报
|
||||
alertcondition(close > upband1 and close < upband2, title = '价格处于R1和R2之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R1和R2之间","位置":"R1-R2","信号":"range_r1_r2"}')
|
||||
|
||||
alertcondition(close < loband1 and close > loband2, title = '价格处于S1和S2之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S1和S2之间","位置":"S1-S2","信号":"range_s1_s2"}')
|
||||
|
||||
alertcondition(close > upband2 and close < upband2_1, title = '价格处于R2和R2_1之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R2和R2_1之间","位置":"R2-R2_1","信号":"range_r2_r2_1"}')
|
||||
|
||||
alertcondition(close < loband2 and close > loband2_1, title = '价格处于S2和S2_1之间', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S2和S2_1之间","位置":"S2-S2_1","信号":"range_s2_s2_1"}')
|
||||
|
||||
// 极端区域警报
|
||||
alertcondition(close > upband2_1, title = '价格处于R2_1以上', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于R2_1以上","位置":"R2_1以上","信号":"above_r2_1"}')
|
||||
|
||||
alertcondition(close < loband2_1, title = '价格处于S2_1以下', message = '{"指标名称":"MRC","交易对":"{{ticker}}","周期":"{{interval}}","MEAN":"{{plot(" Mean")}}","R1":"{{plot(" R1")}}","S1":"{{plot(" S1")}}","R2":"{{plot(" R2")}}","S2":"{{plot(" S2")}}","R2_9":"{{plot("R2_9")}}","S2_9":"{{plot("S2_9")}}","R2_1":"{{plot("R2_1")}}","S2_1":"{{plot("S2_1")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"价格处于S2_1以下","位置":"S2_1以下","信号":"below_s2_1"}')
|
||||
441
rsi.pine
Normal file
441
rsi.pine
Normal file
@@ -0,0 +1,441 @@
|
||||
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
|
||||
// © BackQuant
|
||||
//@version=6
|
||||
|
||||
indicator('Machine Learning RSI 13', 'ML RSI [13]', overlay = false, max_labels_count = 500)
|
||||
|
||||
// Define Groups
|
||||
const string rsi_g = 'Relative Strength Index'
|
||||
const string ml_t = 'Machine Learning Thresholds'
|
||||
const string opt_ = 'ML Optimization'
|
||||
const string ui = 'UI Settings'
|
||||
|
||||
// User Inputs
|
||||
// RSI Settings
|
||||
series float src = input.source(close, 'Calculation Source', group = rsi_g, inline = 'X')
|
||||
simple int rsiLength = input.int(14, 'RSI Length', minval = 2, group = rsi_g, inline = 'X')
|
||||
simple bool smooth = input.bool(true, 'Smooth RSI?', group = rsi_g, inline = 'smt')
|
||||
string maType = input.string('Ema', 'Moving Average Type', options = ['SMA', 'Hull', 'Ema', 'Wma', 'DEMA', 'RMA', 'LINREG', 'TEMA', 'ALMA', 'T3'], group = rsi_g, inline = 'smt')
|
||||
simple int smoothP = input.int(4, 'Smoothing Period', group = rsi_g)
|
||||
simple int sig = input.int(6, 'Sigma for ALMA', group = rsi_g, tooltip = 'this is only used if the ALMA is choosen in the Moving Average Type Input')
|
||||
|
||||
// Machine Learning Thresholding Settings
|
||||
simple int minThresh = input.int(10, 'Threshold Range Min', inline = 'thresh', group = ml_t)
|
||||
simple int maxThresh = input.int(90, 'Max', inline = 'thresh', group = ml_t)
|
||||
simple int step = input.int(5, 'Step', inline = 'thresh', group = ml_t)
|
||||
// Optimization Settings
|
||||
simple float perfAlpha = input.float(10, 'Performance Memory', minval = 2, tooltip = 'controls the weighting of past data or the smoothness of calculations.', group = opt_)
|
||||
simple int maxIter = input.int(1000, 'Max Clustering Steps', group = opt_)
|
||||
simple int maxData = input.int(3000, 'Max Data Points', group = opt_)
|
||||
// UI Settings
|
||||
simple bool showthres = input.bool(true, 'Show Threshold Lines?', group = ui)
|
||||
simple bool paintCandles = input.bool(false, 'Color Bars According to Trend?', group = ui)
|
||||
simple bool showSegments = input.bool(true, 'Show RSI Segments?', group = ui)
|
||||
simple bool showCounting = input.bool(true, 'Show Segment Counting?', group = ui)
|
||||
int linew = input.int(3, 'Signal Line Width', 1, 4, 1, group = ui)
|
||||
color longcol = input.color(#00ff00, 'Long Colour', group = ui, inline = 'xxxx')
|
||||
color shortcol = input.color(#ff0000, 'Short Colour', group = ui, inline = 'xxxx')
|
||||
color neucol = input.color(color.gray, 'Neutral Colour', group = ui)
|
||||
color bgCol = input.color(color.new(color.white, 0), 'Pane Background Color', group = ui)
|
||||
bgcolor(bgCol)
|
||||
|
||||
// Custom DEMA function
|
||||
dema(src, length) =>
|
||||
ema1 = ta.ema(src, length)
|
||||
ema2 = ta.ema(ema1, length)
|
||||
2 * ema1 - ema2
|
||||
|
||||
// Custom TEMA function (Triple Exponential Moving Average)
|
||||
tema(src, length) =>
|
||||
ema1 = ta.ema(src, length)
|
||||
ema2 = ta.ema(ema1, length)
|
||||
ema3 = ta.ema(ema2, length)
|
||||
3 * ema1 - 3 * ema2 + ema3
|
||||
|
||||
// Custom T3 function (Tim Tillson's T3)
|
||||
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 Function
|
||||
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)
|
||||
|
||||
|
||||
// Calculate RSI
|
||||
rsi = ta.rsi(src, rsiLength)
|
||||
// Smooth?
|
||||
if smooth == true
|
||||
rsi := ma(rsi, smoothP, maType, sig)
|
||||
rsi
|
||||
|
||||
// Populate threshold array
|
||||
var factors = array.new_float(0)
|
||||
if barstate.isfirst
|
||||
for i = minThresh to maxThresh by step
|
||||
array.push(factors, i)
|
||||
|
||||
// Clustering for RSI
|
||||
var rsi_values = array.new_float(0)
|
||||
if last_bar_index - bar_index <= maxData
|
||||
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))
|
||||
|
||||
// Initialize clusters
|
||||
var cluster1 = array.new_float(0)
|
||||
var cluster2 = array.new_float(0)
|
||||
var cluster3 = array.new_float(0)
|
||||
|
||||
// Function to compare two arrays
|
||||
f_arrays_equal(arr1, arr2) =>
|
||||
if array.size(arr1) != array.size(arr2)
|
||||
false
|
||||
else
|
||||
all_equal = true
|
||||
for i = 0 to array.size(arr1) - 1 by 1
|
||||
if array.get(arr1, i) != array.get(arr2, i)
|
||||
all_equal := false
|
||||
break
|
||||
all_equal
|
||||
|
||||
for _ = 0 to maxIter by 1
|
||||
// Reset clusters at each iteration
|
||||
cluster1 := array.new_float(0)
|
||||
cluster2 := array.new_float(0)
|
||||
cluster3 := array.new_float(0)
|
||||
|
||||
for value in rsi_values
|
||||
distances = array.new_float(3)
|
||||
for centroid in centroids
|
||||
array.push(distances, math.abs(value - centroid))
|
||||
idx = array.indexof(distances, array.min(distances))
|
||||
if idx == 0
|
||||
array.push(cluster1, value)
|
||||
else if idx == 1
|
||||
array.push(cluster2, value)
|
||||
else
|
||||
array.push(cluster3, value)
|
||||
|
||||
// Update centroids
|
||||
new_centroids = array.new_float(3)
|
||||
array.push(new_centroids, array.avg(cluster1))
|
||||
array.push(new_centroids, array.avg(cluster2))
|
||||
array.push(new_centroids, array.avg(cluster3))
|
||||
|
||||
if f_arrays_equal(new_centroids, centroids)
|
||||
break
|
||||
centroids := new_centroids
|
||||
centroids
|
||||
|
||||
// Dynamic thresholds
|
||||
long_S = array.get(centroids, 2)
|
||||
short_S = array.get(centroids, 0)
|
||||
|
||||
// RSI Segmentation and Counting Logic
|
||||
var int rsi_state = 0 // 0 = neutral, 1 = overbought, -1 = oversold
|
||||
var int prev_rsi_state = 0 // 添加前一个状态的追踪
|
||||
var int extreme_type = 0 // 1 = overbought type, -1 = oversold type, 0 = no extreme
|
||||
var int segment_count = 0 // current count for the extreme type
|
||||
|
||||
// Alert trigger variables
|
||||
var bool overbought_repeat_alert = false
|
||||
var bool oversold_repeat_alert = false
|
||||
var bool overbought_mark2_alert = false // NEW: specific alert for mark 2
|
||||
var bool oversold_mark2_alert = false // NEW: specific alert for mark -2
|
||||
|
||||
// Determine current RSI state
|
||||
current_state = rsi > long_S ? 1 : rsi < short_S ? -1 : 0
|
||||
|
||||
// Track state changes and update counting
|
||||
if current_state != rsi_state and not na(rsi)
|
||||
|
||||
// 确定分段线颜色
|
||||
segment_color = color.black // 默认颜色
|
||||
|
||||
if prev_rsi_state == 0 and current_state == 1
|
||||
segment_color := color.new(color.red, 0) // 从中性区进入超买区 - 红色
|
||||
else if prev_rsi_state == 0 and current_state == -1
|
||||
segment_color := color.new(color.blue, 0) // 从中性区进入超卖区 - 蓝色
|
||||
else if prev_rsi_state == 1 and current_state == 0
|
||||
segment_color := color.new(color.orange, 0) // 从超买区进入中性区 - 橙色
|
||||
else if prev_rsi_state == -1 and current_state == 0
|
||||
segment_color := color.new(color.green, 0) // 从超卖区进入中性区 - 绿色
|
||||
else if prev_rsi_state == 1 and current_state == -1
|
||||
segment_color := color.new(color.purple, 0) // 从超买区直接到超卖区 - 紫色
|
||||
else if prev_rsi_state == -1 and current_state == 1
|
||||
segment_color := color.new(color.yellow, 0) // 从超卖区直接到超买区 - 黄色
|
||||
else if prev_rsi_state == 1 and current_state == 1
|
||||
segment_color := color.new(color.maroon, 0) // 超买区内的重复进入 - 深红色
|
||||
else if prev_rsi_state == -1 and current_state == -1
|
||||
segment_color := color.new(color.navy, 0) // 超卖区内的重复进入 - 深蓝色
|
||||
|
||||
// Draw vertical line at state transition points with color coding
|
||||
if showSegments
|
||||
line.new(bar_index, 0, bar_index, 100,
|
||||
color = segment_color,
|
||||
width = 2, // 增加线宽以便更好地看到颜色
|
||||
style = line.style_solid,
|
||||
extend = extend.none)
|
||||
|
||||
// 更新前一个状态
|
||||
prev_rsi_state := rsi_state
|
||||
|
||||
// Reset alert triggers
|
||||
overbought_repeat_alert := false
|
||||
oversold_repeat_alert := false
|
||||
overbought_mark2_alert := false // NEW: reset specific mark alerts
|
||||
oversold_mark2_alert := false // NEW: reset specific mark alerts
|
||||
|
||||
// Update counting logic
|
||||
if current_state == 1 // Entering overbought
|
||||
if extreme_type != 1 // If previous extreme type was not overbought
|
||||
extreme_type := 1
|
||||
segment_count := 1 // Reset to 1
|
||||
else // Same extreme type, increment
|
||||
segment_count := segment_count + 1
|
||||
|
||||
// Check for repeat alert trigger (count >= 2)
|
||||
if segment_count >= 2
|
||||
overbought_repeat_alert := true
|
||||
|
||||
// NEW: Check for specific mark 2 alert
|
||||
if segment_count == 2
|
||||
overbought_mark2_alert := true
|
||||
|
||||
// Display count label
|
||||
if showCounting
|
||||
label.new(bar_index, rsi,
|
||||
text = str.tostring(segment_count),
|
||||
style = label.style_label_down,
|
||||
color = longcol,
|
||||
textcolor = color.white,
|
||||
size = size.small)
|
||||
|
||||
else if current_state == -1 // Entering oversold
|
||||
if extreme_type != -1 // If previous extreme type was not oversold
|
||||
extreme_type := -1
|
||||
segment_count := -1 // Reset to -1
|
||||
else // Same extreme type, decrement
|
||||
segment_count := segment_count - 1
|
||||
|
||||
// Check for repeat alert trigger (count <= -2)
|
||||
if segment_count <= -2
|
||||
oversold_repeat_alert := true
|
||||
|
||||
// NEW: Check for specific mark -2 alert
|
||||
if segment_count == -2
|
||||
oversold_mark2_alert := true
|
||||
|
||||
// Display count label
|
||||
if showCounting
|
||||
label.new(bar_index, rsi,
|
||||
text = str.tostring(segment_count),
|
||||
style = label.style_label_up,
|
||||
color = shortcol,
|
||||
textcolor = color.white,
|
||||
size = size.small)
|
||||
|
||||
// Update state
|
||||
rsi_state := current_state
|
||||
|
||||
// RSI变化计算 - 计算RSI相对于前一个K线的变化
|
||||
rsi_change = not na(rsi[1]) ? rsi - rsi[1] : 0
|
||||
rsi_direction = rsi_change > 0 ? "升高" : rsi_change < 0 ? "降低" : "持平"
|
||||
rsi_change_value = str.tostring(rsi_change, '#.##')
|
||||
|
||||
// Create plot outputs for alert messages
|
||||
plot(segment_count, 'Segment Count', display = display.none)
|
||||
plot(overbought_repeat_alert ? 1 : 0, 'Overbought Repeat', display = display.none)
|
||||
plot(oversold_repeat_alert ? 1 : 0, 'Oversold Repeat', display = display.none)
|
||||
plot(overbought_mark2_alert ? 1 : 0, 'Overbought Mark2', display = display.none) // NEW
|
||||
plot(oversold_mark2_alert ? 1 : 0, 'Oversold Mark2', display = display.none) // NEW
|
||||
plot(rsi_change, 'RSI Change', display = display.none) // 添加RSI变化的plot输出
|
||||
|
||||
// Cluster plotting arrays
|
||||
var float cluster1_plot = na
|
||||
var float cluster2_plot = na
|
||||
var float cluster3_plot = na
|
||||
|
||||
if not na(rsi)
|
||||
distances = array.new_float(3)
|
||||
for centroid in centroids
|
||||
array.push(distances, math.abs(rsi - centroid))
|
||||
idx = array.indexof(distances, array.min(distances))
|
||||
cluster1_plot := idx == 0 ? rsi : na
|
||||
cluster2_plot := idx == 1 ? rsi : na
|
||||
cluster3_plot := idx == 2 ? rsi : na
|
||||
cluster3_plot
|
||||
|
||||
// --- Visualization ---
|
||||
col = rsi > long_S ? longcol : rsi < short_S ? shortcol : neucol
|
||||
|
||||
plot(rsi, 'RSI', color = col, linewidth = math.max(1, linew)) // Main RSI line
|
||||
|
||||
// Dynamic thresholds via Machine Learning
|
||||
plot(showthres ? long_S : na, 'Long ML Threshold', color = longcol)
|
||||
plot(showthres ? short_S : na, 'Short ML Threshold', color = shortcol)
|
||||
|
||||
// Plot RSI values in clusters
|
||||
plot(cluster1_plot, 'Cluster 1', color = color.green, linewidth = 2, style = plot.style_circles)
|
||||
plot(cluster2_plot, 'Cluster 2', color = color.orange, linewidth = 2, style = plot.style_circles)
|
||||
plot(cluster3_plot, 'Cluster 3', color = color.red, linewidth = 2, style = plot.style_circles)
|
||||
|
||||
barcolor(paintCandles ? col : na)
|
||||
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_rsi_buy = 0
|
||||
var int last_alert_rsi_sell = 0
|
||||
var int last_alert_rsi_neutral_from_ob = 0
|
||||
var int last_alert_rsi_neutral_from_os = 0
|
||||
var int last_alert_overbought_repeat = 0
|
||||
var int last_alert_oversold_repeat = 0
|
||||
var int last_alert_overbought_mark2 = 0
|
||||
var int last_alert_oversold_mark2 = 0
|
||||
var int last_alert_rsi_overbought = 0
|
||||
var int last_alert_rsi_oversold = 0
|
||||
var int last_alert_rsi_neutral = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 基础穿越信号 - 每分钟限制
|
||||
if ta.crossover(rsi, long_S) and current_minute > last_alert_rsi_buy
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(long_S, '#.##') + '","事件":"RSI 已上穿多头ML阈值 - 潜在买入信号","信号":"buy"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_rsi_buy := current_minute
|
||||
|
||||
if ta.crossunder(rsi, short_S) and current_minute > last_alert_rsi_sell
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(short_S, '#.##') + '","事件":"RSI 已下穿空头ML阈值 - 潜在卖出信号","信号":"sell"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_rsi_sell := current_minute
|
||||
|
||||
// 区域转换信号 - 每分钟限制
|
||||
// if ta.crossunder(rsi, long_S) and current_minute > last_alert_rsi_neutral_from_ob
|
||||
// alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(long_S, '#.##') + '","事件":"RSI 已下穿多头ML阈值进入中性区","备注":"进入震荡"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_rsi_neutral_from_ob := current_minute
|
||||
|
||||
// if ta.crossover(rsi, short_S) and current_minute > last_alert_rsi_neutral_from_os
|
||||
// alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(short_S, '#.##') + '","事件":"RSI 已上穿空头ML阈值进入中性区","备注":"进入震荡"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_rsi_neutral_from_os := current_minute
|
||||
|
||||
// 重复进入信号 - 每分钟限制
|
||||
if overbought_repeat_alert and current_minute > last_alert_overbought_repeat
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(long_S, '#.##') + '","事件":"RSI 重复进入超买区","标记":"' + str.tostring(segment_count) + '","信号":"overbought_repeat","警告":"大于和等于2次超买信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_overbought_repeat := current_minute
|
||||
|
||||
if oversold_repeat_alert and current_minute > last_alert_oversold_repeat
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(short_S, '#.##') + '","事件":"RSI 重复进入超卖区","标记":"' + str.tostring(segment_count) + '","信号":"oversold_repeat","警告":"大于和等于2次超卖信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_oversold_repeat := current_minute
|
||||
|
||||
// 特定标记信号 - 每分钟限制
|
||||
if overbought_mark2_alert and current_minute > last_alert_overbought_mark2
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(long_S, '#.##') + '","事件":"RSI 第二次进入超买区","标记":"2","信号":"overbought_mark2","警告":"二次超买信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_overbought_mark2 := current_minute
|
||||
|
||||
if oversold_mark2_alert and current_minute > last_alert_oversold_mark2
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(short_S, '#.##') + '","事件":"RSI 第二次进入超卖区","标记":"-2","信号":"oversold_mark2","警告":"二次超卖信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_oversold_mark2 := current_minute
|
||||
|
||||
// RSI状态警报 - 每分钟限制
|
||||
if rsi > long_S and current_minute > last_alert_rsi_overbought
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","超买阈值":"' + str.tostring(long_S, '#.##') + '","事件":"RSI处于超买状态","RSI变化":"' + rsi_direction + '","RSI变化值":"' + rsi_change_value + '","标记":"' + str.tostring(segment_count) + '","信号":"rsi_overbought","备注":"RSI高于超买线"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_rsi_overbought := current_minute
|
||||
|
||||
if rsi < short_S and current_minute > last_alert_rsi_oversold
|
||||
alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","超卖阈值":"' + str.tostring(short_S, '#.##') + '","事件":"RSI处于超卖状态","RSI变化":"' + rsi_direction + '","RSI变化值":"' + rsi_change_value + '","标记":"' + str.tostring(segment_count) + '","信号":"rsi_oversold","备注":"RSI低于超卖线"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_rsi_oversold := current_minute
|
||||
|
||||
// if rsi < long_S and rsi > short_S and current_minute > last_alert_rsi_neutral
|
||||
// alert_message := '{"指标名称":"RSI","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(long_S, '#.##') + '","Short ML Threshold":"' + str.tostring(short_S, '#.##') + '","事件":"RSI 处于中性区","备注":"震荡"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar)
|
||||
// last_alert_rsi_neutral := current_minute
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(rsi, title = 'RSI值', display = display.none)
|
||||
plot(long_S, title = 'Long ML Threshold', display = display.none)
|
||||
plot(short_S, title = 'Short ML Threshold', display = display.none)
|
||||
|
||||
// 基础穿越信号警报
|
||||
alertcondition(ta.crossover(rsi, long_S), title = 'RSI上穿多头ML阈值', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 已上穿多头ML阈值 - 潜在买入信号","信号":"buy"}')
|
||||
|
||||
alertcondition(ta.crossunder(rsi, short_S), title = 'RSI下穿空头ML阈值', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 已下穿空头ML阈值 - 潜在卖出信号","信号":"sell"}')
|
||||
|
||||
// 区域转换信号警报
|
||||
// alertcondition(ta.crossunder(rsi, long_S), title = 'RSI下穿多头ML阈值进入中性区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 已下穿多头ML阈值进入中性区","备注":"进入震荡","信号":"neutral_from_overbought"}')
|
||||
|
||||
// alertcondition(ta.crossover(rsi, short_S), title = 'RSI上穿空头ML阈值进入中性区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 已上穿空头ML阈值进入中性区","备注":"进入震荡","信号":"neutral_from_oversold"}')
|
||||
|
||||
// 重复进入信号警报
|
||||
alertcondition(overbought_repeat_alert, title = 'RSI重复进入超买区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 重复进入超买区","标记":"{{plot("Segment Count")}}","信号":"overbought_repeat","警告":"大于和等于2次超买信号"}')
|
||||
|
||||
alertcondition(oversold_repeat_alert, title = 'RSI重复进入超卖区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 重复进入超卖区","标记":"{{plot("Segment Count")}}","信号":"oversold_repeat","警告":"大于和等于2次超卖信号"}')
|
||||
|
||||
// 特定标记信号警报
|
||||
alertcondition(overbought_mark2_alert, title = 'RSI第二次进入超买区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 第二次进入超买区","标记":"2","信号":"overbought_mark2","警告":"二次超买信号"}')
|
||||
|
||||
alertcondition(oversold_mark2_alert, title = 'RSI第二次进入超卖区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 第二次进入超卖区","标记":"-2","信号":"oversold_mark2","警告":"二次超卖信号"}')
|
||||
|
||||
// RSI状态警报
|
||||
alertcondition(rsi > long_S, title = 'RSI处于超买状态', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","超买阈值":"{{plot("Long ML Threshold")}}","事件":"RSI处于超买状态","标记":"{{plot("Segment Count")}}","信号":"rsi_overbought","备注":"RSI高于超买线"}')
|
||||
|
||||
alertcondition(rsi < short_S, title = 'RSI处于超卖状态', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","超卖阈值":"{{plot("Short ML Threshold")}}","事件":"RSI处于超卖状态","标记":"{{plot("Segment Count")}}","信号":"rsi_oversold","备注":"RSI低于超卖线"}')
|
||||
|
||||
alertcondition(rsi < long_S and rsi > short_S, title = 'RSI处于中性区', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 处于中性区","备注":"震荡","信号":"rsi_neutral"}')
|
||||
|
||||
// 传统RSI阈值警报(70/30)
|
||||
// alertcondition(ta.crossover(rsi, 70), title = 'RSI上穿70', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","阈值":"70","事件":"RSI上穿70","信号":"rsi_70_cross_up","备注":"传统超买信号"}')
|
||||
|
||||
// alertcondition(ta.crossunder(rsi, 30), title = 'RSI下穿30', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","阈值":"30","事件":"RSI下穿30","信号":"rsi_30_cross_down","备注":"传统超卖信号"}')
|
||||
|
||||
// alertcondition(ta.crossunder(rsi, 70), title = 'RSI下穿70', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","阈值":"70","事件":"RSI下穿70","信号":"rsi_70_cross_down","备注":"从超买区回落"}')
|
||||
|
||||
// alertcondition(ta.crossover(rsi, 30), title = 'RSI上穿30', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","阈值":"30","事件":"RSI上穿30","信号":"rsi_30_cross_up","备注":"从超卖区反弹"}')
|
||||
|
||||
// // RSI中线穿越警报(50)
|
||||
// alertcondition(ta.crossover(rsi, 50), title = 'RSI上穿50', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","中线":"50","事件":"RSI上穿50","信号":"rsi_50_cross_up","备注":"多头信号"}')
|
||||
|
||||
// alertcondition(ta.crossunder(rsi, 50), title = 'RSI下穿50', message = '{"指标名称":"RSI","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI值")}}","中线":"50","事件":"RSI下穿50","信号":"rsi_50_cross_down","备注":"空头信号"}')
|
||||
637
rsi2.pine
Normal file
637
rsi2.pine
Normal file
@@ -0,0 +1,637 @@
|
||||
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
|
||||
// © BackQuant - Optimized Version
|
||||
//@version=6
|
||||
|
||||
indicator('Optimized ML RSI Pro', 'ML RSI Pro', overlay = false, max_labels_count = 500)
|
||||
|
||||
// ===== PARAMETER GROUPS =====
|
||||
const string rsi_g = 'RSI Settings'
|
||||
const string ml_g = 'Machine Learning'
|
||||
const string opt_g = 'Optimization'
|
||||
const string filter_g = 'Signal Filters'
|
||||
const string ui_g = 'UI & Alerts'
|
||||
const string preset_g = 'Preset Modes'
|
||||
|
||||
// ===== PRESET MODES =====
|
||||
string preset_mode = input.string('Custom', 'Preset Mode',
|
||||
options = ['Conservative', 'Balanced', 'Aggressive', 'Custom'],
|
||||
group = preset_g, tooltip = 'Choose a preset or use Custom for manual settings')
|
||||
|
||||
// ===== RSI SETTINGS =====
|
||||
series float src = input.source(close, 'Source', group = rsi_g, inline = 'rsi1')
|
||||
simple int rsi_length = input.int(14, 'RSI Length', minval = 2, maxval = 50, group = rsi_g, inline = 'rsi1')
|
||||
simple bool enable_smooth = input.bool(true, 'Enable Smoothing', group = rsi_g, inline = 'smooth1')
|
||||
string ma_type = input.string('EMA', 'MA Type',
|
||||
options = ['SMA', 'EMA', 'RMA', 'WMA', 'HMA'], group = rsi_g, inline = 'smooth1')
|
||||
simple int smooth_length = input.int(3, 'Smooth Length', minval = 2, maxval = 10, group = rsi_g)
|
||||
|
||||
// ===== MACHINE LEARNING SETTINGS =====
|
||||
simple int lookback_bars = input.int(500, 'Lookback Period', minval = 100, maxval = 2000,
|
||||
group = ml_g, tooltip = 'Number of bars for ML analysis (reduced from 3000 for better performance)')
|
||||
simple int update_frequency = input.int(5, 'Update Every N Bars', minval = 1, maxval = 20,
|
||||
group = ml_g, tooltip = 'Update ML thresholds every N bars to improve performance')
|
||||
simple int max_iterations = input.int(50, 'Max Iterations', minval = 10, maxval = 200,
|
||||
group = ml_g, tooltip = 'Maximum clustering iterations (reduced from 1000)')
|
||||
simple float convergence_threshold = input.float(0.1, 'Convergence Threshold', minval = 0.01, maxval = 1.0,
|
||||
group = ml_g, tooltip = 'Stop clustering when centroids change less than this value')
|
||||
|
||||
// ===== OPTIMIZATION SETTINGS =====
|
||||
simple bool enable_outlier_filter = input.bool(true, 'Filter Outliers', group = opt_g)
|
||||
simple float outlier_threshold = input.float(2.0, 'Outlier Threshold (Std Dev)', minval = 1.0, maxval = 3.0, group = opt_g)
|
||||
simple bool enable_weighted_data = input.bool(true, 'Weight Recent Data', group = opt_g)
|
||||
simple float weight_decay = input.float(0.95, 'Weight Decay Factor', minval = 0.8, maxval = 0.99, group = opt_g)
|
||||
|
||||
// ===== SIGNAL FILTERS =====
|
||||
simple bool enable_trend_filter = input.bool(true, 'Enable Trend Filter', group = filter_g)
|
||||
simple int trend_length = input.int(50, 'Trend MA Length', minval = 20, maxval = 200, group = filter_g)
|
||||
simple bool enable_volume_filter = input.bool(false, 'Enable Volume Filter', group = filter_g)
|
||||
simple float volume_threshold = input.float(1.2, 'Volume Threshold (x Average)', minval = 0.5, maxval = 3.0, group = filter_g)
|
||||
|
||||
// ===== UI & ALERT SETTINGS =====
|
||||
simple bool show_thresholds = input.bool(true, 'Show Threshold Lines', group = ui_g)
|
||||
simple bool show_signals = input.bool(true, 'Show Signal Markers', group = ui_g)
|
||||
simple bool show_statistics = input.bool(false, 'Show Statistics Table', group = ui_g)
|
||||
simple bool enable_alerts = input.bool(true, 'Enable Alerts', group = ui_g)
|
||||
color bull_color = input.color(#00ff88, 'Bull Color', group = ui_g, inline = 'colors')
|
||||
color bear_color = input.color(#ff4444, 'Bear Color', group = ui_g, inline = 'colors')
|
||||
color neutral_color = input.color(#888888, 'Neutral Color', group = ui_g, inline = 'colors')
|
||||
|
||||
// ===== PRESET CONFIGURATIONS =====
|
||||
[preset_lookback, preset_update_freq, preset_max_iter, preset_conv_thresh] = switch preset_mode
|
||||
'Conservative' => [800, 10, 30, 0.2]
|
||||
'Balanced' => [500, 5, 50, 0.1]
|
||||
'Aggressive' => [300, 3, 80, 0.05]
|
||||
=> [lookback_bars, update_frequency, max_iterations, convergence_threshold]
|
||||
|
||||
// Apply preset values if not custom mode
|
||||
final_lookback = preset_mode != 'Custom' ? preset_lookback : lookback_bars
|
||||
final_update_freq = preset_mode != 'Custom' ? preset_update_freq : update_frequency
|
||||
final_max_iter = preset_mode != 'Custom' ? preset_max_iter : max_iterations
|
||||
final_conv_thresh = preset_mode != 'Custom' ? preset_conv_thresh : convergence_threshold
|
||||
|
||||
// ===== HELPER FUNCTIONS =====
|
||||
|
||||
// Enhanced Moving Average Function
|
||||
f_ma(src, length, ma_type) =>
|
||||
switch ma_type
|
||||
'SMA' => ta.sma(src, length)
|
||||
'EMA' => ta.ema(src, length)
|
||||
'RMA' => ta.rma(src, length)
|
||||
'WMA' => ta.wma(src, length)
|
||||
'HMA' => ta.hma(src, length)
|
||||
=> ta.ema(src, length)
|
||||
|
||||
// Outlier Detection Function
|
||||
f_is_outlier(value, data_array, threshold) =>
|
||||
if array.size(data_array) < 10
|
||||
false
|
||||
else
|
||||
mean_val = array.avg(data_array)
|
||||
std_dev = array.stdev(data_array)
|
||||
math.abs(value - mean_val) > threshold * std_dev
|
||||
|
||||
// Weighted Average Function
|
||||
f_weighted_avg(data_array, weight_decay) =>
|
||||
if array.size(data_array) == 0
|
||||
na
|
||||
else
|
||||
weighted_sum = 0.0
|
||||
weight_sum = 0.0
|
||||
size = array.size(data_array)
|
||||
for i = 0 to size - 1
|
||||
weight = math.pow(weight_decay, size - 1 - i)
|
||||
weighted_sum := weighted_sum + array.get(data_array, i) * weight
|
||||
weight_sum := weight_sum + weight
|
||||
weighted_sum / weight_sum
|
||||
|
||||
// Enhanced K-means Clustering Function
|
||||
f_enhanced_kmeans(data_array, max_iter, conv_thresh) =>
|
||||
size = array.size(data_array)
|
||||
if size < 10
|
||||
[na, na, na]
|
||||
else
|
||||
// Initialize centroids using percentiles
|
||||
c1 = array.percentile_linear_interpolation(data_array, 20)
|
||||
c2 = array.percentile_linear_interpolation(data_array, 50)
|
||||
c3 = array.percentile_linear_interpolation(data_array, 80)
|
||||
|
||||
// Iterative clustering with early convergence
|
||||
for iteration = 0 to max_iter - 1
|
||||
cluster1 = array.new_float()
|
||||
cluster2 = array.new_float()
|
||||
cluster3 = array.new_float()
|
||||
|
||||
// Assign points to clusters
|
||||
for i = 0 to size - 1
|
||||
value = array.get(data_array, i)
|
||||
d1 = math.abs(value - c1)
|
||||
d2 = math.abs(value - c2)
|
||||
d3 = math.abs(value - c3)
|
||||
|
||||
if d1 <= d2 and d1 <= d3
|
||||
array.push(cluster1, value)
|
||||
else if d2 <= d3
|
||||
array.push(cluster2, value)
|
||||
else
|
||||
array.push(cluster3, value)
|
||||
|
||||
// Calculate new centroids
|
||||
new_c1 = array.size(cluster1) > 0 ?
|
||||
(enable_weighted_data ? f_weighted_avg(cluster1, weight_decay) : array.avg(cluster1)) : c1
|
||||
new_c2 = array.size(cluster2) > 0 ?
|
||||
(enable_weighted_data ? f_weighted_avg(cluster2, weight_decay) : array.avg(cluster2)) : c2
|
||||
new_c3 = array.size(cluster3) > 0 ?
|
||||
(enable_weighted_data ? f_weighted_avg(cluster3, weight_decay) : array.avg(cluster3)) : c3
|
||||
|
||||
// Check convergence
|
||||
if math.abs(new_c1 - c1) < conv_thresh and
|
||||
math.abs(new_c2 - c2) < conv_thresh and
|
||||
math.abs(new_c3 - c3) < conv_thresh
|
||||
break
|
||||
|
||||
c1 := new_c1
|
||||
c2 := new_c2
|
||||
c3 := new_c3
|
||||
|
||||
[c1, c2, c3]
|
||||
|
||||
// ===== MAIN CALCULATIONS =====
|
||||
|
||||
// Calculate RSI
|
||||
rsi_raw = ta.rsi(src, rsi_length)
|
||||
rsi = enable_smooth ? f_ma(rsi_raw, smooth_length, ma_type) : rsi_raw
|
||||
|
||||
// Data collection with performance optimization
|
||||
var rsi_data = array.new_float()
|
||||
var int last_update_bar = 0
|
||||
|
||||
// Update data array periodically
|
||||
if bar_index % final_update_freq == 0 or barstate.islast
|
||||
// Add current RSI value
|
||||
if not na(rsi)
|
||||
// Apply outlier filter if enabled
|
||||
if enable_outlier_filter and f_is_outlier(rsi, rsi_data, outlier_threshold)
|
||||
// Skip outlier
|
||||
na
|
||||
else
|
||||
array.push(rsi_data, rsi)
|
||||
|
||||
// Maintain data size
|
||||
while array.size(rsi_data) > final_lookback
|
||||
array.shift(rsi_data)
|
||||
|
||||
last_update_bar := bar_index
|
||||
|
||||
// Calculate dynamic thresholds using enhanced clustering
|
||||
[oversold_threshold, neutral_center, overbought_threshold] = f_enhanced_kmeans(rsi_data, final_max_iter, final_conv_thresh)
|
||||
|
||||
// Fallback to traditional levels if clustering fails
|
||||
final_oversold = na(oversold_threshold) ? 30 : oversold_threshold
|
||||
final_overbought = na(overbought_threshold) ? 70 : overbought_threshold
|
||||
|
||||
// ===== SIGNAL GENERATION =====
|
||||
|
||||
// Basic signals
|
||||
rsi_oversold = rsi < final_oversold
|
||||
rsi_overbought = rsi > final_overbought
|
||||
rsi_neutral = not rsi_oversold and not rsi_overbought
|
||||
|
||||
// ===== RSI SEGMENTATION AND COUNTING LOGIC (from original) =====
|
||||
var int rsi_state = 0 // 0 = neutral, 1 = overbought, -1 = oversold
|
||||
var int prev_rsi_state = 0
|
||||
var int extreme_type = 0 // 1 = overbought type, -1 = oversold type, 0 = no extreme
|
||||
var int segment_count = 0 // current count for the extreme type
|
||||
|
||||
// Alert trigger variables
|
||||
var bool overbought_repeat_alert = false
|
||||
var bool oversold_repeat_alert = false
|
||||
var bool overbought_mark2_alert = false
|
||||
var bool oversold_mark2_alert = false
|
||||
|
||||
// Determine current RSI state
|
||||
current_state = rsi > final_overbought ? 1 : rsi < final_oversold ? -1 : 0
|
||||
|
||||
// Track state changes and update counting
|
||||
if current_state != rsi_state and not na(rsi)
|
||||
// Update previous state
|
||||
prev_rsi_state := rsi_state
|
||||
|
||||
// Reset alert triggers
|
||||
overbought_repeat_alert := false
|
||||
oversold_repeat_alert := false
|
||||
overbought_mark2_alert := false
|
||||
oversold_mark2_alert := false
|
||||
|
||||
// Update counting logic
|
||||
if current_state == 1 // Entering overbought
|
||||
if extreme_type != 1 // If previous extreme type was not overbought
|
||||
extreme_type := 1
|
||||
segment_count := 1 // Reset to 1
|
||||
else // Same extreme type, increment
|
||||
segment_count := segment_count + 1
|
||||
|
||||
// Check for repeat alert trigger (count >= 2)
|
||||
if segment_count >= 2
|
||||
overbought_repeat_alert := true
|
||||
|
||||
// Check for specific mark 2 alert
|
||||
if segment_count == 2
|
||||
overbought_mark2_alert := true
|
||||
|
||||
// Display count label
|
||||
if show_signals
|
||||
label.new(bar_index, rsi,
|
||||
text = str.tostring(segment_count),
|
||||
style = label.style_label_down,
|
||||
color = bear_color,
|
||||
textcolor = color.white,
|
||||
size = size.small)
|
||||
|
||||
else if current_state == -1 // Entering oversold
|
||||
if extreme_type != -1 // If previous extreme type was not oversold
|
||||
extreme_type := -1
|
||||
segment_count := -1 // Reset to -1
|
||||
else // Same extreme type, decrement
|
||||
segment_count := segment_count - 1
|
||||
|
||||
// Check for repeat alert trigger (count <= -2)
|
||||
if segment_count <= -2
|
||||
oversold_repeat_alert := true
|
||||
|
||||
// Check for specific mark -2 alert
|
||||
if segment_count == -2
|
||||
oversold_mark2_alert := true
|
||||
|
||||
// Display count label
|
||||
if show_signals
|
||||
label.new(bar_index, rsi,
|
||||
text = str.tostring(segment_count),
|
||||
style = label.style_label_up,
|
||||
color = bull_color,
|
||||
textcolor = color.white,
|
||||
size = size.small)
|
||||
|
||||
// Update state
|
||||
rsi_state := current_state
|
||||
|
||||
// Enhanced signals with filters
|
||||
trend_ma = f_ma(close, trend_length, 'EMA')
|
||||
is_uptrend = enable_trend_filter ? close > trend_ma : true
|
||||
is_downtrend = enable_trend_filter ? close < trend_ma : true
|
||||
|
||||
volume_avg = ta.sma(volume, 20)
|
||||
is_high_volume = enable_volume_filter ? volume > volume_threshold * volume_avg : true
|
||||
|
||||
// Final filtered signals
|
||||
buy_signal = ta.crossover(rsi, final_oversold) and is_uptrend and is_high_volume
|
||||
sell_signal = ta.crossunder(rsi, final_overbought) and is_downtrend and is_high_volume
|
||||
|
||||
// ===== VISUALIZATION =====
|
||||
|
||||
// RSI line with dynamic coloring
|
||||
rsi_color = rsi_overbought ? bear_color : rsi_oversold ? bull_color : neutral_color
|
||||
plot(rsi, 'RSI', color = rsi_color, linewidth = 2)
|
||||
|
||||
// Dynamic threshold lines
|
||||
plot(show_thresholds ? final_overbought : na, 'Overbought', color = bear_color, style = plot.style_line)
|
||||
plot(show_thresholds ? final_oversold : na, 'Oversold', color = bull_color, style = plot.style_line)
|
||||
plot(show_thresholds and not na(neutral_center) ? neutral_center : na, 'Neutral', color = neutral_color, style = plot.style_line)
|
||||
|
||||
// Signal markers
|
||||
plotshape(show_signals and buy_signal, 'Buy Signal', shape.triangleup, location.bottom, bull_color, size = size.small)
|
||||
plotshape(show_signals and sell_signal, 'Sell Signal', shape.triangledown, location.top, bear_color, size = size.small)
|
||||
|
||||
// Reference lines
|
||||
hline(50, 'Midline', color = color.gray, linestyle = hline.style_solid)
|
||||
hline(70, 'Traditional OB', color = color.new(color.red, 50), linestyle = hline.style_dotted)
|
||||
hline(30, 'Traditional OS', color = color.new(color.green, 50), linestyle = hline.style_dotted)
|
||||
|
||||
// ===== STATISTICS TABLE =====
|
||||
if show_statistics and barstate.islast
|
||||
var table stats_table = table.new(position.top_right, 2, 6, bgcolor = color.white, border_width = 1)
|
||||
table.cell(stats_table, 0, 0, 'Metric', text_color = color.black, bgcolor = color.gray)
|
||||
table.cell(stats_table, 1, 0, 'Value', text_color = color.black, bgcolor = color.gray)
|
||||
table.cell(stats_table, 0, 1, 'Current RSI', text_color = color.black)
|
||||
table.cell(stats_table, 1, 1, str.tostring(rsi, '#.##'), text_color = color.black)
|
||||
table.cell(stats_table, 0, 2, 'Oversold Level', text_color = color.black)
|
||||
table.cell(stats_table, 1, 2, str.tostring(final_oversold, '#.##'), text_color = color.black)
|
||||
table.cell(stats_table, 0, 3, 'Overbought Level', text_color = color.black)
|
||||
table.cell(stats_table, 1, 3, str.tostring(final_overbought, '#.##'), text_color = color.black)
|
||||
table.cell(stats_table, 0, 4, 'Data Points', text_color = color.black)
|
||||
table.cell(stats_table, 1, 4, str.tostring(array.size(rsi_data)), text_color = color.black)
|
||||
table.cell(stats_table, 0, 5, 'Mode', text_color = color.black)
|
||||
table.cell(stats_table, 1, 5, preset_mode, text_color = color.black)
|
||||
|
||||
// ===== ADVANCED FEATURES (moved before alerts) =====
|
||||
|
||||
// Multi-timeframe RSI analysis
|
||||
rsi_htf = request.security(syminfo.tickerid, '1D', rsi, lookahead = barmerge.lookahead_off)
|
||||
htf_trend = rsi_htf > 50 ? 1 : rsi_htf < 50 ? -1 : 0
|
||||
|
||||
// Divergence Detection Functions
|
||||
f_find_pivot_high(src, length) =>
|
||||
ph = ta.pivothigh(src, length, length)
|
||||
ph
|
||||
|
||||
f_find_pivot_low(src, length) =>
|
||||
pl = ta.pivotlow(src, length, length)
|
||||
pl
|
||||
|
||||
// Divergence variables
|
||||
var float last_high_price = na
|
||||
var float last_high_rsi = na
|
||||
var float last_low_price = na
|
||||
var float last_low_rsi = na
|
||||
var int last_high_bar = na
|
||||
var int last_low_bar = na
|
||||
|
||||
// Calculate pivot points on each bar for consistency
|
||||
pivot_high = f_find_pivot_high(close, 5)
|
||||
pivot_low = f_find_pivot_low(close, 5)
|
||||
|
||||
// Update pivot points
|
||||
if not na(pivot_high)
|
||||
last_high_price := pivot_high
|
||||
last_high_rsi := rsi[5]
|
||||
last_high_bar := bar_index[5]
|
||||
|
||||
if not na(pivot_low)
|
||||
last_low_price := pivot_low
|
||||
last_low_rsi := rsi[5]
|
||||
last_low_bar := bar_index[5]
|
||||
|
||||
// Detect divergences
|
||||
bullish_divergence = not na(last_low_price) and not na(last_low_rsi) and close < last_low_price and rsi > last_low_rsi and bar_index - last_low_bar < 50
|
||||
|
||||
bearish_divergence = not na(last_high_price) and not na(last_high_rsi) and close > last_high_price and rsi < last_high_rsi and bar_index - last_high_bar < 50
|
||||
|
||||
// RSI Momentum and Velocity
|
||||
rsi_momentum = rsi - rsi[1]
|
||||
rsi_velocity = rsi_momentum - rsi_momentum[1]
|
||||
rsi_acceleration = rsi_velocity - rsi_velocity[1]
|
||||
|
||||
// Dynamic position sizing based on RSI strength
|
||||
rsi_strength = math.abs(rsi - 50) / 50
|
||||
position_size_factor = rsi_strength > 0.4 ? 1.5 : rsi_strength > 0.2 ? 1.0 : 0.5
|
||||
|
||||
// Enhanced signal scoring system
|
||||
signal_score = 0.0
|
||||
if buy_signal
|
||||
signal_score := signal_score + 3.0 // Base signal
|
||||
signal_score := htf_trend == 1 ? signal_score + 1.0 : signal_score // HTF alignment
|
||||
signal_score := bullish_divergence ? signal_score + 2.0 : signal_score // Divergence
|
||||
signal_score := rsi_momentum > 0 ? signal_score + 0.5 : signal_score // Momentum
|
||||
signal_score := rsi_velocity > 0 ? signal_score + 0.5 : signal_score // Acceleration
|
||||
|
||||
if sell_signal
|
||||
signal_score := signal_score - 3.0 // Base signal
|
||||
signal_score := htf_trend == -1 ? signal_score - 1.0 : signal_score // HTF alignment
|
||||
signal_score := bearish_divergence ? signal_score - 2.0 : signal_score // Divergence
|
||||
signal_score := rsi_momentum < 0 ? signal_score - 0.5 : signal_score // Momentum
|
||||
signal_score := rsi_velocity < 0 ? signal_score - 0.5 : signal_score // Acceleration
|
||||
|
||||
// Signal quality classification
|
||||
signal_quality = math.abs(signal_score) > 5 ? 'Strong' : math.abs(signal_score) > 3 ? 'Medium' : math.abs(signal_score) > 1 ? 'Weak' : 'None'
|
||||
|
||||
// ===== UNIFIED ALERT SYSTEM =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_rsi_buy = 0
|
||||
var int last_alert_rsi_sell = 0
|
||||
var int last_alert_rsi_neutral_from_ob = 0
|
||||
var int last_alert_rsi_neutral_from_os = 0
|
||||
var int last_alert_overbought_repeat = 0
|
||||
var int last_alert_oversold_repeat = 0
|
||||
var int last_alert_overbought_mark2 = 0
|
||||
var int last_alert_oversold_mark2 = 0
|
||||
var int last_alert_high_quality_buy = 0
|
||||
var int last_alert_high_quality_sell = 0
|
||||
var int last_alert_bullish_divergence = 0
|
||||
var int last_alert_bearish_divergence = 0
|
||||
var int last_alert_rsi_overbought = 0
|
||||
var int last_alert_rsi_oversold = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 基础穿越信号 - 每分钟限制
|
||||
if ta.crossover(rsi, final_overbought) and enable_alerts and current_minute > last_alert_rsi_buy
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(final_overbought, '#.##') + '","事件":"RSI 已上穿多头ML阈值 - 潜在买入信号","信号":"buy"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_rsi_buy := current_minute
|
||||
|
||||
if ta.crossunder(rsi, final_oversold) and enable_alerts and current_minute > last_alert_rsi_sell
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(final_oversold, '#.##') + '","事件":"RSI 已下穿空头ML阈值 - 潜在卖出信号","信号":"sell"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_rsi_sell := current_minute
|
||||
|
||||
// 区域转换信号 - 每分钟限制
|
||||
// if ta.crossunder(rsi, final_overbought) and enable_alerts and current_minute > last_alert_rsi_neutral_from_ob
|
||||
// alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(final_overbought, '#.##') + '","事件":"RSI 已下穿多头ML阈值进入中性区","备注":"进入震荡"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_rsi_neutral_from_ob := current_minute
|
||||
|
||||
// if ta.crossover(rsi, final_oversold) and enable_alerts and current_minute > last_alert_rsi_neutral_from_os
|
||||
// alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(final_oversold, '#.##') + '","事件":"RSI 已上穿空头ML阈值进入中性区","备注":"进入震荡"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_rsi_neutral_from_os := current_minute
|
||||
|
||||
// 重复进入信号 - 每分钟限制
|
||||
if overbought_repeat_alert and enable_alerts and current_minute > last_alert_overbought_repeat
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(final_overbought, '#.##') + '","事件":"RSI 重复进入超买区","标记":"' + str.tostring(segment_count) + '","信号":"overbought_repeat","警告":"大于和等于2次超买信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_overbought_repeat := current_minute
|
||||
|
||||
if oversold_repeat_alert and enable_alerts and current_minute > last_alert_oversold_repeat
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(final_oversold, '#.##') + '","事件":"RSI 重复进入超卖区","标记":"' + str.tostring(segment_count) + '","信号":"oversold_repeat","警告":"大于和等于2次超卖信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_oversold_repeat := current_minute
|
||||
|
||||
// 特定标记信号 - 每分钟限制
|
||||
if overbought_mark2_alert and enable_alerts and current_minute > last_alert_overbought_mark2
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Long ML Threshold":"' + str.tostring(final_overbought, '#.##') + '","事件":"RSI 第二次进入超买区","标记":"2","信号":"overbought_mark2","警告":"二次超买信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_overbought_mark2 := current_minute
|
||||
|
||||
if oversold_mark2_alert and enable_alerts and current_minute > last_alert_oversold_mark2
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","Short ML Threshold":"' + str.tostring(final_oversold, '#.##') + '","事件":"RSI 第二次进入超卖区","标记":"-2","信号":"oversold_mark2","警告":"二次超卖信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_oversold_mark2 := current_minute
|
||||
|
||||
// 高级信号 - 每分钟限制
|
||||
// if buy_signal and signal_score > 4 and enable_alerts and current_minute > last_alert_high_quality_buy
|
||||
// alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","事件":"高质量买入信号","信号":"high_quality_buy","评分":"' + str.tostring(signal_score, '#.#') + '","备注":"强烈看涨条件"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_high_quality_buy := current_minute
|
||||
|
||||
// if sell_signal and signal_score < -4 and enable_alerts and current_minute > last_alert_high_quality_sell
|
||||
// alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","事件":"高质量卖出信号","信号":"high_quality_sell","评分":"' + str.tostring(signal_score, '#.#') + '","备注":"强烈看跌条件"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_high_quality_sell := current_minute
|
||||
|
||||
// 背离信号 - 每分钟限制
|
||||
// if bullish_divergence and enable_alerts and current_minute > last_alert_bullish_divergence
|
||||
// alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","事件":"牛市背离","信号":"bullish_divergence","备注":"价格新低但RSI更高"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_bullish_divergence := current_minute
|
||||
|
||||
// if bearish_divergence and enable_alerts and current_minute > last_alert_bearish_divergence
|
||||
// alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","事件":"熊市背离","信号":"bearish_divergence","备注":"价格新高但RSI更低"}'
|
||||
// alert(alert_message, alert.freq_once_per_bar_close)
|
||||
// last_alert_bearish_divergence := current_minute
|
||||
|
||||
// RSI状态警报 - 计算RSI变化方向
|
||||
rsi_change = not na(rsi[1]) ? rsi - rsi[1] : 0
|
||||
rsi_direction = rsi_change > 0 ? "升高" : rsi_change < 0 ? "降低" : "持平"
|
||||
rsi_change_value = str.tostring(rsi_change, '#.##')
|
||||
|
||||
// RSI处于超买状态警报 - 每分钟限制
|
||||
if rsi_overbought and enable_alerts and current_minute > last_alert_rsi_overbought
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","超买阈值":"' + str.tostring(final_overbought, '#.##') + '","事件":"RSI处于超买状态","RSI变化":"' + rsi_direction + '","RSI变化值":"' + rsi_change_value + '","信号":"rsi_overbought","备注":"RSI高于超买线"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_rsi_overbought := current_minute
|
||||
|
||||
// RSI处于超卖状态警报 - 每分钟限制
|
||||
if rsi_oversold and enable_alerts and current_minute > last_alert_rsi_oversold
|
||||
alert_message := '{"指标名称":"ML_RSI_Pro","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","RSI":"' + str.tostring(rsi, '#.##') + '","超卖阈值":"' + str.tostring(final_oversold, '#.##') + '","事件":"RSI处于超卖状态","RSI变化":"' + rsi_direction + '","RSI变化值":"' + rsi_change_value + '","信号":"rsi_oversold","备注":"RSI低于超卖线"}'
|
||||
alert(alert_message, alert.freq_once_per_bar)
|
||||
last_alert_rsi_oversold := current_minute
|
||||
|
||||
// (Advanced features moved above alerts section to avoid duplication)
|
||||
|
||||
// ===== ENHANCED VISUALIZATION =====
|
||||
|
||||
// Divergence markers
|
||||
plotshape(bullish_divergence and show_signals, 'Bullish Divergence', shape.diamond,
|
||||
location.bottom, color.lime, size = size.normal, text = 'BD')
|
||||
plotshape(bearish_divergence and show_signals, 'Bearish Divergence', shape.diamond,
|
||||
location.top, color.orange, size = size.normal, text = 'BD')
|
||||
|
||||
// RSI momentum histogram
|
||||
plot(rsi_momentum * 10, 'RSI Momentum', color = rsi_momentum > 0 ? color.green : color.red,
|
||||
style = plot.style_histogram, histbase = 0, display = display.none)
|
||||
|
||||
// Background coloring for trend alignment
|
||||
bgcolor(enable_trend_filter and htf_trend == 1 ? color.new(color.green, 95) : enable_trend_filter and htf_trend == -1 ? color.new(color.red, 95) : na, title = 'HTF Trend Background')
|
||||
|
||||
// ===== PERFORMANCE METRICS =====
|
||||
var int total_signals = 0
|
||||
var int correct_signals = 0
|
||||
var float total_return = 0.0
|
||||
var float entry_price = na
|
||||
|
||||
// Track signal performance (simplified)
|
||||
if buy_signal or sell_signal
|
||||
total_signals := total_signals + 1
|
||||
entry_price := close
|
||||
|
||||
// Calculate approximate return after 10 bars
|
||||
if not na(entry_price) and bar_index % 10 == 0
|
||||
return_pct = (close - entry_price) / entry_price * 100
|
||||
if (buy_signal[10] and return_pct > 0) or (sell_signal[10] and return_pct < 0)
|
||||
correct_signals := correct_signals + 1
|
||||
total_return := total_return + math.abs(return_pct)
|
||||
entry_price := na
|
||||
|
||||
// Calculate success rate
|
||||
success_rate = total_signals > 0 ? correct_signals / total_signals * 100 : 0
|
||||
|
||||
// ===== ENHANCED STATISTICS TABLE =====
|
||||
if show_statistics and barstate.islast
|
||||
var table enhanced_stats = table.new(position.top_left, 2, 10, bgcolor = color.white, border_width = 1)
|
||||
table.cell(enhanced_stats, 0, 0, 'Advanced Metrics', text_color = color.white, bgcolor = color.blue)
|
||||
table.cell(enhanced_stats, 1, 0, 'Value', text_color = color.white, bgcolor = color.blue)
|
||||
table.cell(enhanced_stats, 0, 1, 'Signal Quality', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 1, signal_quality, text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 2, 'Signal Score', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 2, str.tostring(signal_score, '#.#'), text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 3, 'HTF Trend', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 3, htf_trend == 1 ? 'Bullish' : htf_trend == -1 ? 'Bearish' : 'Neutral', text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 4, 'RSI Momentum', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 4, str.tostring(rsi_momentum, '#.##'), text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 5, 'Position Size', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 5, str.tostring(position_size_factor, '#.#') + 'x', text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 6, 'Total Signals', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 6, str.tostring(total_signals), text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 7, 'Success Rate', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 7, str.tostring(success_rate, '#.#') + '%', text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 8, 'Bullish Div', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 8, bullish_divergence ? 'YES' : 'NO', text_color = color.black)
|
||||
table.cell(enhanced_stats, 0, 9, 'Bearish Div', text_color = color.black)
|
||||
table.cell(enhanced_stats, 1, 9, bearish_divergence ? 'YES' : 'NO', text_color = color.black)
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 基础穿越信号警报
|
||||
alertcondition(ta.crossover(rsi, final_overbought), title = 'RSI上穿多头ML阈值', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 已上穿多头ML阈值 - 潜在买入信号","信号":"buy"}')
|
||||
|
||||
alertcondition(ta.crossunder(rsi, final_oversold), title = 'RSI下穿空头ML阈值', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 已下穿空头ML阈值 - 潜在卖出信号","信号":"sell"}')
|
||||
|
||||
// 区域转换信号警报
|
||||
// alertcondition(ta.crossunder(rsi, final_overbought), title = 'RSI下穿多头ML阈值进入中性区', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 已下穿多头ML阈值进入中性区","备注":"进入震荡","信号":"neutral_from_overbought"}')
|
||||
|
||||
// alertcondition(ta.crossover(rsi, final_oversold), title = 'RSI上穿空头ML阈值进入中性区', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 已上穿空头ML阈值进入中性区","备注":"进入震荡","信号":"neutral_from_oversold"}')
|
||||
|
||||
// 重复进入信号警报
|
||||
alertcondition(overbought_repeat_alert, title = 'RSI重复进入超买区', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 重复进入超买区","标记":"{{plot("Segment Count")}}","信号":"overbought_repeat","警告":"大于和等于2次超买信号"}')
|
||||
|
||||
alertcondition(oversold_repeat_alert, title = 'RSI重复进入超卖区', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 重复进入超卖区","标记":"{{plot("Segment Count")}}","信号":"oversold_repeat","警告":"大于和等于2次超卖信号"}')
|
||||
|
||||
// 特定标记信号警报
|
||||
alertcondition(overbought_mark2_alert, title = 'RSI第二次进入超买区', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Long ML Threshold":"{{plot("Long ML Threshold")}}","事件":"RSI 第二次进入超买区","标记":"2","信号":"overbought_mark2","警告":"二次超买信号"}')
|
||||
|
||||
alertcondition(oversold_mark2_alert, title = 'RSI第二次进入超卖区', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","Short ML Threshold":"{{plot("Short ML Threshold")}}","事件":"RSI 第二次进入超卖区","标记":"-2","信号":"oversold_mark2","警告":"二次超卖信号"}')
|
||||
|
||||
// 高级信号警报
|
||||
// alertcondition(buy_signal and signal_score > 4, title = '高质量买入信号', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","事件":"高质量买入信号","信号":"high_quality_buy","评分":"{{plot("Signal Score")}}","备注":"强烈看涨条件"}')
|
||||
|
||||
// alertcondition(sell_signal and signal_score < -4, title = '高质量卖出信号', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","事件":"高质量卖出信号","信号":"high_quality_sell","评分":"{{plot("Signal Score")}}","备注":"强烈看跌条件"}')
|
||||
|
||||
// 背离信号警报
|
||||
// alertcondition(bullish_divergence, title = '牛市背离', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","事件":"牛市背离","信号":"bullish_divergence","备注":"价格新低但RSI更高"}')
|
||||
|
||||
// alertcondition(bearish_divergence, title = '熊市背离', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","事件":"熊市背离","信号":"bearish_divergence","备注":"价格新高但RSI更低"}')
|
||||
|
||||
// RSI状态警报
|
||||
alertcondition(rsi_overbought, title = 'RSI处于超买状态', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","超买阈值":"{{plot("Long ML Threshold")}}","事件":"RSI处于超买状态","信号":"rsi_overbought","备注":"RSI高于超买线"}')
|
||||
|
||||
alertcondition(rsi_oversold, title = 'RSI处于超卖状态', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","超卖阈值":"{{plot("Short ML Threshold")}}","事件":"RSI处于超卖状态","信号":"rsi_oversold","备注":"RSI低于超卖线"}')
|
||||
|
||||
// 基础买卖信号警报
|
||||
// alertcondition(buy_signal, title = '买入信号', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","事件":"买入信号","信号":"buy_signal","备注":"过滤后的买入信号"}')
|
||||
|
||||
// alertcondition(sell_signal, title = '卖出信号', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","事件":"卖出信号","信号":"sell_signal","备注":"过滤后的卖出信号"}')
|
||||
|
||||
// 传统RSI阈值警报(70/30)
|
||||
// alertcondition(ta.crossover(rsi, 70), title = 'RSI上穿70', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","阈值":"70","事件":"RSI上穿70","信号":"rsi_70_cross_up","备注":"传统超买信号"}')
|
||||
|
||||
// alertcondition(ta.crossunder(rsi, 30), title = 'RSI下穿30', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","阈值":"30","事件":"RSI下穿30","信号":"rsi_30_cross_down","备注":"传统超卖信号"}')
|
||||
|
||||
// RSI中线穿越警报(50)
|
||||
// alertcondition(ta.crossover(rsi, 50), title = 'RSI上穿50', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","中线":"50","事件":"RSI上穿50","信号":"rsi_50_cross_up","备注":"多头信号"}')
|
||||
|
||||
// alertcondition(ta.crossunder(rsi, 50), title = 'RSI下穿50', message = '{"指标名称":"ML_RSI_Pro","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","RSI":"{{plot("RSI")}}","中线":"50","事件":"RSI下穿50","信号":"rsi_50_cross_down","备注":"空头信号"}')
|
||||
|
||||
// ===== PLOTS FOR EXTERNAL ACCESS =====
|
||||
plot(buy_signal ? 1 : 0, 'Buy Signal Plot', display = display.none)
|
||||
plot(sell_signal ? 1 : 0, 'Sell Signal Plot', display = display.none)
|
||||
plot(final_oversold, 'Short ML Threshold', display = display.none) // For alert reference
|
||||
plot(final_overbought, 'Long ML Threshold', display = display.none) // For alert reference
|
||||
plot(signal_score, 'Signal Score', display = display.none)
|
||||
plot(bullish_divergence ? 1 : 0, 'Bullish Divergence Plot', display = display.none)
|
||||
plot(bearish_divergence ? 1 : 0, 'Bearish Divergence Plot', display = display.none)
|
||||
plot(htf_trend, 'HTF Trend', display = display.none)
|
||||
plot(segment_count, 'Segment Count', display = display.none) // For alert reference
|
||||
plot(overbought_repeat_alert ? 1 : 0, 'Overbought Repeat', display = display.none)
|
||||
plot(oversold_repeat_alert ? 1 : 0, 'Oversold Repeat', display = display.none)
|
||||
plot(overbought_mark2_alert ? 1 : 0, 'Overbought Mark2', display = display.none)
|
||||
plot(oversold_mark2_alert ? 1 : 0, 'Oversold Mark2', display = display.none)
|
||||
plot(rsi_overbought ? 1 : 0, 'RSI Overbought Status', display = display.none)
|
||||
plot(rsi_oversold ? 1 : 0, 'RSI Oversold Status', display = display.none)
|
||||
plot(rsi_change, 'RSI Change', display = display.none)
|
||||
293
rsi_conbinined.pine
Normal file
293
rsi_conbinined.pine
Normal file
@@ -0,0 +1,293 @@
|
||||
//@version=6
|
||||
indicator('RSI 窗口二显示', shorttitle='RSI-W2', overlay=false, max_labels_count=500)
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 参数设置
|
||||
//************************************************************************************************************
|
||||
|
||||
// RSI 参数组
|
||||
rsi_src = input.source(close, 'RSI Calculation Source', group='RSI')
|
||||
rsiLength = input.int(14, 'RSI Length', minval=2, group='RSI')
|
||||
smooth = input.bool(true, 'Smooth RSI?', group='RSI')
|
||||
maType = input.string('Ema', 'Moving Average Type', options=['SMA', 'Hull', 'Ema', 'Wma', 'DEMA', 'RMA', 'LINREG', 'TEMA', 'ALMA', 'T3'], group='RSI')
|
||||
smoothP = input.int(4, 'Smoothing Period', group='RSI')
|
||||
sig = input.int(6, 'Sigma for ALMA', group='RSI')
|
||||
|
||||
// 显示设置
|
||||
show_segments = input.bool(true, 'Show RSI Segments?', group='Display')
|
||||
show_counting = input.bool(true, 'Show Segment Counting?', group='Display')
|
||||
show_rsi_table = input.bool(true, 'Show RSI Info Table?', group='Display')
|
||||
show_price_labels = input.bool(true, 'Show Price Labels?', group='Display')
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 辅助函数
|
||||
//************************************************************************************************************
|
||||
|
||||
// 自定义移动平均函数
|
||||
dema(src, length) =>
|
||||
ema1 = ta.ema(src, length)
|
||||
ema2 = ta.ema(ema1, length)
|
||||
2 * ema1 - ema2
|
||||
|
||||
tema(src, length) =>
|
||||
ema1 = ta.ema(src, length)
|
||||
ema2 = ta.ema(ema1, length)
|
||||
ema3 = ta.ema(ema2, length)
|
||||
3 * ema1 - 3 * ema2 + ema3
|
||||
|
||||
t3(src, length, vfactor) =>
|
||||
ema1 = ta.ema(src, length)
|
||||
ema2 = ta.ema(ema1, length)
|
||||
ema3 = ta.ema(ema2, length)
|
||||
ema4 = ta.ema(ema3, length)
|
||||
ema5 = ta.ema(ema4, length)
|
||||
ema6 = ta.ema(ema5, length)
|
||||
|
||||
c1 = -vfactor * vfactor * vfactor
|
||||
c2 = 3 * vfactor * vfactor + 3 * vfactor * vfactor * vfactor
|
||||
c3 = -6 * vfactor * vfactor - 3 * vfactor - 3 * vfactor * vfactor * vfactor
|
||||
c4 = 1 + 3 * vfactor + vfactor * vfactor * vfactor + 3 * vfactor * vfactor
|
||||
|
||||
c1 * ema6 + c2 * ema5 + c3 * ema4 + c4 * ema3
|
||||
|
||||
ma(src, len, type, almaSig) =>
|
||||
switch type
|
||||
'SMA' => ta.sma(src, len)
|
||||
'Hull' => ta.hma(src, len)
|
||||
'Ema' => ta.ema(src, len)
|
||||
'Wma' => ta.wma(src, len)
|
||||
'DEMA' => dema(src, len)
|
||||
'RMA' => ta.rma(src, len)
|
||||
'LINREG' => ta.linreg(src, len, 0)
|
||||
'TEMA' => tema(src, len)
|
||||
'ALMA' => ta.alma(src, len, 0, almaSig)
|
||||
'T3' => t3(src, len, 0.7)
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 计算
|
||||
//************************************************************************************************************
|
||||
|
||||
// 计算RSI
|
||||
rsi = ta.rsi(rsi_src, rsiLength)
|
||||
if smooth
|
||||
rsi := ma(rsi, smoothP, maType, sig)
|
||||
|
||||
// RSI 机器学习阈值计算
|
||||
var rsi_values = array.new_float(0)
|
||||
if last_bar_index - bar_index <= 1000
|
||||
array.push(rsi_values, rsi)
|
||||
|
||||
var centroids = array.new_float(3)
|
||||
if array.size(rsi_values) > 3
|
||||
array.set(centroids, 0, array.percentile_linear_interpolation(rsi_values, 25))
|
||||
array.set(centroids, 1, array.percentile_linear_interpolation(rsi_values, 50))
|
||||
array.set(centroids, 2, array.percentile_linear_interpolation(rsi_values, 75))
|
||||
|
||||
long_S = array.get(centroids, 2)
|
||||
short_S = array.get(centroids, 0)
|
||||
|
||||
// RSI 状态和计数逻辑
|
||||
var int rsi_state = 0
|
||||
var int prev_rsi_state = 0
|
||||
var int extreme_type = 0
|
||||
var int segment_count = 0
|
||||
|
||||
// 计数标签变量 - 不再使用全局变量,每次状态变化时创建新标签以保留历史
|
||||
|
||||
current_state = rsi > long_S ? 1 : rsi < short_S ? -1 : 0
|
||||
|
||||
if current_state != rsi_state and not na(rsi)
|
||||
// 确定分段线颜色
|
||||
segment_color = color.black
|
||||
|
||||
if prev_rsi_state == 0 and current_state == 1
|
||||
segment_color := color.new(color.red, 0) // 从中性区进入超买区
|
||||
else if prev_rsi_state == 0 and current_state == -1
|
||||
segment_color := color.new(color.blue, 0) // 从中性区进入超卖区
|
||||
else if prev_rsi_state == 1 and current_state == 0
|
||||
segment_color := color.new(color.orange, 0) // 从超买区进入中性区
|
||||
else if prev_rsi_state == -1 and current_state == 0
|
||||
segment_color := color.new(color.green, 0) // 从超卖区进入中性区
|
||||
else if prev_rsi_state == 1 and current_state == -1
|
||||
segment_color := color.new(color.purple, 0) // 从超买区直接到超卖区
|
||||
else if prev_rsi_state == -1 and current_state == 1
|
||||
segment_color := color.new(color.yellow, 0) // 从超卖区直接到超买区
|
||||
else if prev_rsi_state == 1 and current_state == 1
|
||||
segment_color := color.new(color.maroon, 0) // 超买区内的重复进入
|
||||
else if prev_rsi_state == -1 and current_state == -1
|
||||
segment_color := color.new(color.navy, 0) // 超卖区内的重复进入
|
||||
|
||||
// 绘制分段线
|
||||
if show_segments
|
||||
line.new(bar_index, 0, bar_index, 100,
|
||||
color = segment_color,
|
||||
width = 2,
|
||||
style = line.style_solid,
|
||||
extend = extend.none)
|
||||
|
||||
// 更新计数逻辑
|
||||
if current_state == 1
|
||||
if extreme_type != 1
|
||||
extreme_type := 1
|
||||
segment_count := 1
|
||||
else
|
||||
segment_count := segment_count + 1
|
||||
|
||||
// 显示超买计数标签(保留历史标签)
|
||||
if show_counting
|
||||
label.new(bar_index, rsi,
|
||||
text = str.tostring(segment_count),
|
||||
style = label.style_label_down,
|
||||
color = color.red,
|
||||
textcolor = color.white,
|
||||
size = size.small)
|
||||
|
||||
else if current_state == -1
|
||||
if extreme_type != -1
|
||||
extreme_type := -1
|
||||
segment_count := -1
|
||||
else
|
||||
segment_count := segment_count - 1
|
||||
|
||||
// 显示超卖计数标签(保留历史标签)
|
||||
if show_counting
|
||||
label.new(bar_index, rsi,
|
||||
text = str.tostring(segment_count),
|
||||
style = label.style_label_up,
|
||||
color = color.blue,
|
||||
textcolor = color.white,
|
||||
size = size.small)
|
||||
|
||||
// 更新前一个状态
|
||||
prev_rsi_state := rsi_state
|
||||
rsi_state := current_state
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 绘图
|
||||
//************************************************************************************************************
|
||||
|
||||
// RSI 主线
|
||||
rsi_color = rsi > long_S ? color.red : rsi < short_S ? color.blue : color.gray
|
||||
plot(rsi, 'RSI', color=rsi_color, linewidth=2)
|
||||
|
||||
// 动态阈值线
|
||||
plot(long_S, 'Long ML Threshold', color=color.red, linewidth=1)
|
||||
plot(short_S, 'Short ML Threshold', color=color.blue, linewidth=1)
|
||||
|
||||
// 50中线
|
||||
hline(50, 'RSI 50', color=color.gray, linestyle=hline.style_dashed)
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 变化方向计算
|
||||
//************************************************************************************************************
|
||||
|
||||
// 计算RSI变化
|
||||
rsi_change = not na(rsi[1]) ? rsi - rsi[1] : 0
|
||||
rsi_direction = rsi_change > 0.1 ? "↗" : rsi_change < -0.1 ? "↘" : "→"
|
||||
rsi_direction_text = rsi_change > 0.1 ? "上升" : rsi_change < -0.1 ? "下降" : "平稳"
|
||||
rsi_change_value = str.tostring(math.abs(rsi_change), '#.##')
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 价格标签显示(参考MRC原始实现)
|
||||
//************************************************************************************************************
|
||||
|
||||
// 价格格式化函数
|
||||
format_rsi_value(value) =>
|
||||
str.tostring(value, '#.##')
|
||||
|
||||
// 声明RSI标签变量
|
||||
var label rsi_label = na
|
||||
var label long_threshold_label = na
|
||||
var label short_threshold_label = na
|
||||
var label midline_label = na
|
||||
|
||||
if show_price_labels and barstate.islast
|
||||
// RSI 主线标签(包含变化方向)
|
||||
rsi_label_text = "RSI: " + format_rsi_value(rsi) + " " + rsi_direction + " (" + rsi_direction_text + " " + rsi_change_value + ")"
|
||||
if na(rsi_label)
|
||||
rsi_label := label.new(bar_index, rsi, rsi_label_text, xloc=xloc.bar_index, style=label.style_label_left, color=rsi_color, textcolor=color.white)
|
||||
else
|
||||
label.set_xy(rsi_label, bar_index, rsi)
|
||||
label.set_text(rsi_label, rsi_label_text)
|
||||
label.set_color(rsi_label, rsi_color)
|
||||
|
||||
// 超买阈值标签
|
||||
if na(long_threshold_label)
|
||||
long_threshold_label := label.new(bar_index, long_S, "超买: " + format_rsi_value(long_S), xloc=xloc.bar_index, style=label.style_label_left, color=color.red, textcolor=color.white)
|
||||
else
|
||||
label.set_xy(long_threshold_label, bar_index, long_S)
|
||||
label.set_text(long_threshold_label, "超买: " + format_rsi_value(long_S))
|
||||
|
||||
// 超卖阈值标签
|
||||
if na(short_threshold_label)
|
||||
short_threshold_label := label.new(bar_index, short_S, "超卖: " + format_rsi_value(short_S), xloc=xloc.bar_index, style=label.style_label_left, color=color.blue, textcolor=color.white)
|
||||
else
|
||||
label.set_xy(short_threshold_label, bar_index, short_S)
|
||||
label.set_text(short_threshold_label, "超卖: " + format_rsi_value(short_S))
|
||||
|
||||
// 50中线标签
|
||||
if na(midline_label)
|
||||
midline_label := label.new(bar_index, 50, "中线: 50.00", xloc=xloc.bar_index, style=label.style_label_left, color=color.gray, textcolor=color.white)
|
||||
else
|
||||
label.set_xy(midline_label, bar_index, 50)
|
||||
label.set_text(midline_label, "中线: 50.00")
|
||||
|
||||
//************************************************************************************************************
|
||||
// RSI 信息表格
|
||||
//************************************************************************************************************
|
||||
|
||||
if show_rsi_table and barstate.islast
|
||||
// RSI 状态
|
||||
rsi_position = rsi > long_S ? "超买区" : rsi < short_S ? "超卖区" : "中性区"
|
||||
rsi_cross_count = math.abs(segment_count)
|
||||
cross_type = segment_count > 0 ? "超买穿越" : segment_count < 0 ? "超卖穿越" : "无穿越"
|
||||
|
||||
// 创建RSI表格(扩展为10行)
|
||||
var table rsi_table = table.new(
|
||||
position = position.bottom_right,
|
||||
columns = 2,
|
||||
rows = 10,
|
||||
bgcolor = color.new(color.yellow, 80),
|
||||
border_width = 1)
|
||||
|
||||
// 清空表格
|
||||
table.clear(rsi_table, 0, 0, 1, 9)
|
||||
|
||||
// 添加RSI标题
|
||||
table.cell(rsi_table, 0, 0, "RSI指标", text_color=color.black, bgcolor=color.new(color.orange, 70), text_size=size.small)
|
||||
table.cell(rsi_table, 1, 0, "实时数值", text_color=color.black, bgcolor=color.new(color.orange, 70), text_size=size.small)
|
||||
|
||||
// RSI 值
|
||||
table.cell(rsi_table, 0, 1, "RSI值", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 1, str.tostring(rsi, '#.##'), text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 位置
|
||||
table.cell(rsi_table, 0, 2, "RSI位置", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 2, rsi_position, text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 阈值
|
||||
table.cell(rsi_table, 0, 3, "超买阈值", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 3, str.tostring(long_S, '#.##'), text_color=color.black, text_size=size.tiny)
|
||||
|
||||
table.cell(rsi_table, 0, 4, "超卖阈值", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 4, str.tostring(short_S, '#.##'), text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 穿越次数
|
||||
table.cell(rsi_table, 0, 5, "穿越次数", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 5, str.tostring(rsi_cross_count), text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 穿越类型
|
||||
table.cell(rsi_table, 0, 6, "穿越类型", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 6, cross_type, text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 状态标记
|
||||
table.cell(rsi_table, 0, 7, "状态标记", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 7, str.tostring(segment_count), text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 变化方向
|
||||
table.cell(rsi_table, 0, 8, "变化方向", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 8, rsi_direction_text + " " + rsi_direction, text_color=color.black, text_size=size.tiny)
|
||||
|
||||
// RSI 变化幅度
|
||||
table.cell(rsi_table, 0, 9, "变化幅度", text_color=color.black, text_size=size.tiny)
|
||||
table.cell(rsi_table, 1, 9, rsi_change_value, text_color=color.black, text_size=size.tiny)
|
||||
714
srbr.pine
Normal file
714
srbr.pine
Normal file
@@ -0,0 +1,714 @@
|
||||
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
|
||||
// © ChartPrime
|
||||
|
||||
//@version=6
|
||||
indicator('SRBR 支撑阻力突破回测 [多时间周期表格]', shorttitle = 'SRBR MTF', overlay = true, max_boxes_count = 50)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙐𝙎𝙀𝙍 𝙄𝙉𝙋𝙐𝙏𝙎
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
int lookbackPeriod = input.int(20, 'Lookback Period', minval = 1, group = 'Settings')
|
||||
int vol_len = input.int(2, 'Delta Volume Filter Length', tooltip = 'Higher input, will filter low volume boxes', group = 'Settings')
|
||||
float box_withd = input.float(1, 'Adjust Box Width', maxval = 1000, minval = 0, step = 0.1, group = 'Settings')
|
||||
|
||||
// ═════════ 多时间周期表格设置 ════════
|
||||
mtfSet = input(false, '═════════ 多时间周期表格设置 ════════')
|
||||
show_mtf_table = input.bool(true, title='显示多时间周期表格', group='MTF Table')
|
||||
mtf_1m = input.bool(true, title='显示1分钟数据', group='MTF Table')
|
||||
mtf_5m = input.bool(true, title='显示5分钟数据', group='MTF Table')
|
||||
mtf_15m = input.bool(true, title='显示15分钟数据', group='MTF Table')
|
||||
mtf_30m = input.bool(true, title='显示30分钟数据', group='MTF Table')
|
||||
mtf_45m = input.bool(true, title='显示45分钟数据', group='MTF Table')
|
||||
mtf_1h = input.bool(true, title='显示1小时数据', group='MTF Table')
|
||||
mtf_4h = input.bool(true, title='显示4小时数据', group='MTF Table')
|
||||
|
||||
// ═════════ 表格显示设置 ════════
|
||||
tableSet = input(false, '═════════ 表格显示设置 ════════')
|
||||
table_position = input.string('bottom_right', title='表格位置', options=['top_left', 'top_center', 'top_right', 'middle_left', 'middle_center', 'middle_right', 'bottom_left', 'bottom_center', 'bottom_right'], group='Table Display')
|
||||
table_text_size = input.string('small', title='表格文字大小', options=['auto', 'tiny', 'small', 'normal', 'large', 'huge'], group='Table Display')
|
||||
mtf_table_rows = input.int(9, title='多时间框架表格行数', minval=6, maxval=12, group='Table Display')
|
||||
mtf_table_columns = input.int(8, title='多时间框架表格列数', minval=6, maxval=10, group='Table Display')
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// 辅助函数定义
|
||||
//************************************************************************************************************
|
||||
|
||||
// ═════════ 表格文字大小转换 ════════
|
||||
get_text_size() =>
|
||||
switch table_text_size
|
||||
'auto' => size.auto
|
||||
'tiny' => size.tiny
|
||||
'small' => size.small
|
||||
'normal' => size.normal
|
||||
'large' => size.large
|
||||
'huge' => size.huge
|
||||
=> size.small
|
||||
|
||||
// ═════════ 表格位置转换 ════════
|
||||
get_table_position() =>
|
||||
switch table_position
|
||||
'top_left' => position.top_left
|
||||
'top_center' => position.top_center
|
||||
'top_right' => position.top_right
|
||||
'middle_left' => position.middle_left
|
||||
'middle_center' => position.middle_center
|
||||
'middle_right' => position.middle_right
|
||||
'bottom_left' => position.bottom_left
|
||||
'bottom_center' => position.bottom_center
|
||||
'bottom_right' => position.bottom_right
|
||||
=> position.bottom_left
|
||||
|
||||
// ═════════ 价格状态判断函数 ════════
|
||||
get_price_status(price_val, support_val, resistance_val) =>
|
||||
if na(price_val) or na(support_val) or na(resistance_val)
|
||||
"N/A"
|
||||
else if price_val > resistance_val
|
||||
"看多"
|
||||
else if price_val < support_val
|
||||
"看空"
|
||||
else
|
||||
"震荡"
|
||||
|
||||
// ═════════ 价格状态颜色函数 ════════
|
||||
get_price_status_color(price_val, support_val, resistance_val) =>
|
||||
if na(price_val) or na(support_val) or na(resistance_val)
|
||||
color.new(color.gray, 60)
|
||||
else if price_val > resistance_val
|
||||
color.new(color.green, 40) // 看多 - 绿色
|
||||
else if price_val < support_val
|
||||
color.new(color.red, 40) // 看空 - 红色
|
||||
else
|
||||
color.new(color.orange, 40) // 震荡 - 橙色
|
||||
|
||||
// ═════════ 距离计算函数 ════════
|
||||
get_distance_to_levels(price_val, support_val, resistance_val) =>
|
||||
if na(price_val) or na(support_val) or na(resistance_val)
|
||||
[na, na]
|
||||
else
|
||||
distance_to_support = math.abs(price_val - support_val)
|
||||
distance_to_resistance = math.abs(price_val - resistance_val)
|
||||
[distance_to_support, distance_to_resistance]
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙄𝙉𝘿𝙄𝘾𝘼𝙏𝙊𝙍 𝘾𝘼𝙇𝘾𝙐𝙇𝘼𝙏𝙄𝙊𝙉𝙎
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
// Delta Volume Function
|
||||
upAndDownVolume() =>
|
||||
posVol = 0.0
|
||||
negVol = 0.0
|
||||
|
||||
var isBuyVolume = true
|
||||
|
||||
switch
|
||||
close > open =>
|
||||
isBuyVolume := true
|
||||
isBuyVolume
|
||||
close < open =>
|
||||
isBuyVolume := false
|
||||
isBuyVolume
|
||||
|
||||
if isBuyVolume
|
||||
posVol := posVol + volume
|
||||
posVol
|
||||
else
|
||||
negVol := negVol - volume
|
||||
negVol
|
||||
|
||||
posVol + negVol
|
||||
|
||||
|
||||
// Function to identify support and resistance boxes
|
||||
calcSupportResistance(src, lookbackPeriod) =>
|
||||
// Volume
|
||||
Vol = upAndDownVolume()
|
||||
vol_hi = ta.highest(Vol / 2.5, vol_len)
|
||||
vol_lo = ta.lowest(Vol / 2.5, vol_len)
|
||||
|
||||
var float supportLevel = na
|
||||
var float supportLevel_1 = na
|
||||
var float resistanceLevel = na
|
||||
var float resistanceLevel_1 = na
|
||||
var box sup = na
|
||||
var box res = na
|
||||
var color res_color = na
|
||||
var color sup_color = na
|
||||
var float multi = na
|
||||
|
||||
var bool brekout_res = false
|
||||
var bool brekout_sup = false
|
||||
var bool res_holds = false
|
||||
var bool sup_holds = false
|
||||
|
||||
// Find pivot points
|
||||
pivotHigh = ta.pivothigh(src, lookbackPeriod, lookbackPeriod)
|
||||
pivotLow = ta.pivotlow(src, lookbackPeriod, lookbackPeriod)
|
||||
// Box width
|
||||
atr = ta.atr(200)
|
||||
withd = atr * box_withd
|
||||
|
||||
// Volume range for color gradient
|
||||
vol_highest = ta.highest(Vol, 25)
|
||||
vol_lowest = ta.lowest(Vol, 25)
|
||||
|
||||
// Find support levels with Positive Volume
|
||||
if not na(pivotLow) and Vol > vol_hi
|
||||
|
||||
supportLevel := pivotLow
|
||||
supportLevel_1 := supportLevel - withd
|
||||
|
||||
topLeft = chart.point.from_index(bar_index - lookbackPeriod, supportLevel)
|
||||
bottomRight = chart.point.from_index(bar_index, supportLevel_1)
|
||||
|
||||
sup_color := color.from_gradient(Vol, 0, vol_highest, color(na), color.new(color.green, 30))
|
||||
|
||||
// 注释掉支撑位box绘图,保留计算逻辑
|
||||
// sup := box.new(top_left = topLeft, bottom_right = bottomRight, border_color = color.green, border_width = 1, bgcolor = sup_color, text = 'Vol: ' + str.tostring(math.round(Vol, 2)), text_color = chart.fg_color, text_size = size.small)
|
||||
// sup
|
||||
na
|
||||
|
||||
|
||||
// Find resistance levels with Negative Volume
|
||||
if not na(pivotHigh) and Vol < vol_lo
|
||||
|
||||
resistanceLevel := pivotHigh
|
||||
resistanceLevel_1 := resistanceLevel + withd
|
||||
|
||||
topLeft = chart.point.from_index(bar_index - lookbackPeriod, resistanceLevel)
|
||||
bottomRight = chart.point.from_index(bar_index, resistanceLevel_1)
|
||||
|
||||
res_color := color.from_gradient(Vol, vol_lowest, 0, color.new(color.red, 30), color(na))
|
||||
|
||||
// 注释掉阻力位box绘图,保留计算逻辑
|
||||
// res := box.new(top_left = topLeft, bottom_right = bottomRight, border_color = color.red, border_width = 1, bgcolor = res_color, text = 'Vol: ' + str.tostring(math.round(Vol, 2)), text_color = chart.fg_color, text_size = size.small)
|
||||
// res
|
||||
na
|
||||
|
||||
// Adaptive Box Len - 已注释掉box操作
|
||||
// sup.set_right(bar_index + 1)
|
||||
// res.set_right(bar_index + 1)
|
||||
|
||||
// Break of support or resistance conditions
|
||||
brekout_res := ta.crossover(low, resistanceLevel_1)
|
||||
res_holds := ta.crossunder(high, resistanceLevel)
|
||||
|
||||
sup_holds := ta.crossover(low, supportLevel)
|
||||
brekout_sup := ta.crossunder(high, supportLevel_1)
|
||||
|
||||
// Change Color of Support to red if it was break, change color of resistance to green if it was break - 已注释掉box操作
|
||||
// if brekout_sup
|
||||
// sup.set_bgcolor(color.new(color.red, 80))
|
||||
// sup.set_border_color(color.red)
|
||||
// sup.set_border_style(line.style_dashed)
|
||||
|
||||
// if sup_holds
|
||||
// sup.set_bgcolor(sup_color)
|
||||
// sup.set_border_color(color.green)
|
||||
// sup.set_border_style(line.style_solid)
|
||||
|
||||
// if brekout_res
|
||||
// res.set_bgcolor(color.new(color.green, 80))
|
||||
// res.set_border_color(color.new(color.green, 0))
|
||||
// res.set_border_style(line.style_dashed)
|
||||
|
||||
// if res_holds
|
||||
// res.set_bgcolor(res_color)
|
||||
// res.set_border_color(color.new(color.red, 0))
|
||||
// res.set_border_style(line.style_solid)
|
||||
|
||||
[supportLevel, resistanceLevel, brekout_res, res_holds, sup_holds, brekout_sup]
|
||||
|
||||
|
||||
// Calculate support and resistance levels and their breakouts
|
||||
[supportLevel, resistanceLevel, brekout_res, res_holds, sup_holds, brekout_sup] = calcSupportResistance(close, lookbackPeriod)
|
||||
|
||||
|
||||
// Check if Resistance become Support or Support Become Resistance
|
||||
var bool res_is_sup = false
|
||||
var bool sup_is_res = false
|
||||
|
||||
switch
|
||||
brekout_res =>
|
||||
res_is_sup := true
|
||||
res_is_sup
|
||||
res_holds =>
|
||||
res_is_sup := false
|
||||
res_is_sup
|
||||
|
||||
switch
|
||||
brekout_sup =>
|
||||
sup_is_res := true
|
||||
sup_is_res
|
||||
sup_holds =>
|
||||
sup_is_res := false
|
||||
sup_is_res
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙑𝙄𝙎𝙐𝘼𝙇𝙄𝙕𝘼𝙏𝙄𝙊𝙉
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
// Plot Res and Sup breakouts and holds - 已注释掉图形显示
|
||||
// plotchar(res_holds, 'Resistance Holds', '◆', color = #e92929, size = size.tiny, location = location.abovebar, offset = -1)
|
||||
// plotchar(sup_holds, 'Support Holds', '◆', color = #20ca26, size = size.tiny, location = location.belowbar, offset = -1)
|
||||
|
||||
// plotchar(brekout_res and res_is_sup[1], 'Resistance as Support Holds', '◆', color = #20ca26, size = size.tiny, location = location.belowbar, offset = -1)
|
||||
// plotchar(brekout_sup and sup_is_res[1], 'Support as Resistance Holds', '◆', color = #e92929, size = size.tiny, location = location.abovebar, offset = -1)
|
||||
|
||||
// Break Out Labels - 已注释掉图形显示
|
||||
// if brekout_sup and not sup_is_res[1]
|
||||
// label.new(bar_index[1], supportLevel[1], text = 'Break Sup', style = label.style_label_down, color = #7e1e1e, textcolor = chart.fg_color, size = size.small)
|
||||
|
||||
// if brekout_res and not res_is_sup[1]
|
||||
// label.new(bar_index[1], resistanceLevel[1], text = 'Break Res', style = label.style_label_up, color = #2b6d2d, textcolor = chart.fg_color, size = size.small)
|
||||
|
||||
// 警报标记 - 醒目的视觉提示 - 已注释掉图形显示
|
||||
// 支撑位保持警报标记
|
||||
// if sup_holds
|
||||
// label.new(bar_index, low, text = '🔔SUP', style = label.style_label_down, color = color.new(color.lime, 0), textcolor = color.black, size = size.large, tooltip = '支撑位保持警报')
|
||||
|
||||
// 阻力位保持警报标记
|
||||
// if res_holds
|
||||
// label.new(bar_index, high, text = '🔔RES', style = label.style_label_up, color = color.new(color.red, 0), textcolor = color.white, size = size.large, tooltip = '阻力位保持警报')
|
||||
|
||||
// 支撑位突破警报标记
|
||||
// if brekout_sup
|
||||
// label.new(bar_index[1], supportLevel[1], text = '🚨SUP⬇', style = label.style_label_down, color = color.new(color.orange, 0), textcolor = color.black, size = size.large, tooltip = '支撑位突破警报')
|
||||
|
||||
// 阻力位突破警报标记
|
||||
// if brekout_res
|
||||
// label.new(bar_index[1], resistanceLevel[1], text = '🚨RES⬆', style = label.style_label_up, color = color.new(color.aqua, 0), textcolor = color.black, size = size.large, tooltip = '阻力位突破警报')
|
||||
|
||||
// 阻力转支撑警报标记
|
||||
// if brekout_res and res_is_sup[1]
|
||||
// label.new(bar_index[1], resistanceLevel[1], text = '⭐R→S', style = label.style_label_down, color = color.new(color.purple, 0), textcolor = color.white, size = size.large, tooltip = '阻力转支撑保持警报')
|
||||
|
||||
// 支撑转阻力警报标记
|
||||
// if brekout_sup and sup_is_res[1]
|
||||
// label.new(bar_index[1], supportLevel[1], text = '⭐S→R', style = label.style_label_up, color = color.new(color.maroon, 0), textcolor = color.white, size = size.large, tooltip = '支撑转阻力保持警报')
|
||||
|
||||
// 全局作用域的plotshape - 警报形状标记 - 已注释掉图形显示
|
||||
// plotshape(sup_holds, title = '支撑保持警报', style = shape.triangleup, location = location.belowbar, color = color.new(color.lime, 0), size = size.large)
|
||||
// plotshape(res_holds, title = '阻力保持警报', style = shape.triangledown, location = location.abovebar, color = color.new(color.red, 0), size = size.large)
|
||||
// plotshape(brekout_sup, title = '支撑突破警报', style = shape.xcross, location = location.belowbar, color = color.new(color.orange, 0), size = size.large)
|
||||
// plotshape(brekout_res, title = '阻力突破警报', style = shape.xcross, location = location.abovebar, color = color.new(color.aqua, 0), size = size.large)
|
||||
// plotshape(brekout_res and res_is_sup[1], title = '阻力转支撑警报', style = shape.diamond, location = location.belowbar, color = color.new(color.purple, 0), size = size.large)
|
||||
// plotshape(brekout_sup and sup_is_res[1], title = '支撑转阻力警报', style = shape.diamond, location = location.abovebar, color = color.new(color.maroon, 0), size = size.large)
|
||||
|
||||
|
||||
//************************************************************************************************************
|
||||
// 多时间周期计算
|
||||
//************************************************************************************************************
|
||||
|
||||
// ═════════ 多时间周期专用计算函数(无绘图操作) ════════
|
||||
// 为了避免request.security()中的绘图函数错误,创建简化版本
|
||||
calcSRForMTF(src, lookback) =>
|
||||
// 使用简化的支撑阻力计算,基于pivot点但无绘图
|
||||
pivotHigh = ta.pivothigh(src, lookback, lookback)
|
||||
pivotLow = ta.pivotlow(src, lookback, lookback)
|
||||
|
||||
// 简化的支撑阻力位识别
|
||||
var float mtf_support = na
|
||||
var float mtf_resistance = na
|
||||
|
||||
if not na(pivotLow)
|
||||
mtf_support := pivotLow
|
||||
if not na(pivotHigh)
|
||||
mtf_resistance := pivotHigh
|
||||
|
||||
// 简化的突破判断
|
||||
mtf_brekout_res = src > mtf_resistance
|
||||
mtf_res_holds = src <= mtf_resistance and src >= mtf_resistance * 0.995
|
||||
mtf_sup_holds = src >= mtf_support and src <= mtf_support * 1.005
|
||||
mtf_brekout_sup = src < mtf_support
|
||||
|
||||
[mtf_support, mtf_resistance, mtf_brekout_res, mtf_res_holds, mtf_sup_holds, mtf_brekout_sup]
|
||||
|
||||
// ═════════ 多时间周期数据获取函数 ════════
|
||||
get_mtf_data(tf) =>
|
||||
request.security(syminfo.tickerid, tf, calcSRForMTF(close, lookbackPeriod), lookahead=barmerge.lookahead_off)
|
||||
|
||||
get_mtf_close(tf) =>
|
||||
request.security(syminfo.tickerid, tf, close, lookahead=barmerge.lookahead_off)
|
||||
|
||||
// ═════════ 多时间周期数据获取 ═════════
|
||||
// 1分钟数据
|
||||
var float supportLevel_1m = na
|
||||
var float resistanceLevel_1m = na
|
||||
var bool brekout_res_1m = false
|
||||
var bool res_holds_1m = false
|
||||
var bool sup_holds_1m = false
|
||||
var bool brekout_sup_1m = false
|
||||
var float close_1m = na
|
||||
|
||||
if mtf_1m
|
||||
[sup_1m, res_1m, br_res_1m, r_holds_1m, s_holds_1m, br_sup_1m] = get_mtf_data("1")
|
||||
supportLevel_1m := sup_1m
|
||||
resistanceLevel_1m := res_1m
|
||||
brekout_res_1m := br_res_1m
|
||||
res_holds_1m := r_holds_1m
|
||||
sup_holds_1m := s_holds_1m
|
||||
brekout_sup_1m := br_sup_1m
|
||||
close_1m := get_mtf_close("1")
|
||||
|
||||
// 5分钟数据
|
||||
var float supportLevel_5m = na
|
||||
var float resistanceLevel_5m = na
|
||||
var bool brekout_res_5m = false
|
||||
var bool res_holds_5m = false
|
||||
var bool sup_holds_5m = false
|
||||
var bool brekout_sup_5m = false
|
||||
var float close_5m = na
|
||||
|
||||
if mtf_5m
|
||||
[sup_5m, res_5m, br_res_5m, r_holds_5m, s_holds_5m, br_sup_5m] = get_mtf_data("5")
|
||||
supportLevel_5m := sup_5m
|
||||
resistanceLevel_5m := res_5m
|
||||
brekout_res_5m := br_res_5m
|
||||
res_holds_5m := r_holds_5m
|
||||
sup_holds_5m := s_holds_5m
|
||||
brekout_sup_5m := br_sup_5m
|
||||
close_5m := get_mtf_close("5")
|
||||
|
||||
// 15分钟数据
|
||||
var float supportLevel_15m = na
|
||||
var float resistanceLevel_15m = na
|
||||
var bool brekout_res_15m = false
|
||||
var bool res_holds_15m = false
|
||||
var bool sup_holds_15m = false
|
||||
var bool brekout_sup_15m = false
|
||||
var float close_15m = na
|
||||
|
||||
if mtf_15m
|
||||
[sup_15m, res_15m, br_res_15m, r_holds_15m, s_holds_15m, br_sup_15m] = get_mtf_data("15")
|
||||
supportLevel_15m := sup_15m
|
||||
resistanceLevel_15m := res_15m
|
||||
brekout_res_15m := br_res_15m
|
||||
res_holds_15m := r_holds_15m
|
||||
sup_holds_15m := s_holds_15m
|
||||
brekout_sup_15m := br_sup_15m
|
||||
close_15m := get_mtf_close("15")
|
||||
|
||||
// 30分钟数据
|
||||
var float supportLevel_30m = na
|
||||
var float resistanceLevel_30m = na
|
||||
var bool brekout_res_30m = false
|
||||
var bool res_holds_30m = false
|
||||
var bool sup_holds_30m = false
|
||||
var bool brekout_sup_30m = false
|
||||
var float close_30m = na
|
||||
|
||||
if mtf_30m
|
||||
[sup_30m, res_30m, br_res_30m, r_holds_30m, s_holds_30m, br_sup_30m] = get_mtf_data("30")
|
||||
supportLevel_30m := sup_30m
|
||||
resistanceLevel_30m := res_30m
|
||||
brekout_res_30m := br_res_30m
|
||||
res_holds_30m := r_holds_30m
|
||||
sup_holds_30m := s_holds_30m
|
||||
brekout_sup_30m := br_sup_30m
|
||||
close_30m := get_mtf_close("30")
|
||||
|
||||
// 45分钟数据
|
||||
var float supportLevel_45m = na
|
||||
var float resistanceLevel_45m = na
|
||||
var bool brekout_res_45m = false
|
||||
var bool res_holds_45m = false
|
||||
var bool sup_holds_45m = false
|
||||
var bool brekout_sup_45m = false
|
||||
var float close_45m = na
|
||||
|
||||
if mtf_45m
|
||||
[sup_45m, res_45m, br_res_45m, r_holds_45m, s_holds_45m, br_sup_45m] = get_mtf_data("45")
|
||||
supportLevel_45m := sup_45m
|
||||
resistanceLevel_45m := res_45m
|
||||
brekout_res_45m := br_res_45m
|
||||
res_holds_45m := r_holds_45m
|
||||
sup_holds_45m := s_holds_45m
|
||||
brekout_sup_45m := br_sup_45m
|
||||
close_45m := get_mtf_close("45")
|
||||
|
||||
// 1小时数据
|
||||
var float supportLevel_1h = na
|
||||
var float resistanceLevel_1h = na
|
||||
var bool brekout_res_1h = false
|
||||
var bool res_holds_1h = false
|
||||
var bool sup_holds_1h = false
|
||||
var bool brekout_sup_1h = false
|
||||
var float close_1h = na
|
||||
|
||||
if mtf_1h
|
||||
[sup_1h, res_1h, br_res_1h, r_holds_1h, s_holds_1h, br_sup_1h] = get_mtf_data("60")
|
||||
supportLevel_1h := sup_1h
|
||||
resistanceLevel_1h := res_1h
|
||||
brekout_res_1h := br_res_1h
|
||||
res_holds_1h := r_holds_1h
|
||||
sup_holds_1h := s_holds_1h
|
||||
brekout_sup_1h := br_sup_1h
|
||||
close_1h := get_mtf_close("60")
|
||||
|
||||
// 4小时数据
|
||||
var float supportLevel_4h = na
|
||||
var float resistanceLevel_4h = na
|
||||
var bool brekout_res_4h = false
|
||||
var bool res_holds_4h = false
|
||||
var bool sup_holds_4h = false
|
||||
var bool brekout_sup_4h = false
|
||||
var float close_4h = na
|
||||
|
||||
if mtf_4h
|
||||
[sup_4h, res_4h, br_res_4h, r_holds_4h, s_holds_4h, br_sup_4h] = get_mtf_data("240")
|
||||
supportLevel_4h := sup_4h
|
||||
resistanceLevel_4h := res_4h
|
||||
brekout_res_4h := br_res_4h
|
||||
res_holds_4h := r_holds_4h
|
||||
sup_holds_4h := s_holds_4h
|
||||
brekout_sup_4h := br_sup_4h
|
||||
close_4h := get_mtf_close("240")
|
||||
|
||||
//************************************************************************************************************
|
||||
// 多时间周期表格显示
|
||||
//************************************************************************************************************
|
||||
|
||||
if show_mtf_table and barstate.islast
|
||||
// 创建多时间周期表格
|
||||
var table mtf_table = table.new(
|
||||
position = get_table_position(),
|
||||
columns = mtf_table_columns,
|
||||
rows = mtf_table_rows,
|
||||
bgcolor = color.new(color.white, 85),
|
||||
border_width = 1)
|
||||
|
||||
// 清空表格
|
||||
table.clear(mtf_table, 0, 0, mtf_table_columns-1, mtf_table_rows-1)
|
||||
|
||||
// 获取配置的文字大小
|
||||
text_size = get_text_size()
|
||||
|
||||
// ═════════ 表格标题行 ═════════
|
||||
table.cell(mtf_table, 0, 0, "时间周期", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 1, 0, "当前价格", text_color=color.white, bgcolor=color.new(color.purple, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 2, 0, "支撑位", text_color=color.white, bgcolor=color.new(color.green, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 3, 0, "阻力位", text_color=color.white, bgcolor=color.new(color.red, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 4, 0, "距支撑", text_color=color.white, bgcolor=color.new(color.green, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 5, 0, "距阻力", text_color=color.white, bgcolor=color.new(color.red, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 6, 0, "价格状态", text_color=color.white, bgcolor=color.new(color.blue, 30), text_size=text_size)
|
||||
table.cell(mtf_table, 7, 0, "市场观点", text_color=color.white, bgcolor=color.new(color.orange, 30), text_size=text_size)
|
||||
|
||||
// ═════════ 数据行 ═════════
|
||||
row = 1
|
||||
|
||||
// 1分钟数据行
|
||||
if mtf_1m and row < mtf_table_rows
|
||||
[dist_to_sup_1m, dist_to_res_1m] = get_distance_to_levels(close_1m, supportLevel_1m, resistanceLevel_1m)
|
||||
status_1m = get_price_status(close_1m, supportLevel_1m, resistanceLevel_1m)
|
||||
status_color_1m = get_price_status_color(close_1m, supportLevel_1m, resistanceLevel_1m)
|
||||
|
||||
table.cell(mtf_table, 0, row, "1分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_1m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_1m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_1m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_1m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_1m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_1m, text_color=color.white, bgcolor=status_color_1m, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_1m, text_color=color.white, bgcolor=status_color_1m, text_size=text_size)
|
||||
row := row + 1
|
||||
|
||||
// 5分钟数据行
|
||||
if mtf_5m and row < mtf_table_rows
|
||||
[dist_to_sup_5m, dist_to_res_5m] = get_distance_to_levels(close_5m, supportLevel_5m, resistanceLevel_5m)
|
||||
status_5m = get_price_status(close_5m, supportLevel_5m, resistanceLevel_5m)
|
||||
status_color_5m = get_price_status_color(close_5m, supportLevel_5m, resistanceLevel_5m)
|
||||
|
||||
table.cell(mtf_table, 0, row, "5分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_5m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_5m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_5m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_5m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_5m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_5m, text_color=color.white, bgcolor=status_color_5m, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_5m, text_color=color.white, bgcolor=status_color_5m, text_size=text_size)
|
||||
row := row + 1
|
||||
|
||||
// 15分钟数据行
|
||||
if mtf_15m and row < mtf_table_rows
|
||||
[dist_to_sup_15m, dist_to_res_15m] = get_distance_to_levels(close_15m, supportLevel_15m, resistanceLevel_15m)
|
||||
status_15m = get_price_status(close_15m, supportLevel_15m, resistanceLevel_15m)
|
||||
status_color_15m = get_price_status_color(close_15m, supportLevel_15m, resistanceLevel_15m)
|
||||
|
||||
table.cell(mtf_table, 0, row, "15分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_15m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_15m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_15m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_15m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_15m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_15m, text_color=color.white, bgcolor=status_color_15m, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_15m, text_color=color.white, bgcolor=status_color_15m, text_size=text_size)
|
||||
row := row + 1
|
||||
|
||||
// 30分钟数据行
|
||||
if mtf_30m and row < mtf_table_rows
|
||||
[dist_to_sup_30m, dist_to_res_30m] = get_distance_to_levels(close_30m, supportLevel_30m, resistanceLevel_30m)
|
||||
status_30m = get_price_status(close_30m, supportLevel_30m, resistanceLevel_30m)
|
||||
status_color_30m = get_price_status_color(close_30m, supportLevel_30m, resistanceLevel_30m)
|
||||
|
||||
table.cell(mtf_table, 0, row, "30分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_30m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_30m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_30m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_30m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_30m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_30m, text_color=color.white, bgcolor=status_color_30m, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_30m, text_color=color.white, bgcolor=status_color_30m, text_size=text_size)
|
||||
row := row + 1
|
||||
|
||||
// 45分钟数据行
|
||||
if mtf_45m and row < mtf_table_rows
|
||||
[dist_to_sup_45m, dist_to_res_45m] = get_distance_to_levels(close_45m, supportLevel_45m, resistanceLevel_45m)
|
||||
status_45m = get_price_status(close_45m, supportLevel_45m, resistanceLevel_45m)
|
||||
status_color_45m = get_price_status_color(close_45m, supportLevel_45m, resistanceLevel_45m)
|
||||
|
||||
table.cell(mtf_table, 0, row, "45分钟", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_45m, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_45m, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_45m, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_45m, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_45m, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_45m, text_color=color.white, bgcolor=status_color_45m, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_45m, text_color=color.white, bgcolor=status_color_45m, text_size=text_size)
|
||||
row := row + 1
|
||||
|
||||
// 1小时数据行
|
||||
if mtf_1h and row < mtf_table_rows
|
||||
[dist_to_sup_1h, dist_to_res_1h] = get_distance_to_levels(close_1h, supportLevel_1h, resistanceLevel_1h)
|
||||
status_1h = get_price_status(close_1h, supportLevel_1h, resistanceLevel_1h)
|
||||
status_color_1h = get_price_status_color(close_1h, supportLevel_1h, resistanceLevel_1h)
|
||||
|
||||
table.cell(mtf_table, 0, row, "1小时", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_1h, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_1h, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_1h, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_1h, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_1h, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_1h, text_color=color.white, bgcolor=status_color_1h, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_1h, text_color=color.white, bgcolor=status_color_1h, text_size=text_size)
|
||||
row := row + 1
|
||||
|
||||
// 4小时数据行
|
||||
if mtf_4h and row < mtf_table_rows
|
||||
[dist_to_sup_4h, dist_to_res_4h] = get_distance_to_levels(close_4h, supportLevel_4h, resistanceLevel_4h)
|
||||
status_4h = get_price_status(close_4h, supportLevel_4h, resistanceLevel_4h)
|
||||
status_color_4h = get_price_status_color(close_4h, supportLevel_4h, resistanceLevel_4h)
|
||||
|
||||
table.cell(mtf_table, 0, row, "4小时", text_color=color.black, bgcolor=color.new(color.gray, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 1, row, str.tostring(close_4h, '#.##'), text_color=color.black, bgcolor=color.white, text_size=text_size)
|
||||
table.cell(mtf_table, 2, row, str.tostring(supportLevel_4h, '#.##'), text_color=color.white, bgcolor=color.new(color.green, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 3, row, str.tostring(resistanceLevel_4h, '#.##'), text_color=color.white, bgcolor=color.new(color.red, 60), text_size=text_size)
|
||||
table.cell(mtf_table, 4, row, str.tostring(dist_to_sup_4h, '#.##'), text_color=color.black, bgcolor=color.new(color.green, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 5, row, str.tostring(dist_to_res_4h, '#.##'), text_color=color.black, bgcolor=color.new(color.red, 80), text_size=text_size)
|
||||
table.cell(mtf_table, 6, row, status_4h, text_color=color.white, bgcolor=status_color_4h, text_size=text_size)
|
||||
table.cell(mtf_table, 7, row, status_4h, text_color=color.white, bgcolor=status_color_4h, text_size=text_size)
|
||||
|
||||
// ═════════ 输出支撑阻力位数据供webhook使用 ════════
|
||||
plot(supportLevel, title="supportLevel", display=display.none)
|
||||
plot(resistanceLevel, title="resistanceLevel", display=display.none)
|
||||
|
||||
// ◆
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// <20>𝙍𝙄𝘾𝙀 𝙎𝙏𝘼𝙏𝙐𝙎 & 𝙈𝘼𝙍𝙆𝙀𝙏 𝙊𝙐𝙏𝙇𝙊𝙊𝙆
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
|
||||
// ═════════ 当前图表时间周期价格状态分析 ════════
|
||||
get_current_price_status() =>
|
||||
current_price = close
|
||||
support_level = supportLevel
|
||||
resistance_level = resistanceLevel
|
||||
|
||||
// 计算价格相对位置
|
||||
if na(support_level) and na(resistance_level)
|
||||
"无明确支撑阻力"
|
||||
else if na(support_level)
|
||||
if current_price > resistance_level
|
||||
"突破阻力位上方"
|
||||
else if current_price >= resistance_level * 0.995
|
||||
"接近阻力位"
|
||||
else
|
||||
"阻力位下方"
|
||||
else if na(resistance_level)
|
||||
if current_price < support_level
|
||||
"跌破支撑位下方"
|
||||
else if current_price <= support_level * 1.005
|
||||
"接近支撑位"
|
||||
else
|
||||
"支撑位上方"
|
||||
else
|
||||
range_size = resistance_level - support_level
|
||||
price_position = (current_price - support_level) / range_size
|
||||
|
||||
if current_price > resistance_level
|
||||
"突破阻力位上方"
|
||||
else if current_price < support_level
|
||||
"跌破支撑位下方"
|
||||
else if price_position >= 0.8
|
||||
"接近阻力位"
|
||||
else if price_position <= 0.2
|
||||
"接近支撑位"
|
||||
else
|
||||
"区间中部运行"
|
||||
|
||||
// ═════════ 市场观点生成 ════════
|
||||
get_market_outlook() =>
|
||||
current_status = get_current_price_status()
|
||||
|
||||
// 基于价格状态和突破情况生成观点
|
||||
if brekout_res and res_is_sup[1]
|
||||
"看涨:阻力转支撑确认,建议关注回调买入机会"
|
||||
else if brekout_sup and sup_is_res[1]
|
||||
"看跌:支撑转阻力确认,建议关注反弹卖出机会"
|
||||
else if brekout_res
|
||||
"看涨:突破阻力位,建议关注回踩确认后的追涨机会"
|
||||
else if brekout_sup
|
||||
"看跌:跌破支撑位,建议关注反弹确认后的追跌机会"
|
||||
else if res_holds
|
||||
"中性偏空:阻力位有效,短期上涨受阻"
|
||||
else if sup_holds
|
||||
"中性偏多:支撑位有效,短期下跌受限"
|
||||
else if current_status == "接近阻力位"
|
||||
"谨慎:接近关键阻力位,注意突破或回落"
|
||||
else if current_status == "接近支撑位"
|
||||
"谨慎:接近关键支撑位,注意反弹或破位"
|
||||
else if current_status == "区间中部运行"
|
||||
"中性:价格在支撑阻力区间内震荡"
|
||||
else if current_status == "突破阻力位上方"
|
||||
"看涨:已突破阻力位,关注持续性"
|
||||
else if current_status == "跌破支撑位下方"
|
||||
"看跌:已跌破支撑位,关注反弹力度"
|
||||
else
|
||||
"观望:等待明确的支撑阻力信号"
|
||||
|
||||
// 获取当前价格状态和市场观点
|
||||
current_price_status = get_current_price_status()
|
||||
market_outlook = get_market_outlook()
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// <20>𝘼𝙇𝙀𝙍𝙏 𝘾𝙊𝙉𝘿𝙄𝙏𝙄𝙊𝙉𝙎
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
|
||||
// 支撑位保持警报
|
||||
alertcondition(sup_holds, title = '支撑位保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑位保持","位置":"支撑位","信号":"support_holds","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 阻力位保持警报
|
||||
alertcondition(res_holds, title = '阻力位保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力位保持","位置":"阻力位","信号":"resistance_holds","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 支撑位突破警报
|
||||
alertcondition(brekout_sup, title = '支撑位突破', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑位突破","位置":"支撑位下方","信号":"support_breakout","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 阻力位突破警报
|
||||
alertcondition(brekout_res, title = '阻力位突破', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力位突破","位置":"阻力位上方","信号":"resistance_breakout","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 阻力转支撑警报
|
||||
alertcondition(brekout_res and res_is_sup[1], title = '阻力转支撑保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力转支撑保持","位置":"前阻力位","信号":"resistance_as_support","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 支撑转阻力警报
|
||||
alertcondition(brekout_sup and sup_is_res[1], title = '支撑转阻力保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑转阻力保持","位置":"前支撑位","信号":"support_as_resistance","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
316
srbr1.pine
Normal file
316
srbr1.pine
Normal file
@@ -0,0 +1,316 @@
|
||||
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
|
||||
// © ChartPrime
|
||||
|
||||
//@version=6
|
||||
indicator('Support and Resistance (High Volume Boxes) [ChartPrime]2', shorttitle = 'SR Breaks and Retests [ChartPrime]2', overlay = true, max_boxes_count = 50)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙐𝙎𝙀𝙍 𝙄𝙉𝙋𝙐𝙏𝙎
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
int lookbackPeriod = input.int(20, 'Lookback Period', minval = 1, group = 'Settings')
|
||||
int vol_len = input.int(2, 'Delta Volume Filter Length', tooltip = 'Higher input, will filter low volume boxes', group = 'Settings')
|
||||
float box_withd = input.float(1, 'Adjust Box Width', maxval = 1000, minval = 0, step = 0.1)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙄𝙉𝘿𝙄𝘾𝘼𝙏𝙊𝙍 𝘾𝘼𝙇𝘾𝙐𝙇𝘼𝙏𝙄𝙊𝙉𝙎
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
// Delta Volume Function
|
||||
upAndDownVolume() =>
|
||||
posVol = 0.0
|
||||
negVol = 0.0
|
||||
|
||||
var isBuyVolume = true
|
||||
|
||||
switch
|
||||
close > open =>
|
||||
isBuyVolume := true
|
||||
isBuyVolume
|
||||
close < open =>
|
||||
isBuyVolume := false
|
||||
isBuyVolume
|
||||
|
||||
if isBuyVolume
|
||||
posVol := posVol + volume
|
||||
posVol
|
||||
else
|
||||
negVol := negVol - volume
|
||||
negVol
|
||||
|
||||
posVol + negVol
|
||||
|
||||
|
||||
// Function to identify support and resistance boxes
|
||||
calcSupportResistance(src, lookbackPeriod) =>
|
||||
// Volume
|
||||
Vol = upAndDownVolume()
|
||||
vol_hi = ta.highest(Vol / 2.5, vol_len)
|
||||
vol_lo = ta.lowest(Vol / 2.5, vol_len)
|
||||
|
||||
var float supportLevel = na
|
||||
var float supportLevel_1 = na
|
||||
var float resistanceLevel = na
|
||||
var float resistanceLevel_1 = na
|
||||
var box sup = na
|
||||
var box res = na
|
||||
var color res_color = na
|
||||
var color sup_color = na
|
||||
var float multi = na
|
||||
|
||||
var bool brekout_res = false
|
||||
var bool brekout_sup = false
|
||||
var bool res_holds = false
|
||||
var bool sup_holds = false
|
||||
|
||||
// Find pivot points
|
||||
pivotHigh = ta.pivothigh(src, lookbackPeriod, lookbackPeriod)
|
||||
pivotLow = ta.pivotlow(src, lookbackPeriod, lookbackPeriod)
|
||||
// Box width
|
||||
atr = ta.atr(200)
|
||||
withd = atr * box_withd
|
||||
|
||||
// Volume range for color gradient
|
||||
vol_highest = ta.highest(Vol, 25)
|
||||
vol_lowest = ta.lowest(Vol, 25)
|
||||
|
||||
// Find support levels with Positive Volume
|
||||
if not na(pivotLow) and Vol > vol_hi
|
||||
|
||||
supportLevel := pivotLow
|
||||
supportLevel_1 := supportLevel - withd
|
||||
|
||||
topLeft = chart.point.from_index(bar_index - lookbackPeriod, supportLevel)
|
||||
bottomRight = chart.point.from_index(bar_index, supportLevel_1)
|
||||
|
||||
sup_color := color.from_gradient(Vol, 0, vol_highest, color(na), color.new(color.green, 30))
|
||||
|
||||
sup := box.new(top_left = topLeft, bottom_right = bottomRight, border_color = color.green, border_width = 1, bgcolor = sup_color, text = 'Vol: ' + str.tostring(math.round(Vol, 2)), text_color = chart.fg_color, text_size = size.small)
|
||||
sup
|
||||
|
||||
|
||||
// Find resistance levels with Negative Volume
|
||||
if not na(pivotHigh) and Vol < vol_lo
|
||||
|
||||
resistanceLevel := pivotHigh
|
||||
resistanceLevel_1 := resistanceLevel + withd
|
||||
|
||||
topLeft = chart.point.from_index(bar_index - lookbackPeriod, resistanceLevel)
|
||||
bottomRight = chart.point.from_index(bar_index, resistanceLevel_1)
|
||||
|
||||
res_color := color.from_gradient(Vol, vol_lowest, 0, color.new(color.red, 30), color(na))
|
||||
|
||||
res := box.new(top_left = topLeft, bottom_right = bottomRight, border_color = color.red, border_width = 1, bgcolor = res_color, text = 'Vol: ' + str.tostring(math.round(Vol, 2)), text_color = chart.fg_color, text_size = size.small)
|
||||
res
|
||||
|
||||
// Adaptive Box Len
|
||||
sup.set_right(bar_index + 1)
|
||||
res.set_right(bar_index + 1)
|
||||
|
||||
// Break of support or resistance conditions
|
||||
brekout_res := ta.crossover(low, resistanceLevel_1)
|
||||
res_holds := ta.crossunder(high, resistanceLevel)
|
||||
|
||||
sup_holds := ta.crossover(low, supportLevel)
|
||||
brekout_sup := ta.crossunder(high, supportLevel_1)
|
||||
|
||||
// Change Color of Support to red if it was break, change color of resistance to green if it was break
|
||||
if brekout_sup
|
||||
sup.set_bgcolor(color.new(color.red, 80))
|
||||
sup.set_border_color(color.red)
|
||||
sup.set_border_style(line.style_dashed)
|
||||
|
||||
if sup_holds
|
||||
sup.set_bgcolor(sup_color)
|
||||
sup.set_border_color(color.green)
|
||||
sup.set_border_style(line.style_solid)
|
||||
|
||||
if brekout_res
|
||||
res.set_bgcolor(color.new(color.green, 80))
|
||||
res.set_border_color(color.new(color.green, 0))
|
||||
res.set_border_style(line.style_dashed)
|
||||
|
||||
if res_holds
|
||||
res.set_bgcolor(res_color)
|
||||
res.set_border_color(color.new(color.red, 0))
|
||||
res.set_border_style(line.style_solid)
|
||||
|
||||
[supportLevel, resistanceLevel, brekout_res, res_holds, sup_holds, brekout_sup]
|
||||
|
||||
|
||||
// Calculate support and resistance levels and their breakouts
|
||||
[supportLevel, resistanceLevel, brekout_res, res_holds, sup_holds, brekout_sup] = calcSupportResistance(close, lookbackPeriod)
|
||||
|
||||
|
||||
// Check if Resistance become Support or Support Become Resistance
|
||||
var bool res_is_sup = false
|
||||
var bool sup_is_res = false
|
||||
|
||||
switch
|
||||
brekout_res =>
|
||||
res_is_sup := true
|
||||
res_is_sup
|
||||
res_holds =>
|
||||
res_is_sup := false
|
||||
res_is_sup
|
||||
|
||||
switch
|
||||
brekout_sup =>
|
||||
sup_is_res := true
|
||||
sup_is_res
|
||||
sup_holds =>
|
||||
sup_is_res := false
|
||||
sup_is_res
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙑𝙄𝙎𝙐𝘼𝙇𝙄𝙕𝘼𝙏𝙄𝙊𝙉
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
// Plot Res and Sup breakouts and holds
|
||||
plotchar(res_holds, 'Resistance Holds', '◆', color = #e92929, size = size.tiny, location = location.abovebar, offset = -1)
|
||||
plotchar(sup_holds, 'Support Holds', '◆', color = #20ca26, size = size.tiny, location = location.belowbar, offset = -1)
|
||||
|
||||
plotchar(brekout_res and res_is_sup[1], 'Resistance as Support Holds', '◆', color = #20ca26, size = size.tiny, location = location.belowbar, offset = -1)
|
||||
plotchar(brekout_sup and sup_is_res[1], 'Support as Resistance Holds', '◆', color = #e92929, size = size.tiny, location = location.abovebar, offset = -1)
|
||||
|
||||
// Break Out Labels
|
||||
if brekout_sup and not sup_is_res[1]
|
||||
label.new(bar_index[1], supportLevel[1], text = 'Break Sup', style = label.style_label_down, color = #7e1e1e, textcolor = chart.fg_color, size = size.small)
|
||||
|
||||
if brekout_res and not res_is_sup[1]
|
||||
label.new(bar_index[1], resistanceLevel[1], text = 'Break Res', style = label.style_label_up, color = #2b6d2d, textcolor = chart.fg_color, size = size.small)
|
||||
|
||||
// 警报标记 - 醒目的视觉提示
|
||||
// 支撑位保持警报标记
|
||||
if sup_holds
|
||||
label.new(bar_index, low, text = '🔔SUP', style = label.style_label_down, color = color.new(color.lime, 0), textcolor = color.black, size = size.large, tooltip = '支撑位保持警报')
|
||||
|
||||
// 阻力位保持警报标记
|
||||
if res_holds
|
||||
label.new(bar_index, high, text = '🔔RES', style = label.style_label_up, color = color.new(color.red, 0), textcolor = color.white, size = size.large, tooltip = '阻力位保持警报')
|
||||
|
||||
// 支撑位突破警报标记
|
||||
if brekout_sup
|
||||
label.new(bar_index[1], supportLevel[1], text = '🚨SUP⬇', style = label.style_label_down, color = color.new(color.orange, 0), textcolor = color.black, size = size.large, tooltip = '支撑位突破警报')
|
||||
|
||||
// 阻力位突破警报标记
|
||||
if brekout_res
|
||||
label.new(bar_index[1], resistanceLevel[1], text = '🚨RES⬆', style = label.style_label_up, color = color.new(color.aqua, 0), textcolor = color.black, size = size.large, tooltip = '阻力位突破警报')
|
||||
|
||||
// 阻力转支撑警报标记
|
||||
if brekout_res and res_is_sup[1]
|
||||
label.new(bar_index[1], resistanceLevel[1], text = '⭐R→S', style = label.style_label_down, color = color.new(color.purple, 0), textcolor = color.white, size = size.large, tooltip = '阻力转支撑保持警报')
|
||||
|
||||
// 支撑转阻力警报标记
|
||||
if brekout_sup and sup_is_res[1]
|
||||
label.new(bar_index[1], supportLevel[1], text = '⭐S→R', style = label.style_label_up, color = color.new(color.maroon, 0), textcolor = color.white, size = size.large, tooltip = '支撑转阻力保持警报')
|
||||
|
||||
// 全局作用域的plotshape - 警报形状标记
|
||||
plotshape(sup_holds, title = '支撑保持警报', style = shape.triangleup, location = location.belowbar, color = color.new(color.lime, 0), size = size.large)
|
||||
plotshape(res_holds, title = '阻力保持警报', style = shape.triangledown, location = location.abovebar, color = color.new(color.red, 0), size = size.large)
|
||||
plotshape(brekout_sup, title = '支撑突破警报', style = shape.xcross, location = location.belowbar, color = color.new(color.orange, 0), size = size.large)
|
||||
plotshape(brekout_res, title = '阻力突破警报', style = shape.xcross, location = location.abovebar, color = color.new(color.aqua, 0), size = size.large)
|
||||
plotshape(brekout_res and res_is_sup[1], title = '阻力转支撑警报', style = shape.diamond, location = location.belowbar, color = color.new(color.purple, 0), size = size.large)
|
||||
plotshape(brekout_sup and sup_is_res[1], title = '支撑转阻力警报', style = shape.diamond, location = location.abovebar, color = color.new(color.maroon, 0), size = size.large)
|
||||
|
||||
|
||||
// ◆
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝙋𝙍𝙄𝘾𝙀 𝙎𝙏𝘼𝙏𝙐𝙎 & 𝙈𝘼𝙍𝙆𝙀𝙏 𝙊𝙐𝙏𝙇𝙊𝙊𝙆
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
|
||||
// ═════════ 当前图表时间周期价格状态分析 ════════
|
||||
get_current_price_status() =>
|
||||
current_price = close
|
||||
support_level = supportLevel
|
||||
resistance_level = resistanceLevel
|
||||
|
||||
// 计算价格相对位置
|
||||
if na(support_level) and na(resistance_level)
|
||||
"无明确支撑阻力"
|
||||
else if na(support_level)
|
||||
if current_price > resistance_level
|
||||
"突破阻力位上方"
|
||||
else if current_price >= resistance_level * 0.995
|
||||
"接近阻力位"
|
||||
else
|
||||
"阻力位下方"
|
||||
else if na(resistance_level)
|
||||
if current_price < support_level
|
||||
"跌破支撑位下方"
|
||||
else if current_price <= support_level * 1.005
|
||||
"接近支撑位"
|
||||
else
|
||||
"支撑位上方"
|
||||
else
|
||||
range_size = resistance_level - support_level
|
||||
price_position = (current_price - support_level) / range_size
|
||||
|
||||
if current_price > resistance_level
|
||||
"突破阻力位上方"
|
||||
else if current_price < support_level
|
||||
"跌破支撑位下方"
|
||||
else if price_position >= 0.8
|
||||
"接近阻力位"
|
||||
else if price_position <= 0.2
|
||||
"接近支撑位"
|
||||
else
|
||||
"区间中部运行"
|
||||
|
||||
// ═════════ 市场观点生成 ════════
|
||||
get_market_outlook() =>
|
||||
current_status = get_current_price_status()
|
||||
|
||||
// 基于价格状态和突破情况生成观点
|
||||
if brekout_res and res_is_sup[1]
|
||||
"看涨:阻力转支撑确认,建议关注回调买入机会"
|
||||
else if brekout_sup and sup_is_res[1]
|
||||
"看跌:支撑转阻力确认,建议关注反弹卖出机会"
|
||||
else if brekout_res
|
||||
"看涨:突破阻力位,建议关注回踩确认后的追涨机会"
|
||||
else if brekout_sup
|
||||
"看跌:跌破支撑位,建议关注反弹确认后的追跌机会"
|
||||
else if res_holds
|
||||
"中性偏空:阻力位有效,短期上涨受阻"
|
||||
else if sup_holds
|
||||
"中性偏多:支撑位有效,短期下跌受限"
|
||||
else if current_status == "接近阻力位"
|
||||
"谨慎:接近关键阻力位,注意突破或回落"
|
||||
else if current_status == "接近支撑位"
|
||||
"谨慎:接近关键支撑位,注意反弹或破位"
|
||||
else if current_status == "区间中部运行"
|
||||
"中性:价格在支撑阻力区间内震荡"
|
||||
else if current_status == "突破阻力位上方"
|
||||
"看涨:已突破阻力位,关注持续性"
|
||||
else if current_status == "跌破支撑位下方"
|
||||
"看跌:已跌破支撑位,关注反弹力度"
|
||||
else
|
||||
"观望:等待明确的支撑阻力信号"
|
||||
|
||||
// 获取当前价格状态和市场观点
|
||||
current_price_status = get_current_price_status()
|
||||
market_outlook = get_market_outlook()
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
// 𝘼𝙇𝙀𝙍𝙏 𝘾𝙊𝙉𝘿𝙄𝙏𝙄𝙊𝙉𝙎
|
||||
// ---------------------------------------------------------------------------------------------------------------------{
|
||||
|
||||
// 支撑位保持警报
|
||||
alertcondition(sup_holds, title = '支撑位保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑位保持","位置":"支撑位","信号":"support_holds","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 阻力位保持警报
|
||||
alertcondition(res_holds, title = '阻力位保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力位保持","位置":"阻力位","信号":"resistance_holds","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 支撑位突破警报
|
||||
alertcondition(brekout_sup, title = '支撑位突破', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑位突破","位置":"支撑位下方","信号":"support_breakout","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 阻力位突破警报
|
||||
alertcondition(brekout_res, title = '阻力位突破', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力位突破","位置":"阻力位上方","信号":"resistance_breakout","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 阻力转支撑警报
|
||||
alertcondition(brekout_res and res_is_sup[1], title = '阻力转支撑保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"阻力转支撑保持","位置":"前阻力位","信号":"resistance_as_support","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// 支撑转阻力警报
|
||||
alertcondition(brekout_sup and sup_is_res[1], title = '支撑转阻力保持', message = '{"指标名称":"SRBR","交易对":"{{ticker}}","周期":"{{interval}}","支撑位":"{{plot("supportLevel")}}","阻力位":"{{plot("resistanceLevel")}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","触发时间":"{{timenow}}","时间":"{{time}}","事件":"支撑转阻力保持","位置":"前支撑位","信号":"support_as_resistance","价格状态":"' + current_price_status + '","市场观点":"' + market_outlook + '"}')
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------}
|
||||
503
tmfs.pine
Normal file
503
tmfs.pine
Normal file
@@ -0,0 +1,503 @@
|
||||
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
|
||||
// https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// Original concepts by FibonacciFlux, rewritten for clarity and functionality
|
||||
|
||||
//@version=6
|
||||
indicator('Trendline Breaks 带警报', shorttitle = "TMFS Indicator alerts", overlay = true)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 1: FIBONACCI SUPERTREND CONFIGURATION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Common ATR period for all supertrend calculations
|
||||
atrPeriod = input.int(13, 'ATR Length', minval = 1, tooltip="ATR period used for volatility calculation")
|
||||
|
||||
// Fibonacci-based supertrend factor inputs
|
||||
factor1 = input.float(0.618, 'Factor 1 (Weak/Fibonacci)', minval = 0.01, step = 0.01, tooltip="First Fibonacci factor (0.618)")
|
||||
factor2 = input.float(1.618, 'Factor 2 (Medium/Golden Ratio)', minval = 0.01, step = 0.01, tooltip="Second Fibonacci factor (1.618)")
|
||||
factor3 = input.float(2.618, 'Factor 3 (Strong/Extended Fib)', minval = 0.01, step = 0.01, tooltip="Third Fibonacci factor (2.618)")
|
||||
|
||||
// Calculate the three Supertrend lines with different sensitivity levels
|
||||
[supertrend1, direction1] = ta.supertrend(factor1, atrPeriod)
|
||||
[supertrend2, direction2] = ta.supertrend(factor2, atrPeriod)
|
||||
[supertrend3, direction3] = ta.supertrend(factor3, atrPeriod)
|
||||
|
||||
// Handle initial values (first bar)
|
||||
supertrend1 := barstate.isfirst ? na : supertrend1
|
||||
supertrend2 := barstate.isfirst ? na : supertrend2
|
||||
supertrend3 := barstate.isfirst ? na : supertrend3
|
||||
|
||||
// Calculate average of the three supertends and a smoothed version
|
||||
superlength = input.int(21, "Smoothing Length", tooltip="EMA length for smoothing the average supertrend")
|
||||
average_trend = (supertrend1 + supertrend2 + supertrend3) / 3
|
||||
smoothed_trend = ta.ema(average_trend, superlength)
|
||||
|
||||
// Plot the supertrend lines and fill the area between them
|
||||
trend_plot = plot(average_trend, color = average_trend > average_trend[1] ? color.green : color.red, title="Average Supertrend")
|
||||
smoothed_plot = plot(smoothed_trend, linewidth = 2, color = smoothed_trend > smoothed_trend[1] ? color.green : color.red, title="Smoothed Supertrend")
|
||||
fill(trend_plot, smoothed_plot, color = average_trend > smoothed_trend ? color.new(color.green, 50) : color.new(color.red, 50), title="Trend Direction Fill")
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 2: TRENDLINE DETECTION AND DRAWING
|
||||
//----------------------------------------------------------
|
||||
|
||||
// User settings for Swing Trend Lines
|
||||
swing_length = input.int(8, 'Swing Lookback Period', tooltip="Number of bars to look back for pivot points")
|
||||
atr_multiplier = input.float(1.0, 'ATR Slope Multiplier', minval = 0.0, step = 0.1, tooltip="Multiplier for ATR to control trendline slope")
|
||||
show_extended_lines = input.bool(true, 'Show Extended Lines', tooltip="Display dashed extensions for trendlines")
|
||||
enable_backpainting = input.bool(true, 'Use Backpainting', tooltip="Enable backpainting to move indicators to pivot point")
|
||||
|
||||
// Color settings for trendlines
|
||||
uptrend_color = color.new(color.teal, 0)
|
||||
downtrend_color = color.new(color.red, 0)
|
||||
|
||||
// Variable initialization for trendlines
|
||||
var float upper_trendline = na
|
||||
var float lower_trendline = na
|
||||
var float upper_slope = na
|
||||
var float lower_slope = na
|
||||
var line upline_extension = na
|
||||
var line downline_extension = na
|
||||
|
||||
// Offset for backpainting
|
||||
offset = enable_backpainting ? swing_length : 0
|
||||
bar_idx = bar_index
|
||||
|
||||
// Get pivot high and low points
|
||||
pivot_high = ta.pivothigh(swing_length, swing_length)
|
||||
pivot_low = ta.pivotlow(swing_length, swing_length)
|
||||
|
||||
// Calculate ATR for slope
|
||||
atr_value = ta.atr(swing_length)
|
||||
slope = atr_value / swing_length * atr_multiplier
|
||||
|
||||
// Update upper trendline when pivot high is detected or extend existing trendline
|
||||
if bool(pivot_high)
|
||||
upper_slope := slope
|
||||
upper_trendline := pivot_high
|
||||
else
|
||||
upper_trendline := nz(upper_trendline) - nz(upper_slope)
|
||||
|
||||
// Update lower trendline when pivot low is detected or extend existing trendline
|
||||
if bool(pivot_low)
|
||||
lower_slope := slope
|
||||
lower_trendline := pivot_low
|
||||
else
|
||||
lower_trendline := nz(lower_trendline) + nz(lower_slope)
|
||||
|
||||
// Create and update extended visualization lines if enabled
|
||||
if show_extended_lines
|
||||
// Initialize line objects if not already created
|
||||
if na(upline_extension)
|
||||
upline_extension := line.new(na, na, na, na, extend = extend.right, style = line.style_dashed, color = uptrend_color)
|
||||
|
||||
if na(downline_extension)
|
||||
downline_extension := line.new(na, na, na, na, extend = extend.right, style = line.style_dashed, color = downtrend_color)
|
||||
|
||||
// Update upper trendline extension when a new pivot high is confirmed
|
||||
if bool(pivot_high)
|
||||
line.set_xy1(upline_extension, bar_idx - offset, enable_backpainting ? pivot_high : upper_trendline)
|
||||
line.set_xy2(upline_extension, bar_idx - offset + 1, enable_backpainting ? pivot_high - slope : upper_trendline - slope)
|
||||
|
||||
// Update lower trendline extension when a new pivot low is confirmed
|
||||
if bool(pivot_low)
|
||||
line.set_xy1(downline_extension, bar_idx - offset, enable_backpainting ? pivot_low : lower_trendline)
|
||||
line.set_xy2(downline_extension, bar_idx - offset + 1, enable_backpainting ? pivot_low + slope : lower_trendline + slope)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 3: BREAKOUT DETECTION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Track breakouts above upper trendline and below lower trendline
|
||||
// Initialize tracking variables for breakout conditions
|
||||
var int upper_breakout_state = 0 // State variable to track upper breakout condition
|
||||
var int lower_breakout_state = 0 // State variable to track lower breakout condition
|
||||
|
||||
// Detect breakouts
|
||||
bool upper_breakout = close > upper_trendline
|
||||
bool lower_breakout = close < lower_trendline
|
||||
|
||||
// Update state variables to track when breakouts occur
|
||||
upper_breakout_state := bool(pivot_high) ? 0 : upper_breakout ? 1 : upper_breakout_state
|
||||
lower_breakout_state := bool(pivot_low) ? 0 : lower_breakout ? 1 : lower_breakout_state
|
||||
|
||||
// Plot trendlines with appropriate offsets
|
||||
plot(enable_backpainting ? upper_trendline : upper_trendline, color = bool(pivot_high) ? na : uptrend_color, linewidth = 2, offset = -offset, title = 'Upper Trendline')
|
||||
plot(enable_backpainting ? lower_trendline : lower_trendline, color = bool(pivot_low) ? na : downtrend_color, linewidth = 2, offset = -offset, title = 'Lower Trendline')
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 4: DIRECTIONAL MOVEMENT INDEX (DMI) CALCULATION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// DMI Length parameter
|
||||
dmi_length = input.int(13, "DMI Length", tooltip="Length for DMI calculation")
|
||||
|
||||
// True Range calculation
|
||||
true_range = math.max(math.max(high - low, math.abs(high - nz(close[1]))), math.abs(low - nz(close[1])))
|
||||
|
||||
// Directional Movement calculations
|
||||
directional_movement_plus = high - nz(high[1]) > nz(low[1]) - low ? math.max(high - nz(high[1]), 0) : 0
|
||||
directional_movement_minus = nz(low[1]) - low > high - nz(high[1]) ? math.max(nz(low[1]) - low, 0) : 0
|
||||
|
||||
// Smoothed calculations for DMI
|
||||
var float smoothed_true_range = 0.0
|
||||
smoothed_true_range := nz(smoothed_true_range[1]) - nz(smoothed_true_range[1]) / dmi_length + true_range
|
||||
|
||||
var float smoothed_directional_plus = 0.0
|
||||
smoothed_directional_plus := nz(smoothed_directional_plus[1]) - nz(smoothed_directional_plus[1]) / dmi_length + directional_movement_plus
|
||||
|
||||
var float smoothed_directional_minus = 0.0
|
||||
smoothed_directional_minus := nz(smoothed_directional_minus[1]) - nz(smoothed_directional_minus[1]) / dmi_length + directional_movement_minus
|
||||
|
||||
// Calculate DI+ and DI- values
|
||||
di_plus = smoothed_directional_plus / smoothed_true_range * 100
|
||||
di_minus = smoothed_directional_minus / smoothed_true_range * 100
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 5: SIGNAL DEFINITION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// SMA settings for trend confirmation
|
||||
fast_sma_length = input.int(defval = 2, title = 'Fast SMA Length', minval = 1, group = 'Signal Settings')
|
||||
slow_sma_length = input.int(defval = 3, title = 'Slow SMA Length', minval = 1, group = 'Signal Settings')
|
||||
|
||||
// Calculate SMA crossovers
|
||||
fast_sma = ta.sma(close, fast_sma_length)
|
||||
slow_sma = ta.sma(close, slow_sma_length)
|
||||
|
||||
// Detect SMA crossovers
|
||||
sma_cross_up = ta.crossover(fast_sma, slow_sma)
|
||||
sma_cross_down = ta.crossunder(fast_sma, slow_sma)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 6: ENTRY AND EXIT CONDITIONS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Define entry conditions
|
||||
long_entry_condition = upper_breakout_state > upper_breakout_state[1] and di_plus > di_minus and close > smoothed_trend
|
||||
short_entry_condition = lower_breakout_state > lower_breakout_state[1] and di_minus > di_plus and close < smoothed_trend
|
||||
|
||||
// Define exit conditions
|
||||
long_exit_condition = ta.crossunder(close[1], smoothed_trend)
|
||||
short_exit_condition = ta.crossover(close[1], smoothed_trend)
|
||||
|
||||
// @function Display BUY/SELL labels on chart
|
||||
plotshape(long_entry_condition, title='BUY', text='BUY', location=location.belowbar,
|
||||
style=shape.labelup, size=size.tiny, color=color.new(color.green, 0), textcolor=color.new(color.white, 0))
|
||||
plotshape(short_entry_condition, title='SELL', text='SELL', location=location.abovebar,
|
||||
style=shape.labeldown, size=size.tiny, color=color.new(color.red, 0), textcolor=color.new(color.white, 0))
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 7: STOP LOSS AND TAKE PROFIT SETTINGS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Common settings
|
||||
atr_length = input.int(13, 'ATR Length for SL/TP', minval = 1, group = 'Risk Management')
|
||||
|
||||
// Variable to track if stop loss is triggered
|
||||
var bool long_trailing_tp_executed = false
|
||||
var bool short_trailing_tp_executed = false
|
||||
|
||||
// Store ATR at position entry
|
||||
float entry_atr = ta.valuewhen(long_entry_condition or short_entry_condition, ta.atr(atr_length), 0)
|
||||
|
||||
// Stop Loss settings
|
||||
stop_loss_method = input.string(defval = 'ATR', title = 'Stop Loss Method', options = ['PERC', 'ATR'], group = 'Stop Loss')
|
||||
long_stop_loss_percent = input.float(defval = 0.75, title = 'Long Position Stop Loss %', minval = 0.05, maxval = 100, step = 0.05, group = 'Stop Loss') / 100
|
||||
short_stop_loss_percent = input.float(defval = 0.75, title = 'Short Position Stop Loss %', minval = 0.05, maxval = 100, step = 0.05, group = 'Stop Loss') / 100
|
||||
long_stop_loss_atr_multiplier = input.float(defval = 8.0, title = 'Long Position ATR Multiplier', minval = 0.1, step = 0.1, group = 'Stop Loss')
|
||||
short_stop_loss_atr_multiplier = input.float(defval = 8.0, title = 'Short Position ATR Multiplier', minval = 0.1, step = 0.1, group = 'Stop Loss')
|
||||
stop_loss_trailing_mode = input.string(defval = 'ON', title = 'Trailing Stop Loss Mode', options = ['TP', 'ON', 'OFF'], tooltip = 'ON: Always trail, TP: Trail after Take Profit hit, OFF: Fixed stop', group = 'Stop Loss')
|
||||
break_even_enabled = input.bool(defval = true, title = 'Move to Break Even After TP', group = 'Stop Loss')
|
||||
|
||||
// Take Profit settings
|
||||
take_profit_quantity_percent = input.float(defval = 100, title = 'Take Profit Quantity %', minval = 0.0, maxval = 100, step = 1.0, group = 'Take Profit')
|
||||
take_profit_method = input.string(defval = 'PERC', title = 'Take Profit Method', options = ['PERC', 'ATR', 'RR'], group = 'Take Profit')
|
||||
long_take_profit_percent = input.float(defval = 1, title = 'Long Position Take Profit %', minval = 0.05, step = 0.05, group = 'Take Profit') / 100
|
||||
short_take_profit_percent = input.float(defval = 1, title = 'Short Position Take Profit %', minval = 0.05, step = 0.05, group = 'Take Profit') / 100
|
||||
long_take_profit_atr_multiplier = input.float(defval = 1.5, title = 'Long Position TP ATR Multiplier', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
short_take_profit_atr_multiplier = input.float(defval = 2, title = 'Short Position TP ATR Multiplier', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
long_risk_reward_ratio = input.float(defval = 0.6, title = 'Long Position Risk/Reward Ratio', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
short_risk_reward_ratio = input.float(defval = 1, title = 'Short Position Risk/Reward Ratio', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
trailing_take_profit_enabled = input.bool(defval = true, title = 'Enable Trailing Take Profit', group = 'Take Profit')
|
||||
deviation_method = input.string(defval = 'PERC', title = 'Trailing Deviation Method', options = ['PERC', 'ATR'], group = 'Take Profit')
|
||||
deviation_percent = input.float(defval = 0.01, title = 'Trailing Deviation %', minval = 0.01, maxval = 100, step = 0.05, group = 'Take Profit') / 100
|
||||
deviation_atr_multiplier = input.float(defval = 1.0, title = 'Trailing Deviation ATR Multiplier', minval = 0.01, step = 0.05, group = 'Take Profit')
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 9: CALCULATE STOP LOSS LEVELS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Calculate long position stop loss price based on selected method
|
||||
get_long_stop_loss_price(base_price) =>
|
||||
switch stop_loss_method
|
||||
'PERC' => base_price * (1 - long_stop_loss_percent)
|
||||
'ATR' => base_price - long_stop_loss_atr_multiplier * entry_atr
|
||||
=> na
|
||||
|
||||
// Determine if trailing should be active for long position
|
||||
long_tp_trailing_enabled = stop_loss_trailing_mode == 'ON' or (stop_loss_trailing_mode == 'TP' and long_trailing_tp_executed)
|
||||
|
||||
// Calculate and maintain stop loss price for long positions
|
||||
var float long_stop_loss_price = na
|
||||
long_stop_loss_price := if strategy.position_size > 0
|
||||
if long_entry_condition
|
||||
get_long_stop_loss_price(close)
|
||||
else
|
||||
stop_price = get_long_stop_loss_price(long_tp_trailing_enabled ? high : strategy.position_avg_price)
|
||||
stop_price := break_even_enabled and long_trailing_tp_executed ? math.max(stop_price, strategy.position_avg_price) : stop_price
|
||||
math.max(stop_price, nz(long_stop_loss_price[1]))
|
||||
else
|
||||
na
|
||||
|
||||
// Calculate short position stop loss price based on selected method
|
||||
get_short_stop_loss_price(base_price) =>
|
||||
switch stop_loss_method
|
||||
'PERC' => base_price * (1 + short_stop_loss_percent)
|
||||
'ATR' => base_price + short_stop_loss_atr_multiplier * entry_atr
|
||||
=> na
|
||||
|
||||
// Determine if trailing should be active for short position
|
||||
short_tp_trailing_enabled = stop_loss_trailing_mode == 'ON' or (stop_loss_trailing_mode == 'TP' and short_trailing_tp_executed)
|
||||
|
||||
// Calculate and maintain stop loss price for short positions
|
||||
var float short_stop_loss_price = na
|
||||
short_stop_loss_price := if strategy.position_size < 0
|
||||
if short_entry_condition
|
||||
get_short_stop_loss_price(close)
|
||||
else
|
||||
var float stop_price = get_short_stop_loss_price(short_tp_trailing_enabled ? low : strategy.position_avg_price) // stop_price を var float で宣言
|
||||
if break_even_enabled and short_trailing_tp_executed
|
||||
stop_price := math.min(stop_price, strategy.position_avg_price)
|
||||
short_stop_loss_price := math.min(stop_price, nz(short_stop_loss_price[1], 999999.9))
|
||||
else
|
||||
na
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 9: CALCULATE TAKE PROFIT LEVELS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Calculate long position take profit price based on selected method
|
||||
get_long_take_profit_price() =>
|
||||
switch take_profit_method
|
||||
'PERC' => close * (1 + long_take_profit_percent)
|
||||
'ATR' => close + long_take_profit_atr_multiplier * entry_atr
|
||||
'RR' => close + long_risk_reward_ratio * (close - get_long_stop_loss_price(close))
|
||||
=> na
|
||||
|
||||
// Calculate and maintain take profit price for long positions
|
||||
var float long_take_profit_price = na
|
||||
long_take_profit_price := if strategy.position_size > 0 and not long_trailing_tp_executed
|
||||
if long_entry_condition
|
||||
get_long_take_profit_price()
|
||||
else
|
||||
nz(long_take_profit_price[1], get_long_take_profit_price())
|
||||
else
|
||||
na
|
||||
|
||||
// Update trailing take profit execution flag for long positions
|
||||
long_trailing_tp_executed := strategy.position_size > 0 and (long_trailing_tp_executed[1] or strategy.position_size < strategy.position_size[1] or (strategy.position_size[1] == 0 and high >= long_take_profit_price))
|
||||
|
||||
// Calculate trailing step size in ticks for long positions
|
||||
long_trailing_tp_step_ticks = switch deviation_method
|
||||
'PERC' => long_take_profit_price * deviation_percent / syminfo.mintick
|
||||
'ATR' => deviation_atr_multiplier * entry_atr / syminfo.mintick
|
||||
=> na
|
||||
|
||||
// Calculate short position take profit price based on selected method
|
||||
get_short_take_profit_price() =>
|
||||
switch take_profit_method
|
||||
'PERC' => close * (1 - short_take_profit_percent)
|
||||
'ATR' => close - short_take_profit_atr_multiplier * entry_atr
|
||||
'RR' => close - short_risk_reward_ratio * (get_short_stop_loss_price(close) - close)
|
||||
=> na
|
||||
|
||||
// Calculate and maintain take profit price for short positions
|
||||
var float short_take_profit_price = na
|
||||
short_take_profit_price := if strategy.position_size < 0 and not short_trailing_tp_executed
|
||||
if short_entry_condition
|
||||
get_short_take_profit_price()
|
||||
else
|
||||
nz(short_take_profit_price[1], get_short_take_profit_price())
|
||||
else
|
||||
na
|
||||
|
||||
// Update trailing take profit execution flag for short positions
|
||||
short_trailing_tp_executed := strategy.position_size < 0 and (short_trailing_tp_executed[1] or strategy.position_size > strategy.position_size[1] or (strategy.position_size[1] == 0 and low <= short_take_profit_price))
|
||||
|
||||
// Calculate trailing step size in ticks for short positions
|
||||
short_trailing_tp_step_ticks = switch deviation_method
|
||||
'PERC' => short_take_profit_price * deviation_percent / syminfo.mintick
|
||||
'ATR' => deviation_atr_multiplier * entry_atr / syminfo.mintick
|
||||
=> na
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 11: STRATEGY EXECUTION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Enter long position when conditions are met
|
||||
if long_entry_condition
|
||||
strategy.entry('L', strategy.long, comment = "LONG")
|
||||
|
||||
// Enter short position when conditions are met
|
||||
if short_entry_condition
|
||||
strategy.entry('S', strategy.short, comment = "SHORT")
|
||||
|
||||
// Exit long position when exit conditions are met
|
||||
if long_exit_condition
|
||||
strategy.close('L', comment = "SL Triggered")
|
||||
|
||||
// Exit short position when exit conditions are met
|
||||
if short_exit_condition
|
||||
strategy.close('S', comment = "SL Triggered")
|
||||
|
||||
// Set up take profit and stop loss for long positions
|
||||
strategy.exit(id = 'Long Take Profit / Stop Loss', from_entry = 'L', qty_percent = take_profit_quantity_percent, limit = trailing_take_profit_enabled ? na : long_take_profit_price, stop = long_stop_loss_price, trail_price = trailing_take_profit_enabled ? long_take_profit_price : na, trail_offset = trailing_take_profit_enabled ? long_trailing_tp_step_ticks : na, comment = "TP/SL Triggered")
|
||||
strategy.exit(id = 'Long Stop Loss', from_entry = 'L', stop = long_stop_loss_price, comment = "SL Triggered")
|
||||
|
||||
// Set up take profit and stop loss for short positions
|
||||
strategy.exit(id = 'Short Take Profit / Stop Loss', from_entry = 'S', qty_percent = take_profit_quantity_percent, limit = trailing_take_profit_enabled ? na : short_take_profit_price, stop = short_stop_loss_price, trail_price = trailing_take_profit_enabled ? short_take_profit_price : na, trail_offset = trailing_take_profit_enabled ? short_trailing_tp_step_ticks : na, comment = "TP/SL Triggered")
|
||||
strategy.exit(id = 'Short Stop Loss', from_entry = 'S', stop = short_stop_loss_price, comment = "SL Triggered")
|
||||
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_long_entry = 0
|
||||
var int last_alert_short_entry = 0
|
||||
var int last_alert_long_exit = 0
|
||||
var int last_alert_short_exit = 0
|
||||
var int last_alert_upper_breakout = 0
|
||||
var int last_alert_lower_breakout = 0
|
||||
var int last_alert_sma_cross_up = 0
|
||||
var int last_alert_sma_cross_down = 0
|
||||
var int last_alert_dmi_bullish = 0
|
||||
var int last_alert_dmi_bearish = 0
|
||||
var int last_alert_trend_bullish = 0
|
||||
var int last_alert_trend_bearish = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 入场信号警报 - 每分钟限制
|
||||
if long_entry_condition and current_minute > last_alert_long_entry
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","事件":"多头入场信号触发","信号":"buy","备注":"趋势线突破+DMI确认"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_long_entry := current_minute
|
||||
|
||||
if short_entry_condition and current_minute > last_alert_short_entry
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","事件":"空头入场信号触发","信号":"sell","备注":"趋势线突破+DMI确认"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_short_entry := current_minute
|
||||
|
||||
// 出场信号警报 - 每分钟限制
|
||||
if long_exit_condition and current_minute > last_alert_long_exit
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","事件":"多头出场信号触发","信号":"exit_long","备注":"价格跌破平滑超趋势"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_long_exit := current_minute
|
||||
|
||||
if short_exit_condition and current_minute > last_alert_short_exit
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","事件":"空头出场信号触发","信号":"exit_short","备注":"价格突破平滑超趋势"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_short_exit := current_minute
|
||||
|
||||
// 趋势线突破警报 - 每分钟限制
|
||||
if upper_breakout and not upper_breakout[1] and current_minute > last_alert_upper_breakout
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","上趋势线":"' + str.tostring(upper_trendline, '#.####') + '","事件":"价格突破上趋势线","信号":"upper_breakout","备注":"潜在看涨信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_upper_breakout := current_minute
|
||||
|
||||
if lower_breakout and not lower_breakout[1] and current_minute > last_alert_lower_breakout
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","下趋势线":"' + str.tostring(lower_trendline, '#.####') + '","事件":"价格跌破下趋势线","信号":"lower_breakout","备注":"潜在看跌信号"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_lower_breakout := current_minute
|
||||
|
||||
// SMA交叉警报 - 每分钟限制
|
||||
if sma_cross_up and current_minute > last_alert_sma_cross_up
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","快速SMA":"' + str.tostring(fast_sma, '#.####') + '","慢速SMA":"' + str.tostring(slow_sma, '#.####') + '","事件":"快速SMA上穿慢速SMA","信号":"sma_cross_up","备注":"短期趋势转多"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_sma_cross_up := current_minute
|
||||
|
||||
if sma_cross_down and current_minute > last_alert_sma_cross_down
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","快速SMA":"' + str.tostring(fast_sma, '#.####') + '","慢速SMA":"' + str.tostring(slow_sma, '#.####') + '","事件":"快速SMA下穿慢速SMA","信号":"sma_cross_down","备注":"短期趋势转空"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_sma_cross_down := current_minute
|
||||
|
||||
// DMI信号警报 - 每分钟限制
|
||||
if ta.crossover(di_plus, di_minus) and current_minute > last_alert_dmi_bullish
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","事件":"DI+上穿DI-","信号":"dmi_bullish","备注":"动量转向看涨"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_dmi_bullish := current_minute
|
||||
|
||||
if ta.crossunder(di_plus, di_minus) and current_minute > last_alert_dmi_bearish
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","事件":"DI+下穿DI-","信号":"dmi_bearish","备注":"动量转向看跌"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_dmi_bearish := current_minute
|
||||
|
||||
// 超趋势方向变化警报 - 每分钟限制
|
||||
if ta.crossover(close, smoothed_trend) and current_minute > last_alert_trend_bullish
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","事件":"价格上穿平滑超趋势","信号":"trend_bullish","备注":"趋势转向看涨"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_trend_bullish := current_minute
|
||||
|
||||
if ta.crossunder(close, smoothed_trend) and current_minute > last_alert_trend_bearish
|
||||
alert_message := '{"指标名称":"TMFS","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","事件":"价格下穿平滑超趋势","信号":"trend_bearish","备注":"趋势转向看跌"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_trend_bearish := current_minute
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(smoothed_trend, title = '平滑超趋势', display = display.none)
|
||||
plot(di_plus, title = 'DI+', display = display.none)
|
||||
plot(di_minus, title = 'DI-', display = display.none)
|
||||
plot(fast_sma, title = '快速SMA', display = display.none)
|
||||
plot(slow_sma, title = '慢速SMA', display = display.none)
|
||||
plot(upper_trendline, title = '上趋势线', display = display.none)
|
||||
plot(lower_trendline, title = '下趋势线', display = display.none)
|
||||
|
||||
// 入场信号警报
|
||||
alertcondition(long_entry_condition, title = 'TMFS多头入场', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"多头入场信号触发","信号":"buy","备注":"趋势线突破+DMI确认"}')
|
||||
|
||||
alertcondition(short_entry_condition, title = 'TMFS空头入场', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"空头入场信号触发","信号":"sell","备注":"趋势线突破+DMI确认"}')
|
||||
|
||||
// 出场信号警报
|
||||
alertcondition(long_exit_condition, title = 'TMFS多头出场', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"多头出场信号触发","信号":"exit_long","备注":"价格跌破平滑超趋势"}')
|
||||
|
||||
alertcondition(short_exit_condition, title = 'TMFS空头出场', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"空头出场信号触发","信号":"exit_short","备注":"价格突破平滑超趋势"}')
|
||||
|
||||
// 趋势线突破警报
|
||||
alertcondition(upper_breakout and not upper_breakout[1], title = '价格突破上趋势线', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","上趋势线":"{{plot("上趋势线")}}","事件":"价格突破上趋势线","信号":"upper_breakout","备注":"潜在看涨信号"}')
|
||||
|
||||
alertcondition(lower_breakout and not lower_breakout[1], title = '价格跌破下趋势线', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","下趋势线":"{{plot("下趋势线")}}","事件":"价格跌破下趋势线","信号":"lower_breakout","备注":"潜在看跌信号"}')
|
||||
|
||||
// SMA交叉警报
|
||||
alertcondition(sma_cross_up, title = '快速SMA上穿慢速SMA', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","快速SMA":"{{plot("快速SMA")}}","慢速SMA":"{{plot("慢速SMA")}}","事件":"快速SMA上穿慢速SMA","信号":"sma_cross_up","备注":"短期趋势转多"}')
|
||||
|
||||
alertcondition(sma_cross_down, title = '快速SMA下穿慢速SMA', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","快速SMA":"{{plot("快速SMA")}}","慢速SMA":"{{plot("慢速SMA")}}","事件":"快速SMA下穿慢速SMA","信号":"sma_cross_down","备注":"短期趋势转空"}')
|
||||
|
||||
// DMI信号警报
|
||||
alertcondition(ta.crossover(di_plus, di_minus), title = 'DI+上穿DI-', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"DI+上穿DI-","信号":"dmi_bullish","备注":"动量转向看涨"}')
|
||||
|
||||
alertcondition(ta.crossunder(di_plus, di_minus), title = 'DI+下穿DI-', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"DI+下穿DI-","信号":"dmi_bearish","备注":"动量转向看跌"}')
|
||||
|
||||
// 超趋势方向变化警报
|
||||
alertcondition(ta.crossover(close, smoothed_trend), title = '价格上穿平滑超趋势', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"价格上穿平滑超趋势","信号":"trend_bullish","备注":"趋势转向看涨"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, smoothed_trend), title = '价格下穿平滑超趋势', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"价格下穿平滑超趋势","信号":"trend_bearish","备注":"趋势转向看跌"}')
|
||||
|
||||
// 综合信号警报
|
||||
alertcondition(upper_breakout and di_plus > di_minus, title = '强势看涨信号', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","事件":"强势看涨信号","信号":"strong_bullish","备注":"趋势线突破+DMI看涨"}')
|
||||
|
||||
alertcondition(lower_breakout and di_minus > di_plus, title = '强势看跌信号', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","事件":"强势看跌信号","信号":"strong_bearish","备注":"趋势线跌破+DMI看跌"}')
|
||||
|
||||
// 趋势确认警报
|
||||
alertcondition(close > smoothed_trend and di_plus > di_minus, title = '多头趋势确认', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"多头趋势确认","信号":"bullish_trend_confirmed","备注":"价格在超趋势上方且DMI看涨"}')
|
||||
|
||||
alertcondition(close < smoothed_trend and di_minus > di_plus, title = '空头趋势确认', message = '{"指标名称":"TMFS","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"空头趋势确认","信号":"bearish_trend_confirmed","备注":"价格在超趋势下方且DMI看跌"}')
|
||||
|
||||
561
tmfs2.pine
Normal file
561
tmfs2.pine
Normal file
@@ -0,0 +1,561 @@
|
||||
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
|
||||
// https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// Original concepts by FibonacciFlux, rewritten for clarity and functionality
|
||||
|
||||
//@version=6
|
||||
strategy('Trendline Breaks 带警报2', shorttitle = "TMFS Strategy alerts2", overlay = true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 4,commission_type = strategy.commission.percent, commission_value = 0.03, pyramiding = 2 )
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 1: FIBONACCI SUPERTREND CONFIGURATION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Common ATR period for all supertrend calculations
|
||||
atrPeriod = input.int(13, 'ATR Length', minval = 1, tooltip="ATR period used for volatility calculation")
|
||||
|
||||
// Fibonacci-based supertrend factor inputs
|
||||
factor1 = input.float(0.618, 'Factor 1 (Weak/Fibonacci)', minval = 0.01, step = 0.01, tooltip="First Fibonacci factor (0.618)")
|
||||
factor2 = input.float(1.618, 'Factor 2 (Medium/Golden Ratio)', minval = 0.01, step = 0.01, tooltip="Second Fibonacci factor (1.618)")
|
||||
factor3 = input.float(2.618, 'Factor 3 (Strong/Extended Fib)', minval = 0.01, step = 0.01, tooltip="Third Fibonacci factor (2.618)")
|
||||
|
||||
// Calculate the three Supertrend lines with different sensitivity levels
|
||||
[supertrend1, direction1] = ta.supertrend(factor1, atrPeriod)
|
||||
[supertrend2, direction2] = ta.supertrend(factor2, atrPeriod)
|
||||
[supertrend3, direction3] = ta.supertrend(factor3, atrPeriod)
|
||||
|
||||
// Handle initial values (first bar)
|
||||
supertrend1 := barstate.isfirst ? na : supertrend1
|
||||
supertrend2 := barstate.isfirst ? na : supertrend2
|
||||
supertrend3 := barstate.isfirst ? na : supertrend3
|
||||
|
||||
// Calculate average of the three supertends and a smoothed version
|
||||
superlength = input.int(21, "Smoothing Length", tooltip="EMA length for smoothing the average supertrend")
|
||||
average_trend = (supertrend1 + supertrend2 + supertrend3) / 3
|
||||
smoothed_trend = ta.ema(average_trend, superlength)
|
||||
|
||||
// Plot the supertrend lines and fill the area between them
|
||||
trend_plot = plot(average_trend, color = average_trend > average_trend[1] ? color.green : color.red, title="Average Supertrend")
|
||||
smoothed_plot = plot(smoothed_trend, linewidth = 2, color = smoothed_trend > smoothed_trend[1] ? color.green : color.red, title="Smoothed Supertrend")
|
||||
fill(trend_plot, smoothed_plot, color = average_trend > smoothed_trend ? color.new(color.green, 50) : color.new(color.red, 50), title="Trend Direction Fill")
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 2: TRENDLINE DETECTION AND DRAWING
|
||||
//----------------------------------------------------------
|
||||
|
||||
// User settings for Swing Trend Lines
|
||||
swing_length = input.int(8, 'Swing Lookback Period', tooltip="Number of bars to look back for pivot points")
|
||||
atr_multiplier = input.float(1.0, 'ATR Slope Multiplier', minval = 0.0, step = 0.1, tooltip="Multiplier for ATR to control trendline slope")
|
||||
show_extended_lines = input.bool(true, 'Show Extended Lines', tooltip="Display dashed extensions for trendlines")
|
||||
enable_backpainting = input.bool(true, 'Use Backpainting', tooltip="Enable backpainting to move indicators to pivot point")
|
||||
|
||||
// Color settings for trendlines
|
||||
uptrend_color = color.new(color.teal, 0)
|
||||
downtrend_color = color.new(color.red, 0)
|
||||
|
||||
// Variable initialization for trendlines
|
||||
var float upper_trendline = na
|
||||
var float lower_trendline = na
|
||||
var float upper_slope = na
|
||||
var float lower_slope = na
|
||||
var line upline_extension = na
|
||||
var line downline_extension = na
|
||||
|
||||
// Offset for backpainting
|
||||
offset = enable_backpainting ? swing_length : 0
|
||||
bar_idx = bar_index
|
||||
|
||||
// Get pivot high and low points
|
||||
pivot_high = ta.pivothigh(swing_length, swing_length)
|
||||
pivot_low = ta.pivotlow(swing_length, swing_length)
|
||||
|
||||
// Calculate ATR for slope
|
||||
atr_value = ta.atr(swing_length)
|
||||
slope = atr_value / swing_length * atr_multiplier
|
||||
|
||||
// Update upper trendline when pivot high is detected or extend existing trendline
|
||||
if bool(pivot_high)
|
||||
upper_slope := slope
|
||||
upper_trendline := pivot_high
|
||||
else
|
||||
upper_trendline := nz(upper_trendline) - nz(upper_slope)
|
||||
|
||||
// Update lower trendline when pivot low is detected or extend existing trendline
|
||||
if bool(pivot_low)
|
||||
lower_slope := slope
|
||||
lower_trendline := pivot_low
|
||||
else
|
||||
lower_trendline := nz(lower_trendline) + nz(lower_slope)
|
||||
|
||||
// Create and update extended visualization lines if enabled
|
||||
if show_extended_lines
|
||||
// Initialize line objects if not already created
|
||||
if na(upline_extension)
|
||||
upline_extension := line.new(na, na, na, na, extend = extend.right, style = line.style_dashed, color = uptrend_color)
|
||||
|
||||
if na(downline_extension)
|
||||
downline_extension := line.new(na, na, na, na, extend = extend.right, style = line.style_dashed, color = downtrend_color)
|
||||
|
||||
// Update upper trendline extension when a new pivot high is confirmed
|
||||
if bool(pivot_high)
|
||||
line.set_xy1(upline_extension, bar_idx - offset, enable_backpainting ? pivot_high : upper_trendline)
|
||||
line.set_xy2(upline_extension, bar_idx - offset + 1, enable_backpainting ? pivot_high - slope : upper_trendline - slope)
|
||||
|
||||
// Update lower trendline extension when a new pivot low is confirmed
|
||||
if bool(pivot_low)
|
||||
line.set_xy1(downline_extension, bar_idx - offset, enable_backpainting ? pivot_low : lower_trendline)
|
||||
line.set_xy2(downline_extension, bar_idx - offset + 1, enable_backpainting ? pivot_low + slope : lower_trendline + slope)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 3: BREAKOUT DETECTION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Track breakouts above upper trendline and below lower trendline
|
||||
// Initialize tracking variables for breakout conditions
|
||||
var int upper_breakout_state = 0 // State variable to track upper breakout condition
|
||||
var int lower_breakout_state = 0 // State variable to track lower breakout condition
|
||||
|
||||
// 优化的突破检测 - 添加多K线确认机制,避免假突破
|
||||
bool upper_breakout = close > upper_trendline and close[1] > upper_trendline[1] and close[2] > upper_trendline[2]
|
||||
bool lower_breakout = close < lower_trendline and close[1] < lower_trendline[1] and close[2] < lower_trendline[2]
|
||||
|
||||
// Update state variables to track when breakouts occur
|
||||
upper_breakout_state := bool(pivot_high) ? 0 : upper_breakout ? 1 : upper_breakout_state
|
||||
lower_breakout_state := bool(pivot_low) ? 0 : lower_breakout ? 1 : lower_breakout_state
|
||||
|
||||
// Plot trendlines with appropriate offsets
|
||||
plot(enable_backpainting ? upper_trendline : upper_trendline, color = bool(pivot_high) ? na : uptrend_color, linewidth = 2, offset = -offset, title = 'Upper Trendline')
|
||||
plot(enable_backpainting ? lower_trendline : lower_trendline, color = bool(pivot_low) ? na : downtrend_color, linewidth = 2, offset = -offset, title = 'Lower Trendline')
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 4: DIRECTIONAL MOVEMENT INDEX (DMI) CALCULATION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// DMI Length parameter
|
||||
dmi_length = input.int(13, "DMI Length", tooltip="Length for DMI calculation")
|
||||
|
||||
// True Range calculation
|
||||
true_range = math.max(math.max(high - low, math.abs(high - nz(close[1]))), math.abs(low - nz(close[1])))
|
||||
|
||||
// Directional Movement calculations
|
||||
directional_movement_plus = high - nz(high[1]) > nz(low[1]) - low ? math.max(high - nz(high[1]), 0) : 0
|
||||
directional_movement_minus = nz(low[1]) - low > high - nz(high[1]) ? math.max(nz(low[1]) - low, 0) : 0
|
||||
|
||||
// Smoothed calculations for DMI
|
||||
var float smoothed_true_range = 0.0
|
||||
smoothed_true_range := nz(smoothed_true_range[1]) - nz(smoothed_true_range[1]) / dmi_length + true_range
|
||||
|
||||
var float smoothed_directional_plus = 0.0
|
||||
smoothed_directional_plus := nz(smoothed_directional_plus[1]) - nz(smoothed_directional_plus[1]) / dmi_length + directional_movement_plus
|
||||
|
||||
var float smoothed_directional_minus = 0.0
|
||||
smoothed_directional_minus := nz(smoothed_directional_minus[1]) - nz(smoothed_directional_minus[1]) / dmi_length + directional_movement_minus
|
||||
|
||||
// Calculate DI+ and DI- values
|
||||
di_plus = smoothed_directional_plus / smoothed_true_range * 100
|
||||
di_minus = smoothed_directional_minus / smoothed_true_range * 100
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 4.5: 准确性优化设置
|
||||
//----------------------------------------------------------
|
||||
|
||||
// 根据用户偏好使用第10根K线确认,减少误报
|
||||
confirmation_lookback = input.int(10, "确认回看期间", minval=1, maxval=20, tooltip="使用第N根K线确认交叉信号,减少误报", group="准确性优化")
|
||||
dmi_threshold = input.float(20.0, "DMI最小阈值", minval=10.0, maxval=50.0, tooltip="DMI值必须超过此阈值才触发信号", group="准确性优化")
|
||||
volume_confirmation = input.bool(true, "启用成交量确认", tooltip="要求成交量高于平均值才触发信号", group="准确性优化")
|
||||
volume_multiplier = input.float(1.2, "成交量倍数", minval=1.0, maxval=3.0, step=0.1, tooltip="成交量必须是平均成交量的倍数", group="准确性优化")
|
||||
min_alert_interval = input.int(5, "最小警报间隔", minval=1, maxval=20, tooltip="两次警报之间的最小K线间隔", group="准确性优化")
|
||||
|
||||
// 警报去重机制
|
||||
var int last_alert_bar = 0
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 5: STRATEGY DEFINITION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Enable/disable long and short positions
|
||||
enable_long_positions = input.bool(defval = true, title = 'Enable Long Positions', group = 'Strategy Settings')
|
||||
enable_short_positions = input.bool(defval = true, title = 'Enable Short Positions', group = 'Strategy Settings')
|
||||
|
||||
// 优化的SMA设置 - 增加周期以减少噪音
|
||||
fast_sma_length = input.int(defval = 5, title = 'Fast SMA Length', minval = 1, group = 'Strategy Settings')
|
||||
slow_sma_length = input.int(defval = 10, title = 'Slow SMA Length', minval = 1, group = 'Strategy Settings')
|
||||
sma_distance_threshold = input.float(0.001, "SMA距离阈值", minval=0.0001, step=0.0001, tooltip="SMA之间的最小距离阈值", group = 'Strategy Settings')
|
||||
|
||||
// Calculate SMA crossovers
|
||||
fast_sma = ta.sma(close, fast_sma_length)
|
||||
slow_sma = ta.sma(close, slow_sma_length)
|
||||
|
||||
// 优化的SMA交叉检测 - 添加距离过滤
|
||||
sma_cross_up = ta.crossover(fast_sma, slow_sma) and math.abs(fast_sma - slow_sma) > close * sma_distance_threshold
|
||||
sma_cross_down = ta.crossunder(fast_sma, slow_sma) and math.abs(fast_sma - slow_sma) > close * sma_distance_threshold
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 6: ENTRY AND EXIT CONDITIONS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// 成交量确认
|
||||
volume_avg = ta.sma(volume, 20)
|
||||
volume_confirmed = not volume_confirmation or volume > volume_avg * volume_multiplier
|
||||
|
||||
// 多重确认机制
|
||||
trend_confirmed_bullish = true
|
||||
trend_confirmed_bearish = true
|
||||
for i = 0 to 2
|
||||
trend_confirmed_bullish := trend_confirmed_bullish and close[i] > smoothed_trend[i]
|
||||
trend_confirmed_bearish := trend_confirmed_bearish and close[i] < smoothed_trend[i]
|
||||
|
||||
// 优化的DMI信号 - 添加强度过滤
|
||||
strong_dmi_bullish = di_plus > di_minus and di_plus > dmi_threshold
|
||||
strong_dmi_bearish = di_minus > di_plus and di_minus > dmi_threshold
|
||||
|
||||
// 优化的入场条件 - 添加多重确认
|
||||
long_entry_condition = enable_long_positions and
|
||||
upper_breakout_state > upper_breakout_state[1] and
|
||||
strong_dmi_bullish and
|
||||
trend_confirmed_bullish and
|
||||
volume_confirmed
|
||||
|
||||
short_entry_condition = enable_short_positions and
|
||||
lower_breakout_state > lower_breakout_state[1] and
|
||||
strong_dmi_bearish and
|
||||
trend_confirmed_bearish and
|
||||
volume_confirmed
|
||||
|
||||
|
||||
|
||||
// 优化后的出场条件 - 使用第10根K线确认
|
||||
long_exit_condition = ta.crossunder(close[confirmation_lookback], smoothed_trend[confirmation_lookback])
|
||||
short_exit_condition = ta.crossover(close[confirmation_lookback], smoothed_trend[confirmation_lookback])
|
||||
|
||||
// @function Display BUY/SELL labels on chart
|
||||
plotshape(long_entry_condition, title='BUY', text='BUY', location=location.belowbar,
|
||||
style=shape.labelup, size=size.tiny, color=color.new(color.green, 0), textcolor=color.new(color.white, 0))
|
||||
plotshape(short_entry_condition, title='SELL', text='SELL', location=location.abovebar,
|
||||
style=shape.labeldown, size=size.tiny, color=color.new(color.red, 0), textcolor=color.new(color.white, 0))
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 7: STOP LOSS AND TAKE PROFIT SETTINGS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Common settings
|
||||
atr_length = input.int(13, 'ATR Length for SL/TP', minval = 1, group = 'Risk Management')
|
||||
|
||||
// Variable to track if stop loss is triggered
|
||||
var bool long_trailing_tp_executed = false
|
||||
var bool short_trailing_tp_executed = false
|
||||
|
||||
// Store ATR at position entry
|
||||
float entry_atr = ta.valuewhen(long_entry_condition or short_entry_condition, ta.atr(atr_length), 0)
|
||||
|
||||
// Stop Loss settings
|
||||
stop_loss_method = input.string(defval = 'ATR', title = 'Stop Loss Method', options = ['PERC', 'ATR'], group = 'Stop Loss')
|
||||
long_stop_loss_percent = input.float(defval = 0.75, title = 'Long Position Stop Loss %', minval = 0.05, maxval = 100, step = 0.05, group = 'Stop Loss') / 100
|
||||
short_stop_loss_percent = input.float(defval = 0.75, title = 'Short Position Stop Loss %', minval = 0.05, maxval = 100, step = 0.05, group = 'Stop Loss') / 100
|
||||
long_stop_loss_atr_multiplier = input.float(defval = 8.0, title = 'Long Position ATR Multiplier', minval = 0.1, step = 0.1, group = 'Stop Loss')
|
||||
short_stop_loss_atr_multiplier = input.float(defval = 8.0, title = 'Short Position ATR Multiplier', minval = 0.1, step = 0.1, group = 'Stop Loss')
|
||||
stop_loss_trailing_mode = input.string(defval = 'ON', title = 'Trailing Stop Loss Mode', options = ['TP', 'ON', 'OFF'], tooltip = 'ON: Always trail, TP: Trail after Take Profit hit, OFF: Fixed stop', group = 'Stop Loss')
|
||||
break_even_enabled = input.bool(defval = true, title = 'Move to Break Even After TP', group = 'Stop Loss')
|
||||
|
||||
// Take Profit settings
|
||||
take_profit_quantity_percent = input.float(defval = 100, title = 'Take Profit Quantity %', minval = 0.0, maxval = 100, step = 1.0, group = 'Take Profit')
|
||||
take_profit_method = input.string(defval = 'PERC', title = 'Take Profit Method', options = ['PERC', 'ATR', 'RR'], group = 'Take Profit')
|
||||
long_take_profit_percent = input.float(defval = 1, title = 'Long Position Take Profit %', minval = 0.05, step = 0.05, group = 'Take Profit') / 100
|
||||
short_take_profit_percent = input.float(defval = 1, title = 'Short Position Take Profit %', minval = 0.05, step = 0.05, group = 'Take Profit') / 100
|
||||
long_take_profit_atr_multiplier = input.float(defval = 1.5, title = 'Long Position TP ATR Multiplier', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
short_take_profit_atr_multiplier = input.float(defval = 2, title = 'Short Position TP ATR Multiplier', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
long_risk_reward_ratio = input.float(defval = 0.6, title = 'Long Position Risk/Reward Ratio', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
short_risk_reward_ratio = input.float(defval = 1, title = 'Short Position Risk/Reward Ratio', minval = 0.1, step = 0.1, group = 'Take Profit')
|
||||
trailing_take_profit_enabled = input.bool(defval = true, title = 'Enable Trailing Take Profit', group = 'Take Profit')
|
||||
deviation_method = input.string(defval = 'PERC', title = 'Trailing Deviation Method', options = ['PERC', 'ATR'], group = 'Take Profit')
|
||||
deviation_percent = input.float(defval = 0.01, title = 'Trailing Deviation %', minval = 0.01, maxval = 100, step = 0.05, group = 'Take Profit') / 100
|
||||
deviation_atr_multiplier = input.float(defval = 1.0, title = 'Trailing Deviation ATR Multiplier', minval = 0.01, step = 0.05, group = 'Take Profit')
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 9: CALCULATE STOP LOSS LEVELS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Calculate long position stop loss price based on selected method
|
||||
get_long_stop_loss_price(base_price) =>
|
||||
switch stop_loss_method
|
||||
'PERC' => base_price * (1 - long_stop_loss_percent)
|
||||
'ATR' => base_price - long_stop_loss_atr_multiplier * entry_atr
|
||||
=> na
|
||||
|
||||
// Determine if trailing should be active for long position
|
||||
long_tp_trailing_enabled = stop_loss_trailing_mode == 'ON' or (stop_loss_trailing_mode == 'TP' and long_trailing_tp_executed)
|
||||
|
||||
// Calculate and maintain stop loss price for long positions
|
||||
var float long_stop_loss_price = na
|
||||
long_stop_loss_price := if strategy.position_size > 0
|
||||
if long_entry_condition
|
||||
get_long_stop_loss_price(close)
|
||||
else
|
||||
stop_price = get_long_stop_loss_price(long_tp_trailing_enabled ? high : strategy.position_avg_price)
|
||||
stop_price := break_even_enabled and long_trailing_tp_executed ? math.max(stop_price, strategy.position_avg_price) : stop_price
|
||||
math.max(stop_price, nz(long_stop_loss_price[1]))
|
||||
else
|
||||
na
|
||||
|
||||
// Calculate short position stop loss price based on selected method
|
||||
get_short_stop_loss_price(base_price) =>
|
||||
switch stop_loss_method
|
||||
'PERC' => base_price * (1 + short_stop_loss_percent)
|
||||
'ATR' => base_price + short_stop_loss_atr_multiplier * entry_atr
|
||||
=> na
|
||||
|
||||
// Determine if trailing should be active for short position
|
||||
short_tp_trailing_enabled = stop_loss_trailing_mode == 'ON' or (stop_loss_trailing_mode == 'TP' and short_trailing_tp_executed)
|
||||
|
||||
// Calculate and maintain stop loss price for short positions
|
||||
var float short_stop_loss_price = na
|
||||
short_stop_loss_price := if strategy.position_size < 0
|
||||
if short_entry_condition
|
||||
get_short_stop_loss_price(close)
|
||||
else
|
||||
var float stop_price = get_short_stop_loss_price(short_tp_trailing_enabled ? low : strategy.position_avg_price) // stop_price を var float で宣言
|
||||
if break_even_enabled and short_trailing_tp_executed
|
||||
stop_price := math.min(stop_price, strategy.position_avg_price)
|
||||
short_stop_loss_price := math.min(stop_price, nz(short_stop_loss_price[1], 999999.9))
|
||||
else
|
||||
na
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 9: CALCULATE TAKE PROFIT LEVELS
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Calculate long position take profit price based on selected method
|
||||
get_long_take_profit_price() =>
|
||||
switch take_profit_method
|
||||
'PERC' => close * (1 + long_take_profit_percent)
|
||||
'ATR' => close + long_take_profit_atr_multiplier * entry_atr
|
||||
'RR' => close + long_risk_reward_ratio * (close - get_long_stop_loss_price(close))
|
||||
=> na
|
||||
|
||||
// Calculate and maintain take profit price for long positions
|
||||
var float long_take_profit_price = na
|
||||
long_take_profit_price := if strategy.position_size > 0 and not long_trailing_tp_executed
|
||||
if long_entry_condition
|
||||
get_long_take_profit_price()
|
||||
else
|
||||
nz(long_take_profit_price[1], get_long_take_profit_price())
|
||||
else
|
||||
na
|
||||
|
||||
// Update trailing take profit execution flag for long positions
|
||||
long_trailing_tp_executed := strategy.position_size > 0 and (long_trailing_tp_executed[1] or strategy.position_size < strategy.position_size[1] or (strategy.position_size[1] == 0 and high >= long_take_profit_price))
|
||||
|
||||
// Calculate trailing step size in ticks for long positions
|
||||
long_trailing_tp_step_ticks = switch deviation_method
|
||||
'PERC' => long_take_profit_price * deviation_percent / syminfo.mintick
|
||||
'ATR' => deviation_atr_multiplier * entry_atr / syminfo.mintick
|
||||
=> na
|
||||
|
||||
// Calculate short position take profit price based on selected method
|
||||
get_short_take_profit_price() =>
|
||||
switch take_profit_method
|
||||
'PERC' => close * (1 - short_take_profit_percent)
|
||||
'ATR' => close - short_take_profit_atr_multiplier * entry_atr
|
||||
'RR' => close - short_risk_reward_ratio * (get_short_stop_loss_price(close) - close)
|
||||
=> na
|
||||
|
||||
// Calculate and maintain take profit price for short positions
|
||||
var float short_take_profit_price = na
|
||||
short_take_profit_price := if strategy.position_size < 0 and not short_trailing_tp_executed
|
||||
if short_entry_condition
|
||||
get_short_take_profit_price()
|
||||
else
|
||||
nz(short_take_profit_price[1], get_short_take_profit_price())
|
||||
else
|
||||
na
|
||||
|
||||
// Update trailing take profit execution flag for short positions
|
||||
short_trailing_tp_executed := strategy.position_size < 0 and (short_trailing_tp_executed[1] or strategy.position_size > strategy.position_size[1] or (strategy.position_size[1] == 0 and low <= short_take_profit_price))
|
||||
|
||||
// Calculate trailing step size in ticks for short positions
|
||||
short_trailing_tp_step_ticks = switch deviation_method
|
||||
'PERC' => short_take_profit_price * deviation_percent / syminfo.mintick
|
||||
'ATR' => deviation_atr_multiplier * entry_atr / syminfo.mintick
|
||||
=> na
|
||||
|
||||
//----------------------------------------------------------
|
||||
// SECTION 11: STRATEGY EXECUTION
|
||||
//----------------------------------------------------------
|
||||
|
||||
// Enter long position when conditions are met
|
||||
if long_entry_condition
|
||||
strategy.entry('L', strategy.long, comment = "LONG")
|
||||
|
||||
// Enter short position when conditions are met
|
||||
if short_entry_condition
|
||||
strategy.entry('S', strategy.short, comment = "SHORT")
|
||||
|
||||
// Exit long position when exit conditions are met
|
||||
if long_exit_condition
|
||||
strategy.close('L', comment = "SL Triggered")
|
||||
|
||||
// Exit short position when exit conditions are met
|
||||
if short_exit_condition
|
||||
strategy.close('S', comment = "SL Triggered")
|
||||
|
||||
// Set up take profit and stop loss for long positions
|
||||
strategy.exit(id = 'Long Take Profit / Stop Loss', from_entry = 'L', qty_percent = take_profit_quantity_percent, limit = trailing_take_profit_enabled ? na : long_take_profit_price, stop = long_stop_loss_price, trail_price = trailing_take_profit_enabled ? long_take_profit_price : na, trail_offset = trailing_take_profit_enabled ? long_trailing_tp_step_ticks : na, comment = "TP/SL Triggered")
|
||||
strategy.exit(id = 'Long Stop Loss', from_entry = 'L', stop = long_stop_loss_price, comment = "SL Triggered")
|
||||
|
||||
// Set up take profit and stop loss for short positions
|
||||
strategy.exit(id = 'Short Take Profit / Stop Loss', from_entry = 'S', qty_percent = take_profit_quantity_percent, limit = trailing_take_profit_enabled ? na : short_take_profit_price, stop = short_stop_loss_price, trail_price = trailing_take_profit_enabled ? short_take_profit_price : na, trail_offset = trailing_take_profit_enabled ? short_trailing_tp_step_ticks : na, comment = "TP/SL Triggered")
|
||||
strategy.exit(id = 'Short Stop Loss', from_entry = 'S', stop = short_stop_loss_price, comment = "SL Triggered")
|
||||
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_long_entry = 0
|
||||
var int last_alert_short_entry = 0
|
||||
var int last_alert_long_exit = 0
|
||||
var int last_alert_short_exit = 0
|
||||
var int last_alert_upper_breakout = 0
|
||||
var int last_alert_lower_breakout = 0
|
||||
var int last_alert_sma_cross_up = 0
|
||||
var int last_alert_sma_cross_down = 0
|
||||
var int last_alert_dmi_bullish = 0
|
||||
var int last_alert_dmi_bearish = 0
|
||||
var int last_alert_trend_bullish = 0
|
||||
var int last_alert_trend_bearish = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 入场信号警报 - 每分钟限制
|
||||
if long_entry_condition and current_minute > last_alert_long_entry
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","成交量倍数":"' + str.tostring(volume/volume_avg, '#.##') + '","事件":"多头入场信号触发","信号":"buy","备注":"多重确认+成交量验证"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_long_entry := current_minute
|
||||
|
||||
if short_entry_condition and current_minute > last_alert_short_entry
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","成交量倍数":"' + str.tostring(volume/volume_avg, '#.##') + '","事件":"空头入场信号触发","信号":"sell","备注":"多重确认+成交量验证"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_short_entry := current_minute
|
||||
|
||||
// 出场信号警报 - 每分钟限制
|
||||
if long_exit_condition and current_minute > last_alert_long_exit
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","确认期间":"' + str.tostring(confirmation_lookback) + '","事件":"多头出场信号触发","信号":"exit_long","备注":"第' + str.tostring(confirmation_lookback) + '根K线确认跌破"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_long_exit := current_minute
|
||||
|
||||
if short_exit_condition and current_minute > last_alert_short_exit
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","确认期间":"' + str.tostring(confirmation_lookback) + '","事件":"空头出场信号触发","信号":"exit_short","备注":"第' + str.tostring(confirmation_lookback) + '根K线确认突破"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_short_exit := current_minute
|
||||
|
||||
// 优化的趋势线突破警报 - 每分钟限制
|
||||
if upper_breakout and not upper_breakout[1] and current_minute > last_alert_upper_breakout
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","上趋势线":"' + str.tostring(upper_trendline, '#.####') + '","突破强度":"连续3K线","事件":"价格确认突破上趋势线","信号":"upper_breakout","备注":"3K线确认突破,过滤假突破"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_upper_breakout := current_minute
|
||||
|
||||
if lower_breakout and not lower_breakout[1] and current_minute > last_alert_lower_breakout
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","下趋势线":"' + str.tostring(lower_trendline, '#.####') + '","突破强度":"连续3K线","事件":"价格确认跌破下趋势线","信号":"lower_breakout","备注":"3K线确认跌破,过滤假突破"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_lower_breakout := current_minute
|
||||
|
||||
// 优化的SMA交叉警报 - 每分钟限制
|
||||
if sma_cross_up and current_minute > last_alert_sma_cross_up
|
||||
sma_distance = math.abs(fast_sma - slow_sma) / close * 100
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","快速SMA":"' + str.tostring(fast_sma, '#.####') + '","慢速SMA":"' + str.tostring(slow_sma, '#.####') + '","SMA距离":"' + str.tostring(sma_distance, '#.###') + '%","事件":"SMA金叉确认","信号":"sma_cross_up","备注":"5/10周期+距离过滤"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_sma_cross_up := current_minute
|
||||
|
||||
if sma_cross_down and current_minute > last_alert_sma_cross_down
|
||||
sma_distance = math.abs(fast_sma - slow_sma) / close * 100
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","快速SMA":"' + str.tostring(fast_sma, '#.####') + '","慢速SMA":"' + str.tostring(slow_sma, '#.####') + '","SMA距离":"' + str.tostring(sma_distance, '#.###') + '%","事件":"SMA死叉确认","信号":"sma_cross_down","备注":"5/10周期+距离过滤"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_sma_cross_down := current_minute
|
||||
|
||||
// 优化的DMI信号警报 - 每分钟限制
|
||||
if ta.crossover(di_plus, di_minus) and di_plus > dmi_threshold and current_minute > last_alert_dmi_bullish
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","DMI阈值":"' + str.tostring(dmi_threshold, '#.##') + '","事件":"强势DI+上穿DI-","信号":"dmi_bullish","备注":"动量转向看涨(已过滤弱信号)"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_dmi_bullish := current_minute
|
||||
|
||||
if ta.crossunder(di_plus, di_minus) and di_minus > dmi_threshold and current_minute > last_alert_dmi_bearish
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","DI+":"' + str.tostring(di_plus, '#.##') + '","DI-":"' + str.tostring(di_minus, '#.##') + '","DMI阈值":"' + str.tostring(dmi_threshold, '#.##') + '","事件":"强势DI+下穿DI-","信号":"dmi_bearish","备注":"动量转向看跌(已过滤弱信号)"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_dmi_bearish := current_minute
|
||||
|
||||
// 超趋势方向变化警报 - 每分钟限制
|
||||
if ta.crossover(close, smoothed_trend) and current_minute > last_alert_trend_bullish
|
||||
trend_strength = math.abs(close - smoothed_trend) / close * 100
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.###') + '%","事件":"价格上穿平滑超趋势","信号":"trend_bullish","备注":"趋势转向看涨"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_trend_bullish := current_minute
|
||||
|
||||
if ta.crossunder(close, smoothed_trend) and current_minute > last_alert_trend_bearish
|
||||
trend_strength = math.abs(close - smoothed_trend) / close * 100
|
||||
alert_message := '{"指标名称":"TMFS_V2","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","价格":"' + str.tostring(close, '#.####') + '","平滑超趋势":"' + str.tostring(smoothed_trend, '#.####') + '","趋势强度":"' + str.tostring(trend_strength, '#.###') + '%","事件":"价格下穿平滑超趋势","信号":"trend_bearish","备注":"趋势转向看跌"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_trend_bearish := current_minute
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(smoothed_trend, title = '平滑超趋势', display = display.none)
|
||||
plot(di_plus, title = 'DI+', display = display.none)
|
||||
plot(di_minus, title = 'DI-', display = display.none)
|
||||
plot(fast_sma, title = '快速SMA', display = display.none)
|
||||
plot(slow_sma, title = '慢速SMA', display = display.none)
|
||||
plot(upper_trendline, title = '上趋势线', display = display.none)
|
||||
plot(lower_trendline, title = '下趋势线', display = display.none)
|
||||
plot(volume/volume_avg, title = '成交量倍数', display = display.none)
|
||||
|
||||
// 入场信号警报
|
||||
alertcondition(long_entry_condition, title = 'TMFS_V2多头入场', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","成交量倍数":"{{plot("成交量倍数")}}","事件":"多头入场信号触发","信号":"buy","备注":"多重确认+成交量验证"}')
|
||||
|
||||
alertcondition(short_entry_condition, title = 'TMFS_V2空头入场', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","成交量倍数":"{{plot("成交量倍数")}}","事件":"空头入场信号触发","信号":"sell","备注":"多重确认+成交量验证"}')
|
||||
|
||||
// 出场信号警报
|
||||
alertcondition(long_exit_condition, title = 'TMFS_V2多头出场', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"多头出场信号触发","信号":"exit_long","备注":"第10根K线确认跌破"}')
|
||||
|
||||
alertcondition(short_exit_condition, title = 'TMFS_V2空头出场', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"空头出场信号触发","信号":"exit_short","备注":"第10根K线确认突破"}')
|
||||
|
||||
// 优化的趋势线突破警报
|
||||
alertcondition(upper_breakout and not upper_breakout[1], title = '价格确认突破上趋势线', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","上趋势线":"{{plot("上趋势线")}}","事件":"价格确认突破上趋势线","信号":"upper_breakout","备注":"3K线确认突破,过滤假突破"}')
|
||||
|
||||
alertcondition(lower_breakout and not lower_breakout[1], title = '价格确认跌破下趋势线', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","下趋势线":"{{plot("下趋势线")}}","事件":"价格确认跌破下趋势线","信号":"lower_breakout","备注":"3K线确认跌破,过滤假突破"}')
|
||||
|
||||
// 优化的SMA交叉警报
|
||||
alertcondition(sma_cross_up, title = 'SMA金叉确认', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","快速SMA":"{{plot("快速SMA")}}","慢速SMA":"{{plot("慢速SMA")}}","事件":"SMA金叉确认","信号":"sma_cross_up","备注":"5/10周期+距离过滤"}')
|
||||
|
||||
alertcondition(sma_cross_down, title = 'SMA死叉确认', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","快速SMA":"{{plot("快速SMA")}}","慢速SMA":"{{plot("慢速SMA")}}","事件":"SMA死叉确认","信号":"sma_cross_down","备注":"5/10周期+距离过滤"}')
|
||||
|
||||
// 优化的DMI信号警报
|
||||
alertcondition(ta.crossover(di_plus, di_minus) and di_plus > dmi_threshold, title = '强势DI+上穿DI-', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"强势DI+上穿DI-","信号":"dmi_bullish","备注":"动量转向看涨(已过滤弱信号)"}')
|
||||
|
||||
alertcondition(ta.crossunder(di_plus, di_minus) and di_minus > dmi_threshold, title = '强势DI+下穿DI-', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"强势DI+下穿DI-","信号":"dmi_bearish","备注":"动量转向看跌(已过滤弱信号)"}')
|
||||
|
||||
// 超趋势方向变化警报
|
||||
alertcondition(ta.crossover(close, smoothed_trend), title = '价格上穿平滑超趋势', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"价格上穿平滑超趋势","信号":"trend_bullish","备注":"趋势转向看涨"}')
|
||||
|
||||
alertcondition(ta.crossunder(close, smoothed_trend), title = '价格下穿平滑超趋势', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","事件":"价格下穿平滑超趋势","信号":"trend_bearish","备注":"趋势转向看跌"}')
|
||||
|
||||
// 综合强势信号警报
|
||||
alertcondition(upper_breakout and strong_dmi_bullish and volume_confirmed, title = '强势看涨信号', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","成交量倍数":"{{plot("成交量倍数")}}","事件":"强势看涨信号","信号":"strong_bullish","备注":"趋势线突破+强势DMI+成交量确认"}')
|
||||
|
||||
alertcondition(lower_breakout and strong_dmi_bearish and volume_confirmed, title = '强势看跌信号', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","成交量倍数":"{{plot("成交量倍数")}}","事件":"强势看跌信号","信号":"strong_bearish","备注":"趋势线跌破+强势DMI+成交量确认"}')
|
||||
|
||||
// 趋势确认警报
|
||||
alertcondition(trend_confirmed_bullish and strong_dmi_bullish, title = '多头趋势确认', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"多头趋势确认","信号":"bullish_trend_confirmed","备注":"3K线确认在超趋势上方且强势DMI看涨"}')
|
||||
|
||||
alertcondition(trend_confirmed_bearish and strong_dmi_bearish, title = '空头趋势确认', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","平滑超趋势":"{{plot("平滑超趋势")}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"空头趋势确认","信号":"bearish_trend_confirmed","备注":"3K线确认在超趋势下方且强势DMI看跌"}')
|
||||
|
||||
// 成交量异常警报
|
||||
alertcondition(volume > volume_avg * volume_multiplier * 2, title = '成交量异常放大', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","成交量倍数":"{{plot("成交量倍数")}}","事件":"成交量异常放大","信号":"volume_spike","备注":"成交量超过平均值2倍以上"}')
|
||||
|
||||
// 基础DMI状态警报
|
||||
alertcondition(di_plus > dmi_threshold and di_plus > di_minus, title = 'DI+强势状态', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"DI+强势状态","信号":"dmi_plus_strong","备注":"DI+高于阈值且大于DI-"}')
|
||||
|
||||
alertcondition(di_minus > dmi_threshold and di_minus > di_plus, title = 'DI-强势状态', message = '{"指标名称":"TMFS_V2","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","价格":"{{close}}","DI+":"{{plot("DI+")}}","DI-":"{{plot("DI-")}}","事件":"DI-强势状态","信号":"dmi_minus_strong","备注":"DI-高于阈值且大于DI+"}')
|
||||
|
||||
Reference in New Issue
Block a user