ブレイクトレンドフォロワー V2

作者: リン・ハーンチャオチャン,日付: 2023年11月1日 17:24:08
タグ:

img

概要

この戦略は,私の他のブレイクアウトトレンドフォロワー戦略のバリエーションです.他の戦略では,移動平均をあなたのトレードのためのフィルターとして機能するために使用することができます (つまり,価格が移動平均を下回れば,それは長続きしません).より高いタイムフレームでトレンドを検出するツールを作成した後,私はそれが移動平均よりもより良いフィルターであるかどうかを見たいと思いました.

このスクリプトでは,より高いタイムフレームのトレンド (つまり,より高い高値とより高い低値がありますか?そうであれば,これは上昇傾向です) を見ることができます.トレンドと一緒であるときにのみ取引を行います.フィルターとして機能するために,最大2つのトレンドを選択する機能があります.各トレンド方向は,簡単な参照のためにチャート上のテーブルに表示されています.現在のピボット高値と低値はチャートにプロットされています.

これは他の戦略ほどうまく機能していないことがわかりました. しかし,取引に対してより挑発的なようです. より高い勝利率とより良い利益因子を示しています. ただ,取引が少なくなり,純利益はあまり良くないだけです.

戦略の論理

この戦略の主な論理は,より高い時間枠でサポートとレジスタンスレベルを突破してトレンドを特定し,トレンドの方向に取引を行うことです.

具体的には,次のステップを実行します.

  1. 現在の時間枠 (例えば1時間) でピボットのサポートとレジスタンスレベルを計算します.これは,特定の期間における最高高値と最低低値を見て行う.

  2. 1つまたは複数のより高い時間枠 (例えば4時間および毎日) でピボットのサポートとレジスタンスレベルを計算します.これは現在の時間枠と同じ論理を使用します.

  3. これらのサポートとレジスタンスレベルをグラフ上の水平線として図に描画します.これらのレベルを割ると,より高いタイムフレームでのトレンドの変化を示します.

  4. 価格が前回の高値や低値を突破するかどうかを基準にトレンド方向を決定する.前回の高値を突破すると上昇傾向を示します.前回の低値を突破すると下落傾向を示します.

  5. フィルター条件として,ユーザが1つまたは複数のより高いタイムフレームのトレンドを選択することを許可します.つまり,現在のタイムフレームのトレンドがより高いタイムフレームのトレンドと一致するときにのみ取引を行うことを検討します.

  6. トレンドフィルター条件が満たされ,現在の価格がキーレベルを突破すると,ロングまたはショートに入ります.ストップロスは前のキーサポートまたはレジスタンスレベルに設定されます.

  7. 価格が動くと ストップ・ロスは新低点に調整して 利益を固定して 傾向を追います

  8. ストップ・ロスが起動したり,主要なサポート/レジスタンスレベルが切断されたときに終了します.

複数のタイムフレームのトレンドを分析することで,戦略は勝率を改善するためにより強いトレンドの方向にのみ取引しようとします. 一方,キーレベルは明確なエントリーとストップ損失信号を提供します.

戦略 の 利点

  • 複数のタイムフレームを使用してトレンドを判断することで 騒音を避け より強いトレンド方向を正確に特定できます

  • 主要なトレンドと取引するだけで勝利率が著しく向上する.単純な移動平均フィルターと比較して,この戦略はより高い勝利率とリスク・リターン比を示した.

  • サポートとレジスタンスレベルは明確なエントリーとストップ損失レベルを提供します. 特定のエントリーポイントを推測する必要はありません.

  • トレンドに沿ってストップを調整して 利益を最大化します

  • シンプルで明快な戦略論理 分かりやすく最適化できます

