多级别价格结构识别与公允价值缺口量化交易系统

CHoCH FVG Pivot Points Risk-Reward Ratio Price Structure SWING POINTS Quantitative Trading
创建日期: 2025-06-03 10:50:29 最后修改: 2025-06-03 10:50:29
复制: 0 点击次数: 104
avatar of ianzeng123 ianzeng123
2
关注
69
关注者

多级别价格结构识别与公允价值缺口量化交易系统 多级别价格结构识别与公允价值缺口量化交易系统

概述

多级别价格结构识别与公允价值缺口量化交易系统是一种基于价格行为的自动化交易策略,它结合了两个关键的交易概念:变化特征(CHoCH,Change of Character)和公允价值缺口(FVG,Fair Value Gap)。该策略通过识别市场结构变化点和不平衡区域来捕捉高概率交易机会,在价格回撤至公允价值缺口时进场,实现精确的入场和出场控制。这种系统化的方法使交易者能够客观地分析市场,消除情绪因素,并具有明确的风险管理规则。

策略原理

该量化交易系统基于以下核心原理运作:

  1. 价格结构识别:通过波峰波谷(Pivot Points)技术识别市场中的摆动高点和摆动低点,这些点位是市场结构的关键组成部分。系统使用参数化的摆动长度(默认为5个周期)来确定这些关键点位。

  2. 变化特征(CHoCH)检测:

    • 多头CHoCH:价格在形成较低的低点后突破先前的摆动高点
    • 空头CHoCH:价格在形成较高的高点后突破先前的摆动低点 系统要求CHoCH形成的时间间隔满足最小距离要求(默认10个周期),以过滤掉无效信号。
  3. 公允价值缺口(FVG)识别:

    • 多头FVG:当前蜡烛的低点高于两个周期前蜡烛的高点
    • 空头FVG:当前蜡烛的高点低于两个周期前蜡烛的低点 系统设置了最小FVG大小阈值(默认2个点),确保只捕捉有意义的价格不平衡。
  4. 入场逻辑:

    • 多头入场:在确认多头CHoCH后,等待价格回撤至多头FVG区域
    • 空头入场:在确认空头CHoCH后,等待价格回撤至空头FVG区域 入场价格设定为FVG区域的中点,提供平衡的入场价格。
  5. 风险管理机制:

    • 止损设置在最近的摆动低点(多头)或摆动高点(空头)
    • 止盈基于风险回报比(默认2.0)或固定目标点数
    • 可选的头寸自动调整功能,根据账户风险百分比和止损距离计算头寸大小

策略优势

经过对代码的深入分析,该策略具有以下显著优势:

  1. 结构化市场分析:策略基于价格结构变化和市场不平衡原理,而非简单的指标交叉,使其在识别市场转折点方面具有独特优势。

  2. 精确的入场时机:通过等待CHoCH后的FVG形成,策略能够在有利的价格水平入场,避免追高杀低,提高入场质量。

  3. 自适应风险管理:策略根据实际市场结构自动调整止损位置,而非使用固定点数,这种方法更符合市场实际波动特性。

  4. 可视化交易元素:策略提供了全面的可视化功能,包括CHoCH标签、FVG盒子、摆动点和交易线,使交易者能够直观理解市场结构和策略逻辑。

  5. 灵活的头寸管理:通过风险百分比自动调整头寸大小,既保护账户资金又能根据波动性自动调整风险敞口。

  6. 性能优化设计:代码中包含了清理旧FVG盒子的机制,确保长时间运行时系统性能不会降低。

  7. 综合绩效监控:策略提供实时绩效表格,包括策略状态、胜率、利润因子等关键指标,便于交易者评估策略表现。

策略风险

尽管该策略设计合理,但仍存在一些潜在风险和局限性:

  1. 假突破风险:CHoCH信号可能是假突破,导致价格迅速回撤并触发止损。为缓解此风险,可考虑增加确认机制,如等待多根K线确认突破。

  2. 间隙风险:在波动性大的市场或隔夜交易中,价格可能跳空超过止损位置,导致实际损失超过预期。建议使用保证止损订单(如有可能)或降低头寸规模。

  3. 参数敏感性:策略性能高度依赖于摆动长度、最小CHoCH距离和FVG大小等参数设置。不同市场和时间框架可能需要不同的参数组合,建议进行全面的回测优化。

  4. 市场环境依赖:该策略在趋势市场中表现更好,而在盘整市场可能产生频繁的错误信号。考虑添加趋势过滤器或市场状态识别机制。

  5. 计算复杂性:策略使用多个数组和条件检查,在较低配置的设备上可能导致性能问题。虽然代码已包含清理机制,但长期运行仍需注意资源消耗。

  6. 回撤管理不足:目前策略没有考虑不同市场条件下的头寸规模动态调整,在持续不利环境中可能导致较大回撤。建议实现账户回撤限制和逐步减仓机制。

