Chiến lược giao dịch mô hình ABCD tốt nhất với Stop Loss và Take Profit Tracking

Tác giả:ChaoZhang, Ngày: 2024-02-19 11:22:48
Tags:

img

I. Tổng quan chiến lược

Chiến lược này được đặt tên là Best ABCD Pattern Strategy (with Stop Loss and Take Profit Tracking) . Đây là một chiến lược định lượng dựa trên mô hình mô hình giá ABCD rõ ràng. Ý tưởng chính là đi dài hoặc ngắn theo hướng của mô hình ABCD sau khi xác định mô hình ABCD hoàn chỉnh, và đặt dừng lỗ và theo dõi lợi nhuận để quản lý các vị trí.

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

  1. Xác định các điểm cực của giá bằng cách sử dụng Bollinger Bands để có được đường ZigZag.

  2. Nhận diện các mẫu ABCD hoàn chỉnh trên đường ZigZag. Các điểm A, B, C và D cần đáp ứng các mối quan hệ tỷ lệ nhất định. Đi dài hoặc ngắn sau khi xác định các mẫu ABCD phù hợp.

  3. Thiết lập lệnh dừng lỗ sau khi mở các vị trí để kiểm soát rủi ro. Sử dụng lệnh dừng lỗ cố định trước, chuyển sang lệnh dừng lỗ để khóa một số lợi nhuận sau khi đạt đến một mức lợi nhuận nhất định.

  4. Tương tự như vậy, lợi nhuận sau cũng được thiết lập để đảm bảo đủ lợi nhuận trong thời gian và tránh mất mát.

  5. Đóng các vị trí khi giá đạt mức dừng lỗ hoặc lấy lợi nhuận để kết thúc chu kỳ giao dịch.

III. Phân tích lợi thế

  1. Sử dụng các dải Bollinger để xác định đường ZigZag tránh tái vẽ các vấn đề của ZigZag truyền thống, làm cho tín hiệu giao dịch đáng tin cậy hơn.

  2. Mô hình giao dịch mô hình ABCD là trưởng thành và ổn định với các cơ hội giao dịch đầy đủ.

  3. Các thiết lập dừng lỗ và lấy lợi nhuận hai giai đoạn giúp kiểm soát tốt hơn rủi ro và đảm bảo lợi nhuận.

  4. Thiết kế tham số hợp lý như tỷ lệ phần trăm dừng lỗ, lấy lợi nhuận và kích hoạt theo dõi đều có thể tùy chỉnh để linh hoạt.

  5. Chiến lược có thể được sử dụng cho bất kỳ công cụ giao dịch nào, bao gồm ngoại hối, tiền điện tử, chỉ số chứng khoán, v.v.

IV. Phân tích rủi ro

  1. Cơ hội giao dịch cho các mô hình ABCD vẫn còn hạn chế so với các chiến lược khác, không đảm bảo tần suất đủ.

  2. Trong các thị trường dao động, stop loss và take profit có thể được kích hoạt thường xuyên.

  3. Tiền thanh khoản của các công cụ giao dịch cần được xem xét.

  4. Chiến lược này nhạy cảm với chi phí giao dịch.

  5. Một số thông số có thể được tối ưu hóa thêm, như mức kích hoạt để dừng lỗ và lấy lợi nhuận.

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

  1. Kết hợp với các chỉ số khác để thêm nhiều bộ lọc tránh một số tín hiệu sai và giảm giao dịch không hiệu quả.

  2. Thêm phán đoán về cấu trúc thị trường ba phần, chỉ giao dịch trong phần thứ ba.

  3. Kiểm tra và tối ưu hóa vốn ban đầu để tìm mức tối ưu. Cả hai kích thước quá lớn và quá nhỏ đều ảnh hưởng đến tỷ lệ lợi nhuận.

  4. Thực hiện phân tích đi trước với dữ liệu ngoài mẫu để kiểm tra độ chắc chắn của các thông số trong thời gian dài.

  5. Tiếp tục tối ưu hóa các điều kiện kích hoạt và kích thước trượt của trailing stop loss và lấy lợi nhuận để cải thiện hiệu quả.

VI. Tóm tắt chiến lược

