| import streamlit as st |
| from datetime import date, timedelta |
| |
| import pandas as pd |
| from PIL import Image |
| import time |
|
|
| from plots import ( |
| beta, |
| basic_portfolio, |
| |
| display_heat_map, |
| |
| ER, |
| buble_interactive |
| ) |
|
|
| |
| from ef import( |
| ef_viz |
| ) |
| def risk_str(num): |
| if num >=5 and num <15: |
| return 'Low Risk Aversion' |
| elif num >= 15 and num <25: |
| return 'Medium Risk Aversion' |
| elif num >= 25 and num <=35: |
| return 'High Risk Aversion' |
| |
| |
| from sharp_ratio import( |
| cumulative_return, |
| |
| sharp_ratio_func |
| ) |
|
|
| from arima import ( |
| |
| arima_chart |
| ) |
|
|
|
|
| |
| def load_heading(): |
| """The function that displays the heading. |
| Provides instructions to the user |
| """ |
| with st.container(): |
| st.title('Dataminers') |
| header = st.subheader('This App performs historical portfolio analysis and future analysis ') |
| st.subheader('Please read the instructions carefully and enjoy!') |
| |
|
|
|
|
| def get_choices(): |
| """Prompts the dialog to get the All Choices. |
| Returns: |
| An object of choices and an object of combined dataframes. |
| """ |
| choices = {} |
| |
|
|
| tickers = st.sidebar.text_input('Enter stock tickers.', 'GOOG,AA,AVGO,AMD') |
|
|
| |
| weights_str = st.sidebar.text_input('Enter the investment quantities', '50,30,25,25') |
|
|
| benchmark = st.sidebar.selectbox( |
| 'Select your ideal benchmark of return', |
| ('SP500', 'AOK', 'IXIC')) |
| if benchmark == 'IXIC': |
| st.sidebar.warning("You have selected a volatile benchmark.") |
| elif benchmark == 'SP500': |
| st.sidebar.success('You have selected a balanced benchmark') |
| elif benchmark == 'AOK': |
| st.sidebar.success('You have selected a conservative benchmark') |
|
|
| |
| rf = st.sidebar.number_input('Enter current rate of risk free return', min_value=0.001, max_value=1.00, value=0.041) |
|
|
|
|
| |
| A_coef = st.sidebar.slider('Enter The Coefficient of Risk Aversion', min_value=5, max_value=35, value=30, step=5) |
|
|
| if A_coef > 20: |
| st.sidebar.success("You have selected a "+ risk_str(A_coef) +" investing style") |
| investing_style = 'Conservative' |
| elif A_coef >10 and A_coef <= 20: |
| st.sidebar.success("You have selected a "+risk_str(A_coef) +" investing style") |
| investing_style = 'Balanced' |
| elif A_coef <= 10: |
| st.sidebar.warning("You have selected a "+ risk_str(A_coef) +" investing style") |
| investing_style = 'Risky' |
|
|
| |
| submitted = st.sidebar.button("Calculate") |
|
|
| symbols = [] |
| reset = False |
|
|
| |
| |
| |
| |
| |
|
|
| if submitted: |
| |
| |
| |
| |
| tickers_list = tickers.split(",") |
| weights_list = weights_str.split(",") |
| |
| |
| symbols.extend(tickers_list) |
| |
| |
| weights = [] |
| for item in weights_list: |
| weights.append(float(item)) |
|
|
| if reset: |
| |
| |
| |
| |
|
|
| st.experimental_singleton.clear() |
|
|
|
|
| else: |
| |
| choices = { |
|
|
| 'symbols': symbols, |
| 'weights': weights, |
| 'benchmark': benchmark, |
| 'investing_style': investing_style, |
| 'risk-free-rate': rf, |
| 'A-coef': A_coef |
|
|
| } |
| |
| data = pd.read_csv('data_and_sp500.csv') |
| combined_df = data[tickers_list] |
| raw_data=pd.read_csv('us-shareprices-daily.csv', sep=';') |
| |
| return { |
| 'choices': choices, |
| 'combined_df': combined_df, |
| 'data': data, |
| 'raw_data':raw_data |
| } |
|
|
|
|
| def run(): |
| """The main function for running the script.""" |
|
|
| load_heading() |
| choices = get_choices() |
| if choices: |
| st.success('''** Selected Tickers **''') |
| buble_interactive(choices['data'],choices['choices']) |
| st.header('Tickers Beta') |
| """ |
| The Capital Asset Pricing Model (CAPM) utilizes a formula to enable the application to calculate |
| risk, return, and variability of return with respect to a benchmark. The application uses this |
| benchmark, currently S&P 500 annual rate of return, to calculate the return of a stock using |
| Figure 2 in Appendix A. Elements such as beta can be calculated using the formula in Appendix |
| A Figure 1. The beta variable will serve as a variable to be used for calculating the variability of |
| the stock with respect to the benchmark. This variability factor will prove useful for a variety of |
| calculations such as understanding market risk and return. If the beta is equal to 1.0, the stock |
| price is correlated with the market. When beta is smaller than 1.0, the stock is less volatile than |
| the market. If beta is greater than 1.0, the stock is more volatile than the market. |
| The CAPM model was run for 9 stocks, using 10-year daily historical data for initial test analysis. |
| With this initial analysis, beta was calculated to determine the stock’s risk by measuring the |
| price changes to the benchmark. By using CAPM model, annual expected return and portfolio |
| return is calculated. The model results can be found in Appendix A. |
| """ |
| |
| beta(choices['data'], choices['choices']) |
| ER(choices['data'], choices['choices']) |
| |
| st.header('CAPM Model and the Efficient Frontier') |
| """ |
| CAPM model measures systematic risks, however many of it's functions have unrealistic assumptions and rely heavily on a linear interpretation |
| of the risks vs. returns relationship. It is better to use CAPM model in conjunction with the Efficient Frontier to better |
| graphically depict volatility (a measure of investment risk) for the defined rate of return. \n |
| Below we map the linear Utility function from the CAPM economic model along with the Efficient Frontier |
| Each circle depicted above is a variation of the portfolio with the same input asset, only different weights. |
| Portfolios with higher volatilities have a yellower shade of hue, while portfolios with a higher return have a larger radius. \n |
| As you input different porfolio assets, take note of how diversification can improve a portfolio's risk versus reward profile. |
| """ |
| ef_viz(choices['data'],choices['choices']) |
| """ |
| There are in fact two components of the Efficient Frontier: the Efficient Frontier curve itself and the Minimum Variance Frontier. |
| The lower curve, which is also the Minimum Variance Frontier will contain assets in the portfolio |
| that has the lowest volatility. If our portfolio contains "safer" assets such as Governmental Bonds, the further to the right |
| of the lower curve we will see a portfolio that contains only these "safe" assets, the portfolios on |
| this curve, in theory, will have diminishing returns.\n |
| The upper curve, which is also the Efficient Frontier, contains portfolios that have marginally increasing returns as the risks |
| increases. In theory, we want to pick a portfolio on this curve, as these portfolios contain more balanced weights of assets |
| with acceptable trade-offs between risks and returns. \n |
| If an investor is more comfortable with investment risks, they can pick a portfolio on the right side of the Efficient Frontier. |
| Whereas, a conservative investor might want to pick a portfolio from the left side of the Efficient Frontier. \n |
| Take notes of the assets' Betas and how that changes the shape of the curve as well. \n |
| How does the shape of the curve change when |
| the assets are of similar Beta vs when they are all different?\n |
| Note the behavior of the curve when the portfolio contains only assets with Betas higher than 1 vs. when Betas are lower than 1.\n |
| |
| """ |
| |
| |
| st.subheader('Portfolio Historical Normalized Cumulative Returns') |
| """ |
| Cumulative Returns:\n |
| The cumulative return of an asset is calculated by subtracting the original price paid from the current profit or loss. This answers the question, |
| what is the return on my initial investment?\n |
| The graph below shows the historical normalized cumulative returns for each of the chosen assets for the entire time period of the available data. |
| The default line chart shows tickers AA, AMD, AVGO, and GOOG and we can see that all have a positive cumulative return over the period of the available data. |
| Any of these assets purchased on the starting day and sold on the ending day for the period would have earned a return on their investment.\n |
| This chart can also be used to analyze the correlation of the returns of the chosen assets over the displayed period. |
| Any segments of the line charts that show cumulative returns with similarly or oppositely angled segments can be considered to have some level of |
| correlation during those periods. |
| """ |
| basic_portfolio(choices['combined_df']) |
| """ |
| Negative Correlations (1): \n |
| Occur for assets whose cumulative returns move in opposite directions. When one goes up the other goes down and vice versa. |
| These negatively correlated assets would offer some level of diversification protection to each other. |
| Perfectly negatively correlated stocks are sort of the goal, but unlikely to be common. |
| In most cases finding some level of negatively correlated stocks, should offer some level of diversification protection to your portfolio. |
| The amount of protection depends upon the calculated metric. Our tool includes some CAPM analysis, which attempts to relate the risk and return |
| and the correlation of assets to determine the expected portfolio returns versus the combined, hopefully reduced, risk.\n |
| |
| Positive Correlations (2):\n |
| Occur for assets whose cumulative returns move in concert. When one goes up the other also goes up and vice versa. |
| These positively correlated assets would not offer much or any diversification protection to each other.\n |
| """ |
| im = Image.open('1vs2.png') |
| col1, col2, col3 = st.columns([1,6,1]) |
|
|
| with col1: |
| st.write("") |
| |
| with col2: |
| st.image(im, caption='Trends of Assets Correlations',use_column_width='auto') |
| |
| with col3: |
| st.write("") |
| |
| |
| st.subheader('Heatmap Showing Correlation Of Assets') |
| """ |
| Heatmap: \n |
| The Heat map shows the overall correlation of each asset to the other assets. Notice that the middle diagonal row is filled in with all 1’s. |
| That is because they are all perfectly correlated with themselves. A value of 1 equates to perfect correlation, -1 equates to perfect negative correlation, |
| and 0 equates to no correlation with values in between being relative to their distance from the extremes. A correlation value of .5 would mean |
| the asset moves half as much in the same direction as the correlated asset. A values of -0.5 would mean it moves half as much in the opposite direction |
| as the correlated asset. \n |
| The Heat map shows the correlation coefficient or value for each asset over the entire period to each other asset. |
| It also depicts the color of the intersection as darker for less correlation and lighter for more correlation, which could be either positive or negative. |
| The legend on the right indicates the absolute level of correlation for each color, again positive or negative associated to each color.\n |
| """ |
| |
| display_heat_map(choices['data'],choices['choices']) |
| |
| |
| cumulative_return(choices['combined_df'], choices['choices']) |
| sharp_ratio_func(choices['raw_data'], choices['choices']) |
|
|
| ''' |
| ARIMA:\n |
| ''' |
|
|
| arima_chart(choices['choices']['symbols']) |
|
|
| |
|
|
| if __name__ == "__main__": |
| run() |
|
|
|
|