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

504 lines
34 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

// 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看跌"}')