Xây dựng "chiến lược Rùa" trên TradingView bằng Pinescript

Ở bài viết trước, chúng ta đã biết về "Chiến lược Rùa" và các yếu tố kỉ luật tạo nên một "chiến lược Rùa" hoàn chỉnh với thị trường Crypto. Hôm nay, chúng ta sẽ cùng xây dựng công cụ để nhận tín hiệu giao dịch theo chiến lược này trên TradingView, một trong những công cụ hỗ trợ phân tích kĩ thuật tốt nhất hiện nay. Để làm được điều này, chúng ta sẽ sử dụng Pinescript, ngôn ngữ lập trình của riêng TradingView, giúp người dùng tạo các chỉ báo, chiến lược riêng Nói riêng về Pinescript, đây là ngôn ngữ lập trình nền web tập trung vào mục đích xây dựng các chỉ báo phân tích kĩ thuật, nhược điểm có nó là bị hạn chế về kĩ thuật và sức mạnh để xây dựng các công cụ phức tạp nhưng bù lại nó rất thân thiện và dễ sử dụng với phần lớn người dùng. Giờ chúng ta sẽ đi vào nội dung chính, từng bước xây dựng "chiến lược Rùa" trên TradingView.

Giao dịch theo xu hướng với "chiến lược Rùa"

Chiến lược Rùa, với nguyên tắc xác định điểm vào lệnh vô cùng đơn giản, dễ hiểu: "vào lệnh khi giá breakout ngưỡng cao nhất (hoặc thấp nhất) của n phiên trước đó", là một trong những cách giao dịch theo xu hướng cơ bản nhất. Nhược điểm lớn nhất của phương pháp giao dịch này là nó không có sự phân biệt giữa breakout thật và breakout giả. Và những cú breakout giả kéo theo thua lỗ làm nản lòng trader tuân thủ phương pháp này cũng như giảm hiệu suất sinh lời của nó. Để khắc phục nhược điểm này, chúng ta cần thêm vào điều kiện giao dịch một công cụ, cho phép chúng ta lọc các cú breakout bằng xu hướng thị trường. Theo đó, chúng ta chỉ mở lệnh mua(long) theo tín hiệu breakout khi thị trường đi lên và mở lệnh bán(short) theo tín hiệu breakout khi thị trường đi xuống. Tổng kết lại, chúng ta có được nguyên tắc vào lệnh như sau:

Nguyên tắc vào lệnh theo xu hướng với "chiến lược Rùa"

Mở lệnh mua (long):

  • Mở lệnh mua (long) khi giá vượt trên ngưỡng giá cao nhất của 20 phiên trước đó (cách 1) hoặc 50 phiên trước đó (cách 2). VÀ:
  • Đường SMA(50) nằm trên đường SMA(200)

Thoát lệnh mua (long):

  • Thoát lệnh mua (long) khi giá cắt xuống ngưỡng thấp nhất của 10 phiên trước đó (cách 1) hoặc 20 phiên trước đó (cách 2). HOẶC:
  • Lệnh chạm stoploss tại mức giá = giá vào lệnh - 2 lần giá trị ATR(20) tại điểm vào lệnh.\

Mở lệnh bán (short):

  • Mở lệnh bán (short) khi giá cắt xuống dưới ngưỡng giá thấp nhất của 20 phiên trước đó (cách 1) hoặc 50 phiên trước đó (cách 2). VÀ:
  • Đường SMA(50) nằm dưới đường SMA(200)

Thoát lệnh bán (short):

  • Thoát lệnh bán (short) khi giá cắt lên ngưỡng cao nhất của 10 phiên trước đó (cách 1) hoặc 20 phiên trước đó (cách 2). HOẶC:
  • Lệnh chạm stoploss tại mức giá = giá vào lệnh + 2 lần giá trị ATR(20) tại điểm vào lệnh.

Khối lượng vào lệnh:

