Hệ thống theo dõi xu hướng động đa cấp

ATR MA RSI
Ngày tạo: 2024-07-29 17:19:43 sửa đổi lần cuối: 2024-07-29 17:19:43
sao chép: 0 Số nhấp chuột: 507
1
tập trung vào
1617
Người theo dõi

Hệ thống theo dõi xu hướng động đa cấp

Tổng quan

Hệ thống theo dõi xu hướng động nhiều tầng là một chiến lược cải tiến dựa trên luật giao dịch biển. Chiến lược này sử dụng tín hiệu xu hướng trong nhiều chu kỳ thời gian, kết hợp với dừng động động và đặt cược bằng kim tự tháp, để nắm bắt xu hướng trung và dài hạn. Hệ thống nắm bắt xu hướng với tốc độ khác nhau bằng cách thiết lập hai chu kỳ theo dõi xu hướng ((L1 và L2)), và sử dụng chỉ số ATR thích nghi để động điều chỉnh vị trí vào, đặt cược và dừng lỗ.

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

  1. Nhận biết xu hướng: Sử dụng hai chu kỳ trung bình di chuyển ((L1 và L2) để nhận biết xu hướng với tốc độ khác nhau. L1 được sử dụng để bắt các xu hướng nhanh hơn, L2 được sử dụng để bắt các xu hướng chậm hơn nhưng đáng tin cậy hơn.

  2. Tín hiệu đầu vào: tạo ra nhiều tín hiệu khi giá vượt qua đỉnh L1 hoặc L2. Nếu giao dịch L1 trước đó có lợi nhuận, hãy bỏ qua tín hiệu L1 tiếp theo cho đến khi tín hiệu L2 xuất hiện.

  3. Hạn chế động: Sử dụng số lần ATR (tức là 3 lần mặc định) làm khoảng cách dừng ban đầu, mức dừng sẽ dần tăng lên theo thời gian giữ.

  4. Tháp kim tự tháp: Trong quá trình tiếp tục xu hướng, mỗi khi giá tăng 0,5 ATR thì tăng thêm, tối đa là 5 lần.

  5. Kiểm soát rủi ro: rủi ro cho mỗi giao dịch không vượt quá 2% giá trị tài khoản ròng bằng cách tính toán động số lượng nắm giữ.

  6. Cơ chế thoát ra: Hạn chế khi giá giảm xuống mức thấp thứ 10 (L1) hoặc mức thấp thứ 20 (L2), hoặc khi kích hoạt đường dừng di chuyển.

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

  1. Trình thu thập xu hướng đa cấp: Với hai chu kỳ L1 và L2, nó có thể nắm bắt cả xu hướng nhanh và xu hướng dài hạn, tăng khả năng thích ứng và ổn định của chiến lược.

  2. Quản lý rủi ro động: Sử dụng ATR làm chỉ số biến động, điều chỉnh động vị trí đầu vào, dừng lỗ và tăng vị trí, thích ứng tốt hơn với sự thay đổi của thị trường.

  3. Bảng kim tự tháp: Bảng kim tự tháp tăng dần khi xu hướng tiếp tục, kiểm soát rủi ro và tối đa hóa tiềm năng lợi nhuận.

  4. 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 phù hợp với các thị trường và phong cách giao dịch khác nhau.

  5. Tự động hóa thực hiện: Chiến lược có thể được tự động hóa hoàn toàn, giảm thiểu sự can thiệp của con người và ảnh hưởng cảm xúc.

Rủi ro chiến lược

  1. Rủi ro đảo ngược xu hướng: hoạt động tốt trong thị trường có xu hướng mạnh, nhưng có thể giao dịch thường xuyên dẫn đến thua lỗ trong thị trường chấn động.

  2. Điểm trượt và chi phí giao dịch: Thường xuyên đặt cược và dừng di động có thể dẫn đến chi phí giao dịch cao hơn.

  3. Rủi ro tối ưu hóa quá mức: Các tham số rất nhiều, dễ gây ra quá phù hợp với dữ liệu lịch sử.

  4. Rủi ro quản lý tiền: Nếu vốn ban đầu nhỏ, có thể không thực hiện hiệu quả nhiều lần gia tăng.

  5. Rủi ro về tính thanh khoản của thị trường: Trong một thị trường thiếu thanh khoản, có thể khó thực hiện giao dịch theo giá lý tưởng.

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

  1. Thêm bộ lọc môi trường thị trường: Bạn có thể thêm các chỉ số cường độ xu hướng (như ADX) để đánh giá môi trường thị trường, giảm tần suất giao dịch trong thị trường biến động.

  2. Chiến lược gia tăng tối ưu hóa: Bạn có thể xem xét việc điều chỉnh động khoảng thời gian và số lần gia tăng tùy thuộc vào cường độ của xu hướng, thay vì 0.5 ATR cố định và 5 lần.

  3. Tham gia vào cơ chế dừng: Trong xu hướng dài hạn, có thể thiết lập một phần dừng để khóa lợi nhuận, chẳng hạn như xóa một nửa vị trí khi đạt mức lợi nhuận ATR gấp 3 lần.

  4. Phân tích liên quan đa giống: Khi sử dụng kết hợp, có thể thêm phân tích liên quan giữa các giống để tối ưu hóa tỷ lệ lợi nhuận rủi ro tổng thể.

  5. Thêm bộ lọc biến động: Trong thời gian biến động rất cao, bạn có thể tạm dừng giao dịch hoặc điều chỉnh các tham số rủi ro để đối phó với thị trường bất thường.

  6. Tối ưu hóa cơ chế thoát: Bạn có thể xem xét sử dụng các chỉ số thoát linh hoạt hơn, chẳng hạn như Parabolic SAR hoặc Chandelier Exit.

Tóm tắt

Hệ thống theo dõi xu hướng động đa tầng là một chiến lược tổng hợp kết hợp các quy tắc giao dịch biển cổ điển và công nghệ định lượng hiện đại. Bằng cách sử dụng các phương pháp như nhận dạng xu hướng đa tầng, quản lý rủi ro động và đặt cược bằng kim tự tháp, chiến lược này tăng khả năng nắm bắt xu hướng và tiềm năng lợi nhuận trong khi vẫn giữ được sự ổn định. Mặc dù đối mặt với những thách thức trong thị trường biến động, nhưng thông qua tối ưu hóa tham số và kiểm soát rủi ro hợp lý, chiến lược này có khả năng duy trì hiệu suất ổn định trong các môi trường thị trường khác nhau.

Mã nguồn chiến lược
/*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)