이중 이동 평균 거래 전략

저자:차오장, 날짜: 2023-12-01 14:36:33
태그:

img

전반적인 설명

이중 이동 평균 거래 전략은 빠른 EMA와 느린 EMA를 형성하기 위해 서로 다른 시간 프레임의 기하급수적인 이동 평균 (EMA) 을 계산하고 금색 십자가와 죽음의 십자가를 관찰하여 거래 신호를 생성합니다. 빠른 EMA가 느린 EMA를 넘을 때 길게 이동하고 빠른 EMA가 느린 EMA를 넘을 때 짧게 이동합니다. 이 전략은 이동 평균의 트렌드 역전 지점을 캡처하고 일반적으로 트렌드를 따르는 전략입니다.

전략 논리

이중 이동 평균 전략의 핵심 지표는 빠른 EMA와 느린 EMA입니다. 빠른 EMA는 12 일 기본 매개 변수를 가지고 있으며 느린 EMA는 26 일 기본 매개 변수를 가지고 있습니다. 기하급수적인 이동 평균의 공식은:

EMA (t) = (C (t) - EMA (t-1)) x SF + EMA (t-1)

여기서 C (t) 는 오늘의 종료 가격이고 SF는 평형 요인입니다. 단순한 이동 평균과 달리 EMA는 최근 데이터에 더 많은 무게를 부여하고 따라서 가격 변화에 더 빠르게 반응합니다.

거래 규칙은 다음과 같습니다.

  • 빠른 EMA의 황금색 십자 위에 느린 EMA를 넘어선 긴 포지션을 입력합니다.

  • 상위에서 느린 EMA 아래로 빠른 EMA를 통과하는 죽음의 교차점에 짧은 포지션을 입력합니다.

  • EMA의 오차에 대한 출구 지점

EMA의 크로스오버 패턴을 포착함으로써 시장 동향을 반영하고 수익성을 높일 수 있습니다.

장점

성숙한 기술 지표 전략으로서 이중 이동 평균 전략은 다음과 같은 강점을 가지고 있습니다.

  1. 그 논리는 명확하고 이해하기 쉽고 적용하기 쉽습니다.

  2. 그것은 시장의 수요와 공급에 대해 매우 정확한 판단을 제공합니다. 따라서 상대적으로 높은 승률을 가지고 있습니다.

  3. 시장 소음을 효과적으로 필터링하고 주요 추세를 포착합니다.

  4. 그것은 다양한 도구와 시간 프레임에 적용될 수 있습니다.

  5. 이는 전략 부양을 위한 다른 지표와 결합될 수 있습니다.

  6. 큰 자본 거래에 높은 자본 활용 효율을 가지고 있습니다.

위험 분석

이 전략에는 몇 가지 한계도 있습니다.

  1. 시장의 급격한 파업과 같은 시장 움직임에 반응하지 못합니다.

  2. 그것은 종종 잘못된 신호를 생성하는 경향이 있고 옆으로 범위를 제한하는 시장에서 휘프사입니다.

  3. 그 매개 변수들은 다양한 시장과 기간에 최적화되어야 합니다.

  4. 그것은 트렌드의 적절한 반전 수준을 결정할 수 없습니다.

이 위험은 EMA 기간을 조정하고 추가 필터를 추가하여 전략을 더 견고하게 함으로써 감소시킬 수 있습니다.

더 나은 기회

이중 이동 평균 전략은 다음 측면으로 개선 될 수 있습니다.

  1. 트렌드 강도를 판단하고 잘못된 거래를 피하기 위해 MACD 지표를 포함합니다.

  2. 실제 브레이크오웃 신호를 확인하기 위해 거래량을 추가합니다.

  3. 볼링거 밴드, 촛불 패턴과 결합하여 보다 정확한 입출입 규칙을 얻습니다.

  4. 더 나은 적응력을 위해 LSTM와 같은 기계 학습 접근 방식을 사용하여 매개 변수를 자동으로 최적화합니다.

결론

이중 이동 평균 거래 전략은 EMA 황금 십자와 죽음의 십자에서 트렌드 반전 지점을 결정하기 위해 거래 기회를 캡처합니다. 단순성, 자본 효율성 및 구현 용이성의 장점으로 알고리즘 거래 초보자에게 선호되는 선택입니다. 그러나 잘못된 신호를 생성하는 것과 같은 특정 결함이 있습니다. 특정 시장과 환경에 최적화하기 위해 더 많은 지표를 도입해야합니다. 전반적으로 볼 때 매우 실용적이고 유용한 기술 지표 전략입니다.


