• Lectures 1-5 cover the Python language. Lectures 6-9 use it to work with financial data.

  • No programming experience is assumed. All examples come from finance: tickers, prices, returns, and portfolios.

  • This lecture covers working in Google Colab, then variables, strings, numbers, and lists.

What We'll Cover

  • Ch 1 (Setting Up Your Environment): Google Colab, running and restarting, an optional local setup, checking your Python version, and a first program.

  • Ch 2 (Variables and Simple Data Types): variables and naming, strings and string methods, f-strings, integers and floats, constants, and comments.

  • Ch 3 (Introducing Lists): creating and indexing lists; changing, adding, and removing items; sorting and reversing; and len().

  • The running example is a small stock watchlist. We clean up ticker symbols, compute position values and returns, and manage a list of holdings. All prices and market values are illustrative, not real quotes.

Ch 1: Setting Up Your Environment

  • To run Python you need an interpreter (the program that reads your code and carries it out) and a place to write and save your code.

  • In this course, Google Colab provides both in your web browser, so there is nothing to install.

Google Colab

  • Google Colab (colab.research.google.com) is a free Google service that runs Jupyter notebooks on cloud computers. You need only a Google account and a web browser.

  • A notebook is a single document that combines explanations, code, and the code's output. This lecture is a notebook; notebook files end in .ipynb.

  • A notebook is made of cells of two kinds:

    • Code cells contain Python. When you run one, its output appears right below it.
    • Text cells contain notes formatted with Markdown (headings, bullets, bold, code). The cell you are reading is a text cell.
  • Use the + Code and + Text buttons at the top of the page to add cells. Double-click a text cell to edit it.

  • Python and most of the data packages used later in the course come preinstalled, so everyone in the class works with the same setup.

Running Code Cells

  • To run a code cell, click inside it and press Shift + Enter, which runs the cell and moves to the next one. You can also click the ▶ button at the cell's left edge.

  • The first run connects the notebook to a runtime, a temporary virtual machine in Google's cloud that executes your code. Connecting takes a few seconds.

  • After a cell runs, a number in brackets such as [4] appears beside it. The numbers record the order in which cells ran.

Note: Python executes cells in the order you run them, which can differ from the order on the page. A cell that uses something defined in a cell you skipped will fail. If in doubt, restart and run everything from the top (next section).

Restarting the Runtime

  • The runtime keeps in memory everything your cells have created so far. Restarting clears that memory but leaves your code and text unchanged.

  • Restart when a notebook behaves strangely, or to check that it runs from top to bottom without errors. Choose Runtime → Restart session (called "Restart runtime" in older versions of Colab), then rerun your cells one at a time, or all at once with Runtime → Run all.

  • Colab also shuts down a runtime that has been idle for a while. As with a restart, your code and text are kept, but you need to run the cells again.

Note: A few cells in our notebooks fail on purpose, to show what common errors look like. Each one begins with the line # This will fail: ... (a line starting with # is a comment, which Python ignores; more in Ch 2). Runtime → Run all stops at the first such cell; to continue, run the cells after it.

Saving Your Own Copy

  • If you open a course notebook from a link, Colab may not let you save your edits to it, because the file belongs to someone else.

  • First choose File → Save a copy in Drive. Colab puts the copy in a folder named Colab Notebooks in your Google Drive and opens it. Do your work in that copy, which saves automatically.

  • If you downloaded the .ipynb file instead, open it with File → Upload notebook. To download a notebook, use File → Download → Download .ipynb.

Working on Your Own Computer (Optional)

  • Everything in this course runs in Colab, but you can also install Python on your own computer.

  • Install Python from python.org, or install Anaconda, a distribution that bundles Python with JupyterLab and many of the data packages used in Lectures 6-9.

    • On Windows, check the box in the python.org installer that adds Python to PATH, so the terminal can find it.
    • On macOS, use the command python3 after installing; the plain python command may not exist.
  • To run Python in a terminal, open Command Prompt or PowerShell (Windows) or Terminal (macOS) and type python (Windows) or python3 (macOS). The >>> prompt means Python is waiting for a line of code; type exit() to leave.

  • You also need a program to write code in. VS Code, with its Python and Jupyter extensions, edits .py script files, runs them with one click, and opens .ipynb notebooks. JupyterLab, included with Anaconda, runs notebooks in your browser using the Python installed on your computer.