Chiến lược này chủ yếu dựa trên mô hình ABCD cho thời gian và nhập thị trường. Hai giai đoạn dừng lỗ và lấy lợi nhuận được sử dụng để quản lý rủi ro và lợi nhuận. Chiến lược tương đối trưởng thành và ổn định nhưng tần suất giao dịch có thể thấp. Chúng ta có thể có được các cơ hội giao dịch hiệu quả hơn bằng cách thêm các bộ lọc và điều kiện. Ngoài ra, điều chỉnh tham số hơn nữa và kích thước vốn có thể cải thiện sự ổn định lợi nhuận của nó. Nhìn chung, đây là một chiến lược có logic rõ ràng và dễ hiểu, đáng nghiên cứu sâu và áp dụng trong giao dịch định lượng thực tế.


/*backtest
start: 2024-02-11 00:00:00
end: 2024-02-18 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// @version=4
// @author=Daveatt - BEST

// ABCD Pattern Strat

StrategyName        = "BEST ABCD Pattern Strategy (Trailing SL + TP)"
ShortStrategyName   = "BEST ABCD Strategy (Trailing)" 

strategy(title=StrategyName, shorttitle=ShortStrategyName, overlay=true )

filterBW = input(false, title="filter Bill Williams Fractals?")

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////// UTILITIES ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

//  ||-----------------------------------------------------------------------------------------------------||
//  ||---   Fractal Recognition Functions:  ---------------------------------------------------------------||
isRegularFractal(mode, _high, _low) =>
    ret = mode == 1 ? _high[4] < _high[3] and _high[3] < _high[2] and _high[2] > _high[1] and _high[1] > _high[0] :
     mode == -1 ? _low[4] > _low[3] and _low[3] > _low[2] and _low[2] < _low[1] and _low[1] < _low[0] : false

isBWFractal(mode, _high, _low) =>
    ret = mode == 1 ? _high[4] < _high[2] and _high[3] <= _high[2] and _high[2] >= _high[1] and _high[2] > _high[0] :
     mode == -1 ? _low[4] > _low[2] and _low[3] >= _low[2] and _low[2] <= _low[1] and _low[2] < _low[0] : false

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
////////////////////////////// ABCD PATTERN ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

f_abcd()=>

    _r = timeframe.period
    _g = barmerge.gaps_off
    _l = barmerge.lookahead_on

    _high = high
    _low = low

    filteredtopf = filterBW ? isRegularFractal(1, _high, _low) : isBWFractal(1, _high, _low)
    filteredbotf = filterBW ? isRegularFractal(-1, _high, _low) : isBWFractal(-1, _high, _low)

    //  ||---   ZigZag:
    istop = filteredtopf
    isbot = filteredbotf
    topcount = barssince(istop)
    botcount = barssince(isbot)

    zigzag = (istop and topcount[1] > botcount[1] ? _high[2] :
     isbot and topcount[1] < botcount[1] ? _low[2] : na)

    x = valuewhen(zigzag, zigzag, 4) 
    a = valuewhen(zigzag, zigzag, 3) 
    b = valuewhen(zigzag, zigzag, 2) 
    c = valuewhen(zigzag, zigzag, 1) 
    d = valuewhen(zigzag, zigzag, 0)

    xab = (abs(b-a)/abs(x-a))
    xad = (abs(a-d)/abs(x-a))
    abc = (abs(b-c)/abs(a-b))
    bcd = (abs(c-d)/abs(b-c))

    // ABCD Part
    _abc = abc >= 0.382 and abc <= 0.886
    _bcd = bcd >= 1.13 and bcd <= 2.618
    
    _bull_abcd = _abc and _bcd and d < c 
    _bear_abcd = _abc and _bcd and d > c

    _bull   = _bull_abcd and not _bull_abcd[1]
    _bear   = _bear_abcd and not _bear_abcd[1]

    [_bull, _bear, zigzag]

lapos_x = timenow + round(change(time)*12)

[isLong, isShort, zigzag]  = f_abcd()

plot(zigzag, title= 'ZigZag', color=color.black, offset=-2)
plotshape(isLong, style=shape.labelup, location=location.belowbar, color=color.new(color.green, 0), size=size.normal, text="ABCD", textcolor=color.white)
plotshape(isShort, style=shape.labeldown, location=location.abovebar, color=color.new(color.maroon, 0), size=size.normal, text="ABCD", textcolor=color.white)


long_entry_price    = valuewhen(isLong, close, 0)
short_entry_price   = valuewhen(isShort, close, 0)

sinceNUP = barssince(isLong)
sinceNDN = barssince(isShort)

buy_trend   = sinceNDN > sinceNUP
sell_trend  = sinceNDN < sinceNUP

change_trend = (buy_trend and sell_trend[1]) or (sell_trend and buy_trend[1])

entry_price  = buy_trend ? long_entry_price : short_entry_price

///////////////////////////////
//======[ Trailing STOP ]======//
///////////////////////////////

// use SL?
useSL = input(true, "Use stop Loss")
// Configure trail stop level with input
StopTrailPerc = input(title="Trail Loss (%)", type=input.float, minval=0.0, step=0.1, defval=3) * 0.01
// Will trigger the take profit trailing once reached
use_SL_Trigger = input(true, "Use stop Loss Trigger")
StopTrailTrigger   = input(2.0, "SL Trigger (%)",minval=0,step=0.5,type=input.float) * 0.01


StopLossPriceTrigger = 0.0
StopLossPriceTrigger := if (use_SL_Trigger)
    if buy_trend
        entry_price * (1 + StopTrailTrigger) 
    else
        entry_price * (1 - StopTrailTrigger)
else
    -1


var SL_Trigger_Long_HIT = false
SL_Trigger_Long_HIT := useSL and use_SL_Trigger and buy_trend and high >= StopLossPriceTrigger
 ? true : SL_Trigger_Long_HIT[1]


var SL_Trigger_Short_HIT = false
SL_Trigger_Short_HIT := useSL and use_SL_Trigger and sell_trend and low <= StopLossPriceTrigger
 ? true : SL_Trigger_Short_HIT[1]


display_long_SL_trigger     = useSL and buy_trend  and use_SL_Trigger 
 and SL_Trigger_Long_HIT == false and StopLossPriceTrigger != -1
display_short_SL_trigger    = useSL and sell_trend and use_SL_Trigger 
 and SL_Trigger_Short_HIT == false and StopLossPriceTrigger != -1
display_SL_trigger          = display_long_SL_trigger or display_short_SL_trigger

plot(display_SL_trigger ? StopLossPriceTrigger : na, title='SLPriceTrigger', transp=0, 
 color=color.maroon, style=plot.style_circles, linewidth=3)


// Determine trail stop loss prices
longStopPrice = 0.0, shortStopPrice = 0.0

longStopPrice := if useSL and buy_trend
    stopValue = low * (1 - StopTrailPerc)
    max(stopValue, longStopPrice[1])
else
    0

shortStopPrice := if useSL and sell_trend
    stopValue = high * (1 + StopTrailPerc)
    min(stopValue, shortStopPrice[1])
else
    999999

//////////////////////////////////////////////////////////////////////////////////////////
//*** STOP LOSS HIT CONDITIONS  ***//
//////////////////////////////////////////////////////////////////////////////////////////

