mypythproject 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mypythproject-0.1.1/LICENSE +22 -0
- mypythproject-0.1.1/PKG-INFO +44 -0
- mypythproject-0.1.1/README.md +25 -0
- mypythproject-0.1.1/pyproject.toml +31 -0
- mypythproject-0.1.1/src/mypythproject/DashBoard.py +357 -0
- mypythproject-0.1.1/src/mypythproject/__init__.py +3 -0
- mypythproject-0.1.1/src/mypythproject/mypythproject.py +26 -0
- mypythproject-0.1.1/src/mypythproject/optimization_techniques.py +240 -0
- mypythproject-0.1.1/src/mypythproject/sp500_companies.csv +504 -0
- mypythproject-0.1.1/src/mypythproject/tickers.py +10 -0
@@ -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,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
|