Chiến lược giao dịch định lượng theo dõi biến động giao cắt đường trung bình động thích ứng

MA交叉 ATR EMA SMA WMA HMA VWMA 趋势过滤 波动率过滤 跟踪止损 双重止盈
Ngày tạo: 2025-05-14 10:49:04 sửa đổi lần cuối: 2025-05-14 10:49:04
sao chép: 0 Số nhấp chuột: 317
2
tập trung vào
319
Người theo dõi

Chiến lược giao dịch định lượng theo dõi biến động giao cắt đường trung bình động thích ứng Chiến lược giao dịch định lượng theo dõi biến động giao cắt đường trung bình động thích ứng

Tổng quan về chiến lược

Chiến lược tự điều chỉnh tỷ lệ biến động theo dõi tỷ lệ biến động của đường trung bình là một chiến lược hệ thống được thiết kế đặc biệt cho giao dịch tần số cao và hoạt động đường ngắn. Cốt lõi của chiến lược sử dụng đường trung bình di chuyển nhanh (MA) và đường trung bình di chuyển chậm làm điểm kích hoạt tín hiệu chính, đồng thời kết hợp nhiều bộ lọc quan trọng và công cụ quản lý rủi ro chính xác để nắm bắt biến động giá nhỏ nhưng nhanh.

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

Lập luận cốt lõi của chiến lược này bao gồm các phần quan trọng sau:

  1. Kích hiệu vào cửa: chủ yếu thông qua đường trung bình nhanh và đường trung bình chậm giao / đi qua như là điều kiện kích hoạt nhập. Người dùng có thể linh hoạt cấu hình loại đường trung bình (EMA, SMA, WMA, HMA, VWMA) và độ dài chu kỳ để điều chỉnh độ nhạy của tín hiệu để phù hợp với các điều kiện thị trường khác nhau.

  2. Trình lọc xu hướngChiến lược: Lựa chọn sử dụng đường trung bình di chuyển dài hạn làm bộ lọc xu hướng lớn, đảm bảo giao dịch chỉ theo hướng xu hướng lớn và tránh giao dịch đường ngắn ngược trong thị trường hướng mạnh.

  3. Xác nhận bộ lọc

    • Bộ lọc tỷ lệ ATR: Được thiết kế để tạm dừng giao dịch trong các thị trường cực kỳ phẳng hoặc “ngày chết”, những thị trường có biến động thấp hơn ngưỡng động (dựa trên ATR trung bình), giúp ngăn chặn sự biến động trong điều kiện không có xu hướng, năng lượng thấp.
    • Bộ lọc lượng giao hàng: Bằng cách yêu cầu sự tham gia thị trường tối thiểu (số lượng giao dịch so với trung bình di chuyển của nó) để xác minh tín hiệu nhập cảnh, tránh nhập cảnh dựa trên hoạt động giá thấp hoặc giá không quan trọng.
  4. Bộ phận quản lý rủi ro

    • Lạm phát biến động ban đầuLệnh dừng ban đầu dựa trên ATR cung cấp điểm bắt đầu khách quan cho định nghĩa rủi ro cho mỗi giao dịch, phù hợp với biến động gần đây.
    • ATR theo dõi dừngĐiều quan trọng đối với thị trường năng động là theo dõi đường dừng sẽ điều chỉnh theo xu hướng giá thuận lợi, nhằm bảo vệ lợi nhuận của các giao dịch ngắn thành công, đồng thời giảm tổn thất tương đối nhanh chóng khi xu hướng đảo ngược.
    • Lợi nhuận cân bằng lỗ hổng (có thể lựa chọn): Khi đạt được TP1 hoặc giá di chuyển khoảng cách ATR nhất định, có thể tự động di chuyển dừng lỗ đến giá nhập ((thêm đệm)), được sử dụng cho rủi ro giao dịch trung bình và đã được chứng minh thành công ban đầu.
    • Mức độ lợi nhuận képCài đặt hai mục tiêu lợi nhuận TP1 và TP2, TP1 được thiết kế để kiếm được một phần lợi nhuận nhanh (ví dụ 50%), còn TP2 là để giành thêm không gian cho các vị trí còn lại.
  5. Quản lý vị trí: Sử dụng kích thước vị trí số lượng cố định để kiểm soát chính xác quy mô vị trí của mỗi giao dịch, rất quan trọng cho các ứng dụng rủi ro nhất quán và tạo lệnh API trong môi trường tần số cao.

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

