
이중 VWAP 평균선 흔들림 돌파 전략은 이중 VWAP 평균선 분석을 통해 시장의 경향성을 분석하여 흔들림 시장에서 돌파 기회를 찾습니다. ADX 지표와 결합하여 시장이 흔들리고 있는지 판단하고 두 가지 다른 표준 차이가있는 VWAP 평균선을 사용하여 돌파문 아래의 단일 입구를 찾습니다.
이 전략은 다음과 같은 부분들로 구성됩니다.
VWAP 설정: VWAP 평균선과 그 대역폭을 계산한다. 내부 VWAP 대역폭이 통과stDevMultiplier제어, 기본 1; 외부 VWAP 대역폭을 통해stDevMultiplier통제, 암묵적 2 ᆞ
ADX 설정: ADX값을 계산하여 시장이 흔들리는지 판단한다. ADX가 하락값보다 낮으면 흔들리는 시장으로 판단한다. ADX 파라미터를 구성할 수 있다.
진입 설정: 흔들리는 시장에서 가격이 외부 VWAP 대역폭을 뚫을 때 진입한다. 중지 가격과 중지 가격을 구성할 수 있다.
제한 입시: 선택적으로 EMA 평균선 또는 시간대를 필터링하여 이상적이지 않은 시간에 입시를 피하십시오.
수익방법: 스톱로스를 추적하거나 스톱가격이 깨지면 청산한다. 가격 돌파구를 선택하여 VWAP를 출구한다.
이 전략은 ADX 지표를 통해 진동 상황을 판단하고 VWAP 대역폭을 뚫을 때 진입 기회를 찾습니다. 쌍 VWAP 대역은 더 많은 필터를 제공하여 진입 강도를 보장합니다.
이중 VWAP 테이프로 추가적인 출입 필터를 제공하여 강력한 출입 시간을 보장합니다.
ADX 지표는 변동하는 시장을 판단하고, 동향상태에 착오하는 것을 피한다.
“이런 일이 벌어진다면, 우리는 더 나은 삶을 살 수 있을 것입니다”.
구성 가능한 매개 변수가 풍부하고 적응력이 강하다.
이 아이디어는 명확하고 이해하기 쉽고, 복제하고 수정하기 쉽습니다.
매개 변수 설정이 잘못되면 과도한 진출이나 평점으로 이어질 수 있다. 매개 변수 조합을 최적화하여 전략의 안정성을 보장한다.
트래킹 스톱은 너무 급진적이거나 보수적이기 쉽다. 변동률 지표와 결합하여 스톱 위치를 동적으로 조정한다.
거래 시간에 민감한 성능. 시간 필터를 통해 최적화하여 효율적인 입장을 보장할 수 있다.
VWAP 지표는 비정상적인 가격에 민감하다. 다른 지표와 결합하여 가격 합리성을 확인한다.
동적으로 중지 손실의 폭을 조정한다. 변동률과 같은 지표에 따라 실시간으로 중지 손실 위치를 조정할 수 있다.
다중 타임프레임 진출 시점을 확인한다. 더 높은 타임프레임의 트렌드 및 기관 지표를 추가하여 역동적인 진출을 피한다.
포지션 관리를 고려한다. 변동률과 계좌 자금 동성에 따라 포지션 비율을 조정한다.
다양한 VWAP 주기 성능을 테스트한다. VWAP 주기 설정은 전략의 지분 기간을 결정하며, 최적화할 수 있다.
이중 VWAP 평선 흔들림 돌파 전략은 ADX를 통해 시장의 흔들림을 판단하여 이중 VWAP 대역을 활용하여 추가적인 입문 필터를 제공합니다. 전략 아이디어는 명확하고, 더 쉽게 실행할 수 있습니다. 매개 변수 조정, 손해 방지 최적화, 포지션 관리 등의 방법으로 전략 안정성을 크게 향상시킬 수 있습니다.
/*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)