-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathequal_weight_algo_s&p_500.py
297 lines (214 loc) · 10.2 KB
/
equal_weight_algo_s&p_500.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# -*- coding: utf-8 -*-
"""Equal_Weight_Algo_S&P_500.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/1e5-r-oI6dTZI4PebIKgCivha4TqrxOhC
# Equal-Weight S&P 500 Index Fund
## Introduction & Library Imports
The S&P 500 is the world's most popular stock market index. The largest fund that is benchmarked to this index is the SPDR® S&P 500® ETF Trust. It has more than US$250 billion of assets under management.
The goal of this section of the course is to create a Python script that will accept the value of your portfolio and tell you how many shares of each S&P 500 constituent you should purchase to get an equal-weight version of the index fund.
## Library Imports
The first thing we need to do is import the open-source software libraries that we'll be using in this tutorial.
"""
import numpy as np
import pandas as pd
import requests
import xlsxwriter
import math
"""## Importing Our List of Stocks
The next thing we need to do is import the constituents of the S&P 500.
These constituents change over time, so in an ideal world you would connect directly to the index provider (Standard & Poor's) and pull their real-time constituents on a regular basis.
Paying for access to the index provider's API is outside of the scope of this course.
There's a static version of the S&P 500 constituents available here. [Click this link to download them now](/~https://github.com/ayush0801/Equal-Weight-Algorithm-for-Trading-S-P500/blob/main/sp500.csv).
Now it's time to import these stocks to our Jupyter Notebook file.
"""
stocks = pd.read_csv('/content/sp500.csv')
stocks
"""## Acquiring an API Token
Now it's time to import our IEX Cloud API token. This is the data provider that we will be using throughout this course.
API tokens (and other sensitive information) should be stored in a `secrets.py` file that doesn't get pushed to your local Git repository. I have passed the API_TOKEN as a variable in the secrets in Google Colab. You can save the same in `secrets.py` for using Jupyter Notebook. Move the file into the same directory as this Jupyter Notebook before proceeding.
"""
from google.colab import userdata
API_TOKEN = userdata.get('API_TOKEN')
"""## Making Our First API Call
Now it's time to structure our API calls to IEX cloud.
We need the following information from the API:
* Market capitalization for each stock
* Price of each stock
"""
symbol='AAPL'
api_url = f'https://cloud.iexapis.com/stable/stock/{symbol}/quote?token={API_TOKEN}'
data = requests.get(api_url).json()
data
"""## Parsing Our API Call
The API call that we executed in the last code block contains all of the information required to build our equal-weight S&P 500 strategy.
With that said, the data isn't in a proper format yet. We need to parse it first.
"""
price = data['latestPrice']
market_cap = data['marketCap']
"""## Adding Our Stocks Data to a Pandas DataFrame
The next thing we need to do is add our stock's price and market capitalization to a pandas DataFrame. Think of a DataFrame like the Python version of a spreadsheet. It stores tabular data.
"""
my_columns = [ 'Ticker', 'Stock Price', 'Market Capitalization']
final_dataframe = pd.DataFrame(columns = my_columns)
# final_dataframe
final_dataframe = final_dataframe._append(
pd.Series([
symbol,
price,
market_cap],
index = my_columns),
ignore_index = True
)
"""## Looping Through The Tickers in Our List of Stocks
Using the same logic that we outlined above, we can pull data for all S&P 500 stocks and store their data in the DataFrame using a `for` loop.
"""
final_dataframe = pd.DataFrame(columns = my_columns)
for stock in stocks['Symbol'][:5]:
api_url = f'https://cloud.iexapis.com/stable/stock/{stock}/quote?token={API_TOKEN}'
# print(api_url)
response = requests.get(api_url)
# print(response.status_code)
# print(response.content)
data = requests.get(api_url).json()
final_dataframe = final_dataframe._append(
pd.Series(
[
stock,
data['latestPrice'],
data['marketCap']
],
index = my_columns),
ignore_index = True
)
final_dataframe
"""## Using Batch API Calls to Improve Performance
Batch API calls are one of the easiest ways to improve the performance of your code.
This is because HTTP requests are typically one of the slowest components of a script.
Also, API providers will often give you discounted rates for using batch API calls since they are easier for the API provider to respond to.
IEX Cloud limits their batch API calls to 100 tickers per request. Still, this reduces the number of API calls we'll make in this section from 500 to 5 - huge improvement! In this section, we'll split our list of stocks into groups of 100 and then make a batch API call for each group.
"""
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
symbol_groups = list(chunks(stocks['Symbol'], 100))
symbol_strings = []
for i in range(0, len(symbol_groups)):
symbol_strings.append(','.join(symbol_groups[i]))
final_dataframe = pd.DataFrame(columns = my_columns)
for symbol_string in symbol_strings:
# print(symbol_strings)
batch_api_call_url = f'https://cloud.iexapis.com/stable/stock/market/batch/?types=quote&symbols={symbol_string}&token={API_TOKEN}'
# print(batch_api_call_url)
import json
response = requests.get(batch_api_call_url)
if response.status_code == 200:
data = json.loads(response.text)
# print(data)
else:
print("Error:", response.status_code)
# data = requests.get(batch_api_call_url).json()
for symbol in symbol_string.split(','):
final_dataframe = final_dataframe._append(
pd.Series(
[
symbol,
data[symbol]['quote']['latestPrice'],
data[symbol]['quote']['marketCap']
],
index = my_columns),
ignore_index = True
)
final_dataframe
"""## Calculating the Number of Shares to Buy
As you can see in the DataFrame above, we stil haven't calculated the number of shares of each stock to buy.
We'll do that next.
"""
portfolio_size = input("Enter the value of your portfolio:")
try:
val = float(portfolio_size)
except ValueError:
print("That's not a number! \n Try again:")
portfolio_size = input("Enter the value of your portfolio:")
position_size = float(portfolio_size) / len(final_dataframe.index)
# apple_shares = position_size/500
# apple_shares
for i in range(0, len(final_dataframe['Ticker'])-1):
final_dataframe.loc[i, 'Number Of Shares to Buy'] = math.floor(position_size / final_dataframe['Stock Price'][i])
final_dataframe
"""## Formatting Our Excel Output
We will be using the XlsxWriter library for Python to create nicely-formatted Excel files.
XlsxWriter is an excellent package and offers tons of customization. However, the tradeoff for this is that the library can seem very complicated to new users. Accordingly, this section will be fairly long because I want to do a good job of explaining how XlsxWriter works.
### Initializing our XlsxWriter Object
"""
writer = pd.ExcelWriter('recommended trades.xlsx', engine = 'xlsxwriter')
final_dataframe.to_excel(writer, 'Recommended Trades', index = False)
"""### Creating the Formats We'll Need For Our `.xlsx` File
Formats include colors, fonts, and also symbols like `%` and `$`. We'll need four main formats for our Excel document:
* String format for tickers
* \\$XX.XX format for stock prices
* \\$XX,XXX format for market capitalization
* Integer format for the number of shares to purchase
"""
background_color = '#000000'
font_color = '#ffffff'
string_format = writer.book.add_format(
{
'font_color': font_color,
'bg_color': background_color,
'border': 1
}
)
dollar_format = writer.book.add_format(
{
'num_format':'$0.00',
'font_color': font_color,
'bg_color': background_color,
'border': 1
}
)
integer_format = writer.book.add_format(
{
'num_format':'0',
'font_color': font_color,
'bg_color': background_color,
'border': 1
}
)
"""### Applying the Formats to the Columns of Our `.xlsx` File
We can use the `set_column` method applied to the `writer.sheets['Recommended Trades']` object to apply formats to specific columns of our spreadsheets.
Here's an example:
```python
writer.sheets['Recommended Trades'].set_column('B:B', #This tells the method to apply the format to column B
18, #This tells the method to apply a column width of 18 pixels
string_template #This applies the format 'string_template' to the column
)
```
"""
writer.sheets['Recommended Trades'].write('A1', 'Ticker', string_format)
writer.sheets['Recommended Trades'].write('B1', 'Price', string_format)
writer.sheets['Recommended Trades'].write('C1', 'Market Capitalization', string_format)
writer.sheets['Recommended Trades'].write('D1', 'Number Of Shares to Buy', string_format)
writer.sheets['Recommended Trades'].set_column('A:A', 20, string_format)
writer.sheets['Recommended Trades'].set_column('B:B', 20, dollar_format)
writer.sheets['Recommended Trades'].set_column('C:C', 20, dollar_format)
writer.sheets['Recommended Trades'].set_column('D:D', 20, integer_format)
"""This code works, but it violates the software principle of "Don't Repeat Yourself".
Let's simplify this by putting it in 2 loops:
"""
column_formats = {
'A': ['Ticker', string_format],
'B': ['Price', dollar_format],
'C': ['Market Capitalization', dollar_format],
'D': ['Number of Shares to Buy', integer_format]
}
for column in column_formats.keys():
writer.sheets['Recommended Trades'].set_column(f'{column}:{column}', 20, column_formats[column][1])
writer.sheets['Recommended Trades'].write(f'{column}1', column_formats[column][0], string_format)
"""## Saving Our Excel Output
Saving our Excel file is very easy:
"""
writer._save()
from google.colab import files
files.download('recommended trades.xlsx')