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