Lists and Dictionaries
In this chapter, we are delving into two fundamental data structures in Python: lists and dictionaries. These structures will allow you to store and manage data more efficiently within your programs. They prove to be especially useful when dealing with financial data, such as price time series, asset portfolios, or customer information.
Lists in Python
Alright, let us talk about lists. They are like the toolboxes of Python; you can keep multiple items in them. Think of lists as a series of boxes where you can store different values.
Creating a list
Here is how to create a list containing textual values:
assets = ["stocks", "bonds", "real estate", "cash"]
print(assets)
This list contains four elements: all are strings.
Accessing list elements
To access an element from a list, use the element's index in square brackets. Indices in Python start at 0 for the first element. You can also access elements from the end of the list using negative indices. Try it out with this example:
assets = ["stocks", "bonds", "real estate", "cash"]
print(assets[0]) # Displays "stocks"
print(assets[2]) # Displays "real estate"
print(assets[-1]) # Displays "cash"
Modifying list elements
Lists are mutable, which means you can change the value of an element using its index. For instance:
assets = ["stocks", "bonds", "real estate", "cash"]
assets[-2] = 15 # You can have a list with different types inside
print(assets) # Displays ["stocks", "bonds", 15, "cash"]
Adding and removing list elements
To add an element to the end of a list, use the append()
method:
assets = ["stocks", "bonds", "real estate", "cash"]
assets.append("commodities") # Adds "commodities" to the end of the list
To insert an element at a specific position, use the insert()
method. Provide the index (the index of an item in a list is somewhat like its ranking. In the 'assets' list, "stocks" is at index 0) and the value:
assets.insert(1, "ETFs") # Inserts "ETFs" at position 1 (the second element)
To remove an element from a list, use the remove()
method and provide the value of the element:
assets.remove("cash") # Removes "cash" from the list
To remove an element at a specific index, you can use the del
function:
del assets[0] # Removes the first element from the list
Feel free to experiment using print()
to observe the changes.
Navigating a list with loops
As mentioned earlier, loops are a superb method for iterating through and working with lists. for
loops can be used to traverse a list's items and conduct operations on each element. Here are a few scenarios where loops are used to navigate a list:
Example 1: displaying every element in a list
assets = ["stocks", "bonds", "real estate", "cash"]
for asset in assets:
print(asset)
In this instance, the for
loop cycles through each element in the assets
list, storing the current item in the asset
variable at each iteration. The print()
function is then invoked to show the asset
value.
Example 2: implementing an operation on all list elements
Let us assume we have a list of stock prices and want to calculate the return on each one. Here is how we can achieve that using a for
loop:
prices = [100, 120, 80, 150]
returns = [] # Starting with an empty list that we'll add elements to
for price in prices:
returns.append(price * 1.1) # Computes the return following a 10% increase
print(returns)
In this case, we have a prices
list containing various stock prices. We also create an empty returns
list to hold our results. The for
loop cycles through the prices
list, calculating a 10% return on each price and appending the result to the returns
list. By the end, the returns
list will contain the calculated returns for each stock.
Example 3: Iterating Through a List Using range()
and len()
The len()
function provides the length (i.e., the number of elements) of an iterable object, like a list. You can use this in combination with the range()
function to iterate over a list by element index:
assets = ["stocks", "bonds", "real estate", "cash"]
print(len(assets)) # Outputs 4
for i in range(len(assets)):
print("Index", i, ":", assets[i])
In this illustration, len(assets)
returns 4, since there are four elements in the assets
list. range(len(assets))
then generates a sequence of indices from 0 to 3, inclusive.
The for
loop then traverses these indices, using i
to access the corresponding element in the assets
list. The print()
function is used to display both the index and value of each element.
This technique is particularly useful when you need to access list elements via their index or need to alter list elements while iterating through the list.
Understanding Python Dictionaries
A dictionary in Python is an unordered, mutable, and indexed collection of items. Unlike lists, dictionaries use keys to access items rather than indices. Dictionaries are particularly useful for storing and organizing data in the form of key-value pairs. To create a dictionary, we use braces {}
and separate keys and values by colons :
.
Creating a dictionary
Here is an example of creating a dictionary that holds information about different types of investments:
asset_info = {
"stocks": "investment in company shares",
"bonds": "investment in debt securities",
"real estate": "investment in real estate",
"cash": "investment in cash or near-cash items"
}
print(asset_info)
In this example, the asset_info
dictionary contains four items, each represented by a key-value pair. The keys are strings (the types of assets), and the values are textual descriptions of the assets.
Accessing items in a dictionary
To access an item in a dictionary, we use the corresponding key in brackets []
:
asset_info = {
"stocks": "investment in company shares",
"bonds": "investment in debt securities",
"real estate": "investment in real estate",
"cash": "investment in cash or near-cash items"
}
print(asset_info["stocks"]) # Displays "investment in company shares"
print(asset_info["real estate"]) # Displays "investment in real estate"
Modifying items in a dictionary
Dictionaries are mutable, meaning you can change the value of an item and for this you need to use its key:
asset_info["stocks"] = "investment in company stakes"
print(asset_info["stocks"]) # Displays "investment in company stakes"
Adding and deleting items from a dictionary
To add a new item to a dictionary, simply assign a value to a new key:
asset_info["commodities"] = "investment in commodities"
print(asset_info)
To delete an item from a dictionary, you can use the del
function indicating the key of the item:
del asset_info["cash"]
print(asset_info)
Iterating over a dictionary with loops
You can use loops to iterate over a dictionary and perform operations on its items. Dictionaries can be traversed in different ways, such as by key, by value, or by key-value pairs.
Example 1: Iterating over a dictionary by key
To iterate over a dictionary by key, you can simply use a for
loop:
asset_info = {
"stocks": "investment in company shares",
"bonds": "investment in debt securities",
"real estate": "investment in real estate",
"cash": "investment in cash or near-cash items"
}
for key in asset_info:
print(key) # Displays the key (stocks, bonds...)
print(asset_info[key]) # Displays the value associated with the key
In this example, the for
loop goes through all the keys in the asset_info
dictionary and uses the key
variable to store the current key at each iteration. The print()
function is used to display the key.
Example 2: Iterating Over a Dictionary by Value
If you are re interested in the values contained in the dictionary, you can iterate over them directly using the .values()
method. Here's how you can do it:
asset_info = {
"stocks": "investment in company shares",
"bonds": "investment in debt securities",
"real estate": "investment in real estate",
"cash": "investment in cash or near-cash items"
}
for value in asset_info.values():
print(value) # This will print the value
This code will print out all the values in the asset_info
dictionary, which are the definitions of each investment type.
Example 3: Iterating Over a Dictionary by Key-Value Pairs
If you want both the keys and the values at the same time, you can use the .items()
method, which returns a tuple (an object similar to a list but immutable) for each key-value pair. Here is how you can use it:
asset_info = {
"stocks": "investment in company shares",
"bonds": "investment in debt securities",
"real estate": "investment in real estate",
"cash": "investment in cash or near-cash items"
}
for key, value in asset_info.items():
print(f"The key is {key} and the value is {value}")
In this code, key
and value
are variables that you define to hold the key and value of each item, respectively. The f-string
(formatted string) allows you to include the values of variables directly in a string. This code will print out all the keys and values in the asset_info
dictionary.
More complex lists and dictionaries
Dictionaries and lists are data structures that can become complex. For example, we can have lists of lists, or lists of dictionaries with lists as values. Have a look at this example below:
my_portfolio = {
"APPL":{
"information": {
"common_name": "Apple",
"market_is_open": True,
"currency": "dollar",
},
"quantity": 24,
"current_price": 165.45,
"last_5_days_price": [160.25, 163.87, 161.58, 164.01, 165.45]
},
"GOOG":{
"information": {
"common_name": "Google",
"market_is_open": False,
"currency": "euro",
},
"quantity": 10,
"current_price": 215.72,
"last_5_days_price": [217.56, 220.51, 221.90, 219.19, 215.72]
}
}
This dictionary contains information about a portfolio of stocks. The keys are the stock symbols (like "APPL" for Apple, and "GOOG" for Google), and the values are other dictionaries, which themselves contain more detailed information about each stock.
Here are some commands to display values:
- Display the price of GOOG from 3 days ago:
print(my_stocks["GOOG"]["last_5_days_price"][-3])
- Display whether the market is open for the AAPL stock:
print(my_stocks["APPL"]["information"]["market_is_open"])
Specificity of lists and dictionaries
Lists and dictionaries are slightly special types compared to int
or string
. They behave in a way that can seem counterintuitive, especially in the case of equality. An example is worth a thousand words, so here is an example of their peculiar behaviors.
list1 = [1, 2, 3]
list2 = []
list2 = list1
list2[0] = 542
print(list1) # Displays [542, 2, 3]
As you can see in this example, list1
was never modified. However, its value changed when we changed the list2
variable. This is due to the concept of reference, which is found in many programming languages.
In the case of a list like in our example, when we write list2 = list1
, it does not mean that the value of list2
equals the value of list1
. Writing list2 = list1
means that the list2
variable points to the list1
variable. This implies that if you modify list2
, it also modifies list1
, and vice versa.
To avoid this behaviour, you can use the .copy()
method, which will create an independent copy. Be careful though, if there are other lists or dictionaries inside the list, the copy will not be completely independent, and we move towards the concept of deepcopy, which we will not detail here.
Practical Application: Tracking Transactions
To apply the concepts discussed in this part, let us try to solve an exercise. As usual, we invite you to try to go further than this exercise by making it more complex. That is how you progress the most 😉.
For this exercise, we will provide a list of transactions on cryptocurrencies, and the goal will be to extract certain information from them.
Here is the list of transactions in the form of a list of dictionaries:
transactions = [
{
"symbol": "BTC",
"type": "buy",
"quantity": 0.7,
"price": 27090.4,
"date": "2022-03-07",
},
{
"symbol": "BTC",
"type": "sell",
"quantity": 0.1,
"price": 26561.4,
"date": "2022-04-12",
},
{
"symbol": "BTC",
"type": "buy",
"quantity": 0.4,
"price": 28090.4,
"date": "2022-05-21",
},
{
"symbol": "BTC",
"type": "buy",
"quantity": 0.3,
"price": 25090.4,
"date": "2022-06-02",
},
{
"symbol": "BTC",
"type": "sell",
"quantity": 0.5,
"price": 32034.67,
"date": "2022-06-29",
},
{
"symbol": "ETH",
"type": "buy",
"quantity": 6,
"price": 1754,
"date": "2022-05-21",
},
{
"symbol": "ETH",
"type": "buy",
"quantity": 2,
"price": 1950,
"date": "2022-06-02",
},
{
"symbol": "ETH",
"type": "sell",
"quantity": 3,
"price": 2100.67,
"date": "2022-06-29",
},
]
- From this list, using a loop, create a dictionary with keys for each of the cryptocurrencies present in the transactions and an empty dictionary as its value. This should give you the following result:
portfolio = {
"BTC": {},
"ETH": {},
}
- From this list, using a loop, add to the previous dictionary a key "quantity" which has as its value the quantity still present in the portfolio. (You will need to use conditions to check if these are purchases or sales).
- Considering today's BTC price of
35000
and that of ETH of2400
, add to our previous dictionary our PNL (i.e., our profit or our loss) for each of the cryptos, with the keypnl
. - Add to the dictionary the average purchase price for each of the cryptos.
- (Bonus) For each of the cryptos: display the quantity purchased after the date of
2022-06-02
. For this, you will need to find out how to interact with dates; you need to use thedatetime
library.
This exercise should help you better understand the use of loops and conditions applied to dictionaries and lists in Python in the context of finance. A correction example can be found here: https://github.com/RobotTraders/Python_For_Finance/blob/main/exercise_correction_chapter_3.ipynb. Feel free to adapt this example to your own needs and explore other financial scenarios.