Checking Your Python Version

  • Python adds features with each yearly release (3.10, 3.11, 3.12, ...), and code that uses a newer feature will not run on an older version. This course assumes Python 3.10 or later, which Colab provides.

  • To check the version from code, import the standard-library module sys (modules are covered in Lecture 4) and print sys.version. The leading numbers are the version; the rest describes how this copy of Python was built.

  • In Colab, a line that starts with ! is sent to the computer's command line instead of to Python. !python --version reports the version from the command line.

  • The outputs below come from the computer these notes were run on. Your version number may differ; any version from 3.10 on is fine.

import sys

print(sys.version)
3.13.16 (main, Oct  1 2026, 15:40:24) [GCC 13.3.0]
!python --version
Python 3.13.16

Your First Program

  • print() is a built-in function, a named piece of code that does one job. It displays whatever you put between its parentheses.

  • The text between the quotation marks is a string, Python's type for text (more in Ch 2).

  • A program is a sequence of lines that Python runs from top to bottom. By tradition, a first program is a single line that prints a greeting:

print("Hello, markets!")
Hello, markets!

In-Class Exercise

1-1. Your Own Copy:

  • Save a copy of this notebook to your Google Drive and work in that copy for the rest of the lecture.
  • In the cell below, print a line confirming that your copy is running.

1-2. Version Check:

  • Print your runtime's Python version with sys.version.
  • In the same cell, add the line !python --version. Do the two outputs report the same version number?

1-3. Hello, Markets:

  • Write a program that prints three lines: your name, your field of study, and one company you would like to analyze in this course.
  • Restart the session, then run the cell again. Is the output the same?

Ch 2: Variables and Simple Data Types

  • This chapter covers variables and Python's simplest data types:

    • Strings for text, such as tickers and company names.
    • Integers for whole numbers, such as share counts.
    • Floats for numbers with a decimal point, such as prices and rates.
  • Later in the chapter we compute a position's value, an intraday return, and an annualized volatility, and print them in a formatted report.

Variables

  • A variable is a name that refers to a value. You create one with an assignment such as ticker = "MSFT": a name, an equals sign, and a value.

  • The = sign is an instruction to make the name on the left refer to the value on the right. It does not state that the two sides are equal.

  • Assigning to a name that already exists replaces its value. Below, a new quote arrives and price is updated to the latest number:

ticker = "MSFT"
price = 412.35
print(ticker)
print(price)

price = 415.85
print(price)
MSFT
412.35
415.85

Naming Rules and Conventions

  • Python enforces these rules: a name may contain letters, digits, and underscores; it cannot start with a digit or contain spaces; and it cannot be a keyword that Python reserves for itself, such as if, for, class, or True.

  • By convention (from the PEP 8 style guide), variable names are lowercase words joined by underscores, as in closing_price or shares_held.

  • Use names that say what the value is. In finance code, r might mean a return, an interest rate, or a correlation; annual_return can mean only one thing.

    • Clear: ticker, closing_price, annual_return
    • Legal but vague: x, cp, data2
    • Not allowed: 2024_return (starts with a digit), closing price (contains a space), class (a keyword)

Note: Avoid reusing the names of built-in functions such as print, list, sum, or max. Python allows it, but the original function is then hidden until you restart the runtime.

NameError: A Misspelled Name

  • Names are case-sensitive: price, Price, and PRICE are three different names.

  • Python knows only the names you have assigned. Using any other name, even one that differs by a single capital letter, raises a NameError.

  • To read an error message, start at the bottom. The last line gives the error type and a short explanation, and the arrow ----> points to the line that failed.

# This will fail: names are case-sensitive, and `Closing_price` was never assigned
closing_price = 187.44
print(Closing_price)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 3
      1 # This will fail: names are case-sensitive, and `Closing_price` was never assigned
      2 closing_price = 187.44
----> 3 print(Closing_price)

NameError: name 'Closing_price' is not defined

Strings

  • A string is Python's type for text, such as a ticker, a company name, or an exchange code. In code, a string is written between quotes.

  • Single and double quotes both work. These notes use double quotes, which can contain an apostrophe, as in "Moody's". Inside single quotes, the apostrophe would end the string early and cause a SyntaxError.

ticker = "JPM"
company = 'JPMorgan Chase & Co.'  # single quotes work too
rating_agency = "Moody's Corporation"
print(ticker)
print(company)
print(rating_agency)
JPM
JPMorgan Chase & Co.
Moody's Corporation

