CVD 다이버전스 양적 거래 전략


생성 날짜: 2024-03-15 16:47:47 마지막으로 수정됨: 2024-03-15 16:47:47
복사: 0 클릭수: 1606
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

CVD 다이버전스 양적 거래 전략

전략 요약: 이 CVD 이탈 수량 거래 전략은 CVD 지표와 가격 형성 이탈을 사용하여 잠재적인 트렌드 반전 신호를 포착한다. 이 전략은 CVD 지표를 계산하고 가격과 비교하여 부진 또는 하락 이탈이 형성되는지 판단한다. 이 전략은 부진 신호가 발생하면 과다 또는 공백을 취한다. 동시에 이동 스톱 손실과 고정 퍼센트 스톱을 사용하여 위험을 제어하고 이익을 잠금한다. 이 전략은 동시에 여러 위치의 피라미드 입장을 지원한다.

전략적 원칙:

  1. CVD 지표를 계산: 다중 헤드 트랜잭션과 빈 헤드 트랜잭션에 따라 CVD 지표와 이동 평균을 계산한다.
  2. 이탈을 식별: CVD 지표의 높고 낮은 점과 가격의 높고 낮은 점을 비교하여 이탈이 형성되는지 판단한다.
    • 가격 혁신이 낮지만 CVD 지표는 더 높은 하락점을 형성한다
    • 숨겨진 관측자 반발: 가격 혁신이 높지만 CVD 지표는 더 낮은 하락점을 형성합니다.
    • 평상시 하락: 가격 혁신 높지만 CVD 지표는 더 낮은 고점을 형성합니다.
    • 숨겨진 하락: 가격 혁신이 낮지만 CVD 지표는 더 높은 고점을 형성합니다.
  3. 포지션 개시: 탈방향 신호를 인식할 때, 탈방향 유형에 따라 포지션 개시를 더하거나 공백을 한다.
  4. 손해 차단: 이동식 손해 차단과 고정된 비율 차단을 사용한다. 손해 차단 가격은 포지션 개시 가격에 따라 손해 차단 비율을 곱하며, 손해 차단 가격은 포지션 개시 가격에 따라 손해 차단 비율을 곱한다.
  5. 피라미드 상장: 전략은 최대 3개의 포지션을 허용하는 피라미드 상장을 한다.

전략적 장점:

  1. 트렌드 반전 신호: CVD 이탈은 효과적인 트렌드 반전 신호이며, 트렌드 반전 기회를 잡는 데 도움이 된다.
  2. 트렌드 연장 신호: 숨겨진 이탈은 트렌드 연장 신호로 작용하여 전략이 트렌드 중 올바른 방향을 유지하도록 도와줍니다.
  3. 위험 제어: 이동식 스톱 손실과 고정된 퍼센티지 스톱 스을 사용하여 위험은 효과적으로 제어된다.
  4. 피라미드 포지션: 많은 포지션을 포지션으로 허용하여 트렌드 상황을 더 잘 활용할 수 있습니다.

전략적 위험:

  1. 신호의 유효성: 신호에서 벗어나는 것은 완전히 신뢰할 수 없습니다. 때로는 가짜 신호가 나타납니다.
  2. 매개 변수 구성: 정책 결과는 매개 변수 설정에 민감하며, 다른 매개 변수는 다른 결과를 가져올 수 있다.
  3. 스톱로스 슬라이드 포인트: 급격한 상황에서는 스톱로스 오더가 기본 가격으로 거래되지 않을 수 있으며, 추가적인 위험을 초래한다.
  4. 거래 비용: 빈번하게 입장을 열면 높은 거래 비용을 초래할 수 있으며, 전략적 수익에 영향을 미칠 수 있다.

최적화 방향:

  1. 동적 변수 최적화: 다양한 시장 상황에 적응하는 변수를 사용하여 신호의 효과를 높인다.
  2. 다른 지표와 결합: RSI, MACD 등과 같은 다른 기술 지표와 결합하여 신호 신뢰도를 높인다.
  3. 개선된 스톱: 추적 스톱, 변동률 스톱 등과 같은 더 고급 스톱 전략을 사용한다.
  4. 포지션 규모 관리: 시장의 변동률, 계좌 자금 등의 동적에 따라 포지션 규모를 조정한다.

결론: CVD의 주요 장점은 트렌드 반전 및 연장 신호를 효과적으로 포착하고 피라미드 가공을 통해 트렌드 상황을 더 잘 파악하는 데 있습니다. 그러나 이 전략에는 신호 유효성, 변수 구성, 중지 손실 슬라이드 및 거래 비용과 같은 위험이 있습니다.

