My units at Luna at Lake shadow seem to be sitting vacant longer than usual. Is this the case, or has it been this way for a while? Are certain floorplans underperforming others?
"""Builds the Luna at Lake Shadow vacancy-duration diagnostic workbook.
Raw inputs (hardcoded, sourced from Yardi unit_status_daily episode analysis and
RealAI datamart benchmarks); all derived figures are live Excel formulas.
"""
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
BLUE = Font(name="Arial", size=10, color="0000FF")
BLACK = Font(name="Arial", size=10, color="000000")
GREEN = Font(name="Arial", size=10, color="008000")
BOLD = Font(name="Arial", size=10, bold=True)
TITLE = Font(name="Arial", size=12, bold=True)
HDR_FILL = PatternFill("solid", fgColor="1F3864")
HDR_FONT = Font(name="Arial", size=10, bold=True, color="FFFFFF")
TOP_BORDER = Border(top=Side(style="thin"))
RIGHT = Alignment(horizontal="right")
WRAP = Alignment(wrap_text=True, vertical="center", horizontal="center")
wb = openpyxl.Workbook()
# ---------------------------------------------------------------- Inputs
s = wb.active
s.title = "Inputs"
s["A1"] = "Luna at Lake Shadow - vacancy duration diagnostic"; s["A1"].font = TITLE
s["A2"] = "Vacancy episode = contiguous run of Vacant-Unrented daily status (gaps of <=3 days bridged); episodes under 3 days excluded as turn noise."
s["A2"].font = Font(name="Arial", size=9, italic=True)
rows = [
("Property", "Luna at Lake Shadow", None, "Yardi property code res59281"),
("Address", "2200 Flagler Promenade Way, Maitland, FL 32751", None, "Yardi property table"),
("As-of date", "2026-09-23", None, "Latest Yardi daily status snapshot"),
("Total unit records in Yardi feed", 313, "#,##0", "Includes non-revenue records"),
("Waitlist placeholder records (1 per floorplan)", 13, "#,##0", "Present every day of the series; not real units"),
("Model unit", 1, "#,##0", "Excluded from revenue"),
("Long-sitter threshold (days)", 60, "#,##0", "Judgment: days vacant beyond which a unit is a pricing problem"),
("Days per month (rent proration)", 30, "#,##0", "Convention"),
("Submarket median days on market, leases signed last 30d", 57, "#,##0", "RealAI Rent Index - Lockhart submarket"),
("Property median days on market, leases signed last 30d", 48, "#,##0", "RealAI Rent Index - subject"),
("Submarket occupancy (latest)", 0.9193, "0.0%", "RealAI Rent Index - Lockhart submarket"),
("Submarket occupancy 12 months ago", 0.9758, "0.0%", "RealAI Rent Index - Lockhart submarket"),
("Subject occupancy (latest, RealAI)", 0.9433, "0.0%", "RealAI Rent Index - subject"),
("Subject retention rate (TTM)", 0.6967, "0.0%", "RealAI Rent Index - subject"),
]
s["A4"] = "Input"; s["B4"] = "Value"; s["C4"] = "Basis / source"
for c in "ABC":
s[f"{c}4"].font = HDR_FONT; s[f"{c}4"].fill = HDR_FILL
r = 5
for label, val, fmt, basis in rows:
s.cell(r, 1, label).font = BLACK
cell = s.cell(r, 2, val); cell.font = BLUE
if fmt: cell.number_format = fmt
cell.alignment = RIGHT
s.cell(r, 3, basis).font = Font(name="Arial", size=9, italic=True)
r += 1
s["A20"] = "Revenue units"; s["A20"].font = BOLD
s["B20"] = "=B8-B9-B10"; s["B20"].font = BLACK; s["B20"].number_format = "#,##0"; s["B20"].alignment = RIGHT
s["C20"] = "Total records less waitlist placeholders and model"; s["C20"].font = Font(name="Arial", size=9, italic=True)
s.column_dimensions["A"].width = 46
s.column_dimensions["B"].width = 44
s.column_dimensions["C"].width = 52
# ------------------------------------------------- Floorplan diagnostic
fp = wb.create_sheet("Floorplan Diagnostic")
# name, beds, units, sqft, avg mkt rent TTM, TTM episodes, TTM median, TTM pct>60, prior episodes, prior median, prior pct>60
data = [
("5928A1", 1, 73, 770, 1769, 23, 26.0, 0.130, 74, 37.0, 0.311),
("5928A2", 1, 17, 831, 1798, 5, 17.0, 0.200, 17, 41.0, 0.176),
("5928B1", 2, 49, 1140, 2143, 11, 32.0, 0.273, 37, 34.0, 0.108),
("5928B1A", 2, 15, 1147, 2407, 4, 18.0, 0.000, 19, 19.0, 0.053),
("5928B1B", 2, 15, 1140, 2423, 4, 46.0, 0.000, 13, 25.0, 0.308),
("5928B1C", 2, 15, 1140, 2337, 8, 71.5, 0.625, 16, 26.5, 0.000),
("5928B2", 2, 49, 1226, 2253, 16, 35.5, 0.250, 47, 65.0, 0.532),
("5928B3", 2, 13, 1181, 2384, 11, 22.0, 0.091, 9, 37.0, 0.444),
("5928B4", 2, 25, 1299, 2262, 8, 76.5, 0.625, 17, 56.0, 0.412),
("5928C1A", 3, 3, 1299, None, 0, None, None, 1, 73.0, 1.000),
("5928C1B", 3, 3, 1299, 2660, 1, 4.0, 0.000, 2, 62.0, 0.500),
("5928C1C", 3, 3, 1299, None, 0, None, None, 0, None, None),
("5928C2", 3, 33, 1299, 2520, 19, 39.0, 0.263, 40, 46.0, 0.350),
]
hdrs = ["Floorplan", "Beds", "Revenue units", "Min sqft", "Avg market rent, TTM turns ($)",
"Asking rent per sqft ($)", "TTM vacancy episodes", "TTM median days vacant",
"TTM share over 60 days", "Prior 2.5yr episodes", "Prior 2.5yr median days vacant",
"Prior share over 60 days", "Change in median days", "Annual turns (TTM)",
"Excess vacancy cost per year ($)"]
fp["A1"] = "Floorplan vacancy diagnostic - trailing 12 months vs. prior 2.5 years"; fp["A1"].font = TITLE
for j, h in enumerate(hdrs, start=1):
c = fp.cell(3, j, h); c.font = HDR_FONT; c.fill = HDR_FILL; c.alignment = WRAP
fp.row_dimensions[3].height = 46
r = 4
for (name, beds, units, sqft, rent, ep, med, pct, pep, pmed, ppct) in data:
fp.cell(r, 1, name).font = BLACK
for col, val in ((2, beds), (3, units), (4, sqft), (5, rent), (7, ep), (8, med), (9, pct), (10, pep), (11, pmed), (12, ppct)):
c = fp.cell(r, col, val); c.font = BLUE; c.alignment = RIGHT
fp.cell(r, 2).number_format = "0"
fp.cell(r, 3).number_format = "#,##0"
fp.cell(r, 4).number_format = "#,##0"
fp.cell(r, 5).number_format = "$#,##0;($#,##0);-"
fp.cell(r, 7).number_format = "#,##0"
fp.cell(r, 8).number_format = "#,##0.0"
fp.cell(r, 9).number_format = "0.0%"
fp.cell(r, 10).number_format = "#,##0"
fp.cell(r, 11).number_format = "#,##0.0"
fp.cell(r, 12).number_format = "0.0%"
# derived
c = fp.cell(r, 6, f"=IF(OR(E{r}=\"\",D{r}=\"\"),\"\",E{r}/D{r})"); c.font = BLACK; c.number_format = "$0.00"; c.alignment = RIGHT
c = fp.cell(r, 13, f"=IF(OR(H{r}=\"\",K{r}=\"\"),\"\",H{r}-K{r})"); c.font = BLACK; c.number_format = "#,##0.0;(#,##0.0);-"; c.alignment = RIGHT
c = fp.cell(r, 14, f"=G{r}"); c.font = BLACK; c.number_format = "#,##0"; c.alignment = RIGHT
c = fp.cell(r, 15, f"=IF(OR(M{r}=\"\",E{r}=\"\"),\"\",MAX(0,M{r})*N{r}*E{r}/Inputs!$B$12)")
c.font = BLACK; c.number_format = "$#,##0;($#,##0);-"; c.alignment = RIGHT
r += 1
last = r - 1
tot = r
fp.cell(tot, 1, "Total / weighted").font = BOLD
for col in (3, 7, 10, 15):
c = fp.cell(tot, col, f"=SUM({get_column_letter(col)}4:{get_column_letter(col)}{last})")
c.font = BOLD; c.border = TOP_BORDER; c.alignment = RIGHT
fp.cell(tot, 3).number_format = "#,##0"
fp.cell(tot, 7).number_format = "#,##0"
fp.cell(tot, 10).number_format = "#,##0"
fp.cell(tot, 15).number_format = "$#,##0;($#,##0);-"
for col in (1, 2, 4, 5, 6, 8, 9, 11, 12, 13, 14):
fp.cell(tot, col).border = TOP_BORDER
fp.cell(tot + 2, 1, "Excess vacancy cost = max(0, increase in median days vacant) x TTM turns x daily market rent. It prices only the deterioration, not total downtime.")
fp.cell(tot + 2, 1).font = Font(name="Arial", size=9, italic=True)
fp.cell(tot + 3, 1, "C1A and C1C floorplans had no qualifying vacancy episodes in the trailing 12 months (3 units each); their rows are left blank rather than estimated.")
fp.cell(tot + 3, 1).font = Font(name="Arial", size=9, italic=True)
fp.column_dimensions["A"].width = 12
for col in "BCDEFGHIJKLMNO":
fp.column_dimensions[col].width = 13
fp.freeze_panes = "B4"
# ------------------------------------------------------- Vacancy trend
tr = wb.create_sheet("Vacancy Trend")
tr["A1"] = "Vacancy duration by quarter the unit leased, and monthly vacant-unit exposure"; tr["A1"].font = TITLE
q = [("2023 Q1", 11, 12.0, 14.2, 28, 0.000), ("2023 Q2", 18, 32.0, 39.5, 87, 0.222),
("2023 Q3", 23, 43.0, 47.6, 86, 0.261), ("2023 Q4", 29, 50.0, 54.5, 90, 0.276),
("2024 Q1", 43, 44.0, 48.6, 98, 0.326), ("2024 Q2", 29, 29.0, 47.7, 102, 0.379),
("2024 Q3", 31, 33.0, 43.7, 90, 0.226), ("2024 Q4", 28, 55.5, 63.8, 119, 0.464),
("2025 Q1", 28, 49.0, 50.3, 90, 0.286), ("2025 Q2", 24, 45.5, 54.0, 91, 0.375),
("2025 Q3", 29, 35.0, 41.4, 73, 0.241), ("2025 Q4", 39, 43.0, 46.4, 100, 0.282),
("2026 Q1", 20, 24.5, 32.7, 63, 0.150), ("2026 Q2", 39, 39.0, 49.5, 112, 0.282),
("2026 Q3 (partial)", 11, 37.0, 40.5, 67, 0.182)]
hdr2 = ["Quarter leased", "Episodes", "Median days vacant", "Average days vacant", "90th pctile days", "Share over 60 days"]
for j, h in enumerate(hdr2, 1):
c = tr.cell(3, j, h); c.font = HDR_FONT; c.fill = HDR_FILL; c.alignment = WRAP
tr.row_dimensions[3].height = 32
r = 4
for row in q:
tr.cell(r, 1, row[0]).font = BLACK
for col, val in zip(range(2, 7), row[1:]):
c = tr.cell(r, col, val); c.font = BLUE; c.alignment = RIGHT
tr.cell(r, 2).number_format = "#,##0"
tr.cell(r, 3).number_format = "#,##0.0"
tr.cell(r, 4).number_format = "#,##0.0"
tr.cell(r, 5).number_format = "#,##0"
tr.cell(r, 6).number_format = "0.0%"
r += 1
tr.cell(r, 1, "3-year total / average").font = BOLD
c = tr.cell(r, 2, f"=SUM(B4:B{r-1})"); c.font = BOLD; c.number_format = "#,##0"; c.border = TOP_BORDER; c.alignment = RIGHT
c = tr.cell(r, 3, f"=SUMPRODUCT(B4:B{r-1},C4:C{r-1})/B{r}"); c.font = BOLD; c.number_format = "#,##0.0"; c.border = TOP_BORDER; c.alignment = RIGHT
c = tr.cell(r, 4, f"=SUMPRODUCT(B4:B{r-1},D4:D{r-1})/B{r}"); c.font = BOLD; c.number_format = "#,##0.0"; c.border = TOP_BORDER; c.alignment = RIGHT
tr.cell(r, 5).border = TOP_BORDER
c = tr.cell(r, 6, f"=SUMPRODUCT(B4:B{r-1},F4:F{r-1})/B{r}"); c.font = BOLD; c.number_format = "0.0%"; c.border = TOP_BORDER; c.alignment = RIGHT
tr.cell(r, 1).border = TOP_BORDER
qend = r
# period comparison block
p = qend + 3
tr.cell(p, 1, "Period comparison (episodes that leased in the period)").font = BOLD
hdr3 = ["Period", "Episodes", "Median days vacant", "Average days vacant", "Share over 60 days", "vs. 3-year median (days)"]
for j, h in enumerate(hdr3, 1):
c = tr.cell(p + 1, j, h); c.font = HDR_FONT; c.fill = HDR_FILL; c.alignment = WRAP
tr.row_dimensions[p + 1].height = 32
periods = [("Last 90 days", 12, 37.5, 50.8, 0.250), ("Trailing 12 months", 110, 35.0, 44.3, 0.245),
("Prior 2.5 years", 292, 41.0, 48.0, 0.298), ("Full 3.6-year history", 402, 39.0, 47.0, 0.284)]
rr = p + 2
for name, ep, med, avg, pct in periods:
tr.cell(rr, 1, name).font = BLACK
for col, val in zip(range(2, 6), (ep, med, avg, pct)):
c = tr.cell(rr, col, val); c.font = BLUE; c.alignment = RIGHT
tr.cell(rr, 2).number_format = "#,##0"
tr.cell(rr, 3).number_format = "#,##0.0"
tr.cell(rr, 4).number_format = "#,##0.0"
tr.cell(rr, 5).number_format = "0.0%"
c = tr.cell(rr, 6, f"=C{rr}-$C${p+5}"); c.font = BLACK; c.number_format = "#,##0.0;(#,##0.0);-"; c.alignment = RIGHT
rr += 1
# monthly exposure block
m = rr + 2
tr.cell(m, 1, "Monthly exposure (daily averages)").font = BOLD
hdr4 = ["Month", "Avg vacant unrented units", "Share of revenue units vacant unrented", "Share on notice"]
for j, h in enumerate(hdr4, 1):
c = tr.cell(m + 1, j, h); c.font = HDR_FONT; c.fill = HDR_FILL; c.alignment = WRAP
tr.row_dimensions[m + 1].height = 32
months = [("2025-09", 13.4, 0.059), ("2025-10", 17.9, 0.035), ("2025-11", 13.9, 0.049), ("2025-12", 14.9, 0.048),
("2026-01", 13.1, 0.050), ("2026-02", 14.1, 0.070), ("2026-03", 18.4, 0.061), ("2026-04", 19.9, 0.067),
("2026-05", 11.3, 0.073), ("2026-06", 7.7, 0.075), ("2026-07", 7.5, 0.066), ("2026-08", 7.1, 0.051),
("2026-09 (partial)", 11.5, 0.035)]
rm = m + 2
for name, vac, notice in months:
tr.cell(rm, 1, name).font = BLACK
c = tr.cell(rm, 2, vac); c.font = BLUE; c.number_format = "#,##0.0"; c.alignment = RIGHT
c = tr.cell(rm, 3, f"=B{rm}/Inputs!$B$20"); c.font = GREEN; c.number_format = "0.0%"; c.alignment = RIGHT
c = tr.cell(rm, 4, notice); c.font = BLUE; c.number_format = "0.0%"; c.alignment = RIGHT
rm += 1
tr.column_dimensions["A"].width = 26
for col in "BCDEF":
tr.column_dimensions[col].width = 17
# -------------------------------------------------- Current vacancies
cv = wb.create_sheet("Current Vacancies")
cv["A1"] = "Units vacant and unrented as of 2026-09-23"; cv["A1"].font = TITLE
hdr5 = ["Unit", "Floorplan", "Beds", "Vacant since", "Days vacant", "Market rent ($)",
"Daily rent ($)", "Rent forgone to date ($)", "Cost of another 30 days ($)", "Over threshold?", "Readiness"]
for j, h in enumerate(hdr5, 1):
c = cv.cell(3, j, h); c.font = HDR_FONT; c.fill = HDR_FILL; c.alignment = WRAP
cv.row_dimensions[3].height = 40
vac = [("07-307", "5928B2", 2, "2026-03-02", 206, 2259, "Ready"),
("03-304", "5928B2", 2, "2026-07-15", 71, 2322, "Ready"),
("01-205", "5928B1C", 2, "2026-08-09", 46, 2441, "Ready"),
("09-205", "5928A2", 1, "2026-08-13", 42, 1837, "Ready"),
("01-303", "5928B2", 2, "2026-08-29", 26, 2266, "Ready"),
("10-307", "5928C2", 3, "2026-09-04", 20, 2555, "Not ready"),
("09-305", "5928A2", 1, "2026-09-04", 20, 1803, "Ready"),
("03-206", "5928B1B", 2, "2026-09-05", 19, 2542, "Not ready"),
("01-201", "5928C2", 3, "2026-09-08", 16, 2553, "Ready"),
("11-401", "5928B2", 2, "2026-09-11", 13, 2280, "Not ready"),
("01-107", "5928C2", 3, "2026-09-11", 13, 2569, "Not ready"),
("08-303", "5928A2", 1, "2026-09-15", 9, 1827, "Not ready"),
("07-303", "5928B4", 2, "2026-09-21", 3, 2341, "Not ready"),
("02-202", "5928A1", 1, "2026-09-22", 2, 1842, "Not ready")]
r = 4
for unit, fpc, beds, since, days, rent, ready in vac:
cv.cell(r, 1, unit).font = BLACK
cv.cell(r, 2, fpc).font = BLACK
c = cv.cell(r, 3, beds); c.font = BLUE; c.number_format = "0"; c.alignment = RIGHT
c = cv.cell(r, 4, since); c.font = BLUE; c.alignment = RIGHT
c = cv.cell(r, 5, days); c.font = BLUE; c.number_format = "#,##0"; c.alignment = RIGHT
c = cv.cell(r, 6, rent); c.font = BLUE; c.number_format = "$#,##0;($#,##0);-"; c.alignment = RIGHT
c = cv.cell(r, 7, f"=F{r}/Inputs!$B$12"); c.font = BLACK; c.number_format = "$#,##0.00"; c.alignment = RIGHT
c = cv.cell(r, 8, f"=G{r}*E{r}"); c.font = BLACK; c.number_format = "$#,##0;($#,##0);-"; c.alignment = RIGHT
c = cv.cell(r, 9, f"=G{r}*Inputs!$B$12"); c.font = BLACK; c.number_format = "$#,##0;($#,##0);-"; c.alignment = RIGHT
c = cv.cell(r, 10, f'=IF(E{r}>Inputs!$B$11,"Yes","No")'); c.font = BLACK; c.alignment = RIGHT
cv.cell(r, 11, ready).font = BLACK
r += 1
lastv = r - 1
cv.cell(r, 1, "Total").font = BOLD
for col in (6, 8, 9):
c = cv.cell(r, col, f"=SUM({get_column_letter(col)}4:{get_column_letter(col)}{lastv})")
c.font = BOLD; c.number_format = "$#,##0;($#,##0);-"; c.border = TOP_BORDER; c.alignment = RIGHT
c = cv.cell(r, 5, f"=MEDIAN(E4:E{lastv})"); c.font = BOLD; c.number_format = "#,##0"; c.border = TOP_BORDER; c.alignment = RIGHT
for col in (1, 2, 3, 4, 7, 10, 11):
cv.cell(r, col).border = TOP_BORDER
cv.cell(r, 4, "Median days vacant ->").font = BOLD
cv.cell(r + 2, 1, "Rent forgone to date values the full elapsed vacancy at the unit's current market rent; it is gross lost revenue, not a net-of-expense figure.")
cv.cell(r + 2, 1).font = Font(name="Arial", size=9, italic=True)
cv.column_dimensions["A"].width = 11
cv.column_dimensions["B"].width = 12
cv.column_dimensions["C"].width = 8
cv.column_dimensions["D"].width = 14
for col in "EFGHIJK":
cv.column_dimensions[col].width = 15
cv.freeze_panes = "A4"
wb.save("Luna_at_Lake_Shadow_vacancy_diagnostic.xlsx")
print("saved")
cd /vercel/sandbox && python build_vacancy_workbook.py && python skills/xlsx/scripts/workbook_integrity_scan.py Luna_at_Lake_Shadow_vacancy_diagnostic.xlsx --json integrity.json | tail -40
cd /vercel/sandbox && jq -r '.findings[] | [.severity,.category,.sheet,(.anchor//.cell//"")] | @tsv' integrity.json | sort | uniq -c | head -20 && python skills/xlsx/scripts/recalc.py Luna_at_Lake_Shadow_vacancy_diagnostic.xlsx | tail -20
cd /vercel/sandbox && python -c "
import openpyxl
wb=openpyxl.load_workbook('Luna_at_Lake_Shadow_vacancy_diagnostic.xlsx',data_only=True)
fp=wb['Floorplan Diagnostic']
for r in range(4,18):
print(r,[fp.cell(r,c).value for c in (1,6,8,11,13,15)])
cv=wb['Current Vacancies']
print('CV totals row18:',[cv.cell(18,c).value for c in (5,6,8,9)])
print('CV 07-307:',[cv.cell(4,c).value for c in (5,7,8,9)])
tr=wb['Vacancy Trend']
for r in (19,24,25,26,27):
print('tr',r,[tr.cell(r,c).value for c in range(1,7)])
print('inputs B20',wb['Inputs']['B20'].value)
"Property-wide, vacancy is not getting worse — it's your premium two-bedroom variants, and one unit that's been sitting 206 days, creating the impression.
Across 402 vacancy episodes since March 2023, the median unit takes 39 days to go from vacant to leased. The trailing twelve months runs better than history at 35 days, and the last 90 days at 37.5 — inside the normal band, not above it. Vacant-unrented exposure is also down: 7–12 units a day since May versus 14–20 a year ago. Against the Lockhart submarket, where recent signings take a median 57 days and occupancy has dropped from 97.6% to 91.9% over the year, Luna at 48 days and 94.3% is outperforming a softening market.
So the aggregate says no. The floorplan cut says yes — in three specific plans.
B1C is the real deterioration. It went from a 26.5-day median with zero units ever crossing 60 days, to a 71.5-day median with 63% of turns crossing 60 — on 8 turns, small but unambiguous in direction. B4 worsened to a 76.5-day median and B1B to 46 from 25. All three are the top of your two-bedroom rent stack: B1C asks ~$2,337, B1B ~$2,423, B4 ~$2,262 against a submarket two-bedroom average ask of $1,892. The plainer B1 and B2 at $2,143 and $2,253 both lease in about a month, and B2 actually cut its median in half from 65 days. That is a price-resistance pattern at the top of the stack, not a product problem — priced 20–28% over submarket average while the submarket's own asking rents fell 3.6% over the year and tradeouts run negative. Annualized, the added downtime in those three plans costs roughly $47,200 a year in forgone rent.
Everything else improved. One-bedrooms (A1, A2) now lease in 26 and 17 days, down from 37 and 41. B3 halved to 22 days. Three-bedroom C2 is at 39 days.
Unit 07-307 is the single biggest item on the board. A B2 carrying a $2,259 market rent, vacant and flagged "ready" since March 2 — 206 days, about $15,500 of rent forgone, and 41% of the total $38,200 sitting across all 14 currently vacant units. Nothing in the status history suggests a renovation hold. Either it's offline and mis-coded, or it's been marketed for seven months at a price nobody will pay. Either way it needs an answer today. The rest of the current board is healthy: median 19.5 days vacant, with only 03-304 (71 days) also past the threshold.
What I'd do: pull 07-307's leasing and work-order history this week and either recode it or reprice it. Cut B1C asks toward the low-$2,200s and hold B4 flat rather than pushing it — those two plans carry $40,400 of the $47,200 annual bleed. Leave the one-bedrooms and B2 alone; they're working.
What would change this read: B1C and B4 each turn only 8 times a year, so two fast leases would pull those medians back toward normal. If you have the Box Score, traffic-versus-conversion on those plans would tell us whether it's exposure or price — I'd expect price, but that confirms it.
| Unit | Floorplan | Beds | Vacant since | Days vacant | Market rent | Rent forgone to date |
|---|---|---|---|---|---|---|
| 07-307 | 5928B2 | 2 | Mar 2, 2026 | 206 | $2,259 | $15,512 |
| 03-304 | 5928B2 | 2 | Jul 15, 2026 | 71 | $2,322 | $5,495 |
| 01-205 | 5928B1C | 2 | Aug 9, 2026 | 46 | $2,441 | $3,743 |
| 09-205 | 5928A2 | 1 | Aug 13, 2026 | 42 | $1,837 | $2,572 |
| 01-303 | 5928B2 | 2 | Aug 29, 2026 | 26 | $2,266 | $1,964 |
| 10-307 | 5928C2 | 3 | Sep 4, 2026 | 20 | $2,555 | $1,703 |
| 09-305 | 5928A2 | 1 | Sep 4, 2026 | 20 | $1,803 | $1,202 |
| 03-206 | 5928B1B | 2 | Sep 5, 2026 | 19 | $2,542 | $1,610 |
| 01-201 | 5928C2 | 3 | Sep 8, 2026 | 16 | $2,553 | $1,362 |
| 11-401 | 5928B2 | 2 | Sep 11, 2026 | 13 | $2,280 | $988 |
| 01-107 | 5928C2 | 3 | Sep 11, 2026 | 13 | $2,569 | $1,113 |
| 08-303 | 5928A2 | 1 | Sep 15, 2026 | 9 | $1,827 | $548 |
| 07-303 | 5928B4 | 2 | Sep 21, 2026 | 3 | $2,341 | $234 |
| 02-202 | 5928A1 | 1 | Sep 22, 2026 | 2 | $1,842 | $123 |
| Total | — | — | — | — | — | $38,1691 |
This is a read-only snapshot of a RealAI analysis.