
A estratégia de ruptura de oscilação de linha média VWAP dupla analisa a tendência do mercado através da linha média VWAP dupla, procurando oportunidades de ruptura em mercados de turbulência. Combina o indicador ADX para determinar se o mercado está em turbulência e usa duas linhas médias VWAP de diferentes padrões para encontrar entradas individuais sob o portão de ruptura.
A estratégia é composta por:
Configuração do VWAP: Calcule a linha média do VWAP e a sua largura de banda. A largura de banda interna do VWAP passastDevMultiplierControle, padrão 1; VWAP de banda passandostDevMultiplierControle, aconselhamento 2
Configuração do ADX: Calcule o valor do ADX para determinar se o mercado está em choque. Quando o ADX está abaixo do valor de queda, o mercado é considerado em choque. Os parâmetros do ADX podem ser configurados.
Configuração de entrada: em um mercado de turbulência, a entrada ocorre quando o preço quebra a banda de banda externa do VWAP. Pode-se configurar o preço de parada de perda e o preço de parada.
Restrição de entrada: opcional EMA linha média ou filtro de período de tempo, para evitar a entrada em momentos não ideais.
Método de lucro: rastrear o stop loss ou o stop loss e fechar a posição quando o preço se rompe.
A estratégia julga oscilações através do indicador ADX, procurando oportunidades de entrada quando o preço ultrapassa a banda VWAP. A banda VWAP dupla oferece mais filtragem, garantindo a força de entrada. O rastreamento de stop loss torna os lucros mais estáveis.
A dupla faixa VWAP fornece filtros de entrada adicionais para garantir o tempo de entrada forte.
O ADX é um indicador que julga os mercados de turbulência para evitar erros de tendência.
Acompanhar o stop loss para travar o lucro e evitar a prisão.
Os parâmetros configuráveis são abundantes e adaptáveis.
A ideia é clara, fácil de entender, fácil de copiar e modificar.
A configuração inadequada dos parâmetros pode levar a entradas excessivamente agressivas ou posições vazias. A combinação de parâmetros optimizada garante a estabilidade da estratégia.
O rastreamento de stop loss pode ser muito radical ou conservador. Combinado com a volatilidade do indicador, o stop loss pode ser dinamicamente ajustado.
O desempenho é sensível ao tempo de negociação. Pode ser otimizado através de filtros de tempo, garantindo uma entrada eficiente.
O indicador VWAP é sensível a preços anormais. Em combinação com outros indicadores, confirma a razoabilidade dos preços.
Ajuste dinâmico da amplitude de parada. Pode ajustar a posição de parada em tempo real com base em indicadores como a taxa de flutuação.
Multi timeframe Confirmar o momento de entrada Adicionar tendências e indicadores institucionais de um timeframe mais alto, evitando a entrada de adversidade
Considere a gestão de posições. Ajuste a porcentagem de posições de acordo com a volatilidade e a dinâmica dos fundos da conta.
Teste o desempenho de diferentes ciclos VWAP. A configuração do ciclo VWAP determina o período de posse da estratégia, que pode ser otimizado.
A estratégia de ruptura de equilíbrio de VWAP duplo fornece um filtro de entrada adicional usando a banda VWAP dupla. A estratégia é clara e mais fácil de implementar. A estabilidade da estratégia pode ser significativamente aumentada por meio de ajustes de parâmetros, otimização de stop loss e gerenciamento de posição.
/*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)