Để đảm mỗi lệnh thua lỗ không quá 2% tổng tài sản, chúng ta sẽ lấy 2% tổng tài sản chia cho khoảng cách giữa điểm vào lệnh và điểm stoploss (bằng 2 lần giá trị ATR(20) tại điểm vào lệnh)

Xây dựng "chiến lược Rùa" với Pinescript

Bước 1: Xác định đầu vào và cấu hình cơ bản của chiến lược

Đầu tiên, chúng ta xác định những cấu hình cơ bản của chiến lược bằng câu lệnh strategy và các tham số như sau:

// === DEFINE STRATEGY SETTINGS ===
strategy(title = "Turtles Ultimate strategy", shorttitle = "Turtles Ultimate", overlay = true, pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 10, initial_capital=1000, calc_on_every_tick=true)

Chúng ta đặt tên cho chiến lược với các tham số titleshorttitle.

overlay = true để kết quả của chiến lược sẽ được hiện thị ngay trên chart giá mà không phải ở vùng riêng.

pyramiding = 0 quy định chiến lược sẽ không có giới hạn số lệnh mở cùng lúc

default_qty_type = strategy.percent_of_equity, default_qty_value = 10,initial_capital=1000 quy định số vốn ban đầu là 1000 USD, mỗi lần vào lệnh (nếu không có quy định khác) chúng ta sẽ sử dụng 10% tổng số vốn để vào lệnh.

Các tham số này đều có thể thay đổi trong quá trình chúng ta sử dụng chiến lược mà không cần phải sửa câu lệnh ban đầu.

Tiếp theo, để chiến lược hoạt động theo đúng nguyên tắc chúng ta đề ra, có 3 cấu phần mà chúng ta cần phải khai báo các biến đầu vào:

Một là khoảng thời gian mà chiến lược sẽ hoạt động trên đó.

Đây là cấu phần đặc biệt quan trọng khi bạn muốn backtest chiến lược. Chúng ta khai báo các biến ngày/tháng/năm bắt đầu và ngày tháng/năm/kết thúc bằng câu lệnhinput, tham số defval quy định giá trị mặc định của biến, title là tên biến sẽ hiển thị trong bảng cấu hình, minvalmaxval quy định giá trị lớn nhất và nhỏ nhất mà biến có thể nhận.

// === TIME RANGE INPUT ===
//From date
FromDay   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
FromYear  = input(defval = 2014, title = "From Year", minval = 2014)
//To date
ToDay     = input(defval = 31, title = "To Day", minval = 1, maxval = 31)
ToMonth   = input(defval = 12, title = "To Month", minval = 1, maxval = 12)
ToYear    = input(defval = 9999, title = "To Year", minval = 2014)

Cấu phần thứ hai là những biến tham số đầu vào cho chiến lược.

Bao gồm các biến sau:

Biến market: cung cấp tùy chọn có mở lệnh short hay không? Mặc định là không.

Biến trend: cung cấp tùy chọn có sử dụng bộ lọc xu hướng hay không? Mặc định là có.

// === TURTLE STRATEGY RELATED INPUTS ===
//Market allow open short position or not?
market = input(false, title = "Market allow open short position?")
trend = input(true, title = "trade follow trend?")

Biến enter_fast là ngưỡng vào lệnh (long hoặc short) theo cách 1 của chiến lược rùa.

Biến exit_fast là ngưỡng thoát lệnh (long hoặc short) theo cách 1 của chiến lược rùa.

Biến enter_slow là ngưỡng vào lệnh (long hoặc short) theo cách 2 của chiến lược rùa.

Biến exit_slow là ngưỡng thoát lệnh (long hoặc short) theo cách 2 của chiến lược rùa.

//Turtle settings
enter_fast = input(20, title = "Turtle Fast Option enter", minval=1)
exit_fast = input(10, title = "Turtle Fast Option exit", minval=1)
enter_slow = input(55, title = "Turtle Slow Option enter", minval=1)
exit_slow = input(20, title = "Turtle Slow Option exit", minval=1)

