금과 은 차익거래 전략


생성 날짜: 2026-03-12 11:50:47 마지막으로 수정됨: 2026-03-12 11:50:47
복사: 0 클릭수: 22
avatar of ianzeng123 ianzeng123
2
집중하다
413
수행원

금과 은 차익거래 전략 금과 은 차익거래 전략

ZSCORE, RSI, ATR, SMA, EMA

Z-Score 통계 중개: 금과 은의 가격 대비 수학 게임

이것은 일반적인 트렌드 추적 전략이 아닙니다. XAG/XAU 통계적 거 전략은 하나의 핵심 가정에 기반합니다: 금과 은의 가격이 장기 평균 회귀 관계에 있습니다. Z-Score가 ± 2 표준 차이를 돌파 할 때, 가격이 통계적으로 극한에 도달하여 회귀 기회를 잡습니다.

20주기 표준화 비율: 전통적인 연관성 분석보다 더 정확하다

전략의 핵심은 표준화 가격비율 모델을 구축하는 것이다. XAG와 XAU에 대해 20주기 SMA를 통해 표준화하고, 3주기 EMA를 사용하여 비율을 평형화한다. 이 처리 방식은 간단한 가격비율보다 안정적이며, 단기적 소음을 효과적으로 필터링한다. 표준화 비율의 Z-Score가 ± 2 범위를 초과할 때, 이는 현재 가격이 역사적 평균에서 2 표준 이상 떨어져 있다는 것을 나타냅니다. 통계적으로 작은 확률 사건으로 간주되며, 평균으로 돌아가는 시간을 제공합니다.

RSI 필터: 50 분기선을 잘 활용하는 방법

기존의 RSI 오버 바이 오버 세 신호와는 달리, RSI=50을 다공간 필터 조건으로 사용한다. RSI<50일 때 더 많이 할 수 있고, RSI>50일 때 더 적게 할 수 있다. 이 설계 논리는 명확하다: 상대적으로 약한 경우 구매하여 반발을 기다리고, 상대적으로 강한 경우 판매하여 재조정을 기다린다. 이 필터 메커니즘은 역경 거래의 위험을 효과적으로 줄이고, 신호 품질을 향상시킨다.

3:8의 ATR 리스크/이익 비율: 수학적으로 긍정적인 기대

스톱은 3배의 ATR, 스톱로스는 8배의 ATR로 설정되어 있고, 리스크 수익률은 1:2.67에 달한다. 이 디자인은 통계적 배당의 특징을 기반으로 한다. 평균값이 돌아가는 확률이 높지만, 충분한 오류 허용 공간을 부여해야 한다. 14주기 ATR은 스톱로스 레벨이 시장의 변동성에 적응할 수 있도록 보장한다. 역사적인 회귀는 이 비율이 귀금속 쌍 거래에서 긍정적인 기대 수익을 달성할 수 있음을 보여준다.

적용 시나리오: 위축 시장이 유동 시장보다 우수하다

통계적 중매 전략은 수평 변동 현장에서 가장 잘 작동합니다. 왜냐하면 이 때 평균값 회귀 특성이 더 분명하기 때문입니다. 단방향 시장에서 가격이 평균값에서 오랫동안 벗어날 수 있기 때문에 전략은 더 큰 회수 위험에 직면합니다. 시장의 변동률이 적당하고 명백한 단방향이없는 경우 사용하는 것이 좋습니다. 또한 귀금속 시장은 거시 경제 요인에 의해 영향을 받으며 중요한 사건 동안 신중하게 사용해야합니다.

위험 팁: 통계 모델의 한계

역사적인 통계적 관계는 미래의 지속을 보장하지 않는다. 금 은 비율은 수요 공급 구조의 변화, 통화 정책의 차이 등과 같은 요인들로 인해 장기적으로 편향될 수 있다. 전략은 연속적인 손실의 위험이 있다. 특히 시장 구조의 변화 기간 동안이다.

전략 소스 코드
//@version=6
strategy("Stat Arb(xag & xau)")

// ══════════════════════════════════════════════════════════════
// BENCHMARK DATA
// ══════════════════════════════════════════════════════════════
float benchClose = request.security("XAG_USDT.swap", timeframe.period, close)

// ══════════════════════════════════════════════════════════════
// HELPER FUNCTIONS
// ══════════════════════════════════════════════════════════════
f_cov(float src1, float src2, int len) =>
    ta.sma(src1 * src2, len) - ta.sma(src1, len) * ta.sma(src2, len)

f_var(float src, int len) =>
    ta.sma(src * src, len) - math.pow(ta.sma(src, len), 2)

// ══════════════════════════════════════════════════════════════
// SPREAD ENGINE — NORMALIZED RATIO
// ══════════════════════════════════════════════════════════════
int lookback = 20

