Files
2nd/10_Wiki/Topics/AI_and_ML/Willingness to Pay (WTP).md
T
2026-05-10 22:08:15 +09:00

209 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-willingness-to-pay-wtp
title: Willingness to Pay (WTP)
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [WTP, Reservation Price, Maximum Willingness to Pay]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [pricing, economics, product-management, conjoint, van-westendorp]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: Python/R
framework: pandas/scikit-learn/statsmodels
---
# Willingness to Pay (WTP)
## 매 한 줄
> **"매 customer 가 매 product/feature 에 매 max 얼마까지 지불할 의사가 있는가 — 매 demand curve 의 점 1개"**. 매 price-setting 의 foundation 이지만 매 측정 매 hard (stated WTP 매 over-report, revealed WTP 매 expensive). 2026 현재 매 conjoint analysis (CBC), van Westendorp PSM, MaxDiff, 매 ML-driven 실시간 personalized pricing 이 매 standard toolkit.
## 매 핵심
### 매 정의
- **WTP**: consumer 가 매 specific good/service 에 매 indifferent point — 매 price > WTP 면 매 buy 안 함.
- **Reservation price**: synonym.
- **Producer surplus**: price marginal cost. **Consumer surplus**: WTP price. 매 둘의 합 = total surplus.
### 매 측정 methods
1. **Direct ask (Gabor-Granger, van Westendorp)**: 매 가격 점진적으로 변화시키며 yes/no — cheap 그러나 매 hypothetical bias.
2. **Conjoint (CBC, ACBC)**: 매 trade-off 를 force — 매 제일 실용적 quantitative method.
3. **Auction (BDM, Vickrey)**: 매 incentive-compatible — 매 lab 에서 used.
4. **Revealed preference / A-B test**: 매 actual purchase data — gold standard but expensive.
5. **Behavioral / ML inference**: 매 click, scroll, abandonment 로 pricing model.
### 매 van Westendorp PSM (4 questions)
- "At what price would you consider this product **too expensive** to consider?" (TE)
- "At what price would you consider it expensive but still consider buying?" (Ex)
- "At what price would it be a bargain?" (B)
- "At what price would it be **too cheap**, raising quality concern?" (TC)
- 매 cumulative curves 의 intersection → optimal price point (OPP), point of marginal cheapness/expensiveness.
### 매 응용
1. SaaS pricing tier 결정.
2. Feature prioritization (어느 feature 가 매 WTP boost 매 큰가).
3. Discount / promo 효과 측정.
4. Bundling decisions.
5. Localized pricing (국가별 WTP 차이).
## 💻 패턴
### 1. van Westendorp PSM 분석 (Python)
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Survey responses: TE/Ex/B/TC for each respondent
df = pd.read_csv("psm_survey.csv") # cols: too_exp, expensive, bargain, too_cheap
prices = np.linspace(0, 200, 401)
def cdf(series, prices, direction="leq"):
if direction == "leq":
return np.array([(series <= p).mean() for p in prices])
return np.array([(series >= p).mean() for p in prices])
too_exp_curve = cdf(df.too_exp, prices, "leq")
expensive_curve = cdf(df.expensive, prices, "leq")
bargain_curve = cdf(df.bargain, prices, "geq")
too_cheap_curve = cdf(df.too_cheap, prices, "geq")
# Optimal Price Point: too_cheap == too_exp
opp_idx = np.argmin(np.abs(too_cheap_curve - too_exp_curve))
print(f"OPP: ${prices[opp_idx]:.2f}")
# Indifference Price: bargain == expensive
ip_idx = np.argmin(np.abs(bargain_curve - expensive_curve))
print(f"Indifference Price: ${prices[ip_idx]:.2f}")
```
### 2. Choice-Based Conjoint (CBC) — multinomial logit
```python
import statsmodels.api as sm
import pandas as pd
# Long format: one row per alternative shown
# cols: respondent, task, alt, chosen, price, feature_a, feature_b
df = pd.read_csv("cbc.csv")
# Add chosen as outcome, group by task
X = df[["price", "feature_a", "feature_b"]]
X = sm.add_constant(X)
model = sm.MNLogit(df.chosen, X).fit()
print(model.summary())
# WTP for feature_a = -coef(feature_a) / coef(price)
wtp_a = -model.params["feature_a"][0] / model.params["price"][0]
print(f"WTP for feature A: ${wtp_a:.2f}")
```
### 3. Gabor-Granger curve
```python
from scipy.optimize import curve_fit
# % of respondents willing to buy at each price
df = pd.DataFrame({
"price": [9, 19, 29, 39, 49, 59, 69, 79],
"willing_pct": [0.91, 0.78, 0.62, 0.45, 0.31, 0.18, 0.09, 0.04],
})
def demand(p, a, b):
return 1 / (1 + np.exp(a * (p - b)))
(a, b), _ = curve_fit(demand, df.price, df.willing_pct, p0=[0.05, 40])
revenue = lambda p: p * demand(p, a, b)
optimal_price = max(np.linspace(0, 100, 1000), key=revenue)
print(f"Revenue-maximizing price: ${optimal_price:.2f}")
```
### 4. A/B test on price (revealed WTP)
```python
# Backend: random price assignment per user cohort
import random
PRICE_LADDER = [9.99, 14.99, 19.99, 24.99, 29.99]
def assign_price(user_id: str) -> float:
h = hash(user_id) % len(PRICE_LADDER)
return PRICE_LADDER[h]
# Analysis: conversion × price = revenue per visitor (RPV)
import pandas as pd
log = pd.read_csv("checkout_log.csv") # user, price, converted (0/1)
summary = log.groupby("price").agg(
conv=("converted", "mean"),
n=("converted", "size"),
)
summary["rpv"] = summary.index * summary.conv
print(summary.sort_values("rpv", ascending=False))
```
### 5. ML inference of WTP from behavior
```python
# Predict propensity to convert at given price
from sklearn.ensemble import GradientBoostingClassifier
import numpy as np
X = events[["sessions", "time_on_pricing_page", "company_size", "industry_le"]]
y_at_price = {p: events[f"converted_{p}"] for p in [9, 19, 29, 49]}
models = {p: GradientBoostingClassifier().fit(X, y) for p, y in y_at_price.items()}
def expected_wtp(features):
probs = {p: m.predict_proba([features])[0, 1] for p, m in models.items()}
# WTP = highest price at which P(convert) >= 0.5
over = [p for p, q in probs.items() if q >= 0.5]
return max(over) if over else 0
```
### 6. Localized pricing (PPP-adjusted)
```python
# OECD PPP factors (2025) — adjust list price per country
PPP = {"US": 1.0, "DE": 0.84, "JP": 0.91, "BR": 0.42, "IN": 0.29, "KR": 0.79}
def localize(usd: float, country: str) -> float:
return round(usd * PPP.get(country, 1.0) * 0.99, 2) # nudge to .99
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Pre-launch, new category | van Westendorp PSM (qualitative directional) |
| Feature trade-off, mature market | CBC conjoint |
| Granular dynamic pricing | A/B test + ML model |
| Bundling decisions | ACBC + reservation price model |
| Cross-country | PPP-adjust + per-country PSM |
| B2B enterprise | Sales-led discovery, value-based pricing matrix |
**기본값**: 매 PSM 으로 ballpark → CBC 로 feature WTP → A/B test 로 final tier 검증.
## 🔗 Graph
- 부모: [[Pricing Strategy]] · [[Behavioral Economics]] · [[Microeconomics]]
- 변형: [[Reservation Price]] · [[Hedonic Pricing]] · [[Value-Based Pricing]]
- 응용: [[SaaS Pricing]] · [[Conjoint Analysis]] · [[Revenue Optimization]]
- Adjacent: [[Demand Curve]] · [[Consumer Surplus]] · [[Price Elasticity]]
## 🤖 LLM 활용
**언제**: 매 신제품 pricing tier 결정, 매 feature 의 monetization 평가, 매 international expansion pricing.
**언제 X**: 매 commodity (well-defined market price) 매 marginal cost-plus 가 더 simple. 매 매 sample size 매 작으면 PSM 매 noise.
## ❌ 안티패턴
- **Direct ask 만 사용**: 매 hypothetical bias — stated WTP 매 일반적으로 actual 의 1.5-2x.
- **Single price point survey**: 매 demand curve 그릴 수 없음 — 매 ladder / conjoint 필요.
- **Confound feature with price**: 매 conjoint design 매 price 와 feature 매 orthogonal 보장.
- **Ignoring reference price**: 매 경쟁사/대체재 매 anchor — 매 isolated WTP 매 misleading.
- **PPP adjust 안 한 globally flat pricing**: 매 emerging market 에서 매 piracy/churn 매 폭발.
## 🧪 검증 / 중복
- Verified (van Westendorp 1976, Sawtooth Software CBC docs, Nagle "Strategy and Tactics of Pricing").
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — PSM/CBC/Gabor-Granger/ML behavioral inference |