cond_long_stop_loss_hit  = useSL and buy_trend and crossunder(low, longStopPrice[1]) 
 and (SL_Trigger_Long_HIT or use_SL_Trigger == false)
cond_short_stop_loss_hit = useSL and sell_trend and crossover(high, shortStopPrice[1]) 
 and (SL_Trigger_Short_HIT or use_SL_Trigger == false)


// Plot stop loss values for confirmation
plot(series=useSL and buy_trend and low >= longStopPrice 
 and (SL_Trigger_Long_HIT or use_SL_Trigger == false)
 ? longStopPrice : na,
 color=color.fuchsia, style=plot.style_cross,
 linewidth=2, title="Long Trail Stop")

plot(series=useSL and sell_trend and high <= shortStopPrice 
 and (SL_Trigger_Short_HIT or use_SL_Trigger == false)
 ? shortStopPrice : na,
 color=color.fuchsia, style=plot.style_cross,
 linewidth=2, title="Short Trail Stop")


///////////////////////////////
//======[ Take Profit ]======//
///////////////////////////////

// Use TP?
useTP = input(true, "Use take profit")
// TP trailing
ProfitTrailPerc     = input(1.0, "Trailing Profit (%)",minval=0,step=0.5,type=input.float) * 0.01

use_TP_Trigger = input(true, "Use Take Profit Trigger")
// Will trigger the take profit trailing once reached
takeProfitTrigger   = input(3.0, "Take Profit Trigger (%)",minval=0,step=0.5,type=input.float) * 0.01


