# HTS 캡처 파싱 프롬프트

HTS 캡처 이미지가 제공되면 이 프롬프트를 **분석보다 먼저** 실행한다.
출력 순서: ① 화면판별 → ② 검증 → ③ 충돌감지·캡처우선 선언 → ④ TSV붙여넣기 → ⑤ account_snapshot 상태갱신 → ⑥ 현금요약 → ⑦ 인라인재산출 → ⑧ 다음단계

## 기본 완료 조건

작업 완료는 다음 4개가 함께 있어야 한다.
- `YAML` 증빙
- `코드` 증빙
- `데이터 실체` 증빙
- `검증 증빙`

하나라도 빠지면 완료로 보지 않는다.

---

## WORKFLOW DISCIPLINE

캡처 파싱 전에 반드시 아래 4가지를 먼저 확정한다.

1. WBS 항목
2. 목표
3. 성공판단 데이터
4. 검증 명령

이 4가지가 없으면 파싱을 시작하지 않는다.

---

## STEP 1 — 화면 종류 판별

| 화면 | 판별 기준 | 사용 가능 여부 |
|------|---------|-------------|
| **보유종목 화면** | 종목명·수량·평단·평가손익이 있음 | ✅ 잔고 원장으로 사용 |
| **현금/예수금 화면** | 예수금·D+2·주문가능금액이 있음 | ✅ 현금 원장으로 사용 |
| **자동투자/적립식 화면** | 월 납입금액·약정일이 있음 | ❌ 잔고 원장 사용 금지 (AS006) |
| **미체결 화면** | 주문종목·미체결수량이 있음 | ✅ open_order_amount 참조용 |

화면 판별 결과를 첫 줄에 명시한다. 예: `[보유종목 화면 확인] 일반계좌`

---

## STEP 2 — 검증 (출력 전 필수)

| 규칙 ID | 확인 내용 | 실패 시 |
|---------|---------|--------|
| AS001 | 숫자 앞의 라벨 확인 (수량: X주, 평단: X원) | parse_status = CAPTURE_READ_FAILED |
| AS002 | holding_quantity 정수 확인 (소수 불가) | CAPTURE_READ_FAILED |
| AS003 | market_value ≈ holding_quantity × current_price (오차 1% 이내) | DATA_CONFLICT 표시 |
| AS004 | 현금 필드 0 이상 | CAPTURE_READ_FAILED |
| AS006 | 자동투자 화면 여부 확인 | CAPTURE_PROVIDED_BUT_NOT_HOLDINGS |

검증 결과를 한 줄로 출력: `[검증] AS001 OK | AS002 OK | AS003 OK (오차 0.3%) | parse_status = CAPTURE_READ_OK`

---

## STEP 2b — 캡처 vs JSON/account_snapshot 충돌 감지 (캡처 우선)

**출력 조건**: `GatherTradingData.json` 또는 account_snapshot 데이터가 이번 대화에 업로드되어 있을 때

기존 시장 데이터(JSON `data.data_feed`의 Account_Holding_Qty·Account_Avg_Cost)와 캡처값을 종목별로 비교한다.

```
[충돌 감지 결과]
ticker | 항목            | JSON/GAS값 | 캡처(실시간) | 차이     | 우선권
000660 | holding_quantity | 80주           | 100주       | +20주    | ★캡처우선
000660 | average_cost     | 175,000원      | 170,000원   | -5,000원 | ★캡처우선
012450 | holding_quantity | 20주           | 20주        | 없음     | 일치
```

**캡처 우선 규칙**:
- 캡처값 ≠ GAS값 → **캡처가 정답**. 이후 모든 분석은 캡처값 기준으로 진행.
- GAS값은 account_snapshot 붙여넣기 전 상태의 오래된 값임.
- JSON에 Account_Parse_Status=MANUAL_ENTRY/STALE_MANUAL/""인 종목도 캡처가 있으면 **캡처우선**.
- 충돌 없으면: `[충돌 없음] 모든 종목 일치`

**주의**: 충돌 종목에 대해 이후 분석에서 GAS의 Profit_Pct·Weight_Pct·Sell_Qty 등은 재산출 대상.
재산출 방법은 STEP 7 참조.

---

## STEP 3 — account_snapshot 탭 붙여넣기 표