Bằng cách phân tích mã sâu, chiến lược này có những lợi thế rõ ràng sau:

  1. Tính cấu hình cao: Người dùng có thể điều chỉnh các tham số khác nhau, bao gồm loại và chu kỳ đường trung bình, cài đặt bộ lọc và tham số quản lý rủi ro, để chiến lược có thể phù hợp với nhiều môi trường thị trường và phong cách giao dịch.

  2. Cơ chế lọc nhiều tầng: Kết hợp xu hướng, biến động và bộ lọc khối lượng giao dịch, giảm hiệu quả tín hiệu sai và tiếng ồn thị trường, nâng cao chất lượng giao dịch.

  3. Quản lý rủi ro tốtChiến lược này có nhiều cơ chế dừng lỗ (khởi đầu, theo dõi, cân bằng lỗ) và mục tiêu lợi nhuận kép, cho phép kiểm soát rủi ro và bảo vệ lợi nhuận.

  4. Thiết kế thân thiện với API: Logic nhập và thoát rõ ràng tạo ra tín hiệu không phân biệt, dễ dàng tích hợp với hệ thống giao dịch bên ngoài, thực hiện lệnh gần như ngay lập tức.

  5. Kiểm soát vị trí chính xácLưu trữ số lượng cố định giúp giảm tải trọng của các điểm cuối API và thực hiện tự động hóa một cách đáng tin cậy hơn.

  6. Khả năng thích nghi caoBằng cách điều chỉnh các tham số, chiến lược có thể chuyển đổi từ mô hình giao dịch ngắn tần số cao sang mô hình theo dõi xu hướng lâu hơn, thích ứng với các điều kiện thị trường khác nhau và sở thích giao dịch cá nhân.

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ó một số rủi ro và thách thức tiềm ẩn:

  1. Rủi ro tối ưu hóa tham sốVì chiến lược bao gồm nhiều tham số có thể cấu hình được, quá tối ưu có thể dẫn đến kết quả phản hồi tốt nhưng thực tế kém hiệu quả (cái quá phù hợp), nhà đầu tư nên xác minh trên dữ liệu ngoài mẫu hoặc tránh rủi ro này bằng cách thử nghiệm phía trước.

  2. Tác động chi phí giao dịch: Giao dịch tần số cao có nghĩa là có rất nhiều giao dịch, và các khoản hoa hồng và điểm trượt tích lũy có thể ảnh hưởng đáng kể đến khả năng lợi nhuận ròng, và các chi phí này phải được tính toán chính xác trong thiết lập và phản hồi trước khi sử dụng.

  3. Sự biến động của tín hiệuTrong các điều kiện thị trường khác nhau, độ tin cậy của tín hiệu giao tuyến có thể thay đổi, đặc biệt là trong các thị trường bị dao động ngang hoặc biến động cao.

  4. Sự phụ thuộc vào công nghệLà một chiến lược sẵn sàng API, hiệu quả của nó phụ thuộc một phần vào tốc độ thực hiện và sự ổn định kỹ thuật, sự chậm trễ hoặc trục trặc của hệ thống có thể dẫn đến cơ hội bị mất hoặc sai lệch thực hiện.

  5. Giới hạn về quy môMột số lượng cố định vị trí có thể không phù hợp với tất cả các tài khoản, một số tài khoản nhỏ có thể có rủi ro quá mức, và một số tài khoản lớn có thể không sử dụng đầy đủ số tiền.

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

