562 lines
40 KiB
Plaintext
562 lines
40 KiB
Plaintext
// 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+"}')
|
||
|