# 계산기 수식 검증 — 입력값과 기대 출력

작성: 2026-10-13 · 단계: **1A (계산기 수식 검증)** · 상태: APR/APY 완료, Uniswap V3 완료

AGENTS.md 규칙: *"계산 로직을 바꿀 때는 입력값 예시와 기대 결과를 같이 기록한다."*
이 문서가 그 기록이다. 아래 표의 모든 숫자는 실제로 실행해서 확인한 값이다(추정 아님).

---

## 0. 돌리는 법

```powershell
cd "C:\Users\Simon\Documents\Claude\Pagu.info"; node --test tests\calculators.test.js
```

설치할 것 없다. Node에 들어 있는 테스트 기능만 쓴다 (외부 패키지 0개).
통과하면 마지막에 `pass 24`, `fail 0` 이 뜬다.

수식은 `src/calc-math.js` 한 곳에만 있다. 화면(`src/app.js`)과 테스트가 **같은 파일**을 쓴다.
테스트가 수식을 베껴 쓰면 틀린 수식도 통과하므로, 일부러 그렇게 하지 않았다.

### 기대값을 어디서 가져왔나

"지금 코드가 이렇게 나오니까 맞다"는 기대값은 **하나도 없다.** 세 가지만 썼다.

1. **표준 정의를 손으로 푼 값** — 복리 공식, Uniswap V3 백서 수식
2. **독립 공식과의 교차검증** — Uniswap V2 IL 공식, 자본효율 공식 `1/(1-(Pa/Pb)^0.25)`
3. **보존 법칙** — 토큰 가치 합계 = 예치금, APR→APY→APR 왕복 = 원래 값

---

## 1. APR ↔ APY

### 쓰는 수식

| 복리 방식 | APR → APY | APY → APR |
|---|---|---|
| 이산복리 (n회/년) | `(1 + APR/n)^n − 1` | `n × ((1 + APY)^(1/n) − 1)` |
| 연속복리 | `e^APR − 1` | `ln(1 + APY)` |

**검증 결과: 기존 수식은 맞았다.** 표준 정의와 정확히 같다.
바뀐 것은 ① 연속복리 선택지가 없었던 것, ② 경계값에서 화면에 `NaN%` / `Infinity%` 가
찍히던 것, ③ 아주 작은 값에서의 계산 정확도다. (자세한 내용은 §3)

### 1-1. 기본 변환 (APR → APY)

| # | APR 입력 | 복리 횟수 | 기대 출력 | 왜 이 값인가 |
|---|---:|---|---:|---|
| A-01 | 12% | 365회 (일) | **12.7475%** | `(1+0.12/365)^365 − 1` |
| A-02 | 12% | 52회 (주) | **12.7341%** | 복리 횟수가 줄면 APY도 줄어든다 |
| A-03 | 12% | 12회 (월) | **12.6825%** | 〃 |
| A-04 | 12% | 1회 (연) | **12.0000%** | 복리가 1회면 APY = APR. **정확히** 같아야 한다 |
| A-05 | 12% | 연속 | **12.7497%** | `e^0.12 − 1`. 모든 n의 상한 — A-01보다 커야 한다 |

### 1-2. 기본 변환 (APY → APR)

| # | APY 입력 | 복리 횟수 | 기대 출력 | 왜 이 값인가 |
|---|---:|---|---:|---|
| A-06 | 12.74746% | 365회 | **12.0000%** | A-01의 역방향. 왕복하면 원래 값으로 돌아와야 한다 |
| A-07 | 12.75% | 1회 | **12.7500%** | 복리 1회면 APR = APY |
| A-08 | 12.75% | 12회 | **12.0605%** | 월복리로 12.75% APY를 만들려면 APR은 더 낮아야 한다 |
| A-09 | 12.74969% | 연속 | **12.0000%** | `ln(1.1274969)` |

### 1-3. 경계값 — 0과 음수