策略优化方向

基于代码分析,提出以下优化方向:

  1. 多时间框架确认:引入更高时间框架的市场结构分析,只在主要趋势方向交易。例如,可添加日线趋势过滤器,仅在日线趋势方向一致时执行交易。

  2. 动态参数优化:实现基于市场波动性自动调整的参数系统,例如在高波动期间增加最小FVG大小和CHoCH距离要求,低波动期间减小这些参数。

  3. 入场优化:

    • 实现分批入场策略,例如在FVG区域的不同水平设置多个入场点
    • 添加额外的入场确认,如成交量突破或动量指标确认
  4. 风险管理增强:

    • 实现追踪止损功能,随着交易盈利自动调整止损位置
    • 添加部分获利功能,在达到一定盈利水平时平掉部分头寸
    • 引入最大回撤限制,当账户回撤达到阈值时自动减小头寸规模或暂停交易
  5. 市场状态适应:

    • 添加市场状态识别(趋势/盘整/高波动),并根据不同状态调整策略参数
    • 在盘整市场减少或避免交易
    • 在波动性突然增加时采取更保守的头寸规模
  6. 机器学习增强:引入机器学习算法对历史CHoCH和FVG模式进行分析,识别成功率更高的模式特征,并据此调整入场决策权重。

  7. 交易时间过滤:添加交易时间过滤器,避开重大新闻公告和市场开盘/收盘时的高波动期,专注于流动性较好的交易时段。

总结

多级别价格结构识别与公允价值缺口量化交易系统是一个结合了先进价格行为理论的完整交易解决方案。它通过识别市场结构变化(CHoCH)和价格不平衡区域(FVG),在理想的价格水平进场,并采用系统化的风险管理方法保护交易资本。

该策略最大的优势在于其基于实际市场结构的分析方法,而非依赖滞后指标,使其能够更早识别市场转折点。同时,完善的可视化功能和绩效监控系统使交易者能够直观理解策略逻辑并评估其有效性。

虽然存在假突破和参数敏感性等风险,但通过提出的优化方向,尤其是多时间框架确认、动态参数调整和增强的风险管理功能,可以显著提高策略的稳定性和性能。

对于希望采用系统化方法进行交易的投资者,这一策略提供了一个坚实的框架,既吸收了传统价格行为交易的精髓,又利用了量化系统的客观性和纪律性优势。通过持续的参数优化和市场适应性调整,该策略有潜力在各种市场环境中实现稳定的交易业绩。