Dựa trên thiết kế chiến lược và rủi ro tiềm ẩn, đây là một số hướng tối ưu hóa có thể:

  1. Các tham số thích ứngThiết kế các tham số quan trọng (như ATR và chu kỳ đường trung bình) để điều chỉnh tự động dựa trên điều kiện thị trường, tăng khả năng thích ứng của chiến lược trong các giai đoạn thị trường khác nhau.

  2. Bộ lọc thông minh được tăng cường: tích hợp các chỉ số trạng thái thị trường bổ sung (như cấu trúc thị trường, nhận diện mô hình biến động hoặc sự liên quan của các tài sản liên quan) để nâng cao thêm độ chính xác của bộ lọc.

  3. Quản lý vị trí động: Sử dụng vị trí động dựa trên quy mô tài khoản, biến động hiện tại và hiệu suất chiến lược gần đây để tính toán vị trí thay vì số lượng cố định, để quản lý tiền thông minh hơn.

  4. Xác nhận khung thời gian đa dạng: Xác nhận tín hiệu trên các khung thời gian khác nhau, đảm bảo hướng giao dịch phù hợp với cấu trúc thị trường lớn hơn, giảm giao dịch không cần thiết.

  5. Tích hợp học máy: Sử dụng thuật toán học máy để phân tích hiệu suất tín hiệu lịch sử, dự đoán xác suất thành công của tín hiệu trong tương lai, ưu tiên thực hiện giao dịch có tỷ lệ thành công cao

  6. Quản lý phiên giao dịchThêm bộ lọc thời gian giao dịch, tránh thời gian có tính thanh khoản thấp hoặc biến động cao, tập trung vào cửa sổ giao dịch hiệu quả nhất trên thị trường.

  7. Bộ lọc liên quan: Đối với giao dịch đa tài sản, thêm phân tích liên quan đến thị trường liên quan, tránh tiếp xúc quá mức với các yếu tố rủi ro cụ thể.

Tóm tắt

Chiến lược giao dịch định lượng theo dõi tỷ lệ biến động chéo chéo là một hệ thống giao dịch tần số cao đầy đủ tính năng, kích hoạt tín hiệu qua chéo chéo, kết hợp với nhiều bộ lọc quan trọng và công cụ quản lý rủi ro chính xác, được thiết kế đặc biệt để nắm bắt biến động giá nhỏ nhưng nhanh. Sức mạnh của chiến lược nằm trong khung quản lý rủi ro có khả năng cấu hình cao và hoàn thiện, cho phép các nhà giao dịch điều chỉnh các tham số giao dịch theo khả năng chịu rủi ro cá nhân và điều kiện thị trường.

Đối với các nhà giao dịch tần số cao, chiến lược này cung cấp logic nhập và thoát rõ ràng và khả năng tích hợp liền mạch với các nền tảng thực hiện bên ngoài, điều này rất quan trọng để thực hiện quyết định nhanh chóng trong thị trường biến động nhanh chóng. Tuy nhiên, khi sử dụng chiến lược này, cần chú ý đặc biệt đến rủi ro tích lũy chi phí giao dịch và tối ưu hóa quá mức, đảm bảo duy trì sức khỏe và lợi nhuận của chiến lược trong giao dịch thực tế.

Cuối cùng, chiến lược này đại diện cho một cách cân bằng để tận dụng sức mạnh của các chỉ số kỹ thuật và các công cụ quản lý rủi ro, trong khi vẫn đủ linh hoạt để thích ứng với các điều kiện thị trường thay đổi. Với sự điều chỉnh tham số cẩn thận và cải tiến giám sát liên tục, chiến lược này có thể trở thành một thành phần có giá trị trong danh mục giao dịch định lượng.

Mã nguồn chiến lược
/*backtest
start: 2024-05-14 00:00:00
end: 2025-05-12 08:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"DOGE_USDT"}]
*/

//@version=5
// © ArrowTrade x:ArrowTrade

// --- STRATEGY DEFINITION ---
strategy(
     title="Arrow's Flexible MA Cross Strategy [API Ready]", // Added branding
     shorttitle="ArrowFlex",                  // Added branding
     overlay=true,
     initial_capital=1000, // Example capital, user should adjust
     commission_type=strategy.commission.percent,
     commission_value=0.036, // Example commission, user MUST adjust to their broker/exchange
     slippage=2,             // Example slippage (in ticks), user should adjust based on asset/broker
     process_orders_on_close=true, // Calculates/executes on bar close. Set to false for intrabar (use with caution & specific logic)
     pyramiding=0,           // No pyramiding allowed (one entry per direction)
     default_qty_type=strategy.fixed // Defaulting to fixed quantity
     // Removed default_qty_value from here
     )

