
채권시장은 21세기에도 여전히
우수한 기술력을 자랑하는 플랫폼인
'메신저'에 1200명이 한 방에 모여
돗때기 시장판 마냥 조용한 고성이 오고간다.
실시간으로 호가가 뒤섞여 정신이 없다.
오늘이 지나면 그 호가는 사라진다.
분석이 안 된다.
그래서 할 수 있을지 없을지도 모르겠지만
일단 들이박아본다.
K-Bond 호가분석 시스템 개발.
오늘은 일단 무식하게,
호가를 전부 DB에 쑤셔넣는 것부터.
1. 문자열 분석: regex로 기본구조 발라내기
홍길동 (11:11:11) : 25-3 58- (A사 B부 1234-5678)
김철수 (11:15:20) : ㅎㅈ [C부 2345-6789]
bgc 임꺽정 (14:23:22) 26.3.5(목) 우금캐510-1 (민평 2.617%/끝.82/AA-) 민평 팔자 2.629 (채권부 555-4444)
메신저로 실시간 들어오는 문자열.
규칙이 있는 듯하면서도 없다.
하지만 일단 확실히 있는 규칙부터 턴다.
- 발화자 (broker): 홍길동
이름으로 시작한다. 대부분 세글자이지만,
아닐수도 있다. - 시간 (talk_time): [공백](HH:MM:SS)[공백]:[공백]
- 본문 (content): 25-3 58-
대충 2025년에 3번째로 발행한 5년만기 국채
ytm 2.58% (앞자리 2는 다 아니까 생략)
팔자 (-) (사자는 +)
필요로하는 핵심 메시지이다. - 뒷부분 연락처 (footer)
보통 괄호나 대괄호로 끝남.
전화할거 아니니까 별로 필요없음.

앞쪽부터 regex 회칼로 고정규칙 파트를 식별.
broker, talk_time, main_msg로 해체한다.
main_msg에서 다시 뒷부분 연락처 파트
지느러미 꼬리에 regex 회칼을 쑤셔넣고
footer로 해체한다.
괄호 나온다고 무조건 해체하면,
가운데 꼭 필요한
몸통을 반토막 내버리는 참사가 발생. 주의.
def is_system_message(line: str) -> bool:
# 입장/퇴장, 자동저장 메시지 제거
if "[자동 대화 저장 시작]" in line:
return True
if re.match(r".+님이 입장하셨습니다\.", line.strip()):
return True
if re.match(r".+님이 퇴장하였습니다\.", line.strip()):
return True
return False
입장, 퇴장 등 쓰잘데기 없는 구문.
생선 대가리, 등 지느러미부터 쳐내듯이,
필터 함수로 먼저 깔끔하게 쳐낸다.
2. 정제 후 DataFrame으로 정리
parsed = []
for m in messages:
p = parse_message(m, scrape_time=scrape_time_str)
if p:
# talk_time 문자열 → datetime.datetime 변환
hhmmss = datetime.strptime(p["talk_time"], "%H:%M:%S").time()
full_dt = datetime.combine(scrape_dt.date(), hhmmss)
p["talk_time"] = full_dt
p["raw_message"] = m
p["msg_hash"] = hashlib.md5(m.encode()).hexdigest() # 고유 hash값 생성
parsed.append(p)
df = pd.DataFrame(parsed)
df = df[[
"room", "broker", "talk_time", "content", "footer",
"scrape_time", "raw_message", "msg_hash"
]]
df["talk_time"] = df["talk_time"].apply(lambda x: x.strftime("%Y-%m-%d %H:%M:%S"))
return df
- parse_message() 에서 모든 정제를 마치고,
- hashlib으로 각 메시지마다 고유 hash값 생성.
토막낸 본문만으로 hash를 생성하면,
시간대 다른 동일호가가 중복판정으로 누락 가능.
꼭 raw_message로 hash 생성해야 함. - 향후 조회 용이성을 위해 '(HH:MM:SS)' 시간 칸에,
날짜가 포함된 양식으로 갈아끼운다. - 중복 제거 + 정렬 + 저장을 위한 준비 완료.
3. MySQL DB 설계 후 쏟아붓기
MySQL에 통 하나 만든다.

- 인덱스용 id
- 원문 전체 보존용 raw_message
- 중복 방지용 msg_hash UNIQUE

- 만들어진 kbond_message 통에 정제한 DataFrame을 쏟아붓는다.
- 중복은 INSERT IGNORE INTO 로 해결
결과 확인

11시 이후 메신저 내용을 SELECT 하면,
깔끔하게 해체되어 조회된다.
개꿀.
오늘은 갈치 등뼈정도 발라낸 수준.
젓가락만 들이대면 쏙 빠진다.
이제부터는 본문이다.
패턴이 있어 보이지만 없다.
가시를 하나씩 발라내는 장인정신 필요.
장인정신엔 시간이 필요하여,
일단 다음 편은 FastAPI 기반 웹 조회 방법 쓸 계획.
'Trading & Coding' 카테고리의 다른 글
| [채권 3+초고급엑셀 2] 국채 Tenor별 상대가치분석 자동화 구현(Overview) (5) | 2025.08.19 |
|---|---|
| [엑셀 1] 함수 안먹힐 때, 쉼표 포함 숫자 1초 변환법(텍스트 나누기 활용) (7) | 2025.08.12 |
| [채권 2] K-Bond 호가분석 - 국고·통안 선별기 제작기 (2) | 2025.07.01 |
| [데이터수집] ccxt로 binance 1분봉 실전 수집기 만들기 (0) | 2025.06.22 |
| [Backtest] ATR기반 Trailing Stop전략: 한 줄 버그가 전략을 속임 (3) | 2025.06.15 |