Capital Markets and Settlement
The cancel notice arrived twice and the position flipped sign
한국어 원문으로 표시합니다.
목표
이미 나간 체결에 대한 취소·정정 통지를 원 체결에 이어 붙이고, 원 장부를 지우는 대신 상쇄 기록을 더해 새 장부를 만듭니다. 포지션을 다시 계산해 이미 나간 보고와 대조하고, 같은 통지를 두 번 받아도 장부가 같은지 확인한 뒤 재보고 대상과 정정 보고서를 냅니다.
왜 중요한가
체결 원장은 이미 여러 곳으로 흘러 나간 자료입니다. 그 한 줄을 조용히 고쳐 쓰면 어제 나간 보고와 오늘 보는 원장이 어긋나고, 어긋난 이유는 어디에도 남지 않습니다. 그래서 금융 장부는 뒤에 씁니다. 취소는 부호가 반대인 상쇄 기록을 더하는 일이고, 정정은 상쇄한 뒤 고쳐진 값으로 다시 쓰는 일입니다. 어려운 것은 이 규칙 자체가 아니라 가장자리입니다. 통지가 없는 체결을 가리킬 수도 있고, 같은 통지가 재전송으로 두 번 올 수도 있고, 이미 취소된 체결에 정정이 올 수도 있습니다. 하나만 놓쳐도 포지션이 반대로 넘어가고, 그 사실은 대개 다음 날 보고가 틀린 뒤에야 드러납니다.
단계
python3로/root/bust/data에fills.jsonl·notices.jsonl·position_report.csv·rules.json을 만듭니다.- 통지를 도착 순서대로 읽어 판정을
/root/bust/notice_match.csv에 적습니다. - 적용할 취소를 상쇄 기록으로 더해
/root/bust/ledger_bust.jsonl을 만듭니다. - 정정을 상쇄와 재기장으로 더해
/root/bust/ledger_final.jsonl을 만들고 주문별 평균 단가를/root/bust/order_avg.csv에 냅니다. - 포지션을 다시 계산해
/root/bust/position_diff.csv에 어긋난 종목만 적습니다. - 같은 통지 스트림을 두 번 흘려 넣어
/root/bust/ledger_twice.jsonl과/root/bust/idem.json을 만듭니다. - 보고 시각 뒤에 도착한 통지를 모아
/root/bust/rereport.csv를 만듭니다. - 변경 하나하나의 출처를
/root/bust/trace.csv에, 전체 요약을/root/bust/report.json에 적습니다.
참고
- 통지는
seq가 도착 순서입니다. 판정은 이 순서대로 하고, 적용한 취소를 기억해야 재취소를 가를 수 있습니다. - 판정 이름은 넷입니다. 같은 통지 식별자를 앞에서 이미 본 것은
중복통지, 가리키는 체결이 원장에 없으면대상없음, 가리키는 체결이 앞에서 이미 취소됐으면이미취소됨, 나머지는적용입니다. 이 순서로 봅니다. - 장부 기록은 열한 칸입니다.
entry_id·kind·fill_id·order_id·symbol·side·qty·px·notional·source_notice·entry_time.kind는fill·reversal·rebook셋입니다. - 상쇄 기록의
entry_id는 통지 식별자에-rv를 붙인 것, 재기장은-rb를 붙인 것입니다.entry_time은 통지 시각입니다. - 정정 통지의
new_qty·new_px가null이면 그 값은 원 체결의 값을 그대로 씁니다. - 금액은
decimal로 계산하고 소수 넷째 자리에서ROUND_HALF_UP으로 반올림합니다. 문자열로 적으세요. - 포지션은 매수를 더하고 매도를 빼서 셉니다. 상쇄 기록은 수량이 음수라 부호가 저절로 뒤집힙니다.
- 자료 파일
rules.json에 포지션 보고 시각이 들어 있습니다.date로 오늘을 쓰지 마세요. - 흔한 실수 1: 원 기록을 고쳐서 정정하는 것. 적용 전 자료가 남아 있어야 전후를 견줄 수 있습니다.
- 흔한 실수 2: 통지 식별자를 기억하지 않아 재전송된 취소를 두 번 상쇄하는 것.
- 공개 문서: FIX Standards, Fiximate, decimal. 체결 열여덟 건과 통지 열네 건은 이 실습의 합성 자료입니다.
체결 원장과 취소·정정 통지, 포지션 보고 만들기
python3 로 /root/bust/data 에 fills.jsonl·notices.jsonl·position_report.csv·rules.json 을 만듭니다. 난수를 쓰지 않는 생성 스크립트를 그대로 쓰세요.
고객의 체결 원장을 그대로 가져올 수 없으니 같은 모양의 합성 자료를 만듭니다. 난수를 쓰지 않아야 누가 몇 번을 돌려도 같은 자료가 나오고 서로의 판정을 대조할 수 있습니다. 채점기는 자료를 표준형으로 바꿔 지문을 대조하므로 손으로 고치면 뒤 단계가 전부 막힙니다.
통지와 원 체결을 이어 붙여 판정하기
/root/bust/notice_match.csv 에 첫 줄 seq,notice_id,type,target_fill_id,verdict 를 두고, 통지를 도착 순서대로 읽어 적용·대상없음·이미취소됨·중복통지 중 하나를 적으세요. 모든 통지를 한 줄씩 적습니다.
네 가지를 이 순서로 봅니다. 같은 통지 식별자를 앞에서 이미 봤는가, 가리키는 체결이 원장에 있는가, 그 체결이 앞에서 이미 취소됐는가, 그리고 나머지가 적용입니다. 취소를 적용할 때마다 그 체결 식별자를 기억해 두어야 세 번째 검사가 가능합니다. 통지 식별자는 판정과 무관하게 전부 기억합니다.
취소를 상쇄 기록으로 더해 새 장부 만들기
/root/bust/ledger_bust.jsonl 에 원 체결 열여덟 줄을 kind 가 fill 인 기록으로 그대로 옮기고, 적용할 취소마다 수량과 금액의 부호가 반대인 reversal 기록을 더하세요. 원 기록은 고치지 않습니다.
지우지 않고 더합니다. 상쇄 기록의 수량은 원 체결 수량에 마이너스를 붙인 값이고 단가는 원 체결 그대로입니다. 그래야 금액도 저절로 반대 부호가 됩니다. entry_id 는 통지 식별자에 -rv 를 붙이고 source_notice 에 그 통지를 남겨 두면 나중에 출처를 따라갈 수 있습니다. 원 체결 기록의 source_notice 는 빈 문자열입니다.
정정을 반영하고 평균 단가 다시 내기
/root/bust/ledger_final.jsonl 은 3단계 장부에 정정마다 reversal 과 rebook 두 줄을 더한 것입니다. /root/bust/order_avg.csv 에 첫 줄 order_id,net_qty,net_notional,avg_px 를 두고 주문마다 한 줄씩 적으세요.
정정은 원 기록을 상쇄한 뒤 고쳐진 값으로 다시 한 줄 씁니다. 통지에 없는 값은 원 체결의 값을 그대로 쓰세요. 가격만 바뀐 정정은 수량이 같고 금액만 달라집니다. 평균 단가는 장부의 금액 합을 수량 합으로 나눈 값이고, 전부 취소된 주문은 수량 합이 0 이라 0 으로 둡니다. 나누기 전에 0 인지부터 보세요.
포지션을 다시 계산해 기존 보고와 대조하기
/root/bust/position_diff.csv 에 첫 줄 symbol,reported_qty,recomputed_qty,diff 를 두고, 최종 장부로 다시 계산한 포지션이 position_report.csv 와 다른 종목만 적으세요.
포지션은 매수를 더하고 매도를 빼서 셉니다. 상쇄 기록은 수량이 음수라 부호가 저절로 뒤집히므로 따로 분기할 필요가 없습니다. diff 는 다시 계산한 값에서 보고된 값을 뺀 것입니다. 값이 같은 종목은 적지 않습니다. 차이가 전부 늦게 온 통지로 설명되지는 않으니, 설명되지 않는 종목이 있어도 그대로 두세요.
같은 통지를 두 번 받아도 장부가 같은지 시험하기
통지 스트림 뒤에 같은 통지를 한 번 더 이어 붙여(두 번째 묶음은 seq 에 1000 을 더합니다) /root/bust/ledger_twice.jsonl 을 만들고, /root/bust/idem.json 에 entries·same_as_final·ignored_duplicates 를 적으세요.
재전송은 정상적인 일입니다. 통지 식별자를 기억하지 않으면 한 번 취소된 체결이 두 번 상쇄되어 포지션이 반대로 넘어갑니다. 두 번째 묶음은 식별자가 전부 앞에서 본 것이므로 하나도 적용되지 않아야 하고, 그러면 장부는 4단계 것과 똑같아집니다. ignored_duplicates 는 이어 붙인 스트림 전체에서 중복통지로 판정된 통지의 수이고, same_as_final 은 참과 거짓입니다.
보고 뒤에 도착한 통지를 재보고 대상으로 모으기
/root/bust/rereport.csv 에 첫 줄 notice_id,type,target_fill_id,symbol,position_delta 를 두고, 적용된 통지 가운데 통지 시각이 rules.json 의 포지션 보고 시각보다 뒤인 것을 적으세요.
포지션 보고가 나간 뒤에 도착한 통지는 장부만 고쳐서 끝나지 않고 이미 나간 보고를 틀린 것으로 만듭니다. 기준 시각은 rules.json 에 있으니 오늘 날짜를 쓰지 마세요. position_delta 는 그 통지가 포지션을 얼마나 움직이는가이고, 매도는 부호가 반대입니다. 가격만 바뀐 정정은 수량을 건드리지 않아 0 이 되지만 재보고 대상에서 빼지는 마세요.
정정 보고서와 변경 추적표 쓰기
/root/bust/trace.csv 에 첫 줄 entry_id,kind,fill_id,source_notice,reason,qty,px,notional 을 두고 최종 장부에서 kind 가 fill 이 아닌 기록을 전부 적고, /root/bust/report.json 에 전체 요약을 적으세요.
받는 사람이 다음에 무엇을 할지 정할 수 있어야 보고가 쓸모 있습니다. 변경마다 어떤 통지에서 왔는지와 그 통지의 사유를 붙이면 몇 달 뒤에도 따라갈 수 있습니다. reason 은 통지 자료에서 가져오되 실제로 적용된 통지의 것이어야 합니다. 같은 식별자로 재전송된 사본은 사유가 달라 여기서 갈립니다. 요약에 넣을 열쇠는 fills·notices·적용·대상없음·이미취소됨·중복통지·bust_applied·adjust_applied·entries_before·entries_after·position_mismatch·rereport 입니다.