
动态时间过滤支撑阻力追踪止损交易系统是一种结合了精确入场信号、智能时间过滤和自适应风险管理的高级量化交易策略。该系统专为寻求在特定时间窗口内识别高概率交易机会的交易者设计,同时采用动态追踪止损和部分仓位管理技术,以优化交易表现。策略核心在于通过支撑位和阻力位的动态识别,结合交易时间过滤和成交量确认,提供精准的交易信号。
本策略的基本原理建立在三个核心要素的协同作用上:精确入场、最佳时间和状态管理。
入场系统: 策略通过动态识别关键价格水平来寻找反转机会。它使用可配置的回溯期来计算支撑位和阻力位,并在价格与这些关键区域交互时触发入场信号。入场条件包括价格与支撑/阻力水平的互动、成交量确认和可选的趋势过滤器确认。当价格接触支撑位并且收盘价高于支撑缓冲区时,同时成交量高于平均水平,系统会生成做多信号。类似地,当价格接触阻力位并且收盘价低于阻力缓冲区时,同时成交量高于平均水平,系统会生成做空信号。
时间过滤系统: 策略实现了一个全面的时间过滤系统,允许交易者定义最佳交易时段。这包括: - 12小时格式的交易时间窗口设置 - 多时区支持(UTC、EST、PST、CST) - 按星期几过滤(只交易工作日、周末或两者兼顾) - 自动避开午餐时间(通常是12:00-13:00) - 可视化时间指示器(通过背景颜色显示活跃/非活跃交易时段)
风险管理系统: 策略采用三级风险管理方法: 1. 多级止盈系统:设置两个止盈目标(TP1和TP2),可选择在TP1部分平仓 2. 动态追踪止损技术:提供三种操作模式(保守、平衡、激进),根据当前市场波动性自动调整 3. 智能仓位管理:允许交易者配置入场数量和部分平仓数量,清晰跟踪持仓状态和盈亏
通过深入分析代码,该策略具有以下优势:
综合的入场信号:结合了价格行为、成交量确认和趋势一致性,提高了交易信号的可靠性。系统在关键支撑位和阻力位附近寻找高概率反转点,减少了假突破的风险。
灵活的时间过滤系统:允许交易者聚焦于最佳交易时段,避开低流动性或高波动性的市场环境。这有助于提高交易效率并减少在不利市场条件下交易的可能性。支持多时区交易和自定义交易时间设置,使其适用于全球各地的交易者。
先进的风险管理功能:动态追踪止损系统随市场波动自动调整,帮助保护利润并让赢利头寸继续运行。多级止盈目标和部分平仓选项允许在不同价格水平锁定利润。
全面的视觉反馈:系统提供了详细的图表元素和实时仪表板,帮助交易者直观地理解市场状况和策略表现。入场区域突出显示、动态风险/回报线和追踪止损可视化使交易决策过程更加透明。
高度可定制性:从核心策略参数到时间过滤控制和风险管理选项,策略提供了广泛的自定义能力,可以适应不同的交易风格和市场条件。
尽管该策略具有许多优势,但它也存在一些潜在风险:
参数优化风险:策略依赖于多个参数设置,如回溯期、ATR乘数和趋势过滤器设置。这些参数需要仔细优化和定期调整,以适应不同的市场环境。参数过度优化可能导致过拟合,在未来市场条件下表现不佳。
市场条件敏感性:在高波动性或低流动性市场中,支撑和阻力水平可能不如预期那样可靠。极端市场条件下,价格可能迅速突破关键水平,导致止损被触发。
时间过滤限制:虽然时间过滤可以帮助避开不利的交易时段,但它也可能导致错过某些高质量的交易机会。市场不总是遵循预定的时间模式,特别是在重大事件或突发新闻期间。
追踪止损陷阱:在震荡市场中,动态追踪止损可能过早触发,导致原本可能盈利的交易提前结束。不同的追踪止损设置(保守、平衡、激进)在不同市场环境中表现各异。
信号冲突:当价格接近多个支撑和阻力水平,或者时间过滤与入场信号冲突时,可能会出现混合信号。这需要额外的判断或更复杂的决策规则。
基于代码分析,以下是可能的优化方向:
自适应参数调整:实现一个机制,根据近期市场波动性和交易表现自动调整关键参数,如回溯期和ATR乘数。这可以帮助策略更好地适应不同的市场环境,而无需手动干预。
增强市场结构分析:整合更复杂的价格结构识别方法,如确定更高层级的支撑和阻力区域、识别趋势通道或价格形态。这可以提高入场信号的质量和可靠性。
优化时间过滤逻辑:通过数据分析找出特定市场的最佳交易时间,并根据历史表现自动调整交易时间窗口。考虑整合对季节性模式和市场特定事件(如经济数据发布)的过滤。
改进风险管理机制:设计一个更智能的仓位管理系统,根据历史波动性、当前市场条件和策略表现动态调整仓位大小。在盈利交易中增加基于盈利百分比的阶梯式平仓策略。
集成机器学习模型:使用机器学习算法预测支撑位和阻力位的可靠性,或估计在特定市场条件下入场信号的成功概率。这可以帮助过滤掉潜在的低质量交易信号。
动态时间过滤支撑阻力追踪止损交易系统是一个功能全面的交易策略,结合了精确的入场信号、智能的时间过滤和自适应的风险管理。它通过在关键支撑位和阻力位寻找高概率反转机会,同时利用时间过滤和成交量确认来提高交易质量。
该策略的主要优势在于其全面的时间过滤系统、动态追踪止损技术和高度可视化的用户界面。这些功能共同创造了一个强大而灵活的交易工具,适用于各种市场条件和交易风格。
然而,为了充分发挥该策略的潜力,交易者需要仔细优化参数,理解其在不同市场环境中的表现特点,并可能需要根据具体市场和个人交易目标进行定制调整。通过实施建议的优化措施,可以进一步增强策略的性能和鲁棒性,为交易者提供更可靠的市场分析和交易执行工具。
/*backtest
start: 2025-08-13 00:00:00
end: 2025-08-20 00:00:00
period: 10m
basePeriod: 10m
exchanges: [{"eid":"Futures_OKX","currency":"ETH_USDT","balance":5000}]
*/
//@version=5
strategy("FlowStateTrader", overlay=true)
// Input Parameters
lookbackPeriod = input.int(20, "Lookback Period for Key Levels", minval=5, maxval=100)
atrPeriod = input.int(14, "ATR Period", minval=5, maxval=50)
atrMultiplierSL = input.float(1.5, "SL ATR Multiplier", minval=0.5, maxval=5.0, step=0.1)
atrMultiplierTP1 = input.float(1.5, "TP1 ATR Multiplier", minval=0.5, maxval=5.0, step=0.1)
atrMultiplierTP2 = input.float(2.0, "TP2 ATR Multiplier", minval=0.5, maxval=5.0, step=0.1)
rewardToRisk = input.float(2.0, "Reward to Risk Ratio", minval=1.0, maxval=5.0, step=0.1)
// Trend Filter Settings
enableTrendFilter = input.bool(true, "Enable Trend Filter")
trendMAPeriod = input.int(20, "Trend MA Period", minval=5, maxval=200)
trendMAType = input.string("EMA", "Trend MA Type", options=["EMA", "SMA"])
// TIME FILTER SETTINGS
enableTimeFilter = input.bool(false, "Enable Time-Based Filter", tooltip="Filter trades based on specific time windows")
// 12-hour format time inputs
startHour12 = input.int(9, "Start Hour (1-12)", minval=1, maxval=12, tooltip="Trading start hour in 12-hour format")
startAMPM = input.string("AM", "Start AM/PM", options=["AM", "PM"])
endHour12 = input.int(4, "End Hour (1-12)", minval=1, maxval=12, tooltip="Trading end hour in 12-hour format")
endAMPM = input.string("PM", "End AM/PM", options=["AM", "PM"])
// Timezone selection
timeZone = input.string("UTC", "Time Zone", options=["UTC", "EST", "PST", "CST"], tooltip="Time zone for trading hours")
// Additional controls
avoidLunchHour = input.bool(true, "Avoid Lunch Hour (12:00-1:00 PM)", tooltip="Skip trading during typical lunch break")
weekendsOnly = input.bool(false, "Weekends Only", tooltip="Only trade on weekends")
weekdaysOnly = input.bool(false, "Weekdays Only", tooltip="Only trade on weekdays")
// Strategy Settings
entryQty = input.int(10, "Entry Quantity (Contracts)", minval=1, maxval=1000)
enablePartialClose = input.bool(true, "Enable Partial Close at TP1")
partialCloseQty = input.int(1, "Contracts to Close at TP1", minval=1, maxval=100)
enableAlerts = input.bool(true, "Enable Strategy Alerts")
// Dashboard Settings
dashboardSize = input.string("Medium", "Dashboard Size", options=["Small", "Medium", "Large"], tooltip="Control the size of the information dashboard")
enableScorecard = input.bool(true, "Enable Performance Scorecard", tooltip="Show performance metrics in lower right corner")
// Trailing Stop Settings
enableTrailingStop = input.bool(true, "Enable Trailing Stop")
trailMode = input.string("Balanced", "Trailing Stop Mode", options=["Conservative", "Balanced", "Aggressive"], tooltip="Conservative: Protect more profit | Balanced: Good middle ground | Aggressive: Let winners run longer")
// Set trailing parameters based on mode
trailActivationMultiplier = trailMode == "Conservative" ? 0.8 : trailMode == "Balanced" ? 1.0 : 1.2
trailDistanceMultiplier = trailMode == "Conservative" ? 0.6 : trailMode == "Balanced" ? 0.8 : 1.0
// TIME FILTER FUNCTIONS
// Convert 12-hour format to 24-hour format
convertTo24Hour(hour12, ampm) =>
var int hour24 = na
if ampm == "AM"
hour24 := hour12 == 12 ? 0 : hour12
else // PM
hour24 := hour12 == 12 ? 12 : hour12 + 12
hour24
// Convert timezone to UTC offset
getUTCOffset(tz) =>
var int offset = na
if tz == "UTC"
offset := 0
else if tz == "EST"
offset := -5 // EST is UTC-5
else if tz == "CST"
offset := -6 // CST is UTC-6
else if tz == "PST"
offset := -8 // PST is UTC-8
offset
getCurrentHour() =>
hour(time, "UTC")
getCurrentDayOfWeek() =>
dayofweek(time)
isWeekend() =>
currentDay = getCurrentDayOfWeek()
currentDay == dayofweek.saturday or currentDay == dayofweek.sunday
isWeekday() =>
not isWeekend()
isInTradingWindow() =>
if not enableTimeFilter
true
else
// Convert 12-hour inputs to 24-hour UTC
startHour24 = convertTo24Hour(startHour12, startAMPM)
endHour24 = convertTo24Hour(endHour12, endAMPM)
utcOffset = getUTCOffset(timeZone)
// Convert local time to UTC
startHourUTC = (startHour24 - utcOffset + 24) % 24
endHourUTC = (endHour24 - utcOffset + 24) % 24
currentHour = getCurrentHour()
// Handle trading window logic
var bool inWindow = false
// Handle same-day window vs overnight window
if startHourUTC <= endHourUTC
// Same day window (e.g., 9 AM to 4 PM)
inWindow := currentHour >= startHourUTC and currentHour <= endHourUTC
else
// Overnight window (e.g., 10 PM to 6 AM)
inWindow := currentHour >= startHourUTC or currentHour <= endHourUTC
// Apply day-of-week filters
if weekendsOnly and not isWeekend()
inWindow := false
if weekdaysOnly and not isWeekday()
inWindow := false
// Apply lunch hour filter (12:00-1:00 PM in selected timezone)
if avoidLunchHour and inWindow
lunchStart24 = 12 // 12 PM
lunchEnd24 = 13 // 1 PM
lunchStartUTC = (lunchStart24 - utcOffset + 24) % 24
lunchEndUTC = (lunchEnd24 - utcOffset + 24) % 24
// Check if current hour falls in lunch period
if lunchStartUTC <= lunchEndUTC
// Normal case: lunch doesn't cross midnight
if currentHour >= lunchStartUTC and currentHour < lunchEndUTC
inWindow := false
else
// Edge case: lunch period crosses midnight (shouldn't happen but safety check)
if currentHour >= lunchStartUTC or currentHour < lunchEndUTC
inWindow := false
inWindow
// Combined time filter
isGoodTradingTime() =>
isInTradingWindow()
// ATR and Volume Calculation
atr = ta.atr(atrPeriod)
volumeSMA = ta.sma(volume, atrPeriod)
// Trend Filter
trendMA = enableTrendFilter ? (trendMAType == "EMA" ? ta.ema(close, trendMAPeriod) : ta.sma(close, trendMAPeriod)) : na
isBullishTrend = enableTrendFilter ? close > trendMA : true
isBearishTrend = enableTrendFilter ? close < trendMA : true
// Key Levels Identification (Support & Resistance Zones)
support = ta.lowest(low, lookbackPeriod)
resistance = ta.highest(high, lookbackPeriod)
supportBuffer = support - atr * 0.5
resistanceBuffer = resistance + atr * 0.5
// Define Entry Conditions (with time filter)
isBullishEntry = (close > supportBuffer) and (low <= support) and (volume > volumeSMA) and isBullishTrend and isGoodTradingTime()
isBearishEntry = (close < resistanceBuffer) and (high >= resistance) and (volume > volumeSMA) and isBearishTrend and isGoodTradingTime()
// Calculate Stop Loss and Take Profit Levels
bullishSL = support - atr * atrMultiplierSL
bullishTP1 = support + atr * rewardToRisk * atrMultiplierTP1
bullishTP2 = support + atr * rewardToRisk * atrMultiplierTP2
bearishSL = resistance + atr * atrMultiplierSL
bearishTP1 = resistance - atr * rewardToRisk * atrMultiplierTP1
bearishTP2 = resistance - atr * rewardToRisk * atrMultiplierTP2
// Strategy Position Management
var float longEntryPrice = na
var float shortEntryPrice = na
var bool tp1HitLong = false
var bool tp1HitShort = false
// Trailing Stop Variables
var float longTrailStop = na
var float shortTrailStop = na
var bool longTrailActive = false
var bool shortTrailActive = false
// Calculate position sizing
finalQty = entryQty
// Long Entry
if isBullishEntry and strategy.position_size == 0
strategy.entry("Long", strategy.long, qty=finalQty)
longEntryPrice := close
tp1HitLong := false
// Reset trailing stop variables
longTrailStop := na
longTrailActive := false
if enableAlerts
alert("Long Entry Signal at " + str.tostring(close) + " - Qty: " + str.tostring(finalQty), alert.freq_once_per_bar)
// Short Entry
if isBearishEntry and strategy.position_size == 0
strategy.entry("Short", strategy.short, qty=finalQty)
shortEntryPrice := close
tp1HitShort := false
// Reset trailing stop variables
shortTrailStop := na
shortTrailActive := false
if enableAlerts
alert("Short Entry Signal at " + str.tostring(close) + " - Qty: " + str.tostring(finalQty), alert.freq_once_per_bar)
// Long Position Management
if strategy.position_size > 0
// Calculate current profit
currentProfit = close - strategy.position_avg_price
profitInATR = currentProfit / atr
// Trailing Stop Logic
if enableTrailingStop and profitInATR >= trailActivationMultiplier
// Activate trailing stop
if not longTrailActive
longTrailActive := true
longTrailStop := close - atr * trailDistanceMultiplier
else
// Update trailing stop (only move up, never down)
newTrailStop = close - atr * trailDistanceMultiplier
longTrailStop := math.max(longTrailStop, newTrailStop)
// Determine which stop loss to use
effectiveStopLoss = enableTrailingStop and longTrailActive ? longTrailStop : bullishSL
// Stop Loss (either original or trailing)
strategy.exit("Long SL", "Long", stop=effectiveStopLoss)
// Take Profit 1 (Partial Close by Contracts)
if enablePartialClose and not tp1HitLong and high >= bullishTP1 and strategy.position_size >= partialCloseQty
strategy.close("Long", qty=partialCloseQty, comment="Long TP1", immediately=true)
tp1HitLong := true
// Take Profit 2 (Close Remaining Position) or Full Close if Partial is Disabled
if (enablePartialClose and tp1HitLong and high >= bullishTP2) or (not enablePartialClose and high >= bullishTP1)
strategy.close("Long", comment=enablePartialClose ? "Long TP2" : "Long TP1", immediately=true)
// Short Position Management
if strategy.position_size < 0
// Calculate current profit (for shorts, profit when price goes down)
currentProfit = strategy.position_avg_price - close
profitInATR = currentProfit / atr
// Trailing Stop Logic
if enableTrailingStop and profitInATR >= trailActivationMultiplier
// Activate trailing stop
if not shortTrailActive
shortTrailActive := true
shortTrailStop := close + atr * trailDistanceMultiplier
else
// Update trailing stop (only move down, never up)
newTrailStop = close + atr * trailDistanceMultiplier
shortTrailStop := math.min(shortTrailStop, newTrailStop)
// Determine which stop loss to use
effectiveStopLoss = enableTrailingStop and shortTrailActive ? shortTrailStop : bearishSL
// Stop Loss (either original or trailing)
strategy.exit("Short SL", "Short", stop=effectiveStopLoss)
// Take Profit 1 (Partial Close by Contracts)
if enablePartialClose and not tp1HitShort and low <= bearishTP1 and math.abs(strategy.position_size) >= partialCloseQty
strategy.close("Short", qty=partialCloseQty, comment="Short TP1", immediately=true)
tp1HitShort := true
// Take Profit 2 (Close Remaining Position) or Full Close if Partial is Disabled
if (enablePartialClose and tp1HitShort and low <= bearishTP2) or (not enablePartialClose and low <= bearishTP1)
strategy.close("Short", comment=enablePartialClose ? "Short TP2" : "Short TP1", immediately=true)
// Reset flags when position closes
if strategy.position_size == 0
tp1HitLong := false
tp1HitShort := false
// Reset trailing stop variables
longTrailStop := na
shortTrailStop := na
longTrailActive := false
shortTrailActive := false
// Visualization - Entry Zones
var box bullishBox = na
var box bearishBox = na
var label bullishZoneLabel = na
var label bearishZoneLabel = na
// Bullish Entry Zone
// Bearish Entry Zone
// Visualization - Risk/Reward Lines for Active Positions
var line longTP1Line = na
var line longTP2Line = na
var line longSLLine = na
var line shortTP1Line = na
var line shortTP2Line = na
var line shortSLLine = na
// Labels for TP/SL Values
// Short Position Lines and Labels
// Support and Resistance Lines
plot(support, "Support", color=color.green, linewidth=1, style=plot.style_line)
plot(resistance, "Resistance", color=color.red, linewidth=1, style=plot.style_line)
// Plot Trend MA if enabled
plot(enableTrendFilter ? trendMA : na, "Trend MA", color=color.blue, linewidth=2)
// Plot Trailing Stops if active
plot(strategy.position_size > 0 and longTrailActive ? longTrailStop : na, "Long Trail Stop", color=color.orange, linewidth=2, style=plot.style_stepline)
plot(strategy.position_size < 0 and shortTrailActive ? shortTrailStop : na, "Short Trail Stop", color=color.orange, linewidth=2, style=plot.style_stepline)