{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Optimal Execution Simulator\n",
        "\n",
        "Simulate slicing a large order and compare simple execution schedules.\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",
        "Optimal execution is about trading a large order without paying unnecessary market impact.\n",
        "\n",
        "A naive trader dumps the whole order at once. A better trader splits it over time, but then takes timing risk. This project is about the trade-off."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Starter Code\n",
        "\n",
        "1. Simulate a price path.\n",
        "2. Define a parent order.\n",
        "3. Implement TWAP and VWAP-style schedules.\n",
        "4. Add simple temporary/permanent impact.\n",
        "5. Compare implementation shortfall."
      ]
    },
    {
      "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(501)\n",
        "\n",
        "def simulate_market(n_steps=100, start_price=100.0):\n",
        "    returns = 0.001 * rng.normal(size=n_steps)\n",
        "    volume = rng.lognormal(mean=10, sigma=0.3, size=n_steps)\n",
        "    price = start_price * np.exp(np.cumsum(returns))\n",
        "    return pd.DataFrame({\"price\": price, \"market_volume\": volume})\n",
        "\n",
        "market = simulate_market()\n",
        "market.head()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def twap_schedule(total_quantity, n_steps):\n",
        "    return np.repeat(total_quantity / n_steps, n_steps)\n",
        "\n",
        "def vwap_schedule(total_quantity, market_volume):\n",
        "    weights = market_volume / market_volume.sum()\n",
        "    return total_quantity * weights\n",
        "\n",
        "total_quantity = 100_000\n",
        "\n",
        "market[\"twap_qty\"] = twap_schedule(total_quantity, len(market))\n",
        "market[\"vwap_qty\"] = vwap_schedule(total_quantity, market[\"market_volume\"])\n",
        "\n",
        "market[[\"price\", \"market_volume\", \"twap_qty\", \"vwap_qty\"]].head()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "def execution_cost(market, quantity_col, impact_coefficient=1e-7):\n",
        "    # Simple temporary impact model.\n",
        "    # TODO:\n",
        "    # - Add permanent impact.\n",
        "    # - Add risk penalty.\n",
        "    # - Compare front-loaded vs back-loaded schedules.\n",
        "    quantity = market[quantity_col]\n",
        "    impacted_price = market[\"price\"] + impact_coefficient * quantity\n",
        "    average_execution_price = np.average(impacted_price, weights=quantity)\n",
        "    arrival_price = market[\"price\"].iloc[0]\n",
        "    shortfall = (average_execution_price - arrival_price) * quantity.sum()\n",
        "    return average_execution_price, shortfall\n",
        "\n",
        "{\n",
        "    \"twap\": execution_cost(market, \"twap_qty\"),\n",
        "    \"vwap\": execution_cost(market, \"vwap_qty\")\n",
        "}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Open-ended extensions\n",
        "\n",
        "- Add Almgren-Chriss style risk/impact trade-off\n",
        "- Add stochastic volume\n",
        "- Compare urgent vs patient execution\n",
        "- Penalise leftover inventory\n",
        "- Explain when VWAP is worse than TWAP"
      ]
    },
    {
      "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
}