// ================================================================================
//  Strategy Description (for TradingView Public Library & Users)
// ================================================================================
// © ArrowTrade
//
// A configurable Moving Average Crossover strategy designed for flexibility and
// API integration.
//
// Features:
// - MA Crossover Entries: Uses configurable Fast/Slow MA crossovers for signals.
// - Trend Filter: Optional longer-term MA filter to trade only with the trend.
// - Volatility Filter: Optional ATR filter to avoid low-volatility periods.
// - Volume Filter: Optional Volume filter to confirm entries with sufficient volume.
// - Stop Loss Options:
//     - Initial Volatility Stop (ATR-based)
//     - ATR Trailing Stop
//     - Break-Even Stop (activated by TP1 hit or ATR distance)
// - Take Profit Options:
//     - Two independent TP levels (percentage-based).
//     - Configurable partial close percentage at TP1.
// - Position Sizing: Fixed quantity per trade (adjustable).
//
// Intended Use:
// While configurable for various styles (scalping to trend-following by adjusting
// parameters), this strategy is built with API automation in mind. The clear
// entry and exit logic facilitates integration with external execution platforms
// via webhooks or other methods. Parameters can be tightened (shorter MAs,
// tighter stops/TPs, specific filters) for higher-frequency signals suitable
// for scalping.
//
// Disclaimer:
// Backtesting results are hypothetical and do not guarantee future performance.
// Market conditions change constantly. Always perform your own due diligence,
// forward testing, and rigorous risk management before trading live with any
// strategy. Ensure you adjust inputs like commission, slippage, and position
// size to accurately reflect your specific broker/exchange and risk profile.
// ================================================================================


// === INPUTS (Grouped and Ordered by Importance/Function) ===

// --- 1. Core Signal & Trend Filter ---
grp_signal = "1. Core Signal & Trend Filter"
signalSource   = input.source(high, title="Signal Source", group=grp_signal, tooltip="Price source for calculating the signal MAs (e.g., close, hl2, ohlc4). 'hlc3' or 'ohlc4' can provide smoother signals.")
signalMaType   = input.string("EMA", title="Signal MA Type", options=["EMA", "SMA", "WMA", "HMA", "VWMA"], group=grp_signal, tooltip="Type of Moving Average used for the fast/slow signal lines (EMA reacts faster, SMA smoother, HMA reduces lag).")
signalFastLen  = input.int(12, title="Fast MA Period", minval=2, maxval=100, step=1, group=grp_signal, tooltip="Period for the shorter-term signal MA. Shorter periods lead to more frequent signals (potentially more noise/scalping).")
signalSlowLen  = input.int(25, title="Slow MA Period", minval=3, maxval=200, step=1, group=grp_signal, tooltip="Period for the longer-term signal MA. Must be greater than Fast MA Period. Defines the crossover signal.")
useTrendFilter = input.bool(true, title="Enable Trend Filter", group=grp_signal, tooltip="If enabled, entry signals are only taken in the direction of the longer-term trend defined by the Trend MA.")
trendMaType    = input.string("EMA", title="Trend MA Type", options=["EMA", "SMA", "WMA", "HMA", "VWMA"], group=grp_signal, tooltip="Type of Moving Average used for the trend filter.")
trendMaLen     = input.int(100, title="Trend MA Period", minval=50, maxval=500, step=10, group=grp_signal, tooltip="Period for the Trend MA. Significantly longer than signal MAs typically. Higher values filter more aggressively.")
trendMaSource  = input.source(hl2, title="Trend MA Source", group=grp_signal, tooltip="Price source for the Trend MA calculation.")

