Handelsstrategie mit doppelten gleitenden Durchschnitten

Schriftsteller:ChaoZhang, Datum: 2023-12-01 14:36:33
Tags:

img

Übersicht

Die doppelte gleitende Durchschnittshandelsstrategie erzeugt Handelssignale, indem sie exponentielle gleitende Durchschnitte (EMAs) verschiedener Zeitrahmen berechnet, um einen schnellen EMA und einen langsamen EMA zu bilden, und ihre goldenen Kreuzungen und Todeskreuzungen beobachtet. Sie geht lang, wenn die schnelle EMA über die langsame EMA überschreitet, und geht kurz, wenn die schnelle EMA unter die langsame EMA überschreitet. Diese Strategie erfasst die Trendumkehrpunkte der gleitenden Durchschnitte und ist eine häufig verwendete Trendfolgungsstrategie.

Strategie Logik

Die Kernindikatoren der doppelten gleitenden Durchschnittsstrategie sind die schnelle EMA und die langsame EMA. Die schnelle EMA hat einen Standardparameter von 12 Tagen, während die langsame EMA einen Standardparameter von 26 Tagen hat. Die Formel für den exponentiellen gleitenden Durchschnitt lautet:

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

Die EMA-Werte werden von den jeweiligen Preisen der einzelnen Länder ermittelt, wobei C (t) der heutige Schlusskurs und SF der Gleitfaktor ist.

Die Handelsregeln sind:

  • Eintritt in Longpositionen auf dem goldenen Kreuz der schnellen EMA, die von unten über die langsame EMA geht.

  • Eintritt in Short-Positionen auf dem Todeskreuz einer schnellen EMA, die unterhalb der langsamen EMA von oben kreuzt.

  • Ausgangspositionen bei Divergenz der EMA.

Durch die Erfassung der Crossover-Muster der EMAs kann sie die Marktentwicklung widerspiegeln und die Rentabilität steigern.

Vorteile

Als ausgereifte Strategie für technische Indikatoren weist die doppelte gleitende Durchschnittsstrategie folgende Stärken auf:

  1. Ihre Logik ist klar und leicht zu verstehen und umzusetzen.

  2. Es gibt eine sehr genaue Einschätzung von Angebot und Nachfrage auf dem Markt und hat somit eine relativ hohe Gewinnrate.

  3. Sie filtert effektiv Marktlärm und erfasst die wichtigsten Trends.

  4. Sie kann über verschiedene Instrumente und Zeitrahmen hinweg angewendet werden.

  5. Sie kann mit anderen Indikatoren für die Strategie der Anreicherung kombiniert werden.

  6. Es verfügt über eine hohe Kapitalnutzungseffizienz für den Großkapitalhandel.

Risikoanalyse

Die Strategie hat auch bestimmte Grenzen:

  1. Es reagiert nicht auf intensive Marktbewegungen wie starke Verkaufsrückgänge auf dem Bärenmarkt.

  2. Es neigt dazu, häufige falsche Signale und Whipsaws in seitlichen Bereichsmärkten zu erzeugen.

  3. Die Parameter müssen für verschiedene Märkte und Zeitrahmen optimiert werden.

  4. Sie kann keine angemessenen Umkehrungsniveaus für den Trend ermitteln.

Die Risiken können durch Anpassung der EMA-Perioden, Hinzufügung zusätzlicher Filter usw. gemildert werden, um die Strategie robuster zu gestalten.

Möglichkeiten zur Verbesserung

Die doppelte gleitende Durchschnittsstrategie kann in folgenden Punkten verbessert werden:

  1. Einbeziehung des MACD-Indikators zur Beurteilung der Trendstärke und Vermeidung falscher Trades.

  2. Fügen Sie Handelsvolumina hinzu, um echte Breakout-Signale zu bestätigen.

  3. Kombination mit Bollinger Bands, Kerzenmustern für genauere Ein- und Ausstiegsregeln.

  4. Verwenden Sie maschinelle Lernansätze wie LSTM, um Parameter automatisch zu optimieren, um eine bessere Anpassungsfähigkeit zu erzielen.

Schlussfolgerung

Die doppelte gleitende Durchschnittshandelsstrategie erfasst Handelschancen von EMA-Goldkreuzen und Todskreuzen, um Trendumkehrpunkte für stetige Gewinne zu bestimmen. Mit den Vorteilen von Einfachheit, Kapitaleffizienz und Einfachheit der Implementierung ist sie eine bevorzugte Wahl für Anfänger des algorithmischen Handels. Aber sie hat auch bestimmte Mängel wie die Erzeugung falscher Signale. Mehr Indikatoren sollten eingeführt werden, um sie für bestimmte Märkte und Umgebungen zu optimieren. Insgesamt ist es eine sehr praktische und nützliche technische Indikatorstrategie.


/*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")
// }

Mehr