Programming
Buisness Analytics
Table of Contents
Focus on understanding the Ideas. Your understanding of the Syntax will develop with time & practice
Python
- Python is one way we can use a computer to perform certain tasks
- For example, say we wanted to know the following:
- Hopefully it is faster for us to do this in our head!
- Python code is a series of steps that the computer executes (quote: LYAH)
- Let's say that we wanted to know what the marginal value of an additional dollar saved was in four years times if compounded monthly at an annual 8% rate?
Do not worry about understanding what this code does for the moment!
- Or let's say we want to understand how this varies with the underlying interest rate?
Still don't worry about understanding what this code does for the moment!
Takeaways
(1) We can use Python to Solve Problems
(2) Via Python, we can use other peoples' work to solve our problems
- We don't have to write code to differentiate a function! We can rely on the smart folks at Google who have done this for us
(3) Via Python, we can solve a problem by
- Splitting the solution into components
- Writing code/ using other people's code for each component
- "Re-stacking" these components
Variables
Creating Variables
first_name = 'Lebron'
last_name = 'James'
print(first_name + ' ' + last_name)
a = 5
b = 10
print(a + b)
- The '=' is used to assign a variable to a value
Integers
String (text!)
Creating Variables
- Variables are mutable -- meaning that we can assign a variable to another value
a = 5
b = 10
a = 25
print(a + b)
Integers
first_name = 'Lebron'
last_name = 'James'
first_name = 'Bronny'
print(first_name + ' ' + last_name)
String (text!)
Deep Dive
What happens when we do the following?
a = 5
import sys
a = 10
memory_location = id(a)
size_in_bytes = sys.getsizeof(a)
print(f"Memory location of a: {memory_location}")
print(f"Size of a: {size_in_bytes} bytes")
a
Memory
What happens when we do the following?
a = 5
b = 5
a = 5
b = 5
print(f"Memory location of a: {id(a)}")
print(f"Memory location of b: {id(b)}")
print(a is b)
print(a == b)
a
Memory
b
What happens when we do the following?
a = 257
b = 257
a = 257
b = 257
print(f"Memory location of a: {id(a)}")
print(f"Memory location of b: {id(b)}")
print(a is b)
print(a==b)
a
Memory
b
What happens when we do the following?
a = 257
b = a
a = 10
a
Memory
a = 257
a = 257
b = a
a
Memory
a
Memory
b
a = 257
b = a
a = 257
b = a
a = 10
a
Memory
b
a
Memory
b
Functions
Defining/Creating a Function
def f(x):
return x**2
(1) The `def' keyword tells us that we are defining a function
(2) `f' is the name of the function
(3) `x' is a placeholder for the input to the function
(4) The `:' indicates the beginning of a code block (in this context)
(5) The `return' keyword indicates what the function will return
- The key word is knows. That's literally it. You may be initially surprised when you execute the code block that nothing else happens. But in Python's defense, you haven't told it to do anything else
def f(x):
return x**2
- When you write and then execute the following block of code, Python knows that a function named `f' exists, and it knows that given an input, it will attempt to square that input
- There are really only two steps to working with a function
Working With Functions
- We have to define the function. We have to tell python about the function: give it a name, express how the input(s) get transformed.
def f(x):
return x**2
- We have to call the function. Calling a function on a given input will produce the output
x = 2
f(x)
>> 4
Deep Dive
- Mathematical Functions transform "data"
What Do Mathematical Functions Do?
- Given an x, it returns the corresponding y
Domain
Codomain
- Functions transform "data"
Functions on the Computer
- Given an x, it may (1) change the state of the system and (2) may return a value or None (3) may return a different value each time it's called
Domain
Codomain
Example # 1
def greeting(name):
print("Hello " + name)
a = greeting('Bob')
print(a)
- It changes the state of the system by printing a response
- It returns `None'
Example # 2
def random_wage(avg_wage):
return avg_wage * (1 + np.random.normal(0, 0.1))
a = random_wage(10)
b = random_wage(10)
print(a)
print(b)
- It returns a different value for the same input each time you call it
Example # 3
a = 10
def greeting(name):
global a
a = 20
print("Hello " + name)
print(a)
greeting("Bob")
print(a)
- It changes the state of the system by (1) changing the value of `a' and (2) printing a response
For Loops
Let's Say We Have the Following Code
my_list = [0, 1, 2, 3, 4, 5]
def f(x):
return x**2
Task:
Print the square of each element in this list
Naive Approach
my_list = [0, 1, 2, 3, 4, 5]
def f(x):
return x**2
print(f(my_list[0]))
print(f(my_list[1]))
print(f(my_list[2]))
print(f(my_list[3]))
print(f(my_list[4]))
print(f(my_list[5]))
Redundant!
- We are calling the same "pair" of functions 6 times
- The only thing that changes between functions calls is the input!
Indexing
For Loop #1
def f(x):
return x**2
my_list = [0, 1, 2, 3, 4, 5]
for i in my_list:
print(f(i))
"Easier" to write & read!
- It tells us that for each element of `my_list', apply `f' to that element and print the result
i = 0
print(f(i))
>> 0
i = 1
print(f(i))
>> 1
i = 2
print(f(i))
>> 4
i = 3
print(f(i))
>> 9
i = 4
print(f(i))
>> 16
i = 5
print(f(i))
>> 25
Python
For Loop #2
def f(x):
return x**2
my_list = [0, 1, 2, 3, 4, 5]
my_list_squared = []
for i in my_list:
my_list_squared.append(f(i))
Create empty list
For each element of `my_list`, apply `f` to the element and then include the result as the last element of `my_list_squared`
For Loop #3
In Class Exercise: Given a list, print the square of only the even numbers
my_list = [0, 1, 2, 3, 4, 5]
def f(x):
return x**2
for i in my_list:
if i % 2 == 0:
print(f(i))
For Loop #4
In Class Exercise: Given a list, print the square of the even numbers and the cube of the odd numbers
my_list = [0, 1, 2, 3, 4, 5]
def f(x):
return x**2
def g(x):
return x**3
for i in my_list:
if i % 2 == 0:
print(f(i))
else:
print(g(i))
For Loop #5
In Class Exercise: Given a list (could be a list of integers and/or strings), if it is an even number: print the square, if it is an odd number: print the cube, and if it is a string: print '!'
def f(x):
return x**2
def g(x):
return x**3
my_list = ["a", 1, 0, "b", 27, 9]
for x in my_list:
if type(x) == str:
print("!")
elif x % 2 == 0:
print(f(x))
elif x % 2 == 1:
print(g(x))
For Loop #6
In Class Exercise: Given a list of strings find the first element which begins with the letter 'a'
my_list = ['car', 'boat', 'airplane', 'truck']
for i in my_list:
if i[0] == 'a':
print(i)
break
Data Types
In Class Exercise: The following code doesn't work. Explain why
def f(x):
return x**2
def g(x):
return x**3
my_list = ["a", 1, 0, "b", 27, 9]
for x in my_list:
if x % 2 == 0:
print(f(x))
elif x % 2 == 1:
print(g(x))
else:
print("!")
Original Code
def f(x):
return x**2
def g(x):
return x**3
my_list = ["a", 1, 0, "b", 27, 9]
for x in my_list:
if type(x) == str:
print("!")
elif x % 2 == 0:
print(f(x))
elif x % 2 == 1:
print(g(x))
Adjusted Code
Data Types
- A data type is a set of values
Integer (Int)
a = 1
b = 10
c = -8
String
a = 'Lebron'
b = 'Bronny'
c = 'James'
Float
a = 1.0
b = 10.2
c = -8.7
Boolean (Bool)
a = True
b = False
Function
Same Function, Different Types
Data Types
1 + 2
Int
1.4 + 2.7
Float
True + False
>> 1
Bool
'Lebron ' + 'James'
String
Data Types
Int
Float
Bool
String
def add_one(x):
return x + 1
In Class Exercise: Write a function that adds one to the input
Errors
Data Types
Int
Float
Bool
String
def add_one(x : int) -> int:
return x + 1
We can use Type Hints to inform the user (our future selves) of the type of inputs that our function takes and the type of output it produces
Input Type
Output Type
Data Types
Int
Float
Bool
String
In Class Exercise: Using type hints, write a function that takes an integer and a string as inputs and prints the string the number of times that the integer specifies. Include spaces!
def repeat_string(x : int, y : str) -> None:
print((y + ' ')*x)
Type Casting
Int
Float
int(2.0)
Int
Float
float(25)
import jax
def f(x):
return x**2
jax.grad(f)(1)
Type Error
import jax
def f(x):
return x**2
jax.grad(f)(float(1))
Type Casting
Type Casting
Int
Bool
int(True)
String
Float
float('25')
Infix Functions
'Lebron ' > 'Bronny'
(-1 < 2) & (2 >= 3)
(-1 < 2) | (2 >= 3)
(-1 < 2) or ('String'/2)
(-1 < 2) and (2 >= 3)
Conditionals
Conditionals
- There are multiple instance throughout our day when what we do next depends on something in the current moment
- If it's cold in the morning, we will wear a sweatshirt, but if it's warm then we won't
- If we have homework due tonight, we'll go to the library. If not, we'll hang out with friends
Examples
- There's almost an 'If/Else' pattern that jumps out from these examples!
Conditionals
- We'll want to be able to mimic the same type of behavior in our code.
- If a certain condition is True, then we'll want to execute one block of code
- But if a condition is not True, then we'll want to execute a different block of code
- To make things concrete, let's tackle the following example
print("You won the lottery!")
print("Try again!")
Check if their ticket matches the drawn number
def lottery(ticket, drawn_numbers):
Let's say we want to create a function that captures the following idea
Match
Didn't Match
Example
The New Part
We can express this in Python
if condition:
print("You won the lottery!")
else:
print("Try again!")
We can express this in Python
What should the condition be?
ticket == drawn_number
Evaluates to either True or False
Check if their ticket matches the drawn number
Putting it All Together
print("You won the lottery!")
print("Try again!")
Check if their ticket matches the drawn number
def(ticket, drawn_numbers):
Match
Didn't Match
def lottery(ticket, drawn_number):
if ticket == drawn_number:
print("You won the lottery")
else:
print("Try again!")
my_ticket = 4
wed_draw = 4
lottery(my_ticket, wed_draw)
print("You won the lottery!")
if 4 == 4:
lottery(4, 4)
Walk Through
my_ticket = 8
wed_draw = 3
lottery(my_ticket, wed_draw)
print("Try again!")
if 8 == 3:
lottery(8, 3)
else:
Walk Through
Let's say though that given the score in soccer, we want to report which team won
Motivation
home_score > away_score
home_score == away_score
print("The Home team won!")
Compare the home_score to the away_score
def game(home_score, away_score):
print("Tie!")
print("The Away team won!")
home_score < away_score
If Condition
elif Condition
else Condition
def game(home_score, away_score):
if home_score > away_score:
print("The Home Team Won!")
elif home_score < away_score:
print("The Away Team Won")
else:
print("A Tie!")
Putting it All Together
h_score = 3
a_score = 4
game(h_score, a_score)
print("The Home Team Won!")
if 4 > 3:
game(4, 3)
Walk Through
h_score = 1
a_score = 2
game(h_score, a_score)
print("The Away Team Won!")
if 1 > 2:
game(1, 2)
Walk Through
elif 1 < 2:
h_score = 2
a_score = 2
game(h_score, a_score)
print("The Away Team Won!")
if 2 > 2:
game(2, 2)
Walk Through
elif 2 < 2:
else:
Fun Example
Analyst
Associate
Vice President
Managing Director
Partner
Global Head of Cardboard Packaging Investment Banking
Titles
Americas Head of Exotic Volatility Trading in Stocks Starting with ‘P’
Global head of "whatever the weird trad was"
Head of Macro
- There are a lot of times where what we would like to do next depends on the current context
- As a fun example, let's say we worked at Greenlight Capital Inc. with James Fishback. And more specifically we were introducing him to some other person.
- If that other person also worked at GreenLight Capital Inc. then we would want to introduce James by his role: Research Analyst
- If the other person was a client, then we would want to introduce James as "Head of Macro" (as Matt Levine say, so that everyone is Happy!)
- Via conditionals, we can express this idea in Python
if other_person == 'colleague':
print("This is James, a Research Analyst")
else:
print("This is James, Head of Macro")
Head of Macro
(1) `if' keyword signifies that the following is a conditional
(2) `==' is an infix function that returns True or False
(3) `:' denotes that the following will be an indented line code block
(4) `else:' says run this code block if the first condition was False
Options
if (option == 'call') & (strike_price < stock_price):
profit = stock_price - strike_price - payment
elif (option == 'put') & (strike_price > stock_price):
profit = strike_price - stock_price - payment
else:
profit = - payment
Lists
Lists
companies = ["Microsoft", "GE", "Intel"]
- A list is an order set of elements
- We can create a list in Python using square brackets and separating the elements in the list by commas
Append
companies.append("Uber")
print(companies) # Output: ["Microsoft", "GE", "Intel", "Uber"]
- We can add elements to the end of a list using the `append` function
Consider
What happens if you were to execute this code multiple times in a row?
Index
- We can also select elements from a list as follows
a = companies[2]
print(a) # Output: 'Intel'
- Python does Zero-based indexing which means:
print(companies[0]) # Output: 'Microsoft'
Index
- We can also select elements by referencing their relative position from the end of the list
companies = ["Microsoft", "GE", "Intel","Uber"]
print(companies[-3]) # Output: 'GE'
Slicing
- We can select multiple elements from a list by specifying the position that we would like to slice from, a colon, and the position that we would like to slice up to, but not include
print(companies[1:3]) # Output: ['GE', 'Intel']
- The `1` says to select elements from the list starting from the 1st position
- The `3` says to select the elements up to, but not including the 3rd position
Slicing
- When slicing a list we can omit either of the numbers
print(companies[:2]) # Output: ['Microsoft', GE']
print(companies[0:2]) # Output: ['Microsoft', GE']
- To select the first two elements from a list
print(companies[-3:]) # Output: ['GE', 'Intel', 'Uber']
print(companies[-3:len(companies)]) # Output: ['GE', 'Intel', 'Uber']
- To select the last three elements from a list
Check Your Understanding
#2 Create the same slice of the list using only negative integers
companies[:2]
#1 Create the same slice of the list using only positive integers
companies[-3:]
Lists of Lists
- We can create lists in Python where each element is a list
companies = ['Apple', 'Microsoft', 'Google', 'Amazon', 'Facebook', 'Tesla', 'IBM', 'Netflix', 'Samsung', 'Intel']
current_thoughts = [companies[:3], [companies[4], companies[7]], companies[8:]]
Wouldn't it be great to have labels associated with each inner list?
Check Your Understanding
True/False
companies[0] == companies[:1]
Extending
m_2000.extend(['BP', 'Royal Dutch Shell', 'IBM'])
Remove by Value
m_2000.remove('BP')
Remove by Index
m_2000.pop(2)
>> cisco
Checking Membership
'uber' in m_2000
>> False
Lists
m_2000.sort()
Sorting
Length
len(m_2000)
>> 7
Comparing Lists
[3, 4, 3] < [3, 4, 4]
>> True
Dictionary
Dictionaries
- A dictionary is an ordered set of `key:value` pairs
- We can create a dictionary in Python using curly brackets and separating the elements by commas
current_thoughts = {'prioritize' :companies[:3],
'wait_to_apply': [companies[4], companies[7]],
'ignore': companies[8:]}
Adding Elements to a Dictionary
current_thoughts['research_more'] = companies[1:4]
- We can add elements to a dictionary by indexing the dictionary a new key and assigning it a value/list
Consider
What happens if you were to execute this code multiple times in a row?
Worked Example
People Learn Differently
Want to learn about each function associated with Lists in Python before using them!
Will learn the relevant functions associated with Lists as they arise in real world coding problems
Our Approach
Understanding
- You don't need to understand every detail in every line of the Python code
- We want to understand the Structure of the Code
- How do the lines of code relate to each other
- Why is the code written in one way vs another way
Worked Example
Note some of the quotes and exercises are adopted from
Which is not a book about Python