
この戦略は,ブリン帯の動的上下を活用して,価格がブリン帯の上下を突破したときに多額の取引を,価格がブリン帯の下下を突破したときに平仓を実現する.従来の突破戦略とは異なり,ブリン帯の上下下は,歴史的変動率の動態によって変化し,市場の超買超売状態をよりよく判断することができる.
この戦略は,ブリン帯の指標による価格判断の突破を主に依拠している.ブリン帯は,以下の3つの線で構成されている.
値上がりが上線を超えたとき,市場が超買い状態にあると考えると,より多くを行うことができます。値下がりが下線を超えたとき,市場が超売り状態にあると考えると,平仓するべきです。
このポリシーは,ブリン帯のパラメータをカスタマイズすることを許可します. 中間線長 n と標準差の倍数 k 〇 標準差の倍数 2 〇 〇 〇 〇 〇 〇 〇 〇
株式が毎日閉店した後,当日の閉店価格が上線突破したかどうかをチェックする.もしそうなら,翌日の開店時に多信号を実行する.多を行った後,価格が下線突破したかどうかをリアルタイムで監視し,突破した場合は平仓する.
この戦略はまた,平均線フィルターを導入し,価格が平均線より高い場合にのみ多信号を生成する.現在の周期またはより高い周期で平均線を描画することを選択して,入入の時間点を制御する.
ストップ・ラスト方式も2つの選択肢を提供している:固定パーセントストップまたはブリン・バンド・ダウン・レーンを追跡する.後者は,利潤を運行させるためのより大きなスペースを提供できる.
この戦略は,ブリン帯の動的上下軌道を利用して,超買超売を判断し,均線フィルタリング信号を参考にして,ストップ損失保護資金を採用する。従来の固定軌道の突破と比較して,市場の波動により適応する。パラメータ最適化とリスク制御により,戦略の安定性と収益率をさらに向上させることができる。全体的に,この戦略は,ブリン帯の動的特性を利用し,突破戦略の優位性を獲得し,試行評価と長期追跡最適化に値する。
/*backtest
start: 2022-11-06 00:00:00
end: 2023-11-12 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
// Revision: 1
// Author: @millerrh
// Strategy:
// Entry: Buy when price breaks out of upper Bollinger Band
// Exit: Trail a stop with the lower Bollinger Band
// Conditions/Variables:
// 1. Can add a filter to only take setups that are above a user-defined moving average on current timeframe and/or longer timeframe (helps avoid trading counter trend)
// 2. Manually configure which dates to back test
// 3. User-Configurable Bollinger Band Settings
// 4. Optionally use a tighter initial stop level. Once Bollinger Band catches up, trail with lower Bollinger Band to give more breathing room.
// strategy('Donchian Breakout', overlay=true, initial_capital=100000, currency='USD', default_qty_type=strategy.percent_of_equity, calc_on_every_tick = true,
// default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)
strategy('Bollinger Breakout', overlay=true, initial_capital=100000, currency='USD', default_qty_type=strategy.percent_of_equity,
default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0, calc_on_order_fills=true)
// === BACKTEST RANGE ===
Start = input(defval = timestamp("01 Jan 2019 06:00 +0000"), title = "Backtest Start Date", group = "backtest window")
Finish = input(defval = timestamp("01 Jan 2100 00:00 +0000"), title = "Backtest End Date", group = "backtest window")
// == INPUTS ==
// Bollinger Band Inputs
bbLength = input.int(20, minval=1, group = "Bollinger Band Settings", title="Bollinger Band Length",
tooltip = "Bollinger Band moving average length.")
bbMultTop = input.float(2.0, minval=0.001, maxval=50, title="Standard Deviation (Top)")
bbMultBot = input.float(2.0, minval=0.001, maxval=50, title="Standard Deviation (Bottom)")
useTightStop = input.bool(title='Use Fixed Percentage for Initial Stop?', defval=false, group = "order entry",
tooltip = "'Keep your losers small and let winners run' is the saying. This will allow you to use a tight initial stop
until the lower Bollinger Band catches up.")
percStop = input.int(title="Stop", defval=8, group = "order entry", inline = "perc")
trigInput = input.string(title='Execute Trades On...', defval='Wick', options=['Wick', 'Close'], group = "order entry",
tooltip = "Useful for comparing standing stop orders at the Bollinger Band boundary (executing on the wick) vs. waiting for candle closes prior to taking action")
// Moving Average Filtering Inputs
useMaFilter = input.bool(title='Use Moving Average for Filtering (Current Timeframe)?', defval=false, group = "moving average filtering",
tooltip = "Signals will be ignored when price is under this moving average. The intent is to keep you out of bear periods and only buying when
price is showing strength.")
maType = input.string(defval='SMA', options=['EMA', 'SMA'], title='MA Type For Filtering', group = "moving average filtering")
maLength = input.int(defval=50, title="Moving Average: Length", minval=1, group = "moving average filtering", inline = "1ma")
ma1Color = input.color(color.new(color.green, 50), title = " Color", group = "moving average filtering", inline = "1ma")
useMaFilter2 = input.bool(title='Use Moving Average for Filtering (High Timeframe)?', defval=false, group = "moving average filtering")
tfSet = input.timeframe(defval="D", title="Timeframe of Moving Average", group = "moving average filtering",
tooltip = "Allows you to set a different time frame for a moving average filter. Trades will be ignored when price is under this moving average.
The idea is to keep your eye on the larger moves in the market and stay on the right side of the longer term trends and help you be pickier about
the stocks you trade.")
ma2Type = input.string(defval='SMA', options=['EMA', 'SMA'], title='MA Type For Filtering', group = "moving average filtering")
ma2Length = input.int(defval=50, title="Moving Average: Length", minval=1, group = "moving average filtering", inline = "2ma")
ma2Color = input.color(color.new(color.white, 50), title = " Color", group = "moving average filtering", inline = "2ma")
// === THE BOLLINGER BAND ===
// Logic
bbBasis = ta.sma(close, bbLength)
bbUpper = bbBasis + bbMultTop * ta.stdev(close, bbLength)
bbLower = bbBasis - bbMultBot * ta.stdev(close, bbLength)
// Plotting
plot(bbBasis, "Basis", color=color.new(color.white, 50))
p1 = plot(bbUpper, color=color.new(color.blue, 50), linewidth=1, title='Upper Bollinger Band')
p2 = plot(bbLower, color=color.new(color.blue, 50), linewidth=1, title='Lower Bollinger Band')
fill(p1, p2, title = "Background", color=color.rgb(33, 150, 243, 95))
// == FILTERING LOGIC ==
// Declare function to be able to swap out EMA/SMA
ma(maType, src, length) =>
maType == 'EMA' ? ta.ema(src, length) : ta.sma(src, length) //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc)
maFilter = ma(maType, close, maLength)
maFilter2 = request.security(syminfo.tickerid, tfSet, ma(ma2Type, close, ma2Length))
// Plotting
plot(useMaFilter ? maFilter : na, title='Trend Filter MA - CTF', color=ma1Color, linewidth=2, style=plot.style_line)
plot(useMaFilter2 ? maFilter2 : na, title='Trend Filter MA - HTF', color=ma2Color, linewidth=2, style=plot.style_line)
// == ENTRY AND EXIT CRITERIA ==
// Trigger stop based on candle close or High/Low (i.e. Wick)
trigResistance = trigInput == 'Close' ? close : trigInput == 'Wick' ? high : na
trigSupport = trigInput == 'Close' ? close : trigInput == 'Wick' ? low : na
buySignal = trigResistance >= bbUpper
buyConditions = (useMaFilter ? bbUpper > maFilter : true) and
(useMaFilter2 ? bbUpper > maFilter2 : true)
// == STOP AND PRICE LEVELS ==
// Configure initial stop level
inPosition = strategy.position_size > 0
stopLevel = strategy.position_avg_price - (strategy.position_avg_price * percStop/100)
posStop = stopLevel > bbLower ? stopLevel : bbLower
// Check if using stop vs. not
stop = useTightStop ? posStop : bbLower
plot(inPosition ? stop : na, style=plot.style_linebr, color=color.new(color.red, 40), linewidth = 1, title = "Stop Levels", trackprice=false)
sellSignal = trigSupport <= stop
// == STRATEGY ENTRIES & EXITS ==
// This string of code enters and exits at the candle close
if trigInput == 'Close'
strategy.entry('Long', strategy.long, when=buyConditions and buySignal)
strategy.close('Long', when=sellSignal)
// This string of code enters and exits at the wick (i.e. with pre-set stops)
if trigInput == 'Wick'
strategy.entry('Long', strategy.long, stop=bbUpper, when=buyConditions)
strategy.exit('Exit Long', from_entry='Long', stop=stop)
strategy.cancel('Long',when= not(buyConditions)) // Resets stop level once buyConditions aren't true anymore