전략 소스 코드
/*backtest
start: 2023-03-09 00:00:00
end: 2024-03-14 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/

//@version=5
//@ mmattman

//Thank you to @ contrerae and Tradingview each for parts of the code to make 
//this indicator and matching strategy and also theCrypster for the clean concise TP/SL code.

// indicator(title="CVD Divergence Indicator 1", shorttitle='CVD Div1', format=format.price, timeframe="", timeframe_gaps=true)

strategy("CVD Divergence Strategy.1.mm", shorttitle = 'CVD Div Str 1', overlay=false)


//..................................................................................................................
// Inputs
periodMa = input.int(title='MA Length', minval=1, defval=20)
plotMa = input(title='Plot MA?', defval=false)

// Calculations (Bull & Bear Balance Indicator by Vadim Gimelfarb)
iff_1 = close[1] < open ? math.max(high - close[1], close - low) : math.max(high - open, close - low)
iff_2 = close[1] > open ? high - low : math.max(open - close[1], high - low)
iff_3 = close[1] < open ? math.max(high - close[1], close - low) : high - open
iff_4 = close[1] > open ? high - low : math.max(open - close[1], high - low)
iff_5 = close[1] < open ? math.max(open - close[1], high - low) : high - low
iff_6 = close[1] > open ? math.max(high - open, close - low) : iff_5
iff_7 = high - close < close - low ? iff_4 : iff_6
iff_8 = high - close > close - low ? iff_3 : iff_7
iff_9 = close > open ? iff_2 : iff_8
bullPower = close < open ? iff_1 : iff_9
iff_10 = close[1] > open ? math.max(close[1] - open, high - low) : high - low
iff_11 = close[1] > open ? math.max(close[1] - low, high - close) : math.max(open - low, high - close)
iff_12 = close[1] > open ? math.max(close[1] - open, high - low) : high - low
iff_13 = close[1] > open ? math.max(close[1] - low, high - close) : open - low
iff_14 = close[1] < open ? math.max(open - low, high - close) : high - low
iff_15 = close[1] > open ? math.max(close[1] - open, high - low) : iff_14
iff_16 = high - close < close - low ? iff_13 : iff_15
iff_17 = high - close > close - low ? iff_12 : iff_16
iff_18 = close > open ? iff_11 : iff_17
bearPower = close < open ? iff_10 : iff_18

// Calculations (Bull & Bear Pressure Volume)
bullVolume = bullPower / (bullPower + bearPower) * volume
bearVolume = bearPower / (bullPower + bearPower) * volume

// Calculations Delta
delta = bullVolume - bearVolume
cvd = ta.cum(delta)
cvdMa = ta.sma(cvd, periodMa)

// Plotting
customColor = cvd > cvdMa ? color.new(color.teal, 50) : color.new(color.red, 50)
plotRef1 = plot(cvd, style=plot.style_line, linewidth=1, color=color.new(color.yellow, 0), title='CVD')
plotRef2 = plot(plotMa ? cvdMa : na, style=plot.style_line, linewidth=1, color=color.new(color.white, 0), title='CVD MA')
fill(plotRef1, plotRef2, color=customColor)
//..................................................................................................................


// len = input.int(title="RSI Period", minval=1, defval=14)
// src = input(title="RSI Source", defval=close)
lbR = input(title="Pivot Lookback Right", defval=3)
lbL = input(title="Pivot Lookback Left", defval=7)
rangeUpper = input(title="Max of Lookback Range", defval=60)
rangeLower = input(title="Min of Lookback Range", defval=5)
plotBull = input(title="Plot Bullish", defval=true)
plotHiddenBull = input(title="Plot Hidden Bullish", defval=true)
plotBear = input(title="Plot Bearish", defval=true)
plotHiddenBear = input(title="Plot Hidden Bearish", defval=true)
bearColor = color.red
bullColor = color.green
hiddenBullColor = color.new(color.green, 80)
hiddenBearColor = color.new(color.red, 80)
textColor = color.white
noneColor = color.new(color.white, 100)
osc = cvd

// plot(osc, title="CVD", linewidth=2, color=#2962FF)
// hline(50, title="Middle Line", color=#787B86, linestyle=hline.style_dotted)
// obLevel = hline(70, title="Overbought", color=#787B86, linestyle=hline.style_dotted)
// osLevel = hline(30, title="Oversold", color=#787B86, linestyle=hline.style_dotted)
// fill(obLevel, osLevel, title="Background", color=color.rgb(33, 150, 243, 90))

plFound = na(ta.pivotlow(osc, lbL, lbR)) ? false : true
phFound = na(ta.pivothigh(osc, lbL, lbR)) ? false : true
_inRange(cond) =>
	bars = ta.barssince(cond == true)
	rangeLower <= bars and bars <= rangeUpper

//------------------------------------------------------------------------------
// Regular Bullish
// Osc: Higher Low

oscHL = osc[lbR] > ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])

// Price: Lower Low

priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1)
bullCondAlert = priceLL and oscHL and plFound
bullCond = plotBull and bullCondAlert

plot(
     plFound ? osc[lbR] : na,
     offset=-lbR,
     title="Regular Bullish",
     linewidth=2,
     color=(bullCond ? bullColor : noneColor)
     )

plotshape(
	 bullCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bullish Label",
	 text=" Bull ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Hidden Bullish
// Osc: Lower Low

oscLL = osc[lbR] < ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1])

// Price: Higher Low

priceHL = low[lbR] > ta.valuewhen(plFound, low[lbR], 1)
hiddenBullCondAlert = priceHL and oscLL and plFound
hiddenBullCond = plotHiddenBull and hiddenBullCondAlert

plot(
	 plFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish",
	 linewidth=2,
	 color=(hiddenBullCond ? hiddenBullColor : noneColor)
	 )

plotshape(
	 hiddenBullCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bullish Label",
	 text=" H Bull ",
	 style=shape.labelup,
	 location=location.absolute,
	 color=bullColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Regular Bearish
// Osc: Lower High

oscLH = osc[lbR] < ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])

// Price: Higher High

priceHH = high[lbR] > ta.valuewhen(phFound, high[lbR], 1)

bearCondAlert = priceHH and oscLH and phFound
bearCond = plotBear and bearCondAlert

plot(
	 phFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish",
	 linewidth=2,
	 color=(bearCond ? bearColor : noneColor)
	 )

plotshape(
	 bearCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Regular Bearish Label",
	 text=" Bear ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )

//------------------------------------------------------------------------------
// Hidden Bearish
// Osc: Higher High

oscHH = osc[lbR] > ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1])

// Price: Lower High

priceLH = high[lbR] < ta.valuewhen(phFound, high[lbR], 1)

hiddenBearCondAlert = priceLH and oscHH and phFound
hiddenBearCond = plotHiddenBear and hiddenBearCondAlert

plot(
	 phFound ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish",
	 linewidth=2,
	 color=(hiddenBearCond ? hiddenBearColor : noneColor)
	 )

plotshape(
	 hiddenBearCond ? osc[lbR] : na,
	 offset=-lbR,
	 title="Hidden Bearish Label",
	 text=" H Bear ",
	 style=shape.labeldown,
	 location=location.absolute,
	 color=bearColor,
	 textcolor=textColor
	 )

// alertcondition(bullCondAlert, title='Regular Bullish CVD Divergence', message="Found a new Regular Bullish Divergence, `Pivot Lookback Right` number of bars to the left of the current bar")
// alertcondition(hiddenBullCondAlert, title='Hidden Bullish CVD Divergence', message='Found a new Hidden Bullish Divergence, `Pivot Lookback Right` number of bars to the left of the current bar')
// alertcondition(bearCondAlert, title='Regular Bearish CVD Divergence', message='Found a new Regular Bearish Divergence, `Pivot Lookback Right` number of bars to the left of the current bar')
// alertcondition(hiddenBearCondAlert, title='Hidden Bearisn CVD Divergence', message='Found a new Hidden Bearisn Divergence, `Pivot Lookback Right` number of bars to the left of the current bar')

le = bullCondAlert or hiddenBullCondAlert

se = bearCondAlert or hiddenBearCondAlert

ltp = se

stp = le

// Check if the entry conditions for a long position are met
if (le) //and (close > ema200)
    strategy.entry("Long", strategy.long, comment="EL")

 // Check if the entry conditions for a short position are met
if (se) //and (close < ema200)
    strategy.entry("Short", strategy.short, comment="ES")

// Close long position if exit condition is met
if (ltp) // or (close < ema200)
    strategy.close("Long", comment="XL")

    // Close short position if exit condition is met
if (stp) //or (close > ema200)
    strategy.close("Short", comment="XS")


// The Fixed Percent Stop Loss Code
// User Options to Change Inputs (%)
stopPer = input.float(5.0, title='Stop Loss %') / 100
takePer = input.float(10.0, title='Take Profit %') / 100

// Determine where you've entered and in what direction
longStop = strategy.position_avg_price * (1 - stopPer)
shortStop = strategy.position_avg_price * (1 + stopPer)
shortTake = strategy.position_avg_price * (1 - takePer)
longTake = strategy.position_avg_price * (1 + takePer)

if strategy.position_size > 0 
    strategy.exit("Close Long", "Long", stop=longStop, limit=longTake)
if strategy.position_size < 0 
    strategy.exit("Close Short", "Short", stop=shortStop, limit=shortTake)