قائمة وثائق المطورين

لوحة استثمار لقائمة مختصرة

متقدم

شغّل التقديرات مع مدخلات التمويل لعدة عقارات، واستخرج ملف CSV ولوحة HTML من صفحة واحدة.

الإعداد

يستخدم هذا الدرس الأداة المساعدة jokerprice.py من درس البدء السريع. احفظها بجوار نصك البرمجي واضبط JOKERPRICE_API_KEY.

اكتب قائمة العقارات المرشحة

أنشئ الملف candidates.csv. الأسعار بالريال السعودي.

candidates.csv
name,latitude,longitude,bedrooms,type_id,purchase_price
Al Malqa apartment,24.8094,46.6112,2,6,950000
North Jeddah apartment,21.5675,39.1293,3,6,1100000
Al Khobar villa,26.2794,50.2083,4,7,2400000

قدّر كل عقار مع التمويل

مرّر كائن investment مع التقدير. تُكتب النسب أعدادًا صحيحة، وتأخذ الحقول المحذوفة القيم الافتراضية: دفعة أولى 25٪، وفائدة 6٪، ومدة 25 عامًا، ورسوم منصة 15٪، وإقامات من ليلتين.

Python
import csv
from jokerprice import api

FINANCE = {"downPaymentPct": 30, "loanRatePct": 6.5, "loanTermYears": 25, "platformFeePct": 15,
           "cleaningPerStay": 120, "avgStayNights": 2, "monthlyFixedCosts": 900, "setupCost": 60000}

results = []
for row in csv.DictReader(open("candidates.csv")):
    est = api("POST", "/api/v1/estimate", json={
        "latitude": float(row["latitude"]), "longitude": float(row["longitude"]),
        "bedrooms": int(row["bedrooms"]), "typeId": row["type_id"],
        "investment": {**FINANCE, "purchasePrice": float(row["purchase_price"])},
    })["estimate"]
    inv = est["investment"]
    # A measured projection when available; otherwise the middle (55%) occupancy scenario, labelled as such.
    r = inv["projection"] or (inv["scenarios"][1] if len(inv["scenarios"]) > 1 else None)
    results.append({"name": row["name"], "basis": inv["basis"], "comps": est["asking"]["count"],
                    "adr": r and round(r["adr"]), "occupancy": r and round(r["occupancy"], 3),
                    "revenue": r and round(r["revenue"]), "noi": r and round(r["netOperatingIncome"]),
                    "cap_rate": r and r["capRate"], "cash_on_cash": r and r["cashOnCash"],
                    "monthly_cash_flow": r and round(r["monthlyCashFlow"]), "break_even_occupancy": r and r["breakEvenOccupancy"]})

احفظ ملف CSV

Python
with open("dashboard.csv", "w", newline="") as f:
    out = csv.DictWriter(f, fieldnames=results[0].keys())
    out.writeheader()
    out.writerows(results)

أنشئ لوحة من صفحة واحدة

Python
from html import escape

pct = lambda v: "-" if v is None else f"{v:.1%}"
sar = lambda v: "-" if v is None else f"SAR {v:,.0f}"
rows = "".join(
    f"<tr><td>{escape(r['name'])}</td><td>{r['basis']}</td><td>{r['comps']}</td><td>{sar(r['revenue'])}</td>"
    f"<td>{sar(r['noi'])}</td><td>{pct(r['cap_rate'])}</td><td>{pct(r['cash_on_cash'])}</td>"
    f"<td>{sar(r['monthly_cash_flow'])}</td><td>{pct(r['break_even_occupancy'])}</td></tr>"
    for r in sorted(results, key=lambda r: r["cap_rate"] or -1, reverse=True))
open("dashboard.html", "w").write(
    "<meta charset=utf-8><title>Shortlist</title><style>body{font:14px system-ui;margin:2rem}td,th{padding:6px 10px;border-bottom:1px solid #ddd;text-align:right}td:first-child,th:first-child{text-align:left}</style>"
    "<h1>Shortlist</h1><table><tr><th>Property</th><th>Basis</th><th>Comps</th><th>Revenue</th><th>NOI</th><th>Cap rate</th><th>Cash on cash</th><th>Cash flow / month</th><th>Break-even occ.</th></tr>"
    + rows + "</table>")

اقرأها بعين ناقدة

  • الصفوف التي أساسها scenarios لا يتوفر لها إشغال مقيس في المنطقة، وتفترض أرقامها إشغالًا بنسبة 55٪.
  • إذا تجاوزت قيمة breakEvenOccupancy الإشغال الذي تتوقعه، فالعقار يخسر بعد سداد أقساط الدين.
  • الرسوم والتكاليف الثابتة والتمويل افتراضاتك أنت. غيّر FINANCE وأعد التشغيل، فكل عقار يكلف طلبًا واحدًا.