この戦略の主な考え方は,より大きなタイムフレームでトレンド方向を特定し,より小さなタイムフレームで入力するブレイクアウトポイントを見つけることです.ストップロスの出口は,より大きなタイムフレームで移動平均を追跡します.
この戦略は主に3つの判断指標に基づいています
まず,より長いサイクル (例えば毎日) X 日間の単純な移動平均値を計算します.価格がこの移動平均値を超える場合にのみ購入を許可します.これは全体的なトレンド方向性を決定し,振動期間の取引を避けるのに使用できます.
2つ目は,より短いサイクル (例えば5日) で最も高い価格のスイングハイを計算する.価格がこの最高価格を突破すると,購入信号が誘発される.ここで適切なブレイクアウトポイントを見つけるためにlblookback期間パラメータを使用する.
3つ目は,ストップ・ロスのラインを設定する.ポジションに入ると,ストップ・ロスのラインは,最も最近の低値から一定の期間を離れて最低価格でロックされます.同時に,出口メカニズムとして移動平均線 (日々の10日間のEMAなど) を設定します.価格がこの移動平均線を下回るとポジションを終了します.
戦略は,過剰に延長されたポイントの購入を避けるためにATR値を設定する.バックテスト時間範囲などの他の補助条件もあります.
上記3つの指標の相互作用判断が この戦略の核心論理を構成しています
脱出追跡戦略として,以下の利点があります:
振動する市場における偽のブレイクに囚われないように 2つのタイムフレームを使用します. 長いタイムフレームは全体的なトレンドを決定し,短いタイムフレームは特定のエントリーポイントを見つけます.
スウィング高で形成されたブレイクアウトポイントを使用する.このタイプのブレイクアウトは一定の慣性を持ち,追跡を形成することは簡単です. lb lookback 周期パラメータも,本当に効果的なブレイクアウトを見つけるために調整できます.
ストップ・ロスの方法は比較的厳格で 最新の低点を一定バッファ距離で追跡し 落とし穴を回避します
移動平均を退出メカニズムとして利用し,市場の状況に応じて柔軟に利益を得ることができます.
ATR インディケーターは,過剰レバレッジのリスクを回避します.
テストのために異なるパラメータ組み合わせを設定することができ,大きな最適化スペースがあります.
この戦略にはいくつかのリスクもあります:
価格が移動平均線周りに上下波動するとき,入口と出口のポジションの間に前後を切り替えるのは簡単です.より高い佣金リスクがあります.
ブレイクインポイントが移動平均線に近い場合,比較的大きな引き下げリスクがあります.これは戦略の固有の特徴です.
市場に明らかな傾向がない場合,保持時間が長くなり,時間リスクに直面する可能性があります.
ATRパラメータは合理的に設定する必要があります. ATRが小さすぎると,フィルタリング効果が弱まります. 大きすぎると,エントリー機会が減少します.
異なるlbパラメータが結果に与える影響をテストする必要がある.過大なパラメータはいくつかの機会を逃す可能性があります.過小なパラメータは偽のブレイクを特定することができます.
リスク軽減
また,戦略は以下の側面において最適化することができる.
最適なパラメータを見つけるために移動平均パラメータの異なる組み合わせをテストする.
異なるATRパラメータ設定を試して 侵入機会とリスク管理をバランスにする
より効率的なブレイクアウトを特定するために lb lookback 期間パラメータを最適化します.
動的ストップ・ロスを構築しようとします リスクをコントロールするために 変動と引き下げをベースにします
ブレイクアウトの有効性を決定するために,取引量などの他の要因を考慮します.
/
最適なパラメータのためのパラメータを訓練するために機械学習を試す
概して,これは典型的なブレイクアウト追跡戦略である.デュアルタイムフレームを判断すると,エントリータイミングを特定するためにスウィングハイを使用し,ストップ損失ラインと移動平均のダブル保険退出メカニズムを使用することで,完全な論理システムを形成する.この戦略のリスクとリターン特性は明確で,中長期追跡投資家には適している.特定のリスクがあるにもかかわらず,パラメータとルールを最適化することで軽減することができます.戦略には改善の余地があります.より多くの指標を組み込むことが戦略効果をさらに高める可能性があります.
/*backtest start: 2023-01-24 00:00:00 end: 2024-01-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/ // © millerrh // The intent of this strategy is to buy breakouts with a tight stop on smaller timeframes in the direction of the longer term trend. // Then use a trailing stop of a close below either the 10 MA or 20 MA (user choice) on that larger timeframe as the position // moves in your favor (i.e. whenever position price rises above the MA). // Option of using daily ATR as a measure of finding contracting ranges and ensuring a decent risk/reward. // (If the difference between the breakout point and your stop level is below a certain % of ATR, it could possibly find those consolidating periods.) //@version=4 strategy("Qullamaggie Breakout", 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) // === BACKTEST RANGE === Start = input(defval = timestamp("01 Jan 2019 06:00 +0000"), title = "Backtest Start Date", type = input.time) Finish = input(defval = timestamp("01 Jan 2100 00:00 +0000"), title = "Backtest End Date", type = input.time) // Inputs lb = input(defval = 3, title = "Lookback Period for Swing High", minval = 1, tooltip = "Lookback period for defining the breakout level.") lbStop = input(defval = 3, title = "Lookback Bars for Stop Level", minval = 1, tooltip = "Initial stop placement is the lowest low this many bars back. Allows for tighter stop placement than referencing swing lows.") htf = input(defval="D", title="Timeframe of Moving Averages", type=input.resolution, tooltip = "Allows you to set a different time frame for the moving averages. The default behavior is to identify good tightening setups on a larger timeframe (like daily) and enter the trade on a breakout occuring on a smaller timeframe, using the moving averages of the larger timeframe to trail your stop.") maType = input(defval="SMA", options=["EMA", "SMA"], title = "Moving Average Type") ma1Length = input(defval = 10, title = "1st Moving Average Length", minval = 1) ma2Length = input(defval = 20, title = "2nd Moving Average Length", minval = 1) ma3Length = input(defval = 50, title = "3rd Moving Average Length", minval = 1) useMaFilter = input(title = "Use 3rd Moving Average for Filtering?", type = input.bool, defval = true, tooltip = "Signals will be ignored when price is under this slowest moving average. The intent is to keep you out of bear periods and only buying when price is showing strength or trading with the longer term trend.") trailMaInput = input(defval="2nd Moving Average", options=["1st Moving Average", "2nd Moving Average"], title = "Trailing Stop") // MA Calculations ma(maType, src, length) => maType == "EMA" ? ema(src, length) : sma(src, length) //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc) ma1 = security(syminfo.tickerid, htf, ma(maType, close, ma1Length)) ma2 = security(syminfo.tickerid, htf, ma(maType, close, ma2Length)) ma3 = security(syminfo.tickerid, htf, ma(maType, close, ma3Length)) plot(ma1, color=color.purple, style=plot.style_line, title="MA1", linewidth=2, transp = 60) plot(ma2, color=color.yellow, style=plot.style_line, title="MA2", linewidth=2, transp = 60) plot(ma3, color=color.white, style=plot.style_line, title="MA3", linewidth=2, transp = 60) // === USE ATR FOR FILTERING === // The idea here is that you want to buy in a consolodating range for best risk/reward. So here you can compare the current distance between // support/resistance vs.the ATR and make sure you aren't buying at a point that is too extended from normal. useAtrFilter = input(title = "Use ATR for Filtering?", type = input.bool, defval = false, tooltip = "Signals will be ignored if the distance between support and resistance is larger than a user-defined percentage of Daily ATR. This allows the user to ensure they are not buying something that is too extended and instead focus on names that are consolidating more.") atrPerc = input(defval = 100, title = "% of Daily ATR Value", minval = 1) atrValue = security(syminfo.tickerid, "D", atr(14))*atrPerc*.01 // === PLOT SWING HIGH/LOW AND MOST RECENT LOW TO USE AS STOP LOSS EXIT POINT === // Change these values to adjust the look back and look forward periods for your swing high/low calculations pvtLenL = lb pvtLenR = lb // Get High and Low Pivot Points pvthi_ = pivothigh(high, pvtLenL, pvtLenR) pvtlo_ = pivotlow(low, pvtLenL, pvtLenR) // Force Pivot completion before plotting. Shunt = 1 //Wait for close before printing pivot? 1 for true 0 for flase maxLvlLen = 0 //Maximum Extension Length pvthi = pvthi_[Shunt] pvtlo = pvtlo_[Shunt] // Count How many candles for current Pivot Level, If new reset. counthi = barssince(not na(pvthi)) countlo = barssince(not na(pvtlo)) pvthis = fixnan(pvthi) pvtlos = fixnan(pvtlo) hipc = change(pvthis) != 0 ? na : color.maroon lopc = change(pvtlos) != 0 ? na : color.green // Display Pivot lines plot((maxLvlLen == 0 or counthi < maxLvlLen) ? pvthis : na, color=hipc, transp=0, linewidth=1, offset=-pvtLenR-Shunt, title="Top Levels") // plot((maxLvlLen == 0 or countlo < maxLvlLen) ? pvtlos : na, color=lopc, transp=0, linewidth=1, offset=-pvtLenR-Shunt, title="Bottom Levels") plot((maxLvlLen == 0 or counthi < maxLvlLen) ? pvthis : na, color=hipc, transp=0, linewidth=1, offset=0, title="Top Levels 2") // plot((maxLvlLen == 0 or countlo < maxLvlLen) ? pvtlos : na, color=lopc, transp=0, linewidth=1, offset=0, title="Bottom Levels 2") // BUY CONDITIONS stopLevelCalc = valuewhen(pvtlo_, low[pvtLenR], 0) //Stop Level at Swing Low buyLevel = valuewhen(pvthi_, high[pvtLenR], 0) //Buy level at Swing High plot(buyLevel, style=plot.style_line, color=color.blue, title = "Current Breakout Level", show_last=1, linewidth=1, transp=50, trackprice=true) // Conditions for entry and exit stopLevel = float(na) // Define stop level here as "na" so that I can reference it in the inPosition // variable and the ATR calculation before the stopLevel is actually defined. buyConditions = (useMaFilter ? buyLevel > ma3 : true) and (useAtrFilter ? (buyLevel - stopLevel[1]) < atrValue : true) // buySignal = high > buyLevel and buyConditions buySignal = crossover(high, buyLevel) and buyConditions trailMa = trailMaInput == "1st Moving Average" ? ma1 : ma2 sellSignal = crossunder(close, trailMa) // sellSignal = security(syminfo.tickerid, htf, close < trailMa) and security(syminfo.tickerid, htf, close[1] < trailMa) // STOP AND PRICE LEVELS inPosition = bool(na) inPosition := buySignal[1] ? true : sellSignal[1] ? false : low <= stopLevel[1] ? false : inPosition[1] lowDefine = lowest(low, lbStop) stopLevel := inPosition ? stopLevel[1] : lowDefine // plot(stopLevel) buyPrice = buyLevel buyPrice := inPosition ? buyPrice[1] : buyLevel plot(stopLevel, style=plot.style_line, color=color.orange, title = "Current Stop Level", show_last=1, linewidth=1, transp=50, trackprice=true) plot(inPosition ? stopLevel : na, style=plot.style_circles, color=color.orange, title = "Historical Stop Levels", transp=50, trackprice=false) // plot(buyPrice, style=plot.style_line, color=color.blue, linewidth=1, transp=50, trackprice=true) // (STRATEGY ONLY) Comment out for Study strategy.entry("Long", strategy.long, stop = buyLevel, when = buyConditions) strategy.exit("Exit Long", from_entry = "Long", stop=stopLevel[1]) if (low[1] > trailMa) strategy.close("Long", when = sellSignal) // if (low[1] > trailMa) // strategy.exit("Exit Long", from_entry = "Long", stop=trailMa) //to get this to work right, I need to reference highest highs instead of swing highs //because it can have me buy right back in after selling if the stop level is above the last registered swing high point.