ダイナミック 3 移動平均トレンドフォロー戦略


作成日: 2024-02-23 12:07:11 最終変更日: 2024-02-23 12:07:11
コピー: 1 クリック数: 600
1
フォロー
1617
フォロワー

ダイナミック 3 移動平均トレンドフォロー戦略

概要

動的三均線トレンド追跡策略は,複数の時間周期の動的平滑移動平均を使用して,市場トレンドを識別し,異なる時間周期間のトレンド一致性フィルタリングを実現し,取引信号の信頼性を向上させる.

戦略原則

この戦略は,3つの異なるパラメータの設定の動的平滑移動平均を使用している.最初の移動平均は,現在の周期価格の傾向方向を計算し,第二の移動平均は,より高い時間周期価格の傾向方向を計算し,第三の移動平均は,より高い時間周期価格の傾向方向を計算している.最初の移動平均が,第2の移動平均を上方へ横断すると買入シグナルが生み出され,第3の移動平均も上昇傾向を示し,買入シグナルの信頼性を検証している.

移動平均は,動的平滑機能を使用し,異なる時間周期の間に適切な平滑因子を自動的に計算し,適用することができ,その結果,高時間周期の移動平均は,低時間周期のグラフで形な折り線ではなく,流動的なトレンドラインを表示します.この動的平滑は,戦略が高時間周期で全体的なトレンドの方向を判断できる一方で,低時間周期で取引を実行し,効率的なトレンド追跡を実現します.

戦略的優位性

この戦略の最大の利点は,複数の時間枠のトレンドフィルタリングメカニズムにある.異なる時間周期の価格の平均トレンド方向を計算し,異なる周期間の一致性を要求することにより,取引信号に対する短期価格変動の vieleityの干渉を効果的にフィルタリングすることができ,各取引信号が大トレンドの中に置かれることを保証し,それによって率を大幅に向上させることができる.

もう一つの優点は,動的平滑機能の適用である.これは,戦略が同時に,高時間周期の全体的な傾向と,低時間周期の特定の取引ポイントを識別することを可能にする.戦略は,高時間周期で大トレンドの方向を決定しながら,低時間周期で特定の取引を実行することができる.この多時間枠の使用は,市場機会を把握しながら,取引リスクを制御するのに役立ちます.

リスクと最適化

この戦略の主なリスクは,取引シグナルが少ないことにある. 厳しいトレンドフィルタリング条件は取引機会の数を減少させるが,これは高周波取引を追求する一部の投資家にあまり適していないかもしれない. フィルタリング条件の厳格性を低下させることで,より多くの取引機会を得ることができる.

さらに,パラメータ設定は,特に移動平均の周期長さの最適化に注意深くテストする必要があります.異なる市場では,最適な効果を得るには,異なる周期パラメータを設定する必要があります.最適のパラメータの組み合わせは,反射で探すことができます.

将来の最適化方向は,フィルターに技術指標を追加したり,機械学習アルゴリズムの自動最適化パラメータを追加したりすることも考えられます. これらは,戦略の効果を高める効果的な方法になります.

要約する

この戦略は,全体的に非常に実用的なトレンド追跡戦略である.マルチタイムフレームのトレンドフィルターの仕組みは,各取引の決定に良好な大方向サポートを提供し,取引リスクを効果的に軽減する.ダイナミック・スムージング機能の追加は,このマルチタイムフレームの方法を効率的に実行できるようにする.

