서론: 왜 OKX API와 백테스팅인가?

암호화폐 거래소 APIs를 활용하여 Historical Data를 수집하고 백테스팅 시스템을 구축하는 것은 퀀트 트레이딩의 핵심 역량입니다. 이 튜토리얼에서는 OKX 거래소 REST API에서 Historical K线(Kline/Candlestick) 데이터를 가져오는 방법과 Python 기반 백테스팅 프레임워크를 구축하는 과정을 상세히 다룹니다. 실무에서 흔히遭遇하는 401 Unauthorized, 429 Rate Limit Exceeded, Kline interval not supported 같은 오류들을 체계적으로 다루며, 마지막에는 수집한 데이터를 AI 모델로 분석하여 거래 신호를 生成하는 고급 파이프라인까지 확장하겠습니다.

1. OKX API 설정 및 인증

1.1 API Key 발급

OKX 거래소에서 API Key를 발급받으려면:
  1. OKX官网(https://www.okx.com)에 로그인
  2. 계정 설정 → API 메뉴 이동
  3. "Create API Key" 클릭
  4. API Key, Secret Key, Passphrase 저장 (절대 공개처에 공유 금지)

1.2 Python 환경 구성

# 프로젝트 디렉토리 생성 및 가상환경 설정
mkdir okx-backtest && cd okx-backtest
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

필수 패키지 설치

pip install requests pandas numpy matplotlib pip install python-dotenv # API Key安全管理 #requirements.txt 생성 cat > requirements.txt << 'EOF' requests==2.31.0 pandas==2.1.0 numpy==1.24.3 matplotlib==3.8.0 python-dotenv==1.0.0 EOF

1.3 환경변수 설정

# .env 파일 생성 (gitignore에 추가 필수)

.env

OKX_API_KEY=your_api_key_here OKX_SECRET_KEY=your_secret_key_here OKX_PASSPHRASE=your_passphrase_here OKX_USE_SANDBOX=false # 실전투자시 false

config.py - API 설정 모듈

import os from dotenv import load_dotenv load_dotenv() class OKXConfig: """OKX API 설정 클래스""" BASE_URL = "https://www.okx.com" SANDBOX_URL = "https://www.okx.com" # API Credentials API_KEY = os.getenv("OKX_API_KEY") SECRET_KEY = os.getenv("OKX_SECRET_KEY") PASSPHRASE = os.getenv("OKX_PASSPHRASE") USE_SANDBOX = os.getenv("OKX_USE_SANDBOX", "false").lower() == "true" # 요청 헤더 생성 @staticmethod def get_headers(timestamp: str, sign: str) -> dict: return { "OK-ACCESS-KEY": OKXConfig.API_KEY, "OK-ACCESS-SIGN": sign, "OK-ACCESS-TIMESTAMP": timestamp, "OK-ACCESS-PASSPHRASE": OKXConfig.PASSPHRASE, "Content-Type": "application/json" } @classmethod def get_base_url(cls) -> str: return cls.SANDBOX_URL if cls.USE_SANDBOX else cls.BASE_URL print(f"✅ 설정 완료 - Sandbox 모드: {OKXConfig.USE_SANDBOX}")

2. OKX REST API Historical Data 수집

2.1 HMAC-SHA256 서명 생성

OKX API는 모든 요청에 HMAC-SHA256 서명이 필요합니다. 정확한 서명 생성이 핵심입니다.
import hmac
import hashlib
import base64
import datetime

class OKXAuth:
    """OKX API 인증 및 서명 생성"""
    
    @staticmethod
    def sign(timestamp: str, method: str, path: str, body: str = "") -> str:
        """
        OKX API 서명 생성 (HMAC-SHA256)
        
        Args:
            timestamp: ISO 8601 형식 시간 (예: "2024-01-15T10:30:00.000Z")
            method: HTTP 메서드 (GET, POST 등)
            path: 요청 경로 (예: "/api/v5/market/history-candles")
            body: 요청 본문 (없으면 빈 문자열)
        
        Returns:
            Base64 인코딩된 서명 문자열
        """
        message = timestamp + method + path + body
        
        signature = hmac.new(
            OKXConfig.SECRET_KEY.encode('utf-8'),
            message.encode('utf-8'),
            hashlib.sha256
        ).digest()
        
        return base64.b64encode(signature).decode('utf-8')
    
    @staticmethod
    def get_timestamp() -> str:
        """ISO 8601 형식 현재 시간 반환"""
        return datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z'

서명 테스트

auth = OKXAuth() ts = auth.get_timestamp() test_sign = auth.sign(ts, "GET", "/api/v5/market/history-candles", "") print(f"타임스탬프: {ts}") print(f"서명 길이: {len(test_sign)} bytes") print(f"서명 샘플: {test_sign[:20]}...")

2.2 Historical K线(Kline) Data API

OKX는 Historical Candlestick 데이터를 위해 /api/v5/market/history-candles 엔드포인트를 제공합니다.
import requests
import pandas as pd
from typing import Optional, List

class OKXMarketData:
    """OKX 시장 데이터 수집 클래스"""
    
    def __init__(self):
        self.base_url = OKXConfig.get_base_url()
        self.auth = OKXAuth()
    
    def get_history_candles(
        self,
        inst_id: str,
        bar: str = "1H",
        after: Optional[str] = None,
        before: Optional[str] = None,
        limit: int = 100
    ) -> pd.DataFrame:
        """
        Historical K线 데이터 조회
        
        Args:
            inst_id: 거래_pair ID (예: "BTC-USDT")
            bar: 시간 간격 ("1m", "5m", "15m", "1H", "4H", "1D", etc.)
            after: 이 시간 이전 데이터 (UTC 타임스탬프 ms)
            before: 이 시간 이후 데이터 (UTC 타임스탬프 ms)
            limit: 반환 개수 (최대 100)
        
        Returns:
            Pandas DataFrame with OHLCV data
        """
        endpoint = "/api/v5/market/history-candles"
        params = {
            "instId": inst_id,
            "bar": bar,
            "limit": str(limit)
        }