증권거래전표 · diff
git:20261108.6772bdf to git:20261108.7d18e8f
2 added, 1 removed. Audit A to A.
---
name: 증권거래전표
description: "법인 증권계좌의 국내주식·미국주식 거래내역(증권사 엑셀·CSV·HTML xls·PDF·스캔 PDF·화면 캡처 이미지 OCR)을 읽어 전표로 만든다. 머리글 사전으로 삼성·키움·미래에셋·한국투자·NH·KB·신한·토스·대신·메리츠 등 증권사 양식을 표준거래표로 바꾸고, 종목별 이동평균 원가·외화예수금 장부환율로 처분손익·외환차손익·배당·현지세를 계산해, 위하고 일반전표 업로드 파일과 검증 파일(시트 넷: 요약 · 전표 · 거래원장 · 기초·기말) 두 개를 낸다. 두 파일 모두 파이썬 엔진이 계산한 값만 넣고 수식이 없어 엑셀이 없어도 나온다. 증권사 잔액(원화·외화·보유수량)과 줄마다 대사하고, 중단 사유가 있으면 업로드 파일을 만들지 않는다. 증권 거래내역 전표, 주식 거래 분개, 해외주식 회계처리, 증권계좌 전표, 미국주식 전표, 증권사 거래내역 엑셀, 외화예수금 환산, 단기매매증권 처분손익, 배당 현지세 분개, 위하고 증권 업로드 에 쓴다."
---
# 증권거래전표
증권사 거래내역 파일 → 표준거래표 → 원장 계산 → 전표 · 위하고 업로드.
양식은 증권사마다 달라도 한 거래에서 뽑을 것은 같다. 날짜, 무슨 거래인지, 종목, 수량, 금액, 비용, 통화, 잔액이다. 행마다 무슨 거래인지 보고 읽는다. 금액이 예상과 다른 칸에 들어 있거나(현지세를 비용 칸에), 시장을 「미국」 으로 적었거나, 대금이 그날 합계 한 행으로 오더라도 실제 거래대로 전표가 나와야 한다. 읽은 결과는 증권사 잔액(원화 · 외화 · 보유수량)과 줄마다 맞춰 보고, 안 맞으면 읽은 값부터 다시 본다(2026-11-08).
| 맡는 쪽 | 일 |
|---|---|
| 엔진(`scripts/`) | 파일 읽기, 머리글 맞추기, 이벤트 분류, 이동평균 원가, 외화 장부금액, 분개, 증권사 잔액 대사, 위하고 업로드 파일과 검증 파일 쓰기 |
| AI(이 세션) | 스캔 PDF 를 쪽 이미지로 읽어 표준거래표로 옮겨 적기, 새 머리글·적요를 사전에 넣기, 확인사항 정리 |
| 회계사 | 계정코드, 기초 장부금액, 기말 단가, 검토대기(타사 대체 입출고 · 돈이 오가는 기업행위), 기말 미수배당 · 결제일 자료의 연말 미결제 매매, 세무조정 |
대상은 법인이다. 개인(양도소득세)은 다루지 않는다. 세무조정 · 채권 · 펀드 · 해외직접투자는 다루지 않는다. 이 스킬은 국내 · 미국 주식, 예수금, 배당, 기말 평가를 맡는다.
## 설치와 시험해 보기
- 설치 스크립트로 받으면 `requirements.txt`(openpyxl · xlrd · pdfplumber)까지 깔린다. 스캔 PDF · 화면 캡처를 읽으려면 스킬 폴더에서 `pip install -r requirements-ocr.txt` 를 한 번 더 실행한다(수백 MB, 엑셀 · 글자 있는 PDF 만 쓰면 필요 없다).
+ 설치 스크립트로 받으면 `requirements.txt`(openpyxl · xlrd · pdfplumber · pikepdf)까지 깔린다. pikepdf 는 암호 걸린 PDF(미래에셋 거래내역증명서 · 키움 PDF)를 연다. 스캔 PDF · 화면 캡처를 읽으려면 스킬 폴더에서 `pip install -r requirements-ocr.txt` 를 한 번 더 실행한다(수백 MB, 엑셀 · 글자 있는 PDF 만 쓰면 필요 없다).
1. 설치 확인: `python scripts/check_env.py`. 파이썬 패키지, Node.js(kordoc), OCR 패키지가 있는지 표로 나온다. 엑셀이나 LibreOffice 는 필요 없다. 거래 자료는 읽지 않는다.
2. 시험해 보기: 회사 증권계좌 거래내역 한 달치(엑셀이나 PDF)로 시작한다. Claude 에게 이렇게 요청한다.
> 「`<파일 경로>` 증권거래전표로 만들어줘. 회사는 ○○, 기간은 2026년 1월, 기초 잔고는 없는 것으로.」
기초 잔고를 비우면 거래내역에서 역산하고 「기초 추정」 으로 표시한다. 검증 파일 `요약` 시트의 검산 표가 모두 OK 인지, `[대사]` 가 0 인지 본다. 잔액이 안 맞으면 `_작업/표준거래표.csv` 에서 증권사 행을 어떻게 읽었는지부터 보고, 실행보고의 「못 맞춘 머리글」 · `[미분류]` 를 본다.
이 스킬에는 예시 파일과 시험 자료가 들어 있지 않다.
## 1. 받을 자료
| 자료 | 필수 | 비고 |
|---|---|---|
| 증권사 거래내역(기간 전체, 원화·외화 함께) | 필수 | 엑셀·CSV·xls(HTML 포함)·PDF. 한 줄 보기 · 외화 포함으로 받는다(KB 간편내역은 외화가 빠진다) |
| 전기말 잔고: 원화예수금, 외화예수금(외화·장부금액), 종목별 수량·장부금액 | 필수 | 전기 계정명세서 또는 이 스킬의 전기 검증 파일 `기초·기말` 시트(종목은 평가액, 외화는 환산액이 다음 기 기초 장부금액) |
| 기말 잔고증명서(종목별 단가) | 기말 평가 때 | 단가는 잔고증명서 값을 쓴다 |
| 회사 계정과목표 | 첫 회 | 기본값은 더존 3자리 초안(`engine.DEFAULT_ACCOUNTS`) |
증권사별 머리글 · 적요는 `references/머리글사전.json` · `references/적요사전.json` 에 있다. 받을 때 안내할 것: 키움은 영웅문 [0365]/[3110] 또는 홈페이지 CSV, 한국투자는 결제일 다음 날 이후에 받는다(그 전 원화 금액은 예상환율), 대신증권 HTS 의 .xls 는 내용이 `.files` 폴더에 따로 있어 그 폴더와 함께 받는다.
## 2. 실행 순서
```bash
# 1) 환율표: 첫 거래 직전부터 기말까지 ECOS 일별 매매기준율(키는 ECOS_API_KEY, 없으면 공개 sample 키로 나눠 받음)
python scripts/fetch_rates.py --start 2026-01-01 --end 2026-12-31 --ccy USD -o 환율표.csv
# 2) 설정 JSON(회사·분류·기초·기말·계정). 기초를 비워 두면 거래내역에서 역산하고 확인사항에 적는다
# 3) 실행
python scripts/run.py <거래내역 파일...> --out <산출폴더> --config 설정.json --rates 환율표.csv
# 암호 걸린 PDF(키움: 사업자번호, 미래에셋 거래내역증명서 등)는 비밀번호를 넘긴다. 파일·보고서에 남지 않는다
python scripts/run.py 거래내역증명서.pdf --password <비밀번호> --out <산출폴더> --config 설정.json --rates 환율표.csv
```
설정 예:
```json
{"회사": "가상상사", "증권사": "삼성증권", "분류": "단기매매",
"기초": {"원화예수금": 13, "외화": {"USD": {"잔액": 352.55, "장부금액": 505874}},
"종목": [{"종목": "가상 미국 ETF", "통화": "USD", "수량": 100, "장부금액": 70000000}]},
"기말": {"일자": "2026-12-31", "환율": {"USD": 1480.0}, "단가": {"가상 미국 ETF": 520.5}, "단가출처": "잔고증명서 2026-12-31"},
"계정": {"원화예수금": ["103", "보통예금"], "해외원천세": ["136", "선납세금"]},
"거래처코드": {"삼성증권": "00101"},
"계좌주체": "법인",
"머리글": {"정산후금액": "정산금액"},
"적요규칙": [{"pattern": "해외주식매수결제", "event": "매수", "통화": "외화"}]}
```
`머리글` · `적요규칙` 은 사전에 없는 양식을 코드 수정 없이 읽게 한다(사전보다 먼저 맞춘다). 표준열 이름은 `references/머리글사전.json` 의 `fields` 키, 이벤트 이름은 `references/적요사전.json` 의 `event` 값이다.
종료코드 0 은 검산 통과, 2 는 확인필요 남음, 3 은 중단 사유(환율 없음 · 보유보다 많은 매도 · 외화 잔액보다 많은 출금 · 전표 차대 불일치 · 업로드 반려)다. 중단 사유가 있으면 위하고 업로드 파일을 만들지 않고, 같은 폴더에 앞선 실행이 남긴 업로드 파일도 지운다. 검증 파일은 늘 나온다.
### PDF · 스캔 · 화면 캡처(OCR)
`run.py` 에 PDF 나 이미지(png·jpg·tif·webp·gif)를 그대로 넣는다. PDF 는 읽는 방법 후보를 차례로 전표까지 돌려 보고, 중단 → 대사·미분류 → 종목명 빈 매매 순으로 가장 적은 결과를 쓴다(셋 다 0건이면 거기서 멈춘다). 실행보고 첫머리에 「PDF 읽기: ○○ 선택 (시도: …)」으로 후보별 결과가 남는다.
1. 글자가 들어 있는 PDF: kordoc → pdfplumber. 미래에셋 거래내역증명서 실물 127쪽에서 둘 다 전표 대사 0이었지만, kordoc 은 3줄 1건 표에서 종목명을 31건 빠뜨려 pdfplumber 가 뽑혔다. odl-pdf(2.5.10)는 숫자 칸을 27% 놓쳐 후보에서 뺐다.
2. 스캔 PDF·이미지: `scripts/ocr_table.py`(자체 OCR) → kordoc `--ocr`. 같은 실물을 이미지로만 만든 스캔본 127쪽에서 자체 OCR 은 전표 대사 0(위하고 1,155줄이 글자층 결과와 일자·계정·금액까지 같다), kordoc OCR 은 거래 수부터 틀리고(469건) 대사 410건이었다.
- OCR 로 읽은 표는 금액을 두 번 바로잡는다(`normalize.repair_in_row` · `repair_by_balance`). 외화 금액·단가는 같은 행의 수량 × 단가, 금액 ± 비용 = 입출금액으로, 원화 금액은 증권사 잔액 변동으로 맞춘다. 10·100·1000 배 어긋난 값만 고치고, 고친 거래에는 「OCR 행 교정」·「OCR 잔액 교정」 메모가 붙는다. 127쪽 실물에서 틀린 칸 58개(1,000,000 → 1,00,000, 외화 소수점을 쉼표로 읽은 것)가 이것으로 다 잡혔다.
- OCR 종목명 교정은 종목코드가 다르거나 이름 속 숫자가 다르면 합치지 않는다(같은 운용사의 레버리지 3X ETF 와 2X ETF).
- 127쪽 자체 OCR 은 57분, kordoc OCR 은 41분 걸린다. 큰 스캔본은 백그라운드로 돌린다.
- 엔진은 RapidOCR(PaddleOCR PP-OCRv5 한국어, CPU)이 기본이다. 없으면 `pip install rapidocr` 로 설치한다. Tesseract(kor) 는 RapidOCR 이 없을 때 쓴다.
- 숫자 칸은 두 엔진이 함께 읽는다. RapidOCR 값을 기본으로 두고, 그 값이 같은 열의 숫자 꼴·소수 자릿수에 안 맞을 때만 Tesseract 값으로 바꾼다(두 값의 숫자 배열이 70% 이상 같을 때). 날짜와 글 열은 바꾸지 않는다.
- 전처리: 잡음 제거, 폭 2,400px 까지 확대(최대 4배), 기울기 보정, 밝기 얼룩 보정.
- 칸선이 다 있는 표는 칸을 잘라 칸 안 글자 줄마다 읽는다. 세로선은 행마다 따로 찾는다(셀 병합이 많은 양식은 표 전체를 잇는 세로선이 몇 개뿐이다). 바깥 테두리가 안 잡히면 가로선 양 끝으로 보충하고, 세로선 검출 길이는 줄 높이의 70% 로 잡아 한 줄 높이 칸막이도 지운다. HTS 화면처럼 가로선이 없는 표는 글자 상자를 찾아 줄·열로 묶는다.
- 숫자 열 보정(쉼표·마침표, o→0), 날짜에 붙은 거래번호 떼기, 기호 줄 버리기, 머리글·적요·종목명 오타 교정(자모 유사도)을 한다. 바꾼 것은 확인사항에 남긴다.
- 글자 높이가 6px 미만이거나, PDF 안 이미지의 실제 해상도가 150ppi 미만이면 품질 경고를 낸다. 다시 스캔(300dpi 이상)하거나 증권사에서 원본을 받는다. 89ppi 이미지로 된 한국투자 계산내역 견본은 두 엔진 모두 숫자를 거의 못 읽었다.
3. 그래도 머리글을 못 찾거나 잔액 열이 없는 표는 AI 가 쪽 이미지를 읽어 옮겨 적는다.
- `python scripts/pdf_pages.py <PDF> <폴더>` 로 300dpi 쪽 이미지를 만든다(쪽마다 위·아래 반씩).
- 이미지를 차례로 읽어 `templates/표준거래표_양식.csv` 꼴로 옮겨 적는다. 증권사 잔액 칸(현금잔액·외화예수금·잔고수량)을 꼭 함께 적는다.
- `python scripts/run.py 표준거래표.csv --standard --out ... --config ... --rates ...`
OCR 로 읽은 자료는 잔액 대사로 최종 판정한다. 엔진이 줄마다 잔액을 다시 계산하므로 잘못 읽은 숫자는 `[대사]` 차이로 잡힌다. `[대사]` 가 0 이어도 실행보고의 의심 칸은 원본과 한 번 대조한다. 잔액 열이 없는 화면(매매일지 등)은 대사로 오판독을 못 잡으니 OCR 결과로 전표를 만들지 않는다.
측정치(2026-11-07, 숫자 정확도): 미래에셋 거래내역증명서 실물(127쪽, 거래 450건) 글자층 pdfplumber · kordoc 전표 대사 0. 같은 실물 스캔본 127쪽 자체 OCR 전표 대사 0(교정 전 잔액 불일치 291건). 한국투자 홈페이지 캡처 100%, 한국투자 HTS 견본 96.4%, 미래에셋 HTS 견본 82.1~92.9%, 가상 스캔 300dpi·기울기 100%, 200dpi 팩스 100%. 증권사가 낸 실제 PDF(결합 판독): IBKR Trades 100%, Schwab 거래 상세 86.8%(틀린 5건은 수량 괄호 부호라 전표 금액에 영향 없음), IBKR 체결확인서 66.7%(96ppi 경고), 한국투자 계산내역 4.7%(89ppi 경고). 영문 명세서(IBKR·Schwab)는 숫자는 읽지만 머리글·적요 사전이 없어 전표 단계에서 멈춘다.
표준거래표 열: 일자 · 결제일 · 원문거래종류 · 이벤트(비우면 적요사전으로 분류) · 시장 · 종목코드 · 종목명 · 통화 · 수량 · 단가 · 외화총액 · 외화비용 · 원화금액 · 원화비용 · 증권사원화잔액 · 증권사외화잔액 · 증권사잔고수량 · 상대방. 금액은 모두 양수로 적고 방향은 이벤트가 정한다. 외화총액은 체결금액(배당은 세전), 외화비용은 수수료·SEC fee·현지세다.
## 3. 산출물
산출 폴더에는 두 파일만 둔다. 둘 다 엔진(`engine.py`) 값을 그대로 쓰고 수식이 없다. 그래서 엑셀이 없어도 나오고, 엑셀 판(2016 · 365)이나 미리보기에 따라 값이 달라지지 않는다.
| 파일 | 내용 |
|---|---|
| `위하고_일반전표_<회사>.xlsx` | 올릴 파일. 월·일·구분(3 차변, 4 대변)·계정과목코드·계정과목명·거래처코드·거래처명·적요·차변·대변. 0원 줄은 뺀다. 중단 사유가 있으면 만들지 않는다 |
| `증권전표_검증_<회사>.xlsx` | 회계사가 보는 파일. 시트 넷: `요약`(결론, 검산, 위하고 올리기 전 검사, 손익 합계, 자료 진단, 확인사항과 회계사 결론 칸) · `전표`(업로드 파일과 같은 줄에 거래번호) · `거래원장`(거래마다 금액 · 환율 · 원가 · 손익 · 잔액, 증권사 잔액과 다른 줄은 대사 열이 빨갛다) · `기초·기말`(기초 잔고, 기말 평가, 외화 환산) |
`_작업` 폴더에는 실행보고.md(이 세션이 읽고 보고하는 글), 표준거래표.csv(증권사 행을 어떻게 읽었는지, 원본 파일 · 행번호 포함), PDF 추출 마크다운이 남는다. 넘기는 산출물이 아니다.
기초 장부금액 · 기말 단가 · 계정코드를 바꾸려면 설정 JSON 을 고치고 다시 돌린다. 몇 초 걸린다.
위하고에 올릴 때는 변환옵션 기본값(계정코드 기준·거래처 기준)을 그대로 두고, 다시 올릴 때는 자동분개 일괄검색 및 삭제로 먼저 지운다. 결산 평가 줄은 적요 앞에 `[결산]` 을 붙여 기말일로 낸다. 외화 금액은 업로드 파일에 열이 없어 검증 파일 `거래원장` 시트에만 남는다.
`scripts/wehago_upload.py` 가 업로드 파일을 쓰면서 위하고 올리기 전 검사도 한다. 결과는 검증 파일 `요약` 시트 「위하고 올리기 전 검사」 와 `_작업/실행보고.md` 에 있고, 반려가 하나라도 있으면 종료코드 3 이다.
| 검사 | 반려 · 확인 | 근거 |
|---|---|---|
| 필수 열(월 · 일 · 구분 · 계정과목코드 · 계정과목명) 빈칸, 구분이 3 · 4 가 아님, 구분과 금액 열 어긋남, 음수 | 반려 | 더존 「일반전표입력 엑셀업로드방법_SmartA 10」(2024-12-06) |
| 계정코드 · 월 · 일 · 금액이 숫자형이 아님 | 반려 | 결산 스킬 실측(텍스트면 반려) |
| 적요 71자 이상 | 반려 | 결산 · 급여 스킬 실측. 공식 상한은 못 찾았다. 기본 40자(설정 `적요길이`)로 자르고 끝의 `#거래번호` 는 남긴다 |
| 적요 41~70자, CP949 로 못 쓰는 글자(이모지 등) · 줄바꿈 | 확인 | 쓸 때 줄바꿈은 띄어쓰기로, 못 쓰는 글자는 ? 로 바꾼다 |
| 날짜 안에서 차대가 0 이 안 되는 전표 | 반려 | 같은 날짜에 이어진 줄이 한 전표이고, 차변 합 = 대변 합 |
| 거래처코드가 숫자 3~10자리가 아님 | 반려 | 회사 환경설정 자릿수. 앞자리 0 때문에 텍스트로 쓴다 |
| 거래처명은 있고 거래처코드가 빈 줄 | 확인 | 비워도 오류는 없고 거래처명만 반영된다. 설정 `거래처코드` 에 증권사 코드를 넣으면 채워진다 |
| 위하고 기본 계정표(`references/위하고_계정과목.csv`, 423개)에 없는 코드, 기본 이름과 다른 이름 | 확인 | 998 법인세등은 표에 없다(961 이후는 시트에 안 실림). 104 는 기본 이름이 기타제예금이고 법인 장부는 외화예금으로 바꿔 쓴다. 회사 [계정과목및적요등록] 화면을 따른다 |
회계연도가 둘에 걸치면 파일을 연도마다 나눈다(양식에 연도 열이 없다. 설정 `회계연도시작월`, 기본 1).
2026-11-08 WEHAGO T 커널스페이스(2기)에 가상 거래 3건 · 8줄을 실제로 올려 확인했다. 일반전표입력 > 기능 > 엑셀올리기, 변환옵션 기본값(계정코드 · 거래처 기준)으로 8줄이 그대로 들어갔고(차대 15,110 = 15,110, 같은 날 줄이 한 전표로 묶임), 확인 뒤 같은 화면에서 8줄을 골라 삭제했다. 처음 올린 파일은 계정과목명 · 거래처 · 적요 한글이 깨졌다. openpyxl 이 글자를 숫자 문자참조(`월`)로 쓴 inlineStr 칸이었는데 위하고가 이것을 풀지 못했다. 지금은 쓴 직후 엑셀 저장 꼴(sharedStrings, UTF-8 글자 그대로)로 바꾼다(`wehago_upload.to_shared_strings`). 이렇게 만든 파일이 미리보기에서 한글 그대로 읽히는 것까지 확인했다. 거래처코드 없는 거래처명은 거래처명만 들어갔다.
## 4. 처리 기준
분개표와 판단 항목은 [references/분개규칙.md](references/분개규칙.md). 요점:
- 원가는 종목별 이동평균, 외화예수금은 통화별 이동평균 장부금액. 해외 매수·매도 원화 금액은 거래일 매매기준율(환율표), 환전은 실제 환율.
- 처분손익 = 비용을 뺀 처분대가 − 이동평균 원가. 매수 수수료는 지급수수료(비용)로 처리한다.
- 분류는 단기매매증권(일반기업회계기준) = 당기손익-공정가치측정 금융자산(K-IFRS 1109)만 처리한다. 두 기준은 회계처리가 같고 계정 이름만 달라서, IFRS 회사는 설정 `계정` 에서 이름을 바꾼다. 매도가능증권 · 기타포괄손익-공정가치측정 지분은 엔진에 처분 시 평가손익 누계를 처리하는 규칙이 없어 실행을 멈춘다(2026-11-08). 필요하면 업데이트를 요청한다.
- 해외 배당은 세전 총액을 배당금수익, 현지세를 법인세등(외국납부세액공제 대상, 법인세법 제57조①)으로 둔다.
- 증권사가 배당 입금과 현지세 출금을 두 행으로 내면 합친다. 사이에 같은 통화를 움직인 행이 끼어 있으면 합치지 않고 현지세를 따로 전표로 낸다(줄마다 잔액 대사가 맞도록).
- 미래에셋 매수입고+매수출금, 환전 원화 행·외화 행 짝, 키움 분할체결(마지막 행에만 정산금액), 키움 환전정산입금은 엔진이 자동으로 합치거나 조정한다.
- 무상증자 · 주식배당 · 액면분할 · 병합 · 감자 · 합병 · 교환처럼 수량만 바뀌는 기업행위는 전표 없이 수량만 바꾸고 장부금액은 그대로 둔다. 종목코드가 바뀌면 같은 날 출고 행의 장부금액을 입고 행으로 옮긴다. 합병은 공정가치로 다시 잡으라는 확인사항이 붙는다.
- 유상청약 · 단주대금처럼 돈이 오가는 기업행위와 규칙에 없는 입출금은 가수금 · 가지급금으로 기표하고 확인사항에 올린다. 타사 대체 입출고는 전표를 내지 않고 검토대기로 둔다.
- 인식일은 체결일이다(일반기업회계기준 6.4의2, 법인세법 시행령 제68조①5호). 파일에 체결일 · 매매일 칸이 있으면 그 칸을 일자로 쓴다.
- 국내 ETF · 투자신탁 분배금과 예탁금이용료(원화 · 외화)의 원천세는 선납세금, 해외 배당 현지세는 법인세등이다. 처리마다 회계기준 문단과 세법 조문을 붙인 검토 결과(2026-11-08)가 분개규칙.md 끝에 있다.
- 기말 미수배당, 결제일 자료의 연말 미결제 매매, 세무조정(평가손익 · 외화환산 · 수입배당금 익금불산입 · 의제배당)은 전표에 넣지 않고 확인사항에 고정으로 올린다.
## 5. 검증
### 자료 진단(검산 전에 보는 것)
실행할 때마다 `scripts/diagnose.py` 가 받은 자료로 무엇을 검증할 수 있고 무엇이 빠졌는지 판정한다. 결과는 실행보고와 검증 파일 `요약` 시트의 「자료 진단」에 나온다. 「위험」 이 있으면 검산이 모두 OK 여도 결과를 그대로 쓰지 않는다(종료코드 2).
| 항목 | 위험 · 확인이 뜨는 경우 |
|---|---|
| 읽은 방법 | OCR 이면 확인. 교정 건수와 원본 대조 안내 |
| 잔액 열(대사 수단) | 원화 · 외화 잔액과 보유수량 열이 하나도 없으면 위험(잘못 읽은 숫자를 잡을 수단이 없다). 잔액이 없는 날이 10% 넘으면 확인 |
| 일자의 뜻 | 체결일 칸이 없으면 확인 |
| 기초 장부금액 | 기초 수량만 있고 장부금액이 0 이면 위험(처분이익이 부풀려진다) |
| 계좌 주체 | 법인 설정인데 상장주식 배당에 원천세가 찍혀 있으면 확인(개인 계좌 자료일 수 있다) |
| 못 읽은 것 | 미분류 · 검토대기, 못 맞춘 머리글 |
| 기간 · 통화 | 외화 거래에 환율표가 없으면 위험, 기말일이 없으면 확인 |
양식 · 읽는 방법에 따라 전표가 틀어지는 경우(OCR 자릿수 누락 · 소수점↔쉼표 · 숫자 닮은 글자, kordoc 종목명 누락, 묶음 대금행 등)와 스킬이 잡는 방법은 [references/자료차이.md](references/자료차이.md) 에 있다.
### 검산
검증 파일 `요약` 시트의 검산 표가 아래를 판정한다. 모두 OK 여야 넘긴다. 1 · 2 가 OK 가 아니면 중단이고 위하고 업로드 파일을 만들지 않는다.
1. 전표 차변 − 대변 = 0, 거래별 차대 일치
2. 중단 사유 0, 환율 없는 외화 거래 0
3. 원화예수금 잔액 = 증권사 현금잔액(줄마다)
4. 외화예수금 잔액 = 증권사 외화예수금(줄마다)
5. 보유수량 = 증권사 잔고수량(매매 줄마다)
6. 검토대기 0, 가계정 0, 장부금액 없는 기초 보유 종목 0, 기말 단가 미입력 0, 기말일이 없어 빠진 결산 전표 0
이어서 위하고 올리기 전 검사(위 표)가 같은 시트에 나온다.
계산 엔진은 공개 전에 독립된 정답과 맞춰 봤다(2026-11-08). 엔진 코드를 열지 않은 에이전트가 `references/분개규칙.md` 만 보고 정답 계산기와 사례 16개(분할매도 · 같은 날 매수 · 매도 · 기초 보유분 매도 · 여러 환율 환전 뒤 매수 · 환율 급변 · 배당 현지세 환급 · 소수점 수량 · 기초 외화 · 평가 혼합 · 환산 · x.5원 반올림 등)를 만들었다. 결과는 계정 순액 16/16, 거래별 전표 줄 95묶음이 모두 같다. 이 대조는 엔진이 분개규칙.md 를 문서와 같게 해석하는지만 본다.
PASS 는 계산과 대사만 본다. 원천 자료가 맞는지, 계정 분류·기초 장부금액·기말 단가가 맞는지는 보지 않는다. 보고할 때 이 문장을 함께 적는다.
같은 가상 거래를 삼성 · 키움 · 미래에셋 · KB · 표준거래표 다섯 꼴로 넣어 계정별 순액이 같은지, 엔진 없이 손으로 푼 답과 같은지도 시험했다. 시험 코드와 시험 자료는 이 배포에 싣지 않는다.
## 6. 새 증권사 양식이 들어오면
1. 그대로 돌리고 실행보고 「자료 진단」 을 먼저 본다.
2. 「못 맞춘 머리글」 가운데 금액 · 잔액 · 날짜 열은 설정 `머리글` 에, `[미분류]` 적요는 설정 `적요규칙` 에 더하고 다시 돌린다. 코드와 사전 파일은 고치지 않아도 된다.
3. 같은 양식을 세 번째 받으면 설정에 둔 별칭 · 규칙을 `references/머리글사전.json` · `references/적요사전.json` 으로 옮기고 `_출처` 에 증권사를 적는다. 머리글은 괄호를 지우고 비교한다(`거래금액(외)` → `거래금액외`). 적요 규칙은 위에서부터 처음 맞는 것을 쓴다.
4. 표로 못 읽는 양식(그림, 칸이 표 꼴이 아닌 배치)은 AI 가 쪽 이미지를 읽어 `templates/표준거래표_양식.csv` 로 옮겨 적고 `--standard` 로 돌린다. 증권사 잔액 열도 함께 옮겨 적어야 대사로 검증된다.
5. 2행 1건(키움·KB·NH·신한) 꼴은 머리글 줄 수와 날짜 빈칸 비율로 자동 판정한다. 판정이 틀리면 보고의 `multiline/combined` 표시를 보고 고친다.
## 7. 예외 기록
| 날짜 | 내용 | 처리 |
|---|---|---|
| 2026-11-07 | 삼성 종합거래내역: 최신순, 해외 배당은 배당금입금(세전) + 세금출금(해외) 두 행, 같은 날 사이에 환전이 끼기도 함, 세금출금 행 거래단가 = 그날 매매기준율 | 행을 날짜순으로 뒤집기, 두 행이 붙어 있을 때만 합치기 |
| 2026-11-07 | 원화 예탁금이용료 4,315원에 원천세 0 | 정상. 14% 세액 604원은 1천원 미만이라 징수하지 않는다(법인세법 제73조①) |
| 2026-11-07 | 신규 함수 MAXIFS 는 파일에 `_xlfn.MAXIFS` 로 써야 엑셀이 계산한다 | build_workbook 이 `_xlfn.` 접두어를 붙인다(11-08 철회, 아래 줄) |
| 2026-11-08 | 엑셀 2016(16.0)에는 MAXIFS 가 없다. `#NAME?` 이 SUMIFS 조건에 들어가 오류 표시 없이 적용환율이 0 이 됐다. 해외 매수 · 매도 · 배당 전표가 틀린 채 위하고 업로드 파일이 나왔다(검산은 엔진 대조 차이 15 · 환율 없음 3 으로 확인필요) | 적용환율을 `SUMPRODUCT(MAX(...))` 로 찾게 고쳤다가 같은 날 수식 워크북을 없앴다(아래 줄) |
| 2026-11-08 | 계산을 파이썬 엔진과 엑셀 수식으로 두 번 하고, 업로드 값은 사용자 엑셀이 재계산한 수식 값에서 읽었다. 엑셀 판에 따라 업로드 값이 틀릴 수 있었고 엑셀 · LibreOffice 가 없으면 업로드 파일이 안 나왔다. 워크북은 11개 시트, 거래원장은 46열이었다 | 업로드 · 검증 파일 모두 엔진 값으로 쓴다(수식 없음). 산출은 두 파일, 검증 파일은 요약 · 전표 · 거래원장 · 기초·기말 넷. 중단 사유가 있으면 업로드 파일을 만들지 않고 앞선 실행의 업로드 파일도 지운다. 같은 가상 거래의 업로드 36줄이 옛 구조(엑셀 재계산, 손으로 검증)와 같고, 엔진과 따로 계산한 정답 사례 16개도 계정 순액이 같다 |
| 2026-11-07 | kordoc 은 가로 21열 PDF 표에서 이웃한 열을 한 칸으로 합쳐 읽고, 내장 OCR 은 7pt 표의 숫자를 거의 못 읽는다 | pdfplumber 먼저, 스캔본은 ocr_table(RapidOCR) |
| 2026-11-07 | RapidOCR 한국어 인식 모델은 PP-OCRv5 mobile 만 있다 | server 를 고르면 설정 오류. mobile 고정 |
| 2026-11-07 | HTS 화면은 세로선만 있고 옅다. 머리글은 가운데, 숫자는 오른쪽 정렬 | 글자 상자 방식으로 읽고, 열은 빈 세로 띠로 나눈다 |
| 2026-11-07 | 원화 열의 5,200 을 5.200 으로 읽어 5.2원이 됨 | 소수 둘째 자리 값이 없는 열은 마침표를 쉼표로 바꾼다 |
| 2026-11-07 | 삼성 해외주식 행의 거래일자가 체결일인지 결제일인지 미확인 | 체결일 칸이 있으면 그 칸을 쓰고, 없으면 확인사항에 올린다(일반기업회계기준은 체결일만 허용) |
| 2026-11-07 | 미래에셋 거래내역증명서: 3줄 머리글·3줄 1건, 사전 단어가 많은 둘째 줄이 먼저 잡힘 | 머리글을 위아래로 넓히고, 한 거래 줄 수는 날짜 줄 간격의 최빈값으로 |
| 2026-11-07 | 미래에셋: 같은 날·같은 방향 매매의 대금이 합계 한 행(주식매도입금 = 그날 매도 합계) | 수량행마다 자기 금액으로 거래를 만들고 합계로 대조, 대금행 자리로 옮겨 잔액을 붙인다 |
| 2026-11-07 | 미래에셋: 외화 거래도 수수료·제세금을 USD 로 같은 칸에 적음, 해외 대금행 종목명은 「미국달러」 | 원화 금액·잔액이 빈 외화 행이면 외화 비용으로, 통화 이름 종목명은 빈 이름으로 |
| 2026-11-07 | 미래에셋: 원화주문 자동환전 「외화매수원화출금(미수)」이 해외 매수 뒤에 찍혀 외화 잔액이 음수가 됨 | 같은 날 첫 해외 매수 앞으로 옮기고 증권사 외화 잔액은 원래 자리 앞 거래에 붙인다 |
| 2026-11-07 | 미래에셋: 대여회수입고(기간 전에 빌려준 주식), 대차수수료입금 | 대여는 전표 없이 대여 중 수량만 센다. 보유 − 대여 중 = 증권사 잔고로 대사, 기간 전 대여분은 기초 보유에. 대여 수수료는 잡이익 |
| 2026-11-07 | 미래에셋: 외화예수금이 소수 셋째 자리(12.345 꼴), 출금액은 센트로 끊김 | 외화 잔액은 셋째 자리로 계산, 끝수는 묶음 마지막 거래 수수료에 |
| 2026-11-07 | 미래에셋: 금액·수량 없는 「세금환급」 안내 행, 해외주식현지과세환급금 | 안내 행은 전표 없이 정보로, 환급금은 현지세 환급 |
| 2026-11-07 | pdftotext 는 이 PDF 의 한글을 못 꺼냄(폰트 대응표), pdfplumber·kordoc 은 정상 | pdftotext 는 쓰지 않는다 |
| 2026-11-08 | 미래에셋 스캔본 OCR: 1,000,000 → 1,00,000, 외화 1,234.567 → 1,234,567. 10쪽에선 안 나오고 127쪽에서 나옴, 잔액이 누적되므로 틀린 칸 58개가 잔액 불일치 291건으로 나타남 | 원화는 잔액 변동으로, 외화는 같은 행 수량 × 단가 · 입출금액으로 10 의 거듭제곱 배만 고친다 |
| 2026-11-08 | OCR 종목명 교정이 레버리지 3X ETF 를 같은 운용사 2X ETF 로 합침 | 종목코드 · 이름 속 숫자가 다르면 합치지 않는다 |
| 2026-11-08 | kordoc 글자층이 3줄 1건 표에서 종목명을 빠뜨리고 환율 · 단가를 종목명 앞에 붙임 | 후보 점수에 종목명이 빈 매매 수를 넣음, 종목명 앞 숫자는 지움 |
| 2026-11-08 | kordoc OCR 이 128쪽에서 900초 제한에 걸림 | 제한 시간을 쪽수에 맞춰 늘림 |
| 2026-11-08 | 독립 정답 대조: 표준거래표 시장 칸 「미국」 을 국내로 읽어 해외 매수가 국내 매수로 처리됨 | 외화 거래이거나 국내 시장 이름이 아니면 해외 |
| 2026-11-08 | 독립 정답 대조: 현지세 환급 금액을 외화비용 칸에 적으면 0 으로 읽음 | 금액이 하나뿐인 이벤트(현지세 · 환급)는 채워진 칸에서 읽는다 |
| 2026-11-08 | 위하고 업로드: 계정코드를 텍스트로 썼고, 기본 계정명 넷이 위하고 기본 이름과 달랐음(906 단기투자자산처분익 등) | 계정코드는 숫자형, 이름은 위하고 기본값. 올리기 전 검사(`wehago_upload.py`) |
| 2026-11-08 | 분류가 매도가능이면 처분 시 평가손익 누계를 처리하지 못함 | 단기매매만 받고 나머지는 멈춘다. 필요하면 업데이트 |
| 2026-11-08 | 분개 규칙 원문 검토: 일반기업회계기준은 체결일만 허용(6.4의2), ETF 분배금 · 외화 예탁금이용료도 원천징수 대상, 기말 미수배당 처리 없음 | 체결일 칸 우선, 원천세는 선납세금, 미수배당 · 미결제 매매 · 세무조정은 확인사항 고정 |
| 2026-11-08 | 기업행위가 전부 검토대기라 분할 · 무상증자 뒤 보유수량 대사가 깨짐 | 수량만 바뀌는 기업행위는 수량 반영, 코드가 바뀌면 장부금액 이전 |
| 2026-11-08 | 미래에셋 실물을 기초 장부금액 없이 돌리니 처분이익 31.6백만 원이 부풀려졌는데 검산은 모두 OK | 자료 진단(diagnose.py)과 검산 「장부금액 없는 기초 보유 종목 수」 |
| 2026-11-08 | OCR 이 환율 1,480 을 1,48C 로 읽음 | 숫자 열 안 숫자 닮은 글자를 숫자로(_unconfuse) |
| 2026-11-08 | 새 양식마다 사전 파일을 고쳐야 했음 | 설정 `머리글` · `적요규칙` 으로 더한다 |
| 2026-11-08 | 위하고 실제 업로드에서 한글(계정과목명 · 거래처 · 적요)이 깨짐. openpyxl 이 숫자 문자참조 inlineStr 로 씀 | 쓴 직후 sharedStrings · UTF-8 로 바꾼다. 엑셀로 다시 저장한 파일과 같은 꼴 |
+ | 2026-11-09 | 공개 0.19.3 설치 목록(`requirements.txt`)에 pikepdf 가 없었다. 새로 설치한 PC 에서 미래에셋 거래내역증명서(암호 걸린 PDF)를 비밀번호 없이 넣으면 pdfplumber 가 원인을 알 수 없는 오류로 멈췄다 | `requirements.txt` · `check_env.py` 에 pikepdf 를 넣었다. 암호 걸린 PDF 를 넣었는데 pikepdf 가 없으면 설치 명령과 `--password` 안내를 내고 멈춘다 |