これはボリンジャー帯とMACD指標に基づいた定量的な取引戦略である.トレード機会を特定するために2つの主流の技術指標を組み合わせ,トレンド市場でのより高い勝利率を達成することを目的としている.
この戦略は,価格がボリンジャーバンドの下部帯を突破してトレンドをフォローするときのロングポジションと,価格が上部帯を突破すると閉じるポジションを確立する.MACDインジケターは,モメンタム方向を判断することによって偽ブレイクをフィルタリングするために使用されます.RSIインジケターは,損失をさらに避けるために過剰購入および過剰販売レベルを特定するのに役立つように設定できます.
この戦略は主にボリンジャー帯とMACD指標で構成されています.
ボリンジャーバンドは,価格の標準偏差に基づいて上位および下位帯を計算する.上位帯の上昇突破は過買い状態を示し,下位帯の低下突破は過売状態を示します.この戦略は,価格が下位帯を破ると長引く,上位帯を破るとポジションを閉じる.
MACDインジケーターは価格の勢いと方向を判断する.長期間の移動平均の上での短期移動平均のクロスオーバーは購入信号であり,下のクロスオーバーは販売信号である.MACDはこの戦略でボリンジャーバンドの偽ブレイクをフィルタリングするのに役立ちます.
また,RSIインジケーターは過買い/過売れレベルを特定するのに役立ちます.低RSIは過売れを示し,購入信号を強化し,高いRSIは過買いを示し,販売信号を強化します.
この戦略は,ボリンジャー帯,MACDおよびRSIインジケーターを組み合わせ,価格動向と変動を効果的に決定することができます.その利点には以下が含まれます.
また,注意すべきリスクもいくつかあります.
対策:
戦略を最適化するための主要方向は以下の通りである.
一般的に,これは戦略をフォローする典型的な傾向である.複数の技術指標を組み合わせることで,強度が向上し,シグナルが正確である場合,立派な勝利率を達成することができる.しかし,リスクは監視する必要がある.継続的な最適化とチューニングによってさらなる改善が可能である.
/*backtest start: 2022-12-12 00:00:00 end: 2023-12-18 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © tedwardd // This strategy is intended to help users of the 3commas.io platform backtest bot performance based on a Bollinger Strategy. // It can also be used to signal a bot to open a deal by providing the Bot ID, email token and trading pair in the strategy settings screen. // As currently written, this strategy uses a basic Bollinger Band strategy, recommening a deal start when the closing price crosses under the lower band. // The thick red line plotted on the chart shows the average entry price of the current deal. strategy("[v1.3laoowai]BNB_USDT_3m_3Commas_Bollinger_Strategy_by_tedwardd", overlay=true, default_qty_type=strategy.cash, default_qty_value=1000, initial_capital=900, currency="USD", commission_value=0.1) // 3Commas Bot settinsg bot_type = input(title="Simple bot", defval="simple", options=["simple", "composite"]) bot_id = input(title="3Commas Bot ID", defval="") email_token = input(title="Bot Email Token", defval="") base_order_size = input(title="Base order size",minval=10, step=1, defval=10) safety_order_size = input(title="Safety order size", minval=15, step=1, defval=400) volume_scale = input(title="Safety Order Vol Scale (%)", minval=0.00, step=0.01, defval=1.83) safety_step = input(title="Safety Order Step Scale (%)", minval=0.00, step=0.1, defval=1.55) safety_max = input(title="Max Number of Safety Orders", minval=0, step=1, defval=2) initial_deviation_input = input(title="Initial SO Deviation (%)", minval=0, step=0.01, defval=1.54) * 0.01 stoploss_input = input(title="Long Stop Loss (%)", minval=0, step=1, defval=15) * 0.01 takeprofit_input = input(title="Long Take Profit (%)", minval=0, step=1, defval=1.4) * 0.01 // USER INPUTS sma_short_val = input(title="Short MA Window", defval=21) sma_long_val = input(title="Long MA Window", defval=100) ubOffset = input(title="Upper Band Offset", defval=2.2, step=0.5) lbOffset = input(title="Lower Band Offset", defval=2.40, step=0.5) cross = input(title="Entrry at Cross Over/Under Lower", defval="under", options=["over", "under"]) // Backtesting Date Ranges startDate = input(title="Start Date", defval=1, minval=1, maxval=31) startMonth = input(title="Start Month", defval=1, minval=1, maxval=12) startYear = input(title="Start Year", defval=2016, minval=1800, maxval=2100) endDate = input(title="End Date", defval=31, minval=1, maxval=31) endMonth = input(title="End Month", defval=12, minval=1, maxval=12) endYear = input(title="End Year", defval=2022, minval=1800, maxval=2100) // VARS short_sma = sma(close, sma_short_val) long_sma = sma(close, sma_long_val) stdDev = stdev(close, sma_short_val) upperBand = short_sma + (stdDev * ubOffset) lowerBand = short_sma - (stdDev * lbOffset) stoploss_value = strategy.position_avg_price * (1 - stoploss_input) takeprofit_value = strategy.position_avg_price * (1 + takeprofit_input) initial_dev_val = strategy.position_avg_price * (1 - initial_deviation_input) inDateRange = true initial_deviation = close < initial_dev_val // Market Conditions goodBuy = cross=="over"?crossover(close, lowerBand):crossunder(close, lowerBand) // Buy when close crossing lower band safety = initial_deviation and (1-(close/strategy.position_avg_price))/.01 > strategy.opentrades-1 * safety_step and strategy.opentrades <= safety_max // SO when price deviates below SO threshold % stoploss = close <= stoploss_value // Stoploss condition - true if closing price for current bar drops below stoploss % takeprofit = close >= takeprofit_value // Take profit condition - true if closing price for current bar is >= take profit percentage goodSell = crossover(high, upperBand) // goodSell is currently unused for any practical purpose. If you wish to try it, switch these two values. // Doing so will make sell suggestions at high crossover upper bollinger but it does not trigger the bot to sell as written but may affect backtest results // Plot some lines plot(short_sma, color=color.green) plot(upperBand) plot(lowerBand, color=color.yellow) plot(strategy.position_avg_price, color=color.red, linewidth=3) // Webhook message. Defaults to string. To signal 3c bot, fill in bot_id and email_token in user settings var enter_msg = "Enter Position" var exit_msg = "Exit Position" var close_all = "Exit Position" if bot_id != "" and email_token != "" if bot_type == "composite" enter_msg := '{"message_type": "bot", "bot_id": ' + bot_id + ', "email_token": "' + email_token + '", "delay_seconds": 0, "pair": "' + syminfo.currency + "_" + syminfo.basecurrency + '"}' else enter_msg := '{"message_type": "bot", "bot_id": ' + bot_id + ', "email_token": "' + email_token + '", "delay_seconds": 0}' if bot_type == "composite" exit_msg := '{"message_type": "bot", "bot_id": ' + bot_id + ', "email_token": "' + email_token + '", "delay_seconds": 0, "pair": "' + syminfo.currency + "_" + syminfo.basecurrency + '", "action": "close_at_market_price"}' else exit_msg := '{"message_type": "bot", "bot_id": ' + bot_id + ', "email_token": "' + email_token + '", "delay_seconds": 0, "action": "close_at_market_price"}' close_all := '{"message_type": "bot", "bot_id": ' + bot_id + ', "email_token": "' + email_token + '", "delay_seconds": 0, "action": "close_at_market_price_all"}' actual_safety_size = float(safety_order_size) // Set safety order size to starting safety if strategy.opentrades > 1 // If we have more than two open trades we need to start scaling the safety size by the volume_scale actual_safety_size := (strategy.position_size - base_order_size) * volume_scale // Remove base order from total position size and scale it for next safety order // Momentum Strategy (BTC/USDT; 1h) - MACD (with source code) by Drun30 //@version=4 // Getting inputs fast_length = input(title="Fast Length", type=input.integer, defval=23,group="MACD") slow_length = input(title="Slow Length", type=input.integer, defval=16,group="MACD") src = input(title="Source", type=input.source, defval=open,group="MACD") signal_length = input(title="Signal Smoothing", type=input.integer, minval = 1, maxval = 50, defval = 9,group="MACD") sma_source1 = input(title="Simple MA FAST (Oscillator)", defval="EMA", options=["HMA","DHMA","THMA","FHMA","WMA","DWMA","TWMA","FWMA","SMA","DSMA","TSMA","FSMA","EMA","DEMA","TEMA","FEMA","RMA","DRMA","TRMA","FRMA"],group="MACD") sma_source2 = input(title="Simple MA SLOW (Oscillator)", defval="EMA", options=["HMA","DHMA","THMA","FHMA","WMA","DWMA","TWMA","FWMA","SMA","DSMA","TSMA","FSMA","EMA","DEMA","TEMA","FEMA","RMA","DRMA","TRMA","FRMA"],group="MACD") sma_signal = input(title="Simple MA(Signal Line)",defval="EMA", options=["HMA","DHMA","THMA","FHMA","WMA","DWMA","TWMA","FWMA","SMA","DSMA","TSMA","FSMA","EMA","DEMA","TEMA","FEMA","RMA","DRMA","TRMA","FRMA"],group="MACD") // Calculating ma(source,length,type)=> type=="FEMA"?4*ema(source,length)-ema(ema(ema(ema(source,length),length),length),length):type=="FSMA"?4*sma(source,length)-sma(sma(sma(sma(source,length),length),length),length):type=="FWMA"?4*wma(source,length)-wma(wma(wma(wma(source,length),length),length),length):type=="FRMA"?4*rma(source,length)-rma(rma(rma(rma(source,length),length),length),length):type=="TEMA"?3*ema(source,length)-ema(ema(ema(source,length),length),length):type=="TSMA"?3*sma(source,length)-sma(sma(sma(source,length),length),length):type=="TWMA"?3*wma(source,length)-wma(wma(wma(source,length),length),length):type=="TRMA"?3*rma(source,length)-rma(rma(rma(source,length),length),length):type=="EMA"?ema(source,length):type=="SMA"?sma(source,length):type=="WMA"?wma(source,length):type=="RMA"?rma(source,length):type=="DEMA"?2*ema(source,length)-ema(ema(source,length),length):type=="DSMA"?2*sma(source,length)-sma(sma(source,length),length):type=="DWMA"?2*wma(source,length)-wma(wma(source,length),length):type=="DRMA"?2*rma(source,length)-rma(rma(source,length),length):type=="HMA"?hma(source,length):type=="DHMA"?2*hma(source,length)-hma(hma(source,length),length):type=="THMA"?3*hma(source,length)-hma(hma(hma(source,length),length),length):type=="FHMA"?4*hma(source,length)-hma(hma(hma(hma(source,length),length),length),length):ema(source,length) fast_ma = ma(src,fast_length,sma_source1) slow_ma = ma(src,slow_length,sma_source2) macd = fast_ma - slow_ma //Differenza tra la media mobile veloce e quella lenta signal = ma(macd,signal_length,sma_signal) //usa o la SMA oppure la EMA sulla differenza tra la media mobile veloce e lenta hist = macd - signal //Differenza tra la differenza precedente e la media mobile della differenza use_stress=input(true,title="Use stress on recent bars",group="Stress") recent_stress=input(0.41,title="Stress on recent bars",group="Stress",step=0.01,minval=0.01,maxval=0.99) level=input(6,title="Level of stress",group="Stress") if use_stress macd:=macd*(1/(1-recent_stress)) if not na(macd[1]) macd:=pow((macd*(recent_stress)),level)+(1-recent_stress*macd[1]) use_ma= input(true,title="Use moving average (MACD)?",group="Moving Average") if use_ma macd:=ma(macd,input(36,title="Length",group="Moving Average"),input(title="Type MA",defval="THMA", options=["HMA","DHMA","THMA","FHMA","WMA","DWMA","TWMA","FWMA","SMA","DSMA","TSMA","FSMA","EMA","DEMA","TEMA","FEMA","RMA","DRMA","TRMA","FRMA"],group="Moving Average")) use_linreg= input(true,title="Use linear regression (MACD)?",group="Linear Regression") if use_linreg macd:=linreg(macd,input(10,title="Length",group="Linear Regression"),input(1,title="Offset",group="Linear Regression")) //macd == linea blu (differenza tra media mobile veloce e media mobile lenta) //signal == linea arancione (media mobile dell'macd) //hist == istogramma (differenza tra macd e media mobile) on_cross = input(false,title="Use cross macd and signal",group="Condition entry/exit") on_minmax = input(true,title="Use min/max macd",group="Condition entry/exit") aperturaLong = change(macd)>0//crossover(macd,signal) aperturashort=not (change(macd)>0)//crossunder(macd,signal) if on_cross on_minmax:=false aperturaLong := crossover(macd,signal) aperturashort := crossunder(macd,signal) if on_minmax on_cross:=false aperturaLong := change(macd)>0//crossover(macd,signal) aperturashort:=change(macd)<0//crossunder(macd,signal) rsiFilter = input(false,title="Use RSI filter?",group="RSI") rsiTP = input(true,title="Use RSI Take Profit?",group="RSI") len=input(22,title="RSI period",group="RSI") srcr=input(close,title="RSI source",group="RSI") rsi=rsi(srcr,len) ovb=input(90,title="Overbought height",group="RSI") ovs=input(45,title="Oversold height",group="RSI") okLong=rsi<ovb and change(macd)>0 and change(macd)[1]<=0 okShort=rsi>ovs and change(macd)<0 and change(macd)[1]>=0 if not rsiFilter okLong:=true okShort:=true usiLong=input(true,title="Use long?") usiShort=input(true,title="Use short?") chiusuraShort=rsi<ovs or (aperturaLong) chiusuraLong=rsi>ovb or (aperturashort) if rsiTP aperturaLong := change(macd)>0 and change(macd)[1]<=0 and rsi<ovb//crossover(macd,signal) aperturashort:=change(macd)<0 and change(macd)[1]>=0 and rsi>ovs//crossunder(macd,signal) if not rsiTP chiusuraShort:=okLong and aperturaLong chiusuraLong:=okShort and aperturashort //if chiusuraShort // strategy.close("SHORTISSIMO") //if usiLong and strategy.position_size<=0 and okLong and aperturaLong // strategy.entry("LONGHISSIMO",true) //if chiusuraLong // strategy.close("LONGHISSIMO") //if usiShort and strategy.position_size>=0 and okShort and aperturashort // strategy.entry("SHORTISSIMO",false) // Strategy Actions //Buy if inDateRange and goodBuy strategy.entry("Good Buy", strategy.long, base_order_size, when = strategy.opentrades <= 0, alert_message=enter_msg) if inDateRange and safety strategy.order("Good Buy", strategy.long, actual_safety_size, when = strategy.opentrades > 0, comment = "safety order", alert_message=enter_msg) // Sell if inDateRange and goodSell strategy.close_all(comment="Good sell point", alert_message=exit_msg) if inDateRange and stoploss strategy.close_all(comment="Stoploss", alert_message=exit_msg) //if inDateRange and takeprofit // strategy.close_all(comment="TP Target", alert_message=exit_msg) if usiShort and strategy.position_size>=0 and okShort and aperturashort strategy.close_all(comment="SHORTISSIMO", alert_message=exit_msg) //if chiusuraShort // strategy.close_all(comment="SHORTISSIMO1")