Hệ thống theo dõi xu hướng động đa cấp là một chiến lược cải tiến dựa trên Quy tắc giao dịch rùa. Chiến lược này sử dụng các tín hiệu xu hướng từ nhiều khoảng thời gian, kết hợp với việc dừng lỗ động và xây dựng vị trí kim tự tháp, để nắm bắt xu hướng trung hạn đến dài hạn. Hệ thống thiết lập hai giai đoạn theo xu hướng (L1 và L2) để nắm bắt xu hướng ở tốc độ khác nhau và sử dụng chỉ số ATR thích nghi để điều chỉnh động các điểm nhập cảnh, xây dựng vị trí và dừng lỗ.
Xác định xu hướng: Hai giai đoạn trung bình động (L1 và L2) được sử dụng để xác định xu hướng ở tốc độ khác nhau. L1 được sử dụng để nắm bắt xu hướng nhanh hơn, trong khi L2 nắm bắt xu hướng chậm hơn nhưng đáng tin cậy hơn.
Các tín hiệu đầu vào: Các tín hiệu dài được tạo ra khi giá phá vỡ trên mức cao L1 hoặc L2. Nếu giao dịch L1 trước đó có lợi nhuận, tín hiệu L1 tiếp theo sẽ bị bỏ qua cho đến khi một tín hiệu L2 xuất hiện.
Dynamic Stop-Loss: Một số lần của ATR (bên định 3x) được sử dụng như khoảng cách dừng lỗ ban đầu, dần dần di chuyển lên khi vị trí được giữ.
Xây dựng vị trí kim tự tháp: Trong quá trình tiếp tục xu hướng, các vị trí bổ sung được thêm vào mỗi khi giá tăng 0,5 ATR, tối đa 5 lần.
Kiểm soát rủi ro: Mỗi giao dịch rủi ro không quá 2% vốn chủ sở hữu tài khoản, đạt được thông qua kích thước vị trí năng động.
Cơ chế thoát: Các vị trí được đóng khi giá giảm xuống dưới mức thấp 10 ngày (L1) hoặc thấp 20 ngày (L2), hoặc khi lệnh dừng lỗ bị kích hoạt.
Khám phá xu hướng đa cấp: Thời gian L1 và L2 cho phép nắm bắt cả xu hướng nhanh và dài hạn, cải thiện khả năng thích nghi và ổn định của chiến lược.
Quản lý rủi ro năng động: Sử dụng ATR như một chỉ số biến động cho phép điều chỉnh năng động các điểm nhập cảnh, dừng lỗ và xây dựng vị trí, thích nghi tốt hơn với những thay đổi của thị trường.
Xây dựng vị trí kim tự tháp: Tăng dần các vị trí trong quá trình tiếp tục xu hướng kiểm soát rủi ro và tối đa hóa tiềm năng lợi nhuận.
Cài đặt tham số linh hoạt: Nhiều tham số có thể điều chỉnh cho phép chiến lược thích nghi với các thị trường và phong cách giao dịch khác nhau.
Thực thi tự động: Chiến lược có thể chạy hoàn toàn tự động, giảm can thiệp của con người và ảnh hưởng cảm xúc.
Rủi ro đảo ngược xu hướng: hoạt động tốt trong các thị trường xu hướng mạnh nhưng có thể dẫn đến tổn thất thường xuyên trong các thị trường giới hạn phạm vi.
Chi phí trượt và chi phí giao dịch: Việc xây dựng vị trí thường xuyên và di chuyển dừng lỗ có thể dẫn đến chi phí giao dịch cao.
Nguy cơ tối ưu hóa quá mức: Nhiều thông số có thể dẫn đến quá phù hợp dữ liệu lịch sử.
Rủi ro quản lý vốn: vốn ban đầu nhỏ hơn có thể không thực hiện hiệu quả nhiều vị trí xây dựng.
Rủi ro thanh khoản thị trường: Trong các thị trường ít thanh khoản hơn, có thể khó thực hiện giao dịch với giá lý tưởng.
Tích hợp lọc môi trường thị trường: Thêm các chỉ số sức mạnh xu hướng (ví dụ: ADX) để đánh giá điều kiện thị trường và giảm tần suất giao dịch trong các thị trường giới hạn phạm vi.
Tối ưu hóa chiến lược xây dựng vị trí: Xem xét điều chỉnh động khoảng thời gian và số lượng xây dựng vị trí dựa trên sức mạnh xu hướng, thay vì cố định 0,5 ATR và 5 lần.
Giới thiệu cơ chế thu lợi nhuận: Trong xu hướng dài hạn, thiết lập thu lợi nhuận một phần để khóa lợi nhuận, chẳng hạn như đóng một nửa vị trí khi đạt được lợi nhuận ATR 3 lần.
Phân tích tương quan đa công cụ: Khi áp dụng cho danh mục đầu tư, hãy thêm phân tích tương quan giữa các công cụ để tối ưu hóa tỷ lệ rủi ro-lợi nhuận tổng thể.
Thêm lọc biến động: Ngừng giao dịch hoặc điều chỉnh các tham số rủi ro trong thời gian biến động cực kỳ để xử lý các điều kiện thị trường bất thường.
Tối ưu hóa cơ chế thoát: Xem xét sử dụng các chỉ số thoát linh hoạt hơn như Parabolic SAR hoặc Chandelier Exit.
Hệ thống theo dõi xu hướng động đa cấp là một chiến lược toàn diện kết hợp các quy tắc giao dịch rùa cổ điển với các kỹ thuật định lượng hiện đại. Thông qua việc xác định xu hướng đa cấp, quản lý rủi ro năng động và xây dựng vị trí kim tự tháp, chiến lược này cải thiện khả năng nắm bắt xu hướng và tiềm năng lợi nhuận trong khi duy trì độ bền. Mặc dù phải đối mặt với những thách thức trong các thị trường giới hạn phạm vi, với tối ưu hóa tham số và kiểm soát rủi ro thích hợp, chiến lược có tiềm năng duy trì hiệu suất ổn định trong các môi trường thị trường khác nhau.
/*backtest start: 2024-06-28 00:00:00 end: 2024-07-28 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 // This is a strategy based on the famous turtle system. // https://www.tradingblox.com/originalturtles/originalturtlerules.htm // // In a nutshell, it a trend trading system where you are buying on strength, selling on weakness. // positions should be entered when the price crosses over the 20-day high (L1 high) or 55-day high (L2 high). // positions should be exited when the prices crosses below the 10-day low (L1 low) or 20-day low (L2 low) // you can add positions at every unit (measured by multiple of n, where n=1 ATR) // stops should be placed at 2*n below every position entered, when the stop is hit exit your entire position. // positions should be entered everytime price crosses over L1 or L2, with one exception: // if the last trade was an L1 trade and it was a winning trade, skip the next trade unless the price crosses // over L2, if that is the case, you should take it. // L1 and L2 levels are also configurable for high and lows. // N multiple for stops and pyramid are also configurable // To change this from a strategy to a study: // 1) uncomment the next line and comment out the strategy line. // 2) at the end of the file comment out the last 2 lines // study(title="Turtle Study", overlay=true) strategy(title='kTF-VNI', overlay=true, initial_capital=100000000, commission_type=strategy.commission.percent, commission_value=0.0, pyramiding=100, process_orders_on_close=true, calc_on_every_tick=true) stopInput = input.float(3, 'Stop N', step=.05) riskPercent = input.float(.01, 'Risk % of capital', step=.005) pyramidInput = input.float(0.5, 'Pyramid N', step=.05) maxUnits = input.int(5, 'Max Pyramid Units', step=1) atrPeriod = input(20, 'ATR period') l1LongInput = 10 l2LongInput = 20 l1LongExitInput = 20 l2LongExitInput = 40 l1LongInput := input.int(20, 'L1 Long', minval=2) l2LongInput := input.int(60, 'L2 Long', minval=2) l1LongExitInput := input.int(10, 'L1 Long Exit', minval=2) l2LongExitInput := input.int(20, 'L2 Long Exit', minval=2) FromYear = input.int(1970, 'From Year', minval=1900) FromMonth = input.int(1, 'From Month', minval=1, maxval=12) FromDay = input.int(1, 'From Day', minval=1, maxval=31) ToYear = input.int(9999, 'To Year', minval=1900) ToMonth = input.int(1, 'To Month', minval=1, maxval=12) ToDay = input.int(1, 'To Day', minval=1, maxval=31) FromDate = timestamp(FromYear, FromMonth, FromDay, 00, 00) ToDate = timestamp(ToYear, ToMonth, ToDay, 23, 59) TradeDateIsAllowed() => time >= FromDate and time <= ToDate l1Long = ta.highest(l1LongInput) l1LongExit = ta.lowest(l1LongExitInput) l2Long = ta.highest(l2LongInput) l2LongExit = ta.lowest(l2LongExitInput) bool win = false // tracks if last trade was winning trade of losing trade. float buyPrice = 0.0 // tracks the buy price of the last long position. float nextBuyPrice = 0.0 // tracks the next buy price float stopPrice = na // tracks the stop price int totalBuys = 0 // tracks the total # of pyramid buys bool inBuy = false // tracks if we are in a long position or not. float l1LongPlot = ta.highest(l1LongInput) // tracks the L1 price to display float l2LongPlot = ta.highest(l2LongInput) // tracks the L2 price to display float n = ta.atr(atrPeriod) // tracks the n used to calculate stops and pyramid buys string mode = 'L1' // tracks whether we are in a L1 position or L2 position. bool fake = na // tracks if this is a fake trade, see comments below. string longLevel = na // tracks where long positions, stops, pyramid buys occur. float capitalLeft = strategy.initial_capital var shares = 0 float fakeBuyPrice = 0.0 // by default use the last value from the previous bar. buyPrice := buyPrice[1] totalBuys := totalBuys[1] nextBuyPrice := nextBuyPrice[1] stopPrice := stopPrice[1] win := win[1] capitalLeft := capitalLeft[1] inBuy := inBuy[1] n := ta.atr(atrPeriod) fakeBuyPrice := fakeBuyPrice[1] // State to track if we are in a long positon or not. if not inBuy[1] and (high > l1Long[1] or high > l2Long[1]) inBuy := true inBuy else inBuy := inBuy[1] and low < stopPrice[1] ? false : inBuy inBuy := inBuy[1] and mode[1] == 'L1' and low < l1LongExit[1] ? false : inBuy inBuy := inBuy[1] and mode[1] == 'L2' and low < l2LongExit[1] ? false : inBuy inBuy // State to track if we are ia a fake trade. If the last trade was a winning, we need to skip the next trade. // We still track it though as a fake trade (not counted against us). as the outcome determines if we can // can take the next trade. if not inBuy[1] and high > l1Long[1] and win[1] fake := true fakeBuyPrice := close fakeBuyPrice else fake := fake[1] fake if fake[1] and inBuy[1] and not inBuy fake := false win := close >= fakeBuyPrice win fake := high > l2Long[1] ? false : fake // Series representing the l1 and l2 levels. If we break out above the l1 or l2 level, we want the // line to stay at the breakout level, not follow it up. l1LongPlot := not inBuy[1] or inBuy[1] and mode == 'L1' and fake[1] ? l1Long[1] : l1LongPlot[1] l2LongPlot := not inBuy[1] or inBuy[1] and mode == 'L1' and fake[1] ? l2Long[1] : l2LongPlot[1] // Variable in the series is only set when it happens. Possible values is L1, L2, SR // (stopped out with a loss), SG (exited with a gain), and 'P' for pyramid buy. longLevel := not inBuy[1] and high > l1Long[1] ? 'L1' : na longLevel := (not inBuy[1] or inBuy[1] and fake[1]) and high > l2Long[1] ? 'L2' : longLevel // Either 'L1' or 'L2' depending on what breakout level we are in. mode := longLevel == na ? mode[1] : longLevel // Variables to track calculating nextBuyPrice for pyramiding. if longLevel == 'L1' or longLevel == 'L2' buyPrice := close totalBuys := 1 stopPrice := close - stopInput * n nextBuyPrice := close + pyramidInput * n nextBuyPrice // Marks if we hit our next buy price, if so mark it with a 'P' longLevel := longLevel == na and inBuy[1] and high > nextBuyPrice and TradeDateIsAllowed() and totalBuys < maxUnits ? 'P' : longLevel if longLevel == 'P' buyPrice := close totalBuys := totalBuys[1] + 1 stopPrice := close - stopInput * n nextBuyPrice := close + pyramidInput * n nextBuyPrice // Tracks stops and exits, marking them with SG or SR longLevel := longLevel == na and inBuy[1] and low < stopPrice and close >= strategy.position_avg_price ? 'SG' : longLevel longLevel := longLevel == na and inBuy[1] and low < stopPrice and close < strategy.position_avg_price ? 'SR' : longLevel longLevel := longLevel == na and mode[1] == 'L1' and inBuy[1] and low < l1LongExit[1] and close >= strategy.position_avg_price ? 'SG' : longLevel longLevel := longLevel == na and mode[1] == 'L2' and inBuy[1] and low < l2LongExit[1] and close >= strategy.position_avg_price ? 'SG' : longLevel longLevel := longLevel == na and mode[1] == 'L1' and inBuy[1] and low < l1LongExit[1] and close < strategy.position_avg_price ? 'SR' : longLevel longLevel := longLevel == na and mode[1] == 'L2' and inBuy[1] and low < l2LongExit[1] and close < strategy.position_avg_price ? 'SR' : longLevel // Tracks if the trade was a win or loss. win := longLevel == 'SG' ? true : win win := longLevel == 'SR' ? false : win // Variables used to tell strategy when to enter/exit trade. //plotarrow(fake ? 1 : 0, colordown=color.red, colorup=color.purple, transp=40) // down arrow for winning trade enterLong = (longLevel == 'L1' or longLevel == 'L2' or longLevel == 'P') and not fake and TradeDateIsAllowed() exitLong = (longLevel == 'SG' or longLevel == 'SR') and not fake and TradeDateIsAllowed() p1 = plot(l1LongPlot, title='l1 long', linewidth=3, style=plot.style_stepline, color=color.new(color.green, 0)) p2 = plot(l1LongExit[1], title='l1 exit', linewidth=3, style=plot.style_stepline, color=color.new(color.red, 0)) p3 = plot(l2LongPlot, title='l2 long', linewidth=2, style=plot.style_stepline, color=color.new(color.green, 0)) p4 = plot(l2LongExit[1], title='l2 exit', linewidth=2, style=plot.style_stepline, color=color.new(color.red, 0)) color1 = color.new(color.black, 0) color2 = color.new(color.black, 100) col = inBuy ? color1 : color2 p5 = plot(stopPrice, title='stop', linewidth=2, style=plot.style_circles, join=true, color=color.new(color.black, 0)) p6 = plot(nextBuyPrice, title='next buy', linewidth=2, style=plot.style_circles, join=true, color=color.new(color.blue, 0)) fill(p1, p3, color=color.new(color.green, 90)) fill(p2, p4, color=color.new(color.red, 90)) risk = (strategy.initial_capital + strategy.netprofit) * riskPercent shares := math.floor(risk / (stopInput * n)) capitalLeft := strategy.initial_capital + strategy.netprofit - strategy.position_size * strategy.position_avg_price if shares * close > capitalLeft shares := math.max(0, math.floor(capitalLeft / close)) shares shares := math.max(0, shares) plotshape(longLevel == 'L1' and not fake and strategy.position_size == 0 ? true : false, color=color.new(color.green, 40), style=shape.triangleup, text='L1 ') // up arrow for entering L1 trade plotshape(not fake[1] and fake and longLevel == 'L1' and strategy.position_size == 0 ? true : false, color=color.new(color.gray, 40), style=shape.triangleup, text='L1') // up arrow for entering L1 trade plotshape(longLevel == 'L2' and strategy.position_size == 0 ? true : false, color=color.new(color.green, 40), style=shape.triangleup, text='L2') // up arrow for entering L2 trade plotshape((mode == 'L1' or mode == 'L2') and shares > 0 and enterLong and strategy.position_size > 0 ? true : false, color=color.new(color.green, 40), style=shape.triangleup, text='P') plotarrow(strategy.position_size == 0 and longLevel == 'L1' and enterLong ? 1 : 0, colordown=color.new(color.black, 40), colorup=color.new(color.green, 40)) // up arrow for entering L1 trade plotarrow(strategy.position_size == 0 and longLevel == 'L2' and enterLong ? 1 : 0, colordown=color.new(color.black, 40), colorup=color.new(color.green, 40)) // up arrow for entering L2 trade plotarrow(strategy.position_size > 0 and longLevel == 'SR' and exitLong ? -1 : 0, colordown=color.new(color.red, 40), colorup=color.new(color.purple, 40)) // down arrow for losing trade plotarrow(strategy.position_size > 0 and longLevel == 'SG' and exitLong ? -1 : 0, colordown=color.new(color.green, 40), colorup=color.new(color.purple, 40)) // down arrow for winning trade plotshape(longLevel == na and inBuy[1] and not inBuy, color=color.new(color.gray, 40), style=shape.triangleup, text='Exit') // up arrow for entering L1 trade plot(ta.atr(atrPeriod), title='ATR', color=color.new(#991515, 0)) plot(strategy.position_avg_price, title='Average Price', color=color.new(#991515, 0)) alertcondition(low < stopPrice, title='crosses under stop price', message='price crossed under stop price') alertcondition(high > l1Long, title='crosses over L1 price', message='price crossed over L1 price') alertcondition(high > l2Long, title='crosses over L2 price', message='price crossed over L2 price') alertcondition(low < l1LongExit, title='crosses under L1 exit price', message='price crossed under L1 exit price') alertcondition(low < l2LongExit, title='crosses under L2 exit price', message='price crossed under L2 exit price') strategy.entry('long', strategy.long, qty=shares, comment='long', when=enterLong) strategy.close('long', when=exitLong) // simulate_amount = 100000 // simulate_risk = simulate_amount*0.005 // simulate_shares = floor(simulate_risk/(n*stopInput)) // plot(simulate_shares, "Shares", color=#991515, transp=0) // if (enterLong) // label.new(bar_index, high, text=tostring(simulate), style=label.style_none)