資源の読み込みに... 荷物...

エルゴティック・ダブルレール逆MACD量的な取引戦略

作者: リン・ハーンチャオチャン開催日:2023年12月21日 11:07:51
タグ:

img

概要

この戦略は,双レール逆MACD定量取引戦略である.この戦略は,ウィリアム・ブラウが彼の著書"モメンタム,ディレクション,ディバージェンス"で記述した技術指標をベースに,それらを拡張している.この戦略にはバックテスト機能も備えており,アラート,フィルター,ストップ損失を追うなどの追加機能も組み込むことができる.

原則

この戦略のコアインジケーターはMACDである.高速移動平均EMA®とスロー移動平均EMA ((slowMALen) を計算し,その後その差をxmacdを計算する.また,xmacdのEMA ((signalLength) を計算してxMA_MACDを取得する.xmacdがxMA_MACDの上を横切ると長い信号が起動し,下を横切ると短い信号が起動する.この戦略の重要な側面は逆の取引信号である.すなわち,xmacdとxMA_MACDの関係は従来のMACD指標とは対照的である.このことから,この名前も由来する.

この戦略にはトレンドフィルターも含まれている.ロングシグナルが発射されると,もしブリーッシュトレンドフィルタが設定されている場合,価格が上昇しているかどうかをチェックする.同様に,ショートシグナルが下値トレンドをチェックする.RSIおよびMFI指標もシグナルをフィルタリングするために使用できる.限界を超えた損失を防ぐためにストップ損失メカニズムが含まれている.

利点分析

この戦略の最大の利点は,強力なバックテスト機能である.さまざまな取引手段を選択し,バックテストのタイムフレームを設定し,特定の楽器データに基づいて戦略パラメータを最適化することができます.単純なMACD戦略と比較して,いくつかの同一の信号をフィルタリングするためにトレンドとオーバーバイト/オーバーセール分析を組み込む.ダブルレール逆MACDは伝統的なMACDとは異なります.従来のMACDが逃すかもしれないいくつかの機会を活用することができます.

リスク分析

この戦略の主なリスクは,逆取引論理から生じる.逆信号は,伝統的な信号が逃したいくつかの機会を捉えることができるが,従来のMACDエントリーポイントのいくつかを失うことも意味し,慎重な評価が必要である.さらに,MACD自体も偽の上昇信号を生成する傾向がある.この戦略は,不安定で方向性のない市場中に過剰な取引とコストの増加を引き起こす可能性がある.

リスクを軽減するために,パラメータを最適化できます - 移動平均の長さを調整し,トレンドとインジケーターフィルターを組み合わせると,不安定な市場のシグナルが避けられます.ストップロスの距離を上げると,個々の取引で損失を制限できます.

オプティマイゼーションの方向性

この戦略はいくつかの点で改善できる.

  1. 速いと遅いレールのパラメータを調整し,移動平均長さの最適化,特定の機器のための最適なパラメータセットを見つけるためにバックテスト
  2. トレンドフィルターを追加または調整し,バックテストの結果から,リターンを改善するかどうかを判断します
  3. 安定したまたは後続的な異なるストップ損失メカニズムをテストして,より優れたパフォーマンスを決定します.
  4. KD,ボリンジャー帯などの他の指標を組み合わせて追加フィルター条件を設定し,信号品質を確保してください

概要

デュアルレール逆MACD定量戦略は,拡張および改善によりクラシックMACD指標の上に構築されている.柔軟なパラメータ構成,豊富なフィルター選択,強力なバックテスト機能により,異なる取引手段に合わせて調整することができる.したがって,さらなる探求に値する興味深い有望な定量取引戦略である.


/*backtest
start: 2023-11-20 00:00:00
end: 2023-12-20 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version = 3
////////////////////////////////////////////////////////////
//  Copyright by HPotter v1.0 09/12/2016
// This is one of the techniques described by William Blau in his book
// "Momentum, Direction and Divergence" (1995). If you like to learn more,
// we advise you to read this book. His book focuses on three key aspects
// of trading: momentum, direction and divergence. Blau, who was an electrical
// engineer before becoming a trader, thoroughly examines the relationship 
// between price and momentum in step-by-step examples. From this grounding,
// he then looks at the deficiencies in other oscillators and introduces some
// innovative techniques, including a fresh twist on Stochastics. On directional 
// issues, he analyzes the intricacies of ADX and offers a unique approach to help 
// define trending and non-trending periods.
// Blau`s indicator is like usual MACD, but it plots opposite of meaningof
// stndard MACD indicator. 
//
// You can change long to short in the Input Settings
// Please, use it only for learning or paper trading. Do not for real trading.
//
//
// 2018-09 forked by Khalid Salomão
// - Backtesting
// - Added filters: RSI, MFI, Price trend
// - Trailing Stop Loss
// - Other minor adjustments
//
////////////////////////////////////////////////////////////
strategy(title="Ergotic MACD Backtester [forked from HPotter]", shorttitle="Ergotic MACD Backtester", overlay=true, pyramiding=0, default_qty_type=strategy.cash, default_qty_value=25000, initial_capital=50000, commission_type=strategy.commission.percent, commission_value=0.15, slippage=3)


// === BACKTESTING: INPUT BACKTEST RANGE ===
source = input(close)
strategyType = input(defval="Long Only", options=["Long & Short", "Long Only", "Short Only"])

FromMonth = input(defval = 7, title = "From Month", minval = 1, maxval = 12)
FromDay   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromYear  = input(defval = 2018, title = "From Year", minval = 2017)
ToMonth   = input(defval = 12, title = "To Month", minval = 1, maxval = 12)
ToDay     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToYear    = input(defval = 2030, title = "To Year", minval = 2017)

start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        
window()  => true // window of time verification

// === STRATEGY ===

r = input(144, minval=1, title="R (32,55,89,100,144,200)") // default 32
slowMALen = input(6, minval=1) // default 32
signalLength = input(6, minval=1)
reverse = input(false, title="Trade reverse (long/short switch)")

//hline(0, color=blue, linestyle=line)

fastMA = ema(source, r)
slowMA = ema(source, slowMALen)
xmacd = fastMA - slowMA
xMA_MACD = ema(xmacd, signalLength)

pos = 0
pos := iff(xmacd < xMA_MACD, 1,
	   iff(xmacd > xMA_MACD, -1, nz(pos[1], 0))) 
possig = 0
possig := iff(reverse and pos == 1, -1,
          iff(reverse and pos == -1, 1, pos))

// === FILTER: price trend ====
trending_price_long = input(true, title="Long only if price has increased" )
trending_price_short = input(false, title="Short only if price has decreased" )
trending_price_length = input( 2, minval=1 )
trending_price_with_ema = input( false )
trending_price_ema = input( 3, minval=1 )
price_trend = trending_price_with_ema ? ema(source, trending_price_ema) : source
priceLongTrend() => (trending_price_long ? rising(price_trend, trending_price_length) : true)
priceShortTrend() => (trending_price_short ? falling(price_trend, trending_price_length) : true)

// === FILTER: RSI ===
rsi_length = input( 14, minval=1 )
rsi_overSold = input( 14, minval=0, title="RSI Sell Cutoff (Sell only if >= #)" )
rsi_overBought = input( 82, minval=0, title="RSI Buy Cutoff (Buy only if <= #)" )

vrsi = rsi(source, rsi_length)
rsiOverbought() => vrsi > rsi_overBought
rsiOversold() => vrsi < rsi_overSold

trending_rsi_long = input(false, title="Long only if RSI has increased" )
trending_rsi_length = input( 2 )
rsiLongTrend() => trending_rsi_long ? rising(vrsi, trending_rsi_length) : true

// === FILTER: MFI ===
mfi_length = input(14, minval=1)
mfi_lower = input(14, minval=0, maxval=50)
mfi_upper = input(82, minval=50, maxval=100)
upper_s = sum(volume * (change(source) <= 0 ? 0 : source), mfi_length)
lower_s = sum(volume * (change(source) >= 0 ? 0 : source), mfi_length)
mf = rsi(upper_s, lower_s)

mfiOverbought() => (mf > mfi_upper)
mfiOversold() => (mf < mfi_lower)

trending_mfi_long = input(false, title="Long only if MFI has increased" )
trending_mfi_length = input( 2 )
mfiLongTrend() => trending_mfi_long ? rising(mf, trending_mfi_length) : true

// === SIGNAL CALCULATION ===
long  = window() and possig == 1 and rsiLongTrend() and mfiLongTrend() and not rsiOverbought() and not mfiOverbought() and priceLongTrend()
short = window() and possig == -1 and not rsiOversold() and not mfiOversold() and priceShortTrend()

// === trailing stop
tslSource=input(hlc3,title="TSL source")
//suseCurrentRes = input(true, title="Use current chart resolution for stop trigger?")
tslResolution = input(title="Use different timeframe for stop trigger? Uncheck box above.", defval="5")
tslTrigger = input(3.0) / 100
tslStop = input(0.6) / 100

currentPrice = request.security(syminfo.tickerid, tslResolution, tslSource, barmerge.gaps_off, barmerge.lookahead_off)

isLongOpen = false
isLongOpen := nz(isLongOpen[1], false)
entryPrice=0.0
entryPrice:= nz(entryPrice[1], 0.0)
trailPrice=0.0
trailPrice:=nz(trailPrice[1], 0.0)

// update TSL high mark
if (isLongOpen )
    if (not trailPrice and currentPrice >= entryPrice * (1 + tslTrigger))
        trailPrice := currentPrice
    else 
        if (trailPrice and currentPrice > trailPrice)
            trailPrice := currentPrice

if (trailPrice and currentPrice <= trailPrice * (1 - tslStop))
    // FIRE TSL SIGNAL
    short:=true // <===
    long := false

// if short clean up
if (short)
    isLongOpen := false
    entryPrice := 0.0
    trailPrice := 0.0

if (long)
    isLongOpen := true
    if (not entryPrice)
        entryPrice := currentPrice

// === BACKTESTING: ENTRIES ===
if long
    if (strategyType == "Short Only")
        strategy.close("Short")
    else
        strategy.entry("Long", strategy.long, comment="Long")

if short
    if (strategyType == "Long Only")
        strategy.close("Long")
    else
        strategy.entry("Short", strategy.short, comment="Short")	  
    
//barcolor(possig == -1 ? red: possig == 1 ? green : blue )
//plot(xmacd, color=green, title="Ergotic MACD")
//plot(xMA_MACD, color=red, title="SigLin")

plotshape(trailPrice ? trailPrice : na, style=shape.circle, location=location.absolute, color=blue, size=size.tiny)

plotshape(long, style=shape.triangleup, location=location.belowbar, color=green, size=size.tiny)
plotshape(short, style=shape.triangledown, location=location.abovebar, color=red, size=size.tiny)

// === Strategy Alert ===
alertcondition(long, title='BUY - Ergotic MACD Long Entry', message='Go Long!')
alertcondition(short, title='SELL - Ergotic MACD Long Entry', message='Go Short!')

// === BACKTESTING: EXIT strategy ===
sl_inp = input(7, title='Stop Loss %', type=float)/100
tp_inp = input(1.8, title='Take Profit %', type=float)/100

stop_level = strategy.position_avg_price * (1 - sl_inp)
take_level = strategy.position_avg_price * (1 + tp_inp)

strategy.exit("Stop Loss/Profit", "Long", stop=stop_level, limit=take_level)

もっと