오픈 클로즈 크로스 포인트 전략

저자:차오장, 날짜: 2023-12-13 15:51:13
태그:

img

전반적인 설명

오픈 클로즈 크로스 포인트 전략 (open close cross point strategy) 은 이동 평균 크로스오버를 기반으로 하는 양적 거래 전략이다. 빠른 이동 평균선과 느린 이동 평균선 사이의 크로스오버를 계산하여 가격 트렌드를 결정하고 크로스오버 포인트에서 구매 및 판매 신호를 생성한다. 이 전략은 헐 이동 평균을 빠른 라인으로, 슈퍼 슬로우 필터를 느린 라인으로 사용합니다. 이 조합은 이동 평균의 부드러움과 트렌드 결정 능력을 모두 통합하고 비교적 신뢰할 수있는 거래 신호를 생산하기 위해 가격 움직임을 효과적으로 식별 할 수 있습니다.

전략 원칙

오픈 클로즈 크로스 포인트 전략을 계산하는 공식은 다음과 같습니다. 빠른 라인 (Hull MA): WMA ((2 * WMA ((값, n/2) - WMA ((값, n), SQRT ((n)) 느린 라인 (슈퍼 슬로우더 필터): 가격 트리플 필터

여기서 WMA는 가중화 이동 평균이고, SQRT는 제곱근이고, 필터는 1차 차원의 지연 항과 2차 차원의 지연 항을 포함합니다.

전략은 빠른 라인과 느린 라인의 관계를 계산하여 판단합니다. 빠른 라인의 상향 교차는 구매 신호입니다
빠른 라인의 하향 교차는 판매 신호입니다

이점 분석

오픈 클로즈 크로스 포인트 전략은 이중 이동 평균 판단과 포인트 거래의 장점을 결합합니다. 적시에 진입 및 출구를위한 트렌드 전환점을 정확하게 포착 할 수 있습니다. 단일 이동 평균 전략에 비해 다음과 같은 장점이 있습니다.

  1. 이중 이동 평균 조합은 잘못된 신호를 제거합니다. 빠른 선은 트렌드 방향/강도를 결정합니다. 느린 선은 변동을 필터링하여 신호가 더 신뢰할 수 있습니다.
  2. 슈퍼 슬루더 필터는 가격 트렌드를 효과적으로 추출할 수 있는 뛰어난 데이터 조정 기능을 가지고 있습니다.
  3. 헐 MA는 가격 변화에 매우 민감하며, 역전을 적시에 발견할 수 있습니다.

위험 분석

개방형 클로스 포인트 전략은 또한 특정 위험을 안고 있습니다.

  1. 더 많은 윙사 신호가 시장 범위에서 발생할 수 있습니다. 잘못된 신호를 줄이기 위해 MA 사이의 간격을 넓힐 수 있습니다.
  2. 너무 넓은 간격은 신호 양과 품질을 균형 잡아야 할 기회를 놓칠 수 있습니다.
  3. 이 전략은 더 명확한 경향을 가진 제품에 더 적합하며 매우 휘발성 제품에는 바람직하지 않습니다.

최적화 방향

오픈 클로즈 크로스 포인트 전략은 다음 차원에서 최적화 될 수 있습니다.

  1. 각기 다른 기간과 변동성 범위의 상품에 맞게 MA 매개 변수를 조정합니다.
  2. 추세 품질을 결정하기 위해 추가 지표 또는 필터를 추가하여 윙사브를 줄이십시오.
  3. 트렌드 강도 지표를 적용하여 포지션 크기를 최적화하십시오.

결론

오픈 클로즈 크로스 포인트 전략은 더 진보되고 신뢰할 수있는 양적 거래 체계를 형성하기 위해 이중 이동 평균 판단과 포인트 거래 모델의 사용을 확장하면서 이동 평균 전략의 장점을 계승합니다. 실시간 테스트 및 응용 탐구를받을 자격이있는 타이밍 거래에서 독특한 장점을 가지고 있습니다. 이 기사는이 전략의 원칙, 강점 및 약점을 철저히 분석하고 참조에 최적화 아이디어를 제공합니다. 모델과 매개 변수에 대한 지속적인 개선으로이 전략이 강력한 시장 타이밍 도구가 될 것으로 믿어집니다.


/*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"}]
*/

//@version=5
//

strategy(title='Open Close Cross Strategy ', shorttitle='sacinvesting', overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=10, calc_on_every_tick=false)

// === INPUTS ===
useRes = input(defval=true, title='Use Alternate Resolution?')
intRes = input(defval=3, title='Multiplier for Alernate Resolution')
stratRes = timeframe.ismonthly ? str.tostring(timeframe.multiplier * intRes, '###M') : timeframe.isweekly ? str.tostring(timeframe.multiplier * intRes, '###W') : timeframe.isdaily ? str.tostring(timeframe.multiplier * intRes, '###D') : timeframe.isintraday ? str.tostring(timeframe.multiplier * intRes, '####') : '60'
basisType = input.string(defval='SMMA', title='MA Type: ', options=['SMA', 'EMA', 'DEMA', 'TEMA', 'WMA', 'VWMA', 'SMMA', 'HullMA', 'LSMA', 'ALMA', 'SSMA', 'TMA'])
basisLen = input.int(defval=8, title='MA Period', minval=1)
offsetSigma = input.int(defval=6, title='Offset for LSMA / Sigma for ALMA', minval=0)
offsetALMA = input.float(defval=0.85, title='Offset for ALMA', minval=0, step=0.01)
scolor = input(false, title='Show coloured Bars to indicate Trend?')
delayOffset = input.int(defval=0, title='Delay Open/Close MA (Forces Non-Repainting)', minval=0, step=1)
tradeType = input.string('BOTH', title='What trades should be taken : ', options=['LONG', 'SHORT', 'BOTH', 'NONE'])
// === /INPUTS ===

// Constants colours that include fully non-transparent option.
green100 = #008000FF
lime100 = #00FF00FF
red100 = #FF0000FF
blue100 = #0000FFFF
aqua100 = #00FFFFFF
darkred100 = #8B0000FF
gray100 = #808080FF

// === BASE FUNCTIONS ===
// Returns MA input selection variant, default to SMA if blank or typo.
variant(type, src, len, offSig, offALMA) =>
    v1 = ta.sma(src, len)  // Simple
    v2 = ta.ema(src, len)  // Exponential
    v3 = 2 * v2 - ta.ema(v2, len)  // Double Exponential
    v4 = 3 * (v2 - ta.ema(v2, len)) + ta.ema(ta.ema(v2, len), len)  // Triple Exponential
    v5 = ta.wma(src, len)  // Weighted
    v6 = ta.vwma(src, len)  // Volume Weighted
    v7 = 0.0
    sma_1 = ta.sma(src, len)  // Smoothed
    v7 := na(v7[1]) ? sma_1 : (v7[1] * (len - 1) + src) / len
    v8 = ta.wma(2 * ta.wma(src, len / 2) - ta.wma(src, len), math.round(math.sqrt(len)))  // Hull
    v9 = ta.linreg(src, len, offSig)  // Least Squares
    v10 = ta.alma(src, len, offALMA, offSig)  // Arnaud Legoux
    v11 = ta.sma(v1, len)  // Triangular (extreme smooth)
    // SuperSmoother filter
    // ©️ 2013 John F. Ehlers
    a1 = math.exp(-1.414 * 3.14159 / len)
    b1 = 2 * a1 * math.cos(1.414 * 3.14159 / len)
    c2 = b1
    c3 = -a1 * a1
    c1 = 1 - c2 - c3
    v12 = 0.0
    v12 := c1 * (src + nz(src[1])) / 2 + c2 * nz(v12[1]) + c3 * nz(v12[2])
    type == 'EMA' ? v2 : type == 'DEMA' ? v3 : type == 'TEMA' ? v4 : type == 'WMA' ? v5 : type == 'VWMA' ? v6 : type == 'SMMA' ? v7 : type == 'HullMA' ? v8 : type == 'LSMA' ? v9 : type == 'ALMA' ? v10 : type == 'TMA' ? v11 : type == 'SSMA' ? v12 : v1

// security wrapper for repeat calls
reso(exp, use, res) =>
    security_1 = request.security(syminfo.tickerid, res, exp, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
    use ? security_1 : exp

// === /BASE FUNCTIONS ===

// === SERIES SETUP ===
closeSeries = variant(basisType, close[delayOffset], basisLen, offsetSigma, offsetALMA)
openSeries = variant(basisType, open[delayOffset], basisLen, offsetSigma, offsetALMA)
// === /SERIES ===

// === PLOTTING ===

// Get Alternate resolution Series if selected.
closeSeriesAlt = reso(closeSeries, useRes, stratRes)
openSeriesAlt = reso(openSeries, useRes, stratRes)
//
trendColour = closeSeriesAlt > openSeriesAlt ? color.green : color.red
bcolour = closeSeries > openSeriesAlt ? lime100 : red100
barcolor(scolor ? bcolour : na, title='Bar Colours')
closeP = plot(closeSeriesAlt, title='Close Series', color=trendColour, linewidth=2, style=plot.style_line, transp=20)
openP = plot(openSeriesAlt, title='Open Series', color=trendColour, linewidth=2, style=plot.style_line, transp=20)
fill(closeP, openP, color=trendColour, transp=80)

// === /PLOTTING ===
//
//
// === ALERT conditions
xlong = ta.crossover(closeSeriesAlt, openSeriesAlt)
xshort = ta.crossunder(closeSeriesAlt, openSeriesAlt)
longCond = xlong  // alternative: longCond[1]? false : (xlong or xlong[1]) and close>closeSeriesAlt and close>=open
shortCond = xshort  // alternative: shortCond[1]? false : (xshort or xshort[1]) and close<closeSeriesAlt and close<=open
// === /ALERT conditions.

// === STRATEGY ===
// stop loss
slPoints = input.int(defval=0, title='Initial Stop Loss Points (zero to disable)', minval=0)
tpPoints = input.int(defval=0, title='Initial Target Profit Points (zero for disable)', minval=0)
// Include bar limiting algorithm
ebar = input.int(defval=10000, title='Number of Bars for Back Testing', minval=0)
dummy = input(false, title='- SET to ZERO for Daily or Longer Timeframes')
//
// Calculate how many mars since last bar
tdays = (timenow - time) / 60000.0  // number of minutes since last bar
tdays := timeframe.ismonthly ? tdays / 1440.0 / 5.0 / 4.3 / timeframe.multiplier : timeframe.isweekly ? tdays / 1440.0 / 5.0 / timeframe.multiplier : timeframe.isdaily ? tdays / 1440.0 / timeframe.multiplier : tdays / timeframe.multiplier  // number of bars since last bar
//
//set up exit parameters
TP = tpPoints > 0 ? tpPoints : na
SL = slPoints > 0 ? slPoints : na

// Make sure we are within the bar range, Set up entries and exit conditions
if (ebar == 0 or tdays <= ebar) and tradeType != 'NONE'
    strategy.entry('long', strategy.long, when=longCond == true and tradeType != 'SHORT')
    strategy.entry('short', strategy.short, when=shortCond == true and tradeType != 'LONG')
    strategy.close('long', when=shortCond == true and tradeType == 'LONG')
    strategy.close('short', when=longCond == true and tradeType == 'SHORT')
    strategy.exit('XL', from_entry='long', profit=TP, loss=SL)
    strategy.exit('XS', from_entry='short', profit=TP, loss=SL)

// === /STRATEGY ===
// eof



더 많은