역동적 위험 조정 동력 거래 전략

저자:차오장, 날짜: 2024-01-24 11:13:39
태그:

img

전반적인 설명

이 독특한 체계적인 규칙 기반 거래 전략은 다음 트렌드 범주에 속합니다. 원시 틱어 가격에서 생성 트레이딩 신호로 변환 된 표준화 된 가격 시리즈를 사용합니다. 기관 포트폴리오 관리에 일반적으로 예약 된 고급 위치 사이징 및 리스크 관리 기술이이 전략에서 사용됩니다. 재화 거래 자문자 및 관리 선물 펀드와 같은 금융 자문자가 사용하는 검증 된 위치 및 리스크 제어 기술.

전략 메커니즘

정상화 가격은 변동성 조정 축적 된 일일 수익 시리즈입니다. 일일 변동성 조정 룩백은 사용자 정의입니다. 정상화 가격의 Hull 이동 평균은 주요 트렌드 지표로 사용됩니다. HMA의 룩백 기간은 또한 사용자 정의이며, 과도한 거래를 유발하지 않고 반응 신호에 대한 기본 기간은 100일입니다.

핵심 거래는 간단합니다. 정상화 된 가격 크로스오버 HMA에서 긴, HMA 아래에서 크로스오버 때 짧은. 새로운 신호는 기존의 반대 입장을 닫습니다.

포지션 크기는 최근 가격 변동성과 사용자가 정의한 연간 위험 목표에 따라 동적으로 조정됩니다. 포지션은 위험 가중화, 낮은 변동성과 함께 더 큰 크기와 더 높은 변동성과 함께 작습니다. 최근 변동성은 지난 14 기간 동안의 수익의 표준 편차이며, 예상 수익으로 연간 변동성으로 추출됩니다. 연간 위험 목표는 변동성 조정 된 포지션 크기의 참조로 사용됩니다. 기본 목표는 총 자본의 10%입니다. 초기 자본은 거래당 최대 손실로 설정해야합니다. 최대 레버리지는 기본 자연 변동성이 충분하지 않으면 위험 목표를 달성 할 수 있으며 과도하게 낮은 변동성을 완화합니다.

하드 스톱은 최근 가격 평균 실제 범위 곱자에 기반합니다. 사용자 설정이 가능합니다.

장점

  • 정상화 된 가격은 잘못된 신호를 줄입니다.
  • 동적 위치 사이즈 컨트롤은 효과적으로 위험
  • 단단한 정류는 도망친 손실을 방지합니다
  • 투명성의 논리를 따르는 단순한 경향

위험성

  • 헐 이동 평균의 지연 문제
  • 변동성 조정된 포지션 사이즈를 통해 위험을 줄이는 동시에 수익을 제한하는 것
  • 너무 단단하게 막아 톱니에 취약하다

리스크 통제 조치에는 대체 이동 평균 선택, 리스크 목표의 조정 등이 포함됩니다.

개선

  • 다른 이동 평균의 시험 효과
  • 이동 평균의 매개 변수를 최적화
  • 길게만 사용하거나 짧게만 사용해보세요.
  • 미세 조율 중지 손실 범위
  • 다른 스톱 로스 메커니즘을 실험

결론

이 전략은 정상화, 동적 위치 조정, 위험을 제어하기 위한 하드 스톱과 같은 다양한 기술을 통합한다. 거래는 간단한 트렌드 다음 규칙을 기반으로 한다. 개인 선호도와 시장 체제에 따라 매개 변수를 조정할 수 있다. 실현 가능한 실제 세계 응용을 위해 추가 테스트와 검증을 할 가치가 있다.


