일반화 된 지원/저항에 기초한 역전 거래 전략

저자:차오장, 날짜: 2023-10-30 11:23:25
태그:

img

전반적인 설명

이 전략은 앞서 설정된 이윤 취득 수준과 함께 상승/하락 요인에 기반한 반전 거래를 채택한다. 요인의 핵심은 거래량에 기반한 확장 된 패턴인 '총괄 지원/ 저항'이며, 양량이 높고 변동성이 높은 주식에 적합하다. 장점은 중-단기간에 더 큰 반전 기회를 포착하고 빠르게 수익을 창출하는 데 있으며, 함락 될 위험이 있습니다.

전략 논리

  1. 부피와 함께 일반화된 지원/저항을 기반으로 상승/하락 요인을 식별

    • 촛불 패턴을 사용하여 중요한 부피에 의해 필터링된 고전적인 S/R 수준을 식별합니다.

    • 일반화된 S/R는 고전적인 패턴보다 더 나은 커버리지를 가지고 있습니다.

    • 일반화된 지원 신호를 깨는 긴 계수, 일반화된 저항 신호를 깨는 짧은 계수

  2. 리버스 거래

    • 요인 신호가 발사되면 역행 위치

    • 이미 위치가 있는 경우, 후퇴 위치를 줄이거나 추가합니다.

  3. 수익 목표 수준을 설정

    • ATR에 기초한 스톱 손실 설정

    • 1R, 2R, 3R 같은 여러 수익 수준을 설정

    • 다른 목표를 달성할 때 부분적인 수익

장점

  • 중장기적 반전률을 높이는 것

    S/R 브레이크는 중장기 반전을 감지할 수 있는 어느 정도의 신뢰성을 가진 강력한 반전 신호를 나타냅니다.

  • 급속한 수익, 작은 수요

    중지 손실 및 여러 이익 목표를 설정함으로써, 빠른 이윤을 달성 할 수 있습니다

  • 중요한 기관 자금과 변동성을 가진 주식에 적합합니다.

    이 전략은 규모에 의존하고, 상당한 제도적 참여가 필요합니다. 또한 수익을 창출하기 위해 변동성이 필요합니다.

위험성

  • 범위에 묶인 시장에 갇혀

    상반된 방향으로 자주 스톱 로스 출구와 재입구는 윙사우로 이어질 수 있습니다.

  • 지원/항압의 고장

    일반화된 S/R는 절대적으로 신뢰할 수 없습니다, 일부 장애가 있습니다

  • 일방적 보유 위험

    순수한 반전 논리는 큰 트렌드 기회를 놓칠 수 있습니다.

  • 위험 관리

    • 은 요소 조건, 모든 브레이크오웃에 역전되지 않습니다

    • 다른 필터를 추가합니다. 예를 들어 가격/량 차이

    • 함정을 줄이기 위해 스톱 로스 전략을 최적화하십시오.

개선 방향

  • S/R 매개 변수를 최적화

    일반 S / R 설정을 조정하여 더 신뢰할 수있는 요소를 찾으십시오

  • 수익을 최적화

    더 많은 수익 수준을 추가하거나 고정되지 않은 목표를 사용하십시오.

  • 스톱 손실을 최적화

    ATR 매개 변수를 조정하거나 불필요한 중지를 줄이기 위해 Stop Loss를 사용

  • 추세와 다른 요인을 포함

    큰 트렌드 충돌을 피하기 위해 이동 평균과 같은 트렌드 필터를 추가하십시오. 또한 다른 보조 요소를 추가하십시오.

요약

이 전략의 핵심은 반전 거래를 통해 적당한 중장기 변동을 포착하는 것입니다. 논리는 간단하고 직접적이며 매개 변수 조정으로 실용적 일 수 있습니다. 그러나 반전의 공격적인 성격은 약간의 인하 및 포획 위험에 దారితీస్తుంది. 중지 손실, 수익 취득 및 트렌드 정렬의 추가 향상은 불필요한 손실을 줄이는 데 도움이 될 것입니다.