Joining Strings and f-Strings

  • The + operator joins strings end to end. This is called concatenation.

  • An f-string is a string with the letter f in front, such as f"{ticker} closed higher". When the line runs, Python evaluates the expression inside each pair of braces and inserts the result into the text.

  • f-strings (formally, formatted string literals) are easier to read than a chain of + signs, especially when numbers are involved. This course uses them throughout.

exchange = "NYSE"
ticker = "KO"
company = "Coca-Cola"
print(exchange + ":" + ticker)
print(f"{company} trades on the {exchange} under the ticker {ticker}.")
NYSE:KO
Coca-Cola trades on the NYSE under the ticker KO.

Upper, Lower, and Title Case

  • A method is a function attached to a value. To call one, write the value (or its variable name), a dot, the method name, and parentheses, as in user_input.upper(). The parentheses are required even when they are empty.

  • upper() returns an all-caps copy of a string, the standard form for tickers. A string cannot be changed after it is created, so methods like upper() return a new string instead. To keep the result, assign it to a name.

user_input = "nvda"
ticker = user_input.upper()
print(ticker)
print(user_input)
NVDA
nvda
  • Company names in data feeds and regulatory filings are often in all capitals. title() capitalizes the first letter of each word and lowercases the rest; lower() lowercases everything.

Note: title() applies the same rule to every word, so names with a capital letter inside a word come out wrong, as with JPMorgan on the last line below.

company = "EXXON MOBIL CORP"
print(company.title())
print(company.lower())
print("JPMORGAN CHASE & CO".title())
Exxon Mobil Corp
exxon mobil corp
Jpmorgan Chase & Co

Escape Sequences: \n and \t

  • A backslash inside a string starts an escape sequence, a short code for a character that is awkward to type:

    • \n starts a new line.
    • \t inserts a tab, which lines text up in columns.
  • Together they can lay out a small table. Many data files are organized the same way: one record per line, with a tab or a comma between fields.

print("Ticker\tPrice\nAAPL\t189.50\nKO\t62.15")
Ticker	Price
AAPL	189.50
KO	62.15

Trimming Stray Spaces

  • Text copied from spreadsheets, websites, or forms often has extra spaces, and " MSFT " does not match "MSFT". A lookup that should succeed can then fail because of characters you cannot see.

  • strip() removes whitespace (spaces, tabs, and line breaks) from both ends of a string; lstrip() and rstrip() remove it from the left or the right end only. The square brackets below mark where each result begins and ends:

raw_ticker = "   MSFT  "
print(f"[{raw_ticker.lstrip()}]")
print(f"[{raw_ticker.rstrip()}]")
print(f"[{raw_ticker.strip()}]")
[MSFT  ]
[   MSFT]
[MSFT]

Removing and Replacing Text

  • Tickers often have extra codes attached: an exchange prefix such as NASDAQ:, or a market suffix such as .TO (the Toronto Stock Exchange). removeprefix() and removesuffix() remove that text from the start or end of a string, and return the string unchanged if the text is not there.

  • replace(old, new) replaces every occurrence of old with new. For example, data vendors write share classes differently: Berkshire Hathaway's Class B shares appear as BRK.B in some sources and BRK-B in others.

print("NASDAQ:AAPL".removeprefix("NASDAQ:"))
print("RY.TO".removesuffix(".TO"))
print("BRK.B".replace(".", "-"))
AAPL
RY
BRK-B

Chaining Methods

  • Each method above returns a new string, so you can call another string method directly on the result. The calls run from left to right.

  • The cell below cleans a messy ticker in one line. upper() has to come before removeprefix("NASDAQ:"), because the raw text has the prefix in lowercase.

  • Python has many more string methods; the official documentation lists them all.

raw = "  nasdaq:aapl "
ticker = raw.strip().upper().removeprefix("NASDAQ:")
print(ticker)
AAPL

Numbers: Integers and Floats

  • An integer (int) is a whole number, such as a share count or the number of trading days in a year.

  • A float (floating-point number) can have a fractional part. Prices, interest rates, and returns are stored as floats.

  • The built-in function type() returns a value's type. Multiplying a share count (an integer) by a price (a float) gives a float:

shares = 150
price = 42.75
position_value = shares * price
print(type(shares))
print(type(price))
print(type(position_value))
print(position_value)
<class 'int'>
<class 'float'>
<class 'float'>
6412.5