**출력 조건**: 보유종목 또는 현금 화면이 CAPTURE_READ_OK일 때

**붙여넣기 방법**: Google Sheets → `account_snapshot` 탭 → **A3 셀 선택** → Ctrl+V

TSV(탭구분) 형식으로 출력한다. 각 행은 account_snapshot 탭의 1개 데이터 행이다.
현금 전용 행은 ticker·name·holding_quantity 이하 종목 컬럼을 빈칸으로 두고 현금 컬럼만 채운다.

```
[account_snapshot 탭 — A3 셀에 붙여넣기]
captured_at	account	account_type	ticker	name	holding_quantity	available_quantity	average_cost	total_cost	current_price	market_value	profit_loss	return_pct	immediate_cash	settlement_cash_d2	available_cash	open_order_amount	monthly_contribution_limit	monthly_contribution_used	parse_status	user_confirmed	stop_price	highest_price_since_entry	entry_date	entry_stage	position_type	last_updated
```

**컬럼 순서 고정 — 27컬럼** (변경 금지):
`captured_at | account | account_type | ticker | name | holding_quantity | available_quantity | average_cost | total_cost | current_price | market_value | profit_loss | return_pct | immediate_cash | settlement_cash_d2 | available_cash | open_order_amount | monthly_contribution_limit | monthly_contribution_used | parse_status | user_confirmed | stop_price | highest_price_since_entry | entry_date | entry_stage | position_type | last_updated`

**작성 규칙**:
- `captured_at`: 첫 번째 컬럼. `YYYY-MM-DD HH:MM` 형식. 화면 시각 기준. 없으면 당일 날짜.
- `ticker`: 6자리 문자열 (예: `000660`). 이름만 보이면 종목코드로 변환. 불확실하면 빈칸.
- `holding_quantity`: 정수만. 소수점 불가.
- `available_quantity`: 매도가능수량 (HTS 화면에 표시되는 경우). 없으면 빈칸.
- `average_cost` / `current_price` / `market_value` / `total_cost`: 원 단위 정수 (콤마 없이).
- `total_cost`: 매입금액 = holding_quantity × average_cost. HTS에서 직접 읽으면 그 값 사용.
- `profit_loss`: 평가손익 (원). HTS 화면 값 직접 사용. 없으면 빈칸.
- `return_pct`: 수익률 %. 예: `7.5` (% 기호 제외). 없으면 빈칸.
- 현금 필드: 보유종목 화면에서 현금이 보이지 않으면 빈칸 (0으로 채우지 않음).
- `parse_status`: 검증 통과 시 `CAPTURE_READ_OK`, 실패 시 `CAPTURE_READ_FAILED`.
- `user_confirmed`: 항상 `Y` (붙여넣기 행위 자체가 사용자 확인임).
- 선택 포지션 상태 6컬럼(`stop_price`~`last_updated`)은 캡처에서 확인되지 않으면 빈칸. 기존 값을 보존해야 하면 STEP 4에서 해당 셀만 수정.

**출력 예시** (27컬럼 — 탭으로 구분):
```
[account_snapshot 탭 — A3 셀에 붙여넣기]
2026-05-18 09:30	일반계좌	일반계좌	000660	SK하이닉스	100	100	170000	17000000	181900	18190000	1190000	7.0	3500000	4200000	3500000	0			CAPTURE_READ_OK	Y						
2026-05-18 09:30	일반계좌	일반계좌	012450	한화에어로스페이스	20	20	980000	19600000	1216000	24320000	4720000	24.1					0			CAPTURE_READ_OK	Y						
2026-05-18 09:30	일반계좌	일반계좌		현금				3500000	4200000	3500000	0			CAPTURE_READ_OK	Y						
```

---

## STEP 4 — account_snapshot 선택 포지션 상태 갱신 표

**출력 조건**: stop_price, highest_price_since_entry, entry_stage, position_type, last_updated 갱신이 필요한 경우

**붙여넣기 방법**: 아래 표를 참고해 `account_snapshot` 탭에서 ticker 행을 찾아 해당 선택 열만 수정.
보유수량·평단은 STEP 3의 account_snapshot TSV가 담당한다. `positions` 탭은 사용하지 않는다.

