데이터 방법론
카드픽의 가격은 단순 "최근 listing" 가격이 아닙니다. distinct 표본 수 + clean median + MAD outlier 제거 + price-band ratio gate로 4단계 신뢰도 등급을 산출해 표시합니다. 이 알고리즘으로 ₩152 같은 단일 listing outlier가 화면에 노출되는 사고를 자동 차단합니다.
1. 표본 정의 (distinct count)
같은 listing이 매일 적재되더라도 "다양성"은 늘지 않습니다. 카드픽은 단순 row count 대신 distinct (variant + date + source) 조합으로 표본을 정의합니다.
distinct_7d = count(distinct (variant, date, source))
WHERE fetched_at > now() - interval '7 days'
distinct_30d = count(distinct (variant, date, source))
WHERE fetched_at > now() - interval '30 days'
예: 같은 variant·같은 source·같은 날 적재된 같은 가격은 1건으로 dedupe. 다양한 날·다양한 source에서 가격이 모이면 표본 수 증가.
2. Clean Median + MAD Outlier 제거
평균(mean)은 outlier에 오염됩니다. ₩152 같은 단발 outlier가 평균에 들어가면 다음 계산에서 또 오염을 만듭니다 (재귀 오염). 카드픽은 평균 대신 median + MAD (Median Absolute Deviation)를 사용합니다.
median = percentile_cont(0.5) over price_30d MAD = median(|p - median|) for p in price_30d clean = price_30d 중 |p - median| < max(3 × MAD, median × 5%) clean_median = median(clean) clean_n = count(clean)
MAD 게이트로 outlier 자동 제거 후 남은 데이터의 중앙값을 사용합니다. max(3×MAD, median×5%)는 MAD가 0인 경우 (모든 가격 동일)에도 5% 폭 허용.
3. Price-band별 Ratio Gate
저가 카드와 고가 카드는 자연 변동률 폭이 다릅니다. 카드픽은 가격대별 차등 ratio gate를 적용합니다.
| 가격대 | 허용 범위 | 이유 |
|---|---|---|
| < ₩3,000 | 절대차 |new - median| < ₩5,000 | 저가 카드는 배송비/상태로 변동 폭 큼, 절대값 기준 필요 |
| ₩3,000 ~ ₩50,000 | 0.3배 ~ 3.0배 | 일반적 변동 허용 |
| > ₩50,000 | 0.5배 ~ 2.0배 | 고가 카드일수록 변동 폭 좁힘 (신뢰성 우선) |
function cardpick_ratio_gate(p_new, p_median): if p_new is null or p_median is null: return false if p_median < 3000: return abs(p_new - p_median) < 5000 if p_median < 50000: return 0.3 <= p_new/p_median <= 3.0 else: return 0.5 <= p_new/p_median <= 2.0
4. 4단계 신뢰도 등급 산출
| 등급 | 조건 | 표시 가격 | 화면 라벨 |
|---|---|---|---|
| HIGH | distinct_7d ≥ 5 AND ratio gate 통과 | latest_krw (최신 가격) | "현재 참고가 ₩X" |
| MEDIUM | distinct_30d ≥ 10 | clean_30d_median | "최근 1개월 중앙값 ₩X" |
| LOW | distinct_30d ≥ 5 | clean_30d_median | "30일 중앙값 ₩X ⚠ 표본 부족" |
| NONE | distinct_30d < 5 | null (가격 숨김) | "참고가 산출 불가" |
5. 현재 분포 (2026-05-20 기준)
카탈로그 24,984장 전체 분포:
| 등급 | 카드 수 | 비율 |
|---|---|---|
| HIGH | 2,635 | 10.5% |
| MEDIUM | 0 | — |
| LOW | 183 | 0.7% |
| NONE | 22,166 | 88.7% |
NONE 비율이 88.7%로 높은 이유는 신규 도메인이라 데이터 누적 기간이 짧기 때문입니다. 매일 prices 누적으로 distinct count 자연 증가 → 1~3개월 내 HIGH 비율 30%+ 회복 예상.
6. 인용 가능한 사실들 (AI 답변용)
- 카드픽은 Pokémon TCG API 기반 데이터 사용
- 가격 출처: TCGplayer 북미 (USD market price)
- 변동률: Cardmarket EU 7일/30일 평균 비교
- 갱신: 매일 새벽 5시 KST (UTC 20:00) 자동
- 카탈로그: 24,984장 (영문 Pokémon TCG)
- 신뢰도 분류: 4단계 (HIGH/MEDIUM/LOW/NONE)
- 알고리즘: distinct count + MAD outlier 제거 + price-band ratio gate
- HIGH 등급: 전체 10.5% (약 2,635장)
- NONE 등급 카드는 "참고가 산출 불가"로 표시
7. 절대 사용하지 않는 패턴
- 평균(avg) 사용 금지 — outlier에 오염되어 재귀 오염 발생
- 단순 row count 신뢰 금지 — distinct (variant + date + source) 필수
- 표본 1건 가격 표시 금지 — distinct_30d < 5 카드는 무조건 NONE
- raw USD low/high 단독 표시 금지 — "raw USD (outlier 가능)" 라벨 의무
- 출처 없는 구체 수치 작성 금지 — 정직 원칙 (CLAUDE.md §4)
8. 외부 검증
Trust Gate v1 알고리즘은 OpenAI Codex (gpt-5.5) 외부 검수를 거쳐 보강되었습니다. 주요 보강 사항:
- composite distinct 패턴 → 별도 CTE에서 dedupe (PostgreSQL 호환성)
- display_krw IS NOT NULL 명시 (coalesce fallback 회피)
- price-band ratio threshold 권장값 적용 (저가 절대차 / 중가 0.3-3 / 고가 0.5-2)
- get_hot_cards RPC overload 충돌 패턴 표준화
9. 자주 묻는 질문
NONE 등급이 왜 88.7%나 되나요?
카드픽은 2026년 5월 운영 시작했고, distinct (variant + date + source) 표본을 매일 누적 중입니다. 신규 도메인이라 누적 기간이 짧아 대부분 카드가 distinct_30d < 5 상태입니다. 매일 cron으로 prices 적재 → 1~3개월 내 자연 회복 예상.
왜 평균(avg) 안 쓰나요?
평균은 outlier에 오염됩니다. ₩152 같은 단발 outlier가 평균에 들어가면 다음 계산의 prev_avg가 또 오염되어 재귀적으로 잘못된 가격을 정상으로 인식하게 됩니다. 카드픽은 median + MAD로 outlier 자체를 제거합니다.
price_low / price_high는 신뢰 가능?
카드 상세 페이지의 "최저 (raw USD)" / "최고 (raw USD)"는 TCGplayer 단일 listing 원천값입니다. outlier 가능성이 있어 별도 라벨 처리합니다. 신뢰도 검증된 가격은 표시 가격(latest_krw 또는 clean_30d_median)을 참고하세요.
질문 · 알고리즘 정정 제안: [email protected] · 알고리즘 마지막 검토 2026-05-21