슈퍼트렌드 지표와 주식 곡선 거래에 기반한 양적 거래 전략

저자:차오장, 날짜: 2024-01-15 11:41:53
태그:

img

전반적인 설명

이 전략의 핵심 아이디어는 슈퍼트렌드 지표를 주식 곡선 거래와 결합하는 것입니다. 슈퍼트렌드 지표가 구매 또는 판매 신호를 생성 할 때 우리는 거래를 직접 실행하지 않습니다. 대신 현재 주식 곡선이 이동 평균 이하인지 확인합니다. 주식 곡선이 이동 평균 이상일 때만 포지션을 열 것입니다. 주식 곡선이 이동 평균 이하일 때 우리는 현재 전략에 대한 거래를 일시 중단합니다. 이것은 손실의 확장을 효과적으로 막을 수 있습니다.

전략 논리

이 전략은 크게 두 부분으로 구성됩니다.

  1. 슈퍼트렌드 지표
  2. 주식 곡선 거래

슈퍼트렌드 지표의 계산 공식은 다음과 같습니다.

상단 대역 = 원천 가격 - ATR 곱기 * ATR 하위 대역 = 원천 가격 + ATR 곱기 * ATR

여기서 ATR는 평균 진범을 나타냅니다. 슈퍼트렌드 지표는 ATR를 사용하여 상부 및 하부 대역을 설정합니다. 상부 대역 위의 브레이크오웃은 판매 신호를 나타냅니다. 하부 대역 아래에 있는 브레이크오웃은 구매 신호를 나타냅니다.

주식 곡선 거래의 아이디어는 전략의 주식 곡선의 이동 평균을 취하는 것입니다. 주식 곡선이 이동 평균 이하로 떨어지면 현재 전략의 거래를 일시 중단하고 주식 곡선이 이동 평균보다 다시 상승할 때까지 기다립니다.

이 전략은 두 기법을 결합하여 슈퍼트렌드 지표가 거래 신호를 생성 한 후에 우리는 직접 거래를하지 않습니다. 대신 현재 주식 곡선이 이동 평균보다 높는지 확인합니다. 두 조건이 충족 될 때만 우리는 포지션을 열 것입니다. 이것은 슈퍼트렌드 지표 자체에 내재한 위험을 효과적으로 완화하고 과도한 손실을 방지 할 수 있습니다.

장점

이 전략의 주요 장점은 다음과 같습니다.

  1. 이 지표는 슈퍼트렌드 지표의 위험을 효과적으로 예방할 수 있습니다. 슈퍼트렌드 지표 자체는 손실을 효과적으로 억제 할 수 없습니다. 주식 곡선 거래는이 단점을 보완합니다.

  2. 거래가 불리해지면 과도한 손실을 피하기 위해 거래를 중단합니다. 시장이 회복되면 거래를 재개할 수 있습니다.

  3. 수동 개입 없이 자동으로 포지션을 관리할 수 있습니다. 주식 곡선이 이동 평균 이하로 떨어지면 자동으로 중단되고 주식 곡선이 그 위에 다시 반등하면 재개됩니다.

위험성

이 전략에는 몇 가지 위험도 있습니다.

  1. 잘못된 매개 변수 설정은 주식 곡선 거래가 효과적이지 않을 수 있습니다. 적절한 이동 평균 기간을 선택해야합니다.

  2. 시장 동향이 변할 때 지위를 즉시 조정하지 못할 수도 있습니다. 이것은 특정 손실로 이어질 수 있습니다.

  3. 주식 곡선이 회복되기를 기다리는 동안 좋은 거래 기회를 놓칠 수도 있습니다.

대책:

  1. 매개 변수를 최적화하고 가장 좋은 이동 평균 기간을 선택합니다.

  2. 추세를 판단하고 그에 따라 포지션을 조정하기 위해 다른 지표를 포함합니다.

  3. 중단된 거래 기간을 단축하여 놓친 기회의 가능성을 줄이십시오.

