Estrategia de ruptura de oscilación de media móvil VWAP doble


Fecha de creación: 2023-11-23 11:10:28 Última modificación: 2023-11-23 11:10:28
Copiar: 1 Número de Visitas: 471
1
Seguir
1237
Seguidores

Estrategia de ruptura de oscilación de media móvil VWAP doble

Descripción general

La estrategia de ruptura de la oscilación de la media de VWAP doble analiza la tendencia del mercado a través de la media de VWAP doble, para buscar oportunidades de ruptura en mercados convulsionados. Combina el indicador ADX para determinar si el mercado está convulsionado y utiliza dos medias de VWAP de diferentes parámetros para buscar entradas individuales debajo de la brecha.

Principio de estrategia

La estrategia se compone principalmente de las siguientes partes:

  1. Configuración VWAP: Calcula la línea media VWAP y su ancho de banda. Ancho de banda VWAP internostDevMultiplierControl, por defecto 1; el ancho de banda VWAP externo pasastDevMultiplierControl y consentimiento 2.

  2. Configuración de ADX: Calcula el valor de ADX para determinar si el mercado está convulsionado. Cuando el ADX está por debajo de la devaluación, se determina que el mercado está convulsionado. Los parámetros de ADX se pueden configurar.

  3. Configuración de entrada: en un mercado de turbulencias, la entrada se realiza cuando el precio supera el ancho de banda VWAP externo. Se puede configurar el precio de parada y el precio de parada.

  4. Limitación de la entrada: Se puede elegir la línea media o el filtro de tiempo de la EMA para evitar la entrada en momentos no ideales.

  5. La forma de obtener ganancias: seguir el stop loss o cerrar la posición cuando el precio se rompa. Se puede elegir la salida de VWAP fuera de la ruptura del precio.

La estrategia determina el movimiento de la oscilación a través del indicador ADX y busca oportunidades de entrada cuando el precio supera el ancho de banda VWAP. Las bandas VWAP duales ofrecen más filtración y aseguran la fuerza de entrada. El seguimiento de las paradas hace que los beneficios sean más estables.

Análisis de las ventajas

  1. Las cintas VWAP dobles proporcionan un filtro de entrada adicional para garantizar una buena puntuación.

  2. El índice ADX es un indicador de la volatilidad del mercado para evitar caer en la tendencia.

  3. El seguimiento de las pérdidas para bloquear las ganancias y evitar la cárcel.

  4. La configuración de los parámetros es rica y adaptable.

  5. Las ideas son claras, fáciles de entender, copiar y modificar.

Riesgos y soluciones

  1. La configuración inadecuada de los parámetros puede conducir a una entrada demasiado agresiva en el campo o a una posición baja. La combinación de parámetros optimizada asegura la estabilidad de la estrategia.

  2. El seguimiento de las paradas es fácilmente demasiado radical o conservador. Combinado con el índice de volatilidad, ajusta dinámicamente la posición de las paradas.

  3. El rendimiento es sensible al momento de la transacción. Se puede optimizar a través de un filtro de tiempo para asegurar una entrada eficiente.

  4. El indicador VWAP es sensible a los precios anormales. En combinación con otros indicadores, confirma la racionalidad de los precios.

Dirección de optimización

  1. Ajuste dinámico de la amplitud de la parada. Puede ajustar la posición de la parada en tiempo real según indicadores como la tasa de fluctuación.

  2. Multiple timeframe Confirmar el momento de la entrada ❚ Agregar indicadores de tendencias y agencias con un tiempo más alto para evitar la entrada en contra ❚

  3. Considere la gestión de posiciones. Ajuste el porcentaje de posiciones según la volatilidad y la dinámica de los fondos de la cuenta.

  4. Prueba el rendimiento de diferentes ciclos VWAP. La configuración del ciclo VWAP determina el período de tenencia de la estrategia, que se puede optimizar.

Resumir

La estrategia de ruptura de la oscilación de la línea media de VWAP doble proporciona un filtro de entrada adicional mediante el uso de la banda de VWAP doble para juzgar la oscilación del mercado a través de ADX. La estrategia es clara y más fácil de implementar.

