Chiến lược theo dõi xu hướng Breakout Moving Average

Tác giả:ChaoZhang, Ngày: 2023-11-03 15:57:11
Tags:

img

Tổng quan

Chiến lược này xác định hướng xu hướng bằng đường chéo vàng và đường chéo chết của các đường trung bình di chuyển đơn giản, đi dài hoặc ngắn với kích thước vị trí đầy đủ vào đầu xu hướng, và thiết lập lệnh dừng lỗ và lấy lợi nhuận để kiểm soát rủi ro. Sau khi nhập vào vị trí, nó tiếp tục theo dõi xu hướng bằng cách sử dụng đường trung bình di chuyển và cắt lỗ trong thời gian khi có sự đảo ngược xu hướng. Chiến lược này cũng có các mô-đun có thể cấu hình để dừng lỗ, lấy lợi nhuận và kích thước vị trí, cho phép điều chỉnh linh hoạt các thông số cho các sản phẩm khác nhau.

Chiến lược logic

Cốt lõi của chiến lược này là xác định xu hướng bắt đầu và kết thúc bằng cách sử dụng đường chéo vàng và đường chéo chết của các đường trung bình di chuyển đơn giản. Đầu tiên nó xác định hướng xu hướng dựa trên mối quan hệ giữa SMA nhanh (ví dụ 21 giai đoạn) và SMA chậm (ví dụ 49 giai đoạn). Khi SMA nhanh vượt qua SMA chậm, nó báo hiệu xu hướng tăng, và chiến lược sẽ đi dài. Khi SMA nhanh vượt qua dưới SMA chậm, nó báo hiệu xu hướng giảm, và chiến lược sẽ đi ngắn.

Sau khi nhập vào vị trí, chiến lược tiếp tục theo dõi giá tương đối với SMA trong thời gian thực. Nó sẽ đóng vị trí dài khi giá phá vỡ SMA từ trên, và đóng vị trí ngắn khi giá phá vỡ SMA từ dưới, như tín hiệu đảo ngược xu hướng.

Để kiểm soát rủi ro, chiến lược thiết lập lệnh dừng lỗ và lấy lợi nhuận đồng thời khi mở vị trí. Khoảng cách dừng lỗ dựa trên ATR, trong khi khoảng cách lấy lợi nhuận có thể được cấu hình bằng tỷ lệ phần trăm hoặc số lần ATR. Sau khi mở vị trí, lệnh dừng lỗ tiếp tục theo dõi giá để nhận ra xu hướng. Khi lấy lợi nhuận được chạm vào, nó đóng một phần vị trí đầu tiên trong khi giữ phần còn lại để tiếp tục theo dõi cho đến khi hoàn toàn đóng.

Chiến lược cũng có mô-đun định kích thước vị trí để giới hạn các quỹ được sử dụng cho mỗi giao dịch và kiểm soát rủi ro rủi ro cho mỗi giao dịch.

Ưu điểm

  • Dễ hiểu, sử dụng đường chéo SMA để xác định hướng xu hướng
  • Theo dõi thời gian thực của dừng lỗ sau khi nhập có thể khóa trong hầu hết lợi nhuận
  • Các sản phẩm khác nhau có thể tùy chỉnh stop loss và take profit
  • Chỉ có một giao dịch có thể kiểm soát rủi ro, không giao dịch toàn vị trí
  • Giới hạn rút vốn tối đa để hạn chế tổng lỗ

Rủi ro và giải pháp

  • Đường chéo SMA có một số trễ, có thể bỏ lỡ bước vào tốt nhất tại thời điểm bắt đầu xu hướng
  • Cần điều chỉnh nhiều lần các thông số và thử nghiệm các khoảng thời gian SMA khác nhau
  • SMA chéo có một số whipsaws, chính xác nhập không thể là 100%
  • Chế độ dừng lỗ sau có thể dễ dàng đạt được, không thể khóa toàn bộ lợi nhuận
  • Cần khoảng cách dừng lỗ hợp lý cho việc khôi phục giá
  • Giới hạn rút tiền tối đa có thể quá thận trọng, thiếu tiềm năng tăng
  • Có thể nới lỏng khoản bồi thường rút tiền tối đa để dung nạp chiến lược nhiều hơn

Cơ hội gia tăng

  • Kiểm tra các kết hợp tham số khác nhau để tìm ra thời gian SMA tối ưu
  • Thêm chỉ số sức mạnh xu hướng để cải thiện độ chính xác nhập cảnh
  • Tối ưu hóa chiến lược dừng lỗ để theo đuổi xu hướng tăng và giảm càng nhiều càng tốt
  • Kiểm tra các chiến lược lợi nhuận khác nhau để tìm điểm thoát tối ưu
  • Cải thiện kế hoạch kích thước vị trí để cải thiện việc sử dụng vốn
  • Điều chỉnh thiết lập rút vốn tối đa để cân bằng lợi nhuận so với rủi ro

Kết luận

Tóm lại, đây là một chiến lược khởi động rất phù hợp cho người mới bắt đầu, với logic đơn giản và dễ hiểu. Nó cũng có khả năng kiểm soát rủi ro thích hợp để giảm lỗ lớn. Kết quả tốt có thể đạt được thông qua điều chỉnh tham số. Nhưng điểm yếu nội tại của nó cũng quyết định rằng nó không thể hoạt động với độ chính xác cao. Nó được khuyến cáo cho người mới bắt đầu thực hành, nhưng có thể không phù hợp với các nhà giao dịch tiên tiến theo đuổi hiệu quả cao và tỷ lệ thắng. Để có được hiệu suất giao dịch tốt hơn, nên tìm kiếm các chiến lược có sức dự đoán mạnh hơn.


