CCI và ATR dựa trên xu hướng theo chiến lược

Tác giả:ChaoZhang, Ngày: 2023-09-26 16:08:37
Tags:

Tổng quan

Chiến lược này xác định xu hướng giá bằng cách kết hợp Trung bình True Range (ATR) và Chỉ số kênh hàng hóa (CCI), và sử dụng mức mua quá mức / bán quá mức như tín hiệu vào và ra. ATR tính toán các dải trên và dưới, trong khi CCI xác định hướng xu hướng. Nó đi ngắn khi CCI vượt dưới mức mua quá mức, và đi dài khi CCI vượt trên mức bán quá mức, do đó theo xu hướng.

Chiến lược logic

  1. Tính toán ATR, ở đây 2 thời kỳ ATR được sử dụng
  2. Tính toán giá trị CCI, ở đây CCI 10 giai đoạn được sử dụng
  3. Định hướng xu hướng dựa trên giá trị CCI hiện tại
    • CCI >= 0, Định nghĩa là xu hướng tăng
    • CCI < 0, Định nghĩa là xu hướng giảm
  4. Tính toán dải trên và dải dưới
    • Dải trên = cao nhất cao + ATR * nhân
    • Phạm vi thấp hơn = thấp nhất - ATR * nhân
  5. Dưới các hướng xu hướng khác nhau, lưu và cập nhật Dải trên và Dải dưới
    • Khi CCI >= 0, nếu Upper Band < previous Upper Band, thiết lập lại; Khi CCI < 0, nếu Lower Band > previous Lower Band, thiết lập lại
    • Điều này tránh các kênh di chuyển ngược lại với giá
  6. Nhập ở dải trên hoặc dưới dựa trên giá trị CCI như tín hiệu nhập
  7. Rút khi CCI vượt qua 0 như tín hiệu thoát
  8. Thiết lập dừng lỗ và lấy lợi nhuận thoát

Ưu điểm

Chiến lược này kết hợp xác định xu hướng và phá vỡ kênh, theo dõi xu hướng hiệu quả.

  1. Sử dụng CCI để xác định hướng xu hướng giá để đánh giá nhanh xu hướng dài / ngắn
  2. Kênh ATR thiết lập dừng lỗ và lấy lợi nhuận để kiểm soát rủi ro
  3. Các kênh có thể nhanh chóng điều chỉnh hướng khi giá đảo ngược, tránh bị mắc kẹt trong kênh xu hướng ban đầu
  4. Ra khỏi CCI s 0 vượt qua xu hướng và tránh những đòn giáng

Rủi ro và cải tiến

  1. Các tham số CCI và ATR cần tối ưu hóa để có kết quả tốt nhất trong các giai đoạn và tham số
  2. Mặc dù điều chỉnh kênh tránh tắc nghẽn, sự đảo ngược nghiêm trọng vẫn có thể gây ra lợi nhuận hoặc lỗ không đủ
  3. Đặt dừng lỗ cần tối ưu hóa, thư giãn dừng để tránh dừng quá mức
  4. Các bộ lọc bổ sung trên tín hiệu vào có thể tối ưu hóa cơ hội vào
  5. Kết hợp với chỉ số xu hướng khung thời gian cao hơn có thể tránh giao dịch chống lại xu hướng cao hơn

Tóm lại

Nói chung đây là một chiến lược theo xu hướng đơn giản và thực tế. Ưu điểm của nó là logic rõ ràng và dễ thực hiện để nhanh chóng tận dụng xu hướng. Nhưng các thông số như phạm vi dừng lỗ đòi hỏi tối ưu hóa dựa trên điều kiện thị trường. Kết hợp với các chỉ số khác có thể tăng cường thêm chiến lược. Là một chiến lược theo xu hướng mới bắt đầu, nó đáng để học và tham khảo.