Chúng ta cũng cần nhập các tham số đầu vào cho 2 đường MA được dùng làm công cụ để xác định xu hướng của thị trường vào lọc bỏ các lệnh giao dịch ngược xu hướng này. Bao gồm: biến src (nguồn tính, mặc định là giá close), ma_res (khung thời gian tính, xem thêm bài đường MA đa khung thời gian), fma_typesma_type (loại đường MA: SMA, EMA,... riêng biệt cho 2 đường fast và slow) và độ dài từng đường (fma_lensma_len).

//Trend define by MA
src = input(title="Source MA", type=source, defval=close)
ma_res = input(title="MA resolution ?", type=resolution, defval="D")
fma_type = input(title="FastMA Type: SMA, EMA, WMA, VWMA", type=string, defval="SMA")
fma_len = input(title="FastMA lengh ?", type=integer, defval=50, minval=1)
sma_type = input(title="SlowMA Type: SMA, EMA, WMA, VWMA", type=string, defval="SMA")
sma_len = input(title="SlowMA lengh ?", type=integer, defval=200, minval=1)

Cấu phần thứ ba là các yếu tố quản trị rủi ro giúp ta xác định được khối lượng và điểm stoploss cần thiết khi vào lệnh.

Biến  usestopatr quy định có sử dụng giá trị ATR làm ngưỡng stoploss hay không. Mặc định là có. Biến atrLen quy định chiều dài tính ATR, stopOffset quy định ngưỡng stoploss sẽ bằng bao nhiều lần (mặc định 2 lần) giá trị ATR.

Biến  usestopperc quy định có sử dụng mức % biến động giá  làm ngưỡng stoploss hay không. Mặc định là không, stopperc là giá trị % stoploss (mặc định bằng 15% với biến stopperc)

// === RISK MANAGEMENT INPUT ===
// ATR stop inputs
usestopatr    = input(true, title = "Use ATR value stoploss?")
atrLen     = input(title="ATR Length", type=integer, defval=20)
stopOffset = input(title="Stop Offset", type=float, defval=2.0, step=0.25)
usestopperc   = input(false, title = "Use stoploss on percent?")
stopperc   = input(15, title = "Stoploss percent = ")

Khối lượng vào lệnh là thành phần cuối cùng cần khai báo, chúng ta sử dụng biến usePosSize cung cấp tùy chọn sử dụng giá trị ATR làm căn cứ tính khối lượng giao dịch hoặc khối lượng giao dịch dựa trên phần trăm vốn (theo mặc định). Biến riskPerc là giá trị phần trăm vốn chịu rủi ro nếu lệnh bị stop-out (mặc định bằng 2%)

// Position sizing inputs
usePosSize = input(title="Use Position Sizing?", type=bool, defval=true)
riskPerc   = input(title="Risk %", type=float, defval=2, step=0.25)

Bước 2: Tính toán các giá trị cần thiết

Từ các tham số đầu vào, chúng ta sẽ cần tính những giá trị cần thiết mà chiến lược sẽ sử dụng. Chiến lược Turtle cần rất nhiều giá trị đầu vào và chúng ta sẽ đi qua lần lượt từng giá trị.

Đầu tiên, chúng ta xác định khoảng thời gian chiến lược hoạt động bằng cầu lệnh timestamp như sau:

start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        // backtest finish window
window()  => time >= start and time <= finish ? true : false // create function "within window of time"

Tiếp theo, chúng ta xác định các ngưỡng đỉnh (highest highs), đáy (lowest lows) cho cả 2 cách vào/thoát lệnh của chiến lược:

//fast entry and fast close
fastL = highest(high, enter_fast)[1]
fastLC = lowest(low, exit_fast)[1]
fastS = lowest(low, enter_fast)[1]
fastSC = highest(high, exit_fast)[1]

