장 운영시간·휴장일 처리 — 타임존과 캘린더 함정
분명 평일 오전인데, 왜 장이 안 열려 있지
스케줄러로 자동매매 루프를 돌리는 글에서 정해진 시각에 작업을 실행하는 법을 다뤘다. 그런데 "정해진 시각"이라는 개념 자체가 생각보다 까다롭다. 서버는 평일 오전이라고 판단해서 주문 로직을 돌렸는데, 실제로는 그날이 공휴일이라 거래소가 문을 닫았거나, 서버 시간과 거래소 시간대가 어긋나 있던 경우가 있다.
이 글은 특정 거래소의 실제 개장 시각표를 다루지 않는다. 어떤 시장이든 적용할 수 있는, 시간 관련 함정을 피하는 설계 원칙을 다룬다.
함정 1 — 서버 시간대와 거래소 시간대는 다를 수 있다
서버가 UTC로 돌아가고 있는데 코드에서 "9시부터 15시까지"를 서버의 로컬 시간 기준으로 판단하면, 실제 거래소 시간과 어긋난다. 해외 거래소를 다루면 시차 문제가 더 커진다. 원칙은 하나다 — 판단 로직에서는 항상 거래소가 위치한 타임존으로 명시적으로 변환한 시각을 쓴다.
python 코드 보기
from datetime import datetime
from zoneinfo import ZoneInfo
def is_market_hours(now_utc, exchange_tz, open_time, close_time):
local_now = now_utc.astimezone(ZoneInfo(exchange_tz))
return open_time <= local_now.time() <= close_time서버 시간을 그대로 비교하지 않고, exchange_tz로 변환한 뒤 비교하는 것이 핵심이다. 이렇게 하면 서버가 어느 지역에 있든, 서머타임이 있는 지역이든 같은 코드로 처리할 수 있다.
함정 2 — 서머타임이 있는 지역은 오프셋이 계절마다 바뀐다
미국처럼 서머타임(daylight saving time)을 쓰는 지역은 연중 특정 기간 동안 UTC 오프셋이 한 시간 바뀐다. 오프셋을 숫자로 하드코딩(UTC-5처럼)해두면, 서머타임이 바뀌는 시점에 계산이 한 시간씩 틀어진다. 위 예시처럼 zoneinfo 같은 타임존 라이브러리를 쓰면 서머타임 전환을 라이브러리가 알아서 반영해준다.
함정 3 — 휴장일은 요일만으로 판단할 수 없다
주말을 걸러내는 건 쉽다. 문제는 공휴일, 임시 휴장일, 반나절만 여는 날처럼 요일 패턴으로 예측할 수 없는 날들이다. 이런 날을 코드 안에 규칙으로 박아 넣으면 매년 갱신을 깜빡하게 된다. 대신 거래소가 공식으로 제공하는 휴장일 캘린더(공휴일 목록 API나 파일)를 별도로 불러와 참조하는 구조를 권한다.
python 코드 보기
def is_trading_day(date, holiday_calendar):
if date.weekday() >= 5: # 토·일
return False
return date not in holiday_calendar
def should_run_today(date, holiday_calendar):
if not is_trading_day(date, holiday_calendar):
log_event("info", "skip_non_trading_day", date=str(date))
return False
return Trueholiday_calendar는 코드에 상수로 박아두는 대신, 매년 또는 매월 최신 목록으로 갱신하는 별도 루틴에서 채우는 값으로 설계하는 편이 유지보수에 유리하다.
오늘의 정리
- 시간 판단 로직은 서버의 로컬 시간이 아니라 거래소가 위치한 타임존으로 변환한 시각을 기준으로 삼아야 한다.
- 서머타임이 있는 지역은 오프셋을 숫자로 하드코딩하지 말고 타임존 라이브러리에 맡긴다.
- 휴장일은 요일 패턴으로 예측할 수 없으므로, 코드에 규칙을 박기보다 별도로 갱신되는 휴장일 캘린더를 참조하는 구조가 안전하다.
이 글의 코드는 시간 처리 개념을 설명하기 위한 예시이며, 특정 거래소의 실제 개장 시각표나 실거래 시스템의 구현이 아닙니다. 정확한 개장 시각·휴장일은 반드시 해당 거래소 공식 공지에서 확인하세요. 투자 조언이 아니며 특정 종목이나 매매기법을 추천하지 않습니다. 수익 보장은 없으며, 투자 손실의 책임은 투자자 본인에게 있습니다.