handepeh commited on
Commit
c3673f0
·
1 Parent(s): 2d2e9c5

Upload 3 files

Browse files
Files changed (4) hide show
  1. .gitattributes +1 -0
  2. app.py +127 -0
  3. data_and_sp500.csv +3 -0
  4. plots.py +212 -0
.gitattributes CHANGED
@@ -32,3 +32,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ data_and_sp500.csv filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from datetime import date, timedelta
3
+ #from rest_api.fetch_data import (get_symbol_data)
4
+ import pandas as pd
5
+ from plots import (
6
+ beta,
7
+ basic_portfolio,
8
+ #display_portfolio_return,
9
+ display_heat_map,
10
+ ER,
11
+ buble_interactive
12
+ )
13
+
14
+ def load_heading():
15
+ """The function that displays the heading.
16
+ Provides instructions to the user
17
+ """
18
+ with st.container():
19
+ st.title('Dataminers')
20
+ header = st.subheader('This App performs historical portfolio analysis and future analysis ')
21
+ st.subheader('Please read the instructions carefully and enjoy!')
22
+ # st.text('This is some text.')
23
+
24
+
25
+ def get_choices():
26
+ """Prompts the dialog to get the All Choices.
27
+ Returns:
28
+ An object of choices and an object of combined dataframes.
29
+ """
30
+ choices = {}
31
+
32
+ tickers = st.sidebar.text_input('Enter 4 stock symbols.', 'GOOG,A,AA,AMD')
33
+
34
+ # Set the weights
35
+ weights_str = st.sidebar.text_input('Enter The Investment Quantities', '50,30,25,25')
36
+ # Set Initial Investment
37
+ investment = st.sidebar.number_input('Enter The Initial Investment', min_value=5000, max_value=25000, value=5000)
38
+
39
+ # Every form must have a submit button.
40
+ submitted = st.sidebar.button("Submit")
41
+
42
+ symbols = []
43
+ reset = False
44
+
45
+ # Reusable Error Button DRY!
46
+ #def reset_app(error):
47
+ # st.sidebar.write(f"{error}!")
48
+ # st.sidebar.write(f"Check The Syntax")
49
+ # reset = st.sidebar.button("RESET APP")
50
+
51
+ if submitted:
52
+ # convert strings to lists
53
+ tickers_list = tickers.split(",")
54
+ weights_list = weights_str.split(",")
55
+ #crypto_symbols_list = crypto_symbols.split(",")
56
+ # Create the Symbols List
57
+ symbols.extend(tickers_list)
58
+ #symbols.extend(crypto_symbols_list)
59
+ # Convert Weights To Decimals
60
+ weights = []
61
+ for item in weights_list:
62
+ weights.append(float(item))
63
+
64
+ if reset:
65
+ # # Clears all singleton caches:
66
+ tickers = st.sidebar.selectbox('Enter 11 stock symbols.', ('GOOG','D','AAP','BLK'))
67
+ # crypto_symbols = st.sidebar.text_input('Enter 2 crypto symbols only as below', 'BTC-USD,ETH-USD')
68
+ weights_str = st.sidebar.text_input('Enter The Investment Weights', '0.3,0.3 ,0.3')
69
+
70
+ st.experimental_singleton.clear()
71
+
72
+
73
+ else:
74
+ # Submit an object with choices
75
+ choices = {
76
+
77
+ 'symbols': symbols,
78
+ 'weights': weights,
79
+ 'investment': investment
80
+
81
+ }
82
+ # Load combined_df
83
+ data = pd.read_csv('data_and_sp500.csv')
84
+ combined_df = data[tickers_list]
85
+ # return object of objects
86
+ return {
87
+ 'choices': choices,
88
+ 'combined_df': combined_df,
89
+ 'data': data
90
+ }
91
+
92
+
93
+ def run():
94
+ """The main function for running the script."""
95
+
96
+ load_heading()
97
+ choices = get_choices()
98
+ if choices:
99
+ st.success('''** Selected Tickers **''')
100
+ buble_interactive(choices['data'],choices['choices'])
101
+ st.header('Tickers Beta')
102
+ """
103
+ The Capital Asset Pricing Model (CAPM) utilizes a formula to enable the application to calculate
104
+ risk, return, and variability of return with respect to a benchmark. The application uses this
105
+ benchmark, currently S&P 500 annual rate of return, to calculate the return of a stock using
106
+ Figure 2 in Appendix A. Elements such as beta can be calculated using the formula in Appendix
107
+ A Figure 1. The beta variable will serve as a variable to be used for calculating the variability of
108
+ the stock with respect to the benchmark. This variability factor will prove useful for a variety of
109
+ calculations such as understanding market risk and return. If the beta is equal to 1.0, the stock
110
+ price is correlated with the market. When beta is smaller than 1.0, the stock is less volatile than
111
+ the market. If beta is greater than 1.0, the stock is more volatile than the market.
112
+ The CAPM model was run for 9 stocks, using 10-year daily historical data for initial test analysis.
113
+ With this initial analysis, beta was calculated to determine the stock’s risk by measuring the
114
+ price changes to the benchmark. By using CAPM model, annual expected return and portfolio
115
+ return is calculated. The model results can be found in Appendix A.
116
+ """
117
+ beta(choices['data'], choices['choices'])
118
+ ER(choices['data'], choices['choices'])
119
+ basic_portfolio(choices['combined_df'])
120
+ display_heat_map(choices['combined_df'])
121
+ #display_portfolio_return(choices['combined_df'], choices['choices'])
122
+
123
+
124
+
125
+ if __name__ == "__main__":
126
+ run()
127
+
data_and_sp500.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bb09e57e52edd4e875610fe2ed494af095e682ff26af6f6f7d33bc88b2771e98
3
+ size 18857073
plots.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import seaborn as sns
3
+ import streamlit as st
4
+ import matplotlib.pyplot as plt
5
+ import numpy as np
6
+ import altair as alt
7
+
8
+ def beta(stock_df, choices):
9
+ symbols, weights, investment = choices.values()
10
+ tickers = symbols
11
+ tickers.append('sp500')
12
+ #print(tickers)
13
+ quantity = weights
14
+ selected_stocks = stock_df[tickers]
15
+ # calculating daily return
16
+ # loops through each stocks
17
+ # loops through each row belonging to the stock
18
+ # calculates the percentage change from previous day
19
+ # sets the value of first row to zero since there is no previous value
20
+ df_stocks = selected_stocks.copy()
21
+
22
+ for i in selected_stocks.columns[1:]:
23
+ for j in range(1, len(selected_stocks)):
24
+ df_stocks[i][j] = ((selected_stocks[i][j] - selected_stocks[i][j - 1]) / selected_stocks[i][j - 1]) * 100
25
+ df_stocks[i][0] = 0
26
+ # calculate Beta and alpha for a single stock
27
+ # used sp500 as a benchmark
28
+ # used polyfit to calculate beta
29
+ beta_list = []
30
+ alpha_list = []
31
+ stocks_daily_return = df_stocks
32
+ for i in stocks_daily_return.columns:
33
+ if i != 'Date' and i != 'sp500':
34
+ # stocks_daily_return.plot(kind = 'scatter', x = 'A', y = i)
35
+ b, a = np.polyfit(stocks_daily_return['sp500'], stocks_daily_return[i], 1)
36
+ # plt.plot(stocks_daily_return['sp500'], b * stocks_daily_return['sp500'] + a, '-', color = 'r')
37
+ beta_list.append(round(b, 2))
38
+ alpha_list.append(round(a, 2))
39
+ # plt.show()
40
+ # Formats the results
41
+ symbols.remove('sp500')
42
+ beta = {'Assets': symbols, 'Beta': beta_list}
43
+ alpha = {'Assets': symbols, 'Alpha': alpha_list}
44
+ # Creates a header for streamlit
45
+ st.subheader('Beta and Alpha of Assets Compared to S&P500 index')
46
+ col1, col2 = st.columns(2)
47
+
48
+ with col1:
49
+ st.dataframe(beta)
50
+ with col2:
51
+ st.dataframe(alpha)
52
+
53
+
54
+ def ER(stock_df, choices):
55
+ symbols, weights, investment = choices.values()
56
+ symbols_ =symbols
57
+ tickers = symbols
58
+ tickers.append('sp500')
59
+ #print(tickers)
60
+ quantity = weights
61
+ selected_stocks = stock_df[tickers]
62
+ # calculating daily return
63
+ # loops through each stocks
64
+ # loops through each row belonging to the stock
65
+ # calculates the percentage change from previous day
66
+ # sets the value of first row to zero since there is no previous value
67
+ df_stocks = selected_stocks.copy()
68
+
69
+ for i in selected_stocks.columns[1:]:
70
+ for j in range(1, len(selected_stocks)):
71
+ df_stocks[i][j] = ((selected_stocks[i][j] - selected_stocks[i][j - 1]) / selected_stocks[i][j - 1]) * 100
72
+ df_stocks[i][0] = 0
73
+ beta = {}
74
+ alpha = {}
75
+ stocks_daily_return = df_stocks
76
+ # print(df_stocks)
77
+
78
+ for i in stocks_daily_return.columns:
79
+ if i != 'Date' and i != 'sp500':
80
+ # stocks_daily_return.plot(kind = 'scatter', x = 'A', y = i)
81
+ b, a = np.polyfit(stocks_daily_return['sp500'], stocks_daily_return[i], 1)
82
+ # plt.plot(stocks_daily_return['sp500'], b * stocks_daily_return['sp500'] + a, '-', color = 'r')
83
+ beta[i] = round(b, 2)
84
+ alpha[i] = round(a, 2)
85
+ # plt.show()
86
+
87
+ # calculating camp for a stock
88
+ keys = list(beta.keys())
89
+ ER_ = []
90
+ # rf = 0 assuming risk-free rate of 0
91
+ rf = 0
92
+ # rm - annualize retun
93
+ rm = stocks_daily_return['sp500'].mean() * 252
94
+ for i in keys:
95
+ ER_.append( round(rf + (beta[i] * (rm - rf)), 2))
96
+
97
+ #for i in keys:
98
+ # print('Expected Return based on CAPM for {} is {}%'.format(i, ER_[i]))
99
+ #print(ER)
100
+ symbols.remove('sp500')
101
+ st.subheader('Expected Annual Return Based on CAPM Model')
102
+
103
+ Expected_return = {'Assets': symbols, 'Expected Annual Return': ER_}
104
+ # Creates a header for streamlit
105
+ st.dataframe(Expected_return)
106
+
107
+
108
+ # calculate expected return for the portfolio
109
+ # portfolio weights assume equal
110
+ portfolio_weights = []
111
+ current_cash_value = 0
112
+ total_portfolio_value = 0
113
+ cash_value_stocks =[]
114
+ for i in range(len(tickers) ):
115
+ stocks_name = tickers[i]
116
+ current_cash_value = selected_stocks[stocks_name].iloc[-1]
117
+ stocks_quantity = quantity[i]
118
+ cash_value = stocks_quantity * current_cash_value
119
+ cash_value_stocks.append(cash_value)
120
+ total_portfolio_value += cash_value
121
+ portfolio_weights.append(cash_value)
122
+ #print(portfolio_weights)
123
+ portfolio_weights = (portfolio_weights / total_portfolio_value)*100
124
+ ER_portfolio= []
125
+ ER_portfolio = sum(list(ER_) * portfolio_weights)/100
126
+ print('aaa',ER_portfolio)
127
+
128
+ st.subheader('Expected Portfolio Return Based on CAPM Model')
129
+ # Creates a header for streamlit
130
+ st.write('Expected Portfolio Return is:', ER_portfolio)
131
+ return beta, cash_value_stocks
132
+
133
+
134
+
135
+ def basic_portfolio(stock_df):
136
+ """Uses the stock dataframe to graph the normalized historical cumulative returns of each asset.
137
+ """
138
+ # Calculates the daily returns of the inputted dataframe
139
+ daily_return = stock_df.dropna().pct_change()
140
+ # Calculates the cumulative return of the previously calculated daily return
141
+ cumulative_return = (1 + daily_return).cumprod()
142
+
143
+ # Creates the title for streamlit
144
+ st.subheader('Portfolio Historical Normalized Cumulative Returns')
145
+ # Graphs the cumulative returns
146
+ st.line_chart(cumulative_return)
147
+
148
+
149
+ def display_heat_map(stock_df):
150
+ """Uses the stock dataframe to calculate the correlations between the different assets and display them as a heatmap.
151
+ """
152
+ # Calcuilates the correlation of the assets in the portfolio
153
+ price_correlation = stock_df.corr()
154
+
155
+ # Creates the title for streamlit
156
+ st.subheader('Heatmap Showing Correlation Of Assets')
157
+ # Generates a figure for the heatmap
158
+ fig, ax = plt.subplots()
159
+ sns.heatmap(price_correlation, ax=ax)
160
+ # Displays the heatmap on streamlit
161
+ st.write(fig)
162
+ # Creates a header for the correlation data
163
+ st.subheader('Correlation Data')
164
+ # Displays the correlation data on streamlit
165
+ st.dataframe(price_correlation)
166
+
167
+
168
+ #def display_portfolio_return(stock_df, choices):
169
+ """Uses the stock dataframe and the chosen weights from choices to calculate and graph the historical cumulative portfolio return.
170
+ """
171
+ # symbols, weights, investment = choices.values()
172
+
173
+ # Calculates the daily percentage returns of the
174
+ # daily_returns = stock_df.pct_change().dropna()
175
+ # Applies the weights of each asset to the portfolio
176
+ # portfolio_returns = daily_returns.dot(weights)
177
+ # Calculates the cumulative weighted portfolio return
178
+ # cumulative_returns = (1 + portfolio_returns).cumprod()
179
+ # Calculates the cumulative profit using the cumulative portfolio return
180
+ # cumulative_profit = investment * cumulative_returns
181
+
182
+ # Graphs the result, and displays it with a header on streamlit
183
+ # st.subheader('Portfolio Historical Cumulative Returns Based On Inputs!')
184
+ # st.line_chart(cumulative_profit)
185
+
186
+ def buble_interactive(stock_df,choices):
187
+ import plotly.express as px
188
+ symbols, weights, investment = choices.values()
189
+ beta,cash_value_weights = ER(stock_df,choices)
190
+ my_list = []
191
+ for i in beta.values():
192
+ my_list.append(i)
193
+
194
+ df_final =pd.DataFrame()
195
+ df_final['ticker'] = symbols
196
+ df_final['quantities'] = weights
197
+ df_final['cash_value'] =cash_value_weights
198
+ df_final['Beta'] = my_list
199
+
200
+ fig = px.scatter(
201
+ df_final,
202
+ x="quantities",
203
+ y="Beta",
204
+ size="cash_value",
205
+ #color="continent",
206
+ hover_name="ticker",
207
+ log_x=True,
208
+ size_max=60,
209
+ )
210
+ fig.update_layout(title="Beta ----write something")
211
+ # -- Input the Plotly chart to the Streamlit interface
212
+ st.plotly_chart(fig, use_container_width=True)