/*backtest
start: 2023-08-26 00:00:00
end: 2023-09-25 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("Trend Trader Karan",overlay=true)
res = input(title="Resolution", type=input.resolution, defval="60",confirm = true)

ProfitPerc = input(title=" Take Profit (%)",type=input.float, minval=0.0, step=0.1, defval=1.4) * 0.01

stoploss = input(title=" Stop Loss (%)",type=input.float, minval=0.0, step=0.1, defval=0.7) * 0.01

CCI = input(10,title = "CCI")
ATR = input(2,title = "ATR")
Multiplier= 1
original = false
thisCCI = cci(close, CCI)
lastCCI = nz(thisCCI[1])


calcx()=> 
    bufferDn= high + Multiplier * wma(tr,ATR)
    bufferUp= low - Multiplier * wma(tr,ATR)
    if (thisCCI >= 0 and lastCCI < 0) 
        bufferUp := bufferDn[1]
    if (thisCCI <= 0 and lastCCI > 0) 
        bufferDn := bufferUp[1]

    if (thisCCI >= 0)
        if (bufferUp < bufferUp[1])
            bufferUp := bufferUp[1]
    else
        if (thisCCI <= 0)
            if (bufferDn > bufferDn[1])
                bufferDn := bufferDn[1]

   
    x = 0.0
    x := thisCCI >= 0 ?bufferUp:thisCCI <= 0 ?bufferDn:x[1]
    x

tempx = calcx()

calcswap() =>
    swap = 0.0
    swap := tempx>tempx[1]?1:tempx<tempx[1]?-1:swap[1]
    swap

tempswap = calcswap()

swap2=tempswap==1?color.green:color.red
swap3=thisCCI >=0 ?color.green :color.red
swap4=original?swap3:swap2

//display current timeframe's Trend



plot(tempx,color=swap4 == color.green ? color.green : swap4,transp=0,linewidth=4)


htfx = security(syminfo.tickerid,res,tempx[1],lookahead = barmerge.lookahead_on)
htfswap4 = security(syminfo.tickerid,res,swap4[1],lookahead = barmerge.lookahead_on)

plot(htfx,color=htfswap4,transp=0,linewidth=3)


//plotarrow( ? 1 : swap4[1] == color.yellow and swap4 == color.blue ? -1 :0 , title="Up Entry Arrow", colorup=color.green,colordown = color.blue, maxheight=10, minheight=10, transp=0)

plotshape( swap4[1] == color.red and swap4 == color.green ? 1 : na , style = shape.triangleup , color = color.blue , location = location.belowbar , size = size.tiny )
plotshape( swap4[1] == color.green and swap4 == color.red ? 1 : na , style = shape.triangledown , color = color.red , location = location.abovebar , size = size.tiny)




buy =  swap4[1] == color.red and swap4 == color.green and htfswap4 == color.green

sell =  swap4[1] == color.green and swap4 == color.red and htfswap4 == color.red


if(buy)
    strategy.entry("buy",true)
    
if(sell)
    strategy.entry("sell",false)
    
if(swap4[1] == color.red and swap4 == color.green)
    strategy.close("sell")
    
if(swap4[1] == color.green and swap4 == color.red )
    strategy.close("buy")
    
    
longExitPrice  = strategy.position_avg_price * (1 + ProfitPerc)
shortExitPrice = strategy.position_avg_price * (1 - ProfitPerc)

stop_buy = strategy.position_avg_price * (1 - stoploss)
stop_sell = strategy.position_avg_price * (1 + stoploss)
    
    
if (strategy.position_size > 0)
    strategy.exit(id="Target", limit=longExitPrice , stop = stop_buy)

if (strategy.position_size < 0)
    strategy.exit(id="Target", limit=shortExitPrice , stop = stop_sell)
    
    
///////////////study("EMA ", overlay=true)
plot(ema(close, 200), color=#FF7000, linewidth=2, title='200 Day EMA')
plot(ema(close, 20), color=#0088FA, linewidth=2, title='20 Day EMA')
plot(ema(close, 50), color=#FA00D0, linewidth=2, title='50 Day EMA')


//////////////////study("Trend Lines+++", overlay=true)
//
src = input(low)
len0 = input(100)

calcSlope(src, len0) =>
    if not barstate.islast
        [float(na), float(na), float(na)]
    else
        sumX = 0.0
        sumY = 0.0
        sumXSqr = 0.0
        sumXY = 0.0
        for i = 0 to len0 - 1
            val = src[i]
            per = i + 1.0
            sumX := sumX + per
            sumY := sumY + val
            sumXSqr := sumXSqr + per * per
            sumXY := sumXY + val * per
        slope = (len0 * sumXY - sumX * sumY) / (len0 * sumXSqr - sumX * sumX)
        average = sumY / len0
        intercept = average - slope * sumX / len0 + slope
        [slope, average, intercept]

[s, a, i] = calcSlope(src, len0)

startPrice = i + s * (len0 - 1)
endPrice = i
// var line baseLine = na
// if na(baseLine)
//     baseLine := line.new(bar_index - len0 + 1, startPrice, bar_index, endPrice, width=4, extend=extend.right)
// else
//     line.set_xy1(baseLine, bar_index - len0 + 1, startPrice)
//     line.set_xy2(baseLine, bar_index, endPrice)
//     na 
//

mx = input(100, "Range", minval=1)
mn = max(2, round(mx / 10) + 1)

LN(B, CLR) =>
    s1 = B == 1 ? highest(src, mx) : lowest(src, mx)
    s2 = B == 1 ? highest(src, mn) : lowest(src, mn)
    c1 = s1 == src
    c2 = s2 == src
    b1 = barssince(c1)
    b2 = barssince(c2)
    v1 = valuewhen(c1, s1, 0)
    v2 = valuewhen(c2, s2, 0)
    // line.new(bar_index - b1, v1, bar_index - b2, v2, extend=extend.both, color=CLR, width=2)

// L1 = LN(1, #ff0088), line.delete(L1[1])
// L2 = LN(0, #00ff88), line.delete(L2[1])
//
// Input variables
len=input(30,title="loockback length pivots")
wicks=input(true,title="Draw lines from wicks (checked) or real bodies (unchecked)?")
disp_select=input(true,title="Display only falling 'high' and rising 'low' trendlines?")
do_mono=input(false,title="checked = monochrome lines, unchecked = direction colored lines?")
limit_extension=input(0,title="Limit extensions of the lines? 0 = infinite, other values x 100 bars",minval=0)
do_alerts=input(true,title="show trendline breaks")
trendline_nr=input(5,title="number of past trendlines to check for breaks (max = 10)",minval=0,maxval=10)
select_breaks=input(true,title="only display 'long' breaks on trendlines connecting 'highs' and 'short' for 'lows'")
log_chart=input(false,title="USING A LOG CHART? MAKE SURE TO CHECK THIS BOX!!")


// Calculating the 'time value' of one bar
bar_time=time-time[1]

// Initialising color scheme
var color color_rising=do_mono?color.teal:color.lime
var color color_falling=do_mono?color.teal:color.fuchsia


/////// Function declarations ///////

// Declaration of trendline function
f_trendline(_input_function,_delay,_only_up,_extend) =>
    // Calculate line coordinates (Ax,Ay) - (Bx,By)
    var int Ax = 0
    var int Bx = 0
    var float By = 0.0
    var float slope = 0.0
    Ay = fixnan(_input_function)
    if change(Ay)!=0
        Ax := time[_delay]
        By:= Ay[1]
        Bx := Ax[1]
        slope:=log_chart?((log(Ay)-log(By))/(Ax-Bx)):((Ay-By)/(Ax-Bx))
    else
        Ax := Ax[1]
        Bx := Bx[1]
        By := By[1]
    // Draw trendlines
    var line trendline=na
    var int Axbis=0
    var float Aybis=0.0
    var bool _xtend=true
    extension_time = limit_extension*bar_time*100
    Axbis := Ax + extension_time
    Aybis := log_chart?(Ay*exp(extension_time*slope)):(Ay + extension_time*slope)
    if limit_extension!=0
        _xtend:=false
    if change(Ay)!=0
        line_color = slope*time<0?(_only_up?(disp_select?na:color_rising):color_rising):(_only_up?color_falling:(disp_select?na:color_falling))
        if not na(line_color)
            trendline = line.new(Bx,By,Axbis, Aybis, xloc.bar_time, extend=_xtend?extend.right:extend.none, color=line_color, style=line.style_dotted, width=1)

    [Bx,By,Axbis,Aybis,slope]

// Function to get trendline price for X bars ago ("0" = current value)
line_get_price(_start_time,_start_price,_slope,_lookback_period,_log_chart) =>
    var float current_price=0.0
    elapsed_time = (time-_start_time)
    current_price := _log_chart?(_start_price*exp((elapsed_time-(_lookback_period*bar_time))*_slope)):(_start_price + (elapsed_time-(_lookback_period*bar_time))*_slope)

// Function to check for trendline crosses
line_cross(_check_value,_start_time,_start_price,_slope,_log_chart) =>
    var float current_value=0.0
    var float previous_value=0.0
    // Get current and previous price for the trendline
    current_value := line_get_price(_start_time,_start_price,_slope,0,_log_chart)
    previous_value := line_get_price(_start_time,_start_price,_slope,1,_log_chart)
    // Return 1 for crossover, -1 for crossunder and 0 for no cross detected
    cross =
     _check_value[1]<previous_value and _check_value>current_value?1:
     _check_value[1]>previous_value and _check_value<current_value?-1:0


/////// Start of main script ///////

// Calculate pivot points    
high_point=pivothigh(wicks?high:(close>open?close:open),len,len/2)
low_point=pivotlow(wicks?low:(close>open?open:close),len,len/2)

// Call trendline function for high and low pivot points
[phx1,phy1,phx2,phy2,slope_high]=f_trendline(high_point,len/2,false,true)
[plx1,ply1,plx2,ply2,slope_low]=f_trendline(low_point,len/2,true,true)

// Initialition of pseudo array to keep track of last 10 high and 10 low trendline values
var int high_x0=0, var float high_y0=0.0, var float high_sl0=0.0
var int high_x1=0, var float high_y1=0.0, var float high_sl1=0.0 
var int high_x2=0, var float high_y2=0.0, var float high_sl2=0.0 
var int high_x3=0, var float high_y3=0.0, var float high_sl3=0.0 
var int high_x4=0, var float high_y4=0.0, var float high_sl4=0.0
var int high_x5=0, var float high_y5=0.0, var float high_sl5=0.0
var int high_x6=0, var float high_y6=0.0, var float high_sl6=0.0
var int high_x7=0, var float high_y7=0.0, var float high_sl7=0.0
var int high_x8=0, var float high_y8=0.0, var float high_sl8=0.0
var int high_x9=0, var float high_y9=0.0, var float high_sl9=0.0

var int low_x0=0,  var float low_y0=0.0,  var float low_sl0=0.0
var int low_x1=0,  var float low_y1=0.0,  var float low_sl1=0.0 
var int low_x2=0,  var float low_y2=0.0,  var float low_sl2=0.0 
var int low_x3=0,  var float low_y3=0.0,  var float low_sl3=0.0 
var int low_x4=0,  var float low_y4=0.0,  var float low_sl4=0.0
var int low_x5=0,  var float low_y5=0.0,  var float low_sl5=0.0
var int low_x6=0,  var float low_y6=0.0,  var float low_sl6=0.0
var int low_x7=0,  var float low_y7=0.0,  var float low_sl7=0.0
var int low_x8=0,  var float low_y8=0.0,  var float low_sl8=0.0
var int low_x9=0,  var float low_y9=0.0,  var float low_sl9=0.0

// If a new trendline is formed, shift all values in the array one place up and forget the last values
if change(fixnan(high_point))!=0
    high_x9:=high_x8, high_y9:=high_y8, high_sl9:=high_sl8
    high_x8:=high_x7, high_y8:=high_y7, high_sl8:=high_sl7
    high_x7:=high_x6, high_y7:=high_y6, high_sl7:=high_sl6
    high_x6:=high_x5, high_y6:=high_y5, high_sl6:=high_sl5
    high_x5:=high_x4, high_y5:=high_y4, high_sl5:=high_sl4
    high_x4:=high_x3, high_y4:=high_y3, high_sl4:=high_sl3
    high_x3:=high_x2, high_y3:=high_y2, high_sl3:=high_sl2
    high_x2:=high_x1, high_y2:=high_y1, high_sl2:=high_sl1
    high_x1:=high_x0, high_y1:=high_y0, high_sl1:=high_sl0
    high_x0:=phx1, high_y0:=phy1, high_sl0:=slope_high
if change(fixnan(low_point))!=0
    low_x9:=low_x8, low_y9:=low_y8, low_sl9:=low_sl8
    low_x8:=low_x7, low_y8:=low_y7, low_sl8:=low_sl7
    low_x7:=low_x6, low_y7:=low_y6, low_sl7:=low_sl6
    low_x6:=low_x5, low_y6:=low_y5, low_sl6:=low_sl5
    low_x5:=low_x4, low_y5:=low_y4, low_sl5:=low_sl4
    low_x4:=low_x3, low_y4:=low_y3, low_sl4:=low_sl3
    low_x3:=low_x2, low_y3:=low_y2, low_sl3:=low_sl2
    low_x2:=low_x1, low_y2:=low_y1, low_sl2:=low_sl1
    low_x1:=low_x0, low_y1:=low_y0, low_sl1:=low_sl0
    low_x0:=plx1, low_y0:=ply1, low_sl0:=slope_low
    
// Check Trendline crosses for last X nr. of trendlines
cross_high0=
 disp_select and high_sl0*time>0?0:
  line_cross(close,high_x0,high_y0,high_sl0,log_chart)
cross_low0=
 disp_select and low_sl0*time<0?0:
  line_cross(close,low_x0,low_y0,low_sl0,log_chart)

cross_high1=
 disp_select and high_sl1*time>0?0:
  line_cross(close,high_x1,high_y1,high_sl1,log_chart)
cross_low1=
 disp_select and low_sl1*time<0?0:
  line_cross(close,low_x1,low_y1,low_sl1,log_chart)

cross_high2=
 disp_select and high_sl2*time>0?0:
  line_cross(close,high_x2,high_y2,high_sl2,log_chart)
cross_low2=
 disp_select and low_sl2*time<0?0:
  line_cross(close,low_x2,low_y2,low_sl2,log_chart)

cross_high3=
 disp_select and high_sl3*time>0?0:
  line_cross(close,high_x3,high_y3,high_sl3,log_chart)
cross_low3=
 disp_select and low_sl3*time<0?0:
  line_cross(close,low_x3,low_y3,low_sl3,log_chart)

cross_high4=
 disp_select and high_sl4*time>0?0:
  line_cross(close,high_x4,high_y4,high_sl4,log_chart)
cross_low4=
 disp_select and low_sl4*time<0?0:
  line_cross(close,low_x4,low_y4,low_sl4,log_chart)

cross_high5=
 disp_select and high_sl5*time>0?0:
  line_cross(close,high_x5,high_y5,high_sl5,log_chart)
cross_low5=
 disp_select and low_sl5*time<0?0:
  line_cross(close,low_x5,low_y5,low_sl5,log_chart)

cross_high6=
 disp_select and high_sl6*time>0?0:
  line_cross(close,high_x6,high_y6,high_sl6,log_chart)
cross_low6=
 disp_select and low_sl6*time<0?0:
  line_cross(close,low_x6,low_y6,low_sl6,log_chart)

cross_high7=
 disp_select and high_sl7*time>0?0:
  line_cross(close,high_x7,high_y7,high_sl7,log_chart)
cross_low7=
 disp_select and low_sl7*time<0?0:
  line_cross(close,low_x7,low_y7,low_sl7,log_chart)

cross_high8=
 disp_select and high_sl8*time>0?0:
  line_cross(close,high_x8,high_y8,high_sl8,log_chart)
cross_low8=
 disp_select and low_sl8*time<0?0:
  line_cross(close,low_x8,low_y8,low_sl8,log_chart)

cross_high9=
 disp_select and high_sl9*time>0?0:
  line_cross(close,high_x9,high_y9,high_sl9,log_chart)
cross_low9=
 disp_select and low_sl9*time<0?0:
  line_cross(close,low_x9,low_y9,low_sl9,log_chart)
  
long_break=
 (trendline_nr>9?cross_high9==1 or (select_breaks?false:cross_low9==1):false) or
 (trendline_nr>8?cross_high8==1 or (select_breaks?false:cross_low8==1):false) or
 (trendline_nr>7?cross_high7==1 or (select_breaks?false:cross_low7==1):false) or
 (trendline_nr>6?cross_high6==1 or (select_breaks?false:cross_low6==1):false) or
 (trendline_nr>5?cross_high5==1 or (select_breaks?false:cross_low5==1):false) or
 (trendline_nr>4?cross_high4==1 or (select_breaks?false:cross_low4==1):false) or
 (trendline_nr>3?cross_high3==1 or (select_breaks?false:cross_low3==1):false) or
 (trendline_nr>2?cross_high2==1 or (select_breaks?false:cross_low2==1):false) or
 (trendline_nr>1?cross_high1==1 or (select_breaks?false:cross_low1==1):false) or
 cross_high0==1 or (select_breaks?false:cross_low0==1)

short_break=
 (trendline_nr>9?(select_breaks?false:cross_high9==-1) or cross_low9==-1:false) or
 (trendline_nr>8?(select_breaks?false:cross_high8==-1) or cross_low8==-1:false) or
 (trendline_nr>7?(select_breaks?false:cross_high7==-1) or cross_low7==-1:false) or
 (trendline_nr>6?(select_breaks?false:cross_high6==-1) or cross_low6==-1:false) or
 (trendline_nr>5?(select_breaks?false:cross_high5==-1) or cross_low5==-1:false) or
 (trendline_nr>4?(select_breaks?false:cross_high4==-1) or cross_low4==-1:false) or
 (trendline_nr>3?(select_breaks?false:cross_high3==-1) or cross_low3==-1:false) or
 (trendline_nr>2?(select_breaks?false:cross_high2==-1) or cross_low2==-1:false) or
 (trendline_nr>1?(select_breaks?false:cross_high1==-1) or cross_low1==-1:false) or
 (select_breaks?false:cross_high0==-1) or cross_low0==-1

// Plot and connect pivot points
color_high=slope_high*time<0?color_rising:(disp_select?na:color_falling)
color_low=slope_low*time>0?color_falling:(disp_select?na:color_rising)
plot(high_point,color=color_high,offset=-len/2)
plot(low_point,color=color_low,offset=-len/2)
//
// Function outputs 1 when it's the first bar of the D/W/M/Y
is_newbar(res) =>
    ch = 0
    if(res == 'Y')
        t  = year(time('D'))
        ch := change(t) != 0 ? 1 : 0
    else
        t = time(res)
        ch := change(t) != 0 ? 1 : 0
    ch

////////////
// INPUTS //
////////////

pp_period = input(title = "Period", type=input.string, defval="Day", options = ['Day', 'Week', 'Month', 'Year'])

pp_res = pp_period == 'Day' ? 'D' : pp_period == 'Week' ? 'W' : pp_period == 'Month' ? 'M' : 'Y' 

/////////////////////
// Get HLC from HT //

// Calc High
high_cur = 0.0
high_cur := is_newbar(pp_res) ? high : max(high_cur[1], high)

phigh = 0.0
phigh := is_newbar(pp_res) ? high_cur[1] : phigh[1]

// Calc Low
low_cur = 0.0
low_cur := is_newbar(pp_res) ? low : min(low_cur[1], low)

plow = 0.0
plow := is_newbar(pp_res) ? low_cur[1] : plow[1]

// Calc Close
pclose = 0.0
pclose := is_newbar(pp_res) ? close[1] : pclose[1]


Thêm nữa