김프를 하나의 숫자가 아니라 원화 다리와 자산 다리로 나눠서 그립니다. Pine Script 전체 코드를 아래에 공개했습니다 — 복사해서 붙여넣으면 끝이고, 계정도 결제도 필요 없습니다.
환율로 계산한 김프는 성격이 다른 두 가지를 섞어 놓은 값입니다. 둘은 자주 반대 방향으로 움직입니다.
| 구성 | 무엇을 재는가 | 특징 |
|---|---|---|
| 원화 다리 | 국내 USDT가 시장 환율보다 얼마나 비싸거나 싼지 | 통화 쪽 값이라 모든 코인에 똑같이 적용됩니다 |
| 자산 다리 | 통화 효과를 걷어낸 뒤 코인 자체에 남는 값 | 실제 국내 수요는 여기에 나타납니다 |
전체 프리미엄이 마이너스인데 자산 다리가 0에 가깝다면, 그 코인이 국내에서 싸게 팔리는 것이 아니라 원화 환전 쪽에서 생긴 값입니다. 전체 숫자만 보면 이 상황을 정반대로 읽게 됩니다. 인디케이터는 두 다리가 서로 다른 방향을 가리키는 구간을 붉게 칠해 그 지점을 바로 보여줍니다.
전체 프리미엄 = (국내가 ÷ USD/KRW) ÷ 해외가 − 1
원화 다리 = 국내 USDT ÷ USD/KRW − 1
자산 다리 = (1 + 전체) ÷ (1 + 원화 다리) − 1
// Kimchi Premium — won leg vs asset leg
// by Daepak · https://daepak.com/kimchi · MIT
//
// The kimchi premium is usually published as one number: how much more expensive a coin is
// on a Korean exchange than abroad, converted at the FX rate. That single number mixes two
// different things, and they often move in opposite directions:
//
// won leg — how far Korean USDT trades from the market USD/KRW rate. It is a currency
// effect and applies to every coin equally.
// asset leg — what is left for the coin itself once the currency effect is removed.
//
// If the total premium is negative but the asset leg is near zero, the coin is not cheap in
// Korea — the won conversion is. Reading the total alone gets that backwards.
//
// The asset leg is DERIVED as (1 + total) / (1 + won) − 1, not measured from the coin's own
// USDT pair on Upbit. We tested the direct measurement on 2026-07-30: the implied rate from
// two Upbit order books matched for BTC (1424 vs 1423 market) but drifted to 1449 for SOL
// and 1451 for DOGE, because altcoin USDT pairs are thin and go stale. The derived leg always
// adds back up to the observed total; the direct one was noise.
//
// Honest limit: in our own backtest of 646 episodes, neither leg predicted price direction
// over horizons up to 24 hours. The decomposition explains what is happening now. It does not
// forecast, and this script is not investment advice.
//@version=6
indicator("Kimchi Premium · won leg vs asset leg", "Kimchi legs", overlay = false, precision = 2)
// ───────────────── inputs ─────────────────
gS = "Symbols"
krSym = input.symbol("UPBIT:BTCKRW", "Korean market (KRW)", group = gS,
tooltip = "The coin on a Korean exchange, quoted in won. Change this to follow another coin.")
glSym = input.symbol("BINANCE:BTCUSDT", "Global market (USD)", group = gS,
tooltip = "The same coin on a global exchange. Must be the same asset as the Korean symbol.")
fxSym = input.symbol("FX_IDC:USDKRW", "USD/KRW reference", group = gS,
tooltip = "The market exchange rate used to convert. This is the rate the premium is measured against.")
usdtSym = input.symbol("UPBIT:USDTKRW", "Korean USDT (KRW)", group = gS,
tooltip = "USDT priced in won on a Korean exchange — the most liquid stablecoin market, used to measure the won leg.")
gV = "View"
showTotal = input.bool(true, "Total premium (FX based)", group = gV)
showWon = input.bool(true, "Won leg", group = gV)
showAsset = input.bool(true, "Asset leg", group = gV)
showTable = input.bool(true, "Value panel", group = gV)
gA = "Alerts"
hiLevel = input.float(5.0, "Alert above (asset leg, %)", group = gA, step = 0.5)
loLevel = input.float(-3.0, "Alert below (asset leg, %)", group = gA, step = 0.5)
// ───────────────── data ─────────────────
kr = request.security(krSym, timeframe.period, close)
gl = request.security(glSym, timeframe.period, close)
fx = request.security(fxSym, timeframe.period, close)
usdt = request.security(usdtSym, timeframe.period, close)
ok = not na(kr) and not na(gl) and not na(fx) and gl > 0 and fx > 0
total = ok ? (kr / fx) / gl - 1.0 : na
won = not na(usdt) and not na(fx) and fx > 0 ? usdt / fx - 1.0 : na
// derived, never taken from the coin's own USDT pair — see the header note
asset = not na(total) and not na(won) ? (1.0 + total) / (1.0 + won) - 1.0 : na
totalP = total * 100
wonP = won * 100
assetP = asset * 100
// ───────────────── plots ─────────────────
pT = plot(showTotal ? totalP : na, "Total premium", color = color.new(#7A5CFF, 0), linewidth = 2)
pW = plot(showWon ? wonP : na, "Won leg", color = color.new(#F79009, 0), linewidth = 1)
pA = plot(showAsset ? assetP : na, "Asset leg", color = color.new(#12B76A, 0), linewidth = 2)
hline(0, "Parity", color = color.new(color.gray, 40), linestyle = hline.style_dashed)
// where the two legs disagree — the case the single number hides
fillCol = not na(wonP) and not na(assetP) and wonP * assetP < 0 ? color.new(#F04438, 88) : color.new(color.gray, 94)
fill(pW, pA, color = fillCol, title = "Gap between legs")
// ───────────────── panel ─────────────────
f_pct(float v) => na(v) ? "—" : (v > 0 ? "+" : "") + str.tostring(v, "#.##") + "%"
if showTable and barstate.islast
var table t = table.new(position.top_right, 2, 5, border_width = 1)
table.cell(t, 0, 0, "Kimchi premium", text_color = color.white, bgcolor = #5B3DF5, text_size = size.small)
table.cell(t, 1, 0, "now", text_color = color.white, bgcolor = #5B3DF5, text_size = size.small)
table.cell(t, 0, 1, "Total (FX based)", text_size = size.small)
table.cell(t, 1, 1, f_pct(totalP), text_size = size.small,
text_color = na(totalP) ? color.gray : totalP >= 0 ? #12B76A : #F04438)
table.cell(t, 0, 2, "Won leg", text_size = size.small)
table.cell(t, 1, 2, f_pct(wonP), text_size = size.small,
text_color = na(wonP) ? color.gray : wonP >= 0 ? #12B76A : #F04438)
table.cell(t, 0, 3, "Asset leg", text_size = size.small)
table.cell(t, 1, 3, f_pct(assetP), text_size = size.small,
text_color = na(assetP) ? color.gray : assetP >= 0 ? #12B76A : #F04438)
table.cell(t, 0, 4, na(assetP) ? "waiting for data" :
math.abs(assetP) < 0.3 ? "currency effect, not the coin" :
assetP > 0 ? "Korean demand for the coin" : "coin discounted in Korea",
text_size = size.tiny, text_color = color.gray)
table.cell(t, 1, 4, "daepak.com", text_size = size.tiny, text_color = color.gray)
// ───────────────── alerts ─────────────────
alertcondition(ta.crossover(assetP, hiLevel), "Asset leg above level",
"Kimchi asset leg crossed above the upper level")
alertcondition(ta.crossunder(assetP, loLevel), "Asset leg below level",
"Kimchi asset leg crossed below the lower level")
alertcondition(ta.cross(wonP * assetP, 0), "Legs diverged",
"Kimchi legs now point in opposite directions — the single premium number is misleading here")
저희가 646개 구간으로 검증한 결과, 두 다리 모두 24시간 이내 가격 방향을 예측하지 못했습니다. 분해는 지금 무슨 일이 벌어지고 있는지 설명하는 도구이지 앞을 맞히는 도구가 아닙니다. 이 스크립트는 투자 자문이 아니며, 판단과 책임은 사용자에게 있습니다.
전체 마켓의 김프 순위, 원화 다리와 자산 다리의 실시간 값, 업비트 신규 상장의 첫 캔들부터의 기록은 김치 프리미엄 페이지에서 바로 볼 수 있습니다. 로그인 없이 열립니다. 같은 데이터를 API와 MCP로 부르려면 개발자 문서를 보세요 — ChatGPT나 Claude에서 바로 질문할 수도 있습니다(연결 방법).