
Chiến lược phá vỡ chấn động trung bình VWAP kép sử dụng phân tích xu hướng thị trường bằng hai đường trung bình VWAP để tìm cơ hội phá vỡ trong thị trường chấn động. Nó kết hợp với chỉ số ADX để xác định thị trường có bị chấn động hay không và sử dụng hai đường trung bình VWAP khác nhau để tìm kiếm một mục nhập dưới lỗ phá vỡ.
Chiến lược này bao gồm:
Thiết lập VWAP: tính toán đường trung bình VWAP và băng thông của nó. băng thông VWAP nội bộ thông quastDevMultiplierKiểm soát, mặc định 1; băng thông VWAP bên ngoài thông quastDevMultiplierKiểm soát, mặc định 2.
Thiết lập ADX: tính giá trị ADX để xác định thị trường có bị chấn động hay không. Khi ADX thấp hơn giá trị giảm giá thì xác định là thị trường bị chấn động. Các tham số ADX có thể được cấu hình.
Cài đặt đầu vào: Cài đặt đầu vào khi giá phá vỡ băng thông VWAP bên ngoài trong thị trường biến động. Có thể cấu hình giá dừng lỗ và giá dừng.
Hạn chế nhập cảnh: Có thể chọn lọc theo đường trung bình hoặc khoảng thời gian của EMA để tránh nhập cảnh vào những thời điểm không thích hợp.
Phương thức kiếm tiền: Theo dõi dừng lỗ hoặc dừng lỗ khi giá phá vỡ. Bạn có thể chọn phá vỡ giá ngoài VWAP exiting.
Chiến lược này sử dụng chỉ số ADX để đánh giá các biến động và tìm kiếm cơ hội thâm nhập khi giá vượt qua băng thông VWAP. Các băng tần VWAP kép cung cấp nhiều bộ lọc hơn để đảm bảo sức mạnh của thâm nhập. Theo dõi dừng lỗ làm cho lợi nhuận ổn định hơn.
Các băng VWAP kép cung cấp bộ lọc thêm vào để đảm bảo thời gian nhập cảnh mạnh mẽ.
Chỉ số ADX đánh giá thị trường bất ổn, tránh nhầm lẫn trong xu hướng.
Theo dõi Stop Loss để giữ lợi nhuận và tránh bị mắc kẹt.
Có nhiều tham số có thể cấu hình và có khả năng thích ứng.
Những ý tưởng này rất rõ ràng, dễ hiểu, dễ sao chép và sửa đổi.
Thiết lập tham số không chính xác có thể dẫn đến việc quá mạnh vào sân hoặc hòa. Cấu trúc tham số tối ưu hóa đảm bảo sự ổn định của chiến lược.
Theo dõi dừng lỗ dễ bị quá quyết liệt hoặc bảo thủ. Kết hợp với chỉ số dao động của chỉ số dao động để điều chỉnh vị trí dừng lỗ.
Hiệu suất nhạy cảm với thời gian giao dịch. Có thể được tối ưu hóa thông qua bộ lọc thời gian, đảm bảo hiệu quả đầu vào.
Chỉ số VWAP nhạy cảm với giá bất thường. Kết hợp với các chỉ số khác xác nhận giá hợp lý.
Động thái điều chỉnh mức độ dừng. Bạn có thể điều chỉnh vị trí dừng theo thời gian thực dựa trên các chỉ số như tỷ lệ dao động.
Nhiều khung thời gian xác nhận thời gian nhập học. Thêm các chỉ số xu hướng và cơ quan có khung thời gian cao hơn để tránh nhập học ngược.
Xem xét quản lý vị trí. Điều chỉnh tỷ lệ vị trí theo biến động và số tiền tài khoản.
Kiểm tra hiệu suất của các chu kỳ VWAP khác nhau. Việc thiết lập chu kỳ VWAP quyết định chu kỳ nắm giữ chiến lược và có thể được tối ưu hóa.
Chiến lược đột phá VWAP hai chiều bằng nhau cung cấp bộ lọc nhập thêm bằng cách sử dụng hai vùng VWAP để đánh giá ADX cho sự biến động của thị trường. Ý tưởng chiến lược rõ ràng và dễ thực hiện hơn.
/*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)