Estrategia de cruce de media móvil de bandas de Bollinger con oscilador de impulso


Fecha de creación: 2023-12-19 11:34:46 Última modificación: 2023-12-19 11:34:46
Copiar: 0 Número de Visitas: 652
1
Seguir
1621
Seguidores

Estrategia de cruce de media móvil de bandas de Bollinger con oscilador de impulso

Descripción general

La estrategia es una estrategia de comercio cuantitativa basada en los indicadores Bollinger Bands y MACD. Combina dos indicadores técnicos principales para identificar oportunidades de comercio con el objetivo de obtener una mayor probabilidad de éxito en situaciones de tendencia.

La estrategia se establece en la búsqueda de seguimiento de tendencia cuando el precio se rompe con el Bollinger Band, y se cierra cuando el precio se rompe; al mismo tiempo, se utiliza el indicador MACD para determinar la dirección del movimiento y filtrar las falsas rupturas. Se puede configurar el indicador RSI para ayudar a determinar la sobrecompra y la sobreventa para evitar más pérdidas.

Principio de estrategia

La estrategia se compone principalmente de los indicadores Bollinger Bands y MACD.

Las bandas de Bollinger se basan en el cálculo de la diferencia estándar del precio de las acciones para subir y bajar, las acciones son una señal de sobrecompra cuando el precio se eleva por encima de la subida, y una señal de sobreventa cuando el precio baja por debajo de la subida. Esta estrategia hace más cuando el precio se eleva por debajo de la subida, y se detiene cuando se cae por encima de la subida.

El indicador MACD determina el movimiento y la dirección del precio de las acciones. La brecha de la media corta en la media larga es una señal de compra, en cambio, es una señal de venta. Esta estrategia se combina con el indicador MACD para filtrar las falsas brechas de las bandas de Bollinger.

Además, el indicador RSI puede ayudar a determinar si está sobrecomprando o sobrevendendo. Cuando el RSI es bajo, significa que está sobrevendido y puede aumentar la señal de compra, y cuando el RSI es alto, significa que está sobrecomprando y puede aumentar la señal de venta.

Ventajas estratégicas

La estrategia combina Bollinger Bands, MACD y RSI, tres indicadores que permiten un buen entendimiento de las tendencias y fluctuaciones de los precios. Tiene las siguientes ventajas:

  1. El Bollinger Band puede determinar el rango de fluctuación de los precios y capturar el Trend Following
  2. El MACD determina la dirección del movimiento y filtra los informes falsos de Bollinger
  3. El RSI ayuda a los inversores a comprarse y venderse más de lo esperado, evitando así la subida de las posiciones.
  4. Se puede obtener una mayor tasa de éxito mediante la optimización de parámetros

Riesgo estratégico

La estrategia también tiene algunos riesgos de los que hay que estar alerta:

  1. El riesgo de pérdidas es mayor cuando los precios de las acciones fluctúan fuertemente
  2. Los parámetros no se ajustan a tiempo y la rentabilidad disminuye
  3. El índice MACD se equivoca cuando las tendencias se invierten

Respuesta:

  1. Disminución de los márgenes de amortización que sea apropiada
  2. Se necesita una serie de respuestas para encontrar la combinación óptima de parámetros
  3. Más indicadores pueden usarse para predecir cambios en los precios

Dirección de optimización de la estrategia

La estrategia tiene las siguientes direcciones de optimización principales:

  1. Optimización de los parámetros de las bandas de Bollinger para adaptarse a un mayor número de mercados
  2. Aumentar el número de indicadores de juicio y mejorar la estabilidad de la estrategia
  3. Optimización automática de parámetros con algoritmos de aprendizaje automático
  4. Prueba de la eficacia de la estrategia en datos de alta frecuencia
  5. Aumentar el módulo de gestión de fondos para controlar las pérdidas individuales

Resumir

En general, esta estrategia es una estrategia típica de seguimiento de tendencias. Combina varios indicadores técnicos para aumentar la estabilidad y obtener una buena tasa de éxito cuando se juzga con precisión.

Código Fuente de la Estrategia
/*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")