| # | 입력 | 복리 횟수 | 기대 출력 | 왜 |
|---|---:|---|---:|---|
| A-10 | APR 0% | 어떤 값이든 | **0.0000%** | 이자가 없으면 복리도 없다 |
| A-11 | APY 0% | 어떤 값이든 | **0.0000%** | 〃 |
| A-12 | APR −5% | 365회 | **−4.8774%** | 손실도 복리로 깎이므로 **−5%보다 0에 가깝다**. 부호를 헷갈리기 쉬운 지점 |
| A-13 | APR −100% | 365회 | **−63.2625%** | 매일 조금씩 깎여도 1년에 전액을 잃지는 않는다 |
| A-14 | APR −100% | 1회 | **−100.0000%** | 연 1회 복리에서만 전액 손실 |
| A-15 | APR −100% | 연속 | **−63.2121%** | `e^(−1) − 1` |
| A-16 | APY −50% | 365회 | **−69.2489%** | 하루치로 환산한 명목 연이율 |
| A-17 | APY −100% | 365회 | **−36500.0000%** | 수학적으로 맞다. 하루에 전액을 잃는 비율의 연 환산값 |

> **A-17이 이상해 보이는 이유**: "APY −100%"는 1년 뒤 원금이 0이라는 뜻이다. 그걸 365번
> 복리로 쪼개면 하루마다 −100%여야 하고, 그걸 연 단위 명목이율로 적으면 −36500%가 된다.
> 숫자가 이상한 게 아니라, **이 영역에서 명목 APR이라는 개념 자체가 쓸모없다.**

### 1-4. 경계값 — 극단값과 정의되지 않는 입력

| # | 입력 | 복리 횟수 | 기대 출력 | 왜 |
|---|---:|---|---:|---|
| A-18 | APR 1000% | 365회 | **1925283.2708%** | 일복리의 폭발력. 유한하므로 계산돼야 한다 |
| A-19 | APR 1000% | 1회 | **1000.0000%** | 복리 1회면 그대로 |
| A-20 | APR 1000% | 연속 | **2202546.5795%** | `e^10 − 1` |
| A-21 | APR 0.001% | 365회 | **0.0010%** | 아주 작은 값에서도 유효숫자를 잃지 않아야 한다 |
| A-22 | APR −500% | 1회 | **입력값 확인** | 한 주기에 원금보다 더 잃는 입력 → 복리 정의 없음 |
| A-23 | APR 10,000,000% | 365회 | **입력값 확인** | 오버플로(무한대) → 숫자 대신 안내 문구 |
| A-24 | APY −150% | 365회 | **입력값 확인** | 원금보다 더 잃을 수는 없다 |
| A-25 | APY −100% | 연속 | **입력값 확인** | `ln(0) = −무한` |

### 1-5. 보존 법칙 (테스트가 자동으로 48개 조합 확인)

APR → APY → APR 왕복이 원래 값으로 돌아와야 한다.
복리 횟수 `1, 12, 52, 365, 8760, 연속` × APR `−90%, −5%, 0%, 0.01%, 12%, 50%, 200%, 1000%`
= 48개 조합 전부 상대오차 `1e−12` 이내로 복귀 확인.

---

## 2. Uniswap V3 / CLAMM LP

### 2-1. 어디가 정확하고 어디가 추정인가

| 항목 | 상태 | 근거 |
|---|---|---|
| 토큰 수량 (amount0 / amount1) | **정확** | Uniswap V3 백서 수식 그대로 |
| 토큰 비중 | **정확** | 〃 |
| 구간 이탈 시 자산 구성 | **정확** | 가격을 경계로 고정한 값 (하단 밖 = 변동 토큰 100%, 상단 밖 = 기준 토큰 100%) |
| 집중도 (자본효율) | **정확** | `2√P / V(L=1)`. 독립 공식 `1/(1−(Pa/Pb)^0.25)`와 교차검증 |
| 무상손실 (IL) | **정확** | 구간을 무한히 넓히면 Uniswap V2 공식과 일치하는 것을 확인 |
| **예상 수수료** | **추정 — 원리적으로 정확히 알 수 없음** | 아래 참고 |

> **수수료가 추정일 수밖에 없는 이유**
> 입력한 "Fee APR"이 *이 포지션 기준*인지 *풀 전체 기준*인지 알 수 없고, 더 근본적으로는
> **풀 안에서 다른 LP들이 어느 가격대에 유동성을 얼마나 깔아놨는지(활성 유동성 분포)** 를
> 모르면 내 몫을 계산할 수 없다. 그 정보는 이 계산기의 입력값에 없다.
> 그래서 수수료는 `예치금 × Fee APR × 일수/365` 로만 계산하고 **집중도를 곱하지 않는다.**
> 풀 전체 기준 APR을 넣었다면 화면의 **집중도** 배수를 직접 곱해 상한으로 보면 된다.
> 이 한계는 계산기 화면에도 "수수료는 추정" 배지와 설명으로 표시돼 있다.

### 2-2. 쓰는 수식

