압축된 지표에 기초한 다시간 프레임 트렌드 거래 전략

저자:차오장, 날짜: 2024-02-27 17:40:03
태그:

img

전반적인 설명

이 전략은 붐 헌터 (Boom Hunter), 헐 스위트 (Hull Suite), 그리고 변동성 오시일레이터 (Volatility Oscillator) 인디케이터들을 결합하여 트렌드 추적 및 브레이크아웃 트레이딩을 위한 양적 전략을 여러 시간 프레임에 걸쳐 구현한다. 이는 비트코인과 같은 높은 변동성과 급격한 가격 움직임이 있는 디지털 자산에 적합하다.

원칙

이 전략의 핵심 논리는 다음 세 가지 지표에 기초합니다.

  1. 붐 헌터: 지표 압축 기법을 사용하여 두 분수 (Quotient1와 Quotient2) 사이의 교차에서 거래 신호를 생성하는 오시레이터입니다.

  2. 헬스 스위트: 중간선과 상부/하부 간 사이의 관계를 기반으로 트렌드 방향을 결정하는 평형 이동 평균선의 집합.

  3. 변동성 오시레이터: 가격 변동성을 정량화하는 오시레이터 지표입니다.

이 전략의 진입 논리는 붐 헌터의 두 쿼이언트 지표가 상향 또는 하향을 넘어서면, 가격이 헬스 미드라인을 뚫고 상위 또는 하위 밴드에서 벗어나면서 변동성 오시레이터가 과잉 구매 / 과잉 판매 영역에있을 때입니다. 이것은 일부 잘못된 브레이크 아웃 신호를 필터링하고 진입 정확도를 향상시킵니다.

스톱 손실은 특정 기간 동안 가장 낮은 계곡 또는 가장 높은 정점을 찾는 것으로 설정됩니다 (디폴트 20 바), 그리고 스톱 손실 비율을 구성 된 이익 인수로 곱하여 수익을 얻습니다 (디폴트 3x). 포지션 사이징은 전체 계좌 자금의 비율 (디폴트 3%) 및 도구의 특정 스톱 손실 범위에 따라 계산됩니다.

장점

  • 주요 거래 신호를 가격에서 추출하여 지표 압축 기술을 사용하여 수익성을 향상시킵니다.
  • 여러 지표의 조합은 잘못된 파장을 방지하고 트렌드 방향을 정확하게 결정합니다.
  • 동적 스톱 로스 및 영업 취득 설정은 위험 통제 추세를 허용
  • 변동성 오시레이터를 사용하여 높은 변동성 환경에서 거래를 보장합니다.
  • 다중 시간 프레임 분석을 통해 전략 안정성 강화

위험성

  • 붐 헌터 표시기는 압축 왜곡을 가질 수 있습니다, 잘못된 신호를 생성
  • 헬스 미들 라인은 늦어지고 실시간 가격 변화를 추적할 수 없습니다.
  • 변동성 감소 기간 동안 거래 기회를 놓치거나 강제 청산

해결책:

  1. 압축 지표 매개 변수를 조정하여 민감도를 균형 잡습니다.
  2. 중간선 대신 지수 이동 평균을 시도해보세요.
  3. 변동성 오류를 피하기 위해 다른 판단 지표를 추가합니다.

최적화

이 전략은 다음과 같은 측면에서 최적화 될 수 있습니다.

  1. 매개 변수 최적화: 기간과 압축 계수와 같은 지표 설정을 조정하여 최고의 매개 변수 조합을 얻으십시오.

  2. 시간 프레임 최적화: 최적의 거래 기간을 찾기 위해 다양한 기간 (1분, 5분, 30분 등) 을 테스트합니다.

  3. 위치 크기 최적화: 이상적인 자본 활용 계획을 찾기 위해 거래 위치 크기와 비율에 따른 변화

  4. 손실 최적화 중지: 최적의 위험/이익 비율을 달성하기 위해 다른 거래 도구에 기초한 스톱 로스 배치를 조정합니다.

  5. 조건 최적화: 더 정확한 입력 신호를 얻기 위해 표시 필터를 추가/감소

