Capital Markets and Settlement
After the clock change, two markets closed at the same instant
한국어 원문으로 표시합니다.
목표
네 시장의 지역시 체결 기록을 시간대 규칙으로 UTC 로 바꾸고, 서머타임 전환일의 특수한 시각을 가르고, 세션 구간과 거래일 라벨을 매긴 뒤, 시장별 마감이 UTC 에서 겹치는 날과 달력 자체의 모순을 찾아냅니다.
왜 중요한가
시각 변환을 고정 오프셋으로 해 두면 예외가 나지 않습니다. 그냥 한 시간 어긋난 값이 저장될 뿐이고, 그 사실은 전환 주말이 지나고 대사가 안 맞을 때에야 드러납니다. 자본시장에서는 이 어긋남이 곧바로 마감 배치와 집계에 닿습니다. 게다가 시장마다 전환 날짜가 달라서, 한쪽은 이미 여름 시각인데 다른 쪽은 아직 겨울 시각인 몇 주가 해마다 있습니다. 그 몇 주 동안만 두 시장의 마감이 같은 순간에 놓이는 일이 실제로 일어납니다.
단계
python3로/root/session/data에markets.json·calendar.json·trades.csv를 만듭니다.- 지역시를 시간대 규칙으로 UTC 로 바꿔
/root/session/normalized.csv에trade_id,market,utc_ms로 적습니다. 그 지역시에 존재하지 않는 시각은 넣지 않습니다. - 같은 체결을 겨울 오프셋 고정으로 바꿔 보고, 결과가 다른 것을
/root/session/fixed_diff.csv에 적습니다. - 존재하지 않는 시각을
/root/session/nonexistent.csv에, 두 번 있는 시각을/root/session/ambiguous.csv에 적습니다. - 체결마다 세션 구간을
/root/session/phase.csv에trade_id,phase로 적습니다. - 달력일과 거래일이 갈리는 체결을
/root/session/tradingday.csv에 적습니다. - 기준일마다 시장별 정규 마감을
/root/session/close_utc.csv에, 마감이 가까운 시장 쌍을/root/session/overlap.csv에 적습니다. - 달력 자체의 모순을
/root/session/calendar_defects.csv에 적고, 앞 단계의 수를/root/session/summary.json에 요약합니다.
참고
utc_ms는 UTC 기준 밀리초 정수입니다. 두 번 있는 시각은fold가 0 인 쪽, 즉 먼저 지나간 순간을 씁니다.- 3단계의 겨울 오프셋은 그 시간대의 2025-01-15 12:00 오프셋입니다. 그 값을 코드에 적지 말고 시간대에서 구하세요.
- 5단계 구간은
pre·regular·post·closed·holiday다섯입니다. 구간은 시작을 포함하고 끝을 포함하지 않습니다. 반일장은 정규 마감만 바뀌고, 휴장일은 다른 무엇보다 먼저 판정합니다. - 6단계에서 거래일이 달력일과 다를 수 있는 시장은
calendar.json의overnight_markets에 있습니다. 그 시장에서 개장 후 구간이 끝나는 시각보다 이른 체결은 전날 거래일입니다. - 7단계에서 자정을 넘는 세션의 마감은 다음 날에 있습니다. 가까움의 기준은
calendar.json의overlap_minutes이고, 시장 이름은 사전 순으로 앞선 쪽을market_a에 적습니다. - 8단계 모순은
휴장일에반일장정의와반일장마감이정규보다늦음두 가지입니다. - 흔한 실수 1: 존재하지 않는 시각을 그냥 변환해 저장하는 것. 예외가 나지 않고 한 시간 뒤 값이 됩니다.
- 흔한 실수 2: 휴장일 판정을 세션 구간 판정 뒤에 하는 것. 휴장일의 체결이 정규장으로 분류됩니다.
- 공개 문서: IANA tz, zoneinfo, PEP 615, RFC 3339. 시장 이름과 세션 시각은 이 실습의 합성 자료이고, 시간대 식별자만 실제 IANA 이름입니다.
네 시장의 세션 정의와 달력, 체결 자료 만들기
python3 로 /root/session/data 에 markets.json·calendar.json·trades.csv 를 만듭니다. 난수를 쓰지 않는 생성 스크립트를 그대로 쓰세요.
고객 자료를 그대로 쓸 수 없으니 같은 모양의 합성 자료를 만듭니다. 난수를 쓰지 않아야 누가 몇 번을 돌려도 같은 자료가 나옵니다. 채점기는 자료를 표준형으로 바꿔 지문을 대조하므로 손으로 고치면 뒤 단계가 전부 막힙니다.
지역시를 시간대 규칙으로 UTC 로 바꾸기
/root/session/normalized.csv 에 첫 줄 trade_id,market,utc_ms 를 두고 체결을 UTC 밀리초로 적으세요. 그 지역시에 존재하지 않는 시각은 넣지 않습니다.
zoneinfo.ZoneInfo 로 시간대를 붙입니다. 존재하지 않는 시각인지는 UTC 로 갔다가 같은 시간대로 돌아와 벽시계 값이 그대로인지로 알 수 있습니다. 두 번 있는 시각은 먼저 지나간 쪽을 씁니다.
고정 오프셋으로 바꿔 보고 어긋난 날 찾기
/root/session/fixed_diff.csv 에 첫 줄 trade_id,tz_utc_ms,fixed_utc_ms,diff_min 을 두고, 겨울 오프셋 고정으로 바꾼 값이 시간대 규칙으로 바꾼 값과 다른 체결을 적으세요.
겨울 오프셋은 그 시간대의 2025-01-15 12:00 오프셋입니다. 값을 코드에 적지 말고 시간대에서 구하세요. diff_min 은 고정 오프셋 값에서 규칙 값을 뺀 분 단위 차이입니다. 존재하지 않는 시각은 이 표에 넣지 않습니다.
없는 시각과 두 번 있는 시각 가르기
/root/session/nonexistent.csv 에 trade_id,market,local_ts 를, /root/session/ambiguous.csv 에 trade_id,market,local_ts,first_utc_ms,second_utc_ms 를 적으세요.
봄에 시계를 앞당기는 시장에서는 건너뛴 한 시간이 존재하지 않습니다. 가을에 되돌리는 시장에서는 같은 벽시계 값이 두 번 지나갑니다. fold 가 0 인 것과 1 인 것의 오프셋이 다른지 보면 두 경우를 함께 잡을 수 있고, 둘 중 어느 쪽인지는 되돌아오기 시험으로 가릅니다.
체결마다 세션 구간 매기기
/root/session/phase.csv 에 첫 줄 trade_id,phase 를 두고 모든 체결에 pre·regular·post·closed·holiday 중 하나를 매기세요.
휴장일을 가장 먼저 판정합니다. 그 다음 개장 전, 정규, 개장 후 순서로 보고 어디에도 없으면 닫힌 시각입니다. 반일장이 있는 날은 정규 마감만 바뀝니다. 구간은 시작을 포함하고 끝을 포함하지 않습니다.
자정을 넘는 세션의 거래일 라벨 붙이기
/root/session/tradingday.csv 에 첫 줄 trade_id,calendar_date,trading_day 를 두고, 두 값이 다른 체결만 적으세요.
자정을 넘는 세션이 있는 시장은 자료에 적혀 있습니다. 그 시장에서 개장 후 구간이 끝나는 시각보다 이른 체결은 전날 세션에 속합니다. 다른 시장은 언제나 달력일과 같습니다.
시장별 마감을 UTC 로 모아 겹치는 배치 창 찾기
/root/session/close_utc.csv 에 market,date,close_utc_ms 를, /root/session/overlap.csv 에 date,market_a,market_b,gap_min 을 적으세요.
기준일 목록과 가까움의 기준은 자료에 있습니다. 휴장일인 시장은 그 날 마감이 없습니다. 자정을 넘는 세션의 마감은 다음 날에 있으니 날짜를 하루 더해야 합니다. 시장 쌍은 사전 순으로 앞선 쪽을 먼저 적습니다.
달력 자체의 모순을 찾고 전체를 요약하기
/root/session/calendar_defects.csv 에 market,date,defect 를 적고, /root/session/summary.json 에 trades·nonexistent·ambiguous·fixed_diff·phases·trading_day_differs·overlaps·calendar_defects 를 요약하세요.
모순은 두 가지입니다. 같은 날이 휴장일이면서 반일장으로도 적힌 경우와, 반일장 마감이 정규 마감보다 늦은 경우입니다. 요약의 수는 손으로 세지 말고 앞 단계와 같은 계산에서 가져오세요. phases 는 구간 이름을 열쇠로 하는 개수 객체입니다.