Chiến lược theo dõi sự đột phá

Tác giả:ChaoZhang, Ngày: 2023-10-17 16:36:49
Tags:

img

Tổng quan

Chiến lược này chủ yếu sử dụng chỉ số Donchian Channel để thực hiện chiến lược giao dịch theo dõi. Chiến lược kết hợp các ý tưởng giao dịch theo xu hướng và breakout, tìm kiếm các điểm breakout trong các chu kỳ ngắn hơn dựa trên việc xác định xu hướng chính, để giao dịch theo xu hướng. Ngoài ra, chiến lược đặt mức dừng lỗ và lấy lợi nhuận để kiểm soát rủi ro / phần thưởng của mỗi giao dịch. Nhìn chung, chiến lược có lợi thế theo dõi xu hướng và giao dịch theo hướng xu hướng chính.

Chiến lược logic

  1. Đặt tham số cho chỉ số Donchian Channel, thời gian mặc định là 20;

  2. Đặt EMA trung bình động, thời gian mặc định là 200;

  3. Cài đặt tỷ lệ rủi ro/lợi nhuận, mặc định là 1.5;

  4. Đặt các thông số rút lui sau khi phá vỡ cho dài và ngắn;

  5. Ghi lại nếu đột phá trước đó là điểm cao hoặc thấp;

  6. Tín hiệu dài: nếu đột phá trước đó là thấp, giá phá vỡ trên dải trên Donchian và trên đường EMA;

  7. tín hiệu ngắn: nếu đột phá trước đó là cao, giá phá vỡ dưới dải dưới Donchian và dưới đường EMA;

  8. Sau khi bước vào dài, đặt dừng lỗ ở dải dưới Donchian trừ 5 điểm, lấy lợi nhuận tại tỷ lệ rủi ro/lợi nhuận lần khoảng cách dừng lỗ;

  9. Sau khi bước vào ngắn, đặt dừng lỗ ở dải trên Donchian cộng với 5 điểm, lấy lợi nhuận ở tỷ lệ rủi ro / phần thưởng lần khoảng cách dừng lỗ.

Trong khi đó, dừng lỗ và lấy lợi nhuận kiểm soát rủi ro / phần thưởng của mỗi giao dịch.

Phân tích lợi thế

  1. Theo dõi xu hướng chính, tránh giao dịch chống lại xu hướng.

  2. Kênh Donchian như một chỉ số dài hạn, kết hợp với bộ lọc EMA, có thể xác định hiệu quả xu hướng.

  3. Dừng lỗ và lấy lợi nhuận kiểm soát rủi ro cho mỗi giao dịch, hạn chế tổn thất tiềm năng.

  4. Tối ưu hóa tỷ lệ rủi ro / phần thưởng có thể làm tăng yếu tố lợi nhuận, theo đuổi lợi nhuận vượt quá.

  5. Các thông số backtest linh hoạt, có thể tối ưu hóa các thông số cho các thị trường khác nhau.

Phân tích rủi ro

  1. Kênh Donchian và EMA đôi khi có thể đưa ra tín hiệu sai.

  2. Buổi giao dịch đột phá có thể dễ dàng bị mắc kẹt, cần xác định nền tảng xu hướng rõ ràng.

  3. Stop loss cố định và lấy lợi nhuận không thể điều chỉnh dựa trên biến động thị trường.

  4. Không gian tối ưu hóa giới hạn cho các thông số, hiệu suất trực tiếp không được đảm bảo.

  5. Các hệ thống giao dịch dễ bị tổn thương bởi các sự kiện thiên nga đen, có thể dẫn đến tổn thất nghiêm trọng.

Hướng dẫn tối ưu hóa

  1. Xem xét thêm các bộ lọc như dao động để cải thiện chất lượng tín hiệu.

  2. Đặt stop loss thích nghi và lấy lợi nhuận dựa trên biến động thị trường và ATR.

  3. Sử dụng máy học để kiểm tra và tối ưu hóa các thông số để phù hợp với thị trường thực tế.

  4. Tối ưu hóa logic đầu vào với khối lượng hoặc biến động như một điều kiện để tránh bẫy.

  5. Kết hợp với các hệ thống theo xu hướng hoặc học máy để tạo ra các mô hình lai cho độ bền.