float pairSma   = ta.sma(close,      lookback)
float benchSma  = ta.sma(benchClose, lookback)
float pairNorm  = pairSma  != 0 ? close      / pairSma  * 100.0 : 100.0
float benchNorm = benchSma != 0 ? benchClose / benchSma * 100.0 : 100.0
float modelRaw  = benchNorm != 0 ? pairNorm / benchNorm : 1.0
float model     = ta.ema(modelRaw, 3)

float zMean  = ta.sma(model, lookback)
float zStd   = ta.stdev(model, lookback)
float zScore = zStd != 0 ? (model - zMean) / zStd : 0.0

// ══════════════════════════════════════════════════════════════
// RSI FILTER — BELOW / ABOVE 50
// ══════════════════════════════════════════════════════════════
float rsiVal    = ta.rsi(close, 14)
bool  rsiLongOk  = rsiVal < 50.0
bool  rsiShortOk = rsiVal > 50.0

// ══════════════════════════════════════════════════════════════
// ENTRY SIGNALS
// Z crosses below -2 = long, above +2 = short
// ══════════════════════════════════════════════════════════════
bool enterLong  = ta.crossunder(zScore, -2.0) and rsiLongOk
bool enterShort = ta.crossover(zScore,   2.0) and rsiShortOk

// ══════════════════════════════════════════════════════════════
// ATR STOP + TAKE PROFIT
// Stop:  8x ATR from entry (hardcoded)
// TP:    3x ATR from entry (hardcoded), stamped at entry
// ══════════════════════════════════════════════════════════════
float atrVal = ta.atr(14)

var float tpLevel   = na
var float slLevel   = na
var float entryPrice = na

bool isNewEntry = strategy.position_size != 0 and strategy.position_size[1] == 0
if isNewEntry
    entryPrice := strategy.position_avg_price
    if strategy.position_size > 0
        tpLevel := entryPrice + atrVal * 3.0
        slLevel := entryPrice - atrVal * 8.0
    else
        tpLevel := entryPrice - atrVal * 3.0
        slLevel := entryPrice + atrVal * 8.0

if strategy.position_size == 0
    tpLevel    := na
    slLevel    := na
    entryPrice := na

// ══════════════════════════════════════════════════════════════
// EXIT CONDITIONS — high/low for intrabar touch
// ══════════════════════════════════════════════════════════════
bool tpHitLong  = strategy.position_size > 0 and not na(tpLevel) and high >= tpLevel
bool tpHitShort = strategy.position_size < 0 and not na(tpLevel) and low  <= tpLevel
bool slHitLong  = strategy.position_size > 0 and not na(slLevel) and low  <  slLevel
bool slHitShort = strategy.position_size < 0 and not na(slLevel) and high >  slLevel

// ══════════════════════════════════════════════════════════════
// EXECUTION
// ══════════════════════════════════════════════════════════════
if enterLong
    strategy.close("Short", comment="Flip")
    strategy.entry("Long",  strategy.long)
if enterShort
    strategy.close("Long",  comment="Flip")
    strategy.entry("Short", strategy.short)

if tpHitLong
    strategy.close("Long",  comment="TP")
if tpHitShort
    strategy.close("Short", comment="TP")
if slHitLong
    strategy.close("Long",  comment="SL")
if slHitShort
    strategy.close("Short", comment="SL")

// ══════════════════════════════════════════════════════════════
// VISUALS
// ══════════════════════════════════════════════════════════════
hline( 2.0, "+2",  color=color.new(color.red,  20), linestyle=hline.style_dashed)
hline(-2.0, "-2",  color=color.new(color.teal, 20), linestyle=hline.style_dashed)
hline( 0.0, "Mid", color=color.gray,                linestyle=hline.style_solid)

color zCol = zScore >= 0 ? color.new(color.red, 10) : color.new(color.teal, 10)
plot(zScore, title="Z Score", color=zCol, linewidth=3)

bgcolor(zScore >  2.0 ? color.new(color.red,  90) : na, title="Overbought Zone")
bgcolor(zScore < -2.0 ? color.new(color.teal, 90) : na, title="Oversold Zone")
bgcolor(strategy.position_size > 0 ? color.new(color.teal, 93) : na, title="In Long")
bgcolor(strategy.position_size < 0 ? color.new(color.red,  93) : na, title="In Short")

plotshape(enterLong,  style=shape.triangleup,   location=location.bottom, color=color.teal, size=size.small)
plotshape(enterShort, style=shape.triangledown, location=location.top,    color=color.red,  size=size.small)
plotshape(tpHitLong or tpHitShort, style=shape.flag,   location=location.top, color=color.yellow, size=size.tiny, text="TP")
plotshape(slHitLong or slHitShort, style=shape.xcross, location=location.top, color=color.orange, size=size.tiny, text="SL")