// ttp := ttp>tp ? tp : ttp

takeprofitPriceTrigger = 0.0
takeprofitPriceTrigger := if (use_TP_Trigger)
    if (buy_trend)
        entry_price * (1 + takeProfitTrigger) 
    else
        entry_price * (1 - takeProfitTrigger)
else
    -1

//plot(entry_price, title='entry_price', transp=100)

var TP_Trigger_Long_HIT = false
TP_Trigger_Long_HIT := useTP and use_TP_Trigger and buy_trend and high >= takeprofitPriceTrigger
 ? true : TP_Trigger_Long_HIT[1]


var TP_Trigger_Short_HIT = false
TP_Trigger_Short_HIT := useTP and use_TP_Trigger and sell_trend and low <= takeprofitPriceTrigger
 ? true : TP_Trigger_Short_HIT[1]


display_long_TP_trigger     = useTP and buy_trend  and TP_Trigger_Long_HIT == false 
 and takeprofitPriceTrigger != -1
display_short_TP_trigger    = useTP and sell_trend and TP_Trigger_Short_HIT == false 
 and takeprofitPriceTrigger != -1
display_TP_trigger          = display_long_TP_trigger or display_short_TP_trigger


//🔷🔷🔷
// @hugo: Will display the TP trigger as long as not hit
// once the TP trigger is hit, the TP trailing will activate
plot(display_TP_trigger ? takeprofitPriceTrigger : na, title='takeprofitPriceTrigger', transp=0, color=color.orange, 
 style=plot.style_cross, linewidth=3)

longTrailTP= 0.0, shortTrailTP = 0.0

// Trailing Profit
// Start trailing once trigger is reached
longTrailTP := if useTP and buy_trend 
    tpValue = high * (1 + ProfitTrailPerc)
    max(tpValue, longTrailTP[1])
else
    0

shortTrailTP := if useTP and sell_trend
    tpValue = low * (1 - ProfitTrailPerc)
    min(tpValue, shortTrailTP[1])
else
    999999

//plot(longTrailTP, title='debug longTrailTP', transp=100)
//plot(shortTrailTP, title='debug shortTrailTP', transp=100)

//////////////////////////////////////////////////////////////////////////////////////////
//*** TRAILING TAKE PROFIT HIT CONDITIONS TO BE USED IN ALERTS  ***//
//////////////////////////////////////////////////////////////////////////////////////////


//🔷🔷🔷
// @hugo: I use crossover/crossunder for the alerts to trigger the events only once
cond_long_trail_tp_hit      = useTP and buy_trend   and crossover(high, longTrailTP[1]) 
 and (TP_Trigger_Long_HIT or use_TP_Trigger == false)
cond_short_trail_tp_hit     = useTP and sell_trend  and crossunder(low, shortTrailTP[1]) 
 and (TP_Trigger_Short_HIT or use_TP_Trigger == false)
// 🔷🔷🔷


// Plot take profits values for confirmation
// Display the trailing TP until not hit
plot(series= useTP and buy_trend and high <= longTrailTP and 
 (TP_Trigger_Long_HIT or use_TP_Trigger == false) ? longTrailTP : na,
 color=color.aqua, style=plot.style_circles,
 linewidth=2, title="Long Trail TP")

plot(series= useTP and sell_trend and low >= shortTrailTP and 
 (TP_Trigger_Short_HIT or use_TP_Trigger == false) ? shortTrailTP : na,
 color=color.aqua, style=plot.style_circles,
 linewidth=2, title="Short Trail TP")

close_long  = cond_long_trail_tp_hit or cond_long_stop_loss_hit
close_short = cond_short_trail_tp_hit or cond_short_stop_loss_hit


strategy.entry("Long", 1, when=isLong)
strategy.close("Long", when=close_long)

strategy.entry("Short", 0,  when=isShort)
strategy.close("Short", when=close_short)

if change_trend
    SL_Trigger_Long_HIT := false
    SL_Trigger_Short_HIT := false
    TP_Trigger_Long_HIT := false
    TP_Trigger_Short_HIT := false

Thêm nữa