//slow entry and slow close
slowL = highest(high, enter_slow)[1]
slowLC = lowest(low, exit_slow)[1]
slowS = lowest(low, enter_slow)[1]
slowSC = highest(high, exit_slow)[1]

câu lệnh đầu tiên tính ngưỡng đỉnh (để vào lệnh long theo cách 1 của chiến lược) với câu lệnh highest()[1], bao gồm chuỗi giá trị cần tính (high) và số nến dùng xác định. Ở đây số nến dùng xác định được nhập bởi biến enter_fast, mặc định là 20 trước đó.  Tham số [1] ở cuối câu lệnh quy định 20 nến dùng xác định ngưỡng đỉnh không bao gồm giá trị high của cây nến hiện tại. Tương tự các câu lệnh khác tính điểm vào lệnh short, điểm thoát lệnh theo cả 2 cách 1 và 2.

Tiếp theo, chúng ta xác định 2 đường MA:

//Trend define by MA
variant(type, src, len) =>
v1 = sma(src, len)                                                 // Simple
v2 = ema(src, len)                                                 // Exponential
v3 = wma(src, len)                                                 // Weighted
v4 = vwma(src, len)                                                // Volume Weighted
// return variant, defaults to SMA if input invalid.
type=="EMA"?v2 : type=="WMA"?v3 : type=="VWMA"?v4 : v1
fastMA = security(tickerid, ma_res, variant(fma_type, src, fma_len))
slowMA = security(tickerid, ma_res, variant(sma_type, src, sma_len))

// Determine trend according to moving averages
upTrend   = trend ? ((fastMA > slowMA) ? true : false) : true
downTrend = trend ? ((fastMA < slowMA) ? true : false) : true

Chúng ta cho phép sử dụng 4 loại đường MA có khung thời gian cố định (không phụ thuộc vào khung thời gian của giá) với câu lệnh variant security(Xem thêm bài đăng Đường Moving Average đa khung thời gian trên TradingView). upTrend được xác định khi đường MA nhanh (mặc định SMA 50 ngày) vượt trên đường MA chậm (mặc định SMA 200 ngày).

Tiếp theo là giá trị ATR và khối lượng giao dịch mỗi lệnh:

// Calculate position size
atrValue = atr(atrLen)
riskEquity  = (riskPerc / 100) * strategy.equity
atrCurrency = (stopOffset*atrValue*syminfo.pointvalue)
posSize     = usePosSize ? riskEquity / atrCurrency : na

Khối lượng giao dịch được xác định dựa trên tỷ lệ phần trăm vốn chịu rủi ro riskEquity và ngưỡng stoploss (ở đơn vị tiền tệ) atrCurrency. Để tính toán, đầu tiên chúng ta chuyển giá trị riskPerc về dạng % và nhân với vốn được quy định strategy.equity. Tiếp theo chúng ta tính ngưỡng stoploss (ở đơn vị tiền tệ) bằng công thức: stopOffset*atrValue*syminfo.pointvalue

Tiếp theo, chúng ta xử lý giá trị stoploss cho 2 loại lệnh long và short:

// Determine stops loss
atrLongEntry = (strategy.position_size == 0) ? close - (atrValue * stopOffset) : na
percLongEntry = (strategy.position_size == 0) ? close - (close*stopperc/100) : na
longStop = usestopatr ? fixnan(atrLongEntry) : usestopperc ? fixnan(percLongEntry) : na

atrShortEntry = (strategy.position_size == 0) ? close + (atrValue * stopOffset) : na
percShortEntry = (strategy.position_size == 0) ? close + (close*stopperc/100) : na
shortStop = usestopatr ? fixnan(atrLongEntry) : usestopperc ? fixnan(percShortEntry) : na

