모멘텀 브레이크아웃 양방향 거래 전략


생성 날짜: 2023-10-27 17:04:48 마지막으로 수정됨: 2023-10-27 17:04:48
복사: 0 클릭수: 655
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

모멘텀 브레이크아웃 양방향 거래 전략

개요

이 전략은 간단한 이동 평균을 사용하여 트렌드 방향을 판단하고, 지속적인 상승 시에는 더 많이 하고, 지속적인 하락 시에는 적자를 하고, 양방향 거래를 실현한다.

전략 원칙

이 전략은 무게 이동 평균 VWMA를 사용하여 시장의 경향 방향을 판단합니다. VWMA가 상승하면 더 많이하고, VWMA가 떨어지면 더 적게합니다.

구체적으로, 전략은 먼저 일정 주기 동안의 VWMA를 계산하고, 그 다음 VWMA가 5일 이상 상승했는지 판단하고, 만약 그렇다면, 더 많은 포지션을 열고; VWMA가 5일 이상 하락하면, 포지션을 공백한다. 평형 포지션 조건은 VWMA 방향이 반전된 후 5일 이상 평형 포지션이다.

월간 및 연간 수익 성과를 계산하기 위해, 전략은 매월 및 연간 수익을 기록한다. 이 전략을 시장 기준 수익과 비교함으로써 전략의 상대 시장의 성과를 직관적으로 볼 수 있다.

우위 분석

이 전략은 다음과 같은 장점을 가지고 있습니다.

  1. VWMA를 사용하여 트렌드를 판단하면 시장 소음을 효과적으로 필터링하여 주요 트렌드를 포착할 수 있습니다.

  2. 트렌드가 확인된 후에만 포지션을 개설하면 트렌드 반전의 위험을 피할 수 있다.

  3. 양방향 거래는 시장의 상승과 하락에 상관없이 수익을 창출합니다.

  4. 월간 및 연간 수익을 기록하여 전략의 효과를 평가하는 데 도움이 됩니다.

  5. 수익표에 시장 기준 수익을 추가하여 전략과 시장의 상대적인 성과를 직관적으로 비교할 수 있다.

위험 분석

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

  1. VWMA를 사용하여 트렌드가 지연될 수 있고, 트렌드 초기 단계의 기회를 놓칠 수 있다.

  2. 트렌드가 확인된 후에만 포지션을 열면, 부분적인 Movement을 놓칠 수 있다.

  3. 양방향 거래는 손실이 커질 수 있는 스톱로스를 결정해야 합니다.

  4. 큰 시장의 변동으로 인해 정지 손실이 발생하여 완전한 추세를 유지할 수 없습니다.

  5. 트렌드 반전의 판단은 정확하지 않을 수 있으며, 이로 인해 손실이 커질 수 있습니다.

최적화 방향

이 정책은 다음과 같은 측면에서 최적화될 수 있습니다.

  1. VWMA 주기 변수를 최적화하여 트렌드 판단을 개선한다.

  2. 트렌드를 확인하는 날 수를 조정하고, 출전 시간을 개선한다.

  3. 단편적 손실을 통제하기 위한 스톱로스 전략을 추가합니다.

  4. 다른 지표와 함께, 역동적인 추세를 판단하여 확실성을 높일 수 있습니다.

  5. 포지션 관리를 최적화하고, 시장 상황에 따라 포지션을 조정한다.

  6. 거래 비용을 고려하여 최소 수익을 설정하십시오.

요약하다

이 전략의 전체적인 아이디어는 명확하고 간단하며, VWMA를 사용하여 트렌드 방향을 판단하고, 트렌드 확인 후 쌍방향 거래를 통해 시장 움직임을 효과적으로 추적할 수 있다. 그러나 또한 특정 위험이 존재하며, 추가 테스트 및 최적화 파라미터가 필요하며, 출구 논리를 조정하고, 포지션 크기를 적절히 제어한다. 이 전략은 양방향 거래 전략에 기초하여 양적 거래의 토대를 마련하고, 추가 연구 및 개선할 가치가 있다.