Arithmetic and Order of Operations

  • Python's arithmetic operators:

    • +, -, *, / for addition, subtraction, multiplication, and division
    • ** for powers
    • // for floor division (divide, then round down to a whole number) and % for the remainder
  • Python applies ** first, then *, /, //, and %, then + and -. Parentheses override this order.

  • Parentheses matter in compounding formulas. The 10-year growth factor at 5% per year is (1 + 0.05) ** 10; without the parentheses, only 0.05 is raised to the 10th power:

print((1 + 0.05) ** 10)
print(1 + 0.05 ** 10)
print(1000 * (1 + 0.05) ** 10)
1.628894626777442
1.0000000000000977
1628.894626777442
  • With the parentheses, a deposit of 1,000 grows to about 1,629 over 10 years; without them, the growth factor is essentially 1.

  • // gives the number of whole units that fit, and % gives what is left over. A round lot is traditionally 100 shares, so an order for 1,250 shares is 12 round lots plus an odd lot of 50 shares.

  • / always returns a float, even when there is no remainder (last line below).

order_size = 1250
print(order_size // 100)
print(order_size % 100)
print(1200 / 100)
12
50
12.0

Floats Are Approximations

  • Floats are stored in binary, and most decimal fractions (0.1, 0.05, 99.95) have no exact binary form, so float arithmetic can be off in the last few digits.

  • Below, a 10-cent bid-ask spread comes out slightly below 0.1. round(x, n) rounds x to n decimal places.

  • For analysis, errors this small are harmless. Keep full precision in calculations and round only what you display; f-string formatting, covered below, does the rounding for you.

Note: Where every cent must reconcile exactly, as in accounting or order matching, use the standard-library decimal module, which does exact decimal arithmetic.

bid = 99.95
ask = 100.05
spread = ask - bid
print(spread)
print(round(spread, 2))
0.09999999999999432
0.1

Readable Large Numbers

  • Large figures such as market capitalizations are hard to read as a long run of digits. In code, you can group the digits with underscores, as in 2_950_000_000_000 (2.95 trillion).

  • The underscores appear only in your code. Python stores the plain number, and printing it shows no separators. For thousands separators in output, use an f-string format (covered below).

market_cap = 2_950_000_000_000
shares_outstanding = 15_200_000_000
implied_price = market_cap / shares_outstanding
print(market_cap)
print(implied_price)
2950000000000
194.07894736842104

Assigning Several Variables at Once

  • Python can assign several variables in one statement: open_price, close = 101.25, 103.00 gives open_price the first value and close the second. The two sides must have the same number of items, or Python raises an error.

  • Use this for values that come as a set, such as a trading day's open, high, low, and close (OHLC) prices. Below, we compute the day's range (high minus low) and its open-to-close change.

  • We write open_price rather than open because open is already the name of a built-in function, which opens files.

open_price, high, low, close = 101.25, 103.75, 100.50, 103.00
print(high - low)
print(close - open_price)
3.25
1.75

Constants

  • Some numbers are fixed assumptions, such as 252 trading days per year, 12 months per year, or a tax rate. Give such a number an all-caps name and assign it once, near the top of your code.

  • The capitals mark the value as a constant, which the rest of the program should read but never reassign. Python does not enforce this; it is a PEP 8 convention.

  • A name such as TRADING_DAYS_PER_YEAR also tells the reader what the number means, which a bare 252 does not. The cell below annualizes a daily volatility of 1.2% with the square-root-of-time rule (** 0.5 takes a square root):

TRADING_DAYS_PER_YEAR = 252

daily_vol = 0.012
annual_vol = daily_vol * TRADING_DAYS_PER_YEAR ** 0.5
print(annual_vol)
0.19049409439665055

Mixing Text and Numbers

  • + adds two numbers or joins two strings. Given a string and a number, Python does not convert either one; it raises a TypeError, the error for an operation applied to a value of the wrong type:
# This will fail: `+` cannot join a string and a float
price = 62.15
print("KO last traded at " + price)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[21], line 3
      1 # This will fail: `+` cannot join a string and a float
      2 price = 62.15
----> 3 print("KO last traded at " + price)

TypeError: can only concatenate str (not "float") to str
  • There are two fixes: convert the number to a string with str(), or use an f-string, which converts it for you.

  • Conversion also works the other way. Numbers read from a file or typed by a user arrive as strings; float() and int() turn them into numbers you can calculate with.

print("KO last traded at " + str(price))
print(f"KO last traded at {price}")

price_text = "62.15"
shares_text = "200"
print(float(price_text) * int(shares_text))
KO last traded at 62.15
KO last traded at 62.15
12430.0

Formatting Numbers in f-Strings

  • Inside an f-string's braces, a colon followed by a format specification controls how a number is displayed:

    • {x:.2f}: 2 decimal places, for prices
    • {x:,.2f}: thousands separators and 2 decimals, for dollar amounts
    • {x:,}: thousands separators, for large whole numbers
    • {x:.2%}: multiplied by 100 and followed by a percent sign, for returns and rates
  • Formatting changes only how a number is displayed; the stored value stays the same. The braces can also hold a calculation, like the open-to-close return below. The dollar signs in the code are ordinary text; only the braces are special.

  • The cell below prints numbers computed earlier in this chapter with these formats:

print(f"Position value: ${position_value:,.2f}")
print(f"Implied share price: ${implied_price:.2f}")
print(f"Market cap: ${market_cap:,}")
print(f"Open-to-close return: {close / open_price - 1:.2%}")
print(f"Annualized volatility: {annual_vol:.1%}")
Position value: $6,412.50
Implied share price: $194.08
Market cap: $2,950,000,000,000
Open-to-close return: 1.73%
Annualized volatility: 19.0%

Comments

  • Text after a # symbol, up to the end of the line, is a comment. Python ignores it; comments are written for people reading the code.

  • A comment can be on its own line or at the end of a line of code. PEP 8 asks for at least two spaces before an inline #:

# Coupon payment on a bond that pays interest twice a year
face_value = 1_000     # principal repaid at maturity
coupon_rate = 0.045    # annual rate, paid in two equal halves
coupon_payment = face_value * coupon_rate / 2
print(f"Each coupon payment: ${coupon_payment:.2f}")
Each coupon payment: $22.50

Writing Useful Comments

  • A good comment gives information the code cannot: units, assumptions, data sources, and the reason for a choice.

    • Weak: fee = 4.95 # set fee to 4.95 only repeats the code.
    • Useful: fee = 4.95 # flat commission per trade, USD says what the number is.
  • In research code, comments help make the work reproducible: a coauthor or referee should be able to see where each number comes from without asking you.

  • To switch off a line without deleting it, put # in front of it ("comment it out"). In Colab, Ctrl + / (Cmd + / on a Mac) comments or uncomments the selected lines.

In-Class Exercise

2-1. Clean a Ticker:

  • Assign the messy string " nyse:brk.b " to a variable.
  • Use string methods to turn it into BRK-B, and print the result.

2-2. Report Header:

  • A data feed gives you company = "ALPHABET INC", ticker = "googl", and exchange = "nasdaq".
  • Using a single f-string, print Alphabet Inc (NASDAQ: GOOGL).
  • Hint: the braces of an f-string can hold any expression, including a method call.

2-3. Position Report:

  • Store a ticker, a share count, a purchase price, and a current price in variables (made-up values are fine).
  • Compute the position's current value, its dollar gain, and its percentage return.
  • Print a three-line report: value and gain with thousands separators and 2 decimals, and the return as a percentage with 2 decimals.

2-4. Compound Growth:

  • Store an annual interest rate of 4% in a constant ANNUAL_RATE, and a deposit of 10,000 in a variable (write the number as 10_000).
  • Compute the deposit's value after 30 years with annual compounding, and again with monthly compounding (ANNUAL_RATE / 12 per month for 12 * 30 months).
  • Print both values with 2 decimals, and add a comment noting which is larger and why.

Ch 3: Introducing Lists

  • So far each variable has held one value. A portfolio holds many stocks, and a price history has many observations.

  • A list stores many values under one name, in the order you give them. The NumPy arrays and pandas tables in Lectures 6-9 are often created from lists.

Creating a List

  • To create a list, write its items inside square brackets [] with commas between them.

  • The cell below creates a watchlist of five tickers and a list of five daily closing prices for one stock, oldest first.

watchlist = ["AAPL", "MSFT", "NVDA", "AMZN", "JPM"]
closes = [101.25, 102.80, 101.95, 104.30, 105.10]
print(watchlist)
print(closes)
['AAPL', 'MSFT', 'NVDA', 'AMZN', 'JPM']
[101.25, 102.8, 101.95, 104.3, 105.1]
  • print() shows a list the way you would type it, with brackets, commas, and quotes around strings. Floats are printed without trailing zeros: 102.80 and 102.8 are the same number.

  • The string method split() cuts text into a list at each occurrence of a separator. With "," as the separator, it turns a line of comma-separated data into a list:

line = "XOM,CVX,COP"
energy_tickers = line.split(",")
print(energy_tickers)
['XOM', 'CVX', 'COP']

Reading Items by Position

  • Each item has a numbered position, its index. Square brackets right after a list's name select one item: watchlist[0] means "the item at index 0 of watchlist".

  • Python counts from 0: the first item is at index 0, the second at index 1, and the n-th at index n - 1.

  • Indexing returns the item itself, so watchlist[0] can be used exactly like the string "AAPL":

first = watchlist[0]
print(first)
print(watchlist[2])
print(f"{first} heads the watchlist; {watchlist[1]} is next.")
AAPL
NVDA
AAPL heads the watchlist; MSFT is next.

Negative Indexes

  • Negative indexes count from the end of the list: -1 is the last item and -2 the second to last.

  • In a price list ordered from oldest to newest, closes[-1] is the most recent close and closes[-2] the one before it. Both stay correct as each new day's close is appended. The cell below prints the latest close, the latest daily return, and the return since the first close:

latest = closes[-1]
daily_return = closes[-1] / closes[-2] - 1
period_return = closes[-1] / closes[0] - 1
print(f"Latest close: {latest:.2f}")
print(f"Latest daily return: {daily_return:.2%}")
print(f"Return since the first close: {period_return:.2%}")
Latest close: 105.10
Latest daily return: 0.77%
Return since the first close: 3.80%

Updating a List

  • Lists are mutable: unlike strings, they can be changed in place. This makes them suitable for data that changes over time, such as the holdings in an account or a price history that grows every day.

  • To replace an item, assign a new value to its index. For example, in 2022 Meta Platforms (formerly Facebook) changed its ticker from FB to META:

holdings = ["AAPL", "FB", "JPM"]
holdings[1] = "META"
print(holdings)
['AAPL', 'META', 'JPM']

Adding Items: append() and insert()

  • append() adds an item to the end of a list.

  • insert(index, item) places a new item at index; the items from that position on each move up one index.

holdings.append("XOM")
print(holdings)

holdings.insert(0, "KO")
print(holdings)
['AAPL', 'META', 'JPM', 'XOM']
['KO', 'AAPL', 'META', 'JPM', 'XOM']
  • To collect data as it arrives, start with an empty list, [], and append() each new value. Below, a large buy order is filled in three parts at slightly different prices:
fill_prices = []
fill_prices.append(187.20)
fill_prices.append(187.35)
fill_prices.append(187.10)
print(fill_prices)
[187.2, 187.35, 187.1]

Removing Items: del, pop(), and remove()

  • Python has three ways to remove an item, depending on how you identify it:

    • By position: del holdings[i].
    • By position, keeping the item: holdings.pop(i) removes the item at index i and returns it, so you can store it, for example to log the sale. With no index, pop() removes the last item.
    • By value: holdings.remove("JPM") removes that ticker wherever it is in the list.
  • Below, we sell the stock at index 1 with del, then sell the last stock in the list with pop():

del holdings[1]
print(holdings)

sold = holdings.pop()
print(f"Sold {sold}. Holdings: {holdings}")
['KO', 'META', 'JPM', 'XOM']
Sold XOM. Holdings: ['KO', 'META', 'JPM']
  • With pop(0), a list works as a first-in, first-out queue, like orders that are processed in the order they arrived:
pending_orders = ["BUY 100 KO", "SELL 50 JPM", "BUY 25 MSFT"]
next_order = pending_orders.pop(0)
print(f"Processing: {next_order}")
print(f"Still pending: {pending_orders}")
Processing: BUY 100 KO
Still pending: ['SELL 50 JPM', 'BUY 25 MSFT']
  • remove() finds the item by value, so you do not need to know its position, which changes as you buy and sell.

Note: remove() deletes only the first matching item, as the second list below shows, and raises a ValueError if the item is not in the list.

holdings.remove("META")
print(holdings)

draft = ["KO", "JPM", "KO"]  # KO entered twice by mistake
draft.remove("KO")
print(draft)
['KO', 'JPM']
['JPM', 'KO']

Sorting, Reversing, and Counting

sort(): Reorder the List Itself

  • sort() rearranges the list itself, or in place: strings alphabetically, numbers from smallest to largest. The old order is not kept. For descending order, write reverse=True inside the parentheses.

Note: sort() changes the list and returns None, Python's "no value". Writing tickers = tickers.sort() therefore replaces your list with None.

tickers = ["NVDA", "KO", "AMZN", "XOM", "JPM"]
tickers.sort()
print(tickers)

tickers.sort(reverse=True)
print(tickers)
['AMZN', 'JPM', 'KO', 'NVDA', 'XOM']
['XOM', 'NVDA', 'KO', 'JPM', 'AMZN']

sorted(): Get a Sorted Copy

  • The built-in function sorted() returns a new, sorted list and leaves the original unchanged. Use it when the existing order carries information. Below, the returns are in calendar order, oldest year first, and we want to keep that order:
annual_returns = [0.12, -0.08, 0.21, 0.05, -0.15]
print(sorted(annual_returns))
print(sorted(annual_returns, reverse=True))
print(annual_returns)
[-0.15, -0.08, 0.05, 0.12, 0.21]
[0.21, 0.12, 0.05, -0.08, -0.15]
[0.12, -0.08, 0.21, 0.05, -0.15]

Note: Strings sort by character code, and every uppercase letter comes before every lowercase letter. A lowercase ticker therefore sorts after all the uppercase ones, so convert tickers to uppercase with upper() before sorting:

print(sorted(["aapl", "KO", "MSFT"]))
['KO', 'MSFT', 'aapl']

reverse(): Flip the Order

  • reverse() reverses the order of a list in place, without comparing the values.

  • Some data sources deliver price histories newest first. One call to reverse() puts them in chronological order, which return calculations expect. The result matches closes from earlier:

price_history = [105.10, 104.30, 101.95, 102.80, 101.25]  # newest first
price_history.reverse()
print(price_history)
[101.25, 102.8, 101.95, 104.3, 105.1]

len(): Count the Items

  • The built-in function len() returns the number of items in a list. For example, an equal-weighted portfolio of N stocks puts 1/N of its money in each:
n_stocks = len(watchlist)
weight = 1 / n_stocks
print(f"{n_stocks} stocks, {weight:.0%} in each")
5 stocks, 20% in each

When an Index Is Out of Range

  • A list of length n has valid indexes 0 to n - 1 counting from the front, and -1 to -n counting from the back. Any other index raises an IndexError.

  • In finance code, this often happens with a lookback that reaches further into the past than the data goes. A 5-day return compares the latest close with the close five trading days earlier, which requires 6 closes; closes has only 5.

# This will fail: a 5-day return needs 6 closes, but `closes` holds only 5
five_day_return = closes[-1] / closes[-6] - 1
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[40], line 2
      1 # This will fail: a 5-day return needs 6 closes, but `closes` holds only 5
----> 2 five_day_return = closes[-1] / closes[-6] - 1

IndexError: list index out of range
  • With n closes, you can look back at most n - 1 days from the latest one: here 4 days, to closes[-5], which is the same item as closes[0].

  • Check the list's length with len() before looking far back. In Lecture 2, if statements will let your code make that check itself and skip a calculation the data cannot support.

In-Class Exercise

3-1. Watchlist Basics:

  • Create a list of five tickers you would like to follow.
  • Print the first, third, and last tickers, using a negative index for the last one.
  • Print a sentence that uses one of the tickers in an f-string.

3-2. Price History:

  • Create a list of six daily closing prices, oldest first (made-up values are fine).
  • Compute the 5-day return (the latest close against the close five days earlier) and the most recent one-day return.
  • Print both as percentages with 2 decimals.

3-3. Trading Day:

  • Start from portfolio = ["AAPL", "KO", "JPM"], and print the list after each step.
  • Buy "MSFT" (add it at the end) and "XOM" (add it at the front).
  • Sell "KO" by value, then sell the last holding with pop() and print a message naming the stock you sold.

3-4. Ranking Returns:

  • Store five annual returns, as decimals, in a list.
  • Print them from best to worst without changing the original list, then print the original to confirm it is unchanged.
  • Use len() to print how many years of data you have, then sort the original list in place and print it.