Systems Library / Industry Applications / How to Build a Property Market Analysis AI System
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

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

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

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

Related Systems