// --- 2. Risk Management: Stop Loss ---
grp_stop = "2. Risk Management: Stop Loss"
useVolatilityStop    = input.bool(true, title="Enable Initial Volatility Stop", group=grp_stop, tooltip="Sets the initial stop loss based on Average True Range (ATR) at the time of entry.")
volStopAtrPeriod     = input.int(7, title="   Initial Stop ATR Period", minval=1, maxval=50, step=1, group=grp_stop, tooltip="ATR lookback period for calculating the initial stop distance.")
volStopAtrMultiplier = input.float(5, title="   Initial Stop ATR Multiplier", minval=0.5, maxval=10, step=0.1, group=grp_stop, tooltip="Multiplier for the ATR value to determine stop distance (Stop = Entry +/- ATR * Multiplier). Lower values = tighter initial stop.")
useTrailingStop      = input.bool(true, title="Enable ATR Trailing Stop", group=grp_stop, tooltip="If enabled, the stop loss will trail behind price based on current ATR, potentially locking in profits. Can override the initial/BE stop if it moves favorably.")
trailAtrPeriod       = input.int(15, title="   Trailing ATR Period", minval=1, maxval=50, step=1, group=grp_stop, tooltip="ATR lookback period for calculating the trailing distance.")
trailAtrMultiplier   = input.float(4.0, title="   Trailing ATR Multiplier", minval=0.5, maxval=10, step=0.1, group=grp_stop, tooltip="Multiplier for the current ATR to determine trailing distance. Lower values trail tighter.")
useBreakEvenStop     = input.bool(false, title="Enable Break-Even Stop", group=grp_stop, tooltip="If enabled, moves the stop loss to entry price (plus a small profit buffer) once a certain condition is met.")
beActivationChoice   = input.string("TP1 Reached", title="   BE Activation Condition", options=["TP1 Reached", "ATR Distance Moved"], group=grp_stop, tooltip="When should the Break-Even Stop activate? When TP1 is hit, or when price moves a certain ATR distance from entry?")
beActivationAtrMult  = input.float(1.5, title="   BE Activation ATR Multiplier", minval=0.1, maxval=5, step=0.1, group=grp_stop, tooltip="Used only if 'ATR Distance Moved' is selected. BE activates if price moves (Entry +/- ATR * Multiplier). Uses 'Initial Stop ATR Period'.")
beProfitTicks        = input.int(2, title="   BE Profit Buffer (Ticks)", minval=0, maxval=50, step=1, group=grp_stop, tooltip="Moves the stop to Entry Price +/- this many ticks (e.g., to cover commissions). Set to 0 for exact entry price.")

// --- 3. Risk Management: Take Profit ---
grp_tp = "3. Risk Management: Take Profit (TP)"
useTp1        = input.bool(true, title="Enable TP1", group=grp_tp, tooltip="Enable the first Take Profit level.")
tp1Pct        = input.float(1.5, title="   TP1 Target (%)", minval=0.1, maxval=20, step=0.1, group=grp_tp, tooltip="First TP target as a percentage distance from the entry price. Should be less than TP2 %.")
tp1QtyPercent = input.int(50, title="   TP1 Close Quantity (%)", minval=1, maxval=100, step=5, group=grp_tp, tooltip="Percentage of the original position size to close when TP1 is hit.")
useTp2        = input.bool(true, title="Enable TP2", group=grp_tp, tooltip="Enable the second (final) Take Profit level.")
tp2Pct        = input.float(3.0, title="   TP2 Target (%)", minval=0.2, maxval=30, step=0.1, group=grp_tp, tooltip="Second TP target as a percentage distance from the entry price. Closes the remaining position.")

// --- 4. Additional Filters ---
grp_filters = "4. Additional Filters"
useAtrFilter        = input.bool(true, title="Enable ATR Volatility Filter", group=grp_filters, tooltip="If enabled, avoids entries during periods of very low volatility (ATR below a moving average of ATR). Helps filter choppy/sideways markets.")
atrFilterPeriod     = input.int(14, title="   ATR Filter Period", minval=1, maxval=50, step=1, group=grp_filters, tooltip="Lookback period for calculating the current ATR and its average for the filter.")
atrFilterMultiplier = input.float(0.5, title="   ATR Filter Threshold Multiplier", minval=0.1, maxval=5, step=0.1, group=grp_filters, tooltip="Entry requires current ATR to be >= (Average ATR * Multiplier). Lower values filter more aggressively.")
useVolumeFilter     = input.bool(true, title="Enable Volume Filter", group=grp_filters, tooltip="If enabled, requires the volume of the entry bar to be above a moving average of volume. Acts as confirmation.")
volumeLookback      = input.int(30, title="   Volume MA Period", minval=2, maxval=100, step=1, group=grp_filters, tooltip="Lookback period for calculating the average volume.")
volumeMultiplier    = input.float(1.0, title="   Min Volume Ratio (vs Avg)", minval=0.1, maxval=5, step=0.1, group=grp_filters, tooltip="Entry requires current volume to be >= (Average Volume * Multiplier). Values >= 1 require above-average volume.")