최적화 방향

우리는 다음과 같은 측면에서 전략을 최적화 할 수 있습니다:

  1. 최적의 ATR 기간과 곱기를 찾기 위해 다른 매개 변수 조합을 테스트합니다.

  2. 다른 종류의 이동 평균을 시도해보세요. 기하급수적인 이동 평균, 헐 이동 평균 등

  3. 다른 지표를 추가하여 시장 트렌드를 결정하고, 트렌드가 변할 때 포지션을 조정합니다.

  4. 가장 좋은 균형 을 찾기 위해 이동 평균 기간 을 최적화 한다. 너무 긴 기간 은 기회 를 놓칠 수 있고, 너무 짧은 기간 은 너무 자주 중단 될 수 있다.

  5. 거래 중단을 위한 조건을 최적화하세요. 예를 들어 중단 전에 스톱 로스 임계치를 설정하는 것 처럼요.

결론

이 전략은 슈퍼트렌드 지표를 주식 곡선 거래와巧妙하게 결합하여 두 기법의 장점을 활용합니다. 테스트 결과는 대부분의 경우 주식 곡선 거래를 적용하면 실제로 수익성이 감소한다는 것을 보여줍니다. 따라서이 전략은 방어 트레이더에게 더 적합합니다. 매개 변수 및 논리 최적화로 매우 실용적인 양적 거래 전략이 될 수 있습니다.