/*backtest
start: 2023-01-17 00:00:00
end: 2024-01-23 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/
// © Crunchster1

//@version=5
strategy(title="Crunchster's Normalised Trend Strategy", shorttitle="Normalised Trend Strategy", overlay=false )

// Inputs and Parameters
src = input(close, 'Source', group='Strategy Settings')
length = input.int(title="Lookback period for price normalisation filter", defval=14, minval=2, group='Strategy Settings', tooltip='This sets the lookback period for the volatility adjustment of returns, which is used to transform the price series into the "real price"')
hlength = input.int(title="Lookback period for Hull Moving Average", defval=100, minval=2, group='Strategy Settings')
offset = input.int(title="HMA Offset", defval=0, minval=0, group='Strategy Settings')
long = input(true, 'Long', inline='08', group='Strategy Settings')
short = input(true, 'Short', inline='08', group='Strategy Settings', tooltip='Toggle long/short strategy on/off')

stopMultiple = input.float(1, 'Stop multiple', step=0.25, group='Risk Management Settings', tooltip='Multiple for ATR, setting hard stop loss from entry price')
lev = input.float(1, 'Max Leverage', step=0.5, group='Risk Management Settings', tooltip='Max leverage sets maximum allowable leverage of total capital (initial capital + any net profit), capping maximum volatility adjusted position size')
riskT = input.float(10, maxval=75, title='Annualised Volatility Target %', group='Risk Management Settings', tooltip='Specify annual risk target, used to determine volatility adjusted position size. Annualised daily volatility is referenced to this value and position size adjusted accordingly')
comp = input(false, 'Compounding', inline='09', group='Risk Management Settings')
Comppct = input.float(50, '%', step=5, inline='09', group='Risk Management Settings', tooltip='Toggle compounding of profit, and set % of profit to compound')

// Backtesting period
FromDay = input.int(defval=1, title='From Day', minval=1, maxval=31, inline='04', group='Backtest range')
FromMonth = input.int(defval=1, title='From Mon', minval=1, maxval=12, inline='04', group='Backtest range')
FromYear = input.int(defval=2018, title='From Yr', minval=1900, inline='04', group='Backtest range', tooltip='Set start of backtesting period')
ToDay = input.int(defval=1, title='To Day', minval=1, maxval=31, inline='05', group='Backtest range')
ToMonth = input.int(defval=1, title='To Mon', minval=1, maxval=12, inline='05', group='Backtest range')
ToYear = input.int(defval=9999, title='To Yr', minval=1900, inline='05', group='Backtest range', tooltip='Set end of backtesting period')

start = timestamp(FromYear, FromMonth, FromDay, 00, 00)
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)
window = true

// Normalised returns calculation
nRet = (src - src[1]) / ta.stdev((src - src[1]), length)

nPrice = ta.cum(nRet)

//Hull Moving Average - using normalised price series
fHMA = ta.wma(2 * ta.wma(nPrice[offset], hlength / 2) - ta.wma(nPrice[offset], hlength), math.round(math.sqrt(hlength)))

//Risk Management formulae
strategy.initial_capital = 50000
tr = math.max(high - low, math.abs(high - close), math.abs(low - close)) //True range
stopL = ta.sma(tr, 14) //Average true range
stdev = ta.stdev(close-close[1], 14) //volatility of recent returns
maxcapital = strategy.initial_capital+strategy.netprofit //Maximum capital available to invest - initial capital net of profit
annvol = 100*math.sqrt(365)*stdev/close //converts recent volatility of returns into annualised volatility of returns - assumes daily timeframe

risk = 1.1
if comp
    risk := (strategy.initial_capital+(Comppct*strategy.netprofit/100))//adjust investment capital to include compounding
else
    risk := strategy.initial_capital

shares = (risk * (riskT/annvol)) / close //calculates volatility adjusted position size, dependent on user specified annualised risk target
if ((shares*close) > lev*maxcapital) //ensures position size does not exceed available capital multiplied by user specified maximum leverage
    shares := lev*maxcapital/close

//To set the price at the entry point of trade
Posopen() =>
    math.abs(strategy.position_size[1]) <= 0 and math.abs(strategy.position_size) > 0

var float openN = na
if Posopen()
    openN := stopL

// Strategy Rules
if long
    longCondition = ta.crossover(nPrice, fHMA) and window
    exitlong = ta.crossunder(nPrice, fHMA)
    if (longCondition)
        strategy.entry('Go Long!', strategy.long, qty=shares)
    if strategy.position_size > 0    
        strategy.exit('Stop Long', from_entry = 'Go Long!', stop=(strategy.opentrades.entry_price(0) - (openN * stopMultiple)))
    if (exitlong)
        strategy.close('Go Long!', immediately = true)

if short
    shortCondition = ta.crossunder(nPrice, fHMA) and window
    exitshort = ta.crossover(nPrice, fHMA)
    if (shortCondition)
        strategy.entry('Go Short!', strategy.short, qty=shares)
    if strategy.position_size < 0   
        strategy.exit('Stop Short', from_entry = 'Go Short!', stop=(strategy.opentrades.entry_price(0) + (openN * stopMultiple)))
    if (exitshort)
        strategy.close('Go Short!', immediately = true)

// Visuals of trend and direction
plot(nPrice, title='Real Price', color=color.black)

MAColor = fHMA > fHMA[3] ? #00ff00 : #ff0000
MA1 = plot(fHMA, title='Hull MA', color=MAColor)
MA2 = plot(fHMA[3], title='Hull MA Offset', color=MAColor)
fill(MA1, MA2, title='Band Filler', color=MAColor)

더 많은