가격 `P` (= 기준 토큰 / 변동 토큰, 예: USD per ETH), 구간 `[Pa, Pb]`, 유동성 `L`:

```
구간 안 (Pa ≤ P ≤ Pb):
    amount0 = L × (1/√P − 1/√Pb)        변동 토큰 (ETH)
    amount1 = L × (√P − √Pa)            기준 토큰 (USD)

구간 밖: √P 를 [√Pa, √Pb] 로 가둔(clamp) 뒤 같은 식을 쓴다
    P < Pa → amount1 = 0  (전부 변동 토큰)
    P > Pb → amount0 = 0  (전부 기준 토큰)

예치금에서 L 역산:  L = 예치금 ÷ (2√P − P/√Pb − √Pa)
집중도 = 2√P ÷ (2√P − P/√Pb − √Pa)      (풀레인지 = 1배)
IL   = (LP 가치 ÷ 그냥 보유했을 때 가치) − 1
```

### 2-3. 기본 시나리오

**현재가 $3,500 · 구간 $3,100~$3,900 · 예치금 $10,000 · Fee APR 24% · 30일**

| 항목 | 기대 출력 | 왜 이 값인가 |
|---|---:|---|
| B-01 Range 상태 | In range · 경계까지 11.4% | `min(3500−3100, 3900−3500) / 3500` |
| B-02 변동 토큰 | **1.349078개** | `L × (1/√3500 − 1/√3900)`, L = 1515.3586 |
| B-03 변동 토큰 비중 | **47.22%** | 중앙보다 약간 위에 있으므로 변동 토큰이 절반보다 적다 |
| B-04 기준 토큰 | **$5,278.23** | 합계가 예치금과 정확히 일치해야 한다 |
| B-05 집중도 | **17.93배** | 같은 돈으로 풀레인지에 넣을 때보다 유동성 17.93배 |
| B-06 예상 수수료 | **$197.26** | `10000 × 0.24 × 30/365` |
| B-07 종료가 $3,900일 때 LP | **$10,262.52** | 상단에 닿아 전부 기준 토큰 |
| B-08 〃 그냥 보유했다면 | **$10,539.63** | `1.349078 × 3900 + 5278.23` |
| B-09 〃 IL | **−2.63%** | `10262.52 / 10539.63 − 1` |

### 2-4. 경계 케이스 — 구간 이탈

예치금 $10,000, 구간 $3,100~$3,900 고정.

| # | 현재가 | 기대 출력 | 왜 |
|---|---:|---|---|
| B-10 | $3,000 (하단 밖) | 변동 토큰 **3.333333개 / 100%**, 기준 토큰 **$0.00**, 수수료 **$0.00**, 집중도 **N/A** | 가격이 떨어지면 LP는 변동 토큰만 들고 있다. 수량 = 예치금 ÷ 현재가 |
| B-11 | $4,000 (상단 밖) | 변동 토큰 **0개 / 0%**, 기준 토큰 **$10,000.00**, 수수료 **$0.00** | 가격이 오르면 전부 기준 토큰으로 바뀐다 |
| B-12 | $3,100 (하단 경계) | 변동 토큰 비중 **100%** | 경계에 닿는 순간 한쪽으로 완전히 쏠린다 |
| B-13 | $3,900 (상단 경계) | 기준 토큰 비중 **100%** | 〃 |

> **구간 밖에서 수수료가 $0인 이유**: Uniswap V3에서 구간을 벗어난 포지션은 스왑에
> 쓰이지 않는다. 그래서 1원도 쌓이지 않는다. (이전 구현도 이 부분은 맞았다.)

### 2-5. 경계 케이스 — IL

기본 시나리오(현재가 $3,500, 구간 $3,100~$3,900, $10,000)에서 종료 가격만 바꾼다.

| # | 종료 가격 | LP 가치 | 그냥 보유 | IL | 왜 |
|---|---:|---:|---:|---:|---|
| B-14 | $3,500 (변화 없음) | $10,000.00 | $10,000.00 | **0.00%** | 가격이 그대로면 IL은 정확히 0 |
| B-15 | $3,600 | $10,116.87 | $10,134.91 | **−0.18%** | 구간 안에서는 손실이 작다 |
| B-16 | $3,900 (상단) | $10,262.52 | $10,539.63 | **−2.63%** | 구간 끝에서의 손실 |
| B-17 | $4,500 (상단 밖) | $10,262.52 | $11,349.08 | **−9.57%** | LP 가치는 **$10,262.52에서 멈춘다**. 올라도 더 못 번다 |
| B-18 | $10,000 | $10,262.52 | $18,769.01 | **−45.32%** | 〃 격차가 계속 벌어진다 |
| B-19 | $3,100 (하단) | $9,149.61 | $9,460.37 | **−3.28%** | |
| B-20 | $1,000 (하단 밖) | $2,951.49 | $6,627.31 | **−55.46%** | |
| B-21 | $100 | $295.15 | $5,413.14 | **−94.55%** | 가격이 0으로 가면 IL은 −100%에 수렴 |

