Ma trận trung bình động thích ứng đa chiều và chiến lược giao dịch chính xác động ATR

MA ATR HMA TEMA DEMA VWMA ZLEMA ALMA KAMA EMA SMA WMA
Ngày tạo: 2025-04-16 15:50:36 sửa đổi lần cuối: 2025-04-16 15:50:36
sao chép: 0 Số nhấp chuột: 412
2
tập trung vào
319
Người theo dõi

Ma trận trung bình động thích ứng đa chiều và chiến lược giao dịch chính xác động ATR Ma trận trung bình động thích ứng đa chiều và chiến lược giao dịch chính xác động ATR

Tổng quan

Chiến lược giao dịch chính xác chuyển động tự điều chỉnh đa chiều với ma trận động ATR là một hệ thống giao dịch định lượng cao, được thiết kế cho các điều kiện thị trường thay đổi nhanh chóng. Cốt lõi của chiến lược là kết hợp nhiều loại bộ lọc chuyển động trung bình với ATR (trung lượng thực trung bình) để tạo thành một ma trận giao dịch linh hoạt và tự điều chỉnh. Bằng cách nắm bắt chính xác xu hướng và biến động của thị trường, chiến lược có thể xác định các điểm vào và thoát có tỷ lệ cao trong môi trường giao dịch tần số cao, đồng thời thực hiện các biện pháp kiểm soát rủi ro nghiêm ngặt.

Nguyên tắc chiến lược