戦略 の リスク

  • 長期的傾向に依存し,傾向の逆転に囚われやすい.傾向を判断するための時間枠を短縮するか,他の指標を使用して支援すべきです.

  • 基本的影響は考慮されません. 大事なイベントの価格から逸脱する可能性があります. 収益日付のようなフィルターを追加できます.

  • ポジションサイズ制御は設定されていません. 口座サイズ,変動等によってサイズを最適化する必要があります.

  • 制限されたバックテスト期間. テストをさまざまな市場環境に拡大すべきです.

  • 取引コストは考慮しない 実際のコストに基づいてパラメータを調整すべきです

  • 長期取引のみを考慮し,複数のタイムフレーム戦略を実行するために短期取引のためのシグナルを開発することができます.

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

  • フィルター条件を追加する:

    • 収入やニュースなどの基本情報

    • 音量,ATR停止などの指標

  • パラメータを最適化:

    • サポート/レジスタンスの計算期間

    • 傾向決定の時間枠

  • 戦略の範囲を拡大する

    • 短期的な取引戦略を策定する

    • ショートカットする機会を検討する

    • 市場間差

  • リスク管理を強化する

    • 波動性とサイズによるポジションサイズを最適化する

    • 移動/ブレーキットストップのようなストップ・ロスの戦略を改善する

    • リスク調整指標を導入する

  • 実行ロジックを改善する:

    • 入力タイミングの選択

    • 部分サイズ記号

    • ストップ損失運動の最適化

結論

この戦略は,複数のタイムフレームのトレンドを分析することで,比較的堅牢なブレイクアウトシステムを設計した.移動平均値のような単純なフィルターと比較して,より高い勝利率とリスク報酬比を示した.しかし,堅牢なリスク管理メカニズムの欠如や基礎的考慮などの改善が可能な分野もあります.さらなる最適化により,非常に実践的なトレンドフォロー戦略になることができます.全体として,戦略デザインは健全で,マルチタイムフレーム分析を通じて精度を向上させ,さらなる研究と適用に値します.