Código Fuente de la Estrategia
/*backtest
start: 2023-10-23 00:00:00
end: 2023-11-22 00:00:00
period: 1h
basePeriod: 15m
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/
// © jordanfray

//@version=5
strategy(title="Double VWAP Strategy", overlay=true, scale=scale.none, max_bars_back=500, default_qty_type=strategy.percent_of_equity, default_qty_value=100,initial_capital=100000, commission_type=strategy.commission.percent, commission_value=0.05, backtest_fill_limits_assumption=2)

// Indenting Classs
indent_1 = " "
indent_2 = "  "
indent_3 = "   "
indent_4 = "    "

// Group Titles
group_one_title = "VWAP Settings"
group_two_title = "ADX Settings"
group_three_title = "Entry Settings"
group_four_title = "Limit Entries"

// Input Tips
adx_thresholdToolTip = "The minumn ADX value to allow opening a postion"
adxCancelToolTip= "You can optionally set a different lower value for ADX that will allow entries even if below the trigger threshold."

ocean_blue = color.new(#0C6090,0)
sky_blue = color.new(#00A5FF,0)
green = color.new(#2DBD85,0)
red = color.new(#E02A4A,0)
light_blue = color.new(#00A5FF,90)
light_green = color.new(#2DBD85,90)
light_red = color.new(#E02A4A,90)
light_yellow = color.new(#FFF900,90)
white = color.new(#ffffff,0)
transparent = color.new(#000000,100)

// Strategy Settings - VWAP
var cumVol = 0.
cumVol += nz(volume)
if barstate.islast and cumVol == 0
    runtime.error("No volume is provided by the data vendor.")
    
computeVWAP(src, isNewPeriod, stDevMultiplier) =>
    var float sum_src_vol = na
    var float sum_vol = na
    var float sum_src_src_vol = na

    sum_src_vol := isNewPeriod ? src * volume : src * volume + sum_src_vol[1]
    sum_vol := isNewPeriod ? volume : volume + sum_vol[1]
    sum_src_src_vol := isNewPeriod ? volume * math.pow(src, 2) : volume * math.pow(src, 2) + sum_src_src_vol[1]

    _vwap = sum_src_vol / sum_vol
    variance = sum_src_src_vol / sum_vol - math.pow(_vwap, 2)
    variance := variance < 0 ? 0 : variance
    standard_deviation = math.sqrt(variance)

    lower_band_value = _vwap - standard_deviation * stDevMultiplier
    upper_band_value = _vwap + standard_deviation * stDevMultiplier

    [_vwap, lower_band_value, upper_band_value]

var anchor = input.string(defval="Session", title="Anchor Period", options=["Session", "Week", "Month", "Quarter", "Year"], group=group_one_title)
src = input(defval = close, title = "Inner VWAP Source", group=group_one_title)
multiplier_inner = input(defval=1.0, title="Inner Bands Multiplier", group=group_one_title)
multiplier_outer = input(defval=2.0, title="Outer Bands Multiplier", group=group_one_title)
show_bands = true

timeChange(period) =>
   ta.change(time(period))

isNewPeriod = switch anchor
    "Session" => timeChange("D")
    "Week" => timeChange("W")
    "Month" => timeChange("M")
    "Quarter" => timeChange("3M")
    "Year" => timeChange("12M")
    => false

float vwap_val = na
float upper_inner_band_value = na
float lower_inner_band_value = na
float upper_outer_band_value = na
float lower_outer_band_value = na

[inner_vwap, inner_bottom, inner_top] = computeVWAP(src, isNewPeriod, multiplier_inner)
[outer_vwap, outer_bottom, outer_top] = computeVWAP(src, isNewPeriod, multiplier_outer)
vwap_val := inner_vwap
upper_inner_band_value := show_bands ? inner_top : na
lower_inner_band_value := show_bands ? inner_bottom : na
upper_outer_band_value := show_bands ? outer_top : na
lower_outer_band_value := show_bands ? outer_bottom : na

plot(vwap_val, title="VWAP", color=green)

upper_inner_band = plot(upper_inner_band_value, title="Upper Inner Band", color=sky_blue)
lower_inner_band = plot(lower_inner_band_value, title="Lower Inner Band", color=sky_blue)
upper_outer_band = plot(upper_outer_band_value, title="Upper Outer Band", linewidth=2, color=ocean_blue)
lower_outer_band = plot(lower_outer_band_value, title="Lower Outer Band", linewidth=2, color=ocean_blue)

fill(upper_outer_band, lower_outer_band, title="VWAP Bands Fill", color= show_bands ? light_blue : na)

// ADX Settings
adx_len = input.int(defval=14, title="ADX Smoothing", group=group_two_title)
di_len = input.int(defval=14, title="DI Length", group=group_two_title)
adx_threshold = input.int(defval=40, title="ADX Threshold", group=group_two_title, tooltip=adx_thresholdToolTip)
dirmov(len) =>
    up = ta.change(high)
    down = -ta.change(low)
    plus_dm = na(up) ? na : (up > down and up > 0 ? up : 0)
    minus_dm = na(down) ? na : (down > up and down > 0 ? down : 0)
    true_range = ta.rma(ta.tr, len)
    plus = fixnan(100 * ta.rma(plus_dm, len) / true_range)
    minus = fixnan(100 * ta.rma(minus_dm, len) / true_range)
    [plus, minus]

adx(di_len, adx_len) =>
    [plus, minus] = dirmov(di_len)
    sum = plus + minus
    adx = 100 * ta.rma(math.abs(plus - minus) / (sum == 0 ? 1 : sum), adx_len)

adx_val = adx(di_len, adx_len)
plot(adx_val, title="ADX")

// Entry Settings
stop_loss_val = input.float(defval=2.0, title="Stop Loss (%)", step=0.1, group=group_three_title)/100
take_profit_val = input.float(defval=6.0, title="Take Profit (%)", step=0.1, group=group_three_title)/100
long_entry_limit_lookback = input.int(defval=1, title="Long Entry Limit Lookback", minval=1, step=1, group=group_three_title)
short_entry_limit_lookback = input.int(defval=1, title="Short Entry Limit Lookback", minval=1, step=1, group=group_three_title)
limit_order_long_price = ta.lowest(close, long_entry_limit_lookback)
limit_order_short_price = ta.highest(close, short_entry_limit_lookback)
start_trailing_after = input.float(defval=3, title="Start Trailing After (%)", step=0.1, group=group_three_title)/100
trail_behind = input.float(defval=2, title="Trail Behind (%)", step=0.1, group=group_three_title)/100
close_early_if_crosses_outter_band = input.bool(defval=false, title="Close early if price crosses outer VWAP band")

// Limit Entries
enableEmaFilter = input.bool(defval=true, title="Use EMA Filter", group=group_four_title)
emaFilterTimeframe = input.timeframe(defval="", title=indent_4+"Timeframe", group=group_four_title)
emaFilterLength = input.int(defval=300, minval=1, step=10, title=indent_4+"Length", group=group_four_title)
emaFilterSource = input.source(defval=hl2, title=indent_4+"Source", group=group_four_title)
ema_filter = ta.ema(emaFilterSource, emaFilterLength)
ema_filter_smoothed = request.security(syminfo.tickerid, emaFilterTimeframe, ema_filter[barstate.isrealtime ? 1 : 0], gaps=barmerge.gaps_on)
plot(enableEmaFilter ? ema_filter_smoothed: na, title="EMA Macro Filter", linewidth=2, color=sky_blue, editable=true)

useTimeFilter = input.bool(defval=false, title="Use Time Session Filter", group=group_four_title)

withinTime = true


long_start_trailing_val = strategy.position_avg_price + (strategy.position_avg_price * start_trailing_after)
short_start_trailing_val = strategy.position_avg_price - (strategy.position_avg_price * start_trailing_after)
long_trail_behind_val = close - (strategy.position_avg_price * (trail_behind/100))
short_trail_behind_val = close + (strategy.position_avg_price * (trail_behind/100))
currently_in_a_long_postion = strategy.position_size > 0
currently_in_a_short_postion = strategy.position_size < 0
long_profit_target = strategy.position_avg_price * (1 + take_profit_val)
long_stop_loss = strategy.position_avg_price * (1.0 - stop_loss_val)
short_profit_target = strategy.position_avg_price * (1 - take_profit_val)
short_stop_loss = strategy.position_avg_price * (1 + stop_loss_val)
bars_since_entry = currently_in_a_long_postion or currently_in_a_short_postion ? bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1) + 1 : 5
plot(bars_since_entry, editable=false, title="Bars Since Entry", color=green)
long_run_up = ta.highest(high, bars_since_entry)
long_trailing_stop = currently_in_a_long_postion and bars_since_entry > 0 and long_run_up > long_start_trailing_val ? long_run_up - (long_run_up * trail_behind) : long_stop_loss
//long_run_up_line = plot(long_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? green : transparent)
long_trailing_stop_line = plot(long_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? long_trailing_stop > strategy.position_avg_price ? green : red : transparent)
short_run_up = ta.lowest(low, bars_since_entry)
short_trailing_stop = currently_in_a_short_postion and bars_since_entry > 0 and short_run_up < short_start_trailing_val ? short_run_up + (short_run_up * trail_behind) : short_stop_loss
//short_run_up_line = plot(short_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? green : transparent)
short_trailing_stop_line = plot(short_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? short_trailing_stop < strategy.position_avg_price ? green : red : transparent)


// Conditions
adx_is_below_threshold = adx_val < adx_threshold
price_crossed_down_VWAP_lower_outer_band = ta.crossunder(low, lower_outer_band_value)
price_closed_above_VWAP_lower_outer_band = close > lower_outer_band_value
price_crossed_up_VWAP_upper_outer_band =  ta.crossover(high,upper_outer_band_value)
price_closed_below_VWAP_upper_outer_band = close < upper_outer_band_value
price_above_ema_filter = close > ema_filter_smoothed
price_below_ema_filter = close < ema_filter_smoothed

//Trade Restirctions
no_trades_allowed = not withinTime or not adx_is_below_threshold

// Enter trades when...
long_conditions_met = enableEmaFilter ? price_above_ema_filter and not currently_in_a_long_postion and withinTime and adx_is_below_threshold and price_crossed_down_VWAP_lower_outer_band and price_closed_above_VWAP_lower_outer_band : not currently_in_a_long_postion and withinTime and adx_is_below_threshold and price_crossed_down_VWAP_lower_outer_band and price_closed_above_VWAP_lower_outer_band
short_conditions_met = enableEmaFilter ? price_below_ema_filter and not currently_in_a_short_postion and withinTime and adx_is_below_threshold and price_crossed_up_VWAP_upper_outer_band and price_closed_below_VWAP_upper_outer_band : not currently_in_a_short_postion and withinTime and adx_is_below_threshold and price_crossed_up_VWAP_upper_outer_band and price_closed_below_VWAP_upper_outer_band
plotshape(long_conditions_met ? close  : na, title="Long Entry Symbol", color=green, style=shape.triangleup, location=location.abovebar)
plotshape(short_conditions_met ? close  : na, title="Short Entry Symbol", color=red, style=shape.triangledown, location=location.belowbar)

// Take Profit When...
price_closed_below_short_trailing_stop = ta.cross(close, short_trailing_stop)
price_hit_short_entry_profit_target = low > short_profit_target
price_closed_above_long_entry_trailing_stop = ta.cross(close, long_trailing_stop)
price_hit_long_entry_profit_target = high > long_profit_target

long_position_take_profit = close_early_if_crosses_outter_band ? price_crossed_up_VWAP_upper_outer_band or price_closed_above_long_entry_trailing_stop or price_hit_long_entry_profit_target : price_closed_above_long_entry_trailing_stop or price_hit_long_entry_profit_target
short_position_take_profit = close_early_if_crosses_outter_band ? price_crossed_down_VWAP_lower_outer_band or price_closed_below_short_trailing_stop or price_hit_short_entry_profit_target : price_closed_below_short_trailing_stop or price_hit_short_entry_profit_target

// Cancel limir order if...
cancel_long_condition = false
cancel_short_condition = false


// Long Entry
strategy.entry(id="Long", direction=strategy.long, limit=limit_order_long_price, when=long_conditions_met)
strategy.cancel(id="Cancel Long", when=cancel_long_condition)
strategy.exit(id="Close Long", from_entry="Long", stop=long_trailing_stop, limit=long_profit_target, when=long_position_take_profit)

// Short Entry 
strategy.entry(id="Short", direction=strategy.short, limit=limit_order_short_price, when=short_conditions_met)
strategy.cancel(id="Cancel Short", when=cancel_short_condition)
strategy.exit(id="Close Short", from_entry="Short", stop=short_trailing_stop, limit=short_profit_target, when=short_position_take_profit)

entry = plot(strategy.position_avg_price, editable=false, title="Entry", style=plot.style_stepline, color=currently_in_a_long_postion or currently_in_a_short_postion ? color.blue : transparent, linewidth=1)
fill(entry,long_trailing_stop_line, editable=false, color=currently_in_a_long_postion ? long_trailing_stop > strategy.position_avg_price ? light_green : light_red : transparent)
fill(entry,short_trailing_stop_line, editable=false, color=currently_in_a_short_postion ? short_trailing_stop < strategy.position_avg_price ? light_green : light_red : transparent)
bgcolor(title="No Trades Allowed", color=no_trades_allowed ? light_red : light_green)