ストラテジーソースコード
/*backtest
start: 2024-01-23 00:00:00
end: 2024-02-22 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Harrocop

//@version=5
strategy(title = "Triple MA HTF strategy - Dynamic Smoothing", shorttitle = "Triple MA strategy", overlay=true, 
         pyramiding=5, initial_capital = 10000,
         calc_on_order_fills=false,
         slippage = 0,
         commission_type=strategy.commission.percent, commission_value=0.05)

//////////////////////////////////////////////////////
//////////         Risk Management        ////////////
//////////////////////////////////////////////////////
RISKM = "-------------------- Risk Management  --------------------"
InitialBalance = input.float(defval = 10000, title = "Initial Balance", minval = 1, maxval = 1000000, step = 1000, tooltip = "starting capital", group = RISKM)
LeverageEquity = input.bool(defval = true, title = "qty based on equity %", tooltip = "true turns on MarginFactor based on equity, false gives fixed qty for positionsize", group = RISKM)
MarginFactor = input.float(0, minval = - 0.9, maxval = 100, step = 0.1, tooltip = "Margin Factor, meaning that 0.5 will add 50% extra capital to determine ordersize quantity, 0.0 means 100% of equity is used to decide quantity of instrument", inline = "qty", group = RISKM)
QtyNr = input.float(defval = 3.5, title = "Quantity Contracts", minval = 0, maxval = 1000000, step = 0.01,  tooltip = "Margin Factor, meaning that 0.5 will add 50% extra capital to determine ordersize quantity, 0.0 means 100% of equity is used to decide quantity of instrument", inline = "qty", group = RISKM)
EquityCurrent = InitialBalance + strategy.netprofit[1]
QtyEquity = EquityCurrent * (1 + MarginFactor) / close[1]
QtyTrade = LeverageEquity ? QtyEquity : QtyNr

/////////////////////////////////////////////////////
//////////       MA Filter Trend         ////////////
/////////////////////////////////////////////////////
TREND = "-------------------- Moving Average 1 --------------------"
Plot_MA = input.bool(true, title = "Plot MA trend?", inline = "Trend1", group = TREND)
TimeFrame_Trend = input.timeframe(title='Higher Time Frame', defval='15', inline = "Trend1", group = TREND)
length = input.int(21, title="Length MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend2", group = TREND)
MA_Type  = input.string(defval="McGinley" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type:", inline = "Trend2", group = TREND)

ma(type, src, length) =>
    float result = 0
    if type == 'TMA' // Triangular Moving Average
        result := ta.sma(ta.sma(src, math.ceil(length / 2)), math.floor(length / 2) + 1)
        result
    if type == 'LSMA' // Least Squares Moving Average
        result := ta.linreg(src, length, 0)
        result
    if type == 'SMA'  // Simple Moving Average
        result := ta.sma(src, length)
        result
    if type == 'EMA'  // Exponential Moving Average
        result := ta.ema(src, length)
        result
    if type == 'DEMA'  // Double Exponential Moving Average
        e = ta.ema(src, length)
        result := 2 * e - ta.ema(e, length)
        result
    if type == 'TEMA'  // Triple Exponentiale
        e = ta.ema(src, length)
        result := 3 * (e - ta.ema(e, length)) + ta.ema(ta.ema(e, length), length)
        result
    if type == 'WMA'  // Weighted Moving Average
        result := ta.wma(src, length)
        result
    if type == 'HMA'  // Hull Moving Average
        result := ta.wma(2 * ta.wma(src, length / 2) - ta.wma(src, length), math.round(math.sqrt(length)))
        result
    if type == 'McGinley' // McGinley Dynamic Moving Average
        mg = 0.0
        mg := na(mg[1]) ? ta.ema(src, length) : mg[1] + (src - mg[1]) / (length * math.pow(src / mg[1], 4))
        result := mg
        result
    result

// Moving Average
MAtrend = ma(MA_Type, close, length)
MA_Value_HTF = request.security(syminfo.tickerid, TimeFrame_Trend, MAtrend)

// Get minutes for current and higher timeframes
// Function to convert a timeframe string to its equivalent in minutes
timeframeToMinutes(tf) =>
    multiplier = 1
    if (str.endswith(tf, "D"))
        multiplier := 1440
    else if (str.endswith(tf, "W"))
        multiplier := 10080
    else if (str.endswith(tf, "M"))
        multiplier := 43200
    else if (str.endswith(tf, "H"))
        multiplier := int(str.tonumber(str.replace(tf, "H", "")))
    else
        multiplier := int(str.tonumber(str.replace(tf, "m", "")))
    multiplier

// Get minutes for current and higher timeframes
currentTFMinutes = timeframeToMinutes(timeframe.period)
higherTFMinutes = timeframeToMinutes(TimeFrame_Trend)

// Calculate the smoothing factor
dynamicSmoothing = math.round(higherTFMinutes / currentTFMinutes)
MA_Value_Smooth = ta.sma(MA_Value_HTF, dynamicSmoothing)

// Trend HTF
UP = MA_Value_Smooth > MA_Value_Smooth[1] // Use "UP" Function to use as filter in combination with other indicators
DOWN = MA_Value_Smooth < MA_Value_Smooth[1] // Use "Down" Function to use as filter in combination with other indicators

/////////////////////////////////////////////////////
//////////       Second MA Filter Trend   ///////////
/////////////////////////////////////////////////////
TREND2 = "-------------------- Moving Average 2 --------------------"
Plot_MA2 = input.bool(true, title = "Plot Second MA trend?", inline = "Trend3", group = TREND2)
TimeFrame_Trend2 = input.timeframe(title='HTF', defval='60', inline = "Trend3", group = TREND2)
length2 = input.int(21, title="Length Second MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend4", group = TREND2)
MA_Type2  = input.string(defval="McGinley" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type:", inline = "Trend4", group = TREND2)

// Second Moving Average
MAtrend2 = ma(MA_Type2, close, length2)
MA_Value_HTF2 = request.security(syminfo.tickerid, TimeFrame_Trend2, MAtrend2)

// Get minutes for current and higher timeframes
higherTFMinutes2 = timeframeToMinutes(TimeFrame_Trend2)

// Calculate the smoothing factor for the second moving average
dynamicSmoothing2 = math.round(higherTFMinutes2 / currentTFMinutes)
MA_Value_Smooth2 = ta.sma(MA_Value_HTF2, dynamicSmoothing2)

// Trend HTF for the second moving average
UP2 = MA_Value_Smooth2 > MA_Value_Smooth2[1]
DOWN2 = MA_Value_Smooth2 < MA_Value_Smooth2[1]

/////////////////////////////////////////////////////
//////////       Third MA Filter Trend    ///////////
/////////////////////////////////////////////////////
TREND3 = "-------------------- Moving Average 3 --------------------"
Plot_MA3 = input.bool(true, title = "Plot third MA trend?", inline = "Trend5", group = TREND3)
TimeFrame_Trend3 = input.timeframe(title='HTF', defval='240', inline = "Trend5", group = TREND3)
length3 = input.int(50, title="Length third MA", minval=1, tooltip = "Number of bars used to measure trend on higher timeframe chart", inline = "Trend6", group = TREND3)
MA_Type3  = input.string(defval="McGinley" , options=["EMA","DEMA","TEMA","SMA","WMA", "HMA", "McGinley"], title="MA type:", inline = "Trend6", group = TREND3)

// Second Moving Average
MAtrend3 = ma(MA_Type3, close, length3)
MA_Value_HTF3 = request.security(syminfo.tickerid, TimeFrame_Trend3, MAtrend3)

// Get minutes for current and higher timeframes
higherTFMinutes3 = timeframeToMinutes(TimeFrame_Trend3)

// Calculate the smoothing factor for the second moving average
dynamicSmoothing3 = math.round(higherTFMinutes3 / currentTFMinutes)
MA_Value_Smooth3 = ta.sma(MA_Value_HTF3, dynamicSmoothing3)

// Trend HTF for the second moving average
UP3 = MA_Value_Smooth3 > MA_Value_Smooth3[1]
DOWN3 = MA_Value_Smooth3 < MA_Value_Smooth3[1]

/////////////////////////////////////////////////////
//////////         Entry Settings        ////////////
/////////////////////////////////////////////////////
BuySignal = ta.crossover(MA_Value_HTF, MA_Value_HTF2) and UP3 == true
SellSignal = ta.crossunder(MA_Value_HTF, MA_Value_HTF2) and DOWN3 == true
ExitBuy = ta.crossunder(MA_Value_HTF, MA_Value_HTF2)
ExitSell = ta.crossover(MA_Value_HTF, MA_Value_HTF2)

/////////////////////////////////////////////////
///////////       Strategy       ////////////////
///////////      Entry & Exit    ////////////////
///////////         logic        ////////////////
/////////////////////////////////////////////////
// Long
if BuySignal
    strategy.entry("Long", strategy.long, qty = QtyTrade)

if (strategy.position_size > 0 and ExitBuy == true)
    strategy.close(id = "Long", comment = "Close Long")

// Short
if SellSignal
    strategy.entry("Short", strategy.short, qty = QtyTrade)

if (strategy.position_size < 0 and ExitSell == true)
    strategy.close(id = "Short", comment = "Close Short")

/////////////////////////////////////////////////////
//////////         Visuals Chart         ////////////
/////////////////////////////////////////////////////
// Plot Moving Average HTF
p1 = plot(Plot_MA ? MA_Value_Smooth : na, "HTF Trend", color = UP ? color.rgb(238, 255, 0) : color.rgb(175, 173, 38), linewidth = 1, style = plot.style_line)
p2 = plot(Plot_MA2 ? MA_Value_Smooth2 : na, "HTF Trend", color = UP2 ? color.rgb(0, 132, 255) : color.rgb(0, 17, 255), linewidth = 1, style = plot.style_line)
plot(Plot_MA3 ? MA_Value_Smooth3 : na, "HTF Trend", color = UP3 ? color.rgb(0, 255, 8) : color.rgb(255, 0, 0), linewidth = 2, style = plot.style_line)
fill(p1, p2, color = color.rgb(255, 208, 0, 90), title="Fill")