Industry Applications
real estate
How to Build a Property Market Analysis AI System
Analyze property market data and generate comp reports using AI.
Jay Banlasan
The AI Systems Guy
An AI property market analysis system for automated comps turns raw sales data into actionable pricing intelligence. I built this for agents who were spending an hour pulling comps manually for every listing presentation. Now they get a full comparative market analysis in minutes, with AI-generated narratives that explain the pricing rationale.
What You Need Before Starting
- Python 3.8+
- Anthropic API key
- MLS data export or a property data API
- SQLite for local storage
Step 1: Build the Property Database
import sqlite3
import csv
def init_market_db(db_path="market_data.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS properties (
id INTEGER PRIMARY KEY AUTOINCREMENT,
address TEXT,
city TEXT,
zip_code TEXT,
bedrooms INTEGER,
bathrooms REAL,
sqft INTEGER,
lot_size REAL,
year_built INTEGER,
sale_price INTEGER,
sale_date TEXT,
days_on_market INTEGER,
property_type TEXT
)
""")
conn.commit()
conn.close()
def import_mls_data(csv_file, db_path="market_data.db"):
conn = sqlite3.connect(db_path)
with open(csv_file) as f:
reader = csv.DictReader(f)
for row in reader:
conn.execute("""
INSERT INTO properties (address, city, zip_code, bedrooms, bathrooms, sqft,
lot_size, year_built, sale_price, sale_date, days_on_market, property_type)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)
""", (row["address"], row["city"], row["zip_code"], int(row["bedrooms"]),
float(row["bathrooms"]), int(row["sqft"]), float(row.get("lot_size", 0)),
int(row["year_built"]), int(row["sale_price"]), row["sale_date"],
int(row.get("days_on_market", 0)), row.get("property_type", "single-family")))
conn.commit()
conn.close()
Step 2: Pull Comparable Properties
def find_comps(target_property, db_path="market_data.db"):
conn = sqlite3.connect(db_path)
comps = conn.execute("""
SELECT * FROM properties
WHERE zip_code = ?
AND bedrooms BETWEEN ? AND ?
AND sqft BETWEEN ? AND ?
AND sale_date > date('now', '-6 months')
AND address != ?
ORDER BY ABS(sqft - ?) ASC
LIMIT 10
""", (
target_property["zip_code"],
target_property["bedrooms"] - 1, target_property["bedrooms"] + 1,
target_property["sqft"] * 0.8, target_property["sqft"] * 1.2,
target_property["address"],
target_property["sqft"]
)).fetchall()
columns = ["id", "address", "city", "zip_code", "bedrooms", "bathrooms", "sqft",
"lot_size", "year_built", "sale_price", "sale_date", "days_on_market", "property_type"]
conn.close()
return [dict(zip(columns, row)) for row in comps]
Step 3: Calculate Market Statistics
def calculate_market_stats(comps):
if not comps:
return {"error": "No comparable properties found"}
prices = [c["sale_price"] for c in comps]
price_per_sqft = [c["sale_price"] / c["sqft"] for c in comps if c["sqft"] > 0]
dom = [c["days_on_market"] for c in comps if c["days_on_market"] > 0]
return {
"comp_count": len(comps),
"avg_price": round(sum(prices) / len(prices)),
"median_price": sorted(prices)[len(prices) // 2],
"min_price": min(prices),
"max_price": max(prices),
"avg_price_per_sqft": round(sum(price_per_sqft) / len(price_per_sqft), 2) if price_per_sqft else 0,
"avg_days_on_market": round(sum(dom) / len(dom)) if dom else 0
}
Step 4: Generate the AI Narrative
import anthropic
from dotenv import load_dotenv
load_dotenv()
def generate_market_narrative(target, comps, stats):
client = anthropic.Anthropic()
comp_summary = "\n".join([
f"- {c['address']}: ${c['sale_price']:,} ({c['sqft']} sqft, {c['bedrooms']}bd/{c['bathrooms']}ba, sold {c['sale_date']})"
for c in comps[:6]
])
prompt = f"""Generate a comparative market analysis narrative for:
Subject: {target['address']} ({target['sqft']} sqft, {target['bedrooms']}bd/{target['bathrooms']}ba, built {target['year_built']})
Market Stats:
- {stats['comp_count']} comparable sales in last 6 months
- Average sale price: ${stats['avg_price']:,}
- Average price/sqft: ${stats['avg_price_per_sqft']}
- Average days on market: {stats['avg_days_on_market']}
Top Comps:
{comp_summary}
Write a 150-word professional CMA narrative covering pricing recommendation, market conditions, and how the subject compares to recent sales."""
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system="You are a real estate market analyst. Write factual, data-backed analysis. No hype. No speculation. Reference specific comps by address.",
messages=[{"role": "user", "content": prompt}]
)
return response.content[0].text
Step 5: Generate the Full Report
def generate_cma_report(target_property, db_path="market_data.db"):
comps = find_comps(target_property, db_path)
stats = calculate_market_stats(comps)
narrative = generate_market_narrative(target_property, comps, stats)
suggested_price = round(target_property["sqft"] * stats["avg_price_per_sqft"], -3)
return {
"subject": target_property,
"comps": comps,
"stats": stats,
"narrative": narrative,
"suggested_list_price": suggested_price,
"price_range": {
"low": round(suggested_price * 0.95, -3),
"high": round(suggested_price * 1.05, -3)
}
}
What to Build Next
Add trend analysis that tracks price-per-sqft changes over time for each zip code. That lets agents show sellers whether the market is trending up or cooling.
Related Reading
- AI in Real Estate Operations - the full picture of AI in real estate
- Building a Reporting Dashboard from Scratch - visualizing market data
- AI in Commercial Real Estate - market analysis for commercial properties
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment