양적 지표의 상승 및 하락 신호에 기초한 쌍방향 거래 전략

저자:차오장, 날짜: 2023-12-13 17:30:13
태그:

img

전반적인 설명

이 전략은 양방향 거래를 위한 Donchain 가격 채널 지표와 OBV 오시레이터 양적 지표에 의해 생성되는 상승 및 하락 신호에 기반합니다. 가격 채널 지표를 사용하여 가격 브레이크와 인기를 판단하고, 상승 및 하락 힘을 결정하는 양적 지표와 결합하여 거래 신호를 생성합니다.

전략 원칙

  1. Donchain 가격 채널 지표를 사용하여 상위 및 하위 가격 채널을 결정합니다. 상위 채널은 가장 높은 가격에서 계산되며 하위 채널은 가장 낮은 가격에서 계산됩니다.

  2. 올림과 하림 강도를 결정하기 위해 OBV 양적 지표와 EMA 지표를 사용하여 OBV 오시레이터를 구성합니다. 0 이상의 오시레이터 값은 올림 강도가 하림 강도를 초과하는 것을 나타냅니다. 0보다 작으면 역으로.

  3. 긴 신호는 가격이 상단 채널을 뚫고 오시레이터가 0보다 크면 생성됩니다. 짧은 신호는 가격이 하단 채널을 뚫고 오시레이터가 0보다 작을 때 생성됩니다.

  4. 가격이 하위 채널로 되돌아 갈 때 긴 포지션을 닫습니다. 가격이 상위 채널로 되돌아 갈 때 짧은 포지션을 닫습니다.

전략 의 장점

  1. 가격 채널을 사용하여 동향을 결정하면 변동적인 시장에 의해 오해를 피할 수 있습니다.

  2. 상승과 하락 강도를 판단하기 위한 양적 지표가 포함되면 거래 방향이 시장 강도와 일치한다는 것을 보장합니다.

  3. 쌍방향 거래를 채택하면 시장이 상승하거나 하락하더라도 이익을 얻을 수 있습니다.

  4. 스톱 로스 전략을 세우는 것은 위험을 효과적으로 관리합니다.

전략 의 위험

  1. 가격 채널의 부적절한 매개 변수 설정은 너무 느슨하거나 좁은 채널로 이어질 수 있고, 거래 기회를 놓치고 또는 잘못된 신호를 생성할 수 있습니다.

  2. 부적절한 지표 매개 변수 설정은 신호 생성 지연 또는 조기 발생으로 이어질 수 있습니다.

  3. 사건의 갑작스러운 비정상적인 변동은 손실로 이어지는 스톱 손실을 유발할 수 있습니다.

  4. 쌍방향 거래는 동시에 긴 포지션과 짧은 포지션을 관리해야 하며, 이를 통해 거래가 더 어려워집니다.

전략 최적화의 방향

  1. 최적의 조합을 찾기 위해 가격 채널 매개 변수를 최적화합니다.

  2. OBV 오시일레이터 매개 변수를 테스트하고 최적화하여 상승/하락 강도의 신속하고 정확한 판단을 보장합니다.

  3. 신호 정확성을 높이기 위해 MACD, KD 등과 같은 다른 지표를 통합하는 것을 고려하십시오.

  4. 다른 스톱 손실 방법을 테스트하십시오. 예를 들어 추적 스톱, 비율 스톱 등.

  5. 전략에 가장 적합한 제품을 찾기 위해 다양한 제품을 테스트하십시오.

요약

전체적으로 이것은 시장 추세와 힘을 결정하기 위해 가격 행동과 양적 지표를 통합하는 명확하고 이해하기 쉬운 양방향 거래 전략입니다. 또한 안정성과 수익성을 더 향상시키기 위해 매개 변수 조정 및 지표 조합을 통해 최적화 할 수있는 충분한 공간이 있습니다.


/*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)





더 많은