Indigo Bloomington MN can you tell me about this property the rents in the market as well as the tenants here
mkdir -p scripts && cat > scripts/indigo_rent_premiums.py <<'EOF'
# Indigo Apartments (Bloomington MN) vs Bloomington-east submarket and ZIP 55425; Datamart pull 2026-10-03
p={'ask':1917.17,'inp':1719.97,'ask_med':1946,'inp_med':1609,'0':(1405.25,1380.10),'1':(1597.13,1579.12),'2':(2262.27,2057.97),'3':(2729.00,2332.29),'occ':.9772,'ret':.7215,'dom':61}
s={'ask':1626.72,'inp':1551.58,'0':(1340.44,1313.30),'1':(1530.31,1447.83),'2':(2018.06,1821.83),'3':(3058.00,2439.69),'occ':.9374,'ret':.702,'dom':83}
z={'ask':1721.16,'inp':1656.33,'0':(1346.19,1335.18),'1':(1645.32,1554.52),'2':(2175.46,2006.64),'3':(3058.00,2419.92),'occ':.9372,'ret':.712,'dom':89}
pct=lambda a,b:f"{(a/b-1)*100:+.1f}%"
print("Avg asking vs submarket",pct(p['ask'],s['ask']),"vs zip",pct(p['ask'],z['ask']))
print("Avg in-place vs submarket",pct(p['inp'],s['inp']),"vs zip",pct(p['inp'],z['inp']))
for b in '0123':
print(f"{b}BR asking vs sub {pct(p[b][0],s[b][0])} | in-place vs sub {pct(p[b][1],s[b][1])} | loss-to-lease {pct(p[b][0],p[b][1])}")
print("Property asking-over-in-place (avg)",pct(p['ask'],p['inp']),"median",pct(p['ask_med'],p['inp_med']))
print("Occupancy gap vs submarket (pts)",round((p['occ']-s['occ'])*100,1))
# affordability: property in-place avg*12 / tenant median income
print("Avg in-place x12 / tenant median HHI", round(p['inp']*12/111188*100,1),"%")
print("Tenant median HHI vs ZIP renter median", pct(111188,75728))
EOF
python3 scripts/indigo_rent_premiums.pyBottom line: Indigo is the strongest asset in a soft submarket. It is 97.7% occupied, about 4 points above Bloomington-east. Its asking rents are about 18% above the submarket average and still rising, while rents on new leases nearby are flat to falling. The tenants are well-paid single professionals with little saved wealth. Rent is easy for them to afford today, but they are also likely to leave if rents jump.
| Metric | |||
|---|---|---|---|
| Avg asking rent | $1,9171 | $1,627 | $1,721 |
| Avg in-place rent | $1,720 | $1,552 | $1,656 |
| Studio asking rent | $1,405 | $1,340 | $1,346 |
| Studio in-place rent | $1,380 | $1,313 | $1,335 |
| 1BR asking rent | $1,597 | $1,530 | $1,645 |
| 1BR in-place rent | $1,579 | $1,448 | $1,555 |
| 2BR asking rent | $2,262 | $2,018 | $2,175 |
| 2BR in-place rent | $2,058 | $1,822 | $2,007 |
| 3BR asking rent | $2,729 | $3,058 | $3,058 |
| 3BR in-place rent | $2,332 | $2,440 | $2,420 |
| Occupancy | 97.7% | 93.7% | 93.7% |
| 12-mo asking rent change (median) | 4.23% | 1.55% | 1.02% |
| 12-mo in-place rent change (median) | 1.27% | 1.59% | 0.13% |
| New-lease tradeout % | — | -0.09% | -1.66% |
| Median days on market | 61 | 83 | 89 |
| Retention rate | 72.2% | 70.2% | 71.2% |
Indigo charges more than the market: About $1,917 asking and $1,720 in-place on average , versus about $1,627 asking for the submarket . That is roughly 18% above the submarket and 11% above the ZIP on asking rent, and 11% above the submarket on in-place rent .
The premium is mostly in the 2-bedrooms. Indigo's 2BR asking rents are about 12% above the submarket, and asking is about 10% above what current 2BR tenants pay . Its 3BRs ask about 11% less than the submarket. There are only a few 3BRs, so that number is noisy.
Indigo is raising asking rents while the market isn't. Indigo's asking rents are up 4.2% over 12 months versus 1.6% for the submarket . In-place rents rose only 1.3% . New leases in the ZIP are signing about 1.7% below the prior rent, and the submarket is roughly flat . The gap between Indigo's asking rents and what tenants actually pay could show either:
The fast leasing and high occupancy suggest it is the first, for now.
Main risk: Indigo is pricing for growth in a submarket where new-lease rents are falling. Before underwriting more rent growth, watch whether the 2BR asking rents actually turn into signed leases.
Show me the rent trends over time
mkdir -p extracts && cp tool-outputs/indigo_rent_ts.json tool-outputs/submarket_rent_ts.json tool-outputs/zip_rent_ts.json extracts/ && cat > scripts/indigo_rent_trends.py <<'EOF'
# Monthly rent trend: Indigo vs Bloomington-east submarket vs ZIP 55425 (RealAI Rent Index, MONTH)
import json
def load(f):
d=json.load(open(f'extracts/{f}'))['data']
return {r['mf_rent_ts']['period_start_date'][:7]:r['mf_rent_ts'] for r in d}
P,S,Z=load('indigo_rent_ts.json'),load('submarket_rent_ts.json'),load('zip_rent_ts.json')
f=lambda v,fmt="{:,.0f}": "" if v is None else fmt.format(v)
print("month | IndigoAsk IndigoInPl Occ Leases Tradeout | SubAsk SubInPl SubOcc SubTO | ZipAsk ZipInPl ZipTO")
for m in sorted(P):
p,s,z=P[m],S.get(m,{}),Z.get(m,{})
print(m,"|",f(p['asking_rent_latest_avg']),f(p['in_place_rent_latest_avg']),f(p['occupancy_latest'],"{:.1%}"),p['num_leases_signed'],f(p['tradeout_new_lease_pct_avg'],"{:+.1%}"),"|",
f(s.get('asking_rent_latest_avg')),f(s.get('in_place_rent_latest_avg')),f(s.get('occupancy_latest'),"{:.1%}"),f(s.get('tradeout_new_lease_pct_avg'),"{:+.1%}"),"|",
f(z.get('asking_rent_latest_avg')),f(z.get('in_place_rent_latest_avg')),f(z.get('tradeout_new_lease_pct_avg'),"{:+.1%}"))
ms=sorted(P); first,last=ms[0],ms[-1]
def chg(D,k,a,b):
return (D[b][k]/D[a][k]-1) if D[a].get(k) and D[b].get(k) else None
print("\nWindow",first,"->",last)
for name,D in [("Indigo",P),("Submarket",S),("ZIP",Z)]:
for k in ['asking_rent_latest_avg','in_place_rent_latest_avg']:
c=chg(D,k,first,last); c12=chg(D,k,ms[-13],last)
print(name,k,"total",f(c,"{:+.1%}"),"| last 12m",f(c12,"{:+.1%}"))
# in-place premium over submarket at start vs end
for m in [first,ms[-13],last]:
print("Indigo in-place premium vs submarket",m,f(P[m]['in_place_rent_latest_avg']/S[m]['in_place_rent_latest_avg']-1,"{:+.1%}"))
t=[P[m]['tradeout_new_lease_pct_avg'] for m in ms[-12:] if P[m]['tradeout_new_lease_pct_avg'] is not None]
ts=[S[m]['tradeout_new_lease_pct_avg'] for m in ms[-12:] if S[m].get('tradeout_new_lease_pct_avg') is not None]
print("Avg monthly tradeout last 12m: Indigo",f(sum(t)/len(t),"{:+.1%}"),"n",len(t),"| Submarket",f(sum(ts)/len(ts),"{:+.1%}"))
EOF
python3 scripts/indigo_rent_trends.pySome values come back as strings; converting them to numbers.
cd /vercel/sandbox && sed -i 's/return {r\[.mf_rent_ts.\]\[.period_start_date.\]\[:7\]:r\[.mf_rent_ts.\] for r in d}/out={}\n for r in d:\n t=r["mf_rent_ts"]; out[t["period_start_date"][:7]]={k:(float(v) if isinstance(v,str) and k!="period_start_date" else v) for k,v in t.items()}\n return out/' scripts/indigo_rent_trends.py && python3 scripts/indigo_rent_trends.pycd /vercel/sandbox && python3 - <<'EOF'
import re
s=open('scripts/indigo_rent_trends.py').read()
s=s[:s.index('ms=sorted(P)')]+'''ms=[m for m in sorted(P) if P[m].get('asking_rent_latest_avg')]; first,last=ms[0],ms[-1]
def chg(D,k,a,b):
return (D[b][k]/D[a][k]-1) if D.get(a,{}).get(k) and D.get(b,{}).get(k) else None
print("\\nWindow (Indigo data available)",first,"->",last)
for name,D in [("Indigo",P),("Submarket",S),("ZIP",Z)]:
for k in ['asking_rent_latest_avg','in_place_rent_latest_avg']:
print(name,k,"since",first,f(chg(D,k,first,last),"{:+.1%}"),"| last 12m",f(chg(D,k,"2025-09",last),"{:+.1%}"))
lo=min(ms,key=lambda m:P[m]['asking_rent_latest_avg'])
print("Indigo asking trough",lo,f(P[lo]['asking_rent_latest_avg']),"-> latest",f(P[last]['asking_rent_latest_avg']),f(chg(P,'asking_rent_latest_avg',lo,last),"{:+.1%}"))
for m in [first,"2025-09",last]:
print("Indigo in-place premium vs submarket",m,f(P[m]['in_place_rent_latest_avg']/S[m]['in_place_rent_latest_avg']-1,"{:+.1%}"),
"| asking premium",f(P[m]['asking_rent_latest_avg']/S[m]['asking_rent_latest_avg']-1,"{:+.1%}"))
for lbl,rng in [("Jun25-Mar26",[m for m in ms if "2025-06"<=m<="2026-03"]),("Apr26-Sep26",[m for m in ms if m>="2026-04"])]:
t=[P[m]['tradeout_new_lease_pct_avg'] for m in rng if P[m].get('tradeout_new_lease_pct_avg') is not None]
ts=[S[m]['tradeout_new_lease_pct_avg'] for m in rng if S[m].get('tradeout_new_lease_pct_avg') is not None]
print("Avg monthly new-lease tradeout",lbl,"Indigo",f(sum(t)/len(t),"{:+.1%}"),"| Submarket",f(sum(ts)/len(ts),"{:+.1%}"))
'''
open('scripts/indigo_rent_trends.py','w').write(s)
EOF
python3 scripts/indigo_rent_trends.py | tail -14Bottom line: For about a year, Indigo's rents moved with the market. Since spring 2026 they have pulled ahead. Asking rent is up 21% from its August 2025 low of $1,594 to $1,935 . New leases are now signing about 7% above what the previous tenant paid, while the submarket is flat . In-place rent has barely moved, up 1.1% over 12 months . So the increase so far is only in new leases. It hasn't spread through the rent roll yet.
How it played out
What this changes from my last answer
Data caveats
This is a read-only snapshot of a RealAI analysis.