Trendhandelsstrategie auf Basis eines gleitenden Durchschnitts

Schriftsteller:ChaoZhang, Datum: 2023-10-30 15:53:25
Tags:

img

Übersicht

Diese Strategie verwendet ein gleitendes Durchschnittssystem, um die aktuelle Trendrichtung zu bestimmen, und macht Long- oder Short-Positionen entsprechend dem Trend. Wenn der gleitende Durchschnitt steigt, ist das Vertrauen in Long höher, also gehen Sie lang. Wenn der gleitende Durchschnitt sinkt, ist das Vertrauen in Short höher, also gehen Sie kurz. Diese Strategie verwendet hauptsächlich das gleitende Durchschnittssystem, um die Markttrendrichtung zu bestimmen, die zur Trendfolgestrategie gehört.

Strategie Logik

  1. Der gewichtete gleitende Durchschnitt vwma wird als gleitender Durchschnittsindikator für einen bestimmten Zeitraum berechnet (Standard 400 Perioden).

  2. Bestimmen Sie, ob der gleitende Durchschnitt vwma steigt, wenn steigt, setzen Sie den langen Signal-Aufwärtstrend ein; wenn er fällt, setzen Sie den kurzen Signal-Abwärtstrend ein.

  3. Wenn der Aufwärtstrend wahr ist, gehen Sie lang; wenn der Abwärtstrend wahr ist, schließen Sie lang und gehen Sie kurz.

  4. Berechnen Sie die Strategie return bar_pnl und buy & hold return bar_bh für jeden Balken.

  5. Nach den vierteljährlichen und jährlichen Zeitstempeln berechnen Sie die vierteljährliche Strategierendite quarter_pnl, die jährliche Rendite year_pnl und die entsprechenden Buy & Hold Renditen quarter_bh, year_bh.

  6. Die vierteljährliche Strategierendite gegenüber der Buy & Hold Rendite in einer Tabelle anzeigen.

Analyse der Vorteile

Die wichtigsten Vorteile dieser Strategie sind:

  1. Einfache Bedienung, leicht verständliche Bestimmung der Marktentwicklung durch gleitende Durchschnitte.

  2. Der Trend zu folgen reduziert Verluste auf nicht-trendigen Märkten.

  3. Wenige einstellbare Parameter, hauptsächlich die Periode des gleitenden Durchschnitts, leicht zu testen und zu optimieren.

  4. Intuitive Rücklauftabelle, um die Ergebnisse deutlich zu zeigen.

  5. Hinzufügen der Buy & Hold Rendite in der Tabelle zum Vergleich, zeigt die überschüssige Rendite.

  6. Flexible Tischposition, leicht mit anderen Strategien zu integrieren.

Risikoanalyse

Es gibt auch einige Risiken:

  1. Unterleistung im langfristigen Bullenmarkt im Vergleich zu Buy & Hold. Kann die gleitende Durchschnittsperiode optimieren.

  2. Ein hohes Whipsaw-Risiko im Range-bound Markt kann Filterbedingungen hinzufügen, wie das Brechen des vorherigen Hochs, um Transaktionen zu reduzieren.

  3. Der gleitende Durchschnitt hat eine schlechte Fähigkeit zur Kurvenanpassung, kann Trendwendepunkte verpassen.

  4. Es gibt keinen Stop-Loss-Mechanismus, es besteht ein hohes Risiko für einen Rückzug.

  5. Für die Tabelle kann man Risikometriken wie Sharpe Ratio, Max Drawdown hinzufügen.

Optimierungsrichtlinien

Die Strategie kann in folgenden Aspekten optimiert werden:

  1. Optimierung der gleitenden Durchschnittsparameter, Anpassung der Periode anhand der Marktregeln.

  2. Fügen Sie Filter hinzu, wie das vorherige Hoch zu brechen, um Whipsaws zu reduzieren.

  3. Versuchen Sie verschiedene Arten von gleitenden Durchschnitten, wie WMA, DEMA usw.

  4. Fügen Sie Stop-Loss-Mechanismen hinzu, wie dynamische Stopps oder Positionsgrößen.

  5. Die Tabelleninhalte bereichern, Metriken wie Schärfe, maximale Auslastung hinzufügen.

  6. Kombinieren Sie mit anderen Indikatoren wie MACD, Bollinger Bands, um Trends zu bestimmen.

  7. Optimierung der Positionsgröße, dynamische Anpassung der Positionen anhand der Marktbedingungen.

  8. Versuche mit verschiedenen Produkten, finde den besten Anwendungsbereich.

Schlussfolgerung

Die gleitende Durchschnittshandelsstrategie ist relativ einfach und unkompliziert. Sie folgt dem Trend, indem sie den Trend mit einem gleitenden Durchschnittswert bestimmt, mit guter Ziehkontrolle, geeignet für Trend-nachfolgende Händler. Es gibt immer noch viel Raum für Optimierungen, wie das gleitende Durchschnittssystem, Stop-Loss-Mechanismus, Positionsgröße usw., um es an komplexe Marktumgebungen anzupassen. Das Tabellendesign vergleicht die Strategierendite mit Buy & Hold und zeigt die überschüssigen Renditen intuitiv. Der Rahmen und das Tabellendesign dieser Strategie können für quantitative Händler eine gute Referenz bieten.


/*backtest
start: 2022-10-23 00:00:00
end: 2023-10-29 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/
// © Dannnnnnny

//@version=4
strategy(title="Quarterly Returns in Strategies vs Buy & Hold", 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")//

///////////////////
// QUARTERLY TABLE //
enableQuarterlyTable = input(title="Enable Quarterly Return table", type=input.bool, defval=false)
enableCompareWithMarket = input(title="Compare with Market Benchmark", type=input.bool, defval=false)
table_position = input(title="Table Position", type=input.string, defval='bottom_right', options=['bottom_right','bottom_left','top_right', 'top_left'])
precision = 2
new_quarter = ceil(month(time)/3)  != ceil(month(time[1])/3)
new_year  = year(time)  != year(time[1])

eq = strategy.equity

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

cur_quarter_pnl = 0.0
cur_year_pnl  = 0.0
cur_quarter_bh = 0.0
cur_year_bh  = 0.0

// Current Quarterly P&L
cur_quarter_pnl := new_quarter ? 0.0 : 
                 (1 + cur_quarter_pnl[1]) * (1 + bar_pnl) - 1 
cur_quarter_bh := new_quarter ? 0.0 : 
                 (1 + cur_quarter_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 Quarterly P&Ls
var quarter_pnl  = array.new_float(0)
var quarter_time = array.new_int(0)
var quarter_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)

end_time = false

end_time:= time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory

if (not na(cur_quarter_pnl[1]) and (new_quarter or end_time))
    if (end_time[1])
        array.pop(quarter_pnl)
        array.pop(quarter_time)
        
    array.push(quarter_pnl , cur_quarter_pnl[1])
    array.push(quarter_time, time[1])
    array.push(quarter_bh , cur_quarter_bh[1])

if (not na(cur_year_pnl[1]) and (new_year or end_time))
    if (end_time[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])

// Quarterly P&L Table    
var quarterly_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 or pnl < 2 * bh
            color.new(color.red, transp = 20)
        else if pnl < bh
            color.new(color.red, transp = 50)
        else
            color.new(color.red, transp = 80)

if (end_time and enableQuarterlyTable)
    quarterly_table := table.new(table_position, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)

    table.cell(quarterly_table, 0,  0, "",     bgcolor = #cccccc)
    table.cell(quarterly_table, 1,  0, "Q1",  bgcolor = #cccccc)
    table.cell(quarterly_table, 2,  0, "Q2",  bgcolor = #cccccc)
    table.cell(quarterly_table, 3,  0, "Q3",  bgcolor = #cccccc)
    table.cell(quarterly_table, 4,  0, "Q4",  bgcolor = #cccccc)
    table.cell(quarterly_table, 5,  0, "Year", bgcolor = #999999)


    for yi = 0 to array.size(year_pnl) - 1
        table.cell(quarterly_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(quarterly_table, 5, yi + 1, enableCompareWithMarket ? tostring(round(array.get(year_pnl, yi) * 100, precision)) + " (" + tostring(round(array.get(year_bh, yi) * 100, precision)) + ")" : tostring(round(array.get(year_pnl, yi) * 100, precision)), bgcolor = y_color, text_color=#bfbfbf)
        
    for mi = 0 to array.size(quarter_time) - 1
        m_row   = year(array.get(quarter_time, mi))  - year(array.get(year_time, 0)) + 1
        m_col   = ceil(month(array.get(quarter_time, mi)) / 3)
        m_color = getCellColor(array.get(quarter_pnl, mi), array.get(quarter_bh, mi))
        
        table.cell(quarterly_table, m_col, m_row, enableCompareWithMarket ?  tostring(round(array.get(quarter_pnl, mi) * 100, precision)) + " (" + tostring(round(array.get(quarter_bh, mi) * 100,precision)) +")" : tostring(round(array.get(quarter_pnl, mi) * 100, precision)), bgcolor = m_color, text_color=#bfbfbf)

Mehr