File size: 4,789 Bytes
dbacacd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from typing import Tuple, TypedDict, Optional
import datetime


class ProcessedSynapse(TypedDict):
    id: Optional[str]
    nextplace_id: Optional[str]
    property_id: Optional[str]
    listing_id: Optional[str]
    address: Optional[str]
    city: Optional[str]
    state: Optional[str]
    zip_code: Optional[str]
    price: Optional[float]
    beds: Optional[int]
    baths: Optional[float]
    sqft: Optional[int]
    lot_size: Optional[int]
    year_built: Optional[int]
    days_on_market: Optional[int]
    latitude: Optional[float]
    longitude: Optional[float]
    property_type: Optional[str]
    last_sale_date: Optional[str]
    hoa_dues: Optional[float]
    query_date: Optional[str]
    market: Optional[str]


class StatisticalBaseModel:

    def __init__(self):
        self._load_model()

    def _load_model(self):
        """
        Perform any actions needed to load the model.
        EX: Establish API connections, download an ML model for inference, etc...
        """
        print("Loading model...")
        # Optional model loading
        print("Model loaded.")

    def _get_average_for_market(self, market: str) -> int:
        """
        Get the average days on market for a house in a given market
        :param market: the housing market
        :return: the average days on market
        """
        # You probably want to update this based on the current season. Houses sell faster in the summer.
        # Add more logic for other housing markets!
        if market == 'San Francisco':
            return 23
        elif market == 'Los Angeles':
            return 68
        elif market == 'Seattle':
            return 27
        elif market == 'Austin':
            return 78
        elif market == 'Houston':
            return 73
        elif market == 'Chicago':
            return 25
        elif market == 'New York':
            return 20
        elif market == 'Denver':
            return 24
        return 34


    def _sale_date_predictor(self, input_data: ProcessedSynapse):
        """
        Calculate the expected sale date based on the national average
        :param days_on_market: number of days this house has been on the market
        :return: the predicted sale date, based on the national average of 34 days
        """
        if 'days_on_market' not in input_data:
            return datetime.date.today() + datetime.timedelta(days=1)

        if 'market' not in input_data:
            average = 34

        else:
            average = self._get_average_for_market(input_data['market'])

        days_on_market = input_data['days_on_market']
        if days_on_market < average:
            days_until_sale = average - days_on_market
            sale_date = datetime.date.today() + datetime.timedelta(days=days_until_sale)
            return sale_date
        else:
            return datetime.date.today() + datetime.timedelta(days=1)

    def _get_price_multiplier(self, market: str) -> float:
        """
        Calculate the price multiplier based on the market
        :param market: the marked the house is in
        :return: the multiplier for the predicted price
        """
        # You may want to add more logic to check zipcode for more precise price multipliers
        # Add more logic for other housing markets!
        if market == 'San Francisco':
            return 1.18  # 18% above listing
        elif market == 'Los Angeles':
            return 1.2  # 22% above listing
        elif market == 'Seattle':
            return 1.13  # 13% above listing
        elif market == 'Austin':
            return 1.11  # 11% above listing
        elif market == 'Houston':
            return 1.15  # 15% above listing
        elif market == 'Chicago':
            return 1.12  # 12% above listing
        elif market == 'New York':
            return 1.05  # 5% above listing
        elif market == 'Denver':
            return 1.11  # 11% above listing
        return 1.0

    def run_inference(self, input_data: ProcessedSynapse) -> Tuple[float, str]:
        """
        Predict the sale price and sale date for the house represented by `input_data`
        :param input_data: a formatted Synapse from the validator, representing a currently listed house
        :return: the predicted sale price and predicted sale date for this home
        """
        listing_price = float(input_data['price']) if 'price' in input_data else 1.0
        sale_multiplier = self._get_price_multiplier(input_data['market']) if 'market' in input_data else 1.0
        predicted_sale_price = listing_price * sale_multiplier
        predicted_sale_date = self._sale_date_predictor(input_data)
        predicted_sale_date = predicted_sale_date.strftime("%Y-%m-%d")
        return predicted_sale_price, predicted_sale_date