{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "# Week 0 Python Foundations and Conditions\n\nPostgraduate Financial Econometrics Python Bootcamp 2026 27\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Using JupyterLab\n\nA Jupyter notebook is made from cells. **Code cells** contain Python and show results below the cell. **Markdown cells** contain headings, notes, equations, and links. Click a cell to select it; use the toolbar menu to change its type between **Code** and **Markdown**. The **+** button adds a new cell below the selected cell.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Running a code cell\n\nSelect a code cell and press **Shift+Enter**. Jupyter runs the Python in that cell, displays any result underneath, and moves to the next cell. Change the value in the cell below and run it again.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "2 + 3\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Writing a Markdown cell\n\nSelect **Markdown** from the cell-type menu and type ordinary text. Use `#` at the start of a line for a heading, `**text**` for bold text, and backticks around short pieces of code. Press **Shift+Enter** to render the cell. Double-click a rendered Markdown cell to edit it again.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Notebook files and Python files\n\nThis notebook is an `.ipynb` file. It can mix Markdown, Python code, and stored output, and its cells can be run separately. A `.py` file is a plain-text Python script: it contains Python code but no Markdown cells or stored cell output, and it normally runs from the first line to the last.\n\nIn a notebook, placing a variable such as `profit` on the final line of a cell displays its value. In a `.py` script, use `print(profit)` when a value should appear in the console. Notebooks are convenient for learning and exploring data; `.py` files are useful for code that should be rerun as one complete program. Python code can be moved between the two formats.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Saving and rerunning\n\nPress **Ctrl+S** to save the notebook. Code cells share the kernel's memory, so later cells can use values created earlier. Work from top to bottom. After completing the notebook, use **Kernel > Restart Kernel and Run All Cells** to check that it works from a clean start.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## The notebook and the kernel\n\nRunning a cell creates or changes objects in the kernel's memory. Later cells can use those objects, but restarting the kernel clears them. The code remains visible even when the remembered values have disappeared.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "course = \"Financial Econometrics\"\ncourse\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The next exercise shows why execution order matters. Work through the three cells in the order stated, then compare the outcomes with the solution.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Exercise 1 Execution order\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Create three code cells:\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "counter = 10\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "counter = counter + 1\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "print(counter)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Run the cells from top to bottom. Then run the middle cell two more times and run the final cell again. Finally, restart the kernel and run only the final cell. Explain the three outcomes.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Solution\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The first ordered run prints `11`. Running the middle cell twice more changes the value remembered by the kernel to `13`. After restarting, `counter` has not yet been created, so the final cell produces a `NameError`. The visible notebook and the current kernel state are related, but they are not the same thing.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Variables, assignment, and types\n\nA variable is a name attached to a value. The equals sign assigns the value on the right to the name on the left. Reusing the name later assigns a new value.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker = \"AAPL\"\nticker\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker = \"MSFT\"\nticker\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Choose names that describe what a value represents. Names cannot contain spaces or begin with a number, and `price` and `Price` are different names.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "number_of_trades = 50       # int: a whole number\nprice = 99.95                # float: a decimal number\nusername = \"alice\"          # str: text\nmarket_is_open = True       # bool: True or False\n\ntype(number_of_trades), type(price), type(username), type(market_is_open)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "A value read from a file may have the wrong type. Use `int()`, `float()`, or `str()` when a compatible value needs to be converted.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "shares_raw = \"80\"\nshares = int(shares_raw)\nshares, type(shares)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Essential arithmetic\n\nPython uses `+`, `-`, `*`, and `/` for the four basic operations. Parentheses make the intended order of calculation explicit.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "shares = 80\npurchase_price = 395.00\ncurrent_price = 418.00\n\namount_invested = shares * purchase_price\ncurrent_value = shares * current_price\nprofit = current_value - amount_invested\n\namount_invested, current_value, profit\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "result_without_parentheses = 10 + 2 * 5\nresult_with_parentheses = (10 + 2) * 5\n\nresult_without_parentheses, result_with_parentheses\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Quiz 1 Follow the assignments\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Without running the code, write down the values printed for `x` and `y`. Remember that Python evaluates the right-hand side using the current values before changing the name on the left.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "x = 4\ny = x\nx = y + 3\ny = x + y\nx = y - x\n\nprint(x)\nprint(y)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Quiz answer\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The code prints `4` and then `11`. After the first four assignments, `x` is 7 and `y` is 11. The final assignment therefore calculates `11 - 7` and assigns the result 4 to `x`. An assignment changes one name; it does not retrospectively change earlier calculations.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Strings\n\nStrings store text inside quotation marks. The quotation marks tell Python that the contents are text; they are not part of the stored value.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "company = \"Apple\"\nticker = \"AAPL\"\n\ncompany\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The `+` operator joins strings. Here a one-character string containing a space separates the company name and ticker.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "label = company + \" \" + ticker\nlabel\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "`len()` counts the characters in a string. Spaces and punctuation also count as characters.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "len(company)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Strings can be indexed and sliced. Position `0` is the first character, position `-1` is the last, and the end of a slice is excluded.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker[0]\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker[-1]\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker[:2]\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "String methods perform common text operations. Data read from a file may contain unwanted spaces or inconsistent capitalisation. `strip()` removes surrounding spaces and `upper()` converts letters to uppercase.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "raw_ticker = \"  aapl \"\nwithout_spaces = raw_ticker.strip()\nclean_ticker = without_spaces.upper()\n\nclean_ticker\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Worked example: combining two purchases\n\nThis exercise brings together variables, type conversion, and arithmetic. Complete the calculations first, then compare them with the solution.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Exercise 2 Combine two purchases of the same stock\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "An investor bought the same stock on two different occasions. The numbers of shares have been read from a file as text.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker = \"MSFT\"\nshares_1_raw = \"80\"\nprice_1 = 395.00\nshares_2_raw = \"45\"\nprice_2 = 410.00\ncurrent_price = 418.00\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(a)** Convert the two share counts to an appropriate numerical type.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(b)** Calculate the total number of shares, the total amount invested, the weighted-average purchase price per share, the current value of the position, and the profit at the current price. Your code should continue to work if the starting values are changed.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Solution\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(a) Convert the share counts**\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "ticker = \"MSFT\"\nshares_1_raw = \"80\"\nprice_1 = 395.00\nshares_2_raw = \"45\"\nprice_2 = 410.00\ncurrent_price = 418.00\n\nshares_1 = int(shares_1_raw)\nshares_2 = int(shares_2_raw)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(b) Calculate the position values**\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "total_shares = shares_1 + shares_2\ntotal_invested = shares_1 * price_1 + shares_2 * price_2\naverage_purchase_price = total_invested / total_shares\ncurrent_value = total_shares * current_price\nprofit = current_value - total_invested\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The two purchases contain 125 shares and cost `50050.0` in total. The weighted-average purchase price is `400.4`. At the current price, the position is worth `52250.0`, giving a profit of `2200.0`.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Comparisons and conditional statements\n\nA comparison produces either `True` or `False`. A single equals sign `=` assigns a value; a double equals sign `==` checks equality.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "price = 187.15\nreference_price = 185.00\n\nprice > reference_price, price == reference_price, price != reference_price\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The main comparison operators are `==`, `!=`, `>`, `<`, `>=`, and `<=`. Use `and` when two conditions must both be true.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "price = 950\nvolume = 5000\nprice > 900 and volume > 3000\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "An `if` statement runs its indented block only when its condition is true. The colon and indentation are part of Python's syntax.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "price = 1200\n\nif price > 1000:\n    decision = \"Sell\"\n\ndecision\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Add `else` for the alternative outcome. Use `elif` when there are more than two cases. Python checks the conditions from top to bottom and uses the first branch whose condition is true.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "price = 950\n\nif price > 1000:\n    decision = \"Sell\"\nelif price > 900:\n    decision = \"Consider selling\"\nelse:\n    decision = \"Hold\"\n\ndecision\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Quiz 2 Follow the control flow\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Without running the cell, determine the final value printed for `status`. Pay attention to the fact that these are two separate `if` statements.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "observations = 80\nstatus = \"unchecked\"\n\nif observations >= 60:\n    status = \"usable\"\n\nif observations >= 100:\n    status = \"large\"\nelse:\n    status = status + \", but limited\"\n\nprint(status)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Quiz answer\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The code prints:\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "```text\nusable, but limited\n```\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The first condition is true, so `status` becomes `\"usable\"`. The second condition is false, and its `else` block adds `\", but limited\"` to the current value. The `else` belongs only to the second `if`.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Exercise 3 Decide whether a share order can be placed\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "An investor wants to buy 20 shares at 75 per share and has 1600 available. For this exercise, time is represented by the hour on a 24-hour clock, so `current_hour = 15` means 15:00. Orders can be placed from 09:00 up to, but not including, 16:00.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "share_price = 75\nshares_wanted = 20\ncash_available = 1600\ncurrent_hour = 15\nmarket_open_hour = 9\nmarket_close_hour = 16\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The order can be placed only if the available cash covers its total cost and the current hour is within the trading window. Write code that checks both requirements and sets `decision` equal to `\"place order\"` or `\"do not place order\"`. The code should continue to give the correct decision if any of the starting values are changed.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Solution\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "order_cost = share_price * shares_wanted\nenough_cash = cash_available >= order_cost\nafter_open = current_hour >= market_open_hour\nbefore_close = current_hour < market_close_hour\nwithin_trading_hours = after_open and before_close\ncan_place_order = enough_cash and within_trading_hours\n\nif can_place_order:\n    decision = \"place order\"\nelse:\n    decision = \"do not place order\"\n\ndecision\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The order costs 1500, the investor has enough cash, and 15:00 is inside the trading window. Both requirements are therefore `True`, so the decision is `\"place order\"`. The intermediate Boolean objects make it possible to inspect the cash check and the timing check separately.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Lists\n\nA list is an ordered collection written inside square brackets. Lists let one variable hold several prices, tickers, or other observations.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "tickers = [\"AAPL\", \"MSFT\", \"JPM\", \"SPY\"]\nprices = [185.64, 187.15, 184.86, 188.63]\n\ntickers, prices\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "`len()` counts the items. For numerical lists, `sum()`, `min()`, and `max()` provide simple summaries.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "len(prices), sum(prices), min(prices), max(prices)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "Lists can be changed. The `append()` method adds one item at the end.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "tickers.append(\"TLT\")\ntickers\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Indexing and slicing\n\nPython counts positions from zero, so index `0` selects the first item. Index `-1` selects the final item.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "tickers = [\"AAPL\", \"MSFT\", \"JPM\", \"SPY\", \"TLT\", \"GLD\"]\n\ntickers[0], tickers[1], tickers[-1]\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "A slice `[start:stop]` selects several items. The start is included and the stop is excluded. Either boundary can be omitted.\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "tickers[1:4], tickers[:3], tickers[3:]\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Exercise 5 Create an estimation and evaluation sample\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The weekly closing prices below are ordered from earliest to latest:\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "weekly_prices = [\n    100.4, 101.2, 99.8, 102.1, 103.0, 104.6,\n    103.8, 105.2, 106.1, 104.9, 107.3, 108.0\n]\nestimation_weeks = 8\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "A financial model should be estimated using earlier observations and evaluated using later observations. The order of the data therefore matters.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "1. Use slicing to create an `estimation_sample` containing the first eight prices and an `evaluation_sample` containing the remaining prices. Check their lengths, the final estimation price, and the first evaluation price.\n2. Calculate the average price in each sample. Create a Boolean variable that records whether the evaluation-sample average is higher, and use a conditional statement to describe the result in a sentence.\n3. Use the first three evaluation prices as a simple benchmark for the final price. Calculate their average and check whether the final price is above it. Report the benchmark, the final price, and the result.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "### Solution\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(1) Split the ordered observations**\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "weekly_prices = [\n    100.4, 101.2, 99.8, 102.1, 103.0, 104.6,\n    103.8, 105.2, 106.1, 104.9, 107.3, 108.0\n]\nestimation_weeks = 8\n\nestimation_sample = weekly_prices[:estimation_weeks]\nevaluation_sample = weekly_prices[estimation_weeks:]\n\n(len(estimation_sample), len(evaluation_sample),\n estimation_sample[-1], evaluation_sample[0])\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The samples contain 8 and 4 observations. The boundary values are 105.2 and 106.1, which confirms that the chronological split is correct.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(2) Compare the sample averages**\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "estimation_average = sum(estimation_sample) / len(estimation_sample)\nevaluation_average = sum(evaluation_sample) / len(evaluation_sample)\nevaluation_average_is_higher = evaluation_average > estimation_average\n\nif evaluation_average_is_higher:\n    comparison = \"The evaluation-sample average is higher.\"\nelse:\n    comparison = \"The evaluation-sample average is not higher.\"\n\ncomparison\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "**(3) Compare the final price with its benchmark**\n"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": "benchmark_prices = evaluation_sample[:-1]\nbenchmark_average = sum(benchmark_prices) / len(benchmark_prices)\nfinal_price = evaluation_sample[-1]\nfinal_price_is_higher = final_price > benchmark_average\n\n(benchmark_average, final_price, final_price_is_higher)\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "The two slices preserve the chronological order of the observations. The comparison with the benchmark is deliberately simple; its purpose is to show how an earlier sample can be used to evaluate a later observation.\n"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## Week 0 takeaways\n\nYou can now create variables, identify basic Python types, perform arithmetic, clean simple strings, make decisions with conditional statements, and select values from lists with indexing and slicing.\n"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3"
  },
  "financial_econometrics": {
   "academic_year": "2026/27",
   "source": "postgraduate_financial_econometrics.tex",
   "week": 0,
   "solutions_included": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