Đầu tiên, chúng ta tính ngưỡng stoploss bằng ATR atrLongEntry hoặc ngưỡng stoploss theo % giá percLongEntry khi chưa có lệnh (strategy.position_size == 0). Đây cũng là điểu kiện để chúng ta có 1 ngưỡng stoploss cố định khi vào lệnh. Nếu không, chiến lược sẽ tính lại ngưỡng stoploss mỗi nến và điểm stoploss sẽ không hoạt động (luôn nằm dưới giá hiện tại). Nếu sử dụng cách stoploss theo giá trị ATR (usestopatr = true), chúng ta sẽ đặt ngưỡng stoploss bằng lệnh fixnan(atrLongEntry). Bởi vì ngưỡng stoploss có thể nhận giá trị = na khi strategy.position_size <> 0 nên chúng ta cần lệnh fixan() để lấy ngưỡng stoploss đã được xác định trước khi vào lệnh.

Tương tự, chúng ta tính ngưỡng stoploss khi dùng stoploss theo % giá  usestopperc

Bước 3: Xây dựng nguyên tắc vào/thoát lệnh

Chúng ta sẽ xây dựng nguyên tắc vào/thoát lệnh và lưu kết quả vào các biến nhận 2 giá trị true/false để sử dụng sau.

// === LOGIC ===
//Fast Option
enterL1 = high[1] < fastL[1] and high > fastL and upTrend and window() and barstate.ishistory
exitL1 =  low < fastLC
enterS1 = low[1] > fastS[1] and low < fastS and downTrend  and window() and market and barstate.ishistory
exitS1 = high > fastSC

//Slow Option
enterL2 = high[1] < fastL[1] and high > slowL and upTrend and window() and barstate.ishistory
exitL2 = low < slowLC
enterS2 = low[1] > fastS[1] and low < slowS and downTrend  and window() and market and barstate.ishistory
exitS2 = high > slowSC

Để vào lệnh long theo cách 1 của chiến lược, các yếu tố sau phải xảy ra đồng thời:

  • Giá vượt lên đỉnh (mặc định 20 phiên gần nhất ) (high[1] < fastL[1] and high > fastL)
  • Xu hướng hiện tại là upTrend (upTrend= true)
  • Thời điểm vào lệnh thuộc vùng thời gian quy định trước và không phải nến hiện tại (window() = true and barstate.ishistory)

Để thoát lệnh chúng ta chỉ cần kiểm tra xem giá có cắt xuống đáy (mặc định 10 phiên gần nhất ) hay không.

Tương tự, chúng ta có các nguyên tắc cho điểm vào/thoát lệnh khác theo 2 cách.

Bước 4: Thực thi lệnh theo nguyên tắc

// === STRATEGY - LONG POSITION EXECUTION ===
strategy.entry("fast L", long=true, qty= posSize, when = enterL1)
strategy.close("fast L", when = exitL1)
strategy.entry("slow L", long=true, qty=posSize, when = enterL2)
strategy.close("slow L", when = exitL2)
// === STRATEGY - SHORT POSITION EXECUTION ===
strategy.entry("fast S", long=false, qty=posSize, when = enterS1)
strategy.close("fast S", when = exitS1)
strategy.entry("slow S", long=false, qty=posSize, when = enterS2)
strategy.close("slow S", when = exitS2)

// === STRATEGY RISK MANAGEMENT EXECUTION ===
if (strategy.position_size > 0 and (usestopatr or usestopperc))
strategy.exit(id="stop fast L", from_entry="fast L", stop=longStop)
if (strategy.position_size > 0 and (usestopatr or usestopperc))
strategy.exit(id="stop slow L", from_entry="slow L", stop=longStop)
if (strategy.position_size < 0 and (usestopatr or usestopperc))
strategy.exit(id="stop fast S", from_entry="fast S", stop=shortStop)
if (strategy.position_size < 0 and (usestopatr or usestopperc))
strategy.exit(id="stop slow S", from_entry="slow S", stop=shortStop)
strategy.close_all(when=barstate.isrealtime)

