eda

topics
types
contexts 학교
tags
#kaggle #eda #feature-engineering #crypto

EDA - 가상화폐 시장 예측 대회

데이터 설명

캐글 가상화폐 시장 예측 대회에서 사용한 데이터다. 주문서(Order Book) 정보와 거래 데이터를 기반으로 가격 방향을 예측한다.

타겟 변수: label (가격 상승/하락 예측)


컬럼 설명

기본 컬럼

용어 의미
bid_qty 매수 호가 수량(매수잔량): 현재 시장에 올라와 있는 매수 주문(살 사람)이 원하는 구매 수량의 총합
ask_qty 매도 호가 수량(매도잔량): 현재 시장에 올라와 있는 매도 주문(팔 사람)이 원하는 판매 수량의 총합
buy_qty 매수 수량: 지정된 시간 또는 가격 구간에서 실제로 체결된 매수(구입) 거래의 수량
sell_qty 매도 수량: 지정된 시간 또는 가격 구간에서 실제로 체결된 매도(판매) 거래의 수량
volume 거래량: 특정 기간 동안 해당 가상화폐가 실제로 거래된 총 수량 또는 금액 (보통 24시간 기준)

전체 컬럼 리스트

['bid_qty', 'ask_qty', 'buy_qty', 'sell_qty', 'volume',
 'X1', 'X2', 'X3', ..., 'X780', 'label']

총 780개의 익명화된 특성(X1~X780)과 5개의 기본 특성, 1개의 타겟 변수로 구성된다.


주요 Feature 선택

핵심 Feature (상위권 솔루션 공통)

기본 특성

  • bid_qty, ask_qty, buy_qty, sell_qty, volume

중요한 X 특성

  • X598, X344, X363, X405, X321
  • X175, X179, X197, X22, X181
  • X28, X169, X198, X173, X338

왜 이 특성들이 중요할까?
주문서의 불균형, 거래 강도, 시장 유동성 같은 시장 구조적 특성을 나타내는 것으로 추정된다.

솔루션별 Feature 선택

1. johndoe2011 솔루션

features = [
    'X363', 'X405', 'X321',
    'X175', 'X179', 'X137', 'X197', 'X22', 'X40', 'X181',
    'X28', 'X169', 'X198', 'X173',
    'X338', 'X288', 'X385', 'X344', 'X427', 'X587', 'X450',
    'X97', 'X52', 'X444',
    'X598', 'X379', 'X696', 'X297', 'X138',
    'X572', 'X343', 'X586', 'X466', 'X438', 'X452', 'X459',
    'X435', 'X386', 'X55', 'X341', 'X683', 'X428', 'X605',
    'X445', 'X272', 'X180', 'X593', 'X680',
    'X686', 'X692', 'X695',
    "X603", "X674", "X421", "X333",
    "X415", "X345", "X174", "X302", "X178", "X168", "X612",
    "buy_qty", "sell_qty", "volume",
    "bid_qty", "ask_qty",
]

출처: https://www.kaggle.com/code/johndoe2011/anyone-can-win-on-public-lb

2. rosswade 솔루션

FEATURES = [
    "X863", "X856", "X344", "X598", "X862", "X385", "X852", "X603", "X860", "X674",
    "X415", "X345", "X137", "X855", "X174", "X302", "X178", "X532", "X168", "X612",
    "bid_qty", "ask_qty", "buy_qty", "sell_qty", "volume",
    "X888", "X421", "X333"
]

출처: https://www.kaggle.com/code/rosswade/drw-crypto-market-submission

3. taylorsamarel 솔루션

core_features = [
    'X363', 'X405', 'X321', 'X175', 'X179', 'X197', 'X22', 'X181', 'X28', 'X169',
    'X198', 'X173', 'X338', 'X344', 'X587', 'X450', 'X97', 'X52', 'X444', 'X598',
    'X297', 'X138', 'X572', 'X343', 'X438', 'X459', 'X758', 'X25',
    'buy_qty', 'sell_qty', 'volume', 'bid_qty'
]

출처: https://www.kaggle.com/code/taylorsamarel/xgb-deep-learning-ensemble


Feature Engineering

상호작용 및 기본 관계 지표

주문서 유동성과 실제 거래 간의 상호작용을 나타내는 특성들이다.

"""
거래 활성도와 실제로 내놨을 때 얼마나 팔렸나를 평가하는 척도들
"""

# 매수/매도 호가 수량의 곱. 주문서 유동성의 쌍방향 규모 예상
df['bid_ask_interaction'] = df['bid_qty'] * df['ask_qty']

# 매수 호가수량 × 실제 매수 체결량. 호가잔량과 실제 매수간 상호작용 지표
df['bid_buy_interaction'] = df['bid_qty'] * df['buy_qty']

# 매수 호가수량 × 실제 매도 체결량. 미체결 매수와 매도 거래간 연결도
df['bid_sell_interaction'] = df['bid_qty'] * df['sell_qty']

# 매도 호가수량 × 실제 매수 체결량. 미체결 매도와 매수 거래간 연결도
df['ask_buy_interaction'] = df['ask_qty'] * df['buy_qty']

# 매도 호가수량 × 실제 매도 체결량. 호가잔량과 실제 매도간 상호작용 지표
df['ask_sell_interaction'] = df['ask_qty'] * df['sell_qty']

