트레이딩 도구

바이낸스 API 과거 K-라인(캔들) 조회: 데이터 누락 방지 가이드

2026-04-23 · 8 분 소요

API를 통해 백테스트용 과거 K-라인 데이터를 수집할 때 필요한 페이지네이션과 중복 제거 방법을 안내합니다. 표준 구현 방식을 확인하세요.

전략 백테스트를 위해서는 신뢰할 수 있는 과거 K-라인 데이터가 필수입니다. 먼저 바이낸스 공식 사이트에서 읽기 전용 API 키를 생성하고, 바이낸스 공식 앱을 통해 계정 상태를 확인하세요(iOS 사용자는 iOS 설치 가이드 참조).

인터페이스 규격

GET /api/v3/klines
파라미터: symbol, interval, startTime, endTime, limit

limit은 한 번의 요청당 최대 1,000개까지 조회할 수 있습니다.

전체 과거 데이터 한 번에 가져오기

한 번의 요청으로 수년 치 데이터를 가져오는 것은 불가능합니다. limit 제한 때문에 페이지네이션(Pagination) 처리가 반드시 필요합니다.

페이지네이션 구현 표준

import time
all_klines = []
end = int(time.time() * 1000)
start = end - 365 * 24 * 3600 * 1000  # 최근 1년치 데이터

while start < end:
    klines = client.get_klines(
        symbol='BTCUSDT',
        interval='1h',
        startTime=start,
        limit=1000
    )
    if not klines:
        break
    all_klines.extend(klines)
    start = klines[-1][0] + 1  # 다음 요청은 마지막 캔들의 시간 + 1ms부터 시작
    time.sleep(0.5)  # API 속도 제한 보호

중복 제거

데이터를 가져올 때 경계 지점의 캔들이 중복될 수 있습니다. 다음 요청 시 + 1ms를 더해 요청하거나, 수집 후 다음과 같이 중복을 제거합니다.

import pandas as pd
df = pd.DataFrame(all_klines)
df = df.drop_duplicates(subset=[0])  # 타임스탬프 기준 중복 제거

K-라인 데이터 포맷

각 K-라인은 다음과 같은 배열 형태로 반환됩니다.

[
  open_time,    # 시가 시간(타임스탬프, ms)
  open,         # 시가
  high,         # 고가
  low,          # 저가
  close,        # 종가
  volume,       # 거래량
  close_time,   # 종가 시간(타임스탬프)
  quote_volume, # 쿼트 자산 거래액
  trades,       # 체결 횟수
  taker_buy_base,
  taker_buy_quote,
  ignore
]

DataFrame으로 변환하기

df = pd.DataFrame(all_klines, columns=[
    'open_time','open','high','low','close','volume',
    'close_time','quote_volume','trades',
    'taker_buy_base','taker_buy_quote','ignore'
])
df['open_time'] = pd.to_datetime(df['open_time'], unit='ms')
df.set_index('open_time', inplace=True)
df = df.astype({'open': float, 'high': float, 'low': float, 'close': float, 'volume': float})

이렇게 변환하면 pandas, numpy 등 분석 라이브러리에서 바로 활용할 수 있습니다.

시간대별 데이터 규모

주기 1년치 K-라인 수
1m 525,600
5m 105,120
15m 35,040
1h 8,760
4h 2,190
1d 365

한 번에 1,000개씩 조회할 때:

  • 1분봉 1년치: 약 526회 요청(4~5분 소요)
  • 1시간봉 1년치: 약 9회 요청(수 초 소요)

다중 종목 병렬 수집

import concurrent.futures
symbols = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT']

def fetch(s):
    return get_history(s, '1h', 365)

with concurrent.futures.ThreadPoolExecutor(max_workers=3) as ex:
    results = list(ex.map(fetch, symbols))

병렬 처리를 할 때는 바이낸스 API의 Weight(가중치) 제한을 넘지 않도록 주의해야 합니다.

공개 vs 인증(API Key)

과거 K-라인은 공개 데이터이므로 API Key 없이도 조회가 가능합니다.

import requests
url = 'https://api.binance.com/api/v3/klines'
params = {'symbol': 'BTCUSDT', 'interval': '1h', 'limit': 1000}
r = requests.get(url, params=params)

다만, API Key를 사용하여 인증된 요청을 보낼 경우 더 높은 가중치 한도를 할당받을 수 있습니다.

대량의 과거 데이터 다운로드

바이낸스는 수년 치 데이터를 한 번에 받을 수 있는 역사적 데이터 아카이브(CSV 패키지)를 제공합니다.

  • data.binance.vision/

월별, 주기별로 정리되어 있어 API로 수집하는 것보다 훨씬 빠릅니다.

실시간 업데이트 유지

백테스트 후 실전 운영 시에는 최신 캔들을 지속적으로 업데이트해야 합니다.

1. 폴링(Polling) 방식

매분마다 최근 5개 정도의 캔들을 주기적으로 조회하여 로컬 데이터를 갱신합니다.

2. 웹소켓(WebSocket) 방식

실시간 스트림을 구독합니다.

wss://stream.binance.com:9443/ws/btcusdt@kline_1h

웹소켓은 실시간 데이터 처리에, REST API는 누락된 과거 데이터 보충에 적합합니다.

데이터 품질 관리 유의사항

  • 네트워크 불안정으로 특정 구간이 누락될 수 있습니다.
  • 타임스탬프 단위를 반드시 확인하세요(ms vs s).
  • 아직 마감되지 않은 현재 진행 중인 캔들은 값이 계속 변하므로 백테스트 시 제외해야 합니다.

데이터 저장(Persistence)

수집한 데이터를 효율적으로 관리하려면 다음 저장 방식을 고려하세요.

  • CSV: 구현이 가장 간단함
  • Parquet: 고성능 압축 저장에 유리
  • SQLite: 구조화된 쿼리 가능
  • DuckDB: 대용량 분석에 최적화

중소규모 데이터라면 Parquet 형식을 추천합니다.

파생상품 과거 데이터

선물 거래용 K-라인 인터페이스:

  • U 본위 선물: /fapi/v1/klines
  • 코인 본위 선물: /dapi/v1/klines

파라미터와 반환 포맷은 현물 API와 거의 동일합니다.

펀딩비 히스토리 조회

GET /fapi/v1/fundingRate?symbol=BTCUSDT&limit=1000

8시간마다 생성되는 펀딩비 데이터를 최대 1,000개(약 333일분)까지 조회할 수 있습니다.

자주 묻는 질문(FAQ)

Q: 과거 데이터 수집 시 속도 제한(Rate Limit)이 걸리나요? A: 네, 그렇습니다. 요청 사이에 적절한 지연(sleep)을 두어야 합니다.

Q: 상장 폐지된 코인의 데이터도 볼 수 있나요? A: 상장 폐지된 종목은 API 조회가 제한될 수 있습니다. 이 경우 역사적 데이터 아카이브를 확인해야 합니다.

Q: 1분봉 1년치 데이터는 용량이 얼마나 되나요? A: CSV 기준 종목당 약 50MB 내외입니다. 여러 종목을 수집하면 꽤 커집니다.

Q: 데이터에 슬리피지(Slippage) 정보도 포함되나요? A: 아니요, K-라인 데이터에는 슬리피지 모델이 포함되지 않으므로 직접 계산 모델을 추가해야 합니다.

관련 가이드

과거 데이터는 퀀트 트레이딩의 연료와 같습니다. 데이터 수집, 정제, 저장 프로세스를 잘 구축하는 것만으로도 전략 수립의 절반은 성공한 셈입니다.