// --- 5. Position Sizing ---
grp_size = "5. Position Sizing"
// Define the quantity input with its own default value
qtyValue = input.float(0.01, title="Position Size (Fixed Qty)", minval=0.0001, step=0.0001, group=grp_size, tooltip="Fixed quantity (contracts/shares/lots) per trade. Adjust based on your account size, risk tolerance, and the asset being traded. Can be overridden by API.")


// === FUNCTIONS ===
f_ma(maType, src, len) =>
    float result = na
    if maType == "SMA"
        result := ta.sma(src, len)
    else if maType == "EMA"
        result := ta.ema(src, len)
    else if maType == "WMA"
        result := ta.wma(src, len)
    else if maType == "HMA"
        result := ta.hma(src, len)
    else if maType == "VWMA"
        result := ta.vwma(src, len)
    result

// === CORE CALCULATIONS ===

// Parameter Sanity Check
if signalSlowLen <= signalFastLen and barstate.islast
    runtime.error("Signal Slow MA Period must be greater than Fast MA Period!")

// 1. Moving Averages
float fastMA = f_ma(signalMaType, signalSource, signalFastLen)
float slowMA = f_ma(signalMaType, signalSource, signalSlowLen)
float trendMA = useTrendFilter ? f_ma(trendMaType, trendMaSource, trendMaLen) : na

// 2. ATR Values
float atrValueStop = ta.atr(volStopAtrPeriod)
float atrValueTrail = ta.atr(trailAtrPeriod)
float atrValueFilter = ta.atr(atrFilterPeriod)
float atrValueBE = ta.atr(volStopAtrPeriod)

// 3. Filter Conditions
bool trendFilterOK_L = not useTrendFilter or (not na(trendMA) and signalSource > trendMA)
bool trendFilterOK_S = not useTrendFilter or (not na(trendMA) and signalSource < trendMA)
float avgAtrFilter = ta.sma(atrValueFilter, atrFilterPeriod)
bool volatilityFilterOK = not useAtrFilter or (not na(atrValueFilter) and not na(avgAtrFilter) and atrValueFilter >= avgAtrFilter * atrFilterMultiplier)
float avgVolume = ta.sma(volume, volumeLookback)
bool volumeFilterOK = not useVolumeFilter or (not na(volume) and not na(avgVolume) and volume >= avgVolume * volumeMultiplier)
bool finalFilterOK_L = trendFilterOK_L and volatilityFilterOK and volumeFilterOK
bool finalFilterOK_S = trendFilterOK_S and volatilityFilterOK and volumeFilterOK

// 4. Entry Signals
bool longCross = not na(fastMA) and not na(slowMA) and ta.crossover(fastMA, slowMA)
bool shortCross = not na(fastMA) and not na(slowMA) and ta.crossunder(fastMA, slowMA)
bool longEntrySignal = longCross and finalFilterOK_L
bool shortEntrySignal = shortCross and finalFilterOK_S

// === STRATEGY EXECUTION LOGIC ===

// --- State Variables (persisted between bars) ---
var float entryPriceVar = na
var float initialStopPrice = na
var float currentStopPrice = na
var float trailStopLevel = na
var bool isBEActive = false
var bool tp1Reached = false
var float qtyToCloseTp1_Var = na

// --- Position Status ---
bool inLong = strategy.position_size > 0
bool inShort = strategy.position_size < 0
bool inTrade = strategy.position_size != 0

// --- Reset State Variables on Trade Exit ---
if not inTrade and inTrade[1]
    entryPriceVar := na
    initialStopPrice := na
    currentStopPrice := na
    trailStopLevel := na
    isBEActive := false
    tp1Reached := false
    qtyToCloseTp1_Var := na

// --- Handle New Entries ---
if longEntrySignal and not inTrade
    strategy.entry("Long Entry", strategy.long, qty=qtyValue) // Use qtyValue from input

if shortEntrySignal and not inTrade
    strategy.entry("Short Entry", strategy.short, qty=qtyValue) // Use qtyValue from input