```
[account_snapshot 탭 — 해당 ticker 행의 아래 선택 열을 수동 수정]
ticker	stop_price	highest_price_since_entry	entry_stage	position_type	last_updated
```

**작성 규칙**:
- `stop_price`가 비어 있으면 GAS가 ATR 기반으로 추정한다. 수동 입력을 강제하지 않는다.
- `last_updated` = 오늘 날짜 `YYYY-MM-DD`.
- `position_type`은 `core` 또는 `satellite`. 비어 있으면 GAS가 `satellite`로 간주한다.

---

## STEP 5 — 현금 요약 (1줄)

```
[현금 요약] 즉시현금: X원 | D+2현금: X원 | 주문가능: X원 | 미체결: X원
→ settings 탭 settlement_cash_d2_krw에 X원 입력 필요
```

D+2현금을 settings 탭에 수동 입력해야 GAS가 매수 가능 금액 계산에 사용한다.

---

## STEP 6 — 다음 단계 안내 (항상 출력)

```
[다음 단계]
1. account_snapshot 탭 A3에 위 표 붙여넣기
2. 필요한 경우 account_snapshot 탭에서 ticker별 stop_price·highest_price_since_entry·last_updated 선택 열만 수정
3. settings 탭 settlement_cash_d2_krw = [D+2현금 값] 입력
4. GAS runDataFeed() 재실행 → xlsx 원본 갱신 확인
5. `npm run convert-data-json` 실행 후 갱신된 `GatherTradingData.json` 업로드 후 분석 요청
```

---

## STEP 7 — 충돌 종목 인라인 재산출 (캡처 우선 적용)

**출력 조건**: STEP 2b에서 충돌 종목이 1개 이상 발견된 경우

GAS 재실행 전이라도 캡처값으로 핵심 지표를 직접 재산출해서 분석에 사용한다.
JSON/GAS의 해당 종목 계좌 값은 **무시**하고 아래 재산출값으로 교체한다.

### 재산출 항목

| 항목 | 재산출 공식 | 필요 입력 |
|------|-----------|---------|
| `Profit_Pct` | `(현재가 - 캡처평단) / 캡처평단 × 100` | 캡처평단, JSON Close |
| `Unrealized_PnL` | `(현재가 - 캡처평단) × 캡처수량` | 캡처수량·평단, JSON Close |
| `Weight_Pct` | `(현재가 × 캡처수량) / 총자산 × 100` | 캡처수량, JSON Close, 총자산 |
| `Sell_Qty` | `캡처수량 × Sell_Ratio_Pct / 100` (반올림) | 캡처수량, GAS Sell_Ratio_Pct |
| `매도가능수량` | `캡처 available_quantity` 있으면 상한 적용 | 캡처 available_quantity |

### 출력 형식

```
[캡처 우선 재산출] — GAS 재실행 전 임시값
ticker | 항목          | GAS값(무효) | 캡처재산출값 | 비고
000660 | Profit_Pct    | +4.2%      | +6.9%       | 평단 변경(175000→170000)
000660 | Unrealized_PnL| 3,360,000원 | 1,190,000원 | 수량 변경(80→100)
000660 | Weight_Pct    | 7.8%       | 9.7%        | 수량 변경
000660 | Sell_Qty      | (미산출)    | 25주        | TRIM_25(25%) × 100주
```

**재산출 불가 항목** (GAS 의존): SS001_Grade, RW_Partial, Flow_Credit, Final_Action 등 시장데이터 기반 점수.
이 항목들은 JSON 시장데이터 값을 그대로 사용하되, 수량·손익 계산만 캡처값으로 교체한다.

---

## 오류 처리

| 상황 | 출력 |
|------|------|
| 이미지 흐림·잘림으로 숫자 판독 불가 | 해당 필드 빈칸 + `parse_status=CAPTURE_READ_FAILED` |
| 종목코드 불확실 | ticker 빈칸 + name만 기재 + 경고 메모 |
| AS003 오차 > 1% | DATA_CONFLICT 표시 후 계속 기재 (사용자 확인 후 사용) |
| 자동투자 화면 | `parse_status=CAPTURE_PROVIDED_BUT_NOT_HOLDINGS` + 보유수량 기재 금지 |
| JSON 미업로드 | STEP 2b 생략, STEP 7 생략. 캡처값 단독으로 진행. |
