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

562 lines
40 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

// This 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+"}')