Run a tenant analysis for North Harbor Tower in Chicago: who lives there, household incomes, credit profile, and how tenant quality compares to the surrounding submarket.
Now let me run the calculations.
cat << 'EOF' > /vercel/sandbox/tenant_analysis.py
# North Harbor Tower tenant quality vs Loop submarket benchmark
# --- Income ---
subj_hhi_median = 134146
subj_hhi_avg = 137384
bench_hhi_median = 128991
bench_hhi_avg = 173474
income_var_pct = (subj_hhi_median - bench_hhi_median) / bench_hhi_median * 100
# Bottom quartile proxy: subject has 0% below $75k; bench has ~4.4% below $75k (sum of buckets under 75k)
subj_below_75k = 0.0
bench_below_75k = 0.000601 + 0.014435 + 0.028168 # 10-15k,35-50k,50-75k (all others 0)
bench_below_75k_pct = bench_below_75k * 100
# --- Wealth ---
subj_net_worth_tier_avg = 7.159834
bench_net_worth_tier_avg = 6.496357
subj_net_worth_median_range = "$750,000 - $999,999"
bench_net_worth_median_range = "$500,000 - $749,999"
subj_wealth_tier_avg = 6.776058
bench_wealth_tier_avg = 6.494666
# --- Credit ---
subj_fico = 751.40
bench_fico = 737.64
fico_gap = subj_fico - bench_fico
# Credit tier mix (prime+ = FICO 670+) - subject sample only reports avg FICO, not full tier mix (mf_tenant_profile_detail lacks tier %). Use submarket tier mix for context only.
bench_prime_plus = 0.2283 + 0.5328 + 0.1963 # 670-739 + 740-799 + 800+
bench_subprime_near = 0.0032 + 0.0394 # below579 + 580-669
# Short-term liability (debt burden) tier - lower is better
subj_stl_tier = 2.8765808983863934
bench_stl_tier = 3.495036591551337
# Past due rate
subj_past_due = 0.0592
bench_past_due = 0.0593
# --- Rent to income ---
subj_rti = 0.2395
# submarket RTI field is null; compute manually: submarket in-place median rent * 12 / submarket median income
bench_in_place_rent_median = 2599.00
bench_rti_calc = bench_in_place_rent_median*12/bench_hhi_median
# --- Retention & rent ---
subj_retention = 0.7117
bench_retention = 0.665
subj_in_place_rent_median = 2677.00
bench_in_place_rent_median2 = 2599.00
rent_premium_pct = (subj_in_place_rent_median - bench_in_place_rent_median2)/bench_in_place_rent_median2*100
subj_tradeout = None # not provided at property level in this pull
bench_tradeout_pct = 0.1020
subj_occ = 0.9567
bench_occ = 0.9695
subj_dom = 117
bench_dom = 58
# NOI margin
subj_noi_margin = 0.5863
print("Income variance (median) vs submarket: {:.1f}%".format(income_var_pct))
print("Subject % HH <$75k income: {:.1f}% | Submarket: {:.1f}%".format(subj_below_75k*100, bench_below_75k_pct))
print("Net worth tier avg - Subject: {:.2f} | Submarket: {:.2f}".format(subj_net_worth_tier_avg, bench_net_worth_tier_avg))
print("Wealth resources tier avg - Subject: {:.2f} | Submarket: {:.2f}".format(subj_wealth_tier_avg, bench_wealth_tier_avg))
print("FICO - Subject: {:.0f} | Submarket: {:.0f} | Gap: {:.0f} pts".format(subj_fico, bench_fico, fico_gap))
print("Submarket prime+ (670+) share: {:.1f}% | subprime/near-prime (<670): {:.1f}%".format(bench_prime_plus*100, bench_subprime_near*100))
print("Short-term liability tier (lower=better) - Subject: {:.2f} | Submarket: {:.2f}".format(subj_stl_tier, bench_stl_tier))
print("Past due rate - Subject: {:.2f}% | Submarket: {:.2f}%".format(subj_past_due*100, bench_past_due*100))
print("Rent-to-income - Subject: {:.1f}% | Submarket (calc): {:.1f}%".format(subj_rti*100, bench_rti_calc*100))
print("Retention - Subject: {:.1f}% | Submarket: {:.1f}% | Delta: {:.1f} pts".format(subj_retention*100, bench_retention*100, (subj_retention-bench_retention)*100))
print("In-place median rent - Subject: ${:.0f} | Submarket: ${:.0f} | Premium: {:.1f}%".format(subj_in_place_rent_median, bench_in_place_rent_median2, rent_premium_pct))
print("Occupancy - Subject: {:.1f}% | Submarket: {:.1f}%".format(subj_occ*100, bench_occ*100))
print("Days on market (new leases) - Subject: {:.0f} days | Submarket: {:.0f} days".format(subj_dom, bench_dom))
print("Subject NOI margin (NOI/EGI): {:.1f}%".format(subj_noi_margin*100))
print("Submarket tradeout on new leases: {:.1f}%".format(bench_tradeout_pct*100))
# Household age / mobility
subj_age = 55.55
bench_age = 35.8
print("Household head avg age - Subject: {:.1f} | Submarket: {:.1f}".format(subj_age, bench_age))
EOF
python3 /vercel/sandbox/tenant_analysis.pyNorth Harbor Tower's tenants are genuinely wealthier, older, and lower-debt than the Loop submarket around them — but leasing is moving at half the submarket's pace, and that gap, not tenant quality, is the story here.
| Metric | Subject | Submarket (Loop) | Read |
|---|---|---|---|
| Median household income | $134,1461 | $128,991 | +4%, roughly at parity |
| Households earning under $75K | 0% | 4.3% | Thinner bottom tail |
| Average net worth tier (0-11 scale) | $750K-$999K median | $500K-$749K median | Subject wealthier |
| Average FICO score | 7512 | 738 | Subject ahead, both prime |
| Short-term liability tier (1-8, lower=better) | 2.88 | 3.50 | Subject carries lighter near-term debt |
| Household head average age | 55.5 | 35.8 | Subject much older/established |
The income gap is modest (+4% median), but the shape of the distribution is where the real separation is: not a single subject household reports income below $75K, versus 4.3% of Loop households in that band, and the wealth data confirms it — North Harbor's median net worth tier sits a full band above the submarket's, with tenants carrying noticeably lighter short-term debt (tier 2.88 vs. 3.50) . The 55.5 average household-head age against the Loop's 35.8 tells you who these people are: this isn't the Loop's young-professional renter pool, it's an older, more established, likely empty-nester-leaning tenant base drawn to the lakefront address .
Lifestyle & spending signal
| Category | Signal | ||
|---|---|---|---|
| Borrowing & Credit | Have a mortgage — index 78.7 (+6.7 vs national) | Transfer or consolidate balances — index 36.7 (+15.0 vs national)1 | Subject tenants likely own real estate elsewhere — a wealth marker distinct from the benchmark's active debt-management behavior |
| Lifestyle | Own a boat — index 51.0 (+25.3 vs national) | Own non-motorized watercraft — index 56.7 (-4.4 vs national) | Subject strongly over-indexes on powerboat ownership vs national norms while the broader ZIP's watercraft interest is actually below national baseline — distinctly more marina-affluent, fitting the harbor location |
| Transportation | Purchase a luxury car — index 35.3 (+30.4 vs national) | Commute via train or subway — index 7.4 (+27.9 vs national) | Subject skews car-and-luxury oriented despite the downtown location, benchmark skews transit-dependent |
| Education & Work | Looking for hybrid work — index 29.1 (+14.8 vs national) | Entrepreneur — index 19.1 (+28.9 vs national) | Subject reads as settled corporate professionals, benchmark as a younger entrepreneurial renter pool |
The spending data confirms the demographic read rather than contradicting it. This is a boat-owning, luxury-car-driving, hybrid-corporate-professional persona — consistent with an older, wealthier household that chose a harbor-front tower for the amenity and the address, not a starter-apartment renter .
How the property is performing
What the picture says together
The demographic snapshot and the spending behavior agree completely — wealthier, older, lower-debt, boat-owning professionals — and retention backs that read up. The disconnect is between tenant quality and leasing velocity: a tenant base this strong should be absorbing vacant units faster than the submarket, not twice as slowly. That points to price point or unit mix (this property's 2- and 3-bedroom units run into the $3,800–$5,150 range) rather than any softness in who's actually renting here.
Opportunities and trade-offs
Bottom line: the tenant base is an asset to this business plan, not a liability — income, wealth, and debt load all outrank the Loop submarket, and retention proves the durability. The open question isn't who's living here, it's why absorption on vacant units is running half the submarket's pace; that's worth running down before assuming rent growth here will track the strong tenant profile.
This is a read-only snapshot of a RealAI analysis.