Các nguyên tắc cốt lõi của chiến lược này được xây dựng dựa trên sự phối hợp của một số thành phần quan trọng:

  1. Ma trận trung bình di chuyển cấp caoChiến lược thực hiện lên đến 11 loại moving average khác nhau, bao gồm SMA, EMA, SMMA, HMA, TEMA, WMA, VWMA, ZLEMA, ALMA, KAMA và DEMA. Mỗi loại moving average có phương pháp tính toán và phản ứng riêng, có thể được lựa chọn linh hoạt theo điều kiện thị trường. Hệ thống sử dụng hai loại moving average ((nhanh và chậm) làm chỉ số xu hướng chính, giao chéo và vị trí tương đối của chúng được sử dụng để tạo ra tín hiệu giao dịch cơ bản.

  2. Quản lý rủi ro dựa trên ATRChiến lược sử dụng chỉ số ATR để đo lường sự biến động của thị trường và áp dụng nó cho nhiều khía cạnh:

    • Đánh giá biến động: Sử dụng tỷ lệ ATR so với giá đóng cửa như một điều kiện lọc giá trị biến động
    • Bộ lọc nhập cảnh: đảm bảo giá phải ở đủ khoảng cách với đường trung bình di chuyển chậm (được tính bằng số nhân của ATR) để vào
    • Kiểm soát rủi ro động: Thiết lập dừng cố định, mục tiêu lợi nhuận và theo dõi dừng lỗ dựa trên ATR để quản lý rủi ro phù hợp với biến động thị trường hiện tại
  3. Trình lọc xu hướng nhiều khung thời gianChiến lược: Tăng cường tín hiệu tin cậy bằng cách tìm kiếm xu hướng trung bình di chuyển trong khung thời gian cao hơn ((15 phút) để đảm bảo hướng giao dịch phù hợp với xu hướng thị trường lớn hơn.

  4. Xác nhận giao dịch và cửa sổ thời gian: Giao dịch chỉ được thực hiện khi đáp ứng yêu cầu khối lượng giao dịch tối thiểu, có đột phá khối lượng giao dịch và trong cửa sổ thời gian giao dịch được xác định trước, nâng cao chất lượng giao dịch hơn nữa.

  5. Logic phát tín hiệu

    • Điều kiện đa đầu: Giá cao hơn trung bình di chuyển nhanh và chậm, trung bình di chuyển nhanh cao hơn trung bình di chuyển chậm, đồng thời đáp ứng bộ lọc ATR, điều kiện giao dịch và yêu cầu cửa sổ thời gian
    • Điều kiện đầu rỗng: Điều kiện tương ứng trong trường hợp ngược lại
  6. Logic tổng hợpChiến lược sử dụng cơ chế thoát ba tầng: dừng cố định (tỷ lệ ATR), lợi nhuận mục tiêu (tỷ lệ ATR) và dừng theo dõi (tỷ lệ ATR theo điều chỉnh động), cung cấp bảo vệ rủi ro toàn diện cho mỗi giao dịch.

Lợi thế chiến lược

Phân tích mã hóa của chiến lược này cho thấy những ưu điểm đáng chú ý sau:

  1. Khả năng thích nghi tuyệt vờiThông qua nhiều loại moving average có thể chuyển đổi (từ HMA đến KAMA, v.v.), chiến lược có thể thích ứng với các điều kiện thị trường khác nhau. Sự linh hoạt này cho phép các nhà giao dịch chọn chỉ số tốt nhất dựa trên môi trường thị trường hiện tại mà không cần phải viết lại toàn bộ chiến lược.

  2. Quản lý rủi ro độngCơ chế kiểm soát rủi ro dựa trên ATR đảm bảo mục tiêu dừng lỗ và lợi nhuận sẽ được điều chỉnh tự động theo biến động của thị trường. Phương pháp này cung cấp sự bảo vệ tốt hơn trong thị trường biến động lớn, đồng thời cho phép thu được nhiều lợi nhuận hơn trong thị trường xu hướng.

  3. Bộ lọc tín hiệu đa tầngBằng cách kết hợp các phương thức như giao dịch qua đường trung bình di chuyển, phân tích khối lượng giao dịch, giảm giá biến động và lọc xu hướng trên nhiều khung thời gian, chiến lược này có hiệu quả trong việc giảm các tín hiệu sai và cải thiện chất lượng giao dịch. Đặc biệt, tính năng lọc xu hướng trên khung thời gian 15 phút làm giảm đáng kể khả năng giao dịch ngược.

  4. Điều kiện chính xácChiến lược này không chỉ dựa vào giao thoa các chỉ số kỹ thuật, mà còn yêu cầu giữ khoảng cách ATR đủ giữa giá và đường trung bình di chuyển chậm, giúp tránh giao dịch thường xuyên trong thị trường ngang và giảm tổn thất do phá vỡ giả.

  5. Giám sát hiệu suất minh bạchBảng điều khiển tích hợp cung cấp hiển thị thời gian thực của các chỉ số hiệu suất quan trọng, bao gồm lợi nhuận / lỗ, cổ phần, ATR hiện tại và khoảng cách giữa giá trị nguyên liệu và tỷ lệ phần trăm và trung bình di chuyển, cho phép các nhà giao dịch đánh giá trạng thái chiến lược bất cứ lúc nào.

Rủi ro chiến lược

Mặc dù chiến lược này được thiết kế tốt, nhưng vẫn có những rủi ro tiềm ẩn:

  1. Lỗ bẫy tối ưu hóa tham sốChiến lược bao gồm rất nhiều tham số (như loại và chu kỳ đường trung bình di chuyển, chu kỳ ATR và nhân số, v.v.), tối ưu hóa quá mức có thể dẫn đến sự phù hợp đường cong, làm cho chiến lược không hoạt động tốt trong giao dịch thực. Giải pháp là kiểm tra mạnh mẽ trên khắp thị trường và trong khoảng thời gian để tránh điều chỉnh tham số quá mức.

  2. Rủi ro biến đổi nhanh chóngMặc dù sử dụng dừng động ATR, nhưng trong trường hợp thị trường đột ngột đảo ngược (ví dụ như sau một thông báo lớn), giá có thể tăng cao trước khi dừng phát ra, dẫn đến tổn thất vượt mức dự kiến.

  3. Tín hiệu chậm trễ: Tất cả các đường trung bình di chuyển đều có độ trễ về bản chất. Ngay cả các biến thể có độ trễ thấp như HMA hoặc ZLEMA cũng có thể bỏ lỡ điểm nhập cảnh lý tưởng trong thị trường nhanh.

  4. Sự phụ thuộc vào khối lượng giao dịchChiến lược phát tín hiệu khi khối lượng giao dịch tăng đột biến, nhưng khối lượng giao dịch có thể gây hiểu nhầm trong một số thị trường hoặc thời gian. Nếu cần thiết, bạn nên điều chỉnh bộ lọc khối lượng giao dịch hoặc xem xét tắt tính năng này trong điều kiện thị trường cụ thể.

  5. Giới hạn cửa sổ thời gianCác cửa sổ giao dịch được chỉ định có thể bỏ lỡ các cơ hội giao dịch quan trọng vào ban đêm hoặc sớm.

Hướng tối ưu hóa chiến lược

Sau khi phân tích code, đây là một số hướng tối ưu hóa có thể:

  1. Điều chỉnh tham số thích ứngMột tối ưu hóa cao cấp là thực hiện các tham số điều chỉnh tự động dựa trên tình trạng thị trường (trend, biến động, phạm vi). Ví dụ, có thể tự động tăng ATR nhân trong thời gian biến động cao, hoặc chuyển đổi loại trung bình di chuyển trong môi trường thị trường khác nhau.

  2. Tích hợp mô hình học máy: Bằng cách giới thiệu lớp học máy để dự đoán loại moving average nào có thể hoạt động tốt nhất trong điều kiện thị trường hiện tại, để tự động chọn kết hợp moving average tối ưu. Điều này có thể được thực hiện bằng cách phân tích hiệu suất tương đối của các chỉ số khác nhau trong dữ liệu lịch sử.

  3. Xác định xu hướng cải thiệnNgoài bộ lọc xu hướng 15 phút hiện có, các thuật toán nhận dạng xu hướng phức tạp hơn, chẳng hạn như chỉ số Hurst hoặc chỉ số chuyển động định hướng (DMI), có thể được tích hợp để xác định chính xác hơn cường độ và tính bền vững của xu hướng.

  4. Tăng cường chiến lược rút luiChiến lược thoát hiện tại có thể được tối ưu hóa hơn nữa bằng cách thêm các tín hiệu thoát dựa trên cấu trúc thị trường, chẳng hạn như phá vỡ đường xu hướng, mức hỗ trợ / kháng cự quan trọng hoặc biến động mạnh. Điều này có thể giúp khóa lợi nhuận trước khi xu hướng kết thúc.

  5. Kích thước vị thế điều chỉnh rủi ro: thực hiện điều chỉnh kích thước vị trí động dựa trên biến động hiện tại và số tiền tài khoản, thay vì sử dụng số lượng giao dịch cố định. Ví dụ: giảm vị trí trong thời gian biến động cao và tăng vị trí một cách vừa phải trong thời gian biến động thấp để tối ưu hóa tỷ lệ lợi nhuận rủi ro.

  6. Chèn thị trường liên quanTăng cường chất lượng tín hiệu bằng cách theo dõi các thị trường liên quan (như VIX khi giao dịch chỉ số chứng khoán) hoặc liên kết giữa các tài sản. Khi thị trường liên quan hiển thị chuyển động theo hướng nhất quán, có thể tăng độ tin cậy của giao dịch.

Tóm tắt

Chiến lược giao dịch chính xác chuyển động đa chiều với chiến lược giao dịch chính xác chuyển động đa chiều với ATR đại diện cho một phương pháp giao dịch định lượng toàn diện và tiên tiến. Bằng cách kết hợp các lợi thế của nhiều loại moving average với kiểm soát rủi ro cơ bản nghiêm ngặt của ATR, chiến lược này có thể thích ứng với các điều kiện thị trường khác nhau trong khi vẫn duy trì quản lý rủi ro tốt. Cơ chế lọc tín hiệu đa tầng, điều kiện nhập cảnh chính xác và logic thoát hoàn chỉnh của nó đã tạo ra một hệ thống mạnh mẽ có thể xác định các cơ hội giao dịch có khả năng cao.

Giá trị thực sự của chiến lược này nằm ở tính linh hoạt và thích ứng của nó, cho phép các nhà giao dịch tùy chỉnh theo thị trường cụ thể và sở thích rủi ro cá nhân. Có tiềm năng nâng cao hiệu suất của chiến lược hơn nữa thông qua hướng tối ưu hóa được đề xuất, đặc biệt là điều chỉnh tham số thích ứng và tích hợp học máy.

Đối với các nhà giao dịch tìm cách sử dụng một hệ thống kỹ thuật và kỷ luật trong môi trường giao dịch tần số cao, chiến lược này cung cấp một khuôn khổ vững chắc, kết hợp kỹ thuật chính xác và kiểm soát rủi ro, cả hai đều không thể thiếu. Điều quan trọng là các nhà giao dịch phải xác minh hiệu quả của chiến lược trong thị trường mục tiêu của họ bằng cách phản hồi và mô phỏng giao dịch kỹ lưỡng và điều chỉnh cần thiết cho môi trường giao dịch cụ thể.

Mã nguồn chiến lược
/*backtest
start: 2024-04-16 00:00:00
end: 2025-04-15 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=6
strategy("Dskyz (DAFE) MAtrix with ATR-Powered Precision", 
     overlay=true, 
     default_qty_type=strategy.fixed, 
     initial_capital=1000000, 
     commission_value=0, 
     slippage=1, 
     pyramiding=10)

// ==================================================================
// USER-DEFINED FUNCTIONS
// ==================================================================

// Hull Moving Average (HMA)
hma(src, len) =>
    halfLen = math.round(len * 0.5)
    sqrtLen = math.round(math.sqrt(len))
    wmaf = ta.wma(src, halfLen)
    wmaFull = ta.wma(src, len)
    ta.wma(2 * wmaf - wmaFull, sqrtLen)

// Triple Exponential Moving Average (TEMA)
tema(src, len) =>
    ema1 = ta.ema(src, len)
    ema2 = ta.ema(ema1, len)
    ema3 = ta.ema(ema2, len)
    3 * (ema1 - ema2) + ema3

// Double Exponential Moving Average (DEMA)
dema(src, len) =>
    ema1 = ta.ema(src, len)
    ema2 = ta.ema(ema1, len)
    2 * ema1 - ema2

// VWMA - Volume Weighted Moving Average
vwma(src, len) =>
    ta.vwma(src, len)

// ZLEMA - Zero Lag EMA
zlema(src, len) =>
    lag = math.floor((len - 1) / 2)
    ta.ema(2 * src - src[lag], len)

// ALMA - Arnaud Legoux Moving Average
alma(src, len, offset=0.85, sigma=6) =>
    ta.alma(src, len, offset, sigma)

// Custom Kaufman Adaptive Moving Average (KAMA)
kama(src, len) =>
    fastSC = 2.0 / (2 + 1)
    slowSC = 2.0 / (30 + 1)
    change = math.abs(src - src[len])
    volatility = 0.0
    for i = 0 to len - 1
        volatility += math.abs(src - src[i])
    er = volatility != 0 ? change / volatility : 0.0
    sc = math.pow(er * (fastSC - slowSC) + slowSC, 2)
    var float kama_val = na
    kama_val := na(kama_val) ? ta.sma(src, len) : kama_val + sc * (src - kama_val)
    kama_val

// ==================================================================
// INPUTS
// ==================================================================

fastLength   = input.int(9, "[MA] Fast MA Length", minval=1)
slowLength   = input.int(19, "[MA] Slow MA Length", minval=1)
fastMAType   = input.string("SMA", "Fast MA Type", options=["SMA", "EMA", "SMMA", "HMA", "TEMA", "WMA", "VWMA", "ZLEMA", "ALMA", "KAMA", "DEMA"])
slowMAType   = input.string("SMA", "Slow MA Type", options=["SMA", "EMA", "SMMA", "HMA", "TEMA", "WMA", "VWMA", "ZLEMA", "ALMA", "KAMA", "DEMA"])

atrPeriod           = input.int(14, "ATR Period", minval=1)
atrMultiplier       = input.float(1.5, "ATR Multiplier for Filter", minval=0.1, step=0.1)
useTrendFilter      = input.bool(true, "[Filter Settings] Use 15m Trend Filter")
minVolume           = input.int(10, "Minimum Volume", minval=1)
volatilityThreshold = input.float(1.0, "Volatility Threshold (%)", minval=0.1, step=0.1) / 100
tradingStartHour    = input.int(9, "Trading Start Hour (24h)", minval=0, maxval=23)
tradingEndHour      = input.int(16, "Trading End Hour (24h)", minval=0, maxval=23)
trailOffset         = input.float(0.5, "[Exit Settings] Trailing Stop Offset ATR Multiplier", minval=0.01, step=0.01)
profitTargetATRMult = input.float(1.2, "Profit Target ATR Multiplier", minval=0.1, step=0.1)
fixedStopMultiplier = input.float(1.3, "Fixed Stop Multiplier", minval=0.5, step=0.1)
fixedQuantity       = input.int(2, "Trade Quantity", minval=1)

resetDashboard      = input.bool(false, "Reset Dashboard Stats")

// ==================================================================
// CALCULATIONS
// ==================================================================

volumeOk    = volume >= minVolume
currentHour = hour(time)
timeWindow  = currentHour >= tradingStartHour and currentHour <= tradingEndHour
volumeSpike = volume > 1.2 * ta.sma(volume, 10)

// ATR Calculation
atr          = ta.atr(atrPeriod)
volatility   = nz(atr / close, 0)
volatilityOk = volatility <= volatilityThreshold

// ==================================================================
// MOVING AVERAGES CALCULATIONS
// ==================================================================

var float fastMA = na
var float slowMA = na

// Fast MA Logic
if fastMAType == "SMA"
    fastMA := ta.sma(close, fastLength)
else if fastMAType == "EMA"
    fastMA := ta.ema(close, fastLength)
else if fastMAType == "SMMA"
    fastMA := ta.rma(close, fastLength)
else if fastMAType == "HMA"
    fastMA := hma(close, fastLength)
else if fastMAType == "TEMA"
    fastMA := tema(close, fastLength)
else if fastMAType == "WMA"
    fastMA := ta.wma(close, fastLength)
else if fastMAType == "VWMA"
    fastMA := vwma(close, fastLength)
else if fastMAType == "ZLEMA"
    fastMA := zlema(close, fastLength)
else if fastMAType == "ALMA"
    fastMA := alma(close, fastLength)
else if fastMAType == "KAMA"
    fastMA := kama(close, fastLength)
else if fastMAType == "DEMA"
    fastMA := dema(close, fastLength)

// Slow MA Logic
if slowMAType == "SMA"
    slowMA := ta.sma(close, slowLength)
else if slowMAType == "EMA"
    slowMA := ta.ema(close, slowLength)
else if slowMAType == "SMMA"
    slowMA := ta.rma(close, slowLength)
else if slowMAType == "HMA"
    slowMA := hma(close, slowLength)
else if slowMAType == "TEMA"
    slowMA := tema(close, slowLength)
else if slowMAType == "WMA"
    slowMA := ta.wma(close, slowLength)
else if slowMAType == "VWMA"
    slowMA := vwma(close, slowLength)
else if slowMAType == "ZLEMA"
    slowMA := zlema(close, slowLength)
else if slowMAType == "ALMA"
    slowMA := alma(close, slowLength)
else if slowMAType == "KAMA"
    slowMA := kama(close, slowLength)
else if slowMAType == "DEMA"
    slowMA := dema(close, slowLength)

// ==================================================================
// TREND FILTER & SIGNAL LOGIC
// ==================================================================

// Retrieve 15-minute MAs for trend filtering
[fastMA15m, slowMA15m] = request.security(syminfo.tickerid, "15", [ta.sma(close, fastLength), ta.sma(close, slowLength)])
trend15m    = fastMA15m > slowMA15m ? 1 : fastMA15m < slowMA15m ? -1 : 0
trendLongOk = not useTrendFilter or trend15m >= 0
trendShortOk= not useTrendFilter or trend15m <= 0

// ATR-based Price Filter
atrFilterLong  = close > slowMA + atr * atrMultiplier
atrFilterShort = close < slowMA - atr * atrMultiplier

// Signal Logic: MA alignment + filters
maAbove       = close > fastMA and fastMA > slowMA
maBelow       = close < fastMA and fastMA < slowMA
longCondition = maAbove and trendLongOk and atrFilterLong and volumeOk and volumeSpike and timeWindow and volatilityOk
shortCondition= maBelow and trendShortOk and atrFilterShort and volumeOk and volumeSpike and timeWindow and volatilityOk

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

if strategy.position_size == 0 and longCondition
    strategy.entry("Long", strategy.long, qty=fixedQuantity)
if strategy.position_size == 0 and shortCondition
    strategy.entry("Short", strategy.short, qty=fixedQuantity)

// ==================================================================
// EXIT LOGIC
// ==================================================================
if strategy.position_size > 0
    strategy.exit("Long Exit", "Long",
         stop  = strategy.position_avg_price - atr * fixedStopMultiplier,
         limit = strategy.position_avg_price + atr * profitTargetATRMult,
         trail_offset = atr * trailOffset,
         trail_points = atr * trailOffset)
if strategy.position_size < 0
    strategy.exit("Short Exit", "Short",
         stop  = strategy.position_avg_price + atr * fixedStopMultiplier,
         limit = strategy.position_avg_price - atr * profitTargetATRMult,
         trail_offset = atr * trailOffset,
         trail_points = atr * trailOffset)

// ==================================================================
// VISUALS: PLOT MAs
// ==================================================================

plot(fastMA, color=color.blue, linewidth=2, title="Fast MA")
plot(slowMA, color=color.red, linewidth=2, title="Slow MA")

// ==================================================================
// METRICS CALCULATIONS (for Dashboard)
// ==================================================================

// Additional metrics:
atrPct   = close != 0 ? (atr / close) * 100 : na               // ATR as percentage of Close
maGapPct = (slowMA != 0) ? (math.abs(fastMA - slowMA) / slowMA) * 100 : na  // % difference between MAs

// Open PnL Calculation
currentPnL = strategy.position_size != 0 ? (close - strategy.position_avg_price) * strategy.position_size : 0

// Persistent variable for highest equity (for drawdown calculation)
var float highestEquity = strategy.equity
highestEquity := math.max(highestEquity, strategy.equity)
totalDrawdown = strategy.equity - highestEquity

// Reset dashboard metrics if reset toggle is on.
if resetDashboard
    highestEquity := strategy.equity

// ==================================================================
// DASHBOARD: WATERMARK LOGO (Bottom-Right)
// ==================================================================
var table watermarkTable = table.new(position.bottom_right, 1, 1, bgcolor=color.rgb(0, 0, 0, 80), border_color=color.rgb(0, 50, 137), border_width=1)
if barstate.islast
    table.cell(watermarkTable, 0, 0, "⚡ Dskyz - DAFE Trading Systems", text_color=color.rgb(159, 127, 255, 80), text_size=size.large)

// ==================================================================
// DASHBOARD: METRICS TABLE (Bottom-Left)
// ==================================================================
var table dashboard = table.new(position.middle_right, 2, 12, bgcolor=color.new(#000000, 29), border_color=color.rgb(80, 80, 80), border_width=1)
if barstate.islast
    // Row 0 – Dashboard Title (duplicated in both columns to simulate spanning)
    table.cell(dashboard, 0, 0, "⚡(DAFE) Trading Systems", text_color=color.rgb(135, 135, 135), text_size=size.small)
    
    // Row 1 – Position
    table.cell(dashboard, 0, 1, "Position", text_color=color.gray)
    positionText = strategy.position_size > 0 ? "Long" : strategy.position_size < 0 ? "Short" : "Flat"
    table.cell(dashboard, 1, 1, positionText, text_color=strategy.position_size > 0 ? color.green : strategy.position_size < 0 ? color.red : color.blue)
    
    // Row 2 – Current PnL
    table.cell(dashboard, 0, 2, "Current P/L", text_color=color.gray)
    table.cell(dashboard, 1, 2, str.tostring(currentPnL, "#.##"), text_color=(currentPnL > 0 ? color.green : currentPnL < 0 ? color.red : color.gray))
    
    // Row 3 – Equity
    table.cell(dashboard, 0, 3, "Equity", text_color=color.gray)
    table.cell(dashboard, 1, 3, str.tostring(strategy.equity, "#.##"), text_color=color.white)

    // Row 4 – Closed Trades
    table.cell(dashboard, 0, 4, "Closed Trades", text_color=color.gray)
    table.cell(dashboard, 1, 4, str.tostring(strategy.closedtrades), text_color=color.white)

    // Row 5 – Title Step
    table.cell(dashboard, 0, 5, "Metrics", text_color=color.rgb(76, 122, 23))
   
    // Row 6 – Fast MA
    table.cell(dashboard, 0, 6, "Fast MA", text_color=color.gray)
    table.cell(dashboard, 1, 6, str.tostring(fastMA, "#.##"), text_color=color.white)
    
    // Row 7 – Slow MA
    table.cell(dashboard, 0, 7, "Slow MA", text_color=color.gray)
    table.cell(dashboard, 1, 7, str.tostring(slowMA, "#.##"), text_color=color.white)
    
    // Row 8 – ATR (Raw)
    table.cell(dashboard, 0, 8, "ATR", text_color=color.gray)
    table.cell(dashboard, 1, 8, str.tostring(atr, "#.##"), text_color=color.white)
    
    // Row 9 – ATR (%)
    table.cell(dashboard, 0, 9, "ATR (%)", text_color=color.gray)
    table.cell(dashboard, 1, 9, str.tostring(atrPct, "#.##") + "%", text_color=color.white)
    
    // Row 10 – MA Gap (%)
    table.cell(dashboard, 0, 10, "MA Gap (%)", text_color=color.gray)
    table.cell(dashboard, 1, 10, na(maGapPct) ? "N/A" : str.tostring(maGapPct, "#.##") + "%", text_color=color.white)
    
    // Row 11 – Volatility (%)
    table.cell(dashboard, 0, 11, "Volatility (%)", text_color=color.gray)
    table.cell(dashboard, 1, 11, str.tostring(volatility * 100, "#.##") + "%", text_color=color.white)