ダブルVWAP振動突破戦略は,ダブルVWAP帯を使用して市場動向を分析し,振動する市場における突破機会を探します.市場が振動しているかどうかを判断するためにADX指標を組み合わせ,ブレイクアウトエントリーポイントを特定するために異なる標準偏差の2つのVWAP帯を使用します.
戦略は以下の主要要素で構成されています.
VWAP 設定: VWAP 帯域とその幅を計算します.stDevMultiplier
外側のVWAP幅は,stDevMultiplier
2に設定します.
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)