CEX 데이터 기초 분석 마트 설계: Binance & Upbit 활용


심볼 정보 (MARKET)

거래쌍 식별자를 공통 규칙으로 표현하기 위해 **심볼정보 테이블(dim_market)**을 설계하였다. dim_market은 전역 표준 라벨 **market_code(BASE-QUOTE)**와 내부 식별자 **market_id**로 유일 식별하며, base_asset/quote_asset과 필요 시 자산 한·영명(asset_name_kr/asset_name_en)을 보관한다. 모든 사실 테이블은 market_id를 FK로 참조하여 연결하며, 거래소 간 표기 차이와 무관하게 동일 의미의 거래를 한 축으로 비교·집계할 수 있다.

처리 흐름 요약
  • 원본 수집: Binance symbol, Upbit market을 스테이징에 저장한다.
  • 표준화: 규칙대로 market_code, base_asset, quote_asset을 생성하고 dim_market에 업서트한다 → market_id를 획득한다.
  • 매핑 기록: map_exchange_symbol(exchange_code, native_symbol, market_id, valid_from, valid_to)를 기록한다.
  • 활용: 사실 테이블은 market_id만 저장하고, 조회 시 dim_market을 조인해 market_code로 분석한다.

    원본 필드 맵핑 기획
    의미BinanceUpbit표준 필드최종 저장 위치
    원본 심볼symbol (예: BTCUSDT)market (예: KRW-BTC)native_symbolmap_exchange_symbol
    표준 마켓 라벨market_code (예: BTC-USDT, BTC-KRW)dim_market
    기준 자산baseAssetmarket 뒤쪽base_assetdim_market
    상대 자산quoteAssetmarket 앞쪽quote_assetdim_market
    거래 상태status(거래소별 값)보류/별도 테이블 (표준 테이블엔 미저장)
    자산 한/영명korean_name, english_nameasset_name_kr, asset_name_endim_market(옵션)
    • 상태값, 틱사이즈 같은 거래소별 상이 값은 표준 라벨(dim_market)에 넣지 않는다. 필요 시 dim_market_exchange(exchange_code, market_id, …) 같은 보조 차원으로 분리한다.

    표준 매핑 테이블 설계, map_exchange_symbol
    컬럼타입/키설명값 예시비고
    map_idPK매핑 레코드의 내부 식별자이다.5001DB가 자동 생성한다.
    market_idFK연결된 표준 마켓이다. dim_market.market_id를 참조한다.101유일한 FK이다.
    exchange_code데이터 출처 거래소/채널 코드이다.BINANCE, UPBIT텍스트 코드이다.
    native_symbol거래소 원본 심볼이다.BTCUSDT, KRW-BTC원본 그대로 보존한다.
    valid_from이 매핑이 유효해진 시작 시각이다(UTC).2025-01-01 00:00:00Z이력 시작이다.
    valid_to이 매핑이 종료된 시각이다(UTC).NULL 또는 2025-06-30Z활성행은 NULL이다.
    • 활성 유니크 규칙: (exchange_code, native_symbol) 조합은 **valid_to IS NULL**에서 유일하다.

    최종 활용 테이블 dim_market
    컬럼타입/키설명값 예시비고
    market_idPK전역 표준 마켓의 내부 식별자이다. 사실 테이블이 FK로 참조한다.101숫자 서러게이트 키
    market_codeUK표준화된 심볼 라벨이다. BASE-QUOTE 대문자+하이픈 규칙을 따른다.BTC-USDT, BTC-KRW전역에서 유일
    base_asset기준 자산 코드이다.BTC, ETH문자열 코드
    quote_asset상대(결제) 자산 코드이다.USDT, KRW문자열 코드
    asset_name_kr(옵션)기준 자산의 한글명이다. Upbit 원본에서 보강한다.비트코인없으면 NULL
    asset_name_en(옵션)기준 자산의 영문명이다. Upbit 원본에서 보강한다.Bitcoin없으면 NULL
    • market_code = UPPER(base_asset) || '-' || UPPER(quote_asset)
    • Binance는 baseAsset/quoteAsset로 만들고, Upbit는 market(예: KRW-BTC)를 분리해 뒤집어 BTC-KRW로 만든다.

    현재가/24h 통계 (Ticker)

    티커는 시점별 현재가와 24시간 통계를 스냅샷으로 저장하는 지표이다. 거래소별 서로 다른 필드를 표준 컬럼으로 통일하고, exchange_codemarket_id를 함께 보관하여 교차거래소 비교와 합산 집계를 모두 지원하도록 설계하였다. 기준 시각은 ts_utc(UTC, ms)로 통일한다.

    처리 흐름 요약
    • 원본 적재: Binance/Upbit 티커를 스테이징에 저장한다(event_ts_utc 포함).
    • 표준화: 현재가·고저·24h 거래량/대금을 공통 컬럼으로 변환하고 market_code를 생성한다.
    • DIM 조회/증분: market_codedim_market을 조회해 market_id를 얻고, 신규 마켓만 업서트한다.
    • FACT 적재: (exchange_code, market_id, ts_utc) 기준으로 fact_ticker에 업서트한다. ts_utc는 원본 이벤트 시각이 있으면 그 값을, 없으면 load_ts를 사용한다.

    원본 필드 맵핑 기획
    의미BinanceUpbit표준 필드최종 저장 위치
    스냅샷 시각event_ts_utc 또는 수집시각응답시각 또는 수집시각ts_utc(UTC, ms)fact_ticker
    현재가lastPricetrade_priceprice_lastfact_ticker
    24h 고/저highPrice/lowPricehigh_price/low_pricehigh_24h/low_24hfact_ticker
    24h 거래량(베이스)volumeacc_trade_volume_24hvolume_base_24hfact_ticker
    24h 거래대금(쿼트)quoteVolumeacc_trade_price_24hvolume_quote_24hfact_ticker
    24h 변화량/변동률priceChange/priceChangePercentsigned_change_price/signed_change_rate (없으면 파생)chg_abs_24h/chg_pct_24hfact_ticker

    최종 테이블 fact_ticker
    컬럼타입/키설명값 예시비고
    exchange_codePK(복합)데이터 출처 거래소 코드이다.BINANCE, UPBIT문자열
    market_idPK(복합), FK표준 마켓 식별자이다. dim_market.market_id를 참조한다.101FK
    ts_utcPK(복합)스냅샷 기준 시각(UTC, ms)이다.1732608000000BIGINT(ms)
    price_lastNOT NULL, DECIMAL현재가이다.9876.500000000000000000누락 시 적재하지 않는다.
    high_24hDECIMAL24시간 고가이다.10050.000000000000000000
    low_24hDECIMAL24시간 저가이다.9500.000000000000000000
    volume_base_24hDECIMAL, CHECK(>=0)24시간 거래량(베이스)이다.1234.567000000000000000코인 수량 단위
    volume_quote_24hDECIMAL, CHECK(>=0)24시간 거래대금(쿼트)이다.12345678.900000000000000000결제통화 금액
    chg_abs_24hDECIMAL24시간 가격 변화량이다.-120.500000000000000000
    chg_pct_24hDECIMAL24시간 변화율(%)이다.-1.20
    load_tsNOT NULL, TIMESTAMP적재 시각이다.2025-06-01 00:00:05Z파이프라인 기록
    date_utc생성 컬럼DATE(ts_utc)이다.2025-06-01파티션/보존용
    date_kst생성 컬럼DATE(ts_utc + 9 HOUR)이다.2025-06-01리포트용
    • PK: (exchange_code, market_id, ts_utc)이다.
    • ts_utc: 원본 이벤트 시각이 있으면 그 값을 쓰고, 없으면 load_ts로 대체한다.
    • 지표 타입: 가격·금액·수량은 DECIMAL(38,18)로 저장한다.
    • 인덱스: (market_id, ts_utc DESC), (exchange_code, ts_utc DESC)를 각각 생성한다.
    • 조회는 fact_ticker → dim_market 조인으로 market_code를 붙여 사용한다.

    최근 체결(Trades)

    체결 데이터는 거래가 발생할 때마다 기록되는 행 단위 사실(Fact) 이다. 거래소별 원본 스키마를 표준 필드로 통일하고, exchange_codemarket_id를 함께 보관하여 교차거래소 비교·집계를 가능하게 한다. 기준 시각은 trade_ts_utc(UTC, ms) 로 통일한다.

    처리 흐름 요약
    • 원본 적재: Binance/Upbit 체결을 스테이징에 저장한다(event_ts_utc 포함).
    • 표준화: 원본 심볼/마켓으로 market_code를 만들고 taker_side를 규칙에 따라 통일한다.
    • DIM 조회/증분: market_codedim_market을 조회하여 market_id를 얻고, 신규 마켓만 업서트한다.
    • FACT 적재: (exchange_code, market_id, native_trade_id) 기준으로 fact_trades에 업서트한다. trade_ts_utc는 원본 이벤트 시각을 사용한다(없으면 load_ts).

    원본 필드 맵핑 기획
    의미BinanceUpbit표준 필드최종 저장 위치
    원본 체결 IDidsequential_idnative_trade_idfact_trades
    원본 심볼/마켓symbolmarket(→ market_code 생성)dim_market(조회)
    체결가 / 수량price / qtytrade_price / trade_volumeprice / qtyfact_trades
    체결 시각time(ms)timestamp(ms)trade_ts_utc(UTC, ms)fact_trades
    매수/매도 구분isBuyerMaker(true/false)ask_bid(‘ASK’/’BID’)taker_side(‘BUY’/’SELL’)fact_trades
    • 사이드 규칙: Binance isBuyerMaker=true‘SELL’, false‘BUY’ / Upbit ASK‘SELL’, BID‘BUY’.

    사실 테이블 설계 fact_trades
    컬럼타입/키설명값 예시비고
    exchange_codePK(복합)데이터 출처 거래소 코드이다.BINANCE, UPBIT문자열 코드
    market_idPK(복합), FK표준 마켓 식별자이다.101dim_market.market_id 참조
    native_trade_idPK(복합)원본 체결 고유 ID이다.1234567890Binance id / Upbit sequential_id
    trade_ts_utc체결 시각(UTC, ms)이다.1732608123456BIGINT(ms)이다.
    priceDECIMAL(38,18) NOT NULL체결가이다.9876.500000000000000000
    qtyDECIMAL(38,18) NOT NULL, CHECK(qty>0)체결 수량(베이스)이다.0.123400000000000000
    amount_quoteGENERATED (price*qty)체결 금액(쿼트)이다.1219.999999999999999999저장형 생성 컬럼
    taker_sideENUM(‘BUY’,’SELL’) NOT NULL테이커 방향이다.BUY사이드 표준 규칙 적용
    load_tsNOT NULL, TIMESTAMP적재 시각이다.2025-06-01 00:03:21Z파이프라인 기록
    date_utc생성 컬럼DATE(trade_ts_utc)이다.2025-06-01파티션/보존
    date_kst생성 컬럼DATE(trade_ts_utc + 9 HOUR)이다.2025-06-01리포트용
    • PK: (exchange_code, market_id, native_trade_id)이다.
    • 시간 정책: trade_ts_utc는 원본 이벤트 시각(UTC, ms)으로 저장한다. 없으면 load_ts로 대체한다.
    • 사이드 매핑: Binance isBuyerMaker=true→'SELL', false→'BUY'; Upbit ASK→'SELL', BID→'BUY'이다.
    • 인덱스 권장: (market_id, trade_ts_utc DESC), (exchange_code, trade_ts_utc DESC)를 각각 생성한다.
    • 파티션 권장: date_utc 기준 일(일자) 파티션이다.
    • 조회: fact_trades → dim_market 조인으로 market_code를 붙여 분석한다

    오더북 (order book)

    오더북은 시점별로 매수(BID)/매도(ASK) 레벨과 잔량을 스냅샷으로 기록하는 사실 테이블이다. 거래소별 응답(bids/asks 배열, orderbook_units)을 레벨 단위 행으로 표준화하고, exchange_codemarket_id를 함께 보관하여 교차거래소 비교·집계를 가능하게 하였다.

    • Trades의 taker_side('BUY'/'SELL') 는 체결의 테이커 방향, Orderbook의 side('BID'/'ASK') 는 장부 방향이다. 용어만 다르며 의미가 다름을 글에 명시하였다.

    처리 흐름 요약
    • 원본 적재: Binance/Upbit 오더북을 스테이징에 적재(bids/asks 또는 orderbook_units → 레벨 전개).
    • 표준화: market_code 생성, side('BID'/'ASK') 부여, 레벨(1..N) 부여, book_ts_utc(UTC, ms) 산출.
    • DIM 조회/증분: market_codedim_market 조회→market_id 획득(신규만 업서트).
    • FACT 적재: (exchange_code, market_id, book_ts_utc, side, level) 기준으로 fact_orderbook 업서트, Binance는 last_update_id 보관.

    원본 필드 맵핑 기획
    의미BinanceUpbit표준 필드최종 저장 위치
    스냅샷 시각eventTime/수집시각응답시각/수집시각book_ts_utc(UTC, ms)fact_orderbook
    레벨 전개bids/asks[price, qty]orderbook_unitsbid/ask_price,sizelevel(1..N)fact_orderbook
    장부 방향bids/asks 구분bid/ask 구분side(‘BID’/’ASK’)fact_orderbook
    가격/수량price / qtyprice / sizeprice / qtyfact_orderbook
    스냅샷 IDlastUpdateIdlast_update_idfact_orderbook(Binance 전용)
    총 잔량total_bid_size / total_ask_size(별도 요약 테이블/파생 집계로 관리 권장)
    마켓 식별symbolmarket(→ market_code 생성)dim_market(조회)

    최종 테이블 fact_orderbook
    컬럼타입/키설명값 예시비고
    exchange_codePK(복합)데이터 출처 거래소 코드이다.BINANCE, UPBIT문자열 코드
    market_idPK(복합), FK표준 마켓 식별자이다.101dim_market.market_id 참조
    book_ts_utcPK(복합)스냅샷 기준 시각(UTC, ms)이다.1732608000000BIGINT(ms)이다.
    sidePK(복합)장부 방향이다.BID / ASKENUM('BID','ASK') NOT NULL
    levelPK(복합)레벨 번호이다.1INT CHECK(level≥1)
    priceDECIMAL(38,18) NOT NULL레벨 가격이다.97500.000000000000000000
    qtyDECIMAL(38,18) NOT NULL, CHECK(qty≥0)해당 레벨 잔량이다.2.345600000000000000
    last_update_idBIGINT NULLBinance 스냅샷 ID이다.1234567890Upbit는 NULL
    load_tsNOT NULL, TIMESTAMP적재 시각이다.2025-06-01 00:00:05Z파이프라인 기록
    date_utc생성 컬럼DATE(book_ts_utc)이다.2025-06-01파티션/보존용
    date_kst생성 컬럼DATE(book_ts_utc + 9 HOUR)이다.2025-06-01리포트용
    • PK: (exchange_code, market_id, book_ts_utc, side, level)이다.
    • index: (market_id, book_ts_utc DESC), (exchange_code, book_ts_utc DESC), (선택) (market_id, side, level, book_ts_utc DESC)
    • 시간 정책: book_ts_utc는 원본 이벤트 시각(UTC, ms)으로 저장, 없으면 book_ts_utc = load_ts.
    • 파티션: PARTITION BY date_utc = DATE(book_ts_utc) 권장.
    • 레벨 규칙: BID=고가→저가 1..N / ASK=저가→고가 1..N.
    캔들 (candles)

    캔들은 일정 구간(분·시·일 등) 동안의 OHLCV를 집계한 스냅샷이다. 거래소별 포맷 차이를 표준 컬럼으로 통일하고, exchange_codemarket_id를 함께 보관하여 교차거래소 비교·집계를 가능하게 하였다. 봉의 기준 시각은 open_ts_utc(봉 시작, UTC ms) 로 통일한다.

    처리 흐름 요약
    • 원본 적재: Binance/Upbit 캔들을 스테이징에 저장하고 interval_code, open_ts_utc(UTC ms)를 산출한다.
    • 표준화: OHLC, volume_base/quote, trades_count, taker_buy_*를 공통 컬럼으로 변환한다.
    • DIM 조회/증분: market_codedim_market을 조회해 market_id를 얻고, 신규 마켓만 업서트한다.
    • FACT 적재: (exchange_code, market_id, interval_code, open_ts_utc) 기준으로 fact_candles에 업서트한다.

    원본 필드 맵핑 기획
    의미BinanceUpbit표준 필드최종 저장 위치
    봉 시작/끝 시각openTime / closeTime(ms)(파생) open_ts_utc / close_ts_utcopen_ts_utc / close_ts_utcfact_candles
    OHLCopen, high, low, closeopen, high, low, trade_priceopen, high, low, closefact_candles
    거래량(베이스)volumecandle_acc_trade_volumevolume_basefact_candles
    거래대금(쿼트)quoteAssetVolumecandle_acc_trade_pricevolume_quotefact_candles
    거래 수tradestrades_countfact_candles
    테이커 매수takerBuyBase/Quotetaker_buy_base/quotefact_candles
    마켓 식별symbolmarket(→ market_code 생성)dim_market(조회)
    구간 코드API interval엔드포인트별 단위interval_codefact_candles

    최종 테이블 fact_candles
    컬럼타입/키설명값 예시비고
    exchange_codePK(복합)데이터 출처 거래소 코드이다.BINANCE, UPBIT문자열 코드
    market_idPK(복합), FK표준 마켓 식별자이다.101dim_market.market_id 참조
    interval_codePK(복합)캔들 구간 코드이다.1m, 5m, 1h, 1d도메인 표준
    open_ts_utcPK(복합)봉 시작 시각(UTC, ms)이다.1732608000000BIGINT(ms)
    close_ts_utc봉 종료 시각(UTC, ms)이다.1732608060000open_ts_utc + duration
    open / high / low / closeDECIMAL(38,18) NOT NULL구간 OHLC 값이다.
    volume_base / volume_quoteDECIMAL(38,18) CHECK(>=0)구간 누적 거래량/대금이다.
    trades_countBIGINT NULL구간 체결 수이다.1234Upbit는 NULL
    taker_buy_base / taker_buy_quoteDECIMAL(38,18) NULL테이커 매수량(베이스/쿼트)이다.Binance 전용
    load_tsNOT NULL, TIMESTAMP적재 시각이다.2025-06-01 00:00:05Z파이프라인 기록
    date_utc / date_kst생성 컬럼DATE(open_ts_utc) / DATE(open_ts_utc + 9 HOUR)이다.2025-06-01보존/리포트용
    • PK: (exchange_code, market_id, interval_code, open_ts_utc)
    • index: (market_id, interval_code, open_ts_utc DESC), (exchange_code, interval_code, open_ts_utc DESC)
    • 시간 정책: open_ts_utc는 봉 시작(UTC, ms), close_ts_utc = open_ts_utc + interval_duration_ms
    • 파티션: PARTITION BY date_utc = DATE(open_ts_utc)
    • interval_code 예시: 1m,3m,5m,15m,30m,1h,4h,6h,12h,1d,1w,1M

    해당 글은 표준 마켓 차원 dim_market과 세 가지 사실 테이블 fact_candles, fact_trades, fact_orderbook까지, CEX 분석에 필요한 핵심 4개 테이블을 설계하였다. 이 구조만으로도 가격·수익률·유동성·체결 흐름을 교차거래소 기준으로 일관되게 분석할 수 있으나, 더 심도 깊은 분석을 위해서는 본 스키마를 축으로 확장이 필요하다. 확장 항목은 추후 순차적으로 업데이트할 예정이다.

    • 확장 가능한 스키마
      • fact_ticker_latest : 최신가 캐시(대시보드용)이다.
      • fact_funding(파생) : 펀딩 비율·시각을 저장한다.
      • fact_liquidations(파생) : 강제청산 이벤트를 기록한다.
      • fact_order_events : 주문/취소/체결 이벤트 단위를 저장한다.
      • fact_balances / fact_fees : 계정 잔고·수수료(내부 분석용)이다.
      • dim_exchange / dim_interval : 거래소·구간 메타데이터를 관리한다.
      • map_exchange_symbol(SCD) : 심볼 변경 이력을 관리한다.

    댓글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다