Pandas vs Polars 틱 데이터 백테스팅 속도 차이는 어디서 벌어질까?
틱 데이터 때문에 Pandas를 Polars로 바꿀지 고민하고 있다면 단순한 속도 비교보다 어떤 작업에서 차이가 발생하는지부터 확인하는 것이 좋습니다. 파일 로딩, 필터링, 집계와 실제 매매 이벤트 계산은 서로 다른 문제이어서 아래 글에 Pandas와 Polars를 비교할 때 제가 먼저 확인하는 기준을 정리했습니다. 큰 도움 되시기를…
Pandas가 느리다면 Polars로 바꾸는 것이 정답일까?
파이썬으로 틱 데이터 백테스팅을 만들다 보면 한 번쯤 이런 생각을 하게 됩니다.
“Pandas가 느린 것 같은데 그냥 Polars로 전부 바꿔볼까?”
검색해보면 Polars가 Pandas보다 빠르다는 이야기도 쉽게 볼 수 있습니다.
그래서 기존 코드를 전부 Polars로 다시 작성하면 백테스트 속도가 크게 개선될 것처럼 느껴질 수 있습니다. 하지만 실제 틱 데이터 백테스트에서는 이야기가 조금 복잡합니다.
백테스트에는 크게 두 종류의 작업이 섞여 있기 때문입니다.
첫 번째는 데이터를 읽고 정리하는 작업입니다.
- 파일 읽기
- 종목·날짜 필터링
- 필요한 컬럼 선택
- 시간순 정렬
- 그룹 연산
- 리샘플링
- 통계 계산
두 번째는 실제 전략을 실행하는 작업입니다.
- 현재 포지션 확인
- 매수·매도 조건 판단
- 주문 발생
- 체결 여부 계산
- 수수료와 슬리피지 반영
- 손익 업데이트
이 둘을 구분하지 않고 “Pandas가 느리다”고 결론 내리면 엉뚱한 부분을 최적화할 가능성이 있습니다.
특히 DataFrame 처리보다 Python으로 작성된 이벤트 반복문이 전체 실행시간 대부분을 차지한다면 DataFrame 라이브러리를 바꿔도 기대한 만큼 차이가 나지 않을 수 있습니다.
그래서 Pandas와 Polars를 비교할 때 가장 먼저 해야 할 질문은 이것입니다.
내 백테스트에서 DataFrame이 느린가, 전략 시뮬레이션이 느린가? 이 질문부터 분리해야 합니다.
Polars는 어떤 부분에서 강점을 가질까?
Polars에서 특히 눈여겨볼 부분은 Lazy API입니다.
Pandas에서는 일반적으로 명령을 실행할 때마다 결과가 만들어지는 방식으로 코드를 작성하는 경우가 많습니다. 반면 Polars의 Lazy API는 먼저 수행할 작업을 구성한 뒤 전체 쿼리 계획을 최적화하고 실행할 수 있습니다.
Polars 공식 문서에서는 대표적인 최적화 기능으로 predicate pushdown과 projection pushdown 등을 설명합니다.
쉽게 말하면, 필터링할 데이터는 가능한 앞에서 제거하고, 사용하지 않는 컬럼은 처음부터 읽지 않는 방식입니다.
예를 들어 틱 데이터에 이런 컬럼이 있다고 가정해보겠습니다.
- timestamp
- symbol
- price
- volume
- bid
- ask
- exchange
- condition
- sequence
그런데 내가 만드는 전략에서 실제 필요한 데이터가
timestamp
price
volume
세 개뿐이라면 모든 데이터를 메모리에 올린 뒤 필요 없는 컬럼을 버리는 것보다 필요한 부분만 읽는 구조가 효율적일 수 있습니다.
기간도 마찬가지입니다.
전체 데이터를 읽은 뒤 특정 거래일을 선택하는 것보다 파일을 읽는 단계에서부터 필요한 기간을 좁힐 수 있다면 처리할 데이터량 자체가 줄어듭니다.
틱 데이터처럼 원본 데이터량이 커질수록 이런 차이가 중요해질 수 있습니다.
Polars 공식 문서에서도 Lazy API를 사용할 경우 필요한 행과 컬럼을 읽는 단계부터 줄여 CPU와 메모리 부담을 낮출 수 있다고 설명합니다.

