바이낸스 API 과거 K-라인(캔들) 조회: 데이터 누락 방지 가이드
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-라인 데이터에는 슬리피지 모델이 포함되지 않으므로 직접 계산 모델을 추가해야 합니다.
관련 가이드
과거 데이터는 퀀트 트레이딩의 연료와 같습니다. 데이터 수집, 정제, 저장 프로세스를 잘 구축하는 것만으로도 전략 수립의 절반은 성공한 셈입니다.