Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
amitvkulkarni committed Mar 14, 2023
1 parent 38a2f6d commit 853da4d
Show file tree
Hide file tree
Showing 4 changed files with 646 additions and 0 deletions.
243 changes: 243 additions & 0 deletions Portfolio Simulator Using Python/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
import dash
import pandas as pd
import numpy as np
import dash_daq as daq
import plotly.graph_objs as go
import plotly.express as px
import plotly.figure_factory as ff
from dash import Dash, html, dcc
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from datetime import date
import layout
import dataload




app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

server = app.server


##################################################################
# The layout section
##################################################################

app.layout = layout.Financial_Portfolio_Layout


##################################################################
# The callback section
##################################################################
@app.callback(
[
Output('store-data', 'data'),
Output("alert-wip-data", "is_open")
],
[
Input("id-company-dropdown","value"),
Input("id-start-date","date"),
Input("id-end-date","date")
]
)
def update_storeData(company, start_date, end_date):
"""_summary_
Args:
company (List): Loads the data DCC data store with the stock data
Returns:
Dataframe: Returns a dataframe which has price data for selected companies
"""
s_year = int(start_date[0:4])
s_month = int(start_date[5:7])
s_day = int(start_date[8:10])

e_year = int(end_date[0:4])
e_month = int(end_date[5:7])
e_day = int(end_date[8:10])

s_date = date(s_year,s_month,s_day)
e_date = date(e_year,e_month,e_day)

try:
dataset = dataload.load_stock_data(s_date, e_date, company)

dataset.reset_index(inplace = True)
return dataset.to_dict('records'), True
except Exception as e:
print(f'An exception occurred while updating the data store: {e}')



@app.callback(
[
Output("id_low_risk", 'value'),
# Output("id_lowrisk_returns", 'value'),
Output("id_high_risk", 'value'),
# Output("id_highrisk_returns", 'value'),
Output("fig_allocation_low", 'figure'),
Output("alert-wip", "is_open"),
Output("fig_allocation_high", 'figure'),
Output("id-info_low", 'children'),
Output("id-info_high", 'children'),
],
[
Input('id-btn-create', 'n_clicks'),
State('id-company-dropdown', 'value'),
State('store-data', 'data'),
State("alert-wip", "is_open")
],
prevent_initial_call = True
)
def update_allocation(btn_create, company, data, val_is_open):
"""_summary_
Args:
company (List): Loads the data DCC data store with the stock data
data (Dataframe): The DCC data store which has the stock data
val_is_open (Boolean): A boolean value for displaying alert on successful generation of portfolio
Returns:
_type_: _description_
"""
button_id = dash.callback_context.triggered[0]['prop_id'].split('.')[0]
global df_risk

if button_id == 'id-btn-create':

try:
ddf = pd.DataFrame.from_records(data, index=['Date'])
ddf = ddf[ddf.columns & company]

ddf_returns = ddf.pct_change().dropna()
dd_returns = ddf_returns.copy()

ddf_cumulative = ddf_returns.copy()
ddf.reset_index(inplace = True)
ddf_returns.reset_index(inplace = True)


low_risk_wts, high_risk_wts, low_risk_return, low_risk_volatility, high_risk_return, high_risk_volatility, df_risk = dataload.sim_bootstrap(dd_returns, company)

fig_allocation_low_risk = px.pie(values = low_risk_wts, names = company, hole= 0.3)
fig_allocation_high_risk = px.pie(values = high_risk_wts, names = company, hole= 0.3)



return [low_risk_volatility,
# low_risk_return,
high_risk_volatility,
# high_risk_return,
fig_allocation_low_risk,
True,
fig_allocation_high_risk,
html.Div(f'At 95% confidence, the maximum loss expected will be {low_risk_volatility} %', id="id-info_low",style={'display': 'block', 'color': 'blue', 'fontSize': 15, 'font-weight': 'bold', "text-align": "center"}),
html.Div(f'At 95% confidence, the maximum loss expected will be {high_risk_volatility} %', id="id-info_low",style={'display': 'block', 'color': 'blue', 'fontSize': 15, 'font-weight': 'bold', "text-align": "center"}),
]


except Exception as e:
print(f'An exception occurred while executing update_trendsChart(): {e}')

else:
return [None,
# None,
None,
# None,
layout.blank_fig(),
None,
layout.blank_fig(),
None,
None]





@app.callback(
Output("fig_trends", 'figure'),
[
Input('id-btn-create', 'n_clicks'),
Input('id-analysis-options', 'value'),
State('id-company-dropdown', 'value'),
State('store-data', 'data')
],
prevent_initial_call=True
)
def update_trends(btn_create, option_selected, company, data):

""" Stock trends analysis
Returns:
String: The radio button selection value
"""


try:

ddf = pd.DataFrame.from_records(data, index=['Date'])
ddf = ddf[ddf.columns & company]

ddf_returns = ddf.pct_change().dropna()
dd_returns = ddf_returns.copy()

ddf_cumulative = ddf_returns.copy()