策略源码
/*backtest
start: 2024-06-03 00:00:00
end: 2025-06-02 00:00:00
period: 2h
basePeriod: 2h
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/

//@version=5
strategy("ICT CHoCH & FVG Strategy - NQ1!", overlay=true, pyramiding=0, calc_on_every_tick=false, calc_on_order_fills=false, max_boxes_count=500, max_lines_count=100, max_labels_count=100)

// ============================================================================
// INPUT PARAMETERS
// ============================================================================

// Strategy Settings
riskRewardRatio = input.float(2.0, title="Risk:Reward Ratio", minval=0.5, maxval=10.0, group="Strategy Settings")
fixedTarget = input.int(40, title="Fixed Target (Ticks)", minval=5, maxval=200, group="Strategy Settings")
useRRTarget = input.bool(true, title="Use Risk:Reward Target", tooltip="If false, uses fixed target", group="Strategy Settings")
riskPercent = input.float(2.0, title="Risk % of Account", minval=0.1, maxval=10.0, group="Strategy Settings")
useAutoSize = input.bool(false, title="Auto Size Positions", tooltip="Size based on risk % and stop distance", group="Strategy Settings")

// Visual Settings
showCHoCH = input.bool(true, title="Show CHoCH Labels", group="Visual Settings")
showFVG = input.bool(true, title="Show FVG Boxes", group="Visual Settings")
showSwings = input.bool(true, title="Show Swing Points", group="Visual Settings")
showTradeLines = input.bool(true, title="Show Entry/SL/TP Lines", group="Visual Settings")

// CHoCH Detection Settings
swingLength = input.int(5, title="Swing Detection Length", minval=2, maxval=20, group="CHoCH Settings")
minCHoCHDistance = input.int(10, title="Min CHoCH Distance (bars)", minval=5, maxval=50, group="CHoCH Settings")

// FVG Settings
minFVGSize = input.float(2.0, title="Min FVG Size (ticks)", minval=0.25, maxval=10.0, group="FVG Settings")
maxFVGAge = input.int(50, title="Max FVG Age (bars)", minval=10, maxval=200, group="FVG Settings")

// ============================================================================
// VARIABLES AND ARRAYS
// ============================================================================

// Swing point detection
var float lastSwingHigh = na
var float lastSwingLow = na
var int lastSwingHighBar = na
var int lastSwingLowBar = na

// CHoCH tracking
var bool bullishCHoCH = false
var bool bearishCHoCH = false
var float chochLevel = na
var int chochBar = na
var bool waitingForFVG = false

// FVG tracking
var array<box> bullishFVGs = array.new<box>()
var array<box> bearishFVGs = array.new<box>()
var float activeFVGTop = na
var float activeFVGBottom = na
var bool lookingForEntry = false

// Trade management
var float stopLossLevel = na
var float takeProfitLevel = na
var bool inPosition = false

// ============================================================================
// HELPER FUNCTIONS
// ============================================================================

// Convert ticks to price for NQ
ticksToPrice(ticks) => ticks * 0.25

// Calculate position size based on risk
calcPositionSize(stopDistance) =>
    if useAutoSize and strategy.equity > 0
        accountValue = strategy.equity
        riskAmount = accountValue * (riskPercent / 100)
        stopDistancePrice = stopDistance * syminfo.mintick
        math.max(1, math.floor(riskAmount / stopDistancePrice))
    else
        1

// ============================================================================
// SWING POINT DETECTION
// ============================================================================

// Detect swing highs and lows
swingHigh = ta.pivothigh(high, swingLength, swingLength)
swingLow = ta.pivotlow(low, swingLength, swingLength)

// Update swing points
if not na(swingHigh)
    lastSwingHigh := swingHigh
    lastSwingHighBar := bar_index - swingLength
    if showSwings
        label.new(bar_index - swingLength, swingHigh, "SH", style=label.style_triangledown, color=color.red, size=size.tiny)

if not na(swingLow)
    lastSwingLow := swingLow
    lastSwingLowBar := bar_index - swingLength
    if showSwings
        label.new(bar_index - swingLength, swingLow, "SL", style=label.style_triangleup, color=color.green, size=size.tiny)

// ============================================================================
// CHoCH DETECTION
// ============================================================================

// Check for bullish CHoCH (break above prior swing high after making lower low)
bullishCHoCHCondition = not na(lastSwingHigh) and not na(lastSwingLow) and 
                       high > lastSwingHigh and 
                       lastSwingLow < lastSwingHigh and
                       bar_index - lastSwingHighBar > minCHoCHDistance and
                       strategy.position_size == 0

// Check for bearish CHoCH (break below prior swing low after making higher high)
bearishCHoCHCondition = not na(lastSwingHigh) and not na(lastSwingLow) and 
                       low < lastSwingLow and 
                       lastSwingHigh > lastSwingLow and
                       bar_index - lastSwingLowBar > minCHoCHDistance and
                       strategy.position_size == 0

// Process CHoCH signals
if bullishCHoCHCondition and not bullishCHoCH
    bullishCHoCH := true
    bearishCHoCH := false
    chochLevel := lastSwingHigh
    chochBar := bar_index
    waitingForFVG := true
    lookingForEntry := false
    


if bearishCHoCHCondition and not bearishCHoCH
    bearishCHoCH := true
    bullishCHoCH := false
    chochLevel := lastSwingLow
    chochBar := bar_index
    waitingForFVG := true
    lookingForEntry := false
    


// ============================================================================
// FVG DETECTION
// ============================================================================

// Check for FVG formation (3-candle pattern)
if bar_index >= 2
    // Bullish FVG: low[0] > high[2]
    bullishFVG = low[0] > high[2] and (low[0] - high[2]) >= ticksToPrice(minFVGSize)
    
    // Bearish FVG: high[0] < low[2]  
    bearishFVG = high[0] < low[2] and (low[2] - high[0]) >= ticksToPrice(minFVGSize)
    
    // Process bullish FVG after bullish CHoCH
    if bullishFVG and bullishCHoCH and waitingForFVG and bar_index > chochBar
        fvgTop = low[0]
        fvgBottom = high[2]
        

        
        // Set active FVG for entry
        activeFVGTop := fvgTop
        activeFVGBottom := fvgBottom
        waitingForFVG := false
        lookingForEntry := true
    
    // Process bearish FVG after bearish CHoCH
    if bearishFVG and bearishCHoCH and waitingForFVG and bar_index > chochBar
        fvgTop = low[2]
        fvgBottom = high[0]
        

        
        // Set active FVG for entry
        activeFVGTop := fvgTop
        activeFVGBottom := fvgBottom
        waitingForFVG := false
        lookingForEntry := true

// ============================================================================
// ENTRY LOGIC
// ============================================================================

// Long entry: price touches bullish FVG after bullish CHoCH
longCondition = lookingForEntry and bullishCHoCH and 
               not na(activeFVGTop) and not na(activeFVGBottom) and
               low <= activeFVGTop and high >= activeFVGBottom and
               strategy.position_size == 0

// Short entry: price touches bearish FVG after bearish CHoCH  
shortCondition = lookingForEntry and bearishCHoCH and  not na(activeFVGTop) and not na(activeFVGBottom) and low <= activeFVGTop and high >= activeFVGBottom and  strategy.position_size == 0

// Process long entries
if longCondition
    var float entryPrice = na
    var float stopLoss = na
    var float takeProfit = na
    
    entryPrice := math.avg(activeFVGTop, activeFVGBottom)
    stopLoss := lastSwingLow
    stopDistance = entryPrice - stopLoss
    
    if useRRTarget
        takeProfit := entryPrice + (stopDistance * riskRewardRatio)
    else
        takeProfit := entryPrice + ticksToPrice(fixedTarget)
    
    // Calculate position size
    qty = calcPositionSize(stopDistance / syminfo.mintick)
    
    // Enter trade
    strategy.entry("Long", strategy.long, qty=qty)
    strategy.exit("Long Exit", "Long", stop=stopLoss, limit=takeProfit)
    
    // Update tracking
    stopLossLevel := stopLoss
    takeProfitLevel := takeProfit
    inPosition := true
    lookingForEntry := false
    
    // Reset CHoCH state
    bullishCHoCH := false
    activeFVGTop := na
    activeFVGBottom := na
    


// Process short entries
if shortCondition
    var float entryPrice = na
    var float stopLoss = na
    var float takeProfit = na
    
    entryPrice := math.avg(activeFVGTop, activeFVGBottom)
    stopLoss := lastSwingHigh
    stopDistance = stopLoss - entryPrice
    
    if useRRTarget
        takeProfit := entryPrice - (stopDistance * riskRewardRatio)
    else
        takeProfit := entryPrice - ticksToPrice(fixedTarget)
    
    // Calculate position size
    qty = calcPositionSize(stopDistance / syminfo.mintick)
    
    // Enter trade
    strategy.entry("Short", strategy.short, qty=qty)
    strategy.exit("Short Exit", "Short", stop=stopLoss, limit=takeProfit)
    
    // Update tracking
    stopLossLevel := stopLoss
    takeProfitLevel := takeProfit
    inPosition := true
    lookingForEntry := false
    
    // Reset CHoCH state
    bearishCHoCH := false
    activeFVGTop := na
    activeFVGBottom := na
    

// ============================================================================
// POSITION MANAGEMENT
// ============================================================================

// Reset position state when trade is closed
if inPosition and strategy.position_size == 0
    inPosition := false
    stopLossLevel := na
    takeProfitLevel := na

// ============================================================================
// VISUAL SIGNALS
// ============================================================================

// Plot entry signals
plotshape(longCondition, title="Long Entry", location=location.belowbar, color=color.green, 
          style=shape.triangleup, size=size.normal)

plotshape(shortCondition, title="Short Entry", location=location.abovebar, color=color.red, 
          style=shape.triangledown, size=size.normal)

// Plot active stop loss and take profit levels
plot(inPosition ? stopLossLevel : na, title="Stop Loss", color=color.red, linewidth=2, style=plot.style_linebr)
plot(inPosition ? takeProfitLevel : na, title="Take Profit", color=color.green, linewidth=2, style=plot.style_linebr)

// ============================================================================
// CLEANUP
// ============================================================================

// Clean up old FVG boxes (helps with performance)
if bar_index % 100 == 0
    while array.size(bullishFVGs) > 20
        box.delete(array.shift(bullishFVGs))
    while array.size(bearishFVGs) > 20
        box.delete(array.shift(bearishFVGs))

// ============================================================================
// ALERTS
// ============================================================================

// Alert conditions
alertcondition(longCondition, title="Long Entry Signal", message="ICT Strategy: Long entry at FVG - SL: {{strategy.position_avg_price}}")
alertcondition(shortCondition, title="Short Entry Signal", message="ICT Strategy: Short entry at FVG - SL: {{strategy.position_avg_price}}")

相关推荐