/*backtest
start: 2023-10-24 00:00:00
end: 2023-10-26 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4

// Revision:        1
// Author:          @millerrh
// Strategy:  Enter long when recent swing high breaks out, using recent swing low as stop level.  Move stops up as higher lows print to act
// as trailing stops.  Ride trend as long as it is there and the higher lows aren't breached.  
// The difference between this one and the previous Breakout Trend Follower is that this one uses higher timeframe higher highs/higher lows as a filter instead 
// of an arbitrary Moving Average.  I wanted to test out whether waiting for longer term actual trend changes produced better stats than just the moving average.
// Conditions/Variables 
//    1. Manually configure which dates to back test
//    2. Can add a filter to only take setups that are above (or below for shorts) user-defined larger timeframe trends (helps avoid trading counter trend) 

// === CALL STRATEGY/STUDY, PROGRAMATICALLY ENTER STRATEGY PARAMETERS HERE SO YOU DON'T HAVE TO CHANGE THEM EVERY TIME YOU RUN A TEST ===
// (STRATEGY ONLY) - Comment out srategy() when in a study() 
strategy("Breakout Trend Follower V2", overlay=true, initial_capital=10000, currency='USD', 
   default_qty_type=strategy.percent_of_equity, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)
// (STUDY ONLY) - Comment out study() when in a strategy() 
//study("Breakout Trend Follower V2", overlay=true)

// === BACKTEST RANGE ===
Start = input(defval = timestamp("01 Jan 2019 06:00 +0000"), title = "Backtest Start Date", type = input.time, group = "Backtest Range")
Finish = input(defval = timestamp("01 Jan 2100 00:00 +0000"), title = "Backtest End Date", type = input.time, group = "Backtest Range")

// == USER INPUTS ==
tableLocation = input(defval="Top", options=["Top", "Bottom"], title = "Info Table Location", group = "Display",
  tooltip = "Place information table on the top of the pane or the bottom of the pane.")
lookback = input(defval = 3, title = "Pivot Lookback Period", group = "Pivot Points",
  tooltip = "Looks for pivot points within this number of bars both left and right.")
showPivotPoints = input(title = "Show Historical Pivot Points?", type = input.bool, defval = false, group = "Pivot Points",
  tooltip = "Toggle this on to see the historical pivot points that were used.  Change the Lookback Period to adjust the frequency of these points.
  The pivot points are only shown for the current chart timeframe - to see the Daily pivot pionts, use the Daily timeframe, etc.")
trendFilter = input(defval="1st Timeframe", options=["1st Timeframe", "Both Timeframes", "None"], title = "Use HTF Trend for Filtering?", group = "Higher Timeframe Levels",
  tooltip = "Signals will be ignored when price is not aligned with the higher timeframe trend(s).  The intent is to keep you out of bear periods and only buying when 
  price is showing strength and you are trading with the trend.")
twoSet = input(defval="D", title="1st High Timeframe", type=input.resolution, group = "Higher Timeframe Levels",
  tooltip = "Allows you to set two different time frames for looking at the trend.")
threeSet = input(defval="W", title="2nd High Timeframe", type=input.resolution, group = "Higher Timeframe Levels")
showMTFLevels = input(title = "Show Multiple Timeframe S/R Levels?", type = input.bool, defval = true, group = "Higher Timeframe Levels",
  tooltip = "Displays the pivot highs and lows of higher timeframes to use as support/resistance levels. When these levels break, the trend
  will change on these higher timeframes.")
currentColorS = input(color.new(color.orange,50), title = "Current Timeframe    Support", type = input.color, group = "Higher Timeframe Levels", inline = "MTF1")
currentColorR = input(color.new(color.blue,50), title = " Resistance", type = input.color, group = "Higher Timeframe Levels", inline = "MTF1")
oneColorS = input(color.new(color.yellow,50), title = "1st High Timeframe   Support", type = input.color, group = "Higher Timeframe Levels", inline = "MTF2")
oneColorR = input(color.new(color.yellow,50), title = " Resistance", type = input.color, group = "Higher Timeframe Levels", inline = "MTF2")
twoColorS = input(color.new(color.white,50), title = "2nd High Timeframe    Support", type = input.color, group = "Higher Timeframe Levels", inline = "MTF3")
twoColorR = input(color.new(color.white,50), title = " Resistance", type = input.color, group = "Higher Timeframe Levels", inline = "MTF3")

//  == DEFINE FUNCTIONS FOR USE IN MULTIPLE TIMEFRAMES (USING A TUPLE TO AVOID SO MANY SECURITY CALLS) ==  
f_getHTF() =>
    ph = pivothigh(high, lookback, lookback)
    pl = pivotlow(low, lookback, lookback)
    highLevel = valuewhen(ph, high[lookback], 0)
    lowLevel = valuewhen(pl, low[lookback], 0)
    barsSinceHigh = barssince(ph) + lookback
    barsSinceLow = barssince(pl) + lookback
    timeSinceHigh = time[barsSinceHigh]
    timeSinceLow = time[barsSinceLow]
    [ph, pl, highLevel, lowLevel, barsSinceHigh, barsSinceLow, timeSinceHigh, timeSinceLow]
    
[ph_01, pl_01, hL_01, lL_01, bsSH_01, bsSL_01, tSH_01, tSL_01] = security(syminfo.tickerid, "", f_getHTF())
[ph_02, pl_02, hL_02, lL_02, bsSH_02, bsSL_02, tSH_02, tSL_02] = security(syminfo.tickerid, twoSet, f_getHTF())
[ph_03, pl_03, hL_03, lL_03, bsSH_03, bsSL_03, tSH_03, tSL_03] = security(syminfo.tickerid, threeSet, f_getHTF())

// Plot historical pivot points for debugging and configuring the lookback period.
plot(showPivotPoints ? ph_01 : na, style=plot.style_cross, linewidth=3, color=color.new(color.yellow,50), offset=-lookback)
plot(showPivotPoints ? pl_01 : na, style=plot.style_cross, linewidth=3, color=color.new(color.yellow,50), offset=-lookback)

// == PLOT SUPPORT/RESISTANCE LINES ON THE HIGHER TIMEFRAMES ==
// Use a function to define the lines
f_line(x1, y1, y2, _color) =>
    var line id = na
    // line.delete(id)
    // id := line.new(x1, y1, time, y2, xloc.bar_time, extend.right, _color)

// 1st Timeframe
highLine1 = showMTFLevels ? f_line(tSH_01, hL_01, hL_01, currentColorR) : na
lowLine1 = showMTFLevels ? f_line(tSL_01, lL_01, lL_01, currentColorS) : na 
// 2nd Timeframe
highLine2 = showMTFLevels ? f_line(tSH_02, hL_02, hL_02, oneColorR) : na
lowLine2 = showMTFLevels ? f_line(tSL_02, lL_02, lL_02, oneColorS) : na
// 3rd Timeframe
highLine3 = showMTFLevels ? f_line(tSH_03, hL_03, hL_03, twoColorR) : na
lowLine3 = showMTFLevels ? f_line(tSL_03, lL_03, lL_03, twoColorS) : na

// == TREND CALCULATIONS (USING A TUPLE TO CONSOLIDATE REPETATIVE CODE AND GENERATE MULTIPE VARIABLES WITH ONE FUNCTION ==
f_signal(highLevel, lowLevel) =>
    uptrendSignal    = high > highLevel
    downtrendSignal  = low < lowLevel
    inUptrend        = bool(na)
    inDowntrend      = bool(na) 
    inUptrend       := uptrendSignal[1] ? true : downtrendSignal[1] ? false : inUptrend[1]
    inDowntrend     := not inUptrend
    [uptrendSignal, downtrendSignal, inUptrend, inDowntrend]

[uptrendSignal1, downtrendSignal1, inUptrend1, inDowntrend1] = f_signal(hL_01, lL_01)  // 1st Timeframe
[uptrendSignal2, downtrendSignal2, inUptrend2, inDowntrend2] = f_signal(hL_02, lL_02)  // 2nd Timeframe
[uptrendSignal3, downtrendSignal3, inUptrend3, inDowntrend3] = f_signal(hL_03, lL_03)  // 3rd Timeframe

// == TREND TABLE PLOTTING ==
tablePos = tableLocation == "Top" ? position.top_right : position.bottom_right
var table trendTable = table.new(tablePos, 3, 1, border_width = 3)
upColor = color.rgb(38, 166, 154)
downColor = color.rgb(240, 83, 80)

f_fillCell(_column, _row, _cellText, _c_color) =>
    table.cell(trendTable, _column, _row, _cellText, bgcolor = color.new(_c_color, 70), text_color = _c_color, width = 6)

if barstate.islast or barstate.islastconfirmedhistory
    f_fillCell(0, 0, inUptrend1 ? "▲" : "▼", inUptrend1 ? upColor : downColor)
    f_fillCell(1, 0, inUptrend2 ? "▲ " + twoSet : "▼ " + twoSet, inUptrend2 ? upColor : downColor)
    f_fillCell(2, 0, inUptrend3 ? "▲ " + threeSet : "▼ " + threeSet, inUptrend3 ? upColor : downColor)

// Conditions for entry and exit
buyConditions =  true
buySignal = high > hL_01 and buyConditions // Code to act like a stop-buy for the Study
sellSignal = low < lL_01 // Code to act like a stop-loss for the Study

// (STRATEGY ONLY) Comment out for Study
strategy.entry("Long", strategy.long, stop = hL_01, when = buyConditions)
// strategy.entry("Long", strategy.long, stop = buyLevel2, when = time > Start and time < Finish and high > maFilterCheck)
strategy.exit("Exit Long", from_entry = "Long", stop=lL_01)



もっと