Chiến lược giao dịch hai chiều dựa trên các tín hiệu tăng và giảm của các chỉ số định lượng

Tác giả:ChaoZhang, Ngày: 2023-12-13 17:30:13
Tags:

img

Tổng quan

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.

Nguyên tắc chiến lược

  1. Sử dụng chỉ số kênh giá Donchain để xác định các kênh giá trên và dưới.

  2. 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.

  3. 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.

  4. Đó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.

Ưu điểm của Chiến lược

  1. 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.

  2. 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.

  3. 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.

  4. Thiết lập các chiến lược dừng lỗ quản lý rủi ro hiệu quả.

Rủi ro của chiến lược

  1. 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.

  2. 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.

  3. 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ỗ.

  4. 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.

Hướng dẫn tối ưu hóa chiến lược

  1. Tối ưu hóa các thông số kênh giá để tìm kết hợp tối ưu.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

Tóm lại

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)





Thêm nữa