/*backtest
start: 2023-09-29 00:00:00
end: 2023-10-29 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/
// © DojiEmoji

//@version=5
strategy("Fractal Strat [KL] ", overlay=true, pyramiding=1, initial_capital=1000000000)
var string ENUM_LONG = "Long"
var string GROUP_ENTRY = "Entry"
var string GROUP_TSL = "Stop loss"
var string GROUP_TREND = "Trend prediction"
var string GROUP_ORDER = "Order size and Profit taking"

// backtest_timeframe_start = input.time(defval=timestamp("01 Apr 2000 13:30 +0000"), title="Backtest Start Time")
within_timeframe = true

// TSL: calculate the stop loss price. {
_multiple       = input(2.0, title="ATR Multiplier for trailing stop loss", group=GROUP_TSL)
ATR_TSL         = ta.atr(input(14, title="Length of ATR for trailing stop loss", group=GROUP_TSL, tooltip="Initial risk amount = atr(this length) x multiplier")) * _multiple
TSL_source      = low
TSL_line_color  = color.green
TSL_transp      = 100
var stop_loss_price = float(0)

var float initial_entry_p    = float(0)
var float risk_amt           = float(0)
var float initial_order_size = float(0)

if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_TSL
else if strategy.position_size > 0
    stop_loss_price := math.max(stop_loss_price, TSL_source - ATR_TSL)
    TSL_transp := 0

plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// } end of "TSL" block


// Order size and profit taking {
pcnt_alloc = input.int(5, title="Allocation (%) of portfolio into this security", tooltip="Size of positions is based on this % of undrawn capital. This is fixed throughout the backtest period.", minval=0, maxval=100, group=GROUP_ORDER) / 100

// Taking profits at user defined target levels relative to risked amount (i.e 1R, 2R, 3R)
var bool  tp_mode = input(true, title="Take profit and different levels", group=GROUP_ORDER)
var float FIRST_LVL_PROFIT = input.float(1, title="First level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking first level profit at 1R means taking profits at $11", group=GROUP_ORDER)
var float SECOND_LVL_PROFIT = input.float(2, title="Second level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking second level profit at 2R means taking profits at $12", group=GROUP_ORDER)
var float THIRD_LVL_PROFIT = input.float(3, title="Third level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking third level profit at 3R means taking profits at $13", group=GROUP_ORDER)

// }

// Fractals {
// Modified from synapticEx's implementation: https://www.tradingview.com/script/cDCNneRP-Fractal-Support-Resistance-Fixed-Volume-2/

rel_vol_len = 6 // Relative volume is used; the middle candle has to have volume above the average (say sma over prior 6 bars)
rel_vol = ta.sma(volume, rel_vol_len)
_up = high[3]>high[4] and high[4]>high[5] and high[2]<high[3] and high[1]<high[2] and volume[3]>rel_vol[3]
_down = low[3]<low[4] and low[4]<low[5] and low[2]>low[3] and low[1]>low[2] and volume[3]>rel_vol[3]

fractal_resistance = high[3], fractal_support = low[3]   // initialize

fractal_resistance :=  _up ? high[3] : fractal_resistance[1]
fractal_support := _down ? low[3] : fractal_support[1]

plot(fractal_resistance, "fractal_resistance", color=color.new(color.red,50), linewidth=2, style=plot.style_cross, offset =-3, join=false)
plot(fractal_support, "fractal_support", color=color.new(color.lime,50), linewidth=2, style=plot.style_cross, offset=-3, join=false)
// }

// ATR diversion test {
// Hypothesis testing (2-tailed):
//
// Null hypothesis (H0) and Alternative hypothesis (Ha):
//     H0 : atr_fast equals atr_slow
//     Ha : atr_fast not equals to atr_slow; implies atr_fast is either too low or too high
len_fast    = input(5,title="Length of ATR (fast) for diversion test", group=GROUP_ENTRY)
atr_fast    = ta.atr(len_fast)
atr_slow    = ta.atr(input(50,title="Length of ATR (slow) for diversion test", group=GROUP_ENTRY, tooltip="This needs to be larger than Fast"))

// Calculate test statistic (test_stat)
std_error   = ta.stdev(ta.tr, len_fast) / math.pow(len_fast, 0.5)
test_stat = (atr_fast - atr_slow) / std_error

// Compare test_stat against critical value defined by user in settings
//critical_value = input.float(1.645,title="Critical value", tooltip="Strategy uses 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- this critical value, then H0 will be rejected.", group=GROUP_ENTRY)
conf_interval = input.string(title="Confidence Interval", defval="95%", options=["90%","95%","99%"], tooltip="Critical values of 1.645, 1.96, 2.58, for CI=90%/95%/99%, respectively; Under 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- critical value, then H0 will be rejected.")
critical_value = conf_interval == "90%" ? 1.645 : conf_interval == "95%" ? 1.96 : 2.58
reject_H0_lefttail = test_stat < -critical_value
reject_H0_righttail = test_stat > critical_value

// } end of "ATR diversion test" block

// Entry Signals
entry_signal_long = close >= fractal_support and reject_H0_lefttail

// MAIN {
// Update the stop limit if strategy holds a position.
if strategy.position_size > 0
    strategy.exit(ENUM_LONG, comment="SL", stop=stop_loss_price)

// Entry
if within_timeframe and entry_signal_long and strategy.position_size == 0
    initial_entry_p := close
    risk_amt := ATR_TSL
    initial_order_size := math.floor(pcnt_alloc * strategy.equity / close)
    strategy.entry(ENUM_LONG, strategy.long, qty=initial_order_size)

var int TP_taken_count = 0
if tp_mode and close > strategy.position_avg_price
    if close >= initial_entry_p + THIRD_LVL_PROFIT * risk_amt and TP_taken_count == 2
        strategy.close(ENUM_LONG, comment="TP Lvl3", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    else if close >= initial_entry_p + SECOND_LVL_PROFIT * risk_amt and TP_taken_count == 1
        strategy.close(ENUM_LONG, comment="TP Lvl2", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    else if close >= initial_entry_p + FIRST_LVL_PROFIT * risk_amt and TP_taken_count == 0
        strategy.close(ENUM_LONG, comment="TP Lvl1", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    
// Alerts
_atr = ta.atr(14)
alert_helper(msg) =>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + str.tostring(close, "#.##") + "; atr=" + str.tostring(_atr, "#.##") + ")"
    alert(str.tostring(prefix) + str.tostring(msg) + str.tostring(suffix), alert.freq_once_per_bar)

if strategy.position_size > 0 and ta.change(strategy.position_size)
    if strategy.position_size > strategy.position_size[1]
        alert_helper("BUY")
    else if strategy.position_size < strategy.position_size[1]
        alert_helper("SELL")

// Clean up - set the variables back to default values once no longer in use
if ta.change(strategy.position_size) and strategy.position_size == 0
    TP_taken_count := 0
    initial_entry_p := float(0)
    risk_amt := float(0)
    initial_order_size := float(0)
    stop_loss_price := float(0)
// } end of MAIN block


더 많은