{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Weather Derivatives Pricer\n",
        "\n",
        "Price a simple HDD/CDD weather derivative using simulated temperature paths and payoff logic.\n",
        "\n",
        "**How to use this notebook:** We give you the structure, the key ideas, starter code, and places where you need to make the important research decisions yourself."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## What you should have by the end\n",
        "\n",
        "- A working prototype\n",
        "- A few graphs/tables that explain what your model is doing\n",
        "- A short write-up of your assumptions\n",
        "- At least one extension that makes the project feel like yours"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Concept\n",
        "\n",
        "Weather derivatives are contracts whose payoffs depend on weather variables, usually temperature.\n",
        "\n",
        "This is cool because the underlying is not a tradable asset like a stock. That means you cannot just blindly use the same no-arbitrage logic you use for vanilla options."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Starter Code\n",
        "\n",
        "1. Define a weather index such as Heating Degree Days or Cooling Degree Days.\n",
        "2. Simulate daily temperature paths.\n",
        "3. Define a payoff.\n",
        "4. Estimate the expected payoff.\n",
        "5. Discuss what is missing from the model."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import pandas as pd\n",
        "\n",
        "rng = np.random.default_rng(42)\n",
        "\n",
        "def simulate_temperature_paths(\n",
        "    n_paths=1000,\n",
        "    n_days=30,\n",
        "    start_temp=18.0,\n",
        "    mean_reversion=0.08,\n",
        "    long_run_mean=20.0,\n",
        "    daily_vol=2.5\n",
        "):\n",
        "    # Simple mean-reverting weather process.\n",
        "    # TODO:\n",
        "    # - Add seasonality.\n",
        "    # - Calibrate parameters to real weather data.\n",
        "    # - Try non-Gaussian shocks.\n",
        "    temps = np.zeros((n_paths, n_days))\n",
        "    temps[:, 0] = start_temp\n",
        "\n",
        "    for t in range(1, n_days):\n",
        "        drift = mean_reversion * (long_run_mean - temps[:, t-1])\n",
        "        shock = daily_vol * rng.normal(size=n_paths)\n",
        "        temps[:, t] = temps[:, t-1] + drift + shock\n",
        "\n",
        "    return temps\n",
        "\n",
        "paths = simulate_temperature_paths()\n",
        "pd.DataFrame(paths[:5]).round(2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def cooling_degree_days(temps, base_temp=18.0):\n",
        "    # CDD = max(average daily temperature - base, 0).\n",
        "    return np.maximum(temps - base_temp, 0).sum(axis=1)\n",
        "\n",
        "def weather_derivative_payoff(index_values, strike=80, tick_value=1000):\n",
        "    # Example call-style payoff on total CDD.\n",
        "    # TODO:\n",
        "    # - Add capped payoffs.\n",
        "    # - Add put-style structures.\n",
        "    # - Add multiple locations.\n",
        "    return tick_value * np.maximum(index_values - strike, 0)\n",
        "\n",
        "cdd = cooling_degree_days(paths)\n",
        "payoff = weather_derivative_payoff(cdd)\n",
        "\n",
        "estimated_price = payoff.mean()\n",
        "estimated_price"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Research questions\n",
        "\n",
        "- How sensitive is the price to daily volatility?\n",
        "- What happens if temperatures have fat-tailed shocks?\n",
        "- How would you calibrate this to Brisbane, Chicago, Singapore, or London?\n",
        "- What is the difference between pricing under real-world probability and risk-neutral probability here?"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Final write-up prompts\n",
        "\n",
        "Answer these before putting the project on your resume:\n",
        "\n",
        "1. What problem were you trying to solve?\n",
        "2. What assumptions did your model make?\n",
        "3. Where did the model work well?\n",
        "4. Where did it fail?\n",
        "5. What would you improve with more time?\n",
        "6. What is one interesting thing you learned that was not obvious before starting?"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.x"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