전략 소스 코드
/*backtest
start: 2023-01-01 00:00:00
end: 2023-10-26 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(title="Monthly Returns in Strategies with Market Benchmark", shorttitle="Monthly P&L With Market", initial_capital= 1000, overlay=true,default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.1)
maLength= input(400)

wma= vwma(hl2,maLength)
uptrend= rising(wma, 5)
downtrend= falling(wma,5)

plot(wma)

if uptrend
    strategy.entry("Buy", strategy.long)
else
    strategy.close("Buy")//

///////////////////
// MONTHLY TABLE //

new_month = month(time) != month(time[1])
new_year  = year(time)  != year(time[1])

eq = strategy.equity

bar_pnl = eq / eq[1] - 1
bar_bh = (close-close[1])/close[1]

cur_month_pnl = 0.0
cur_year_pnl  = 0.0
cur_month_bh = 0.0
cur_year_bh  = 0.0

// Current Monthly P&L
cur_month_pnl := new_month ? 0.0 : 
                 (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1 
cur_month_bh := new_month ? 0.0 : 
                 (1 + cur_month_bh[1]) * (1 + bar_bh) - 1

// Current Yearly P&L
cur_year_pnl := new_year ? 0.0 : 
                 (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1
cur_year_bh := new_year ? 0.0 : 
                 (1 + cur_year_bh[1]) * (1 + bar_bh) - 1

// Arrays to store Yearly and Monthly P&Ls
var month_pnl  = array.new_float(0)
var month_time = array.new_int(0)
var month_bh  = array.new_float(0)

var year_pnl  = array.new_float(0)
var year_time = array.new_int(0)
var year_bh  = array.new_float(0)

last_computed = false

if (not na(cur_month_pnl[1]) and (new_month or time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory))
    if (last_computed[1])
        array.pop(month_pnl)
        array.pop(month_time)
        
    array.push(month_pnl , cur_month_pnl[1])
    array.push(month_time, time[1])
    array.push(month_bh , cur_month_bh[1])

if (not na(cur_year_pnl[1]) and (new_year or time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory))
    if (last_computed[1])
        array.pop(year_pnl)
        array.pop(year_time)
        
    array.push(year_pnl , cur_year_pnl[1])
    array.push(year_time, time[1])
    array.push(year_bh , cur_year_bh[1])

last_computed := (time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory) ? true : nz(last_computed[1])

// Monthly P&L Table    
var monthly_table = table(na)

getCellColor(pnl, bh)  => 
    if pnl > 0
        if bh < 0 or pnl > 2 * bh
            color.new(color.green, transp = 20)
        else if pnl > bh
            color.new(color.green, transp = 50)
        else
            color.new(color.green, transp = 80)
    else
        if bh > 0
            color.new(color.red, transp = 20)
        else if pnl < bh
            color.new(color.red, transp = 50)
        else
            color.new(color.red, transp = 80)

if last_computed
    monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(monthly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(monthly_table, 1,  0, "Jan",  bgcolor = #cccccc)
    table.cell(monthly_table, 2,  0, "Feb",  bgcolor = #cccccc)
    table.cell(monthly_table, 3,  0, "Mar",  bgcolor = #cccccc)
    table.cell(monthly_table, 4,  0, "Apr",  bgcolor = #cccccc)
    table.cell(monthly_table, 5,  0, "May",  bgcolor = #cccccc)
    table.cell(monthly_table, 6,  0, "Jun",  bgcolor = #cccccc)
    table.cell(monthly_table, 7,  0, "Jul",  bgcolor = #cccccc)
    table.cell(monthly_table, 8,  0, "Aug",  bgcolor = #cccccc)
    table.cell(monthly_table, 9,  0, "Sep",  bgcolor = #cccccc)
    table.cell(monthly_table, 10, 0, "Oct",  bgcolor = #cccccc)
    table.cell(monthly_table, 11, 0, "Nov",  bgcolor = #cccccc)
    table.cell(monthly_table, 12, 0, "Dec",  bgcolor = #cccccc)
    table.cell(monthly_table, 13, 0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(monthly_table, 0,  yi + 1, tostring(year(array.get(year_time, yi))), bgcolor = #cccccc)
        
        y_color = getCellColor(array.get(year_pnl, yi), array.get(year_bh, yi))
        table.cell(monthly_table, 13, yi + 1, tostring(round(array.get(year_pnl, yi) * 100)) + " (" + tostring(round(array.get(year_bh, yi) * 100)) + ")", bgcolor = y_color)
        
    for mi = 0 to array.size(month_time) - 1
        m_row   = year(array.get(month_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = month(array.get(month_time, mi)) 
        m_color = getCellColor(array.get(month_pnl, mi), array.get(month_bh, mi))
        
        table.cell(monthly_table, m_col, m_row, tostring(round(array.get(month_pnl, mi) * 100)) + " (" + tostring(round(array.get(month_bh, mi) * 100)) +")", bgcolor = m_color)