Lệnh strategy.entry dùng để mở một position mới là (fast L) long (long=true) hoặc short (long=false), có khối lượng định trước (qty= posSize) và điều kiện để mở position (when = enterL1)

Lệnh strategy.close dùng để đóng 1 position đã có trước đó (fast L) khi đủ điều kiện (when = exitL1)

Lệnh strategy.exit dùng để thực hiện lệnh stoploss stop=longStop khi đủ điều kiện (strategy.position_size > 0 and (usestopatr or usestopperc))

Lệnh strategy.close_all(when=barstate.isrealtime) dùng để đóng toàn bộ position đã mở trước (hiện tại position =0) để đảm bảo kết quả chính xác khi chúng ta thực hiện backtest.

Trên đây là các bước để xây dựng "chiến lược Rùa" với công cụ pinescript của tradingview. Trong bài viết tới, Crypto_level_up sẽ cũng mọi người sử dụng tradingview để thực hiện backtest chiến lược này.

Toàn bộ code của chiến lược mọi người có thể lấy tại đây:

//@version=3
// Revision:        1
// Author:          @cryptolevelup.org
//
// *** original idea from «Way of the Turtle: The Secret Methods that Turned Ordinary People into Legendary Traders» ***

// === DEFINE STRATEGY SETTINGS ===
strategy(title = "Turtles Ultimate strategy", shorttitle = "Turtles Ultimate", overlay = true, pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 10, initial_capital=1000, calc_on_every_tick=true)

// === TIME RANGE INPUT ===
//From date
FromDay   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
FromYear  = input(defval = 2014, title = "From Year", minval = 2014)
//To date
ToDay     = input(defval = 31, title = "To Day", minval = 1, maxval = 31)
ToMonth   = input(defval = 12, title = "To Month", minval = 1, maxval = 12)
ToYear    = input(defval = 9999, title = "To Year", minval = 2014)

// === TURTLE STRATEGY RELATED INPUTS ===
//Market allow open short position or not?
market = input(false, title = "Market allow open short position?")
trend = input(true, title = "trade follow trend?")

//Turtle settings
enter_fast = input(20, title = "Turtle Fast Option enter", minval=1)
exit_fast = input(10, title = "Turtle Fast Option exit", minval=1)
enter_slow = input(55, title = "Turtle Slow Option enter", minval=1)
exit_slow = input(20, title = "Turtle Slow Option exit", minval=1)

//Trend define by MA
src = input(title="Source MA", type=source, defval=close)
ma_res = input(title="MA resolution ?", type=resolution, defval="D")
fma_type = input(title="FastMA Type: SMA, EMA, WMA, VWMA", type=string, defval="SMA")
fma_len = input(title="FastMA lengh ?", type=integer, defval=50, minval=1)
sma_type = input(title="SlowMA Type: SMA, EMA, WMA, VWMA", type=string, defval="SMA")
sma_len = input(title="SlowMA lengh ?", type=integer, defval=200, minval=1)

// === RISK MANAGEMENT INPUT ===
// ATR stop inputs
usestopatr    = input(true, title = "Use ATR value stoploss?")
atrLen     = input(title="ATR Length", type=integer, defval=20)
stopOffset = input(title="Stop Offset", type=float, defval=2.0, step=0.25)
usestopperc   = input(false, title = "Use stoploss on percent?")
stopperc   = input(15, title = "Stoploss percent = ")

// Position sizing inputs
usePosSize = input(title="Use Position Sizing?", type=bool, defval=true)
riskPerc   = input(title="Risk %", type=float, defval=2, step=0.25)

// === TIME RANGE PREPARE ===
start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        // backtest finish window
window()  => time >= start and time <= finish ? true : false // create function "within window of time"

// === SERIES SETUP ===
//fast entry and fast close
fastL = highest(high, enter_fast)[1]
fastLC = lowest(low, exit_fast)[1]
fastS = lowest(low, enter_fast)[1]
fastSC = highest(high, exit_fast)[1]

