4-factor composite model — REST API
BTC Pulse provides a free, public API that returns the 4-factor composite score for Bitcoin's macro direction. The model blends Macro Liquidity, Halving Cycle, Price Trend, and Market Sentiment into a single 0–100 score.
https://btcpulse.vercel.appReturns the latest composite score, signal, factor breakdown, and optional historical data.
| Param | Type | Default | Description |
|---|---|---|---|
days | int | "max" | 120 | Number of days of history. Max 3650, or "max" for all available data. |
history | "true" | "false" | "true" | Set to "false" to return only the latest score (faster response). |
GET /api/pulse?days=120&history=false
{
"score": 55,
"signal": "NEUTRAL",
"price": 96432,
"date": "2026-05-02",
"factors": {
"macro": 12.5,
"cycle": 15.0,
"trend": 18.3,
"sentiment": 11.2,
"base": 5
},
"model": "v2",
"weights": "Macro(25)+Cycle(25)+Trend(25)+Sentiment(20)+Base(5)=100"
}
GET /api/pulse?days=7
{
"score": 55,
"signal": "NEUTRAL",
"price": 96432,
"date": "2026-05-02",
"factors": { ... },
"model": "v2",
"weights": "...",
"history": [
{ "date": "2026-04-26", "price": 94102, "score": 57, "signal": "NEUTRAL" },
{ "date": "2026-04-27", "price": 94800, "score": 56, "signal": "NEUTRAL" },
...
]
}
| Field | Type | Description |
|---|---|---|
score | int | Composite score 0–100 (EMA smoothed) |
signal | string | One of: STRONG_BUY, BUY, NEUTRAL, CAUTION, RISK_OFF |
price | float | Latest BTC close price (USD) |
date | string | Date of the latest data point (YYYY-MM-DD) |
factors | object | Breakdown of the 4 factor scores + base |
factors.macro | float | Macro Liquidity score (0–25) |
factors.cycle | float | Halving Cycle score (5–25) |
factors.trend | float | Price Trend score (0–25, with overheating penalty) |
factors.sentiment | float | Market Sentiment score (4–20, contrarian mapping) |
factors.base | int | Base score (always 5) |
model | string | Model version identifier |
history | array | Daily score history (omitted when history=false) |
| Score | Signal | Interpretation |
|---|---|---|
| 80–100 | STRONG_BUY | All factors aligned bullish |
| 60–80 | BUY | Most factors bullish |
| 40–60 | NEUTRAL | Mixed signals, direction unclear |
| 20–40 | CAUTION | Most factors bearish |
| 0–20 | RISK_OFF | All factors aligned bearish |
curl "https://btcpulse.vercel.app/api/pulse?days=30&history=false"
const res = await fetch("https://btcpulse.vercel.app/api/pulse?days=30");
const data = await res.json();
console.log(`BTC Score: ${data.score} — ${data.signal}`);
import requests
r = requests.get("https://btcpulse.vercel.app/api/pulse", params={"days": 30, "history": "false"})
data = r.json()
print(f"BTC Score: {data['score']} — {data['signal']}")
Click to fetch the latest score from the API:
Score = Macro(25) + Cycle(25) + Trend(25) + Sentiment(20) + Base(5) = 0~100
| Factor | Max | Source | Method |
|---|---|---|---|
| Macro Liquidity | 25 | FRED (M2SL, DGS10, DTWEXBGS) | Z-score blend: 60% absolute + 40% rate-of-change |
| Halving Cycle | 25 | Hardcoded dates | Deterministic curve: peak 6–18mo post-halving |
| Price Trend | 25 | CryptoCompare | Price/200DMA ratio with overheating penalty >1.5x |
| Sentiment | 20 | Alternative.me FNG | Non-linear contrarian mapping |
| Base | 5 | — | Constant to prevent zero-floor edge cases |
Final score is smoothed with EMA (k=0.1, ~20-day effective window) to reduce daily noise.