> **B-21이 −100%로 가는 이유**: 하단 밖에서 LP는 변동 토큰만 들고 있어 가격을 따라
> 0으로 간다. 반면 그냥 들고 있었다면 처음 받은 **기준 토큰(스테이블) 절반이 그대로 남는다.**
> 그래서 비율 차이가 계속 벌어진다.

### 2-6. 경계 케이스 — 잘못된 입력

| # | 입력 | 기대 출력 |
|---|---|---|
| B-22 | 하단 = 상단 ($3,100 / $3,100) | 전 항목 **입력값 확인** |
| B-23 | 하단 > 상단 ($3,900 / $3,100) | 전 항목 **입력값 확인** |
| B-24 | 하단 0 또는 음수 | 전 항목 **입력값 확인** |
| B-25 | 현재가 0 또는 음수 | 전 항목 **입력값 확인** |
| B-26 | 예치 금액 음수 | 전 항목 **입력값 확인** |
| B-27 | 보유 기간 음수 | 수수료 **입력값 확인** |
| B-28 | 종료 가격 0 또는 음수 | LP·보유·IL **입력값 확인** |

### 2-7. 구간 폭에 따른 집중도

예치금 $10,000, 현재가 $3,500.

| # | 구간 | 집중도 | 변동 토큰 비중 |
|---|---|---:|---:|
| B-29 | $3,465~$3,535 (±1%) | **200.49배** | 49.75% |
| B-30 | $3,100~$3,900 (±약 11%) | **17.93배** | 47.22% |
| B-31 | $1,750~$5,250 (±50%) | **4.20배** | 38.52% |
| B-32 | 사실상 풀레인지 | **1.00배** | — |

좁을수록 집중도가 커지고, 풀레인지에 가까워지면 1배로 수렴한다. 테스트가 이 순서를 확인한다.

### 2-8. 교차검증 (테스트가 자동 확인)

| 검증 | 방법 | 결과 |
|---|---|---|
| 집중도 공식 | 현재가가 구간의 기하평균 중앙일 때 `1/(1−(Pa/Pb)^0.25)`와 비교 (5개 구간) | 상대오차 `1e−9` 이내 일치 |
| IL 공식 | 구간을 극단적으로 넓혀 Uniswap V2 공식 `2√r/(1+r) − 1`과 비교 (가격 0.1~10배, 8개 지점) | 상대오차 `1e−7` 이내 일치 |
| 가치 보존 | 토큰 가치 합계 = 예치금 (9개 시나리오) | 상대오차 `1e−12` 이내 일치 |

---

## 3. 바꾸기 전후 숫자 비교

"고쳤다"는 주장이 아니라 **바뀐 숫자**가 증거다.

### 3-1. APR ↔ APY — 핵심 수식은 원래 맞았다

| 상황 | 이전 | 이후 | 판정 |
|---|---:|---:|---|
| APR 12% 일복리 → APY | 12.75% | 12.75% | **변화 없음 (원래 맞음)** |
| APY 12.75% 일복리 → APR | 12.00% | 12.00% | **변화 없음 (원래 맞음)** |
| APR −5% 일복리 → APY | −4.88% | −4.88% | **변화 없음 (원래 맞음)** |
| 연속복리 선택 | 선택지 자체가 없었음 | **12.7497%** | 기능 추가 |
| APY −150% → APR | `NaN%` (화면에 그대로 노출) | **입력값 확인** | 버그 수정 |
| APR 10,000,000% → APY | `Infinity%` | **입력값 확인** | 버그 수정 |
| APR −500% 연 1회 → APY | `−500.00%` (복리 정의가 없는데 숫자를 냄) | **입력값 확인** | 버그 수정 |
| APR 0.001% 일복리 | 유효숫자 손실 | `expm1`/`log1p`로 정확도 확보 | 정밀도 개선 |

### 3-2. Uniswap V3 — 여기가 실제로 틀렸다

