|
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() |
|
|
|
|