# 실제 매수·매도 체결량의 곱. 거래 활성도의 상대 척도
df['buy_sell_interaction'] = df['buy_qty'] * df['sell_qty']

# (매도호가수량-매수호가수량)/(양 호가잔량 누적)로 유동성 불균형 지표
df['spread_indicator'] = (df['ask_qty'] - df['bid_qty']) / (df['ask_qty'] + df['bid_qty'] + 1e-8)

# 실시간 매수 체결량/매도 체결량 비율
df['buy_sell_ratio'] = df['buy_qty'] / (df['sell_qty'] + 1e-8)

# 매수호가잔량/매도호가잔량 비율
df['bid_ask_ratio'] = df['bid_qty'] / (df['ask_qty'] + 1e-8)

유동성 지표

# 유동성
df['total_liquidity'] = df['bid_qty'] + df['ask_qty']

# 유동성 불균형도
df['liquidity_imbalance'] = (df['bid_qty'] - df['ask_qty']) / (df['total_liquidity'] + 1e-8)

# 매수 체결량/매수호가. 매수세가 호가잔량 대비 얼마나 큰지
df['normalized_buy_volume'] = df['buy_qty'] / (df['bid_qty'] + 1e-8)

# 매도 체결량/매도호가. 매도세가 호가잔량 대비 얼마나 큰지
df['normalized_sell_volume'] = df['sell_qty'] / (df['ask_qty'] + 1e-8)

거래 강도 지표

각 매수매도의 힘과 전체 시장의 방향성과 힘이 얼마인지를 확인할 수 있다.

# 매도호가수량-매수호가수량)/총거래량. 유동성 대비 스프레드 지표
df['relative_spread'] = (df['ask_qty'] - df['bid_qty']) / (df['volume'] + 1e-8)

# 볼륨 가중 지표
df['volume_weighted_buy'] = df['buy_qty'] * df['volume']
df['volume_weighted_sell'] = df['sell_qty'] * df['volume']
df['volume_weighted_bid'] = df['bid_qty'] * df['volume']
df['volume_weighted_ask'] = df['ask_qty'] * df['volume']

# 실시간 매수·매도 힘 균형
df['order_flow_imbalance'] = (df['buy_qty'] - df['sell_qty']) / (df['volume'] + 1e-8)

# 볼륨을 반영한 유동성 불균형도
df['liquidity_adjusted_imbalance'] = df['order_flow_imbalance'] * df['depth_ratio']

# 매수/매도 압력
df['buying_pressure'] = df['buy_qty'] / (df['volume'] + 1e-8)
df['selling_pressure'] = df['sell_qty'] / (df['volume'] + 1e-8)

# 전체 체결횟수/총거래량. 시장의 거래 활성 수준
df['trade_intensity'] = (df['buy_qty'] + df['sell_qty']) / (df['volume'] + 1e-8)

# 평균 체결 단위. 한 번 거래당 평균 체결량
df['avg_trade_size'] = df['volume'] / (df['buy_qty'] + df['sell_qty'] + 1e-8)

# 실질 순매수/매도 흐름. (매수-매도)/(매수+매도)
df['net_trade_flow'] = (df['buy_qty'] - df['sell_qty']) / (df['buy_qty'] + df['sell_qty'] + 1e-8)

# 총유동성/총거래량. 시장 유동성 깊이 척도
df['depth_ratio'] = df['total_liquidity'] / (df['volume'] + 1e-8)

df['volume_participation'] = (df['buy_qty'] + df['sell_qty']) / (df['total_liquidity'] + 1e-8)

# 시장 활성 지표. 주문서-실제 거래의 복합 지표
df['market_activity'] = df['volume'] * df['total_liquidity']

# 체결량 차이/거래량. 시장 실효적 스프레드 근사치
df['effective_spread_proxy'] = np.abs(df['buy_qty'] - df['sell_qty']) / (df['volume'] + 1e-8)

df['realized_volatility_proxy'] = np.abs(df['order_flow_imbalance']) * df['volume']

# 매수압력 × 스프레드 지표. 매수세와 유동성 스프레드의 복합 움직임
df['pressure_spread_interaction'] = df['buying_pressure'] * df['spread_indicator']

추가 유용한 특성 (rosswade 솔루션)

# 로그 변환
df['log_volume'] = np.log1p(df['volume'])

# 호가 불균형
df['bid_ask_imbalance'] = (df['bid_qty'] - df['ask_qty']) / (df['bid_qty'] + df['ask_qty'] + 1e-8)

# 주문 흐름 불균형
df['order_flow_imbalance'] = (df['buy_qty'] - df['sell_qty']) / (df['buy_qty'] + df['sell_qty'] + 1e-8)

# 유동성 비율
df['liquidity_ratio'] = (df['bid_qty'] + df['ask_qty']) / (df['volume'] + 1e-8)

왜 이렇게 했냐면: 원본 특성만으로는 시장의 구조적 패턴을 충분히 표현하기 어렵다. 특성 간 상호작용을 만들어서 모델이 더 복잡한 패턴을 학습할 수 있게 한다.


참고 자료

Kaggle 솔루션

리지 회귀 참고 자료


관련 문서