/*backtest
start: 2022-11-24 00:00:00
end: 2023-11-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © antondmt

//@version=5
strategy("Returns & Drawdowns Table", "R & DD", true, calc_on_every_tick = false, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, process_orders_on_close = true)
i_eq_to_dd =            input.string("Compound Equity", "Mode", ["Simple Equity", "Compound Equity", "Drawdown"], group = "R & DD Table")
i_precision =           input.int(2, "Return Precision", group = "R & DD Table")
i_headers_col =         input.color(#D4D4D4, "Headers Color", group = "R & DD Table")
i_headers_text_col =    input.color(color.black, "Headers Text Color", group = "R & DD Table")
i_pos_col =             input.color(color.green, "Positive Color", group = "R & DD Table")
i_neg_col =             input.color(color.red, "Negative Color", group = "R & DD Table")
i_zero_col =            input.color(#DDDDDD, "Zero Color", group = "R & DD Table")
i_cell_text_col =       input.color(color.white, "Cell Text Color", group = "R & DD Table")

// TIME {
var month_times = array.new_int(0)                                                              // Array of all month times  
new_month = month(time) != month(time[1]) 
if(new_month or barstate.isfirst)
    array.push(month_times, time)

var year_times = array.new_int(0)                                                               
new_year = year(time) != year(time[1])  
if (new_year or barstate.isfirst)
    array.push(year_times, time)
//}

// SIMPLE EQUITY CALCULATIONS {
// Simple equity is strictly calculated from start to end of each month/year equity. There is no compound
var monthly_simp_pnls = array.new_float(0)                                                      // Array of all monthly profits and losses
var yearly_simp_pnls = array.new_float(0)                                                       

if(i_eq_to_dd == "Simple Equity")
    var initial_monthly_equity = strategy.equity                                                // Starting equity for each month
    cur_month_pnl = nz((strategy.equity - initial_monthly_equity) / initial_monthly_equity)     // Current month's equity change
    if(new_month or barstate.isfirst)
        initial_monthly_equity := strategy.equity
        array.push(monthly_simp_pnls, cur_month_pnl)
    else 
        array.set(monthly_simp_pnls, array.size(monthly_simp_pnls) - 1, cur_month_pnl)
    
    var initial_yearly_equity = strategy.equity
    cur_year_pnl = nz((strategy.equity - initial_yearly_equity) / initial_yearly_equity)
    if (new_year or barstate.isfirst)
        initial_yearly_equity := strategy.equity
        array.push(yearly_simp_pnls, cur_year_pnl)
    else 
        array.set(yearly_simp_pnls, array.size(yearly_simp_pnls) - 1, cur_year_pnl)
// }

// COMPOUND EQUITY CALCULATIONS {
// Compound equity is strictly calculated based on equity state from the beginning of time until the end of each month/year equity. It shows the exact equity movement through time
var monthly_comp_pnls = array.new_float(0)                                                      // Array of all monthly profits and losses
var yearly_comp_pnls = array.new_float(0)                                                       

if(i_eq_to_dd == "Compound Equity")
    var initial_equity = strategy.equity                                                
    cur_month_pnl = nz((strategy.equity - initial_equity) / initial_equity)                     // Current month's equity change
    if(new_month or barstate.isfirst)
        array.push(monthly_comp_pnls, cur_month_pnl)
    else 
        array.set(monthly_comp_pnls, array.size(monthly_comp_pnls) - 1, cur_month_pnl)
    
    cur_year_pnl = nz((strategy.equity - initial_equity) / initial_equity)
    if (new_year or barstate.isfirst)
        array.push(yearly_comp_pnls, cur_year_pnl)
    else 
        array.set(yearly_comp_pnls, array.size(yearly_comp_pnls) - 1, cur_year_pnl)
// }
    
// DRAWDOWN CALCULATIONS {
// Drawdowns are calculated from highest equity to lowest trough for the month/year
var monthly_dds = array.new_float(0)                                                            // Array of all monthly drawdowns
var yearly_dds = array.new_float(0)                                                             

if (i_eq_to_dd == "Drawdown")
    total_equity = strategy.equity - strategy.openprofit                        
    
    var cur_month_dd = 0.0  
    var m_ATH = total_equity                                                                    // Monthly All-Time-High (ATH). It is reset each month
    m_ATH := math.max(total_equity, nz(m_ATH[1]))
    m_drawdown = -math.abs(total_equity / m_ATH * 100 - 100) / 100                              // Drawdown at current bar
    if(m_drawdown < cur_month_dd)
        cur_month_dd := m_drawdown
    if(new_month or barstate.isfirst)
        cur_month_dd := 0.0
        m_ATH := strategy.equity - strategy.openprofit
        array.push(monthly_dds, 0)
    else 
        array.set(monthly_dds, array.size(monthly_dds) - 1, cur_month_dd)
    
    var cur_year_dd = 0.0
    var y_ATH = total_equity
    y_ATH := math.max(total_equity, nz(y_ATH[1]))
    y_drawdown = -math.abs(total_equity / y_ATH * 100 - 100) / 100
    if(y_drawdown < cur_year_dd)
        cur_year_dd := y_drawdown
    if (new_year or barstate.isfirst)
        cur_year_dd := 0.0
        y_ATH := strategy.equity - strategy.openprofit
        array.push(yearly_dds, 0)
    else 
        array.set(yearly_dds, array.size(yearly_dds) - 1, cur_year_dd) 
// }

// TABLE LOGIC { 
var main_table = table(na)
table.clear(main_table, 0, 0, 13, new_year ? array.size(year_times) - 1 : array.size(year_times))
main_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_times) + 1, border_width = 1)

t_set_headers() =>                                                                              // Sets time headers of the table
    // Set month headers
    table.cell(main_table, 0,  0, "",     text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 1,  0, "Jan",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 2,  0, "Feb",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 3,  0, "Mar",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 4,  0, "Apr",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 5,  0, "May",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 6,  0, "Jun",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 7,  0, "Jul",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 8,  0, "Aug",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 9,  0, "Sep",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 10, 0, "Oct",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 11, 0, "Nov",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 12, 0, "Dec",  text_color = i_headers_text_col, bgcolor = i_headers_col)
    table.cell(main_table, 13, 0, str.tostring(i_eq_to_dd), text_color = i_headers_text_col, bgcolor = i_headers_col)

    // Set year headers
    for i = 0 to array.size(year_times) - 1
        table.cell(main_table, 0,  i + 1, str.tostring(year(array.get(year_times, i))), text_color = i_headers_text_col, bgcolor = i_headers_col)

t_set_months() =>                                                                               // Sets inner monthly data of the table
    display_array = switch i_eq_to_dd 
        "Simple Equity" => monthly_simp_pnls 
        "Compound Equity" => monthly_comp_pnls
        => monthly_dds
    for i = 0 to array.size(month_times) - 1
        m_row = year(array.get(month_times, i)) - year(array.get(year_times, 0)) + 1
        m_col = month(array.get(month_times, i)) 
        m_color = array.get(display_array, i) == 0 ? color.new(i_zero_col, transp = 30) : array.get(display_array, i) > 0 ? color.new(i_pos_col, transp = 30) : color.new(i_neg_col, transp = 30)
        table.cell(main_table, m_col, m_row, str.tostring(math.round(array.get(display_array, i) * 100, i_precision)), bgcolor = m_color, text_color = i_cell_text_col)
        
t_set_years() =>                                                                                // Sets inner yearly data of the table
    display_array = switch i_eq_to_dd 
        "Simple Equity" => yearly_simp_pnls 
        "Compound Equity" => yearly_comp_pnls
        => yearly_dds
    for i = 0 to array.size(year_times) - 1
        y_color = array.get(display_array, i) == 0 ? color.new(i_zero_col, transp = 30) : array.get(display_array, i) > 0 ? color.new(i_pos_col, transp = 20) : color.new(i_neg_col, transp = 20)
        table.cell(main_table, 13, i + 1, str.tostring(math.round(array.get(display_array, i) * 100, i_precision)), bgcolor = y_color, text_color = i_cell_text_col)

t_set_headers() 
t_set_months()
t_set_years()
// }

// PLACE YOUR STRATEGY CODE HERE {
// This is a sample code of a working strategy to show the table in action
fastLength = input(12)
slowlength = input(26)
MACDLength = input(9)
MACD = ta.ema(close, fastLength) - ta.ema(close, slowlength)
aMACD = ta.ema(MACD, MACDLength)
delta = MACD - aMACD
if (ta.crossover(delta, 0))
	strategy.entry("MacdLE", strategy.long, comment = "MacdLE")
if (ta.crossunder(delta, 0))
	strategy.entry("MacdSE", strategy.short, comment = "MacdSE")
// }

더 많은