//slow entry and slow close
slowL = highest(high, enter_slow)[1]
slowLC = lowest(low, exit_slow)[1]
slowS = lowest(low, enter_slow)[1]
slowSC = highest(high, exit_slow)[1]

//Trend define by MA
variant(type, src, len) =>
v1 = sma(src, len)                                                  // Simple
v2 = ema(src, len)                                                  // Exponential
v3 = wma(src, len)                                                  // Weighted
v4 = vwma(src, len)                                                 // Volume Weighted
// return variant, defaults to SMA if input invalid.
type=="EMA"?v2 : type=="WMA"?v3 : type=="VWMA"?v4 : v1
fastMA = security(tickerid, ma_res, variant(fma_type, src, fma_len))
slowMA = security(tickerid, ma_res, variant(sma_type, src, sma_len))

// Determine trend according to moving averages
upTrend   = trend ? ((fastMA > slowMA) ? true : false) : true
downTrend = trend ? ((fastMA < slowMA) ? true : false) : true

// Calculate position size
atrValue = atr(atrLen)
riskEquity  = (riskPerc / 100) * strategy.equity
atrCurrency = (stopOffsetatrValuesyminfo.pointvalue)
posSize     = usePosSize ? riskEquity / atrCurrency : na

// Determine stops loss
atrLongEntry = (strategy.position_size == 0) ? close - (atrValue * stopOffset) : na
percLongEntry = (strategy.position_size == 0) ? close - (close*stopperc/100) : na
longStop = usestopatr ? fixnan(atrLongEntry) : usestopperc ? fixnan(percLongEntry) : na

atrShortEntry = (strategy.position_size == 0) ? close + (atrValue * stopOffset) : na
percShortEntry = (strategy.position_size == 0) ? close + (close*stopperc/100) : na
shortStop = usestopatr ? fixnan(atrLongEntry) : usestopperc ? fixnan(percShortEntry) : na

// === LOGIC ===
//Fast Option
enterL1 = high[1] < fastL[1] and high > fastL and upTrend and window() and barstate.ishistory
exitL1 =  low < fastLC
enterS1 = low[1] > fastS[1] and low < fastS and downTrend  and window() and market and barstate.ishistory
exitS1 = high > fastSC

//Slow Option
enterL2 = high[1] < fastL[1] and high > slowL and upTrend and window() and barstate.ishistory
exitL2 = low < slowLC
enterS2 = low[1] > fastS[1] and low < slowS and downTrend  and window() and market and barstate.ishistory
exitS2 = high > slowSC

// === STRATEGY - LONG POSITION EXECUTION ===
strategy.entry("fast L", long=true, qty= posSize, when = enterL1)
strategy.close("fast L", when = exitL1)
strategy.entry("slow L", long=true, qty=posSize, when = enterL2)
strategy.close("slow L", when = exitL2)
// === STRATEGY - SHORT POSITION EXECUTION ===
strategy.entry("fast S", long=false, qty=posSize, when = enterS1)
strategy.close("fast S", when = exitS1)
strategy.entry("slow S", long=false, qty=posSize, when = enterS2)
strategy.close("slow S", when = exitS2)

// === STRATEGY RISK MANAGEMENT EXECUTION ===
if (strategy.position_size > 0 and (usestopatr or usestopperc))
strategy.exit(id="stop fast L", from_entry="fast L", stop=longStop)
if (strategy.position_size > 0 and (usestopatr or usestopperc))
strategy.exit(id="stop slow L", from_entry="slow L", stop=longStop)
if (strategy.position_size < 0 and (usestopatr or usestopperc))
strategy.exit(id="stop fast S", from_entry="fast S", stop=shortStop)
if (strategy.position_size < 0 and (usestopatr or usestopperc))
strategy.exit(id="stop slow S", from_entry="slow S", stop=shortStop)
strategy.close_all(when=barstate.isrealtime)

Show Comments

Get the latest posts delivered right to your inbox.