결론

이 전략은 붐 헌터 (Boom Hunter), 헐 스위트 (Hull Suite) 및 변동성 오시일레이터를 결합하여 다중 타임프레임 트렌드 추적 거래를 구현하여 매우 변동성 있는 디지털 자산에 적합한 급격한 가격 행동을 효과적으로 식별합니다. 제어 가능한 위험, 강력한 실용성 및 매개 변수 조정, 필터 조건 및 스톱 로스 최적화를 통해 확장성으로, 그것은 모범적인 양적 모델입니다.


/*backtest
start: 2024-01-27 00:00:00
end: 2024-02-26 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// Strategy based on the 3 indicators:
//  - Boom Hunter Pro
//  - Hull Suite
//  - Volatility Oscillator
//
// Strategy was designed for the purpose of back testing. 
// See strategy documentation for info on trade entry logic.
// 
// Credits:
//  - Boom Hunter Pro: veryfid (https://www.tradingview.com/u/veryfid/)
//  - Hull Suite: InSilico (https://www.tradingview.com/u/InSilico/)
//  - Volatility Oscillator: veryfid (https://www.tradingview.com/u/veryfid/)

//@version=5
strategy("Boom Hunter + Hull Suite + Volatility Oscillator Strategy", overlay=false, initial_capital=1000, currency=currency.NONE, max_labels_count=500, default_qty_type=strategy.cash, commission_type=strategy.commission.percent, commission_value=0.01)

// =============================================================================
// STRATEGY INPUT SETTINGS
// =============================================================================

// ---------------
// Risk Management
// ---------------
swingLength = input.int(20, "Swing High/Low Lookback Length", group='Strategy: Risk Management', tooltip='Stop Loss is calculated by the swing high or low over the previous X candles')
accountRiskPercent = input.float(3, "Account percent loss per trade", step=0.1, group='Strategy: Risk Management', tooltip='Each trade will risk X% of the account balance')
profitFactor = input.float(3, "Profit Factor (R:R Ratio)", step = 0.1, group='Strategy: Risk Management')

// ----------
// Date Range
// ----------
start_year = input.int(title='Start Date', defval=2022, minval=2010, maxval=3000, group='Strategy: Date Range', inline='1')
start_month = input.int(title='', defval=1, group='Strategy: Date Range', inline='1', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
start_date = input.int(title='', defval=1, group='Strategy: Date Range', inline='1', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
end_year = input.int(title='End Date', defval=2023, minval=1800, maxval=3000, group='Strategy: Date Range', inline='2')
end_month = input.int(title='', defval=1, group='Strategy: Date Range', inline='2', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
end_date = input.int(title='', defval=1, group='Strategy: Date Range', inline='2', options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31])
in_date_range = true

// =============================================================================
// INDICATORS
// =============================================================================

// ---------------
// Boom Hunter Pro
// ---------------
square = input.bool(true, title='Square Line?', group='Main Settings')
//Quotient
LPPeriod = input.int(6, title='Quotient | LPPeriod', inline='quotient', group='EOT 1 (Main Oscillator)')
K1 = input.int(0, title='K1', inline='quotient', group='EOT 1 (Main Oscillator)')
esize = 60  //, title = "Size", inline = "quotient2", group = "EOT 1 (Main Oscillator)")
ey = 50  //, title = "Y axis", inline = "quotient2", group = "EOT 1 (Main Oscillator)")
trigno = input.int(1, 'Trigger Length', group='EOT 1 (Main Oscillator)', inline='quotient2')
trigcol = input.color(color.white, title='Trigger Color:', group='EOT 1 (Main Oscillator)', inline='q2')

// EOT 2
//Inputs
LPPeriod2 = input.int(28, title='LPPeriod2', group='EOT 2 (Red Wave)', inline='q2')
K22 = input.float(0.3, title='K2', group='EOT 2 (Red Wave)', inline='q2')

//EOT 1
//Vars
alpha1 = 0.00
HP = 0.00
a1 = 0.00
b1 = 0.00
c1 = 0.00
c2 = 0.00
c3 = 0.00
Filt = 0.00
Peak = 0.00
X = 0.00
Quotient1 = 0.00
pi = 2 * math.asin(1)

//Highpass filter cyclic components
//whose periods are shorter than 100 bars
alpha1 := (math.cos(.707 * 2 * pi / 100) + math.sin(.707 * 2 * pi / 100) - 1) / math.cos(.707 * 2 * pi / 100)
HP := (1 - alpha1 / 2) * (1 - alpha1 / 2) * (close - 2 * nz(close[1]) + nz(close[2])) + 2 * (1 - alpha1) * nz(HP[1]) - (1 - alpha1) * (1 - alpha1) * nz(HP[2])

//SuperSmoother Filter
a1 := math.exp(-1.414 * pi / LPPeriod)
b1 := 2 * a1 * math.cos(1.414 * pi / LPPeriod)
c2 := b1
c3 := -a1 * a1
c1 := 1 - c2 - c3
Filt := c1 * (HP + nz(HP[1])) / 2 + c2 * nz(Filt[1]) + c3 * nz(Filt[2])

//Fast Attack - Slow Decay Algorithm
Peak := .991 * nz(Peak[1])
if math.abs(Filt) > Peak
    Peak := math.abs(Filt)
    Peak

//Normalized Roofing Filter
if Peak != 0
    X := Filt / Peak
    X

Quotient1 := (X + K1) / (K1 * X + 1)

// EOT 2
//Vars
alpha1222 = 0.00
HP2 = 0.00
a12 = 0.00
b12 = 0.00
c12 = 0.00
c22 = 0.00
c32 = 0.00
Filt2 = 0.00
Peak2 = 0.00
X2 = 0.00
Quotient4 = 0.00

alpha1222 := (math.cos(.707 * 2 * pi / 100) + math.sin(.707 * 2 * pi / 100) - 1) / math.cos(.707 * 2 * pi / 100)
HP2 := (1 - alpha1222 / 2) * (1 - alpha1222 / 2) * (close - 2 * nz(close[1]) + nz(close[2])) + 2 * (1 - alpha1222) * nz(HP2[1]) - (1 - alpha1222) * (1 - alpha1222) * nz(HP2[2])

//SuperSmoother Filter
a12 := math.exp(-1.414 * pi / LPPeriod2)
b12 := 2 * a12 * math.cos(1.414 * pi / LPPeriod2)
c22 := b12
c32 := -a12 * a12
c12 := 1 - c22 - c32
Filt2 := c12 * (HP2 + nz(HP2[1])) / 2 + c22 * nz(Filt2[1]) + c32 * nz(Filt2[2])

//Fast Attack - Slow Decay Algorithm
Peak2 := .991 * nz(Peak2[1])
if math.abs(Filt2) > Peak2
    Peak2 := math.abs(Filt2)
    Peak2

//Normalized Roofing Filter
if Peak2 != 0
    X2 := Filt2 / Peak2
    X2

Quotient4 := (X2 + K22) / (K22 * X2 + 1)
q4 = Quotient4 * esize + ey

//Plot EOT
q1 = Quotient1 * esize + ey
trigger = ta.sma(q1, trigno)
Plot3 = plot(trigger, color=trigcol, linewidth=2, title='Quotient 1')
Plot44 = plot(q4, color=color.new(color.red, 0), linewidth=2, title='Quotient 2')


// ----------
// HULL SUITE
// ----------

//INPUT
src = input(close, title='Source')
modeSwitch = input.string('Hma', title='Hull Variation', options=['Hma', 'Thma', 'Ehma'])
length = input(200, title='Length(180-200 for floating S/R , 55 for swing entry)')
lengthMult = input(2.4, title='Length multiplier (Used to view higher timeframes with straight band)')

useHtf = input(false, title='Show Hull MA from X timeframe? (good for scalping)')
htf = input.timeframe('240', title='Higher timeframe')

//FUNCTIONS
//HMA
HMA(_src, _length) =>
    ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
//EHMA    
EHMA(_src, _length) =>
    ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length)))
//THMA    
THMA(_src, _length) =>
    ta.wma(ta.wma(_src, _length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length)

//SWITCH
Mode(modeSwitch, src, len) =>
    modeSwitch == 'Hma' ? HMA(src, len) : modeSwitch == 'Ehma' ? EHMA(src, len) : modeSwitch == 'Thma' ? THMA(src, len / 2) : na

//OUT
_hull = Mode(modeSwitch, src, int(length * lengthMult))
HULL = useHtf ? request.security(syminfo.ticker, htf, _hull) : _hull
MHULL = HULL[0]
SHULL = HULL[2]

//COLOR
hullColor = MHULL > SHULL ? color.green : color.red

//PLOT
///< Frame
Fi1 = plot(-10, title='MHULL', color=hullColor, linewidth=2)

// -----------------
// VOLUME OSCILLATOR
// -----------------

volLength = input(80)
spike = close - open
x = ta.stdev(spike, volLength)
y = ta.stdev(spike, volLength) * -1
volOscCol = spike > x ? color.green : spike < y ? color.red : color.gray
plot(-30, color=color.new(volOscCol, transp=0), linewidth=2)


// =============================================================================
// STRATEGY LOGIC
// =============================================================================

// Boom Hunter Pro entry conditions
boomLong = ta.crossover(trigger, q4)
boomShort = ta.crossunder(trigger, q4)

// Hull Suite entry conditions
hullLong = MHULL > SHULL and close > MHULL
hullShort = MHULL < SHULL and close < SHULL

// Volatility Oscillator entry conditions
volLong = spike > x
volShort = spike < y

inLong = strategy.position_size > 0
inShort = strategy.position_size < 0

longCondition = boomLong and hullLong and volLong and in_date_range
shortCondition = boomShort and hullShort and volShort and in_date_range

swingLow = ta.lowest(source=low, length=swingLength)
swingHigh = ta.highest(source=high, length=swingLength)

atr = ta.atr(14)
longSl = math.min(close - atr, swingLow)
shortSl = math.max(close + atr, swingHigh)

longStopPercent = math.abs((1 - (longSl / close)) * 100)
shortStopPercent = math.abs((1 - (shortSl / close)) * 100)

longTpPercent = longStopPercent * profitFactor
shortTpPercent = shortStopPercent * profitFactor
longTp = close + (close * (longTpPercent / 100))
shortTp = close - (close * (shortTpPercent / 100))

// Position sizing (default risk 3% per trade)
riskAmt = strategy.equity * accountRiskPercent / 100
longQty = math.abs(riskAmt / longStopPercent * 100) / close
shortQty = math.abs(riskAmt / shortStopPercent * 100) / close

if (longCondition and not inLong)
    strategy.entry("Long", strategy.long, qty=longQty)
    strategy.exit("Long  SL/TP", from_entry="Long", stop=longSl, limit=longTp, alert_message='Long SL Hit')
    buyLabel = label.new(x=bar_index, y=high[1], color=color.green, style=label.style_label_up)
    label.set_y(id=buyLabel, y=-40)
    label.set_tooltip(id=buyLabel, tooltip="Risk Amt: " + str.tostring(riskAmt) + " Qty: " + str.tostring(longQty) + " Swing low: " + str.tostring(swingLow) + " Stop Percent: " + str.tostring(longStopPercent) + " TP Percent: " + str.tostring(longTpPercent))

if (shortCondition and not inShort)
    strategy.entry("Short", strategy.short, qty=shortQty)
    strategy.exit("Short  SL/TP", from_entry="Short", stop=shortSl, limit=shortTp, alert_message='Short SL Hit')
    sellLabel = label.new(x=bar_index, y=high[1], color=color.red, style=label.style_label_up)
    label.set_y(id=sellLabel, y=-40)
    label.set_tooltip(id=sellLabel, tooltip="Risk Amt: " + str.tostring(riskAmt) + " Qty: " + str.tostring(shortQty) + " Swing high: " + str.tostring(swingHigh) + " Stop Percent: " + str.tostring(shortStopPercent) + " TP Percent: " + str.tostring(shortTpPercent))


더 많은