ddf.reset_index(inplace = True)
ddf_returns.reset_index(inplace = True)

# low_risk_wts, high_risk_wts, low_risk_return, low_risk_volatility, high_risk_return, high_risk_volatility, df_risk = dataload.sim_bootstrap(dd_returns, company)


if option_selected == 'STOCK PRICE TRENDS':

fig_price = px.line(ddf, x="Date", y = ddf.columns, template="simple_white")
return fig_price

elif option_selected == 'STOCK RETURNS TRENDS':

fig_returns = px.line(ddf_returns, x="Date", y = ddf_returns.columns, template="simple_white")
return fig_returns

elif option_selected == 'CUMULATIVE RETURNS':

df_cumulative = (ddf_cumulative+1).cumprod()
df_cumulative.reset_index(inplace = True)

fig_cumulative = px.line(df_cumulative, x="Date", y = df_cumulative.columns, template="simple_white")
return fig_cumulative

elif option_selected == 'VOLATILITY IN RETURNS':
# df_risk['Risk'] = df_risk['Risk'].abs()
df_risk['Risk'] = df_risk['Risk'] * 100
fig_risk_returns = px.scatter(df_risk, x = 'Risk', y = 'Returns')
return fig_risk_returns

else:
return layout.blank_fig()

except Exception as e:
print(f'An exception occurred while executing update_trendsChart(): {e}')






if __name__ == "__main__":
app.run_server(debug=True, use_reloader=False)



123 changes: 123 additions & 0 deletions Portfolio Simulator Using Python/dataload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import pandas as pd
import numpy as np
import datetime
from datetime import date
from nsepy import get_history as gh



##################################################################
# Data Loading
##################################################################
def load_stock_data(start_date, end_date, ticker):
"""_summary_
Args:
start_date (Date): Start data for stock selection
end_date (Date): End date for stock selection
ticker (List): List of stocks
Returns:
Dataframe: price data for selected stock for a selected period
"""
try:
df = pd.DataFrame()

for i in range(len(ticker)):
data = gh(symbol=ticker[i],start= start_date, end=end_date)[['Symbol','Close']]
data.rename(columns={'Close':data['Symbol'][0]},inplace=True)
data.drop(['Symbol'], axis=1,inplace=True)
if i == 0:
df = data

if i != 0:
df = df.join(data)


return df
except Exception as e:
print(f'An exception occurred while executing data load: {e}')




##################################################################
# Data Loading
##################################################################

def sim_portfolio(weights, dd_returns):
"""_summary_
Args:
weights (List): Weights for each of the stock
Returns:
Float: Returns the risk at 95% percentile
"""
try:
tmp_pp = (weights * dd_returns.values).sum(axis=1)
var_sim_port = np.percentile(tmp_pp, 5, interpolation = 'lower')
return var_sim_port
except Exception as e:
print(f'An exception occurred while executing sim_portfolio: {e}')


def sim_bootstrap(dd_returns, company):
"""_summary_
Args:
dd_returns (Dataframe): the dataframe which has stock returns.
company (List): List of stocks
Returns:
int: returns various metrics
"""

try:

port_returns = []
port_volatility = []
port_weights = []

num_assets = len(company)
num_portfolios = 100
np.random.seed(1357)
for port in range(num_portfolios):
weights = np.random.random(num_assets)
weights = weights/sum(weights)
port_weights.append(weights)
df_wts_returns = dd_returns.mean().dot(weights)
port_returns.append(df_wts_returns*100)

var_port_95 = sim_portfolio(weights, dd_returns)
port_volatility.append(var_port_95)


port_weights = [wt for wt in port_weights]
dff = {'Returns': port_returns, 'Risk': port_volatility, 'Weights': port_weights}
df_risk = pd.DataFrame(dff)

min_risk = df_risk.iloc[df_risk['Risk'].idxmax()]

# low_risk_return = f'{round(abs(min_risk[0]),4)*100:.2f}'
# low_risk_volatility = f'{round(abs(min_risk[1]),4)*100:.2f}'
low_risk_return = f'{round((min_risk[0]),4)*100:.2f}'
low_risk_volatility = f'{round((min_risk[1]),4)*100:.2f}'
low_risk_wts = min_risk[2]

print(f'{low_risk_volatility} and {low_risk_return}')


max_risk = df_risk.iloc[df_risk['Risk'].idxmin()]
# high_risk_return = f'{round(abs(max_risk[0]),4)*100:.2f}'
# high_risk_volatility = f'{round(abs(max_risk[1]),4)*100:.2f}'
high_risk_return = f'{round((max_risk[0]),4)*100:.2f}'
high_risk_volatility = f'{round((max_risk[1]),4)*100:.2f}'
high_risk_wts = max_risk[2]

print(f'{high_risk_volatility} and {high_risk_return}')

return low_risk_wts, high_risk_wts, low_risk_return,low_risk_volatility, high_risk_return, high_risk_volatility, df_risk

except Exception as e:
print(f'An exception occurred while executing sim_bootstrap: {e}')
Loading

0 comments on commit 853da4d

Please sign in to comment.