
Hệ thống giao dịch định lượng phân tích cấu trúc giá nhiều cấp với khoảng cách giá trị công bằng là một chiến lược giao dịch tự động dựa trên hành vi giá, kết hợp hai khái niệm giao dịch quan trọng: đặc điểm thay đổi (CHoCH, Change of Character) và khoảng cách giá trị công bằng (FVG, Fair Value Gap). Chiến lược này nắm bắt các cơ hội giao dịch có xác suất cao bằng cách xác định các điểm thay đổi cấu trúc thị trường và khu vực không cân bằng, nhập cảnh khi giá quay trở lại khoảng cách giá trị công bằng, kiểm soát chính xác vào và ra.
Hệ thống giao dịch định lượng hoạt động dựa trên các nguyên tắc cốt lõi sau:
Xác định cấu trúc giá cảThông qua công nghệ Pivot Points, các điểm biến động trong thị trường được xác định là các điểm biến động cao và thấp, các điểm này là thành phần quan trọng của cấu trúc thị trường. Hệ thống sử dụng độ dài biến động tham số (thường là 5 chu kỳ) để xác định các điểm quan trọng này.
Chức năng thay đổi (CHoCH):
Xác định khoảng trống giá trị công bằng (FVG):
Nhập logic:
Cơ chế quản lý rủi ro:
Sau khi phân tích sâu về mã, chiến lược này có những ưu điểm đáng chú ý sau:
Phân tích thị trường cấu trúcChiến lược này dựa trên các nguyên tắc thay đổi cấu trúc giá cả và sự mất cân bằng của thị trường, chứ không phải là chỉ số giao thoa đơn giản, làm cho nó có lợi thế độc đáo trong việc xác định các điểm biến đổi của thị trường.
Thời gian chính xácBằng cách chờ đợi cho CHoCH sau khi FVG hình thành, chiến lược này có thể nhập cảnh ở mức giá thuận lợi, tránh theo đuổi cao giết thấp, nâng cao chất lượng nhập cảnh.
Quản lý rủi ro thích nghiChiến lược: Điều chỉnh vị trí dừng tự động dựa trên cấu trúc thị trường thực tế, thay vì sử dụng số điểm cố định, phương pháp này phù hợp hơn với đặc tính biến động thực tế của thị trường.
Hình ảnh các yếu tố giao dịchChiến lược cung cấp tính năng hiển thị toàn diện, bao gồm thẻ CHoCH, hộp FVG, điểm dao động và đường giao dịch, cho phép thương nhân hiểu trực quan cấu trúc thị trường và logic chiến lược.
Quản lý vị thế linh hoạtTự động điều chỉnh kích thước vị trí bằng tỷ lệ rủi ro, bảo vệ tài khoản và tự động điều chỉnh lỗ hổng rủi ro theo biến động.
Thiết kế tối ưu hóa hiệu suất: Mã có chứa cơ chế làm sạch các hộp FVG cũ để đảm bảo rằng hiệu suất hệ thống không bị suy giảm khi chạy lâu.
Giám sát hiệu quả tổng hợpChiến lược cung cấp bảng hiệu suất thời gian thực, bao gồm các chỉ số quan trọng như trạng thái chiến lược, tỷ lệ thắng, yếu tố lợi nhuận, để giúp các nhà giao dịch đánh giá hiệu suất chiến lược.
Mặc dù chiến lược này được thiết kế hợp lý, nhưng vẫn có một số rủi ro và hạn chế tiềm ẩn:
Rủi ro đột phá giả: CHoCH tín hiệu có thể là phá vỡ giả, dẫn đến giá rút lại nhanh chóng và kích hoạt dừng lỗ. Để giảm thiểu rủi ro này, bạn có thể xem xét thêm cơ chế xác nhận, chẳng hạn như chờ đợi dòng K của Dogan xác nhận phá vỡ.
Rủi ro lỗ hổng: Trong thị trường có nhiều biến động hoặc giao dịch qua đêm, giá có thể vượt quá vị trí dừng lỗ, dẫn đến tổn thất thực tế cao hơn dự kiến.
Độ nhạy tham sốHiệu suất chiến lược phụ thuộc rất nhiều vào các thiết lập tham số như độ dài dao động, khoảng cách CHoCH tối thiểu và kích thước FVG. Các thị trường và khung thời gian khác nhau có thể yêu cầu các kết hợp tham số khác nhau, nên tối ưu hóa phản hồi toàn diện.
Sự phụ thuộc vào môi trường thị trường: Chiến lược này hoạt động tốt hơn trong thị trường xu hướng, và có thể tạo ra các tín hiệu sai thường xuyên trong thị trường tổng hợp. Hãy xem xét thêm bộ lọc xu hướng hoặc cơ chế nhận dạng trạng thái thị trường.
Độ phức tạp tính toánChiến lược: Sử dụng nhiều mảng và kiểm tra điều kiện, có thể gây ra vấn đề về hiệu suất trên các thiết bị cấu hình thấp hơn. Mặc dù mã đã bao gồm cơ chế làm sạch, nhưng hoạt động lâu dài vẫn cần lưu ý đến tiêu thụ tài nguyên.
Quản lý rút lui không tốtChiến lược hiện tại không tính đến sự thay đổi động của quy mô vị trí trong các điều kiện thị trường khác nhau, có thể dẫn đến việc rút lui lớn hơn trong môi trường bất lợi liên tục.
Dựa trên phân tích mã, các hướng tối ưu hóa sau đây được đề xuất:
Xác nhận khung thời gian đa dạngVí dụ, bạn có thể thêm bộ lọc xu hướng ngày, chỉ thực hiện giao dịch khi xu hướng ngày phù hợp.
Tối ưu hóa tham số động: Thực hiện hệ thống tham số điều chỉnh tự động dựa trên biến động thị trường, chẳng hạn như tăng kích thước FVG tối thiểu và yêu cầu khoảng cách CHoCH trong thời gian biến động cao và giảm các tham số này trong thời gian biến động thấp.
Tối ưu hóa nhập học:
Tăng cường quản lý rủi ro:
Thị trường thích nghi:
Tăng cường học máyGhi chú: Tiến hành các thuật toán học máy để phân tích các mô hình CHoCH và FVG lịch sử, xác định các đặc điểm mô hình có tỷ lệ thành công cao hơn và điều chỉnh trọng lượng quyết định nhập cảnh phù hợp.
Trình lọc thời gian giao dịchThêm bộ lọc thời gian giao dịch, tránh các thông báo tin tức quan trọng và thời gian biến động cao khi thị trường mở / đóng cửa, tập trung vào thời gian giao dịch có tính thanh khoản tốt hơn.
Hệ thống giao dịch định lượng cấu trúc giá nhiều cấp với lỗ hổng giá trị công bằng là một giải pháp giao dịch hoàn chỉnh kết hợp lý thuyết hành vi giá tiên tiến. Nó bảo vệ vốn giao dịch bằng cách xác định sự thay đổi cấu trúc thị trường (CHoCH) và khu vực không cân bằng giá (FVG) tại mức giá lý tưởng và sử dụng phương pháp quản lý rủi ro có hệ thống.
Ưu điểm lớn nhất của chiến lược này là phương pháp phân tích dựa trên cấu trúc thị trường thực tế, thay vì dựa vào các chỉ số chậm trễ, cho phép nó xác định sớm hơn các điểm biến đổi của thị trường. Ngoài ra, các chức năng hiển thị và hệ thống giám sát hiệu suất hoàn thiện cho phép các nhà giao dịch hiểu trực quan logic của chiến lược và đánh giá hiệu quả của nó.
Mặc dù có những rủi ro như đột phá giả và tính nhạy cảm của tham số, nhưng sự ổn định và hiệu suất của chiến lược có thể được cải thiện đáng kể bằng cách đưa ra hướng tối ưu hóa, đặc biệt là xác nhận khung thời gian đa, điều chỉnh tham số động và tăng cường chức năng quản lý rủi ro.
Đối với các nhà đầu tư muốn sử dụng phương pháp giao dịch có hệ thống, chiến lược này cung cấp một khuôn khổ vững chắc, hấp thụ tinh thần của giao dịch hành vi giá truyền thống và lợi dụng tính khách quan và kỷ luật của hệ thống định lượng. Với sự tối ưu hóa tham số liên tục và điều chỉnh phù hợp với thị trường, chiến lược này có tiềm năng đạt được kết quả giao dịch ổn định trong nhiều môi trường thị trường.
/*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}}")