슈퍼트렌드 지표와 주가곡선 트레이딩을 기반으로 한 양적 전략


생성 날짜: 2024-01-15 11:41:53 마지막으로 수정됨: 2024-01-15 11:41:53
복사: 1 클릭수: 601
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

슈퍼트렌드 지표와 주가곡선 트레이딩을 기반으로 한 양적 전략

개요

이 전략의 핵심 아이디어는 초 트렌드 지표와 순수 곡선 거래를 결합하는 것입니다. 초 트렌드 지표가 구매 또는 판매 신호를 발신할 때, 우리는 거래를 직접 실행하지 않고, 현재의 순수 곡선이 이동 평균보다 낮는지 판단합니다. 순수 곡선이 이동 평균보다 높을 때만 포지션을 열 것입니다.

전략 원칙

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

  1. 트렌드 이상 지표
  2. 순자치 곡선 거래

트렌드 이상 지표의 계산 공식은 다음과 같습니다:

선로 = 원금 - ATR 곱하기 ATR 하위 레일 = 출처값 + ATR 곱하기 ATR

그 중, ATR은 평균 실제 파장을 나타냅니다. 초 트렌드 지표는 ATR을 사용하여 오르락 내리락을 설정합니다. 가격이 오르락 돌리면 판매 신호가 되고, 가격이 하락 돌리면 구매 신호가 됩니다.

순수 곡선 거래의 아이디어는, 우리는 전략 순수 곡선의 이동 평균을 하고, 순수 곡선이 이동 평균보다 낮을 때, 현재 전략의 거래를 중지하고, 순수 곡선이 이동 평균보다 상승한 후에 다시 거래를 시작하는 것을 기다린다.

이 전략은 둘을 결합하여, 초 트렌드 지표가 거래 신호를 생성한 후, 우리는 직접 거래하지 않고, 현재의 당기순 가치 곡선이 이동 평균보다 높는지 판단합니다. 둘 다 동시에 조건이 충족되면, 우리는 포지션을 열 것입니다.

우위 분석

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

  1. 초트렌드 지표의 위험을 효과적으로 방지할 수 있다. 초트렌드 지표 자체는 손실을 효과적으로 피할 수 없으며, 순가율 곡선 거래는 이 단점을 보완할 수 있다.

  2. 거래가 좋지 않을 때, 전략의 거래를 일시 중지하여 손실이 너무 크지 않도록 할 수 있다. 시장이 전환될 때까지 기다려야 다시 열 수 있다.

  3. 수동 개입 없이 자동으로 포지션을 관리할 수 있다. 순자율 곡선이 이동 평균보다 낮으면 자동으로 정지되고, 이동 평균보다 높으면 자동으로 시작된다.

위험 분석

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

  1. 매개 변수 설정 오류는 순수 가치 곡선 거래의 효과를 효과적으로 발휘하지 못하게 할 수 있습니다. 적절한 이동 평균 주기를 선택해야합니다.

  2. 시장 추세가 변할 때, 적시에 포지션을 조정할 수 없을 수도 있다. 이것은 약간의 손실을 초래할 수 있다.

  3. 하지만, 이 경우에도, 그보다 더 나은 기회를 놓칠 수 있습니다.

대책:

  1. 최적화 변수, 최적의 이동 평균 주기를 선택하십시오.

  2. 다른 지표의 추세와 함께 포지션을 적시에 조정하십시오.

  3. 거래 중단 기간을 적절히 단축하여 출입을 놓칠 확률을 줄여주세요.

최적화 방향

이 전략은 다음과 같은 부분에서 최적화될 수 있습니다.

  1. 다른 변수 조합을 테스트하여 최적의 ATR 주기 및 ATR 곱수를 찾습니다.

  2. 다른 종류의 이동 평균을 시도해 보세요. 지수 이동 평균, 헐 이동 평균 등이죠.

  3. 트렌드를 판단하는 다른 지표를 추가하고, 트렌드가 변할 때 적시에 위치를 조정한다.

  4. 이동 평균 주기를 최적화하여 최적의 균형점을 찾는다. 너무 긴 주기는 기회를 놓치고, 너무 짧은 주기는 자주 중단된다.

  5. 거래 중지 조건의 최적화, 예를 들어 Stop Loss Line를 설정하여 손실이 일정 수준에 도달한 후에만 중지하십시오.

요약하다

이 전략은 우월한 트렌드 지표와 순수 곡선 거래를 교묘하게 결합한다. 우월한 트렌드 지표의 추세를 판단하는 장점을 유지하면서도 순수 곡선 거래를 통해 위험을 효과적으로 제어한다. 테스트 결과는 대부분의 경우 순수 곡선 거래를 적용하면 수익률이 감소한다는 것을 보여줍니다. 따라서 이 전략은 방어 유형의 거래자에게 더 적합하다. 매개 변수 최적화 및 규칙 최적화를 통해 이 전략은 매우 실용적인 정량 거래 전략이 될 수 있다.

전략 소스 코드
/*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])