// --- Manage Stops and Take Profits for Open Positions ---
if inTrade
    // Initialize state on the bar immediately AFTER entry
    if na(entryPriceVar)
        entryPriceVar := strategy.position_avg_price
        float positionQty = strategy.position_size

        if not na(positionQty) and tp1QtyPercent > 0 and useTp1
            qtyToCloseTp1_Var := math.abs(positionQty * tp1QtyPercent / 100)
        else
            qtyToCloseTp1_Var := 0.0

        if useVolatilityStop and not na(atrValueStop)
            initialStopPrice := entryPriceVar + (inLong ? -1 : 1) * atrValueStop * volStopAtrMultiplier
            currentStopPrice := initialStopPrice
        else
            initialStopPrice := na
            currentStopPrice := na

        if useTrailingStop and not na(atrValueTrail)
            trailStopLevel := entryPriceVar + (inLong ? -1 : 1) * atrValueTrail * trailAtrMultiplier
        else
            trailStopLevel := na

        isBEActive := false
        tp1Reached := false

    // --- Calculations within the trade (if entry price is set) ---
    if not na(entryPriceVar)

        // 1. Calculate TP Levels for the current bar
        float tp1LevelL = na, float tp2LevelL = na, float tp1LevelS = na, float tp2LevelS = na
        if useTp1
            tp1LevelL := entryPriceVar * (1 + tp1Pct / 100)
            tp1LevelS := entryPriceVar * (1 - tp1Pct / 100)
        if useTp2
            tp2LevelL := entryPriceVar * (1 + tp2Pct / 100)
            tp2LevelS := entryPriceVar * (1 - tp2Pct / 100)

        // 2. Check and Activate Break-Even Stop
        if useBreakEvenStop and not isBEActive and not na(currentStopPrice)
            float beTriggerL = na, float beTriggerS = na
            if beActivationChoice == "TP1 Reached" and useTp1
                if not na(tp1LevelL)
                    beTriggerL := tp1LevelL
                if not na(tp1LevelS)
                    beTriggerS := tp1LevelS
            else if beActivationChoice == "ATR Distance Moved" and not na(atrValueBE)
                beTriggerL := entryPriceVar + atrValueBE * beActivationAtrMult
                beTriggerS := entryPriceVar - atrValueBE * beActivationAtrMult

            float beTargetLevel = entryPriceVar + (inLong ? 1 : -1) * beProfitTicks * syminfo.mintick

            if not na(beTriggerL) and not na(beTargetLevel) and inLong and high >= beTriggerL and beTargetLevel > currentStopPrice
                currentStopPrice := beTargetLevel
                isBEActive := true
            if not na(beTriggerS) and not na(beTargetLevel) and inShort and low <= beTriggerS and beTargetLevel < currentStopPrice
                currentStopPrice := beTargetLevel
                isBEActive := true

        // 3. Update Trailing Stop
        if useTrailingStop and not na(currentStopPrice) and not na(atrValueTrail)
            float newTrailStopL = low - atrValueTrail * trailAtrMultiplier
            float newTrailStopS = high + atrValueTrail * trailAtrMultiplier
            float prevTrail = trailStopLevel[1]
            float calculatedNewTrail = na

            if inLong
                calculatedNewTrail := na(prevTrail) ? newTrailStopL : math.max(prevTrail, newTrailStopL)
                if not na(calculatedNewTrail)
                    trailStopLevel := calculatedNewTrail
                if not na(trailStopLevel) and trailStopLevel > currentStopPrice
                    currentStopPrice := trailStopLevel
            if inShort
                calculatedNewTrail := na(prevTrail) ? newTrailStopS : math.min(prevTrail, newTrailStopS)
                if not na(calculatedNewTrail)
                    trailStopLevel := calculatedNewTrail
                if not na(trailStopLevel) and trailStopLevel < currentStopPrice
                    currentStopPrice := trailStopLevel

        // --- Execute Exits ---

        // 4. Apply Stop Loss Exit
        if not na(currentStopPrice)
            bool isTrailingActiveNow = useTrailingStop and not na(trailStopLevel) and currentStopPrice == trailStopLevel
            string stop_comment = isBEActive ? "BE Stop" : (isTrailingActiveNow ? "Trail Stop" : "Vol Stop")
            if inLong
                strategy.exit("SL Exit L", from_entry="Long Entry", stop=currentStopPrice, comment=stop_comment + " L")
            if inShort
                strategy.exit("SL Exit S", from_entry="Short Entry", stop=currentStopPrice, comment=stop_comment + " S")

        // 5. Apply Take Profit Exits
        // TP1 Exit (Partial Quantity)
        if useTp1 and not tp1Reached and not na(qtyToCloseTp1_Var) and qtyToCloseTp1_Var > 0
            if inLong and not na(tp1LevelL)
                strategy.exit("TP1 Exit L", from_entry="Long Entry", qty=qtyToCloseTp1_Var, limit=tp1LevelL, comment="TP1 Hit L")
                if high >= tp1LevelL
                    tp1Reached := true
            if inShort and not na(tp1LevelS)
                strategy.exit("TP1 Exit S", from_entry="Short Entry", qty=qtyToCloseTp1_Var, limit=tp1LevelS, comment="TP1 Hit S")
                if low <= tp1LevelS
                    tp1Reached := true

        // TP2 Exit (Remaining Quantity)
        if useTp2
            if inLong and not na(tp2LevelL)
                strategy.exit("TP2 Exit L", from_entry="Long Entry", limit=tp2LevelL, comment="TP2 Hit L")
            if inShort and not na(tp2LevelS)
                strategy.exit("TP2 Exit S", from_entry="Short Entry", limit=tp2LevelS, comment="TP2 Hit S")