이전 구현은 Uniswap V3 수식이 아니라 **임의의 근사 배수**를 썼다.

```js
// 이전 (src/app.js)
const concentrationBoost = inRange ? Math.max(0.35, Math.min(1.8, current / (upper - lower))) : 0;
const expectedFees = deposit * feeApr * (days / 365) * concentrationBoost;
```

`현재가 ÷ 구간폭`을 0.35~1.8로 자른 값이었다. 백서에 없는 식이고, 실제 집중도와 크게 다르다.

| 항목 (기본 시나리오) | 이전 | 이후 | 차이 |
|---|---:|---:|---|
| 집중도 | **1.80배** (상한에 걸려 고정) | **17.93배** | 약 **10배 과소평가** |
| 예상 수수료 (30일) | **$355.07** | **$197.26** | **$157.81 과대평가** (−44%) |
| 토큰 수량 | 없음 | 1.349078개 / $5,278.23 | 신규 |
| 토큰 비중 | 없음 | 47.22% / 52.78% | 신규 |
| 무상손실 (IL) | 없음 | −2.63% (종료가 $3,900) | 신규 |
| 하단 = 상단 입력 | **$355.07** (그럴듯한 숫자) | **입력값 확인** | 버그 수정 |
| 좁은 구간 ±1% 집중도 | **1.80배** (넓은 구간과 동일) | **200.49배** | 구간 폭을 구분하지 못했음 |

> **수수료가 왜 줄었나**: 이전에는 근거 없는 1.8배를 곱하고 있었다. 지금은 입력한 Fee APR을
> 그대로 쓴다. 숫자가 작아진 게 아니라 **없던 배수를 뺀 것**이다. 풀 전체 기준 APR을
> 넣었다면 화면의 집중도(17.93배)를 직접 곱해 상한으로 보면 된다.
>
> **±1% 구간 사례가 핵심**: 이전 구현은 `±1%` 구간과 `±11%` 구간을 **똑같이 1.80배**로
> 봤다. 둘의 실제 차이는 200.49배 대 17.93배로 11배가 넘는다. 구간을 좁히는 것이
> V3 LP의 전부인데, 그 효과를 전혀 반영하지 못했다는 뜻이다.

---

## 4. 화면 쪽 요구사항 (2026-10-13 적용 완료)

아래 id 계약은 **지금 화면에 그대로 들어가 있다.** 계산 결과가 나오려면 반드시 필요하므로
화면을 다시 고칠 때도 유지한다. 빠지면 조용히 빈칸이 된다(에러는 안 나게 처리해 뒀다).

`calculators/*.html` 디자인이 교체될 예정이다. **계산 결과가 화면에 나오려면 아래가 필요하다.**
빠지면 조용히 빈칸이 된다(에러는 안 나게 처리해 뒀다).

### 4-1. 스크립트

`calc-math.js` 가 `app.js` **앞에** 들어가야 한다. 순서가 바뀌면 계산이 전혀 안 된다.

`calculators/apr-apy.html`:

```html
<script src="../src/calc-math.js?v=20261013-1a" defer></script>
<script src="../src/app.js?v=20261013-1a" defer></script>
```

`calculators/uniswap-v3.html` — 전용 화면 코드가 가운데 들어간다:

```html
<script src="../src/calc-math.js?v=20261013-pool" defer></script>
<script src="../src/uniswap-calculator.js?v=20261013-pool" defer></script>
<script src="../src/app.js?v=20261013-pool" defer></script>
```

`uniswap-calculator.js` 가 로드되면 `window.PaguUniswapV3` 가 생기고 `app.js` 의 옛
`initUniswap()` 은 건너뛴다. 그 파일을 지우면 자동으로 옛 화면 코드로 돌아간다.

### 4-2. `calculators/apr-apy.html`

| 종류 | id | 라벨 (단위 포함) |
|---|---|---|
| 입력 | `aprInput` | APR (%) |
| 입력 (select) | `compoundInput` | 복리 횟수 (회/년) — **`value="continuous"` 선택지 필수** |
| 입력 | `apyInput` | APY (%) |
| 출력 | `aprToApy` | APR → APY |
| 출력 | `apyToApr` | APY → APR |
| 출력 | `aprPeriodRate` | 주기당 이자율 (%) |
| 출력 | `aprCompoundGain` | 복리 효과 (APY-APR) |

배지: `검증 완료` (초록) + `표준 복리 정의와 대조 · 2026-10-13`

