Chiến lược này dựa trên các tín hiệu tăng và giảm được tạo ra bởi chỉ số kênh giá Donchain và chỉ số định lượng dao động OBV cho giao dịch hai hướng. Nó sử dụng chỉ số kênh giá để đánh giá sự đột phá và giảm giá, kết hợp với các chỉ số định lượng để xác định sức mạnh tăng và giảm, để tạo ra các tín hiệu giao dịch.
Sử dụng chỉ số kênh giá Donchain để xác định các kênh giá trên và dưới.
Xây dựng một dao động OBV bằng cách sử dụng chỉ số định lượng OBV và chỉ số EMA để xác định sức mạnh tăng và giảm. Giá trị dao động lớn hơn 0 cho thấy sức mạnh tăng vượt quá sức mạnh giảm và ngược lại nếu nhỏ hơn 0.
Một tín hiệu dài được tạo ra khi giá vượt qua kênh trên và dao động lớn hơn 0; Một tín hiệu ngắn được tạo ra khi giá vượt qua kênh dưới và dao động nhỏ hơn 0.
Đóng các vị trí dài khi giá rút trở lại kênh dưới; Đóng các vị trí ngắn khi giá rút trở lại kênh trên.
Sử dụng các kênh giá để xác định xu hướng tránh bị đánh lừa bởi thị trường biến động.
Việc kết hợp các chỉ số định lượng để đánh giá sức mạnh tăng và giảm đảm bảo hướng giao dịch phù hợp với sức mạnh thị trường.
Việc áp dụng giao dịch hai hướng cho phép lợi nhuận cho dù thị trường tăng hay giảm.
Thiết lập các chiến lược dừng lỗ quản lý rủi ro hiệu quả.
Cài đặt tham số không chính xác của các kênh giá có thể dẫn đến các kênh quá lỏng lẻo hoặc hẹp, bỏ lỡ các cơ hội giao dịch hoặc tạo ra các tín hiệu sai.
Cài đặt tham số chỉ số không chính xác cũng có thể dẫn đến việc tạo tín hiệu chậm hoặc sớm.
Các động thái biến động bất thường đột ngột từ các sự kiện có thể kích hoạt dừng lỗ dẫn đến lỗ.
Giao dịch hai hướng đòi hỏi phải quản lý đồng thời cả hai vị trí dài và ngắn làm cho nó khó hoạt động hơn.
Tối ưu hóa các thông số kênh giá để tìm kết hợp tối ưu.
Kiểm tra và tối ưu hóa các thông số dao động OBV để đảm bảo đánh giá kịp thời và chính xác về sức mạnh tăng / giảm.
Xem xét kết hợp các chỉ số khác như MACD, KD vv để cải thiện độ chính xác tín hiệu.
Kiểm tra các phương pháp dừng lỗ khác nhau, ví dụ như dừng theo dõi, dừng tỷ lệ phần trăm v.v.
Kiểm tra các sản phẩm khác nhau để tìm ra sản phẩm phù hợp nhất với chiến lược.
Nhìn chung, đây là một chiến lược giao dịch hai hướng rõ ràng, dễ hiểu kết hợp hành động giá và các chỉ số định lượng để xác định xu hướng và sức mạnh thị trường.
/*backtest start: 2022-12-06 00:00:00 end: 2023-12-12 00:00:00 period: 1d basePeriod: 1h 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/ // © ahancock //@version=4 strategy( title = "Hancock - Filtered Volume OBV OSC [Strategy]", initial_capital = 1000, overlay = false, commission_type = strategy.commission.percent, commission_value= 0.075) // Inputs source = input(close, title = "Source", type = input.source) use_volume_filter = input(true, title = "Use Volume Filter", type = input.bool) vol_filter_length = input(20, title = "Volume Filter - Length", type = input.integer, minval = 1) vol_filter_multiplier = input(1.2, title = "Volume Filter - Multiplier", type = input.float, minval = 0.1, step = 0.1) use_osc = input(true, title = "Use Oscillator", type = input.bool) osc_length = input(40, title = "Oscillator - Signal Length", type = input.integer, minval = 1) channel_length = input(65, title = "Channel - Slow Length", minval = 5, maxval = 200, step = 5) channel_percent = input(70, title = "Channel - Fast Length Percent", minval = 5, maxval = 100, step = 5) trade_both = "Both", trade_long = "Long", trade_short = "Short" trade_direction = input("Both", title = "Trade - Direction", options = [trade_both, trade_long, trade_short]) trade_leverage = input(2, title = "Trade - Leverage", type = input.integer, minval = 1, maxval = 100) trade_stop = input(7.5, title = "Trade - Stop Loss %", type = input.float, minval = 0.5, step = 0.5, maxval = 100) trade_trail_threshold = input(5, title = "Trade - Trail Stop Threshold %", type = input.float, minval = 0.5, step = 0.5, maxval = 100) trade_trail = input(5, title = "Trade - Trail Stop Minimum %", type = input.float, minval = 0.5, step = 0.5, maxval = 100) trade_risk = input(100, title = "Trade - Risk %", type = input.integer, step = 1, minval = 1, maxval = 100) test_year = input(2019, "Test - Year", type = input.integer, minval = 1970, maxval = 2222) test_month = input(01, "Test - Month", type = input.integer, minval = 1, maxval = 12) test_day = input(01, "Test - Day", type = input.integer, minval = 1, maxval = 31) // Functions get_round(value, precision) => round(value * (pow(10, precision))) / pow(10, precision) get_obv(values, filter_length, filter_multiplier, use_filter, osc_length, use_osc) => threshold = abs(avg(volume, filter_length) - (stdev(volume, filter_length) * filter_multiplier)) obv = 0.0 if (use_filter and volume < threshold) obv := nz(obv[1]) else obv := nz(obv[1]) + sign(change(values)) * volume use_osc ? (obv - ema(obv, osc_length)) : obv get_dc(high_values, low_values, length) => top = highest(high_values, length) bot = lowest(low_values, length) mid = bot + ((top - bot) / 2) [top, mid, bot] get_dcs(high_values, low_values, length, length_percent) => slow_length = length fast_length = slow_length * length_percent / 100 [slow_top, slow_mid, slow_bot] = get_dc(high_values, low_values, slow_length) [fast_top, fast_mid, fast_bot] = get_dc(high_values, low_values, fast_length) [slow_top, slow_mid, slow_bot, fast_top, fast_mid, fast_bot] // Strategy obv = get_obv( source, vol_filter_length, vol_filter_multiplier, use_volume_filter, osc_length, use_osc) [slow_top_price, _, slow_bot_price, fast_top_price, _, fast_bot_price] = get_dcs(high, low, channel_length, channel_percent) [slow_top_obv, _, slow_bot_obv, fast_top_obv, _, fast_bot_obv] = get_dcs(obv, obv, channel_length, channel_percent) enter_long_price = high > slow_top_price[1] exit_long_price = low < fast_bot_price[1] enter_short_price = low < slow_bot_price[1] exit_short_price = high > fast_top_price[1] enter_long_obv = obv > slow_top_obv[1] and (use_osc ? obv > 0 : true) enter_short_obv = obv < fast_bot_obv[1] and (use_osc ? obv < 0 : true) exit_long_obv = obv < slow_bot_obv[1] exit_short_obv = obv > fast_top_obv[1] // Trade Conditions can_trade = true enter_long_condition = enter_long_obv and enter_long_price exit_long_condition = exit_long_obv and exit_long_price enter_short_condition = enter_short_obv and enter_short_price exit_short_condition = exit_short_obv and exit_short_price position_signal = 0 position_signal := enter_long_condition ? 1 : enter_short_condition ? -1 : exit_long_condition or exit_short_condition ? 0 : position_signal[1] // Positions test_time = timestamp(test_year, test_month, test_day, 0, 0) if (time >= test_time and strategy.opentrades == 0) contracts = get_round((strategy.equity * trade_leverage / close) * (trade_risk / 100), 4) if (trade_direction == trade_both or trade_direction == trade_long) strategy.entry( "LONG", strategy.long, qty = contracts, when = enter_long_condition) if (trade_direction == trade_both or trade_direction == trade_short) strategy.entry( "SHORT", strategy.short, qty = contracts, when = enter_short_condition) in_long = strategy.position_size > 0 in_short = strategy.position_size < 0 float long_high = na float short_low = na long_high := in_long ? high >= nz(long_high[1], low) ? high : long_high[1] : na short_low := in_short ? low <= nz(short_low[1], high) ? low : short_low[1] : na long_change = abs(((long_high - strategy.position_avg_price) / strategy.position_avg_price) * 100) short_change = abs(((short_low - strategy.position_avg_price) / strategy.position_avg_price) * 100) threshold_difference = (strategy.position_avg_price / trade_leverage) * (trade_trail_threshold / 100) long_trail_threshold = in_long ? strategy.position_avg_price + threshold_difference : na short_trail_threshold = in_short ? strategy.position_avg_price - threshold_difference : na long_trail = in_long and long_high > long_trail_threshold ? long_high - (long_high / trade_leverage) * (trade_trail / 100) : na short_trail = in_short and short_low < short_trail_threshold ? short_low + (short_low / trade_leverage) * (trade_trail / 100) : na stop_difference = (strategy.position_avg_price / trade_leverage) * (trade_stop / 100) long_stop = in_long ? long_high > long_trail_threshold ? long_trail : strategy.position_avg_price - stop_difference : na short_stop = in_short ? short_low < short_trail_threshold ? short_trail : strategy.position_avg_price + stop_difference : na strategy.exit("S/L", "LONG", stop = long_stop, qty = abs(get_round(strategy.position_size, 4))) strategy.exit("S/L", "SHORT", stop = short_stop, qty = abs(get_round(strategy.position_size, 4))) strategy.close_all(when = abs(change(position_signal)) > 0) // Plots plotshape(enter_long_condition, "Enter Long", shape.diamond, location.top, color.green) plotshape(exit_long_condition, "Exit Long", shape.diamond, location.top, color.red) plotshape(enter_short_condition, "Enter Short", shape.diamond, location.bottom, color.green) plotshape(exit_short_condition, "Exit Short", shape.diamond, location.bottom, color.red) color_green = #63b987 color_red = #eb3d5c hline(use_osc ? 0 : na) plot(use_osc ? obv : na, color = color.silver, style = plot.style_area, transp = 90) plot(obv, color = color.white, style = plot.style_line, linewidth = 2, transp = 0) plot_slow_top = plot(slow_top_obv, color = color_green, linewidth = 2, transp = 60) plot_slow_bot = plot(slow_bot_obv, color = color_green, linewidth = 2, transp = 60) fill(plot_slow_top, plot_slow_bot, color = color_green, transp = 90) plot_fast_top = plot(fast_top_obv, color = color_red, linewidth = 2, transp = 60) plot_fast_bot = plot(fast_bot_obv, color = color_red, linewidth = 2, transp = 60) fill(plot_fast_top, plot_fast_bot, color = color_red, transp = 90)