Kết luận

Chiến lược này là một chiến lược theo dõi breakout, với logic giao dịch dọc theo xu hướng chính được xác định, và lấy breakout làm tín hiệu nhập cảnh, trong khi đặt dừng lỗ và lấy lợi nhuận để kiểm soát rủi ro cho mỗi giao dịch. Chiến lược có một số lợi thế, nhưng cũng có chỗ để cải thiện. Nhìn chung, với điều chỉnh tham số thích hợp, thời gian nhập cảnh và cải tiến với các kỹ thuật khác, nó có thể trở thành một chiến lược theo xu hướng thực tế. Nhưng các nhà đầu tư nên luôn ghi nhớ rằng không có hệ thống giao dịch nào có thể loại bỏ hoàn toàn rủi ro thị trường và quản lý rủi ro là điều cần thiết.


/*backtest
start: 2023-09-16 00:00:00
end: 2023-10-16 00:00:00
period: 4h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Welcome to my second script on Tradingview with Pinescript
// First of, I'm sorry for the amount of comments on this script, this script was a challenge for me, fun one for sure, but I wanted to thoroughly go through every step before making the script public
// Glad I did so because I fixed some weird things and I ended up forgetting to add the EMA into the equation so our entry signals were a mess
// This one was a lot tougher to complete compared to my MACD crossover trend strategy but I learned a ton from it, which is always good and fun
// Also I'll explain the strategy and how I got there through some creative coding(I'm saying creative because I had to figure this stuff out by myself as I couldn't find any reference codes)
// First things first. This is a Donchian Channel Breakout strategy which follows the following rules
// If the price hits the upperband of the Donchian Channel + price is above EMA and the price previously hit the lowerband of the Donchian Channel it's a buy signal
// If the price hits the lowerband of the Donchian Channel + price is below EMA and the price prevbiously hit the upper band of the Donchian Channel it's a sell signal
// Stop losses are set at the lower or upper band with a 0.5% deviation because we are acting as if those two bands are the resistance in this case
// Last but not least(yes, this gave BY FAR the most trouble to code), the profit target is set with a 1.5 risk to reward ratio
// If you have any suggestions to make my code more efficient, I'll be happy to hear so from you
// So without further ado, let's walk through the code

// The first line is basically standard because it makes backtesting so much more easy, commission value is based on Binance futures fees when you're using BNB to pay those fees in the futures market
// strategy(title="Donchian Channels", shorttitle="DC", overlay=true, default_qty_type = strategy.cash, default_qty_value = 150, initial_capital = 1000, currency = currency.USD, commission_type = "percent", commission_value = 0.036)
// The built-in Donchian Channels + an added EMA input which I grouped with the historical bars from the Donchian Channels
length          = input(20, minval=1, group = "Indicators")
lower           = lowest(length)
upper           = highest(length)
basis           = avg(upper, lower)
emaInput        = input(title = "EMA Input", type = input.integer, defval = 200, minval = 10, maxval = 400, step = 1, group = "Indicators")
// I've made three new inputs, for risk/reward ratio and for the standard pullback deviation. My advise is to not use the pullback inputs as I'm not 100% sure if they work as intended or not
riskreward      = input(title = "Risk/Reward Ratio", type = input.float, defval = 1.50, minval = 0.01, maxval = 100, step = 0.01, group = "Risk/Reward")
pullbackLong    = input(title = "Distance from Long pullback %", type = input.float, defval = 0.995, minval = 0.001, maxval = 2, step = 0.001, group = "Risk/Reward")
pullbackShort   = input(title = "Distance from Short pullback %", type = input.float, defval = 1.005, minval = 0.001, maxval = 2, step = 0.001, group = "Risk/Reward")

// Input backtest range, you can adjust these in the input options, just standard stuff
fromMonth       = input(defval = 1,    title = "From Month",      type = input.integer, minval = 1, maxval = 12, group = "Backtest Date Range")
fromDay         = input(defval = 1,    title = "From Day",        type = input.integer, minval = 1, maxval = 31, group = "Backtest Date Range")
fromYear        = input(defval = 2000, title = "From Year",       type = input.integer, minval = 1970,           group = "Backtest Date Range")
thruMonth       = input(defval = 1,    title = "Thru Month",      type = input.integer, minval = 1, maxval = 12, group = "Backtest Date Range")
thruDay         = input(defval = 1,    title = "Thru Day",        type = input.integer, minval = 1, maxval = 31, group = "Backtest Date Range")
thruYear        = input(defval = 2099, title = "Thru Year",       type = input.integer, minval = 1970,           group = "Backtest Date Range")
// Date variable also standard stuff
inDataRange     = (time >= timestamp(syminfo.timezone, fromYear, fromMonth, fromDay, 0, 0)) and (time < timestamp(syminfo.timezone, thruYear, thruMonth, thruDay, 0, 0))

// I had to makes these variables because the system has to remember whether the previous 'breakout' was a high or a low
// Also, because I based my stoploss on the upper/lower band of the indicator I had to find a way to change this value just once without losing the value, that was added, on the next bar
var previousishigh = false
var previousislow = false
var longprofit = 0.0
var shortprofit = 0.0
var stoplossLong = 0.0
var stoplossShort = 0.0
// These are used as our entry variables
emaCheck = ema(close, emaInput)
longcond = high >= upper and close > emaCheck
shortcond = low <= lower and close < emaCheck

// With these two if statements I'm changing the boolean variable above to true, we need this to decide out entry position
if high >= upper
    previousishigh := true
if low <= lower
    previousislow := true

// Made a last minute change on this part. To clean up our entry signals we don't want our breakouts, while IN a position, to change. This way we do not instantly open a new position, almost always in the opposite direction, upon exiting one
if strategy.position_size > 0 or strategy.position_size < 0 
    previousishigh := false
    previousislow := false

// Strategy inputs
// Long - previous 'breakout' has to be a low, the current price has to be a new high and above the EMA, we're not allowed to be in a position and ofcourse it has to be within our given data for backtesting purposes
if previousislow == true and longcond and strategy.position_size == 0 and inDataRange
    strategy.entry("Long Entry", strategy.long, comment = "Entry Long")
    stoplossLong := lower * pullbackLong
    longprofit := ((((1 - stoplossLong / close) * riskreward) + 1) * close)
    strategy.exit("Long Exit", "Long Entry", limit = longprofit, stop = stoplossLong, comment = "Long Exit")

// Short - Previous 'breakout' has to be a high, current price has to be a new low and lowe than the 200EMA, we're not allowed to trade when we're in a position and it has to be within our given data for backtesting purposes
if previousishigh == true and shortcond and strategy.position_size == 0 and inDataRange
    strategy.entry("Short Entry", strategy.short, comment = "Entry Short")
    stoplossShort := upper * pullbackShort
    shortprofit := (close - ((((1 - close / stoplossShort) * riskreward) * close)))
    strategy.exit("Short Exit", "Short Entry", limit = shortprofit, stop = stoplossShort, comment = "Short Exit")
    
// This plots the Donchian Channels on the chart which is just using the built-in Donchian Channels
plot(basis, "Basis", color=color.blue)
u = plot(upper, "Upper", color=color.green)
l = plot(lower, "Lower", color=color.red)
fill(u, l, color=#0094FF, transp=95, title="Background")

// These plots are to show if the variables are working as intended, it's a mess I know but I didn't have any better ideas, they work well enough for me
// plot(previousislow ? close * 0.95 : na, color=color.red, linewidth=2, style=plot.style_linebr)
// plot(previousishigh ? close * 1.05 : na, color=color.green, style=plot.style_linebr)
// plot(longprofit, color=color.purple)
// plot(shortprofit, color=color.silver)
// plot(stoplossLong)
// plot(stoplossShort)
// plot(strategy.position_size)

Thêm nữa