// === PLOTTING ===

// 1. Moving Averages
plot(fastMA, "Fast MA", color=color.new(color.aqua, 0), linewidth=1)
plot(slowMA, "Slow MA", color=color.new(color.fuchsia, 0), linewidth=1)
plot(useTrendFilter and not na(trendMA) ? trendMA : na, "Trend MA", color=color.new(color.gray, 0), linewidth=2, style=plot.style_cross)

// 2. Active Stop Loss Level
color stopColor = color.new(color.red, 0)
bool isTrailingActivePlot = useTrailingStop and not na(trailStopLevel) and not na(currentStopPrice) and currentStopPrice == trailStopLevel
if isBEActive
    stopColor := color.new(color.orange, 0)
else if isTrailingActivePlot
    stopColor := color.new(color.blue, 0)
plot(inTrade and not na(currentStopPrice) ? currentStopPrice : na, "Active Stop Loss", stopColor, style=plot.style_linebr, linewidth=2)

// 3. Take Profit Levels
float plot_tp1LevelL = na, float plot_tp1LevelS = na, float plot_tp2LevelL = na, float plot_tp2LevelS = na
if not na(entryPriceVar)
    if useTp1
        plot_tp1LevelL := entryPriceVar * (1 + tp1Pct / 100)
        plot_tp1LevelS := entryPriceVar * (1 - tp1Pct / 100)
    if useTp2
        plot_tp2LevelL := entryPriceVar * (1 + tp2Pct / 100)
        plot_tp2LevelS := entryPriceVar * (1 - tp2Pct / 100)
plot(inTrade and useTp1 and not na(inLong ? plot_tp1LevelL : plot_tp1LevelS) ? (inLong ? plot_tp1LevelL : plot_tp1LevelS) : na, "TP1 Level", color=color.new(color.green, 30), style=plot.style_linebr, linewidth=1)
plot(inTrade and useTp2 and not na(inLong ? plot_tp2LevelL : plot_tp2LevelS) ? (inLong ? plot_tp2LevelL : plot_tp2LevelS) : na, "TP2 Level", color=color.new(color.green, 0), style=plot.style_linebr, linewidth=1)

// 4. Entry Signal Markers
plotshape(longEntrySignal, title="Long Entry Signal", location=location.belowbar, color=color.new(color.green, 0), style=shape.triangleup, size=size.small)
plotshape(shortEntrySignal, title="Short Entry Signal", location=location.abovebar, color=color.new(color.red, 0), style=shape.triangledown, size=size.small)

// 5. Background Color Filters
bgcolor(useTrendFilter and not na(trendMA) and inTrade ? (inLong ? color.new(color.blue, 90) : color.new(color.red, 90)) : na, title="Trend Filter Active")
bgcolor(useAtrFilter and not volatilityFilterOK ? color.new(color.gray, 85) : na, title="Low Volatility Filter Active")
bgcolor(useVolumeFilter and not volumeFilterOK ? color.new(color.yellow, 90) : na, title="Low Volume Filter Active")