### 4-3. `calculators/uniswap-v3.html`

| 종류 | id | 라벨 (단위 포함) |
|---|---|---|
| 입력 | `uniCurrent` | 현재 가격 (USD) |
| 입력 | `uniLower` | 하단 가격 (USD) |
| 입력 | `uniUpper` | 상단 가격 (USD) |
| 입력 | `uniDeposit` | 예치 금액 (USD) |
| 입력 | `uniFeeApr` | 예상 Fee APR (%) |
| 입력 | `uniDays` | 보유 기간 (일) |
| 입력 | `uniExit` | 예상 종료 가격 (USD) — **IL 계산에 필요. 신규** |
| 출력 | `uniStatus` | Range 상태 |
| 출력 | `uniAmount0` | 변동 토큰 (개) |
| 출력 | `uniShare0` | 변동 토큰 비중 (%) |
| 출력 | `uniAmount1` | 기준 토큰 (USD) |
| 출력 | `uniConcentration` | 집중도 (배) |
| 출력 | `uniFees` | 예상 수수료 (USD) |
| 출력 | `uniLpValue` | 종료 시 LP (USD) |
| 출력 | `uniHodlValue` | 그냥 보유 시 (USD) |
| 출력 | `uniIl` | 무상손실 IL (%) |

배지: `수량·IL 검증 완료` (초록) + `수수료는 추정` (노랑) + `Uniswap V3 백서 수식 · 2026-10-13`

**수수료가 추정이라는 설명은 화면에 반드시 남아야 한다** (§2-1의 인용 박스 내용).
사용자 지시: *"근사로 남긴 부분이 있다면 화면에 그렇게 표시"*.

### 4-4. 숫자 표시 규칙

출력값은 `syncNumericAlignment()`의 패턴에 맞아야 자동으로 오른쪽 정렬된다.
현재 출력 형식(`$10,262.52`, `47.22%`, `17.93x`, `1.349078`)은 전부 통과하는 것을 확인했다.
형식을 바꾸면 `src/app.js`의 `numericValuePattern`도 같이 확인할 것.

---

## 5. 다음에 할 일

- [ ] **Pendle 계산기 3종 검증** — 3단계에서 시트(`964795995`, `344127195`, `240987043`)를 정답지로 대조. 이번 1A 범위 밖
- [x] **수수료 모델 개선 — A안 구현 완료 (2026-10-13)**. 조사 단계는 DeFiLlama 풀 목록 + 온체인 활성 유동성으로 §2-1의 "추정" 한계를 실제로 풀 수 있음을 확인했다. 두 독립 방법이 0.4% 이내로 일치. **A안(풀 목록 자동 입력) 채택 후 같은 날 구현했다** — `scripts/lib/uniswap-pools.mjs` 수집기,
  `data/uniswap-pools.json` (7체인 70풀), `src/calc-math.js` 의 `v3FeeProjection`,
  `src/uniswap-calculator.js` + `src/calculator.css` 화면. 설계·검증된 사실·주의사항 전부 →
  [docs/pool-data-feasibility.md](pool-data-feasibility.md)
  - 특히 §3-1 **단위 환산**을 먼저 읽을 것. 조사 중 실제로 50배 틀렸고 그 값이 그럴듯해 보였다
- [ ] 틱 간격(tick spacing) 반영 — 실제 Uniswap은 아무 가격이나 구간 경계로 쓸 수 없고 수수료 등급별 틱 간격에 맞춰 반올림된다. 현재 계산기는 입력 가격을 그대로 쓰므로 실제 포지션과 소수점 수준의 차이가 날 수 있다

### 5-1. 남은 항목 (A안 이후)

- [ ] **B안 — 임의 포크 풀 주소 붙여넣기.** 타당성은 확인됐고 순서상 보류했다
      (pool-data-feasibility.md §5). A안이 돌아가는 지금이 재개 조건을 만족한다
- [ ] **Uniswap V4.** 사용자 결정으로 이번에는 제외했다. V4 는 풀이 컨트랙트가 아니라
      PoolManager 안의 id 라서 수집기 구조가 달라진다 (pool-data-feasibility.md §3-3)
- [ ] **스냅샷 신선도.** 가격이 하루 한 번 갱신이라 변동성이 큰 날에는 현재가를 직접 고쳐야 한다.
      화면에 갱신 시각을 적어 뒀지만, 가격만 브라우저에서 실시간으로 받아오는 방법을 B안과 함께 검토
