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, drop me a 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}")