mypythproject 0.1.1__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024, Amine Lahlou
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.1
2
+ Name: mypythproject
3
+ Version: 0.1.1
4
+ Summary: An extension of pybacktestchain that enhances portfolio optimization and backtesting with advanced features.
5
+ License: MIT
6
+ Author: Amine Lahlou
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: dash (>=2.18.2,<3.0.0)
14
+ Requires-Dist: matplotlib (>=3.10.0,<4.0.0)
15
+ Requires-Dist: numba (>=0.60.0,<0.61.0)
16
+ Requires-Dist: pybacktestchain (>=0.2.1,<0.3.0)
17
+ Description-Content-Type: text/markdown
18
+
19
+ # mypythproject
20
+
21
+ An extension of pybacktestchain that enhances portfolio optimization and backtesting with advanced features.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ $ pip install mypythproject
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ - TODO
32
+
33
+ ## Contributing
34
+
35
+ Interested in contributing? Check out the contributing guidelines. Please note that this project is released with a Code of Conduct. By contributing to this project, you agree to abide by its terms.
36
+
37
+ ## License
38
+
39
+ `mypythproject` was created by Amine Lahlou. It is licensed under the terms of the MIT license.
40
+
41
+ ## Credits
42
+
43
+ `mypythproject` was created with [`cookiecutter`](https://cookiecutter.readthedocs.io/en/latest/) and the `py-pkgs-cookiecutter` [template](https://github.com/py-pkgs/py-pkgs-cookiecutter).
44
+
@@ -0,0 +1,25 @@
1
+ # mypythproject
2
+
3
+ An extension of pybacktestchain that enhances portfolio optimization and backtesting with advanced features.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ $ pip install mypythproject
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ - TODO
14
+
15
+ ## Contributing
16
+
17
+ Interested in contributing? Check out the contributing guidelines. Please note that this project is released with a Code of Conduct. By contributing to this project, you agree to abide by its terms.
18
+
19
+ ## License
20
+
21
+ `mypythproject` was created by Amine Lahlou. It is licensed under the terms of the MIT license.
22
+
23
+ ## Credits
24
+
25
+ `mypythproject` was created with [`cookiecutter`](https://cookiecutter.readthedocs.io/en/latest/) and the `py-pkgs-cookiecutter` [template](https://github.com/py-pkgs/py-pkgs-cookiecutter).
@@ -0,0 +1,31 @@
1
+ [tool.poetry]
2
+ name = "mypythproject"
3
+ version = "0.1.1"
4
+ description = "An extension of pybacktestchain that enhances portfolio optimization and backtesting with advanced features."
5
+ authors = ["Amine Lahlou"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+
9
+ [tool.poetry.dependencies]
10
+ python = "^3.11"
11
+ pybacktestchain = "^0.2.1"
12
+ numba = "^0.60.0"
13
+ dash = "^2.18.2"
14
+ matplotlib = "^3.10.0"
15
+
16
+ [tool.poetry.dev-dependencies]
17
+
18
+ [tool.poetry.group.dev.dependencies]
19
+ python-semantic-release = "^9.15.2"
20
+ pytest = "^8.3.4"
21
+ pytest-cov = "^6.0.0"
22
+
23
+ [build-system]
24
+ requires = ["poetry-core>=1.0.0"]
25
+ build-backend = "poetry.core.masonry.api"
26
+
27
+ [tool.semantic_release]
28
+ version_variable = "pyproject.toml:version"
29
+ version_toml = [
30
+ "pyproject.toml:tool.poetry.version",
31
+ ]
@@ -0,0 +1,357 @@
1
+ import dash
2
+ from dash import dcc, html, dash_table
3
+ from dash.dependencies import Input, Output, State
4
+ from datetime import datetime, timedelta
5
+ import pandas as pd
6
+ import plotly.graph_objs as go
7
+ from pybacktestchain.data_module import get_stock_data
8
+ from pybacktestchain.broker import Backtest, StopLoss, Broker, Position
9
+ from optimization_techniques import MaxSharpe, MinVariance, MaxReturn
10
+ from pybacktestchain.data_module import FirstTwoMoments
11
+ from tickers import csv_to_ticker_dict
12
+ import logging
13
+ import random
14
+ import string
15
+
16
+ # Remove yfinance error logs
17
+ logging.getLogger("yfinance").setLevel(logging.CRITICAL)
18
+
19
+ # Map the symbols in the dictionary to securities
20
+ sp_dict = csv_to_ticker_dict()
21
+ universe_options = [
22
+ {"label": security, "value": symbol} for symbol, security in sp_dict.items()
23
+ ]
24
+
25
+ # Create Dash App
26
+ app = dash.Dash(__name__)
27
+
28
+ app.layout = html.Div([
29
+ html.H1("Python Project - Backtest Portfolio Value", style={'marginBottom': '20px'}),
30
+
31
+ html.Div([
32
+ html.Label("Initial Date:"),
33
+ dcc.DatePickerSingle(
34
+ id='initial-date',
35
+ date='2019-01-01',
36
+ display_format='YYYY-MM-DD'
37
+ )
38
+ ], style={'marginBottom': '20px'}),
39
+
40
+ html.Div([
41
+ html.Label("Final Date:"),
42
+ dcc.DatePickerSingle(
43
+ id='final-date',
44
+ date='2020-01-01',
45
+ display_format='YYYY-MM-DD'
46
+ )
47
+ ], style={'marginBottom': '20px'}),
48
+
49
+ html.Div([
50
+ html.Label("Optimization Technique:"),
51
+ dcc.Dropdown(
52
+ id='information-class',
53
+ options=[
54
+ {'label': 'FirstTwoMoments', 'value': 'first_two_moments'},
55
+ {'label': 'MaxReturn', 'value': 'max_return'},
56
+ {'label': 'MinVariance', 'value': 'min_variance'},
57
+ {'label': 'MaxSharpe', 'value': 'max_sharpe'},
58
+ ],
59
+ value='first_two_moments',
60
+ clearable=False
61
+ )
62
+ ], style={'width': '300px', 'marginBottom': '20px'}),
63
+
64
+ html.Div([
65
+ html.Label("Select S&P500 Securities:"),
66
+ dcc.Dropdown(
67
+ id='universe-dropdown',
68
+ options=universe_options,
69
+ value=[],
70
+ multi=True,
71
+ placeholder='Pick one or more securities'
72
+ )
73
+ ], style={'width': '400px', 'marginBottom': '20px'}),
74
+
75
+ html.Button("Run Backtest", id='run-button', n_clicks=0,
76
+ style={'marginTop': '20px', 'marginBottom': '20px'}),
77
+
78
+ html.Div([
79
+ html.H3("Final Portfolio Summary"),
80
+ dash_table.DataTable(id='portfolio-summary-table', style_table={'overflowX': 'auto'})
81
+ ], style={'marginTop': '40px'}),
82
+
83
+ dcc.Graph(id='correlation-graph', style={'marginTop': '40px'}),
84
+
85
+ dcc.Graph(id='portfolio-value-graph', style={'marginTop': '40px'}),
86
+
87
+ html.Div([
88
+ html.H3("Statistics (Daily Returns)"),
89
+ dash_table.DataTable(
90
+ id='stats-table',
91
+ style_table={'overflowX': 'auto'},
92
+ style_cell={'textAlign': 'center'}
93
+ )
94
+ ], style={'marginTop': '40px'})
95
+ ])
96
+
97
+ @app.callback(
98
+ [
99
+ Output('portfolio-summary-table', 'data'),
100
+ Output('portfolio-summary-table', 'columns'),
101
+ Output('correlation-graph', 'figure'),
102
+ Output('portfolio-value-graph', 'figure'),
103
+ Output('stats-table', 'data'),
104
+ Output('stats-table', 'columns')
105
+ ],
106
+ Input('run-button', 'n_clicks'),
107
+ State('initial-date', 'date'),
108
+ State('final-date', 'date'),
109
+ State('information-class', 'value'),
110
+ State('universe-dropdown', 'value')
111
+ )
112
+
113
+ def run_backtest(n_clicks, init_date_str, final_date_str, information_class_str, selected_symbols):
114
+ if n_clicks == 0:
115
+ return [], [], go.Figure(), go.Figure(), [], []
116
+
117
+ init_date = datetime.strptime(init_date_str, "%Y-%m-%d")
118
+ final_date = datetime.strptime(final_date_str, "%Y-%m-%d")
119
+
120
+ # Map information class
121
+ information_class = {
122
+ 'first_two_moments': FirstTwoMoments,
123
+ 'max_return': MaxReturn,
124
+ 'min_variance': MinVariance,
125
+ 'max_sharpe': MaxSharpe
126
+ }.get(information_class_str, FirstTwoMoments)
127
+
128
+ # -------------------------
129
+ # 1) BACKTEST AND BROKER
130
+ # -------------------------
131
+ backtest = Backtest(
132
+ initial_date=init_date,
133
+ final_date=final_date,
134
+ information_class=information_class,
135
+ risk_model=StopLoss,
136
+ name_blockchain='backtest_' + ''.join(random.choices(string.ascii_lowercase + string.digits, k=5)),
137
+ verbose=False
138
+ )
139
+ backtest.universe = selected_symbols
140
+
141
+ backtest.run_backtest()
142
+ broker = Broker(cash=1_000_000, verbose=False)
143
+
144
+ # Transaction log from the backtest
145
+ transaction_log = backtest.broker.get_transaction_log()
146
+
147
+ # We'll track daily portfolio value
148
+ portfolio_values = []
149
+ last_prices = {}
150
+ rebalance_dates = []
151
+
152
+ current_date = init_date
153
+ while current_date <= final_date:
154
+ # Skip weekends explicitly
155
+ if current_date.weekday() >= 5:
156
+ current_date += timedelta(days=1)
157
+ continue
158
+
159
+ # Filter transactions for current day
160
+ daily_transactions = transaction_log[transaction_log['Date'] == current_date]
161
+ for _, transaction in daily_transactions.iterrows():
162
+ ticker = transaction['Ticker']
163
+ action = transaction['Action']
164
+ quantity = transaction['Quantity']
165
+ price = transaction['Price']
166
+
167
+ if action == 'BUY':
168
+ broker.buy(ticker, quantity, price, current_date)
169
+ elif action == 'SELL':
170
+ broker.sell(ticker, quantity, price, current_date)
171
+
172
+ # Check for rebalancing
173
+ if backtest.rebalance_flag().time_to_rebalance(current_date):
174
+ rebalance_dates.append(current_date)
175
+
176
+ # Get current market prices
177
+ market_prices = {}
178
+ for ticker in broker.positions.keys():
179
+ try:
180
+ data = get_stock_data(
181
+ ticker,
182
+ current_date.strftime('%Y-%m-%d'),
183
+ (current_date + timedelta(days=1)).strftime('%Y-%m-%d')
184
+ )
185
+ if not data.empty:
186
+ market_prices[ticker] = data.iloc[-1]['Close']
187
+ last_prices[ticker] = market_prices[ticker]
188
+ else:
189
+ market_prices[ticker] = last_prices.get(ticker, 0)
190
+ except Exception:
191
+ market_prices[ticker] = last_prices.get(ticker, 0)
192
+
193
+ # Calculate portfolio value for the current day
194
+ try:
195
+ portfolio_value = broker.get_portfolio_value(market_prices)
196
+ except Exception:
197
+ # If something goes wrong, fallback to previous day
198
+ portfolio_value = portfolio_values[-1][1] if portfolio_values else 1_000_000
199
+
200
+ portfolio_values.append((current_date, portfolio_value))
201
+
202
+ current_date += timedelta(days=1)
203
+
204
+ # -------------------------
205
+ # 2) PREPARE SUMMARY TABLE
206
+ # -------------------------
207
+ final_market_prices = {
208
+ ticker: last_prices.get(ticker, 0) for ticker in broker.positions.keys()
209
+ }
210
+ summary_data = []
211
+ for ticker, position in broker.positions.items():
212
+ summary_data.append({
213
+ "Ticker": ticker,
214
+ "Shares": position.quantity,
215
+ "Last Price": final_market_prices[ticker],
216
+ "Value": position.quantity * final_market_prices[ticker]
217
+ })
218
+
219
+ total_value = sum(item["Value"] for item in summary_data) + broker.cash
220
+ summary_data.append({
221
+ "Ticker": "Total",
222
+ "Shares": "-",
223
+ "Last Price": "-",
224
+ "Value": total_value
225
+ })
226
+
227
+ summary_columns = [
228
+ {"name": "Ticker", "id": "Ticker"},
229
+ {"name": "Shares", "id": "Shares"},
230
+ {"name": "Last Price", "id": "Last Price"},
231
+ {"name": "Value", "id": "Value"}
232
+ ]
233
+
234
+ # -------------------------
235
+ # 3) CORRELATION GRAPH
236
+ # -------------------------
237
+ # Build a DataFrame of daily closes for each selected symbol so we can compute daily returns and correlation.
238
+ price_df = pd.DataFrame()
239
+ for symbol in selected_symbols:
240
+ data = get_stock_data(symbol, init_date_str, final_date_str)
241
+ if not data.empty:
242
+ # Align on date index to handle merges properly
243
+ data = data[['Date','Close']].set_index('Date')
244
+ data.index = pd.to_datetime(data.index)
245
+ price_df[symbol] = data['Close']
246
+
247
+ # Drop any days that are all NaN
248
+ price_df.dropna(how='all', inplace=True)
249
+
250
+ # Compute daily returns and then plot correlation heatmap
251
+ ret_df = price_df.pct_change().dropna()
252
+ if not ret_df.empty:
253
+ corr_matrix = ret_df.corr()
254
+ corr_fig = go.Figure(
255
+ data=go.Heatmap(
256
+ z=corr_matrix.values,
257
+ x=corr_matrix.columns,
258
+ y=corr_matrix.columns,
259
+ colorscale='RdYlGn',
260
+ zmin=-1,
261
+ zmax=1
262
+ )
263
+ )
264
+ corr_fig.update_layout(title="Correlation Heatmap of Daily Returns")
265
+ else:
266
+ corr_fig = go.Figure()
267
+
268
+ # -------------------------
269
+ # 4) PORTFOLIO VALUE GRAPH
270
+ # -------------------------
271
+ df_portfolio = pd.DataFrame(portfolio_values, columns=['Date', 'Portfolio Value'])
272
+ fig_portfolio = go.Figure()
273
+ fig_portfolio.add_trace(
274
+ go.Scatter(
275
+ x=df_portfolio['Date'],
276
+ y=df_portfolio['Portfolio Value'],
277
+ mode='lines',
278
+ name='Portfolio Value'
279
+ )
280
+ )
281
+ # Add a reference line at 1M
282
+ fig_portfolio.add_trace(
283
+ go.Scatter(
284
+ x=df_portfolio['Date'],
285
+ y=[1_000_000] * len(df_portfolio),
286
+ mode='lines',
287
+ line=dict(color='red', dash='dash'),
288
+ name='1M Threshold'
289
+ )
290
+ )
291
+ # Mark rebalancing points
292
+ for reb_date in rebalance_dates:
293
+ marker_day = reb_date - timedelta(days=1)
294
+ val = df_portfolio.loc[df_portfolio['Date'] == marker_day, 'Portfolio Value']
295
+ if not val.empty:
296
+ fig_portfolio.add_trace(
297
+ go.Scatter(
298
+ x=[marker_day],
299
+ y=[val.values[0]],
300
+ mode='markers',
301
+ marker=dict(color='blue', size=10, symbol='circle'),
302
+ showlegend=False
303
+ )
304
+ )
305
+ fig_portfolio.update_layout(
306
+ title="Portfolio Value Over Time",
307
+ xaxis_title="Date",
308
+ yaxis_title="Portfolio Value"
309
+ )
310
+
311
+ # -------------------------
312
+ # 5) STATISTICS TABLE
313
+ # -------------------------
314
+ stats_data = []
315
+ if not ret_df.empty:
316
+ # Per-ticker stats:
317
+ for symbol in ret_df.columns:
318
+ avg_return = ret_df[symbol].mean() * 100
319
+ std_return = ret_df[symbol].std() * 100
320
+ stats_data.append({
321
+ 'Ticker': symbol,
322
+ 'Average Return (%)': round(avg_return, 2),
323
+ 'Std Dev (%)': round(std_return, 2)
324
+ })
325
+
326
+ # Entire portfolio stats:
327
+ if len(df_portfolio) > 1:
328
+ df_portfolio['Daily Return'] = df_portfolio['Portfolio Value'].pct_change()
329
+ # Drop the first row (NaN return)
330
+ daily_returns = df_portfolio['Daily Return'].dropna()
331
+
332
+ if not daily_returns.empty:
333
+ avg_port = daily_returns.mean() * 100
334
+ std_port = daily_returns.std() * 100
335
+ stats_data.append({
336
+ 'Ticker': 'Entire Portfolio',
337
+ 'Average Return (%)': round(avg_port, 2),
338
+ 'Std Dev (%)': round(std_port, 2)
339
+ })
340
+
341
+ stats_columns = [
342
+ {'name': 'Ticker', 'id': 'Ticker'},
343
+ {'name': 'Average Return (%)', 'id': 'Average Return (%)'},
344
+ {'name': 'Std Dev (%)', 'id': 'Std Dev (%)'}
345
+ ]
346
+
347
+ return (
348
+ summary_data,
349
+ summary_columns,
350
+ corr_fig,
351
+ fig_portfolio,
352
+ stats_data,
353
+ stats_columns
354
+ )
355
+
356
+ if __name__ == '__main__':
357
+ app.run_server(debug=True)
@@ -0,0 +1,3 @@
1
+ # read version from installed package
2
+ from importlib.metadata import version
3
+ __version__ = version("mypythproject")
@@ -0,0 +1,26 @@
1
+ from pybacktestchain.broker import Backtest, StopLoss
2
+ from pybacktestchain.blockchain import load_blockchain
3
+ from datetime import datetime
4
+ from optimization_techniques import MaxSharpe
5
+ from optimization_techniques import MinVariance
6
+ from optimization_techniques import MaxReturn
7
+ from pybacktestchain.data_module import FirstTwoMoments
8
+
9
+ # Set verbosity for logging
10
+ verbose = False # Set to True to enable logging, or False to suppress it
11
+
12
+ backtest = Backtest(
13
+ initial_date=datetime(2019, 1, 1),
14
+ final_date=datetime(2020, 1, 1),
15
+ information_class=FirstTwoMoments,
16
+ risk_model=StopLoss,
17
+ name_blockchain='backtest',
18
+ verbose=verbose
19
+ )
20
+ backtest.universe = ['BAC','JPM','GS']
21
+ backtest.run_backtest()
22
+ block_chain = load_blockchain('backtest')
23
+
24
+ print(str(block_chain))
25
+ # check if the blockchain is valid
26
+ print(block_chain.is_valid())
@@ -0,0 +1,240 @@
1
+ import yfinance as yf
2
+ import pandas as pd
3
+ from sec_cik_mapper import StockMapper
4
+ from dataclasses import dataclass
5
+ from datetime import datetime, timedelta
6
+ import logging
7
+ from scipy.optimize import minimize
8
+ import numpy as np
9
+ from pybacktestchain.data_module import Information
10
+
11
+ @dataclass
12
+ class MaxSharpe(Information):
13
+ def compute_portfolio(self, t: datetime, information_set: dict):
14
+ try:
15
+ mu = information_set['expected_return']
16
+ Sigma = information_set['covariance_matrix']
17
+ n = len(mu)
18
+
19
+ # Sharpe objective
20
+ def sharpe_ratio_neg(x):
21
+ eps = 1e-8 # Add small epsilon to avoid division by zero
22
+ numerator = x.dot(mu)
23
+ denominator = np.sqrt(x.dot(Sigma).dot(x)) + eps
24
+ return - numerator / denominator
25
+
26
+ # constraints:
27
+ constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
28
+ bounds = [(0.0, 1.0)] * n
29
+
30
+ # initial guess, equal weights
31
+ x0 = np.ones(n) / n
32
+
33
+ res = minimize(sharpe_ratio_neg,
34
+ x0,
35
+ constraints=constraints,
36
+ bounds=bounds,
37
+ method='SLSQP')
38
+
39
+ # prepare dictionary
40
+ portfolio = {k: None for k in information_set['companies']}
41
+
42
+ # if converged update
43
+ if res.success:
44
+ for i, company in enumerate(information_set['companies']):
45
+ portfolio[company] = res.x[i]
46
+ else:
47
+ raise Exception("Optimization did not converge")
48
+
49
+ return portfolio
50
+
51
+ except Exception as e:
52
+ # if something goes wrong return an equal weigh portfolio but let the user know
53
+ logging.warning("Error computing portfolio, returning equal weight portfolio")
54
+ logging.warning(e)
55
+ return {k: 1/len(information_set['companies'])
56
+ for k in information_set['companies']}
57
+
58
+
59
+ def compute_information(self, t: datetime):
60
+ # get the data module
61
+ data = self.slice_data(t)
62
+ # the information set will be a dictionary with data
63
+ information_set = {}
64
+ # sort data by ticker and date
65
+ data = data.sort_values(by=[self.company_column, self.time_column])
66
+
67
+ # compute returns
68
+ data['return'] = data.groupby(self.company_column)[self.adj_close_column].pct_change()
69
+
70
+ # expected return by company
71
+ information_set['expected_return'] = data.groupby(self.company_column)['return'].mean().to_numpy()
72
+
73
+ # covariance matrix
74
+
75
+ # 1. pivot the data
76
+ data_pivot = data.pivot(index=self.time_column,
77
+ columns=self.company_column,
78
+ values=self.adj_close_column)
79
+ # drop missing values
80
+ data_pivot = data_pivot.dropna(axis=0)
81
+ # 2. compute the covariance matrix
82
+ covariance_matrix = data_pivot.cov().to_numpy()
83
+
84
+ # add to information set
85
+ information_set['covariance_matrix'] = covariance_matrix
86
+ information_set['companies'] = data_pivot.columns.to_numpy()
87
+
88
+ return information_set
89
+
90
+ @dataclass
91
+ class MinVariance(Information):
92
+ def compute_portfolio(self, t: datetime, information_set: dict):
93
+ try:
94
+ mu = information_set['expected_return']
95
+ Sigma = information_set['covariance_matrix']
96
+ n = len(mu)
97
+
98
+ # Min Variance objective
99
+ def variance_obj(x):
100
+ return x.dot(Sigma).dot(x)
101
+
102
+ # constraints:
103
+ constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
104
+ bounds = [(0.0, 1.0)] * n
105
+
106
+ # initial guess, equal weights
107
+ x0 = np.ones(n) / n
108
+
109
+ res = minimize(variance_obj,
110
+ x0,
111
+ constraints=constraints,
112
+ bounds=bounds,
113
+ method='SLSQP')
114
+
115
+ # prepare dictionary
116
+ portfolio = {k: None for k in information_set['companies']}
117
+
118
+ # if converged update
119
+ if res.success:
120
+ for i, company in enumerate(information_set['companies']):
121
+ portfolio[company] = res.x[i]
122
+ else:
123
+ raise Exception("Optimization did not converge")
124
+
125
+ return portfolio
126
+
127
+ except Exception as e:
128
+ # if something goes wrong return an equal weight portfolio but let the user know
129
+ logging.warning("Error computing portfolio, returning equal weight portfolio")
130
+ logging.warning(e)
131
+ return {k: 1/len(information_set['companies'])
132
+ for k in information_set['companies']}
133
+
134
+
135
+ def compute_information(self, t: datetime):
136
+ # get the data module
137
+ data = self.slice_data(t)
138
+ # the information set will be a dictionary with data
139
+ information_set = {}
140
+ # sort data by ticker and date
141
+ data = data.sort_values(by=[self.company_column, self.time_column])
142
+
143
+ # compute returns
144
+ data['return'] = data.groupby(self.company_column)[self.adj_close_column].pct_change()
145
+
146
+ # expected return by company
147
+ information_set['expected_return'] = data.groupby(self.company_column)['return'].mean().to_numpy()
148
+
149
+ # covariance matrix
150
+
151
+ # 1. pivot the data
152
+ data_pivot = data.pivot(index=self.time_column,
153
+ columns=self.company_column,
154
+ values=self.adj_close_column)
155
+ # drop missing values
156
+ data_pivot = data_pivot.dropna(axis=0)
157
+ # 2. compute the covariance matrix
158
+ covariance_matrix = data_pivot.cov().to_numpy()
159
+
160
+ # add to information set
161
+ information_set['covariance_matrix'] = covariance_matrix
162
+ information_set['companies'] = data_pivot.columns.to_numpy()
163
+
164
+ return information_set
165
+
166
+ @dataclass
167
+ class MaxReturn(Information):
168
+ def compute_portfolio(self, t: datetime, information_set: dict):
169
+ try:
170
+ mu = information_set['expected_return']
171
+ Sigma = information_set['covariance_matrix']
172
+ n = len(mu)
173
+
174
+ # Max Return objective
175
+ def neg_return(x):
176
+ return -x.dot(mu)
177
+
178
+ # constraints:
179
+ constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1})
180
+ bounds = [(0.0, 1.0)] * n
181
+
182
+ # initial guess, equal weights
183
+ x0 = np.ones(n) / n
184
+
185
+ res = minimize(neg_return,
186
+ x0,
187
+ constraints=constraints,
188
+ bounds=bounds,
189
+ method='SLSQP')
190
+
191
+ # prepare dictionary
192
+ portfolio = {k: None for k in information_set['companies']}
193
+
194
+ # if converged update
195
+ if res.success:
196
+ for i, company in enumerate(information_set['companies']):
197
+ portfolio[company] = res.x[i]
198
+ else:
199
+ raise Exception("Optimization did not converge")
200
+
201
+ return portfolio
202
+
203
+ except Exception as e:
204
+ # if something goes wrong return an equal weight portfolio but let the user know
205
+ logging.warning("Error computing portfolio, returning equal weight portfolio")
206
+ logging.warning(e)
207
+ return {k: 1/len(information_set['companies'])
208
+ for k in information_set['companies']}
209
+
210
+
211
+ def compute_information(self, t: datetime):
212
+ # get the data module
213
+ data = self.slice_data(t)
214
+ # the information set will be a dictionary with data
215
+ information_set = {}
216
+ # sort data by ticker and date
217
+ data = data.sort_values(by=[self.company_column, self.time_column])
218
+
219
+ # compute returns
220
+ data['return'] = data.groupby(self.company_column)[self.adj_close_column].pct_change()
221
+
222
+ # expected return by company
223
+ information_set['expected_return'] = data.groupby(self.company_column)['return'].mean().to_numpy()
224
+
225
+ # covariance matrix
226
+
227
+ # 1. pivot the data
228
+ data_pivot = data.pivot(index=self.time_column,
229
+ columns=self.company_column,
230
+ values=self.adj_close_column)
231
+ # drop missing values
232
+ data_pivot = data_pivot.dropna(axis=0)
233
+ # 2. compute the covariance matrix
234
+ covariance_matrix = data_pivot.cov().to_numpy()
235
+
236
+ # add to information set
237
+ information_set['covariance_matrix'] = covariance_matrix
238
+ information_set['companies'] = data_pivot.columns.to_numpy()
239
+
240
+ return information_set
@@ -0,0 +1,504 @@
1
+ Symbol;Security;GICS Sector
2
+ MMM;3M;Industrials
3
+ AOS;A. O. Smith;Industrials
4
+ ABT;Abbott Laboratories;Health Care
5
+ ABBV;AbbVie;Health Care
6
+ ACN;Accenture;Information Technology
7
+ ADBE;Adobe Inc.;Information Technology
8
+ AMD;Advanced Micro Devices;Information Technology
9
+ AES;AES Corporation;Utilities
10
+ AFL;Aflac;Financials
11
+ A;Agilent Technologies;Health Care
12
+ APD;Air Products;Materials
13
+ ABNB;Airbnb;Consumer Discretionary
14
+ AKAM;Akamai Technologies;Information Technology
15
+ ALB;Albemarle Corporation;Materials
16
+ ARE;Alexandria Real Estate Equities;Real Estate
17
+ ALGN;Align Technology;Health Care
18
+ ALLE;Allegion;Industrials
19
+ LNT;Alliant Energy;Utilities
20
+ ALL;Allstate;Financials
21
+ GOOGL;Alphabet Inc. (Class A);Communication Services
22
+ GOOG;Alphabet Inc. (Class C);Communication Services
23
+ MO;Altria;Consumer Staples
24
+ AMZN;Amazon;Consumer Discretionary
25
+ AMCR;Amcor;Materials
26
+ AEE;Ameren;Utilities
27
+ AEP;American Electric Power;Utilities
28
+ AXP;American Express;Financials
29
+ AIG;American International Group;Financials
30
+ AMT;American Tower;Real Estate
31
+ AWK;American Water Works;Utilities
32
+ AMP;Ameriprise Financial;Financials
33
+ AME;Ametek;Industrials
34
+ AMGN;Amgen;Health Care
35
+ APH;Amphenol;Information Technology
36
+ ADI;Analog Devices;Information Technology
37
+ ANSS;Ansys;Information Technology
38
+ AON;Aon;Financials
39
+ APA;APA Corporation;Energy
40
+ APO;Apollo Global Management;Financials
41
+ AAPL;Apple Inc.;Information Technology
42
+ AMAT;Applied Materials;Information Technology
43
+ APTV;Aptiv;Consumer Discretionary
44
+ ACGL;Arch Capital Group;Financials
45
+ ADM;Archer Daniels Midland;Consumer Staples
46
+ ANET;Arista Networks;Information Technology
47
+ AJG;Arthur J. Gallagher & Co.;Financials
48
+ AIZ;Assurant;Financials
49
+ T;AT&T;Communication Services
50
+ ATO;Atmos Energy;Utilities
51
+ ADSK;Autodesk;Information Technology
52
+ ADP;Automatic Data Processing;Industrials
53
+ AZO;AutoZone;Consumer Discretionary
54
+ AVB;AvalonBay Communities;Real Estate
55
+ AVY;Avery Dennison;Materials
56
+ AXON;Axon Enterprise;Industrials
57
+ BKR;Baker Hughes;Energy
58
+ BALL;Ball Corporation;Materials
59
+ BAC;Bank of America;Financials
60
+ BAX;Baxter International;Health Care
61
+ BDX;Becton Dickinson;Health Care
62
+ BRK.B;Berkshire Hathaway;Financials
63
+ BBY;Best Buy;Consumer Discretionary
64
+ TECH;Bio-Techne;Health Care
65
+ BIIB;Biogen;Health Care
66
+ BLK;BlackRock;Financials
67
+ BX;Blackstone Inc.;Financials
68
+ BK;BNY Mellon;Financials
69
+ BA;Boeing;Industrials
70
+ BKNG;Booking Holdings;Consumer Discretionary
71
+ BWA;BorgWarner;Consumer Discretionary
72
+ BSX;Boston Scientific;Health Care
73
+ BMY;Bristol Myers Squibb;Health Care
74
+ AVGO;Broadcom;Information Technology
75
+ BR;Broadridge Financial Solutions;Industrials
76
+ BRO;Brown & Brown;Financials
77
+ BF.B;Brown–Forman;Consumer Staples
78
+ BLDR;Builders FirstSource;Industrials
79
+ BG;Bunge Global;Consumer Staples
80
+ BXP;BXP, Inc.;Real Estate
81
+ CHRW;C.H. Robinson;Industrials
82
+ CDNS;Cadence Design Systems;Information Technology
83
+ CZR;Caesars Entertainment;Consumer Discretionary
84
+ CPT;Camden Property Trust;Real Estate
85
+ CPB;Campbell Soup Company;Consumer Staples
86
+ COF;Capital One;Financials
87
+ CAH;Cardinal Health;Health Care
88
+ KMX;CarMax;Consumer Discretionary
89
+ CCL;Carnival;Consumer Discretionary
90
+ CARR;Carrier Global;Industrials
91
+ CAT;Caterpillar Inc.;Industrials
92
+ CBOE;Cboe Global Markets;Financials
93
+ CBRE;CBRE Group;Real Estate
94
+ CDW;CDW;Information Technology
95
+ CE;Celanese;Materials
96
+ COR;Cencora;Health Care
97
+ CNC;Centene Corporation;Health Care
98
+ CNP;CenterPoint Energy;Utilities
99
+ CF;CF Industries;Materials
100
+ CRL;Charles River Laboratories;Health Care
101
+ SCHW;Charles Schwab Corporation;Financials
102
+ CHTR;Charter Communications;Communication Services
103
+ CVX;Chevron Corporation;Energy
104
+ CMG;Chipotle Mexican Grill;Consumer Discretionary
105
+ CB;Chubb Limited;Financials
106
+ CHD;Church & Dwight;Consumer Staples
107
+ CI;Cigna;Health Care
108
+ CINF;Cincinnati Financial;Financials
109
+ CTAS;Cintas;Industrials
110
+ CSCO;Cisco;Information Technology
111
+ C;Citigroup;Financials
112
+ CFG;Citizens Financial Group;Financials
113
+ CLX;Clorox;Consumer Staples
114
+ CME;CME Group;Financials
115
+ CMS;CMS Energy;Utilities
116
+ KO;Coca-Cola Company (The);Consumer Staples
117
+ CTSH;Cognizant;Information Technology
118
+ CL;Colgate-Palmolive;Consumer Staples
119
+ CMCSA;Comcast;Communication Services
120
+ CAG;Conagra Brands;Consumer Staples
121
+ COP;ConocoPhillips;Energy
122
+ ED;Consolidated Edison;Utilities
123
+ STZ;Constellation Brands;Consumer Staples
124
+ CEG;Constellation Energy;Utilities
125
+ COO;Cooper Companies (The);Health Care
126
+ CPRT;Copart;Industrials
127
+ GLW;Corning Inc.;Information Technology
128
+ CPAY;Corpay;Financials
129
+ CTVA;Corteva;Materials
130
+ CSGP;CoStar Group;Real Estate
131
+ COST;Costco;Consumer Staples
132
+ CTRA;Coterra;Energy
133
+ CRWD;CrowdStrike;Information Technology
134
+ CCI;Crown Castle;Real Estate
135
+ CSX;CSX Corporation;Industrials
136
+ CMI;Cummins;Industrials
137
+ CVS;CVS Health;Health Care
138
+ DHR;Danaher Corporation;Health Care
139
+ DRI;Darden Restaurants;Consumer Discretionary
140
+ DVA;DaVita;Health Care
141
+ DAY;Dayforce;Industrials
142
+ DECK;Deckers Brands;Consumer Discretionary
143
+ DE;Deere & Company;Industrials
144
+ DELL;Dell Technologies;Information Technology
145
+ DAL;Delta Air Lines;Industrials
146
+ DVN;Devon Energy;Energy
147
+ DXCM;Dexcom;Health Care
148
+ FANG;Diamondback Energy;Energy
149
+ DLR;Digital Realty;Real Estate
150
+ DFS;Discover Financial;Financials
151
+ DG;Dollar General;Consumer Staples
152
+ DLTR;Dollar Tree;Consumer Staples
153
+ D;Dominion Energy;Utilities
154
+ DPZ;Domino's;Consumer Discretionary
155
+ DOV;Dover Corporation;Industrials
156
+ DOW;Dow Inc.;Materials
157
+ DHI;D. R. Horton;Consumer Discretionary
158
+ DTE;DTE Energy;Utilities
159
+ DUK;Duke Energy;Utilities
160
+ DD;DuPont;Materials
161
+ EMN;Eastman Chemical Company;Materials
162
+ ETN;Eaton Corporation;Industrials
163
+ EBAY;eBay;Consumer Discretionary
164
+ ECL;Ecolab;Materials
165
+ EIX;Edison International;Utilities
166
+ EW;Edwards Lifesciences;Health Care
167
+ EA;Electronic Arts;Communication Services
168
+ ELV;Elevance Health;Health Care
169
+ EMR;Emerson Electric;Industrials
170
+ ENPH;Enphase Energy;Information Technology
171
+ ETR;Entergy;Utilities
172
+ EOG;EOG Resources;Energy
173
+ EPAM;EPAM Systems;Information Technology
174
+ EQT;EQT Corporation;Energy
175
+ EFX;Equifax;Industrials
176
+ EQIX;Equinix;Real Estate
177
+ EQR;Equity Residential;Real Estate
178
+ ERIE;Erie Indemnity;Financials
179
+ ESS;Essex Property Trust;Real Estate
180
+ EL;Estée Lauder Companies (The);Consumer Staples
181
+ EG;Everest Group;Financials
182
+ EVRG;Evergy;Utilities
183
+ ES;Eversource Energy;Utilities
184
+ EXC;Exelon;Utilities
185
+ EXPE;Expedia Group;Consumer Discretionary
186
+ EXPD;Expeditors International;Industrials
187
+ EXR;Extra Space Storage;Real Estate
188
+ XOM;ExxonMobil;Energy
189
+ FFIV;F5, Inc.;Information Technology
190
+ FDS;FactSet;Financials
191
+ FICO;Fair Isaac;Information Technology
192
+ FAST;Fastenal;Industrials
193
+ FRT;Federal Realty Investment Trust;Real Estate
194
+ FDX;FedEx;Industrials
195
+ FIS;Fidelity National Information Services;Financials
196
+ FITB;Fifth Third Bancorp;Financials
197
+ FSLR;First Solar;Information Technology
198
+ FE;FirstEnergy;Utilities
199
+ FI;Fiserv;Financials
200
+ FMC;FMC Corporation;Materials
201
+ F;Ford Motor Company;Consumer Discretionary
202
+ FTNT;Fortinet;Information Technology
203
+ FTV;Fortive;Industrials
204
+ FOXA;Fox Corporation (Class A);Communication Services
205
+ FOX;Fox Corporation (Class B);Communication Services
206
+ BEN;Franklin Resources;Financials
207
+ FCX;Freeport-McMoRan;Materials
208
+ GRMN;Garmin;Consumer Discretionary
209
+ IT;Gartner;Information Technology
210
+ GE;GE Aerospace;Industrials
211
+ GEHC;GE HealthCare;Health Care
212
+ GEV;GE Vernova;Industrials
213
+ GEN;Gen Digital;Information Technology
214
+ GNRC;Generac;Industrials
215
+ GD;General Dynamics;Industrials
216
+ GIS;General Mills;Consumer Staples
217
+ GM;General Motors;Consumer Discretionary
218
+ GPC;Genuine Parts Company;Consumer Discretionary
219
+ GILD;Gilead Sciences;Health Care
220
+ GPN;Global Payments;Financials
221
+ GL;Globe Life;Financials
222
+ GDDY;GoDaddy;Information Technology
223
+ GS;Goldman Sachs;Financials
224
+ HAL;Halliburton;Energy
225
+ HIG;Hartford (The);Financials
226
+ HAS;Hasbro;Consumer Discretionary
227
+ HCA;HCA Healthcare;Health Care
228
+ DOC;Healthpeak Properties;Real Estate
229
+ HSIC;Henry Schein;Health Care
230
+ HSY;Hershey Company (The);Consumer Staples
231
+ HES;Hess Corporation;Energy
232
+ HPE;Hewlett Packard Enterprise;Information Technology
233
+ HLT;Hilton Worldwide;Consumer Discretionary
234
+ HOLX;Hologic;Health Care
235
+ HD;Home Depot (The);Consumer Discretionary
236
+ HON;Honeywell;Industrials
237
+ HRL;Hormel Foods;Consumer Staples
238
+ HST;Host Hotels & Resorts;Real Estate
239
+ HWM;Howmet Aerospace;Industrials
240
+ HPQ;HP Inc.;Information Technology
241
+ HUBB;Hubbell Incorporated;Industrials
242
+ HUM;Humana;Health Care
243
+ HBAN;Huntington Bancshares;Financials
244
+ HII;Huntington Ingalls Industries;Industrials
245
+ IBM;IBM;Information Technology
246
+ IEX;IDEX Corporation;Industrials
247
+ IDXX;Idexx Laboratories;Health Care
248
+ ITW;Illinois Tool Works;Industrials
249
+ INCY;Incyte;Health Care
250
+ IR;Ingersoll Rand;Industrials
251
+ PODD;Insulet Corporation;Health Care
252
+ INTC;Intel;Information Technology
253
+ ICE;Intercontinental Exchange;Financials
254
+ IFF;International Flavors & Fragrances;Materials
255
+ IP;International Paper;Materials
256
+ IPG;Interpublic Group of Companies (The);Communication Services
257
+ INTU;Intuit;Information Technology
258
+ ISRG;Intuitive Surgical;Health Care
259
+ IVZ;Invesco;Financials
260
+ INVH;Invitation Homes;Real Estate
261
+ IQV;IQVIA;Health Care
262
+ IRM;Iron Mountain;Real Estate
263
+ JBHT;J.B. Hunt;Industrials
264
+ JBL;Jabil;Information Technology
265
+ JKHY;Jack Henry & Associates;Financials
266
+ J;Jacobs Solutions;Industrials
267
+ JNJ;Johnson & Johnson;Health Care
268
+ JCI;Johnson Controls;Industrials
269
+ JPM;JPMorgan Chase;Financials
270
+ JNPR;Juniper Networks;Information Technology
271
+ K;Kellanova;Consumer Staples
272
+ KVUE;Kenvue;Consumer Staples
273
+ KDP;Keurig Dr Pepper;Consumer Staples
274
+ KEY;KeyCorp;Financials
275
+ KEYS;Keysight Technologies;Information Technology
276
+ KMB;Kimberly-Clark;Consumer Staples
277
+ KIM;Kimco Realty;Real Estate
278
+ KMI;Kinder Morgan;Energy
279
+ KKR;KKR;Financials
280
+ KLAC;KLA Corporation;Information Technology
281
+ KHC;Kraft Heinz;Consumer Staples
282
+ KR;Kroger;Consumer Staples
283
+ LHX;L3Harris;Industrials
284
+ LH;LabCorp;Health Care
285
+ LRCX;Lam Research;Information Technology
286
+ LW;Lamb Weston;Consumer Staples
287
+ LVS;Las Vegas Sands;Consumer Discretionary
288
+ LDOS;Leidos;Industrials
289
+ LEN;Lennar;Consumer Discretionary
290
+ LII;Lennox International;Industrials
291
+ LLY;Lilly (Eli);Health Care
292
+ LIN;Linde plc;Materials
293
+ LYV;Live Nation Entertainment;Communication Services
294
+ LKQ;LKQ Corporation;Consumer Discretionary
295
+ LMT;Lockheed Martin;Industrials
296
+ L;Loews Corporation;Financials
297
+ LOW;Lowe's;Consumer Discretionary
298
+ LULU;Lululemon Athletica;Consumer Discretionary
299
+ LYB;LyondellBasell;Materials
300
+ MTB;M&T Bank;Financials
301
+ MPC;Marathon Petroleum;Energy
302
+ MKTX;MarketAxess;Financials
303
+ MAR;Marriott International;Consumer Discretionary
304
+ MMC;Marsh McLennan;Financials
305
+ MLM;Martin Marietta Materials;Materials
306
+ MAS;Masco;Industrials
307
+ MA;Mastercard;Financials
308
+ MTCH;Match Group;Communication Services
309
+ MKC;McCormick & Company;Consumer Staples
310
+ MCD;McDonald's;Consumer Discretionary
311
+ MCK;McKesson Corporation;Health Care
312
+ MDT;Medtronic;Health Care
313
+ MRK;Merck & Co.;Health Care
314
+ META;Meta Platforms;Communication Services
315
+ MET;MetLife;Financials
316
+ MTD;Mettler Toledo;Health Care
317
+ MGM;MGM Resorts;Consumer Discretionary
318
+ MCHP;Microchip Technology;Information Technology
319
+ MU;Micron Technology;Information Technology
320
+ MSFT;Microsoft;Information Technology
321
+ MAA;Mid-America Apartment Communities;Real Estate
322
+ MRNA;Moderna;Health Care
323
+ MHK;Mohawk Industries;Consumer Discretionary
324
+ MOH;Molina Healthcare;Health Care
325
+ TAP;Molson Coors Beverage Company;Consumer Staples
326
+ MDLZ;Mondelez International;Consumer Staples
327
+ MPWR;Monolithic Power Systems;Information Technology
328
+ MNST;Monster Beverage;Consumer Staples
329
+ MCO;Moody's Corporation;Financials
330
+ MS;Morgan Stanley;Financials
331
+ MOS;Mosaic Company (The);Materials
332
+ MSI;Motorola Solutions;Information Technology
333
+ MSCI;MSCI;Financials
334
+ NDAQ;Nasdaq, Inc.;Financials
335
+ NTAP;NetApp;Information Technology
336
+ NFLX;Netflix;Communication Services
337
+ NEM;Newmont;Materials
338
+ NWSA;News Corp (Class A);Communication Services
339
+ NWS;News Corp (Class B);Communication Services
340
+ NEE;NextEra Energy;Utilities
341
+ NKE;Nike, Inc.;Consumer Discretionary
342
+ NI;NiSource;Utilities
343
+ NDSN;Nordson Corporation;Industrials
344
+ NSC;Norfolk Southern Railway;Industrials
345
+ NTRS;Northern Trust;Financials
346
+ NOC;Northrop Grumman;Industrials
347
+ NCLH;Norwegian Cruise Line Holdings;Consumer Discretionary
348
+ NRG;NRG Energy;Utilities
349
+ NUE;Nucor;Materials
350
+ NVDA;Nvidia;Information Technology
351
+ NVR;NVR, Inc.;Consumer Discretionary
352
+ NXPI;NXP Semiconductors;Information Technology
353
+ ORLY;O'Reilly Auto Parts;Consumer Discretionary
354
+ OXY;Occidental Petroleum;Energy
355
+ ODFL;Old Dominion;Industrials
356
+ OMC;Omnicom Group;Communication Services
357
+ ON;ON Semiconductor;Information Technology
358
+ OKE;ONEOK;Energy
359
+ ORCL;Oracle Corporation;Information Technology
360
+ OTIS;Otis Worldwide;Industrials
361
+ PCAR;Paccar;Industrials
362
+ PKG;Packaging Corporation of America;Materials
363
+ PLTR;Palantir Technologies;Information Technology
364
+ PANW;Palo Alto Networks;Information Technology
365
+ PARA;Paramount Global;Communication Services
366
+ PH;Parker Hannifin;Industrials
367
+ PAYX;Paychex;Industrials
368
+ PAYC;Paycom;Industrials
369
+ PYPL;PayPal;Financials
370
+ PNR;Pentair;Industrials
371
+ PEP;PepsiCo;Consumer Staples
372
+ PFE;Pfizer;Health Care
373
+ PCG;PG&E Corporation;Utilities
374
+ PM;Philip Morris International;Consumer Staples
375
+ PSX;Phillips 66;Energy
376
+ PNW;Pinnacle West;Utilities
377
+ PNC;PNC Financial Services;Financials
378
+ POOL;Pool Corporation;Consumer Discretionary
379
+ PPG;PPG Industries;Materials
380
+ PPL;PPL Corporation;Utilities
381
+ PFG;Principal Financial Group;Financials
382
+ PG;Procter & Gamble;Consumer Staples
383
+ PGR;Progressive Corporation;Financials
384
+ PLD;Prologis;Real Estate
385
+ PRU;Prudential Financial;Financials
386
+ PEG;Public Service Enterprise Group;Utilities
387
+ PTC;PTC Inc.;Information Technology
388
+ PSA;Public Storage;Real Estate
389
+ PHM;PulteGroup;Consumer Discretionary
390
+ PWR;Quanta Services;Industrials
391
+ QCOM;Qualcomm;Information Technology
392
+ DGX;Quest Diagnostics;Health Care
393
+ RL;Ralph Lauren Corporation;Consumer Discretionary
394
+ RJF;Raymond James Financial;Financials
395
+ RTX;RTX Corporation;Industrials
396
+ O;Realty Income;Real Estate
397
+ REG;Regency Centers;Real Estate
398
+ REGN;Regeneron Pharmaceuticals;Health Care
399
+ RF;Regions Financial Corporation;Financials
400
+ RSG;Republic Services;Industrials
401
+ RMD;ResMed;Health Care
402
+ RVTY;Revvity;Health Care
403
+ ROK;Rockwell Automation;Industrials
404
+ ROL;Rollins, Inc.;Industrials
405
+ ROP;Roper Technologies;Information Technology
406
+ ROST;Ross Stores;Consumer Discretionary
407
+ RCL;Royal Caribbean Group;Consumer Discretionary
408
+ SPGI;S&P Global;Financials
409
+ CRM;Salesforce;Information Technology
410
+ SBAC;SBA Communications;Real Estate
411
+ SLB;Schlumberger;Energy
412
+ STX;Seagate Technology;Information Technology
413
+ SRE;Sempra;Utilities
414
+ NOW;ServiceNow;Information Technology
415
+ SHW;Sherwin-Williams;Materials
416
+ SPG;Simon Property Group;Real Estate
417
+ SWKS;Skyworks Solutions;Information Technology
418
+ SJM;J.M. Smucker Company (The);Consumer Staples
419
+ SW;Smurfit WestRock;Materials
420
+ SNA;Snap-on;Industrials
421
+ SOLV;Solventum;Health Care
422
+ SO;Southern Company;Utilities
423
+ LUV;Southwest Airlines;Industrials
424
+ SWK;Stanley Black & Decker;Industrials
425
+ SBUX;Starbucks;Consumer Discretionary
426
+ STT;State Street Corporation;Financials
427
+ STLD;Steel Dynamics;Materials
428
+ STE;Steris;Health Care
429
+ SYK;Stryker Corporation;Health Care
430
+ SMCI;Supermicro;Information Technology
431
+ SYF;Synchrony Financial;Financials
432
+ SNPS;Synopsys;Information Technology
433
+ SYY;Sysco;Consumer Staples
434
+ TMUS;T-Mobile US;Communication Services
435
+ TROW;T. Rowe Price;Financials
436
+ TTWO;Take-Two Interactive;Communication Services
437
+ TPR;Tapestry, Inc.;Consumer Discretionary
438
+ TRGP;Targa Resources;Energy
439
+ TGT;Target Corporation;Consumer Staples
440
+ TEL;TE Connectivity;Information Technology
441
+ TDY;Teledyne Technologies;Information Technology
442
+ TFX;Teleflex;Health Care
443
+ TER;Teradyne;Information Technology
444
+ TSLA;Tesla, Inc.;Consumer Discretionary
445
+ TXN;Texas Instruments;Information Technology
446
+ TPL;Texas Pacific Land Corporation;Energy
447
+ TXT;Textron;Industrials
448
+ TMO;Thermo Fisher Scientific;Health Care
449
+ TJX;TJX Companies;Consumer Discretionary
450
+ TSCO;Tractor Supply;Consumer Discretionary
451
+ TT;Trane Technologies;Industrials
452
+ TDG;TransDigm Group;Industrials
453
+ TRV;Travelers Companies (The);Financials
454
+ TRMB;Trimble Inc.;Information Technology
455
+ TFC;Truist Financial;Financials
456
+ TYL;Tyler Technologies;Information Technology
457
+ TSN;Tyson Foods;Consumer Staples
458
+ USB;U.S. Bancorp;Financials
459
+ UBER;Uber;Industrials
460
+ UDR;UDR, Inc.;Real Estate
461
+ ULTA;Ulta Beauty;Consumer Discretionary
462
+ UNP;Union Pacific Corporation;Industrials
463
+ UAL;United Airlines Holdings;Industrials
464
+ UPS;United Parcel Service;Industrials
465
+ URI;United Rentals;Industrials
466
+ UNH;UnitedHealth Group;Health Care
467
+ UHS;Universal Health Services;Health Care
468
+ VLO;Valero Energy;Energy
469
+ VTR;Ventas;Real Estate
470
+ VLTO;Veralto;Industrials
471
+ VRSN;Verisign;Information Technology
472
+ VRSK;Verisk Analytics;Industrials
473
+ VZ;Verizon;Communication Services
474
+ VRTX;Vertex Pharmaceuticals;Health Care
475
+ VTRS;Viatris;Health Care
476
+ VICI;Vici Properties;Real Estate
477
+ V;Visa Inc.;Financials
478
+ VST;Vistra Corp.;Utilities
479
+ VMC;Vulcan Materials Company;Materials
480
+ WRB;W. R. Berkley Corporation;Financials
481
+ GWW;W. W. Grainger;Industrials
482
+ WAB;Wabtec;Industrials
483
+ WBA;Walgreens Boots Alliance;Consumer Staples
484
+ WMT;Walmart;Consumer Staples
485
+ DIS;Walt Disney Company (The);Communication Services
486
+ WBD;Warner Bros. Discovery;Communication Services
487
+ WM;Waste Management;Industrials
488
+ WAT;Waters Corporation;Health Care
489
+ WEC;WEC Energy Group;Utilities
490
+ WFC;Wells Fargo;Financials
491
+ WELL;Welltower;Real Estate
492
+ WST;West Pharmaceutical Services;Health Care
493
+ WDC;Western Digital;Information Technology
494
+ WY;Weyerhaeuser;Real Estate
495
+ WMB;Williams Companies;Energy
496
+ WTW;Willis Towers Watson;Financials
497
+ WDAY;Workday, Inc.;Information Technology
498
+ WYNN;Wynn Resorts;Consumer Discretionary
499
+ XEL;Xcel Energy;Utilities
500
+ XYL;Xylem Inc.;Industrials
501
+ YUM;Yum! Brands;Consumer Discretionary
502
+ ZBRA;Zebra Technologies;Information Technology
503
+ ZBH;Zimmer Biomet;Health Care
504
+ ZTS;Zoetis;Health Care
@@ -0,0 +1,10 @@
1
+ import pandas as pd
2
+
3
+ def csv_to_ticker_dict(csv_file_path="src/mypythproject/sp500_companies.csv", print_dict=False):
4
+ df = pd.read_csv(csv_file_path, delimiter=';')
5
+ ticker_dict = dict(zip(df['Symbol'], df['Security']))
6
+
7
+ if print_dict:
8
+ print(ticker_dict) # Only prints if you explicitly set print_dict=True
9
+
10
+ return ticker_dict