Run a migration analysis on California and tell me where people are moving and where incoming movers are coming from and who they are. Dive deeper into the biggest submarkets showing me the trends that move the needle
mkdir -p /vercel/sandbox/work && cat > /vercel/sandbox/work/ca_migration.py << 'EOF'
import json
# California state-level migration
ca = {
"net": -82989, "net_pct": -0.004868, "sample_in": 129672, "sample_out": 212661,
"hhi_med_in": 140588, "hhi_med_out": 144914,
"nw_in": 5.8, "nw_out": 6.6,
"edu_in": 7.3, "edu_out": 6.9,
"dist_in": 1512, "dist_out": 1363.5,
"age_med_in": 45, "age_med_out": 51,
}
ca["hhi_diff"] = ca["hhi_med_in"] - ca["hhi_med_out"]
ca["nw_diff"] = round(ca["nw_in"] - ca["nw_out"], 2)
ca["edu_diff"] = round(ca["edu_in"] - ca["edu_out"], 2)
print("CALIFORNIA STATE")
print(json.dumps(ca, indent=2))
# Submarkets
subs = [
{"name":"South Orange County","market":"Los Angeles","net_pct":0.004991,"net":1045,"hhi_in":202671,"hhi_out":199130,"nw_in":6.8,"nw_out":7.9,"edu_in":7.9,"edu_out":7.8,"dist_med_in":42.5,"dist_med_out":59.5},
{"name":"Victorville/Apple Valley","market":"Riverside","net_pct":0.002180,"net":405,"hhi_in":96293,"hhi_out":102438,"nw_in":3.8,"nw_out":4.6,"edu_in":5.5,"edu_out":5.4,"dist_med_in":47.3,"dist_med_out":65.5},
{"name":"Rocklin/Roseville","market":"Sacramento","net_pct":0.010091,"net":1646,"hhi_in":148805,"hhi_out":142515,"nw_in":6.4,"nw_out":6.9,"edu_in":7.7,"edu_out":7.5,"dist_med_in":45.1,"dist_med_out":38.1},
{"name":"Pasadena/Arcadia","market":"Los Angeles","net_pct":-0.028643,"net":-4598,"hhi_in":140784,"hhi_out":147556,"nw_in":6.2,"nw_out":7.5,"edu_in":7.9,"edu_out":7.6,"dist_med_in":16.2,"dist_med_out":20.5},
{"name":"Oakland East","market":"San Francisco","net_pct":-0.006547,"net":-924,"hhi_in":172468,"hhi_out":180567,"nw_in":5.8,"nw_out":6.8,"edu_in":8.0,"edu_out":7.7,"dist_med_in":14.4,"dist_med_out":17.6},
{"name":"Far South San Jose","market":"San Jose","net_pct":-0.010821,"net":-1527,"hhi_in":284847,"hhi_out":284346,"nw_in":7.0,"nw_out":8.4,"edu_in":7.9,"edu_out":7.7,"dist_med_in":11.3,"dist_med_out":32.9},
{"name":"Antioch/Oakley","market":"San Francisco","net_pct":-0.003928,"net":-548,"hhi_in":167385,"hhi_out":171462,"nw_in":5.5,"nw_out":6.1,"edu_in":6.5,"edu_out":6.2,"dist_med_in":28,"dist_med_out":39.7},
{"name":"Hemet/San Jacinto","market":"Riverside","net_pct":-0.000158,"net":-21,"hhi_in":137704,"hhi_out":135826,"nw_in":4.7,"nw_out":5.0,"edu_in":6.2,"edu_out":6.1,"dist_med_in":37.4,"dist_med_out":44},
{"name":"Nuevo/Perris/Menifee","market":"Riverside","net_pct":0.015412,"net":1983,"hhi_in":128608,"hhi_out":132702,"nw_in":4.5,"nw_out":5.5,"edu_in":5.6,"edu_out":5.4,"dist_med_in":31.4,"dist_med_out":39.3},
{"name":"Santa Clarita","market":"Los Angeles","net_pct":-0.003154,"net":-400,"hhi_in":144579,"hhi_out":193578,"nw_in":5.6,"nw_out":6.7,"edu_in":7.3,"edu_out":7.1,"dist_med_in":26.5,"dist_med_out":80.4},
]
for s in subs:
s["hhi_diff"] = s["hhi_in"] - s["hhi_out"]
s["nw_diff"] = round(s["nw_in"] - s["nw_out"], 2)
s["edu_diff"] = round(s["edu_in"] - s["edu_out"], 2)
subs_sorted_net = sorted(subs, key=lambda x: x["net_pct"], reverse=True)
print("\nSUBMARKETS ranked by net migration % (desc)")
for s in subs_sorted_net:
print(f"{s['name']:28s} net_pct={s['net_pct']*100:+.2f}% net={s['net']:+6d} hhi_diff=${s['hhi_diff']:+7,.0f} nw_diff={s['nw_diff']:+.1f}")
print("\nVerify: only Nuevo/Perris/Menifee has net_pct above 1.5%?")
top = max(subs, key=lambda x: x["net_pct"])
print("Top by net_pct:", top["name"], top["net_pct"])
print("\nVerify: Pasadena/Arcadia has the most negative net_pct among the 10?")
bottom = min(subs, key=lambda x: x["net_pct"])
print("Bottom by net_pct:", bottom["name"], bottom["net_pct"])
# income diff check - who has widest negative outmigration income premium (out-migrants richer)
widest_neg = min(subs, key=lambda x: x["hhi_diff"])
print("\nWidest negative income diff (out-migrants earn more):", widest_neg["name"], widest_neg["hhi_diff"])
EOF
python3 /vercel/sandbox/work/ca_migration.pyCalifornia is losing people on net, but the story splits cleanly in two: the state is losing wealthier, older residents to Texas, Arizona, Nevada, Florida, and Washington, while inside its biggest submarkets, growth is a local sorting mechanism — households leaving expensive coastal cores for cheaper exurban rings just a few miles away.
The state-level exodus. California lost 82,989 people net over the trailing observation window (net migration of -0.49% of population, 10th percentile nationally — a real outflow, not noise). The five most common destinations for people leaving are Texas, Arizona, Nevada, Florida, and Washington — every one a no-or-low income-tax state, and notably the same five states supply most of California's inbound migrants too, so this is a high-volume bilateral churn, not a one-way drain. California loses that exchange on both people and dollars: out-migrants have a median household income of $144,914 versus $140,588 for in-migrants (a -$4,326 gap, below-average nationally) and a materially higher net-worth tier (6.6 vs 5.8 in). The offsetting signal: in-migrants are younger (median age 45 vs. 51 leaving) and slightly more educated (education score 7.3 vs. 6.9) — California is trading some current income and wealth for a younger, comparably-skilled replacement cohort, not a wholesale downgrade.
| Submarket | Parent Market | Net Migration Rate (%) | Net Migrants (count) | Income Diff ($) | Net Worth Tier Diff | Top Origin/Destination Submarket |
|---|---|---|---|---|---|---|
| Growing | ||||||
| Riverside, CA | +1.54%1 | +1,983 | -$4,0941 | -1.0 | Moreno Valley/Hemet-San Jacinto | |
| Sacramento, CA | +1.01%1 | +1,646 | +$6,2901 | -0.5 | Outlying Placer County | |
| Los Angeles, CA | +0.50%1 | +1,045 | +$3,5411 | -1.1 | Mission Viejo-Lake Forest/West Irvine | |
| Riverside, CA | +0.22%1 | +405 | -$6,1451 | -0.8 | Adelante/Oro Grande | |
| Shrinking | ||||||
| Riverside, CA | -0.02%1 | -21 | +$1,8781 | -0.3 | Moreno Valley/Nuevo-Perris-Menifee | |
| Los Angeles, CA | -0.32%1 | -400 | -$48,9991 | -1.1 | Castaic/Angeles National Forest | |
| San Francisco, CA | -0.39%1 | -548 | -$4,0771 | -0.6 | Concord/East Bay | |
| San Francisco, CA | -0.65%1 | -924 | -$8,0991 | -1.0 | Oakland West/Berkeley | |
| San Jose, CA | -1.08%1 | -1,527 | +$5011 | -1.4 | East San Jose/Los Gatos-Saratoga | |
| Los Angeles, CA | -2.86%1 | -4,598 | -$6,7721 | -1.3 | Alhambra/San Gabriel/El Monte | |
The submarket dive: growth is fleeing the core for the exurban ring. Pasadena/Arcadia is by far the sharpest loser among California's largest submarkets — a -2.86% net migration rate that lands in the 1st percentile nationally and MSA-wide — and it's feeding almost entirely into adjacent, cheaper LA-basin submarkets (Alhambra/San Gabriel/El Monte, Azusa/Monrovia, Glendale). The same pattern repeats at Oakland East (-0.65%, feeding Oakland West, Berkeley, Alameda) and Far South San Jose (-1.08%, feeding East San Jose, Los Gatos-Saratoga, Santa Clara) — dense, expensive urban cores losing residents to the next ring out within the same metro. Santa Clarita carries the widest income gap of any submarket in the set: households leaving earn $193,578 versus just $144,579 for households moving in — a $48,999 income downgrade as wealthier residents push further out to Castaic and Palmdale while more budget-constrained households take their place.
On the other side, growth concentrates in exactly the exurban destinations those flows are feeding: Nuevo/Perris/Menifee in the Inland Empire posts the strongest net migration rate of any large CA submarket (+1.54%, 97th percentile vs. its MSA), pulling from neighboring Riverside submarkets (Moreno Valley, Hemet/San Jacinto) at a modest income discount — classic affordability-driven in-migration. Rocklin/Roseville outside Sacramento is the one growth market where in-migrants actually earn more than out-migrants (+$6,290, above-average vs. MSA), pulling from outlying Placer County and Sacramento's other suburbs — a genuine wealth trade-up story, not just a cost play. South Orange County is the outlier in composition: its in-migrants are the oldest cohort of the ten (average age 54.2) and carry an income premium, pointing to a retiree/move-up dynamic among OC's own beach cities rather than an affordability squeeze.
The read: California's headline net-out migration is a tax-and-cost story playing out against Texas, Arizona, Nevada, Florida, and Washington, and it's costing the state disposable income and net worth, not talent — the inbound cohort is younger and equally or more educated. But the more consequential story for anyone underwriting inside California is the second, hyper-local one: money and households are actively sorting away from expensive urban cores like Pasadena, Oakland, and San Jose's core into their own exurban rings (Inland Empire, outer Sacramento), and that reallocation is larger in percentage terms than the state's net interstate loss in several of these submarkets. What would flip this read: if Pasadena/Arcadia's outflow reversed alongside firming in-place rents there, it would signal the affordability-driven core-to-exurb sort is stalling rather than accelerating — worth rechecking net migration next data refresh (6 weeks out) if that's the trade you're sizing.
Happy to layer in rent and supply data for any of these ten submarkets, or push the same lens to a specific metro (LA, Bay Area, Inland Empire) at finer grain.
This is a read-only snapshot of a RealAI analysis.