즉 Polars의 장점은 단순히 “Rust로 만들어져 빠르다” 한 문장으로 설명하기보다, 불필요한 데이터를 얼마나 일찍 제거할 수 있는 구조인가 라는 관점에서 보는 것이 더 정확합니다.
실제 속도 비교에서 반드시 조심해야 하는 부분
여기서 가장 많이 하는 실수가 있습니다.
인터넷에서 본 벤치마크 숫자를 그대로 자신의 백테스트에 적용하는 것입니다.
Polars 개발팀도 Pandas, DuckDB, PySpark 등을 대상으로 한 PDS-H 벤치마크 결과를 공개하고 있습니다. 하지만 해당 테스트는 분석 쿼리를 기준으로 한 벤치마크이지, 특정 증권시장의 틱 데이터 백테스팅을 그대로 재현한 테스트가 아닙니다.
따라서 “Polars가 벤치마크에서 빨랐으니 내 전략도 같은 비율로 빨라질 것이다” 라고 해석하면 곤란합니다. 백테스트에서는 작업 유형을 따로 비교해야 합니다.
예를 들어 이런 식입니다.
- 파일 읽기 속도
- 날짜 필터링 속도
- 종목 필터링 속도
- group_by 연산
- rolling 계산
- resample 또는 시간 단위 집계
- 전략 시그널 생성
- 이벤트 기반 주문 시뮬레이션
특히 8번은 완전히 다른 문제일 수 있습니다.
예를 들어 다음 틱의 계산이 이전 틱의 포지션 상태에 따라 결정된다고 해보겠습니다.
현재 포지션이 없는가?
매수 신호가 발생했는가?
주문이 체결됐는가?
체결됐다면 평균단가는 얼마인가?
손절 조건에 도달했는가?
이런 계산은 순차적으로 상태가 변합니다.
따라서 단순한 컬럼 계산과는 성격이 다릅니다.
DataFrame 처리 속도만 비교해서는 전체 백테스트 성능을 제대로 평가하기 어려운 이유입니다.
틱 데이터라면 CSV보다 Parquet부터 비교해보자
Pandas와 Polars를 비교하기 전에 파일 형식부터 확인해야 하는 경우도 많습니다.
대규모 틱 데이터를 매번 CSV로 읽고 있다면 라이브러리보다 I/O가 먼저 병목이 될 수 있습니다.
Parquet은 컬럼 기반 저장 포맷입니다.
Apache Arrow 공식 문서에서도 필요한 일부 컬럼만 선택해서 읽을 수 있으며, 컬럼형 구조 때문에 전체 파일을 읽는 것보다 효율적일 수 있다고 설명합니다.
예를 들어 백테스트에서 timestamp, price, volume만 사용한다면 해당 컬럼만 읽는 구조를 만들 수 있습니다.
여기에 DuckDB 같은 도구를 활용하는 방법도 있습니다.
DuckDB는 Parquet 파일을 직접 조회하면서 필요한 컬럼만 읽는 projection pushdown과 조건에 맞는 데이터를 미리 거르는 filter pushdown을 지원합니다.
따라서 비교 순서를 이렇게 잡아보는 것이 좋습니다.
- Pandas + CSV
- Pandas + Parquet
- Polars + Parquet
- Polars Lazy + Parquet
- DuckDB로 필요한 데이터만 조회 후 DataFrame 전달
이렇게 테스트하면 중요한 사실을 하나 알 수 있습니다.
속도 개선이
Pandas → Polars
에서 발생한 것인지,
아니면
CSV → Parquet
에서 더 크게 발생한 것인지 분리해서 볼 수 있습니다.
이 차이를 모르고 여러 가지를 동시에 바꾸면 나중에는 무엇 때문에 빨라졌는지 알 수 없습니다.
또 Parquet이라고 모두 같은 성능이 나오는 것도 아닙니다.
파일 개수, row group 크기, 압축 방식, 데이터 배치 구조 등에 따라 실제 성능은 달라질 수 있습니다. DuckDB 공식 문서 역시 Parquet 파일 구조와 row group 설정 등이 처리 성능에 영향을 줄 수 있다고 설명하고 있습니다.
Pandas vs Polars 틱 데이터 백테스팅 속도 차이는 어디서 벌어질까?
결국 Pandas와 Polars 중 무엇을 선택해야 할까?
결론부터 말하면 모든 백테스트를 Polars로 바꿔야 하는 것도 아니고, 익숙하다는 이유만으로 계속 Pandas만 사용할 필요도 없습니다.
작업에 따라 나눠 보는 것이 가장 현실적입니다.
Pandas를 계속 사용해도 좋은 경우
- 데이터 규모가 충분히 관리 가능한 경우
- 기존 분석 코드가 Pandas 중심으로 안정적으로 구축된 경우
- DataFrame 처리가 전체 병목이 아닌 경우
- 개발과 유지보수 편의성이 더 중요한 경우
- NumPy와 기존 Python 생태계 연결이 중요한 경우
특히 계산 병목이 수치 반복문이라면 Pandas를 버리기보다 NumPy 배열과 Numba를 결합하는 방법을 먼저 검토할 수 있습니다.
Pandas 공식 성능 문서 역시 큰 데이터의 특정 연산에서는 Numba JIT를 활용할 수 있다고 설명합니다. 다만 첫 실행에서는 컴파일 비용이 발생하므로 작은 데이터에서는 오히려 이점이 크지 않을 수도 있습니다.
Polars를 적극적으로 검토해볼 경우
- 수천만 건 이상의 데이터를 반복 처리하는 경우
- 필터링과 집계 작업이 많은 경우
- 여러 컬럼 중 일부만 반복해서 사용하는 경우
- 데이터 전처리에 많은 시간이 소요되는 경우
- Lazy Query 최적화를 활용할 수 있는 경우
- 메모리 사용량 때문에 전체 데이터를 처리하기 어려운 경우
하지만 여기에서도 한 가지는 변하지 않습니다.
직접 측정해야 합니다.
예를 들어 동일한 Parquet 데이터를 준비하고 다음과 같이 비교합니다.
Pandas 로딩 시간
Polars 로딩 시간
Pandas 필터링 시간
Polars 필터링 시간
Pandas 시그널 생성 시간
Polars 시그널 생성 시간
그리고 마지막으로
전체 백테스트 실행시간
을 비교합니다.
가능하다면 첫 실행과 반복 실행도 구분해서 측정하는 편이 좋습니다.
OS 파일 캐시, JIT 컴파일, 데이터 캐싱 등에 따라 첫 실행과 이후 실행의 조건이 달라질 수 있기 때문입니다.
그리고 속도만 비교해서도 안 됩니다.
두 코드의 결과가 동일한지 반드시 함께 확인해야 합니다.
timestamp 정렬 순서가 동일한가?
결측치 처리는 같은가?
동일 timestamp의 여러 틱 처리 순서는 같은가?
rolling 계산의 경계 조건은 같은가?
체결 결과와 최종 손익이 같은가?
이 조건이 맞지 않으면 빠른 코드와 느린 코드를 비교한 것이 아니라 서로 다른 백테스트를 비교한 셈이 됩니다.
Pandas와 Polars 중 하나를 고르는 것보다 중요한 것은 결국 이것입니다.
데이터 처리 엔진과 전략 실행 엔진을 분리해서 생각하는 것.
틱 데이터를 빠르게 읽고 정리하는 부분은 Polars·Parquet·DuckDB 같은 도구를 활용하고,
순차적인 전략 계산에서는 NumPy·Numba 또는 별도의 이벤트 엔진을 사용하는 식으로 역할을 나누는 방법도 충분히 검토할 수 있습니다.
처음부터 하나의 라이브러리가 모든 것을 해결해야 할 이유는 없습니다.
지금 Pandas 백테스트가 느리다면 바로 전체 코드를 Polars로 다시 작성하기보다 먼저 데이터 로딩, 전처리, 시그널 계산, 체결 시뮬레이션 시간을 각각 측정해보세요.
그 결과를 보면 어디를 바꿔야 하는지가 훨씬 명확해집니다.
자주 묻는 질문
Q1. Polars가 Pandas보다 항상 빠른가요?
그렇게 단정하기 어렵습니다. 데이터 크기, 연산 종류, 파일 형식, 코드 구조와 하드웨어에 따라 결과가 달라질 수 있습니다. 특히 DataFrame 처리와 이벤트 기반 백테스트는 별도로 측정해야 합니다.
Q2. 기존 Pandas 코드를 전부 Polars로 바꾸는 것이 좋을까요?
먼저 프로파일링하는 편이 좋습니다. 전체 실행시간 중 데이터 전처리 비중이 크다면 효과가 있을 수 있지만 Python 이벤트 루프가 병목이라면 다른 최적화가 우선일 수 있습니다.
Q3. 틱 데이터를 처음 구축한다면 어떤 구조가 좋을까요?
하나의 정답은 없지만 원본 데이터, 분석용 저장 데이터, 전략 실행 로직을 분리하는 구조가 관리하기 좋습니다. 반복적으로 사용할 틱 데이터는 Parquet 같은 분석용 저장 포맷을 검토하고 필요한 데이터만 읽을 수 있도록 날짜·종목 구조를 설계하는 것도 방법입니다.
자료 출처
- Polars 공식 User Guide, Lazy API 및 Query Optimizations
- Polars PDS-H 공개 벤치마크, 2025년 공개 자료
- pandas 공식 문서, Enhancing Performance 및 Numba 활용 가이드
- Apache Arrow 공식 문서, Parquet 컬럼 기반 저장 및 선택적 컬럼 읽기
- DuckDB 공식 문서, Parquet Projection·Filter Pushdown 및 성능 가이드
※ 공개 벤치마크 결과는 특정 하드웨어, 데이터와 쿼리 조건에서 측정된 결과입니다. 틱 데이터 백테스트의 실제 처리 속도를 의미하지 않으며 라이브러리 버전, CPU, 메모리, 저장장치, 파일 형식과 구현 방식에 따라 결과가 달라질 수 있습니다.
※ 본 글은 데이터 처리와 백테스팅 시스템 구축에 관한 기술 정보이며 특정 투자전략의 성과나 수익을 보장하거나 예측하는 내용이 아닙니다.
금알남
댓글 0
첫 댓글을 남겨보세요.