Scenario
GDP growth, CPI inflation, and unemployment rates affect every consumer segment differently. A retiree on fixed income reacts to 5% CPI differently than a tech worker with stock options. This job pulls the latest economic indicators, creates demographic personas (retiree, new graduate, small business owner, dual-income family), and runs a Focus Group where each persona reacts to the actual data — revealing how to message products during different economic conditions. Flow: Alpha VantageGET ?function=REAL_GDP + CPI + UNEMPLOYMENT → Mavera POST /personas → POST /focus-groups → Economic messaging insights
Code
import os, requests, time
AV_KEY = os.environ["ALPHA_VANTAGE_KEY"]
AV_BASE = "https://www.alphavantage.co/query"
MV = os.environ["MAVERA_API_KEY"]
MV_BASE = "https://app.mavera.io/api/v1"
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
# 1. Fetch economic indicators
indicators = {}
for func, label in [("REAL_GDP", "GDP"), ("CPI", "CPI"), ("UNEMPLOYMENT", "Unemployment")]:
r = requests.get(AV_BASE, params={"function": func, "interval": "quarterly" if func == "REAL_GDP" else "monthly", "apikey": AV_KEY})
r.raise_for_status()
data = r.json().get("data", [])
recent = data[:4]
indicators[label] = {
"latest": recent[0] if recent else {},
"trend": [{"date": d.get("date",""), "value": d.get("value","")} for d in recent],
}
latest = recent[0] if recent else {}
print(f"{label}: {latest.get('value','N/A')} ({latest.get('date','N/A')})")
time.sleep(15)
# 2. Build economic snapshot
snapshot = "\n".join(
f"**{label}**: {d['latest'].get('value','N/A')} (as of {d['latest'].get('date','N/A')})\n"
f" Trend: {' → '.join(t['value'] for t in reversed(d['trend']))}"
for label, d in indicators.items()
)
# 3. Create demographic personas
DEMOGRAPHICS = [
{"name": "Retiree on Fixed Income", "desc": "Age 68. Pension + Social Security. $52K/year. Inflation directly erodes purchasing power. Risk-averse. Watches news daily."},
{"name": "Recent College Graduate", "desc": "Age 23. First job, $55K salary. $38K student debt. Optimistic but financially stressed. Rents. No investments yet."},
{"name": "Small Business Owner", "desc": "Age 42. Restaurant owner, 12 employees. Revenue $1.2M. Margins thin (8%). Labor costs and food costs top concerns."},
{"name": "Dual-Income Suburban Family", "desc": "Ages 36/38. Combined $180K. Mortgage, two kids, saving for college. Feel upper-middle but stretched. Inflation hits grocery and childcare."},
]
persona_ids = []
for demo in DEMOGRAPHICS:
p = requests.post(f"{MV_BASE}/personas", headers=MV_H, json={
"name": f"Econ: {demo['name']}", "description": demo["desc"],
}).json()
persona_ids.append(p["id"])
time.sleep(0.3)
# 4. Focus Group
fg = requests.post(f"{MV_BASE}/focus-groups", headers=MV_H, json={
"name": "Economic Indicator Reactions",
"persona_ids": persona_ids,
"questions": [
f"Here are the latest economic numbers:\n{snapshot}\n\nHow do these numbers make you feel about your financial situation?",
"Based on these numbers, will you spend more, less, or the same in the next 3 months? On what?",
"If a financial services company approached you right now, what message would resonate?",
"What's the one economic indicator you personally watch most? Why?",
],
"responses_per_persona": 2,
}).json()
for _ in range(25):
time.sleep(5)
data = requests.get(f"{MV_BASE}/focus-groups/{fg['id']}", headers=MV_H).json()
if data.get("status") == "completed":
break
# 5. Print responses
print(f"\n{'='*60}\nECONOMIC FOCUS GROUP RESULTS\n{'='*60}")
print(f"Indicators: {snapshot}\n")
for resp in data.get("responses", []):
pid = resp.get("persona_id", "")
idx = persona_ids.index(pid) if pid in persona_ids else -1
name = DEMOGRAPHICS[idx]["name"] if 0 <= idx < len(DEMOGRAPHICS) else "Unknown"
print(f"[{name}] Q: {resp.get('question','')[:80]}")
print(f" A: {resp.get('answer','')[:350]}\n")
const AV_KEY = process.env.ALPHA_VANTAGE_KEY;
const AV_BASE = "https://www.alphavantage.co/query";
const MV = process.env.MAVERA_API_KEY;
const MV_BASE = "https://app.mavera.io/api/v1";
const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
// 1. Economic indicators
const indicators = {};
for (const [func, label, interval] of [
["REAL_GDP", "GDP", "quarterly"], ["CPI", "CPI", "monthly"], ["UNEMPLOYMENT", "Unemployment", "monthly"]
]) {
const r = await fetch(`${AV_BASE}?function=${func}&interval=${interval}&apikey=${AV_KEY}`);
const data = (await r.json()).data || [];
const recent = data.slice(0, 4);
indicators[label] = { latest: recent[0] || {}, trend: recent.map(d => ({ date: d.date, value: d.value })) };
console.log(`${label}: ${recent[0]?.value || "N/A"} (${recent[0]?.date || "N/A"})`);
await new Promise(r => setTimeout(r, 15000));
}
// 2. Snapshot
const snapshot = Object.entries(indicators).map(([label, d]) =>
`**${label}**: ${d.latest.value||"N/A"} (${d.latest.date||"N/A"})\n Trend: ${d.trend.map(t=>t.value).reverse().join(" → ")}`).join("\n");
// 3. Personas
const DEMOGRAPHICS = [
{ name: "Retiree on Fixed Income", desc: "Age 68. Pension + SS. $52K. Inflation erodes purchasing power." },
{ name: "Recent Graduate", desc: "Age 23. $55K salary. $38K debt. Optimistic but stressed. Rents." },
{ name: "Small Business Owner", desc: "Age 42. Restaurant, 12 employees. $1.2M revenue, 8% margins." },
{ name: "Dual-Income Family", desc: "Ages 36/38. $180K combined. Mortgage, 2 kids. Stretched." },
];
const personaIds = [];
for (const demo of DEMOGRAPHICS) {
const p = await fetch(`${MV_BASE}/personas`, { method: "POST", headers: MV_H,
body: JSON.stringify({ name: `Econ: ${demo.name}`, description: demo.desc }),
}).then(r => r.json());
personaIds.push(p.id);
await new Promise(r => setTimeout(r, 300));
}
// 4. Focus Group
const fg = await fetch(`${MV_BASE}/focus-groups`, { method: "POST", headers: MV_H,
body: JSON.stringify({ name: "Economic Indicator Reactions", persona_ids: personaIds,
questions: [
`Latest numbers:\n${snapshot}\n\nHow do these affect your financial situation?`,
"Spend more, less, or same next 3 months? On what?",
"What message from a financial company would resonate right now?",
"Which indicator do you watch most? Why?",
], responses_per_persona: 2 }),
}).then(r => r.json());
let data;
for (let i = 0; i < 25; i++) {
await new Promise(r => setTimeout(r, 5000));
data = await fetch(`${MV_BASE}/focus-groups/${fg.id}`, { headers: MV_H }).then(r => r.json());
if (data.status === "completed") break;
}
console.log(`\n${"=".repeat(60)}\nECONOMIC FOCUS GROUP RESULTS`);
for (const resp of data.responses || []) {
const idx = personaIds.indexOf(resp.persona_id);
const name = idx >= 0 ? DEMOGRAPHICS[idx].name : "Unknown";
console.log(`[${name}] Q: ${(resp.question||"").slice(0,80)}`);
console.log(` A: ${(resp.answer||"").slice(0,350)}\n`);
}
Example Output
GDP: 22038.236 (2025-10-01)
CPI: 315.648 (2026-01-01)
Unemployment: 4.1 (2026-02-01)
ECONOMIC FOCUS GROUP RESULTS
============================================================
[Retiree on Fixed Income] Q: How do these numbers affect your financial situation?
A: CPI at 315 means my grocery bill is up 20% from 2020 but my
pension COLA was only 3.2%. I'm making trade-offs I shouldn't
have to make — generic medications, store brands, skipping the
annual trip. GDP growth means nothing when my income is fixed.
[Recent Graduate] Q: Spend more, less, or same? On what?
A: Same on rent because I have no choice. Less on eating out —
switched to meal prep. More on skill-building (online courses)
because 4.1% unemployment won't last. Need to be irreplaceable.
[Small Business Owner] Q: What message would resonate?
A: "We'll help you keep your margins without cutting staff."
That's it. Don't tell me the economy is growing — my food
costs are up 15% and I can't raise menu prices again.
Error Handling
Rate limits across indicators
Rate limits across indicators
3 indicator calls at 15s intervals = 45s. On free tier, this uses 3 of 25 daily calls. Cache indicators — they update monthly/quarterly.
Data format
Data format
GDP returns in billions, CPI is an index (base 1982-84=100), Unemployment is a percentage. Include units in Focus Group context so personas interpret correctly.
Focus Group timeout
Focus Group timeout
Economic questions are complex. Allow up to 2 minutes for completion. The polling loop handles this with 25 × 5s iterations.