/*backtest
start: 2023-01-14 00:00:00
end: 2024-01-14 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy('Supertrend & Equity curve with EMA', overlay=false, format=format.price, precision=2, initial_capital=100000)

eqlen = input.int(25, "EQ EMA len", group = "New Equity Curve Settings")
shEQandMA = input.bool(true, "Show Original Equity Curve and MA")
shEQfilt = input.bool(true, "Show Filtered Equity Curve by MA")

Periods = input(title='ATR Period', defval=10, group = "SuperTrend Settings")
src = input(hl2, title='Source', group = "SuperTrend Settings")
Multiplier = input.float(title='ATR Multiplier', step=0.1, defval=3.0, group = "SuperTrend Settings")
changeATR = input(title='Change ATR Calculation Method ?', defval=true, group = "SuperTrend Settings")

//SuperTrend Code
atr2 = ta.sma(ta.tr, Periods)
atr = changeATR ? ta.atr(Periods) : atr2
up = src - Multiplier * atr
up1 = nz(up[1], up)
up := close[1] > up1 ? math.max(up, up1) : up
dn = src + Multiplier * atr
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? math.min(dn, dn1) : dn
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend

// Strategy main code
buySignal = trend == 1 and trend[1] == -1
sellSignal = trend == -1 and trend[1] == 1
if buySignal
    strategy.entry('Long', strategy.long)
if sellSignal
    strategy.entry('Short', strategy.short)



//Equity Curve calcs
eq = strategy.netprofit
ch = ta.change(eq)
neq = ch != 0 ? eq : na
mova = ta.ema(neq,eqlen)

// New Equity Curve
var float neweq = 0
var int ttrades = 0
var int wintrades = 0
var int losetrades = 0

switch
    strategy.netprofit == strategy.netprofit[1]  => na
    strategy.netprofit < mova and strategy.netprofit[1] > mova  => neweq := neweq + ch
    strategy.netprofit < mova and strategy.netprofit[1] < mova => na
    strategy.netprofit > mova and strategy.netprofit[1] > mova => neweq := neweq + ch

newch = ta.change(neweq)
switch
    newch == 0 => na
    newch > 0 => 
        wintrades := wintrades +1
        ttrades := ttrades +1
    newch < 0 =>
        losetrades := losetrades +1
        ttrades := ttrades +1

//plot(eq, linewidth = 2)
//plot(mova, color=color.red)
//plot(neweq, color= color.green, linewidth = 3)


//Table 
var testTable = table.new(position = position.top_right, columns = 5, rows = 10, bgcolor = color.green, border_width = 1)
table.cell(table_id = testTable, column = 0, row = 0, text = "Strategy: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 1, row = 0, text = "Original: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 2, row = 0, text = "Equity Curve EMA: ", bgcolor=color.white)     

table.cell(table_id = testTable, column = 0, row = 1, text = "Total Trades: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 2, text = "Win Trades: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 3, text = "Lose Trades: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 4, text = "Win Rate: ", bgcolor=color.white)     
table.cell(table_id = testTable, column = 0, row = 5, text = "Net Profit: ", bgcolor=color.white)     

//Equity Curve EMA stat
table.cell(table_id = testTable, column = 2, row = 1, text = str.tostring(ttrades), bgcolor=color.white)     
table.cell(table_id = testTable, column = 2, row = 2, text = str.tostring(wintrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 3, text = str.tostring(losetrades), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 4, text = str.tostring(math.round(100*wintrades/ttrades,2)), bgcolor=color.white)
table.cell(table_id = testTable, column = 2, row = 5, text = str.tostring(math.round(neweq)), bgcolor=color.white)

//Original Strategy stat
// table.cell(table_id = testTable, column = 1, row = 1, text = str.tostring(strategy.closedtrades), bgcolor=color.white)     
// table.cell(table_id = testTable, column = 1, row = 2, text = str.tostring(strategy.wintrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 3, text = str.tostring(strategy.losstrades), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 4, text = str.tostring(math.round(100*strategy.wintrades/strategy.closedtrades,2)), bgcolor=color.white)
// table.cell(table_id = testTable, column = 1, row = 5, text = str.tostring(math.round(strategy.netprofit)), bgcolor=color.white)




//New Equity curve
var newcurve = array.new_float(0)
var int ida = 0
var bool printEQ = false
if newch !=0 
    array.push(newcurve, neweq)
if bar_index > last_bar_index - array.size(newcurve) - 1 - 20  and array.size(newcurve) > 20 
    printEQ := true
else
    printEQ := false

plot(printEQ and ida < strategy.closedtrades and shEQfilt ? array.get(newcurve, ida) : na, color=color.green, linewidth = 2)

if printEQ
    ida := ida + 1
if ida >= array.size(newcurve) and printEQ
    ida := array.size(newcurve) -1



//Original Equity curve
var newcurve2 = array.new_float(0)
var int ida2 = 0
var bool printEQ2 = false
if ch !=0 
    array.push(newcurve2, eq)
if bar_index > last_bar_index - array.size(newcurve2) - 1 - 20  and array.size(newcurve2) > 20 
    printEQ2 := true
else
    printEQ2 := false

plot(printEQ2 and ida2 < strategy.closedtrades and shEQandMA  ? array.get(newcurve2, ida2) : na, color=color.blue, linewidth = 2)

if printEQ2
    ida2 := ida2 + 1
if ida2 >= array.size(newcurve2) and printEQ2
    ida2 := array.size(newcurve2) -1



//Moving Average Array
var marray = array.new_float(0)
if ch
    array.push(marray, mova)

plot(printEQ2 and  array.size(marray) > 40 and shEQandMA ? array.get(marray, ida2-1) : na, color=color.red, linewidth = 1)

hline(0,"0 line", color=color.black, linestyle = hline.style_dotted)


if (last_bar_index-1) and array.size(newcurve2) > 20 and array.size(newcurve) > 20
    l = label.new(bar_index+2, array.get(newcurve2, array.size(newcurve2)-1), "Original Equity Curve", color=color.rgb(33, 149, 243, 85), textcolor = color.black, style = label.style_label_left)
    label.delete(l[1])
    f = label.new(bar_index+2, array.get(newcurve, array.size(newcurve)-1), "Filtered Equity Curve", color=color.rgb(69, 238, 97, 85), textcolor = color.black, style = label.style_label_left)
    label.delete(f[1])

더 많은