Generate a Chart of Median House Prices With Mortgage Rates And Recessions in Python
A Python tutorial using free economic data
In case you want to generate a beautiful chart in Python of median house prices with mortgage rates and recessions overlaid, here's the code. It's all self-explanatory but if you need help, comment below.
import pandas as pd
import matplotlib.pyplot as plt
from pandas_datareader.data import DataReader
from datetime import datetime
save_path = "./results/median-house-price-with-mortgage-rates.png"
# Fetch median sales price data from FRED
def fetch_median_sales_price():
"""
Fetches Median Sales Price of Houses in the US from FRED.
Returns:
DataFrame with date index and median sales price.
"""
start_date = "1988-01-01"
end_date = datetime.now()
median_sales_price = DataReader("MSPNHSUS", "fred", start_date, end_date)
median_sales_price.rename(columns={"MSPNHSUS": "Median Sales Price"}, inplace=True)
return median_sales_price
# Fetch mortgage rates from FRED
def fetch_mortgage_rates():
"""
Fetches 30-Year Fixed Mortgage Rates in the US from FRED.
Returns:
DataFrame with date index and mortgage rates.
"""
start_date = "1988-01-01"
end_date = datetime.now()
mortgage_rates = DataReader("MORTGAGE30US", "fred", start_date, end_date)
mortgage_rates.rename(columns={"MORTGAGE30US": "Mortgage Rates"}, inplace=True)
return mortgage_rates
# Fetch recession data from FRED
def fetch_recession_data():
"""
Fetches US recession data from FRED.
Returns:
DataFrame with date index and recession indicators.
"""
start_date = "1988-01-01"
end_date = datetime.now()
recession_data = DataReader("USREC", "fred", start_date, end_date)
return recession_data
def get_recession_periods(recessions):
"""
Extracts periods of recessions.
Args:
recessions: DataFrame containing recession indicators (1 for recession, 0 otherwise).
Returns:
List of tuples representing start and end dates of recessions.
"""
recession_periods = []
in_recession = False
start_date = None
for date, value in recessions["USREC"].items():
if value == 1 and not in_recession:
in_recession = True
start_date = date
elif value == 0 and in_recession:
in_recession = False
end_date = date
recession_periods.append((start_date, end_date))
return recession_periods
def plot_median_sales_price_and_mortgage_rates(median_sales_price, mortgage_rates, recession_periods):
"""
Plots the Median Sales Price of Houses and Mortgage Rates with recession periods.
Args:
median_sales_price: DataFrame with median sales price data.
mortgage_rates: DataFrame with mortgage rate data.
recession_periods: List of recession periods (start and end dates).
"""
fig, ax1 = plt.subplots(figsize=(14, 8))
# Plot median sales price
ax1.plot(median_sales_price.index, median_sales_price["Median Sales Price"], color="blue", linewidth=1.5, label="Median Sales Price")
ax1.set_xlabel("Year", fontsize=14, labelpad=10)
ax1.set_ylabel("Median Sales Price (USD)", fontsize=14, labelpad=10, color="blue")
ax1.tick_params(axis="y", labelcolor="blue")
ax1.grid(visible=True, which="major", linestyle="--", linewidth=0.5, alpha=0.7)
# Add recession periods
for start_date, end_date in recession_periods:
ax1.axvspan(start_date, end_date, color="gray", alpha=0.3, label="Recession" if start_date == recession_periods[0][0] else "")
# Plot mortgage rates
ax2 = ax1.twinx()
ax2.plot(mortgage_rates.index, mortgage_rates["Mortgage Rates"], color="green", linewidth=1.5, linestyle="--", label="Mortgage Rates")
ax2.set_ylabel("Mortgage Rates (%)", fontsize=14, labelpad=10, color="green")
ax2.tick_params(axis="y", labelcolor="green")
# Combine legends
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax1.legend(lines + lines2, labels + labels2, fontsize=12, loc="upper left")
# Title and layout
plt.title("Median Sales Price of Houses and Mortgage Rates with Recession Periods", fontsize=18, fontweight="bold", pad=20)
plt.tight_layout()
plt.savefig(save_path, dpi=300, bbox_inches="tight")
plt.show()
if __name__ == "__main__":
try:
median_sales_price = fetch_median_sales_price()
mortgage_rates = fetch_mortgage_rates()
recession_data = fetch_recession_data()
recession_periods = get_recession_periods(recession_data)
plot_median_sales_price_and_mortgage_rates(median_sales_price, mortgage_rates, recession_periods)
except Exception as e:
print(f"An error occurred: {e}")