/*backtest
start: 2023-01-01 00:00:00
end: 2023-11-02 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 
//  -----------------------------------------------------------------------------
//  Copyright 2022 Iason Nikolas | jason5480
//  Template Strategy script may be freely distributed under the MIT license.
//
//  Permission is hereby granted, free of charge, 
//  to any person obtaining a copy of this software and associated documentation files (the "Software"), 
//  to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 
//  publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
//  subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
//  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//  -----------------------------------------------------------------------------
//
//  Authors:  @jason5480
//  Revision: v0.0.1
//  Date:     26-Feb-2022
//
//  Description
//  =============================================================================
//  This script is designed to be used as a template for building new strategies.
//  The framework provide you with a configurable implementation of the entry, exit,
//  stop loss and take profit trailing logic. The user of this script has to copy
//  it and replace the openLongPosition, openShortPosition, closeLongPosition and
//  closeShortPosition variables in the STRATEGY module according to his needs! 
//  
//  -----------------------------------------------------------------------------
//  Disclaimer:
//    1. I am not licensed financial advisors or broker dealer. I do not tell you 
//       when or what to buy or sell. I developed this software which enables you 
//       execute manual or automated trades using TradingView. The 
//       software allows you to set the criteria you want for entering and exiting 
//       trades.
//    2. Do not trade with money you cannot afford to lose.
//    3. I do not guarantee consistent profits or that anyone can make money with no 
//       effort. And I am not selling the holy grail.
//    4. Every system can have winning and losing streaks.
//    5. Money management plays a large role in the results of your trading. For 
//       example: lot size, account size, broker leverage, and broker margin call 
//       rules all have an effect on results. Also, your Take Profit and Stop Loss 
//       settings for individual pair trades and for overall account equity have a 
//       major impact on results. If you are new to trading and do not understand 
//       these items, then I recommend you seek education materials to further your
//       knowledge.
//
//    YOU NEED TO FIND AND USE THE TRADING SYSTEM THAT WORKS BEST FOR YOU AND YOUR 
//    TRADING TOLERANCE.
//
//    I HAVE PROVIDED NOTHING MORE THAN A TOOL WITH OPTIONS FOR YOU TO TRADE WITH THIS PROGRAM ON TRADINGVIEW.
//    
//    I accept suggestions to improve the script.
//    If you encounter any problems I will be happy to share with me.
//  -----------------------------------------------------------------------------
//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// SETUP ============================================================================================================
strategy(title = 'Template Trailing Strategy',
         shorttitle = 'TTS',
         overlay = true,
         pyramiding = 0,
         default_qty_type = strategy.percent_of_equity,
         default_qty_value = 100,
         initial_capital = 100000)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// FILTERS ==========================================================================================================

// INPUT ============================================================================================================
usefromDate = input.bool(defval = true, title = 'From', inline = "From Date", group = "Filters")
fromDate = input(defval = timestamp('01 Jan 2021 00:00 UTC'), title = '', inline = "From Date", group = 'Filters')
usetoDate = input.bool(defval = false, title = 'To ', inline = "To Date", group = "Filters")
toDate = input(defval = timestamp('31 Dec 2121 23:59 UTC'), title = '', inline = "To Date", group = 'Filters')

longTradesEnabled = input.bool(defval = true, title = 'Long Trades', inline = 'Trades', group = 'Filters')
shortTradesEnabled = input.bool(defval = true, title = 'Short Trades', tooltip = 'Enable long/short trades.', inline = 'Trades', group = 'Filters')

emaFilterEnabled = input.bool(defval = true, title = 'EMA Filter', tooltip = 'Enable long/short trades based on EMA.', group = 'Filters')
emaResolution = input.timeframe(defval = 'D', title = 'EMA Res/Len/Src', inline = 'EMA Filter', group = 'Filters')
emaLength = input.int(defval = 200, title = '', inline = 'EMA Filter', group = 'Filters')
emaSrc = input.source(defval = close, title = '', tooltip = 'The timeframe, period and source for the EMA calculation.', inline = 'EMA Filter', group = 'Filters')
emaAtrBandEnabled = input.bool(defval = true, title = 'EMA ATR Band', tooltip = 'Enable ATR band for EMA filter.', group = 'Filters')
filterAtrLength = input.int(defval = 5, title = 'EMA ATR Len/Mul', minval = 1, inline = 'EMA ATR', group = 'Filters')
filterAtrMul = input.float(defval = 1.0, title = '', tooltip = 'ATR length and multiplier to be used for the ATR calculation that will be added on top of the EMA filter.', minval = 0.1, step = 0.1, inline = 'EMA ATR', group = 'Filters')

// LOGIC ============================================================================================================
isWithinPeriod() => true

emaLine = request.security(syminfo.tickerid, emaResolution, ta.ema(emaSrc, emaLength))
emaAtr = ta.atr(filterAtrLength)
emaUpperBand = emaLine + filterAtrMul * emaAtr
emaLowerBand = emaLine - filterAtrMul * emaAtr
bool emaLongApproval = emaFilterEnabled ? close > (emaAtrBandEnabled ? emaUpperBand : emaLine) and open > (emaAtrBandEnabled ? emaUpperBand : emaLine) : true
bool emaShortApproval = emaFilterEnabled ? close < (emaAtrBandEnabled ? emaLowerBand : emaLine) and open < (emaAtrBandEnabled ? emaLowerBand : emaLine) : true

bool longFiltersApproval = longTradesEnabled and emaLongApproval and isWithinPeriod()
bool shortFiltersApproval = shortTradesEnabled and emaShortApproval and isWithinPeriod()

// PLOT =============================================================================================================
bgcolor(color = isWithinPeriod() ? color.new(color.gray, 90) : na, title = 'Period')

showEma = input.bool(defval = true, title = 'Show EMA Line', inline = 'EMA Show', group = 'Plot')
showEmaBand = input.bool(defval = false, title = 'Show EMA Band', tooltip = 'Show the EMA Line/Band.', inline = 'EMA Show', group = 'Plot')

emaLineColor = emaLongApproval ? color.teal : emaShortApproval ? color.maroon : color.gray
plot(series = emaFilterEnabled and showEma ? emaLine : na, color = emaLineColor, style = plot.style_line, linewidth = 2, title = 'EMA Line')
emaUpperBandPlot = plot(series = emaUpperBand, color = na, style = plot.style_line, linewidth = 1, title = 'EMA Upper Band')
emaLowerBandPlot = plot(series = emaLowerBand, color = na, style = plot.style_line, linewidth = 1, title = 'EMA Lower Band')
emaBandFillColor = emaFilterEnabled and emaAtrBandEnabled and showEmaBand ? color.new(emaLineColor, 95) : na
fill(plot1 = emaUpperBandPlot, plot2 = emaLowerBandPlot, color = emaBandFillColor, title = 'EMA Band')

// INPUT ============================================================================================================

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// STRATEGY =========================================================================================================

// INPUT ============================================================================================================
fastMALen = input.int(defval = 21, title = 'Fast/Slow SMA Length', inline = 'MA Length', group = 'Strategy')
slowMALen = input.int(defval = 49, title = '', tooltip = 'How many candles back to calculte the fast/slow SMA.', inline = 'MA Length', group = 'Strategy')

// LOGIC ============================================================================================================
fastMA = ta.sma(close, fastMALen)
slowMA = ta.sma(close, slowMALen)

bool openLongPosition = longFiltersApproval and ta.crossover(fastMA, slowMA)
bool openShortPosition = shortFiltersApproval and ta.crossunder(fastMA, slowMA)

bool closeLongPosition = longTradesEnabled and ta.crossunder(fastMA, slowMA)
bool closeShortPosition = shortTradesEnabled and ta.crossover(fastMA, slowMA)

// PLOT =============================================================================================================
var fastColor = color.new(#0056BD, 0)
plot(series = fastMA, title = 'Fast SMA', color = fastColor, linewidth = 1, style = plot.style_line)
var slowColor = color.new(#FF6A00, 0)
plot(series = slowMA, title = 'Slow SMA', color = slowColor, linewidth = 1, style = plot.style_line)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// SHARED VARIABLES =================================================================================================

// INPUT ============================================================================================================
atrLength = input.int(defval = 14, title = 'ATR Length', minval = 1, tooltip = 'How many previous candles to use for the ATR calculation.', group = 'General')

// LOGIC ============================================================================================================
// the open signals when not already into a position
bool validOpenLongPosition = openLongPosition and not (strategy.position_size > 0)
bool validOpenShortPosition = openShortPosition and not (strategy.position_size < 0)
bool validCloseLongPosition = closeLongPosition and strategy.position_size > 0
bool validCloseShortPosition = closeShortPosition and strategy.position_size < 0

// count how far are the last valid open and regular close signals
int barsSinceValidOpenLong = nz(ta.barssince(validOpenLongPosition), 999999)
int barsSinceValidOpenShort = nz(ta.barssince(validOpenShortPosition), 999999)
int barsSinceCloseLong = nz(ta.barssince(closeLongPosition), 999999)
int barsSinceCloseShort = nz(ta.barssince(closeShortPosition), 999999)

// take profit has to communicate its execution with the stop loss logic when 'TP' mode is selected
var bool longTrailingTakeProfitExecuted = false
var bool shortTrailingTakeProfitExecuted = false

// close price when the valid open signal was triggered
float openPrice = ta.valuewhen(validOpenLongPosition or validOpenShortPosition, close, 0)

float openAtr = ta.valuewhen(validOpenLongPosition or validOpenShortPosition, ta.atr(atrLength), 0)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// ENTRY ============================================================================================================

// INPUT ============================================================================================================
enableEntryTrailing = input.bool(defval = false, title = 'Enable Trailing', tooltip = 'Enable or disable the trailing for entry position.', group = 'Entry')
devEntryMethod = input.string(defval = 'PERC', title = 'Deviation Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Deviation for the Trailing Entry.', group = 'Entry')
devEntryPerc = input.float(defval = 1.0, title = 'Deviation %', minval = 0.01, maxval = 100, step = 0.05, tooltip = 'The step to follow the price when the open position condition is met.', group = 'Entry') / 100
devEntryAtrMul = input.float(defval = 0.5, title = 'Deviation ATR Mul', minval = 0.01, step = 0.05, tooltip = 'Multiplier to be used on the initial entrys` ATR to calculate the step for following the price, when the entry target is reached.', group = 'Entry')
ctrLongEntrySrc = input.source(defval = high, title = 'Long/Short Entry Control', inline = 'Control', group = 'Entry')
ctrShortEntrySrc = input.source(defval = low, title = '', tooltip = 'The price source to check with the entry target to trigger the entry order for Long/Short position.', inline = 'Control', group = 'Entry')

// LOGIC ============================================================================================================
var bool enterLongPosition = false

int barsSinceEnterLong = nz(ta.barssince(enterLongPosition), 999999)
bool openLongIsActive = barsSinceCloseLong >= barsSinceValidOpenLong
bool enterLongIsPending = barsSinceEnterLong >= barsSinceValidOpenLong
bool tryEnterLongPosition = longFiltersApproval and openLongIsActive and enterLongIsPending

getLongEntryPrice(baseSrc) =>
    switch devEntryMethod
        'PERC' => baseSrc * (1 + devEntryPerc)
        'ATR' => baseSrc + devEntryAtrMul * openAtr
        => na

float longEntryPrice = na
longEntryPrice := if validOpenLongPosition
    getLongEntryPrice(close)
else if tryEnterLongPosition
    math.min(getLongEntryPrice(low), nz(longEntryPrice[1], 999999))
else
    na

enterLongPosition := enableEntryTrailing ? longFiltersApproval and ta.crossover(openLongPosition ? close : ctrLongEntrySrc, longEntryPrice) : openLongPosition
bool validEnterLongPosition = enterLongPosition and not (strategy.position_size > 0)

var bool enterShortPosition = false

int barsSinceEnterShort = nz(ta.barssince(enterShortPosition), 999999)
bool openShortIsActive = barsSinceCloseShort >= barsSinceValidOpenShort
bool enterShortIsPending = barsSinceEnterShort >= barsSinceValidOpenShort
bool tryEnterShortPosition = shortFiltersApproval and openShortIsActive and enterShortIsPending

getShortEntryPrice(baseSrc) =>
    switch devEntryMethod
        'PERC' => baseSrc * (1 - devEntryPerc)
        'ATR' => baseSrc - devEntryAtrMul * openAtr
        => na
        
float shortEntryPrice = na
shortEntryPrice := if validOpenShortPosition
    getShortEntryPrice(close)
else if tryEnterShortPosition
    math.max(getShortEntryPrice(high), nz(shortEntryPrice[1]))
else
    na

enterShortPosition := enableEntryTrailing ? shortFiltersApproval and ta.crossunder(openShortPosition ? close : ctrShortEntrySrc, shortEntryPrice) : openShortPosition
bool validEnterShortPosition = enterShortPosition and not (strategy.position_size < 0)

// PLOT =============================================================================================================
var buyColor = color.new(color.green, 0)
plot(series = enableEntryTrailing ? longEntryPrice : na, title = 'Long Buy Price', color = buyColor, linewidth = 1, style = plot.style_linebr)
plot(series = enableEntryTrailing ? shortEntryPrice : na, title = 'Short Sell Price', color = buyColor, linewidth = 1, style = plot.style_linebr)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// EXIT ============================================================================================================

// INPUT ============================================================================================================
enableExitTrailing = input.bool(defval = false, title = 'Enable Trailing', tooltip = 'Enable or disable the trailing for exit position.', group = 'Exit')
devExitMethod = input.string(defval = 'PERC', title = 'Deviation Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Deviation for the Trailing Exit.', group = 'Exit')
devExitPerc = input.float(defval = 3.0, title = 'Deviation %', minval = 0.01, maxval = 100, step = 0.05, tooltip = 'The step to follow the price when the close position condition is met.', group = 'Exit') / 100
devExitAtrMul = input.float(defval = 0.5, title = 'Deviation ATR Mul', minval = 0.01, step = 0.05, tooltip = 'Multiplier to be used on the initial entrys` ATR to calculate the step for following the price, when the exit target is reached.', group = 'Exit')
ctrLongExitSrc = input.source(defval = low, title = 'Long/Short Exit Control', inline = 'Control', group = 'Exit')
ctrShortExitSrc = input.source(defval = high, title = '', tooltip = 'The price source to check with the entry target to trigger the entry order for Long/Short position.', inline = 'Control', group = 'Exit')

// LOGIC ============================================================================================================
var bool exitLongPosition = false

int barsSinceExitLong = nz(ta.barssince(exitLongPosition), 999999)
bool closeLongIsActive = barsSinceValidOpenLong >= barsSinceCloseLong
bool exitLongIsPending = barsSinceExitLong >= barsSinceCloseLong
bool tryExitLongPosition = isWithinPeriod() and closeLongIsActive and exitLongIsPending

getLongExitPrice(baseSrc) =>
    switch devExitMethod
        'PERC' => baseSrc * (1 - devExitPerc)
        'ATR' => baseSrc - devExitAtrMul * openAtr
        => na

float longExitPrice = na
longExitPrice := if validCloseLongPosition
    getLongExitPrice(close)
else if tryExitLongPosition
    math.max(getLongExitPrice(high), nz(longExitPrice[1], 999999))
else
    na

exitLongPosition := enableExitTrailing ? isWithinPeriod() and ta.crossunder(closeLongPosition ? close : ctrLongExitSrc, longExitPrice) : closeLongPosition

bool longIsActive = enterLongPosition or strategy.position_size > 0 and not exitLongPosition

var bool exitShortPosition = false

int barsSinceExitShort = nz(ta.barssince(exitShortPosition), 999999)
bool closeShortIsActive = barsSinceValidOpenShort >= barsSinceCloseShort
bool exitShortIsPending = barsSinceExitShort >= barsSinceCloseShort
bool tryExitShortPosition = isWithinPeriod() and closeShortIsActive and exitShortIsPending

getShortExitPrice(baseSrc) =>
    switch devExitMethod
        'PERC' => baseSrc * (1 + devExitPerc)
        'ATR' => baseSrc + devExitAtrMul * openAtr
        => na

float shortExitPrice = na
shortExitPrice := if validCloseShortPosition
    getShortExitPrice(close)
else if tryExitShortPosition
    math.min(getShortExitPrice(low), nz(shortExitPrice[1], 999999))
else
    na

exitShortPosition := enableExitTrailing ? isWithinPeriod() and ta.crossunder(closeShortPosition ? close : ctrShortExitSrc, shortExitPrice) : closeShortPosition

bool shortIsActive = enterShortPosition or strategy.position_size < 0 and not exitShortPosition

// PLOT =============================================================================================================
var sellColor = color.new(color.red, 0)
plot(series = enableExitTrailing ? longExitPrice : na, title = 'Long Sell Price', color = sellColor, linewidth = 1, style = plot.style_linebr)
plot(series = enableExitTrailing ? shortExitPrice : na, title = 'Short Sell Price', color = sellColor, linewidth = 1, style = plot.style_linebr)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// STOP LOSS ========================================================================================================

// INPUT ============================================================================================================
stopLossMethod = input.string(defval = 'PERC', title = 'Stop Loss Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Stop Loss (percentagewise, based on initial ATR or based on ATR changing over time).', group = 'Stop Loss - Target')
longTrailingStopLossPerc = input.float(defval = 7.5, title = 'Long/Short Stop Loss %', minval = 0.05, maxval = 100, step = 0.05, inline = 'Trailing Stop Loss Perc', group = 'Stop Loss - Target') / 100
shortTrailingStopLossPerc = input.float(defval = 7.5, title = '', minval = 0.05, maxval = 100, step = 0.05, tooltip = 'The percentage of the price decrease/increase to set the Stop Loss price target for long/short positions.', inline = 'Trailing Stop Loss Perc', group = 'Stop Loss - Target') / 100
longStopLossAtrMul = input.float(defval = 3.0, title = 'ATR Long/Short Mul ', minval = 0.1, step = 0.1, inline = 'Trailing Stop Loss ATR Multiplier', group = 'Stop Loss - Target')
shortStopLossAtrMul = input.float(defval = 3.0, title = '', minval = 0.1, step = 0.1, tooltip = 'ATR multiplier to be used for the long/short Stop Loss.', inline = 'Trailing Stop Loss ATR Multiplier', group = 'Stop Loss - Target')
enableStopLossTrailing = input.string(defval = 'TP', title = 'Enable Trailing', options = ['TP', 'ON', 'OFF'], tooltip = 'Enable the trailing for Stop Loss when Take Profit order is executed (TP) or from the start of the entry order (ON) or not at all (OFF).', group = 'Stop Loss - Trailing')
breakEvenEnabled = input.bool(defval = false, title = 'Break Even', tooltip = 'When Take Profit price target is hit, move the Stop Loss to the entry price (or to a more strict price defined by the Stop Loss %/ATR Multiplier).', group = 'Stop Loss - Trailing')

// LOGIC ============================================================================================================
getLongStopLossPrice(baseSrc) =>
    switch stopLossMethod
        'PERC' => baseSrc * (1 - longTrailingStopLossPerc)
        'ATR' => baseSrc - longStopLossAtrMul * openAtr
        => na

getLongStopLossPerc(baseSrc) =>
    (baseSrc - getLongStopLossPrice(baseSrc)) / baseSrc
    
// trailing starts when the take profit price is reached if 'TP' mode is set or from the very begining if 'ON' mode is selected
bool enableLongTakeProfitTrailing = enableStopLossTrailing == 'ON' or enableStopLossTrailing == 'TP' and longTrailingTakeProfitExecuted

// calculate trailing stop loss price when enter long position and peserve its value until the position closes
float longTrailingStopLossPrice = na
longTrailingStopLossPrice := if longIsActive
    if validEnterLongPosition
        getLongStopLossPrice(openPrice)
    else
        stopPrice = getLongStopLossPrice(enableLongTakeProfitTrailing ? high : openPrice)
        stopPrice := breakEvenEnabled and longTrailingTakeProfitExecuted ? math.max(stopPrice, openPrice) : stopPrice
        math.max(stopPrice, nz(longTrailingStopLossPrice[1]))
else
    na

getShortStopLossPrice(baseSrc) =>
    switch stopLossMethod
        'PERC' => baseSrc * (1 + shortTrailingStopLossPerc)
        'ATR' => baseSrc + shortStopLossAtrMul * openAtr
        => na

getShortStopLossPerc(baseSrc) =>
    (getShortStopLossPrice(baseSrc) - baseSrc) / baseSrc

// trailing starts when the take profit price is reached if 'TP' mode is set or from the very begining if 'ON' mode is selected
bool enableShortTakeProfitTrailing = enableStopLossTrailing == 'ON' or enableStopLossTrailing == 'TP' and shortTrailingTakeProfitExecuted

// calculate trailing stop loss price when enter short position and peserve its value until the position closes
float shortTrailingStopLossPrice = na
shortTrailingStopLossPrice := if shortIsActive
    if validEnterShortPosition
        getShortStopLossPrice(openPrice)
    else
        stopPrice = getShortStopLossPrice(enableShortTakeProfitTrailing ? low : openPrice)
        stopPrice := breakEvenEnabled and shortTrailingTakeProfitExecuted ? math.min(stopPrice, openPrice) : stopPrice
        math.min(stopPrice, nz(shortTrailingStopLossPrice[1], 999999.9))
else
    na

// PLOT =============================================================================================================
var stopLossColor = color.new(#e25141, 0)
plot(series = longTrailingStopLossPrice, title = 'Long Trail Stop', color = stopLossColor, linewidth = 1, style = plot.style_linebr, offset = 1)
plot(series = shortTrailingStopLossPrice, title = 'Short Trail Stop', color = stopLossColor, linewidth = 1, style = plot.style_linebr, offset = 1)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// TAKE PROFIT ======================================================================================================

// INPUT ============================================================================================================
takeProfitMethod = input.string(defval = 'PERC', title = 'Take Profit Method', options = ['PERC', 'ATR', 'RR'], tooltip = 'The method to calculate the Take Profit price.', group = 'Take Profit - Target')
longTakeProfitPerc = input.float(defval = 10.0, title = 'Long/Short Take Profit %', minval = 0.05, step = 0.05, inline = 'Take Profit Perc', group = 'Take Profit - Target') / 100
shortTakeProfitPerc = input.float(defval = 10.0, title = '', minval = 0.05, step = 0.05, tooltip = 'The percentage of the price increase/decrease to set the take profit price target for long/short positions.', inline = 'Take Profit Perc', group = 'Take Profit - Target') / 100
longTakeProfitAtrMul = input.float(defval = 9.0, title = 'ATR Long/Short Mul ', minval = 0.1, step = 0.1, inline = 'Take Profit ATR Multiplier', group = 'Take Profit - Target')
shortTakeProfitAtrMul = input.float(defval = 9.0, title = '', minval = 0.1, step = 0.1, tooltip = 'ATR multiplier to be used for the long/short Take Profit.', inline = 'Take Profit ATR Multiplier', group = 'Take Profit - Target')
longRiskRewardRatio = input.float(defval = 1.5, title = 'Long/Short RR Ratio ', minval = 0.1, step = 0.1, inline = 'Risk Reward Ratio', group = 'Take Profit - Target')
shortRiskRewardRatio = input.float(defval = 1.5, title = '', minval = 0.1, step = 0.1, tooltip = 'The Risk/Reward Ratio to be used for the long/short Take Profit based on the Stop Loss Price.', inline = 'Risk Reward Ratio', group = 'Take Profit - Target')

enableTakeProfitTrailing = input.bool(defval = true, title = 'Enable Trailing', tooltip = 'Enable or disable the trailing for take profit.', group = 'Take Profit - Trailing')
devTakeProfitMethod = input.string(defval = 'PERC', title = 'Deviation Method', options = ['PERC', 'ATR'], tooltip = 'The method to calculate the Deviation for the Trailing Take Profit.', group = 'Take Profit - Trailing')
devTakeProfitPerc = input.float(defval = 1.0, title = 'Deviation %', minval = 0.01, maxval = 100, step = 0.05, tooltip = 'The percentage wise step to be used for following the price, when the take profit target is reached.', group = 'Take Profit - Trailing') / 100
devTakeProfitAtrMul = input.float(defval = 1.0, title = 'Deviation ATR Mul', minval = 0.01, step = 0.05, tooltip = 'Multiplier to be used on the initial entrys` ATR to calculate the step for following the price, when the take profit target is reached.', group = 'Take Profit - Trailing')

// LOGIC ============================================================================================================
getLongTakeProfitPrice(baseSrc) =>
    switch takeProfitMethod
        'PERC' => baseSrc * (1 + longTakeProfitPerc)
        'ATR' => baseSrc + longTakeProfitAtrMul * openAtr
        'RR' => baseSrc + longRiskRewardRatio * (baseSrc - getLongStopLossPrice(baseSrc))
        => na

getLongTakeProfitPerc(baseSrc) =>
    (baseSrc - getLongTakeProfitPrice(baseSrc)) / baseSrc

// calculate take profit price when enter long position and peserve its value until the position closes
float longTakeProfitPrice = na
longTakeProfitPrice := if longIsActive and not longTrailingTakeProfitExecuted
    if validEnterLongPosition
        getLongTakeProfitPrice(openPrice)
    else
        nz(longTakeProfitPrice[1], getLongTakeProfitPrice(close))
else
    na

longTrailingTakeProfitExecuted := strategy.position_size > 0 and (longTrailingTakeProfitExecuted[1] or strategy.position_size < strategy.position_size[1] or strategy.position_size[1] == 0 and high >= longTakeProfitPrice)

longTrailingTakeProfitStepTicks = switch devTakeProfitMethod
    'PERC' => longTakeProfitPrice * devTakeProfitPerc / syminfo.mintick
    'ATR' => devTakeProfitAtrMul * openAtr / syminfo.mintick
    => na

getShortTakeProfitPrice(baseSrc) =>
    switch takeProfitMethod
        'PERC' => baseSrc * (1 - shortTakeProfitPerc)
        'ATR' => baseSrc - shortTakeProfitAtrMul * openAtr
        'RR' => baseSrc - shortRiskRewardRatio * (getShortStopLossPrice(baseSrc) - baseSrc)
        => na

getShortTakeProfitPerc(baseSrc) =>
    (getShortTakeProfitPrice(baseSrc) - baseSrc) / baseSrc

// calculate take profit price when enter short position and peserve its value until the position closes
float shortTakeProfitPrice = na
shortTakeProfitPrice := if shortIsActive and not shortTrailingTakeProfitExecuted
    if validEnterShortPosition
        getShortTakeProfitPrice(openPrice)
    else
        nz(shortTakeProfitPrice[1], getShortTakeProfitPrice(close))
else
    na

shortTrailingTakeProfitExecuted := strategy.position_size < 0 and (shortTrailingTakeProfitExecuted[1] or strategy.position_size > strategy.position_size[1] or strategy.position_size[1] == 0 and low <= shortTakeProfitPrice)

shortTrailingTakeProfitStepTicks = switch devTakeProfitMethod
    'PERC' => shortTakeProfitPrice * devTakeProfitPerc / syminfo.mintick
    'ATR' => devTakeProfitAtrMul * openAtr / syminfo.mintick
    => na

// PLOT =============================================================================================================
var takeProfitColor = color.new(#419388, 0) 
plot(series = longTakeProfitPrice, title = 'Long Take Profit', color = takeProfitColor, linewidth = 1, style = plot.style_linebr, offset = 1)
plot(series = shortTakeProfitPrice, title = 'Short Take Profit', color = takeProfitColor, linewidth = 1, style = plot.style_linebr, offset = 1)

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// QUANTITY MANAGEMENT ==============================================================================================

// INPUT ============================================================================================================
takeProfitQuantityPerc = input.float(defval = 50, title = 'Take Profit Quantity %', minval = 0.0, maxval = 100, step = 1.0, tooltip = 'The percentage of the position that will be withdrawn when the take profit price target is reached.', group = 'Quantity/Risk Management')

riskPerc = input.float(defval = 2, title = 'Capital at Risk %', minval = 1, tooltip = 'The maximum percentage of the equity to risk in every trade when no leverage is used.', group = "Quantity/Risk Management") / 100
minTrade = input.int(defval = 10, title = 'Minimum Trade Price', minval = 1, tooltip = 'The minimum trade price in Quote currency that is allowed in the exchange for a valid new position.', group = "Quantity/Risk Management")
longLeverage = input.int(defval = 1, title = 'Leverage Long/Short ', minval = 1, inline = 'Leverage', group = "Quantity/Risk Management")
shortLeverage = input.int(defval = 1, title = '', minval = 1, tooltip = 'Leverage factor used to multiply the initial risk quantity of each trade (by borrowing the remaining amount). Thus, the profits and losses are multiplied respectivelly.', inline = 'Leverage', group = "Quantity/Risk Management")

// LOGIC ============================================================================================================
var int quoteDecimalDigits = math.max(math.ceil(-1 * math.log10(syminfo.mintick * syminfo.pointvalue)), 0)

floor(number, precision) =>
    fact = math.pow(10,  precision)
    num = number * fact
    math.floor(num) / fact

ceil(number, precision) =>
    fact = math.pow(10,  precision)
    num = number * fact
    math.ceil(num) / fact
    
clamp(number, lower, highest, precision) =>
    ceil(math.max(floor(math.min(number, highest), precision), lower), precision)

getLongRiskQuoteQuantity() =>
    clamp(strategy.equity * riskPerc * longLeverage / getLongStopLossPerc(close), minTrade, strategy.equity * longLeverage, quoteDecimalDigits)
    
getLongRiskQuoteQuantityPerc() =>
    getLongRiskQuoteQuantity() / strategy.equity

getLongRiskBaseQuantity() =>
    getLongRiskQuoteQuantity() / close

float longEntryBaseQuantity = na
longEntryBaseQuantity := if longIsActive
    if validOpenLongPosition
        getLongRiskBaseQuantity()
    else
        nz(longEntryBaseQuantity[1], getLongRiskBaseQuantity())
else
    na

getShortRiskQuoteQuantity() =>
    clamp(strategy.equity * riskPerc * shortLeverage / getShortStopLossPerc(close), minTrade, strategy.equity * shortLeverage, quoteDecimalDigits)
    
getShortRiskQuoteQuantityPerc() =>
    getShortRiskQuoteQuantity() / strategy.equity

getShortRiskBaseQuantity() =>
    getShortRiskQuoteQuantity() / close

float shortEntryBaseQuantity = na
shortEntryBaseQuantity := if shortIsActive
    if validOpenShortPosition
        getShortRiskBaseQuantity()
    else
        nz(shortEntryBaseQuantity[1], getShortRiskBaseQuantity())
else
    na

// PLOT =============================================================================================================
label.new(x = validOpenLongPosition ? bar_index : na, y = na, text = 'Buy\n' + str.tostring(100 * getLongRiskQuoteQuantityPerc(), '#.##') + '%', yloc = yloc.belowbar, color = buyColor, style = label.style_label_up, textcolor = color.new(color.white, 0))
label.new(x = validOpenShortPosition ? bar_index : na, y = na, text = 'Sell\n' + str.tostring(100 * getShortRiskQuoteQuantityPerc(), '#.##') + '%', yloc = yloc.abovebar, color = sellColor, style = label.style_label_down, textcolor = color.new(color.white, 0))
label.new(x = validCloseShortPosition ? bar_index : na, y = na, text = 'Buy', yloc = yloc.belowbar, color = buyColor, style = label.style_label_up, textcolor = color.new(color.white, 0))
label.new(x = validCloseLongPosition ? bar_index : na, y = na, text = 'Sell', yloc = yloc.abovebar, color = sellColor, style = label.style_label_down, textcolor = color.new(color.white, 0))

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// ALERT MESSAGES ===================================================================================================

// INPUT ============================================================================================================
msgOpenLong = input.string(defval = 'Long: Started', title = 'Open Long/Short', inline = 'Open Message', group = 'Alert Messages')
msgOpenShort = input.string(defval = 'Short: Started', title = '', tooltip = 'Alert messages emited when open long/short position.', inline = 'Open Message', group = 'Alert Messages')
msgCloseLong = input.string(defval = 'Long: Closed at market price', title = 'Close Long/Short', inline = 'Close Message', group = 'Alert Messages')
msgCloseShort = input.string(defval = 'Short: Closed at market price', title = '', tooltip = 'Alert messages emited when close long/short position.', inline = 'Close Message', group = 'Alert Messages')
msgTPSLLong = input.string(defval = 'Long: Take Profit or Stop Loss executed', title = 'TP/SL Long/Short', inline = 'TP/SL Message', group = 'Alert Messages')
msgTPSLShort = input.string(defval = 'Short: Take Profit or Stop Loss executed', title = '', tooltip = 'Alert message emited when the first quantity target (take profit or stop loss) for long/short position is hit.', inline = 'TP/SL Message', group = 'Alert Messages')
msgSLLong = input.string(defval = 'Long: Stop Loss executed', title = 'SL Long/Short ', inline = 'SL Message', group = 'Alert Messages')
msgSLShort = input.string(defval = 'Short: Stop Loss executed', title = '', tooltip = 'Alert message emited when the second quantity stop loss target for long/short position is hit.', inline = 'SL Message', group = 'Alert Messages')
msgMaxDrawdown= input.string(defval = 'Death is the new beginning', title = 'Max Drawdown', tooltip = 'Alert message emited when the max drawdown limit is hit.', group = 'Alert Messages')

//
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// POSITION ORDERS ==================================================================================================

// INPUT ============================================================================================================
maxDrawdown = input.int(defval = 25, title = 'Max Drawdown %', minval = 1, maxval = 100, tooltip = 'The maximum drawdown to stop trading.', group = "Quantity/Risk Management")

highlighting = input.bool(defval = false, title = 'Show Position Highlighter', tooltip = 'Highlight winning/lossing position.', group = 'Plot')

// LOGIC ============================================================================================================
// close on trend reversal
strategy.close(id = 'Long Entry', when = exitLongPosition, comment = 'Close Long', alert_message = msgCloseLong)

// close on trend reversal
strategy.close(id = 'Short Entry', when = exitShortPosition, comment = 'Close Short', alert_message = msgCloseShort)

// getting into LONG position
strategy.entry(id = 'Long Entry', direction = strategy.long, qty = longEntryBaseQuantity, when = enterLongPosition, alert_message = msgOpenLong)
// submit exit order for trailing take profit price also set the stop loss for the take profit percentage in case that stop loss it reached first
strategy.exit(id = 'Long Take Profit / Stop Loss', from_entry = 'Long Entry', qty_percent = takeProfitQuantityPerc, limit = enableTakeProfitTrailing ? na : longTakeProfitPrice, stop = longTrailingStopLossPrice, trail_price = enableTakeProfitTrailing ? longTakeProfitPrice : na, trail_offset = enableTakeProfitTrailing ? longTrailingTakeProfitStepTicks : na, when = longIsActive, alert_message = msgTPSLLong)
// submit exit order for trailing stop loss price for the remaining percent of the quantity not reserved by the take profit order
strategy.exit(id = 'Long Stop Loss', from_entry = 'Long Entry', stop = longTrailingStopLossPrice, when = longIsActive, alert_message = msgSLLong)

// getting into SHORT position
strategy.entry(id = 'Short Entry', direction = strategy.short, qty = shortEntryBaseQuantity, when = enterShortPosition, alert_message = msgOpenShort)
// submit exit order for trailing take profit price also set the stop loss for the take profit percentage in case that stop loss it reached first
strategy.exit(id = 'Short Take Profit / Stop Loss', from_entry = 'Short Entry', qty_percent = takeProfitQuantityPerc, limit = enableTakeProfitTrailing ? na : shortTakeProfitPrice, stop = shortTrailingStopLossPrice, trail_price = enableTakeProfitTrailing ? shortTakeProfitPrice : na, trail_offset = enableTakeProfitTrailing ? shortTrailingTakeProfitStepTicks : na, when = shortIsActive, alert_message = msgTPSLShort)
// submit exit order for trailing stop loss price for the remaining percent of the quantity not reserved by the take profit order
strategy.exit(id = 'Short Stop Loss', from_entry = 'Short Entry', stop = shortTrailingStopLossPrice, when = shortIsActive, alert_message = msgSLShort)

// limit the maximum drawdown
// strategy.risk.max_drawdown(value = maxDrawdown, type = strategy.percent_of_equity, alert_message = msgMaxDrawdown)

// PLOT =============================================================================================================
lowHighPrice = high > strategy.position_avg_price and low < strategy.position_avg_price ? longIsActive ? high : shortIsActive ? low : na
             : high > strategy.position_avg_price ? high
             : low < strategy.position_avg_price ? low
             : na

pricePlot = plot(series = lowHighPrice, title = 'Price', color = na, linewidth = 1, style = plot.style_linebr)
var posColor = color.new(color.white, 0)
posPlot = plot(series = strategy.position_avg_price, title = 'Position', color = posColor, linewidth = 1, style = plot.style_linebr)

highlightColor = lowHighPrice > strategy.position_avg_price and longIsActive or lowHighPrice < strategy.position_avg_price and shortIsActive ? takeProfitColor
               : lowHighPrice < strategy.position_avg_price and longIsActive or lowHighPrice > strategy.position_avg_price and shortIsActive ? stopLossColor
               : na

fill(plot1 = posPlot, plot2 = pricePlot, color = highlighting ? color.new(highlightColor, 90) : na, title = 'Highlight trades')

// ==================================================================================================================

Thêm nữa