From 94832d06457b71ce57232b3c6ac04930a3a13e66 Mon Sep 17 00:00:00 2001 From: yuhigawa Date: Mon, 13 Dec 2021 09:55:37 -0300 Subject: [PATCH 1/4] FIX: data display in Markowitz App --- frontend/pages/ai_models_app.py | 230 +++++++++----------------- frontend/pages/markowitz/Markowits.py | 128 +++++++++----- frontend/pages/markowitz_app.py | 38 ++++- 3 files changed, 200 insertions(+), 196 deletions(-) diff --git a/frontend/pages/ai_models_app.py b/frontend/pages/ai_models_app.py index e03169d..4aad5ce 100644 --- a/frontend/pages/ai_models_app.py +++ b/frontend/pages/ai_models_app.py @@ -36,10 +36,8 @@ def load_csv(name): st.sidebar.header('Informações para simulação') st.sidebar.warning('Clique em simulação para retreinar o modelo') - from_year = st.sidebar.number_input( - 'Data Inicial', format='%d', value=2019, min_value=2000, max_value=2022, step=1) - to_year = st.sidebar.number_input( - 'Data Final', format='%d', value=2020, min_value=2000, max_value=2022, step=1) + from_year = st.sidebar.number_input('Data Inicial', format='%d', value=2019, min_value=2000, max_value=2022, step=1) + to_year = st.sidebar.number_input('Data Final', format='%d', value=2020, min_value=2000, max_value=2022, step=1) if from_year > to_year: st.sidebar.error("Data Inicial maior que a Final") @@ -48,21 +46,16 @@ def load_csv(name): deploy = st.sidebar.checkbox('Simulação?') if deploy: - train_size_value = st.sidebar.number_input( - 'Treino %', value=80, min_value=0, max_value=90, step=10) + train_size_value = st.sidebar.number_input('Treino %', value=80, min_value=0, max_value=90, step=10) - test_size_value = st.sidebar.number_input('Teste %', value=int( - 90 - train_size_value), min_value=0, max_value=int(90 - train_size_value), step=10) + test_size_value = st.sidebar.number_input('Teste %', value=int(90 - train_size_value), min_value=0, max_value=int(90 - train_size_value), step=10) - deploy_size = st.sidebar.number_input('Simulação %', value=int(100 - (train_size_value + test_size_value)), min_value=int( - 100 - (train_size_value + test_size_value)), max_value=int(100 - (train_size_value + test_size_value)), step=10) + deploy_size = st.sidebar.number_input('Simulação %', value=int(100 - (train_size_value + test_size_value)), min_value=int(100 - (train_size_value + test_size_value)), max_value=int(100 - (train_size_value + test_size_value)), step=10) simular = st.sidebar.button(label='Simular') else: - train_size_value = st.sidebar.number_input( - 'Treino %', value=80, min_value=0, max_value=90, step=10) - test_size_value = st.sidebar.number_input('Teste %', value=int( - 100 - (train_size_value)), min_value=int(100 - train_size_value), max_value=int(100 - train_size_value), step=10) + train_size_value = st.sidebar.number_input('Treino %', value=80, min_value=0, max_value=90, step=10) + test_size_value = st.sidebar.number_input('Teste %', value=int(100 - (train_size_value)), min_value=int(100 - train_size_value), max_value=int(100 - train_size_value), step=10) for ativo in assets: if '-' not in ativo: @@ -77,13 +70,11 @@ def load_csv(name): st.line_chart(data['Close']) else: for model in models: - r_summary = requests.get( - 'https://btk-ai-app.herokuapp.com/setups/svr_model/', json={'name': ativo}) + r_summary = requests.get('https://btk-ai-app.herokuapp.com/setups/svr_model/', json={'name': ativo}) model_summary = r_summary.json()['summary'] - df = load_data( - ativo + '.SA', str(int(from_year)), str(int(to_year))) + df = load_data(ativo + '.SA', str(int(from_year)), str(int(to_year))) df['Date'] = df.index @@ -92,8 +83,7 @@ def load_csv(name): df = df[str(int(from_year)):str(int(to_year))] - df['log_return'] = np.log( - df['Close']/df['Close'].shift(-1)) + df['log_return'] = np.log(df['Close']/df['Close'].shift(-1)) df['diff'] = df['High'] - df['Low'] @@ -103,85 +93,52 @@ def load_csv(name): df['ma_15'] = df['diff'].rolling(window=15).mean() df['ma_30'] = df['diff'].rolling(window=30).mean() - df.loc[df['ma_2'] > df['ma_2'].shift( - 1), 'tend_2'] = 1 - df.loc[df['ma_2'] < df['ma_2'].shift( - 1), 'tend_2'] = -1 - df.loc[df['ma_2'] == df['ma_2'].shift( - 1), 'tend_2'] = 0 - - df.loc[df['ma_5'] > df['ma_5'].shift( - 4), 'tend_5'] = 1 - df.loc[df['ma_5'] < df['ma_5'].shift( - 4), 'tend_5'] = -1 - df.loc[df['ma_5'] == df['ma_5'].shift( - 4), 'tend_5'] = 0 - - df.loc[df['ma_10'] > df['ma_10'].shift( - 9), 'tend_10'] = 1 - df.loc[df['ma_10'] < df['ma_10'].shift( - 9), 'tend_10'] = -1 - df.loc[df['ma_10'] == df['ma_10'].shift( - 9), 'tend_10'] = 0 - - df.loc[df['ma_15'] > df['ma_15'].shift( - 14), 'tend_15'] = 1 - df.loc[df['ma_15'] < df['ma_15'].shift( - 14), 'tend_15'] = -1 - df.loc[df['ma_15'] == df['ma_15'].shift( - 14), 'tend_15'] = 0 - - df.loc[df['ma_30'] > df['ma_30'].shift( - 29), 'tend_30'] = 1 - df.loc[df['ma_30'] < df['ma_30'].shift( - 29), 'tend_30'] = -1 - df.loc[df['ma_30'] == df['ma_30'].shift( - 29), 'tend_30'] = 0 - - df['desv_2'] = df['log_return'].rolling( - window=2).std() - df['desv_5'] = df['log_return'].rolling( - window=5).std() - df['desv_10'] = df['log_return'].rolling( - window=10).std() - df['desv_15'] = df['log_return'].rolling( - window=15).std() - df['desv_30'] = df['log_return'].rolling( - window=30).std() - - df.loc[(df['Close'] > df['Close'].shift(2)) & - df['desv_2'].notnull(), 'var_2'] = df['desv_2'] - df.loc[(df['Close'] < df['Close'].shift(2)), - 'var_2'] = -df['desv_2'] - - df.loc[(df['Close'] > df['Close'].shift(5)) & - df['desv_5'].notnull(), 'var_5'] = df['desv_5'] - df.loc[(df['Close'] < df['Close'].shift(5)), - 'var_5'] = -df['desv_5'] - - df.loc[(df['Close'] > df['Close'].shift(10)) & - df['desv_10'].notnull(), 'var_10'] = df['desv_10'] - df.loc[(df['Close'] < df['Close'].shift(10)), - 'var_10'] = -df['desv_10'] - - df.loc[(df['Close'] > df['Close'].shift(15)) & - df['desv_15'].notnull(), 'var_15'] = df['desv_15'] - df.loc[(df['Close'] < df['Close'].shift(15)), - 'var_15'] = -df['desv_15'] - - df.loc[(df['Close'] > df['Close'].shift(30)) & - df['desv_30'].notnull(), 'var_30'] = df['desv_30'] - df.loc[(df['Close'] < df['Close'].shift(30)), - 'var_30'] = -df['desv_30'] + df.loc[df['ma_2'] > df['ma_2'].shift(1), 'tend_2'] = 1 + df.loc[df['ma_2'] < df['ma_2'].shift(1), 'tend_2'] = -1 + df.loc[df['ma_2'] == df['ma_2'].shift(1), 'tend_2'] = 0 + + df.loc[df['ma_5'] > df['ma_5'].shift(4), 'tend_5'] = 1 + df.loc[df['ma_5'] < df['ma_5'].shift(4), 'tend_5'] = -1 + df.loc[df['ma_5'] == df['ma_5'].shift(4), 'tend_5'] = 0 + + df.loc[df['ma_10'] > df['ma_10'].shift(9), 'tend_10'] = 1 + df.loc[df['ma_10'] < df['ma_10'].shift(9), 'tend_10'] = -1 + df.loc[df['ma_10'] == df['ma_10'].shift(9), 'tend_10'] = 0 + + df.loc[df['ma_15'] > df['ma_15'].shift(14), 'tend_15'] = 1 + df.loc[df['ma_15'] < df['ma_15'].shift(14), 'tend_15'] = -1 + df.loc[df['ma_15'] == df['ma_15'].shift(14), 'tend_15'] = 0 + + df.loc[df['ma_30'] > df['ma_30'].shift(29), 'tend_30'] = 1 + df.loc[df['ma_30'] < df['ma_30'].shift(29), 'tend_30'] = -1 + df.loc[df['ma_30'] == df['ma_30'].shift(29), 'tend_30'] = 0 + + df['desv_2'] = df['log_return'].rolling(window=2).std() + df['desv_5'] = df['log_return'].rolling(window=5).std() + df['desv_10'] = df['log_return'].rolling(window=10).std() + df['desv_15'] = df['log_return'].rolling(window=15).std() + df['desv_30'] = df['log_return'].rolling(window=30).std() + + df.loc[(df['Close'] > df['Close'].shift(2)) & df['desv_2'].notnull(), 'var_2'] = df['desv_2'] + df.loc[(df['Close'] < df['Close'].shift(2)), 'var_2'] = -df['desv_2'] + + df.loc[(df['Close'] > df['Close'].shift(5)) & df['desv_5'].notnull(), 'var_5'] = df['desv_5'] + df.loc[(df['Close'] < df['Close'].shift(5)), 'var_5'] = -df['desv_5'] + + df.loc[(df['Close'] > df['Close'].shift(10)) & df['desv_10'].notnull(), 'var_10'] = df['desv_10'] + df.loc[(df['Close'] < df['Close'].shift(10)), 'var_10'] = -df['desv_10'] + + df.loc[(df['Close'] > df['Close'].shift(15)) & df['desv_15'].notnull(), 'var_15'] = df['desv_15'] + df.loc[(df['Close'] < df['Close'].shift(15)), 'var_15'] = -df['desv_15'] + + df.loc[(df['Close'] > df['Close'].shift(30)) & df['desv_30'].notnull(), 'var_30'] = df['desv_30'] + df.loc[(df['Close'] < df['Close'].shift(30)), 'var_30'] = -df['desv_30'] df['ma_2'].fillna(df['ma_2'].mean(), inplace=True) df['ma_5'].fillna(df['ma_5'].mean(), inplace=True) - df['ma_10'].fillna( - df['ma_10'].mean(), inplace=True) - df['ma_15'].fillna( - df['ma_15'].mean(), inplace=True) - df['ma_30'].fillna( - df['ma_30'].mean(), inplace=True) + df['ma_10'].fillna(df['ma_10'].mean(), inplace=True) + df['ma_15'].fillna(df['ma_15'].mean(), inplace=True) + df['ma_30'].fillna(df['ma_30'].mean(), inplace=True) df['tend_2'].fillna(0, inplace=True) df['tend_5'].fillna(0, inplace=True) @@ -189,51 +146,35 @@ def load_csv(name): df['tend_15'].fillna(0, inplace=True) df['tend_30'].fillna(0, inplace=True) - df['desv_2'].fillna( - df['desv_2'].median(), inplace=True) - df['var_2'].fillna( - df['var_2'].median(), inplace=True) + df['desv_2'].fillna(df['desv_2'].median(), inplace=True) + df['var_2'].fillna(df['var_2'].median(), inplace=True) - df['desv_5'].fillna( - df['desv_5'].median(), inplace=True) - df['var_5'].fillna( - df['var_5'].median(), inplace=True) + df['desv_5'].fillna(df['desv_5'].median(), inplace=True) + df['var_5'].fillna(df['var_5'].median(), inplace=True) - df['desv_10'].fillna( - df['desv_10'].median(), inplace=True) - df['var_10'].fillna( - df['var_10'].median(), inplace=True) + df['desv_10'].fillna(df['desv_10'].median(), inplace=True) + df['var_10'].fillna(df['var_10'].median(), inplace=True) - df['desv_15'].fillna( - df['desv_15'].median(), inplace=True) - df['var_15'].fillna( - df['var_15'].median(), inplace=True) + df['desv_15'].fillna(df['desv_15'].median(), inplace=True) + df['var_15'].fillna(df['var_15'].median(), inplace=True) - df['desv_30'].fillna( - df['desv_30'].median(), inplace=True) - df['var_30'].fillna( - df['var_30'].median(), inplace=True) + df['desv_30'].fillna(df['desv_30'].median(), inplace=True) + df['var_30'].fillna(df['var_30'].median(), inplace=True) data_ativo = deepcopy(df) - df.drop(['Volume', 'Adj Close', 'log_return', 'tend_2', 'tend_5', - 'tend_10', 'tend_15', 'tend_30', 'Date'], axis=1, inplace=True) + df.drop(['Volume', 'Adj Close', 'log_return', 'tend_2', 'tend_5', 'tend_10', 'tend_15', 'tend_30', 'Date'], axis=1, inplace=True) list_to_pred = df.iloc[-1].tolist() - y_pred = requests.get('https://btk-ai-app.herokuapp.com/setups/svr_model/predict', json={ - 'name': ativo, 'data': list_to_pred}) + y_pred = requests.get('https://btk-ai-app.herokuapp.com/setups/svr_model/predict', json={'name': ativo, 'data': list_to_pred}) - st.subheader( - f'{ativo} - Modelo {model} de {int(from_year)} até {int(to_year)}') + st.subheader(f'{ativo} - Modelo {model} de {int(from_year)} até {int(to_year)}') if deploy: - train_value = int( - len(data_ativo)*((1-deploy_size/100) - train_size_value/100)) - test_value = int( - len(data_ativo)*((1-deploy_size/100) - test_size_value/100)) - deploy_value = int( - len(data_ativo)*((train_size_value/100 + test_size_value/100)) - deploy_size/100) + train_value = int(len(data_ativo)*((1-deploy_size/100) - train_size_value/100)) + test_value = int(len(data_ativo)*((1-deploy_size/100) - test_size_value/100)) + deploy_value = int(len(data_ativo)*((train_size_value/100 + test_size_value/100)) - deploy_size/100) __treino = go.Scatter( x=data_ativo['Date'].iloc[:test_value], @@ -267,10 +208,8 @@ def load_csv(name): showgrid=False), yaxis=dict(showgrid=False)) else: - train_value = int( - len(data_ativo)*(1 - train_size_value/100)) - test_value = int( - len(data_ativo)*(1 - test_size_value/100)) + train_value = int(len(data_ativo)*(1 - train_size_value/100)) + test_value = int(len(data_ativo)*(1 - test_size_value/100)) deploy_value = len(data_ativo) __treino = go.Scatter( @@ -291,14 +230,11 @@ def load_csv(name): scatter_data = [__treino, __teste] group_labels = ['Treino', 'Teste'] - layout = go.Layout(legend=dict(traceorder="reversed"), xaxis=dict( - showgrid=False), yaxis=dict(showgrid=False)) + layout = go.Layout(legend=dict(traceorder="reversed"), xaxis=dict(showgrid=False), yaxis=dict(showgrid=False)) fig = go.Figure() - fig.update_xaxes( - gridwidth=1, gridcolor='#444') - fig.update_yaxes( - gridwidth=1, gridcolor='#444') + fig.update_xaxes(gridwidth=1, gridcolor='#444') + fig.update_yaxes(gridwidth=1, gridcolor='#444') fig.add_trace(__treino) fig.add_trace(__teste) @@ -327,14 +263,11 @@ def load_csv(name): } if simular: - response = requests.get( - f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/fit', json=json) + response = requests.get(f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/fit', json=json) if response.status_code == 200: - r_summary = requests.get( - f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/', json={'name': ativo}) - model_summary = r_summary.json()[ - 'summary'] + r_summary = requests.get(f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/', json={'name': ativo}) + model_summary = r_summary.json()['summary'] else: json = { 'name': ativo, @@ -345,12 +278,10 @@ def load_csv(name): 'deploy_size': 0.0 } - response = requests.get( - f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/fit', json=json) + response = requests.get(f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/fit', json=json) if response.status_code == 200: - r_summary = requests.get( - f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/', json={'name': ativo}) + r_summary = requests.get(f'https://btk-ai-app.herokuapp.com/setups/{model.lower()}_model/', json={'name': ativo}) model_summary = r_summary.json()['summary'] with st.expander('Mais detalhes'): @@ -364,5 +295,4 @@ def load_csv(name): st.subheader('Histórico do modelo') st.write(data.tail(10)) st.subheader('Relatório do modelo') - st.download_button( - 'Documento', data=f'static/docs/{ativo}/{model}.pdf', file_name=f'{ativo}_{model}_BTK.pdf') + st.download_button('Documento', data=f'static/docs/{ativo}/{model}.pdf', file_name=f'{ativo}_{model}_BTK.pdf') diff --git a/frontend/pages/markowitz/Markowits.py b/frontend/pages/markowitz/Markowits.py index 54073d2..fdc5f4a 100644 --- a/frontend/pages/markowitz/Markowits.py +++ b/frontend/pages/markowitz/Markowits.py @@ -14,18 +14,21 @@ def markowitz(df_symbols: pd.DataFrame, st): + + @st.cache(allow_output_mutation=True) def plot_normalized_price(df): fig = plt.figure(figsize=(16, 8)) ax = plt.axes() ax.set_title('Normalized Price Plot') ax.plot(df[-252:]/df.iloc[-252] * 100) + ax.legend(df.columns, loc='upper left') ax.grid(True) return fig - + @st.cache(allow_output_mutation=True) def plot_annualized_returns(annual_returns): fig = plt.figure() ax = plt.axes() @@ -36,7 +39,7 @@ def plot_annualized_returns(annual_returns): return fig - + @st.cache(allow_output_mutation=True) def plot_annualized_volatility(annual_vols): fig = plt.figure() ax = plt.axes() @@ -46,7 +49,7 @@ def plot_annualized_volatility(annual_vols): return fig - + @st.cache(allow_output_mutation=True) def plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets): fig = plt.figure() ax = plt.axes() @@ -54,12 +57,10 @@ def plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets): ax.set_title('Monte Carlo Simulated Allocation') # Simulated portfolios - fig.colorbar(ax.scatter(port_vols, port_rets, c=port_rets / port_vols, - marker='o', cmap='RdYlGn', edgecolors='black'), label='Sharpe Ratio') + fig.colorbar(ax.scatter(port_vols, port_rets, c=port_rets / port_vols, marker='o', cmap='RdYlGn', edgecolors='black'), label='Sharpe Ratio') # Maximum sharpe ratio portfolio - ax.scatter(msrp['volatility'], msrp['returns'], c='red', - marker='*', s=300, label='Max Sharpe Ratio') + ax.scatter(msrp['volatility'], msrp['returns'], c='red', marker='*', s=300, label='Max Sharpe Ratio') ax.set_xlabel('Expected Volatility') ax.set_ylabel('Expected Return') @@ -67,7 +68,7 @@ def plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets): return fig - + @st.cache(allow_output_mutation=True) def portfolio_stats(weights, returns): weights = np.array(weights)[:, np.newaxis] port_rets = weights.T @ np.array(returns.mean() * 252)[:, np.newaxis] @@ -164,14 +165,70 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra # VaR Histórico pCVaR_90, pCVaR_95, pCVaR_99, pHVaR_90, pHVaR_95, pHVaR_99 = CVar_Port(dict_data['weight'][int(index)], returns) - # st.write(f"Acoes: {symbols}") - st.write(f"Retorno : {np.round(dict_data['retorno'][int(index)]*100,2)}% \t | Volatilidade : {np.round(dict_data['volatilidade'][int(index)]*100,2)}% \t | Indice Sharpe : {np.round((dict_data['retorno'][int(index)]/dict_data['volatilidade'][int(index)]),2)}") + + # dict_data_weights = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][int(index)]] + df_atv_table_dict_data = pd.DataFrame( + np.array([[ f'Referente ao indice {index} da fronteira eficiente', + np.round(dict_data['retorno'][int(index)]*100,2), + np.round(dict_data['volatilidade'][int(index)]*100,2), + np.round((dict_data['retorno'][int(index)]/dict_data['volatilidade'][int(index)]),2), + dict_data['weight'][int(index)] + ]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write(f"Carteira referente a fronteira eficiente") + # st.table(df_atv_table_dict_data) + + # pesos_acao_print = + # st.write(f"Pesos para cada ação: {pesos_acao_print}") + # st.write("VaR Paramétrico \n90 :", np.round(pVaR_90*100, 2), "/95 :", np.round(pVaR_95*100, 2), "/99 :", np.round(pVaR_99*100, 2)) + # st.write("VaR Histórico \n90 :", np.round(pHVaR_90*100, 2), "/95 :", np.round(pHVaR_95*100, 2), "/99 :", np.round(pHVaR_99*100, 2)) + # st.write("CVaR Histórico \n 90 :", np.round(pCVaR_90*100, 2), "/95 :", np.round(pCVaR_95*100, 2), "/99 :", np.round(pCVaR_99*100, 2)) + + df_atv_table_opt_sharpe = pd.DataFrame( + np.array([[ 'Maior Indice Sharpe', + np.round(portfolio_stats(opt_sharpe['x'], returns)[0]*100,2), + np.round(portfolio_stats(opt_sharpe['x'], returns)[1]*100,2), + np.round(portfolio_stats(opt_sharpe['x'], returns)[2],2), + np.round(opt_sharpe['x']*100,2)]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write('\nCarteira Fundamentalista com maior Indice Sharpe') + # st.table(df_atv_table_opt_sharpe) + + df_atv_table_opt_var = pd.DataFrame( + np.array([[ 'Menor volatilidade', + np.round(portfolio_stats(opt_var['x'], returns)[0]*100, 2), + np.round(portfolio_stats(opt_var['x'], returns)[1]*100, 2), + np.round(portfolio_stats(opt_var['x'], returns)[2], 2), + np.round(opt_var['x']*100, 2)]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write('\nCarteira Fundamentalista com menor volatilidade') + # st.table(df_atv_table_opt_var) + + + df_atv_table_fundamentalista = pd.DataFrame( + np.array([[ 'Portfolio inserido', + np.round(portfolio_stats(array_weights, returns)[0]*100,2), + np.round(portfolio_stats(array_weights, returns)[1]*100,2), + np.round(portfolio_stats(array_weights, returns)[2],2), + np.round(array_weights*100,2)]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write('\nCarteira Fundamentalista') + # st.table(df_atv_table_fundamentalista) + + wallets_merge = {} + wallets_merge['Carteira referente a fronteira eficiente'] = df_atv_table_dict_data + wallets_merge['Carteira Fundamentalista Com maior Indice Sharpe'] = df_atv_table_opt_sharpe + wallets_merge['Carteira Fundamentalista Com menor volatilidade'] = df_atv_table_opt_var + # wallets_merge['Carteira Fundamentalista'] = df_atv_table_fundamentalista + - pesos_acao_print = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][int(index)]] - st.write(f"Pesos para cada ação: {pesos_acao_print}") - st.write("VaR Paramétrico \n90 :", np.round(pVaR_90*100, 2), "/95 :", np.round(pVaR_95*100, 2), "/99 :", np.round(pVaR_99*100, 2)) - st.write("VaR Histórico \n90 :", np.round(pHVaR_90*100, 2), "/95 :", np.round(pHVaR_95*100, 2), "/99 :", np.round(pHVaR_99*100, 2)) - st.write("CVaR Histórico \n 90 :", np.round(pCVaR_90*100, 2), "/95 :", np.round(pCVaR_95*100, 2), "/99 :", np.round(pCVaR_99*100, 2)) + df_all_wallet = pd.concat([df_atv_table_dict_data, df_atv_table_opt_sharpe, df_atv_table_opt_var, df_atv_table_fundamentalista]) + # df_all_wallet = pd.DataFrame([wallets_merge]) + st.table( df_all_wallet ) + + + # st.write(f"Retorno : {np.round(portfolio_stats(array_weights)[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(array_weights)[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(array_weights)[2],2)) + # st.write("Pesos : ", np.round(array_weights*100,2)) # st.write('\nCarteira Fundamentalista Com maior Indice Sharpe ') # st.write(f"Retorno : {np.round(portfolio_stats(opt_sharpe['x'])[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(opt_sharpe['x'])[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(opt_sharpe['x'])[2],2)) @@ -218,13 +275,8 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra wts = numofasset * [1./numofasset] wts = np.array(wts)[:, np.newaxis] - array_weights = np.array([[0.15], [0.05], [0.07], [0.15], [0.05], [0.14], [0.15], [0.15], [0.05], [0.04]]) - ret = np.array(returns.mean() * 252)[:, np.newaxis] - - cov = returns.cov() * 252 - var = multi_dot([wts.T, cov, wts]) - - w = np.random.random(numofasset)[:, np.newaxis] + array_weights = np.full((numofasset, 1), 1/numofasset) + # array_weights = np.array([[0.15], [0.05], [0.07], [0.15], [0.05], [0.14], [0.15], [0.15], [0.05], [0.04]]) # Initialize the lists rets = [] @@ -258,7 +310,6 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra }) msrp = msrp_df.iloc[msrp_df['sharpe_ratio'].idxmax()] - max_sharpe_port_wts = msrp_df['weights'][msrp_df['sharpe_ratio'].idxmax()] fig = plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets) st.pyplot(fig) @@ -268,13 +319,10 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra initial_wts = numofasset*[1./numofasset] opt_sharpe = sco.minimize(min_sharpe_ratio, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=cons) - stats = ['Returns', 'Volatility', 'Sharpe Ratio'] opt_var = sco.minimize(min_variance, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=cons) array_weights = array_weights.flatten() - data = pd.DataFrame(columns=['Retorno', 'Volatilidade', 'Indice Sharpe', 'pesos']) - targetrets = np.linspace(port_rets.min(), port_rets.max(), 250) tvols = [] @@ -287,7 +335,7 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra opt_ef = sco.minimize(min_volatility, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=ef_cons) tvols.append(opt_ef['fun']) - tweights.append(opt_ef['x']) + tweights.append(np.round(opt_ef['x'], 2)) targetweights = np.array(tweights) targetvols = np.array(tvols) @@ -299,23 +347,23 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra dict_data['sharpe'] = targetrets/targetvols dict_data['weight'] = targetweights - st.write(f"Weight len: {len(dict_data['weight'])}") - st.write(f"Vol len: {len(dict_data['volatilidade'])}") - st.write(f"Return len: {len(dict_data['retorno'])}") + # index_dict = [i for i in range(len(dict_data["retorno"])) if round(dict_data["retorno"][i], 4) % portfolio_stats(array_weights, returns)[0] <= 0.005] - index_dict = [i for i in range(len(dict_data["retorno"])) if round(dict_data["retorno"][i], 4) % portfolio_stats(array_weights, returns)[0] <= 0.005] + # retorno_print = np.round(dict_data['retorno'][index_dict[0] - 1], 2) + # vol_print = np.round(dict_data['volatilidade'][index_dict[0] - 1], 2) + # weights_plot = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][index_dict[0] - 1]] - retorno_print = np.round(dict_data['retorno'][index_dict[0] - 1], 2) - vol_print = np.round(dict_data['volatilidade'][index_dict[0] - 1], 2) - weights_plot = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][index_dict[0] - 1]] + # df_atv_table = pd.DataFrame( np.array([[retorno_print, vol_print, weights_plot]]), columns=['Retorno', 'Volatilidade', 'Peso']) + # st.table(df_atv_table) - st.write(f"Retorno: {retorno_print}") - st.write(f"volatilidade: {vol_print}") - st.write(f"weight: {weights_plot}") - st.write(f"somaweight: {sum(dict_data['weight'][index_dict[0] - 1])*100}") + # st.write(f"Retorno: {retorno_print}") + # st.write(f"volatilidade: {vol_print}") + # st.write(f"weight: {weights_plot}") + # st.write(f"somaweight: {sum(dict_data['weight'][index_dict[0] - 1])*100}") index_dict = wallet_reposition("retorno", array_weights, dict_data, opt_sharpe, returns) - # plot_index = st.slider('Movimento sua cartira dentro da fronteira eficiente', 0, 249, 1) - fig = plot_int(0, targetvols, targetrets, opt_sharpe, opt_var, dict_data, array_weights, returns, st) + # TODO: when the slider is pressed the page can't reload + plot_index = st.slider('Movimento sua cartira dentro da fronteira eficiente', 0, 249, 1) + fig = plot_int(plot_index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, array_weights, returns, st) st.pyplot(fig) \ No newline at end of file diff --git a/frontend/pages/markowitz_app.py b/frontend/pages/markowitz_app.py index f3e6bff..13c54cd 100644 --- a/frontend/pages/markowitz_app.py +++ b/frontend/pages/markowitz_app.py @@ -8,9 +8,7 @@ from pages.markowitz.Markowits import markowitz - class MarkowitzApp: - def home(self, st): @st.cache @@ -39,15 +37,43 @@ def load_json(): assets = st.sidebar.multiselect('Selecione sua carteira de ativos', symbols) if len(assets) >= 2: + # TODO: O USUÁRIO COLOCAR A PORCENTAGEM DE CAPITAL PARA CADA ATIVO + + # st.sidebar.markdown('Deseja colocar porcentagem dividida para cada ativo?') + # weight_button = st.sidebar.button('Sim') + + # if weight_button: + # st.write('-------') + # wallet_weights = [] + # max_weight = 100.0 + + # for asset in assets: + # porcentagem = st.sidebar.number_input(f'Porcentagem aplicada em {asset}', format='%f', value=1.0, min_value=1.0, max_value=float(max_weight), step=1.0) + # max_weight = int(max_weight - porcentagem) + + # # train_size_value = st.sidebar.number_input('Treino %', value=80, min_value=0, max_value=90, step=10) + # # test_size_value = st.sidebar.number_input('Teste %', value=int(90 - train_size_value), min_value=0, max_value=int(90 - train_size_value), step=10) + # # deploy_size = st.sidebar.number_input('Simulação %', value=int(100 - (train_size_value + test_size_value)), min_value=int(100 - (train_size_value + test_size_value)), max_value=int(100 - (train_size_value + test_size_value)), step=10) + + # print(f'max_weight: {max_weight}') + + # wallet_weights.append(porcentagem) + + # st.sidebar.write(wallet_weights) + # st.sidebar.write('-------') + from_year = st.sidebar.number_input('Data Inicial', format='%d', value=2019, min_value=2000, max_value=2022, step=1) to_year = st.sidebar.number_input('Data Final', format='%d', value=2020, min_value=2000, max_value=2022, step=1) - + if from_year > to_year: - st.sidebar.error("Data Inicial maior que a Final") + st.sidebar.error('Data Inicial maior que a Final') else: ok = st.sidebar.button('Aplicar Markowitz') - + if ok: - df_symbols = yf.download(assets, start=f'{from_year}-01-01', end=f'{to_year}-12-31', progress=False)['Close'] + print(f'from_year: {from_year} | to_year: {to_year}') + df_symbols = yf.download(assets, start=f'{str(from_year)}-01-01', end=f'{str(to_year)}-12-31', progress=False)['Close'] + + df_symbols.dropna(axis=0, inplace=True) markowitz(df_symbols, st) \ No newline at end of file From 27ac18775a3bd43bd4d47ed23baaad92f082bee0 Mon Sep 17 00:00:00 2001 From: yuhigawa Date: Mon, 13 Dec 2021 10:11:11 -0300 Subject: [PATCH 2/4] FIX: gitignore repetitive lines --- .gitignore | 53 ++++++++++++++------------- frontend/pages/markowitz/Markowits.py | 6 --- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 96d161c..b133db4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,13 +4,29 @@ btk_api_env/* *.pyc *.log -backend/authentication/__pycache__ -backend/authentication/__pycache__/* -backend/backend/__pycache__/ -frontend/pages/__pycache__/ -backend/authentication/migrations/* +frontend/pages/__pycache__ +frontend/pages/__pycache__/* + +frontend/pages/markowitz/__pycache__/* +frontend/pages/markowitz/__pycache__ + backend/db.sqlite3 + datalake/logs/ +datalake/dags/__pycache__ +datalake/dags/__pycache__/* + +*/btk_env +btk_env/ +btk_env + +backend/db.sqlite3 + +backend/backend/__pycache__/ +backend/authentication/migrations/* + +backend/authentication/__pycache__ +backend/authentication/__pycache__/* backend/setups/ai_models/strategies/__pycache__ backend/setups/ai_models/strategies/__pycache__/* @@ -18,37 +34,22 @@ backend/setups/ai_models/strategies/__pycache__/* backend/setups/ai_models/svm/__pycache__ backend/setups/ai_models/svm/__pycache__/* -*/btk_env -btk_env/ - -btk_env backend/setups/ai_models/strategies/__pycache__/ backend/setups/ai_models/strategies/__pycache__/* -backend/setups/ai_models/strategies/__pycache__/svr_model.cpython-38.pyc -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc -backend/db.sqlite3 backend/static/saved_models/ backend/static/saved_models/BIDI11/SVR_summary_deploy.pkl backend/static/saved_models/BIDI11/SVR_summary.pkl backend/static/saved_models/BIDI11/SVR.pkl + +backend/static/saved_models/ITUB4/SVR_summary_deploy.pkl backend/static/saved_models/ITUB4/SVR_summary.pkl backend/static/saved_models/ITUB4/SVR.pkl + +backend/static/saved_models/PETR4/SVR_summary_deploy.pkl backend/static/saved_models/PETR4/SVR_summary.pkl backend/static/saved_models/PETR4/SVR.pkl + backend/static/saved_models/VALE3/SVR_summary_deploy.pkl backend/static/saved_models/VALE3/SVR_summary.pkl -backend/static/saved_models/VALE3/SVR.pkl -backend/static/saved_models/BIDI11/SVR_summary_deploy.pkl -backend/setups/ai_models/strategies/__pycache__/svr_model.cpython-38.pyc -<<<<<<< HEAD -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc -backend/setups/ai_models/strategies/__pycache__/svr_model.cpython-38.pyc -backend/setups/ai_models/strategies/__pycache__/svr_model.cpython-38.pyc -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc -======= -backend/setups/ai_models/svm/__pycache__/svm.cpython-38.pyc ->>>>>>> master +backend/static/saved_models/VALE3/SVR.pkl \ No newline at end of file diff --git a/frontend/pages/markowitz/Markowits.py b/frontend/pages/markowitz/Markowits.py index fdc5f4a..7e41da3 100644 --- a/frontend/pages/markowitz/Markowits.py +++ b/frontend/pages/markowitz/Markowits.py @@ -215,12 +215,6 @@ def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, arra # st.write('\nCarteira Fundamentalista') # st.table(df_atv_table_fundamentalista) - wallets_merge = {} - wallets_merge['Carteira referente a fronteira eficiente'] = df_atv_table_dict_data - wallets_merge['Carteira Fundamentalista Com maior Indice Sharpe'] = df_atv_table_opt_sharpe - wallets_merge['Carteira Fundamentalista Com menor volatilidade'] = df_atv_table_opt_var - # wallets_merge['Carteira Fundamentalista'] = df_atv_table_fundamentalista - df_all_wallet = pd.concat([df_atv_table_dict_data, df_atv_table_opt_sharpe, df_atv_table_opt_var, df_atv_table_fundamentalista]) # df_all_wallet = pd.DataFrame([wallets_merge]) From 43a4e9f46abf1696985b5549a00fb3755aa86ba2 Mon Sep 17 00:00:00 2001 From: yuhigawa Date: Sat, 18 Dec 2021 13:55:52 -0300 Subject: [PATCH 3/4] F in the chat --- frontend/pages/markowitz_app.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/frontend/pages/markowitz_app.py b/frontend/pages/markowitz_app.py index 13c54cd..b785efd 100644 --- a/frontend/pages/markowitz_app.py +++ b/frontend/pages/markowitz_app.py @@ -6,7 +6,7 @@ import plotly.express as px import plotly.graph_objects as go -from pages.markowitz.Markowits import markowitz +from pages.markowitz_plot.markowits_plot import plot_normalized_price, plot_annualized_returns, plot_annualized_volatility, plot_monte_carlo_simulated_allocation, plot_int class MarkowitzApp: def home(self, st): @@ -71,9 +71,29 @@ def load_json(): ok = st.sidebar.button('Aplicar Markowitz') if ok: - print(f'from_year: {from_year} | to_year: {to_year}') - df_symbols = yf.download(assets, start=f'{str(from_year)}-01-01', end=f'{str(to_year)}-12-31', progress=False)['Close'] + json_data = { + 'start_date': from_year, + 'end_date': to_year, + 'assets': assets + } - df_symbols.dropna(axis=0, inplace=True) + response_data = requests.get('http://localhost:8000/tools/markowitz/', json=json_data) - markowitz(df_symbols, st) \ No newline at end of file + try: + df_data = response_data.json()['assets_data'] + try: + fig = plot_normalized_price(df_data) + st.pyplot(fig) + except: + st.error('Erro ao mostrar o gráfico de dados normalizados') + except: + st.error('Erro ao receber os dados normalizados') + + + + # print(f'from_year: {from_year} | to_year: {to_year}') + # df_symbols = yf.download(assets, start=f'{str(from_year)}-01-01', end=f'{str(to_year)}-12-31', progress=False)['Close'] + + # df_symbols.dropna(axis=0, inplace=True) + + # markowitz(df_symbols, st) \ No newline at end of file From ef0e4757d8253ee7857a89230ccdf60610774a6c Mon Sep 17 00:00:00 2001 From: yuhigawa Date: Sat, 18 Dec 2021 13:56:03 -0300 Subject: [PATCH 4/4] f f --- backend/tools/markowitz/markowits.py | 193 ++++++++++ backend/tools/views.py | 24 +- frontend/pages/markowitz/Markowits.py | 363 ------------------ .../pages/markowitz_plot/markowitz_plot.py | 166 ++++++++ 4 files changed, 382 insertions(+), 364 deletions(-) create mode 100644 backend/tools/markowitz/markowits.py delete mode 100644 frontend/pages/markowitz/Markowits.py create mode 100644 frontend/pages/markowitz_plot/markowitz_plot.py diff --git a/backend/tools/markowitz/markowits.py b/backend/tools/markowitz/markowits.py new file mode 100644 index 0000000..d43b49d --- /dev/null +++ b/backend/tools/markowitz/markowits.py @@ -0,0 +1,193 @@ +import pandas as pd +import numpy as np +import yfinance as yf +import scipy.optimize as sco + +from numpy.linalg import multi_dot +from scipy.stats import norm +from tabulate import tabulate + +def markowitz(df_symbols: pd.DataFrame, st): + def portfolio_stats(weights, returns): + weights = np.array(weights)[:, np.newaxis] + port_rets = weights.T @ np.array(returns.mean() * 252)[:, np.newaxis] + port_vols = np.sqrt(multi_dot([weights.T, returns.cov() * 252, weights])) + + return np.array([port_rets, port_vols, port_rets/port_vols]).flatten() + + + def min_sharpe_ratio(weights, returns): + return -portfolio_stats(weights, returns)[2] + + + def min_variance(weights, returns): + return portfolio_stats(weights, returns)[1]**2 + + + def min_volatility(weights, returns): + return portfolio_stats(weights, returns)[1] + + + def wallet_reposition(reposition, array_weights, dict_data, opt_sharpe, returns): + data = array_weights + + if reposition == "retorno": + index_port = 0 + if reposition == "volatilidade": + index_port = 1 + if reposition == "sharpe": + index_port = 2 + data = opt_sharpe['x'] + + if len([i for i in range(len(dict_data[reposition])) if round(dict_data[reposition][i], 4) % portfolio_stats(data, returns)[index_port] <= 0.005]): + return [i for i in range(len(dict_data[reposition])) if round(dict_data[reposition][i], 4) % portfolio_stats(array_weights, returns)[index_port] <= 0.005][0] - 1 + + return None + + + def Var_Port(weights, returns): + port_ret = np.dot(returns, weights) + port_mean = port_ret.mean() + port_mean + + port_stdev = np.sqrt(multi_dot([weights.T, returns.cov(), weights])) + port_stdev.flatten()[0] + + pVaR_90 = norm.ppf(1-0.90, port_mean, port_stdev).flatten()[0] + pVaR_95 = norm.ppf(1-0.95, port_mean, port_stdev).flatten()[0] + pVaR_99 = norm.ppf(1-0.99, port_mean, port_stdev).flatten()[0] + + return pVaR_90, pVaR_95, pVaR_99 + + + def CVar_Port(weights, returns): + Port = np.dot(returns, weights) + Port.sort() + + hVaR_99 = np.quantile(Port, 0.01) + hVaR_95 = np.quantile(Port, 0.05) + hVaR_90 = np.quantile(Port, 0.1) + + CVaR_90 = Port[Port <= hVaR_90].mean() + CVaR_95 = Port[Port <= hVaR_95].mean() + CVaR_99 = Port[Port <= hVaR_99].mean() + + return CVaR_90, CVaR_95, CVaR_99, hVaR_90, hVaR_95, hVaR_99 + + + df = df_symbols.copy(deep=True) + + numofasset = len(df.columns) + numofportfolio = 5000 + + returns = df.pct_change().dropna() + + # fig = plot_normalized_price(df) + # st.pyplot(fig) + + annual_returns = (returns.mean() * 252) + + # fig = plot_annualized_returns(annual_returns) + # st.pyplot(fig) + + vols = returns.std() + annual_vols = vols*np.sqrt(252) + + # fig = plot_annualized_volatility(annual_vols) + # st.pyplot(fig) + + wts = numofasset * [1./numofasset] + wts = np.array(wts)[:, np.newaxis] + + array_weights = np.full((numofasset, 1), 1/numofasset) + # array_weights = np.array([[0.15], [0.05], [0.07], [0.15], [0.05], [0.14], [0.15], [0.15], [0.05], [0.04]]) + + # Initialize the lists + rets = [] + vols = [] + wts = [] + + # Simulate 5,000 portfoliosplot_index + for i in range(5000): + # Generate random weights + weights = np.random.random(numofasset)[:, np.newaxis] + # st.write(weights) + # Set weights such that sum of weights equals 1 + + weights /= sum(weights) + # st.write(weights) + # Portfolio statistics + rets.append(weights.T @ np.array(returns.mean() * 252)[:, np.newaxis]) + vols.append(np.sqrt(multi_dot([weights.T, returns.cov()*252, weights]))) + wts.append(weights.flatten()) + + # Record values + port_rets = np.array(rets).flatten() + port_vols = np.array(vols).flatten() + port_wts = np.array(wts) + + msrp_df = pd.DataFrame({ + 'returns': port_rets, + 'volatility': port_vols, + 'sharpe_ratio': (port_rets - 0.015)/port_vols, + 'weights': list(port_wts) + }) + + msrp = msrp_df.iloc[msrp_df['sharpe_ratio'].idxmax()] + + # fig = plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets) + # st.pyplot(fig) + + cons = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) + bnds = tuple((0, 1) for x in range(numofasset)) + initial_wts = numofasset*[1./numofasset] + + opt_sharpe = sco.minimize(min_sharpe_ratio, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=cons) + + opt_var = sco.minimize(min_variance, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=cons) + array_weights = array_weights.flatten() + + targetrets = np.linspace(port_rets.min(), port_rets.max(), 250) + tvols = [] + + tweights = [] + + for tr in targetrets: + ef_cons = ({'type': 'eq', 'fun': lambda x: portfolio_stats(x, returns)[0] - tr}, + {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) + + opt_ef = sco.minimize(min_volatility, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=ef_cons) + + tvols.append(opt_ef['fun']) + tweights.append(np.round(opt_ef['x'], 2)) + + targetweights = np.array(tweights) + targetvols = np.array(tvols) + + dict_data = {} + + dict_data['retorno'] = targetrets + dict_data['volatilidade'] = targetvols + dict_data['sharpe'] = targetrets/targetvols + dict_data['weight'] = targetweights + + # index_dict = [i for i in range(len(dict_data["retorno"])) if round(dict_data["retorno"][i], 4) % portfolio_stats(array_weights, returns)[0] <= 0.005] + + # retorno_print = np.round(dict_data['retorno'][index_dict[0] - 1], 2) + # vol_print = np.round(dict_data['volatilidade'][index_dict[0] - 1], 2) + # weights_plot = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][index_dict[0] - 1]] + + # df_atv_table = pd.DataFrame( np.array([[retorno_print, vol_print, weights_plot]]), columns=['Retorno', 'Volatilidade', 'Peso']) + # st.table(df_atv_table) + + # st.write(f"Retorno: {retorno_print}") + # st.write(f"volatilidade: {vol_print}") + # st.write(f"weight: {weights_plot}") + # st.write(f"somaweight: {sum(dict_data['weight'][index_dict[0] - 1])*100}") + + index_dict = wallet_reposition("retorno", array_weights, dict_data, opt_sharpe, returns) + + # TODO: when the slider is pressed the page can't reload + # plot_index = st.slider('Movimento sua cartira dentro da fronteira eficiente', 0, 249, 1) + # fig = plot_int(plot_index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, array_weights, returns, st) + # st.pyplot(fig) \ No newline at end of file diff --git a/backend/tools/views.py b/backend/tools/views.py index b7fd7b4..eb2e5a7 100644 --- a/backend/tools/views.py +++ b/backend/tools/views.py @@ -1,17 +1,39 @@ from django.shortcuts import render +from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response import json +import yfinance as yf + +from .markowitz import markowits # Create your views here. class HomeView(APIView): def get(self, request): - return Response({'ok': 200}) + return Response(status=status.HTTP_200_OK) class MarkowitzView(APIView): def get(self, request): + body_data = json.dumps(request.data) + body_data = json.loads(body_data) + + try: + start_date = body_data['start_date'] + end_date = body_data['end_date'] + assets_list = body_data['assets'] + except: + return Response(status=status.HTTP_400_BAD_REQUEST) + + try: + df_symbols = yf.download(assets_list, start=f'{str(start_date)}-01-01', end=f'{str(end_date)}-12-31', progress=False)['Close'] + df_symbols.dropna(axis=0, inplace=True) + except: + return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + markowits(df_symbols) + return Response({'ok': 200}) diff --git a/frontend/pages/markowitz/Markowits.py b/frontend/pages/markowitz/Markowits.py deleted file mode 100644 index 7e41da3..0000000 --- a/frontend/pages/markowitz/Markowits.py +++ /dev/null @@ -1,363 +0,0 @@ -import pandas as pd -import numpy as np -import yfinance as yf -import scipy.optimize as sco - -from numpy.linalg import multi_dot -from scipy.stats import norm -from tabulate import tabulate - -# Plot settings -import matplotlib -import matplotlib.pyplot as plt -matplotlib.rcParams['figure.figsize'] = 16, 8 - - -def markowitz(df_symbols: pd.DataFrame, st): - - @st.cache(allow_output_mutation=True) - def plot_normalized_price(df): - fig = plt.figure(figsize=(16, 8)) - ax = plt.axes() - - ax.set_title('Normalized Price Plot') - ax.plot(df[-252:]/df.iloc[-252] * 100) - - ax.legend(df.columns, loc='upper left') - ax.grid(True) - - return fig - - @st.cache(allow_output_mutation=True) - def plot_annualized_returns(annual_returns): - fig = plt.figure() - ax = plt.axes() - - ax.bar(annual_returns.index, annual_returns * - 100, color='royalblue', alpha=0.75) - ax.set_title('Annualized Returns (in %)') - - return fig - - @st.cache(allow_output_mutation=True) - def plot_annualized_volatility(annual_vols): - fig = plt.figure() - ax = plt.axes() - - ax.bar(annual_vols.index, annual_vols*100, color='orange', alpha=0.5) - ax.set_title('Annualized Volatility (in %)') - - return fig - - @st.cache(allow_output_mutation=True) - def plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets): - fig = plt.figure() - ax = plt.axes() - - ax.set_title('Monte Carlo Simulated Allocation') - - # Simulated portfolios - fig.colorbar(ax.scatter(port_vols, port_rets, c=port_rets / port_vols, marker='o', cmap='RdYlGn', edgecolors='black'), label='Sharpe Ratio') - - # Maximum sharpe ratio portfolio - ax.scatter(msrp['volatility'], msrp['returns'], c='red', marker='*', s=300, label='Max Sharpe Ratio') - - ax.set_xlabel('Expected Volatility') - ax.set_ylabel('Expected Return') - ax.grid(True) - - return fig - - @st.cache(allow_output_mutation=True) - def portfolio_stats(weights, returns): - weights = np.array(weights)[:, np.newaxis] - port_rets = weights.T @ np.array(returns.mean() * 252)[:, np.newaxis] - port_vols = np.sqrt(multi_dot([weights.T, returns.cov() * 252, weights])) - - return np.array([port_rets, port_vols, port_rets/port_vols]).flatten() - - - def min_sharpe_ratio(weights, returns): - return -portfolio_stats(weights, returns)[2] - - - def min_variance(weights, returns): - return portfolio_stats(weights, returns)[1]**2 - - - def min_volatility(weights, returns): - return portfolio_stats(weights, returns)[1] - - - def wallet_reposition(reposition, array_weights, dict_data, opt_sharpe, returns): - data = array_weights - - if reposition == "retorno": - index_port = 0 - if reposition == "volatilidade": - index_port = 1 - if reposition == "sharpe": - index_port = 2 - data = opt_sharpe['x'] - - if len([i for i in range(len(dict_data[reposition])) if round(dict_data[reposition][i], 4) % portfolio_stats(data, returns)[index_port] <= 0.005]): - return [i for i in range(len(dict_data[reposition])) if round(dict_data[reposition][i], 4) % portfolio_stats(array_weights, returns)[index_port] <= 0.005][0] - 1 - - return None - - - def Var_Port(weights, returns): - port_ret = np.dot(returns, weights) - port_mean = port_ret.mean() - port_mean - - port_stdev = np.sqrt(multi_dot([weights.T, returns.cov(), weights])) - port_stdev.flatten()[0] - - pVaR_90 = norm.ppf(1-0.90, port_mean, port_stdev).flatten()[0] - pVaR_95 = norm.ppf(1-0.95, port_mean, port_stdev).flatten()[0] - pVaR_99 = norm.ppf(1-0.99, port_mean, port_stdev).flatten()[0] - - return pVaR_90, pVaR_95, pVaR_99 - - - def CVar_Port(weights, returns): - Port = np.dot(returns, weights) - Port.sort() - - hVaR_99 = np.quantile(Port, 0.01) - hVaR_95 = np.quantile(Port, 0.05) - hVaR_90 = np.quantile(Port, 0.1) - - CVaR_90 = Port[Port <= hVaR_90].mean() - CVaR_95 = Port[Port <= hVaR_95].mean() - CVaR_99 = Port[Port <= hVaR_99].mean() - - return CVaR_90, CVaR_95, CVaR_99, hVaR_90, hVaR_95, hVaR_99 - - - def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, array_weights, returns, st): - # Visualize the simulated portfolio for risk and return - fig = plt.figure() - ax = plt.axes() - - ax.set_title('Efficient Frontier Portfolio') - - # Efficient Frontier - fig.colorbar(ax.scatter(targetvols, targetrets, c=targetrets / targetvols, marker='x', cmap='RdYlGn', edgecolors='black'), label='Sharpe Ratio') - - # Maximum Sharpe Portfolio - ax.plot(portfolio_stats(opt_sharpe['x'], returns)[1], portfolio_stats(opt_sharpe['x'], returns)[0], 'r*', markersize=15.0) - - # Minimum Variance Portfolio - ax.plot(portfolio_stats(opt_var['x'], returns)[1], portfolio_stats(opt_var['x'], returns)[0], 'b*', markersize=15.0) - # Fronteira Eficiente - ax.plot(dict_data["volatilidade"][int(index)], dict_data["retorno"][int(index)], 'o', markersize=10.0) - # Nosso Portifolio - ax.plot(portfolio_stats(array_weights, returns)[1], portfolio_stats(array_weights, returns)[0], 'h', color='green', markersize=15.0) - - ax.set_xlabel('Expected Volatility') - ax.set_ylabel('Expected Return') - ax.grid(True) - # VaR Paramétrico - pVaR_90, pVaR_95, pVaR_99 = Var_Port(dict_data['weight'][int(index)], returns) - - # VaR Histórico - pCVaR_90, pCVaR_95, pCVaR_99, pHVaR_90, pHVaR_95, pHVaR_99 = CVar_Port(dict_data['weight'][int(index)], returns) - - - # dict_data_weights = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][int(index)]] - df_atv_table_dict_data = pd.DataFrame( - np.array([[ f'Referente ao indice {index} da fronteira eficiente', - np.round(dict_data['retorno'][int(index)]*100,2), - np.round(dict_data['volatilidade'][int(index)]*100,2), - np.round((dict_data['retorno'][int(index)]/dict_data['volatilidade'][int(index)]),2), - dict_data['weight'][int(index)] - ]]), - columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) - # st.write(f"Carteira referente a fronteira eficiente") - # st.table(df_atv_table_dict_data) - - # pesos_acao_print = - # st.write(f"Pesos para cada ação: {pesos_acao_print}") - # st.write("VaR Paramétrico \n90 :", np.round(pVaR_90*100, 2), "/95 :", np.round(pVaR_95*100, 2), "/99 :", np.round(pVaR_99*100, 2)) - # st.write("VaR Histórico \n90 :", np.round(pHVaR_90*100, 2), "/95 :", np.round(pHVaR_95*100, 2), "/99 :", np.round(pHVaR_99*100, 2)) - # st.write("CVaR Histórico \n 90 :", np.round(pCVaR_90*100, 2), "/95 :", np.round(pCVaR_95*100, 2), "/99 :", np.round(pCVaR_99*100, 2)) - - df_atv_table_opt_sharpe = pd.DataFrame( - np.array([[ 'Maior Indice Sharpe', - np.round(portfolio_stats(opt_sharpe['x'], returns)[0]*100,2), - np.round(portfolio_stats(opt_sharpe['x'], returns)[1]*100,2), - np.round(portfolio_stats(opt_sharpe['x'], returns)[2],2), - np.round(opt_sharpe['x']*100,2)]]), - columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) - # st.write('\nCarteira Fundamentalista com maior Indice Sharpe') - # st.table(df_atv_table_opt_sharpe) - - df_atv_table_opt_var = pd.DataFrame( - np.array([[ 'Menor volatilidade', - np.round(portfolio_stats(opt_var['x'], returns)[0]*100, 2), - np.round(portfolio_stats(opt_var['x'], returns)[1]*100, 2), - np.round(portfolio_stats(opt_var['x'], returns)[2], 2), - np.round(opt_var['x']*100, 2)]]), - columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) - # st.write('\nCarteira Fundamentalista com menor volatilidade') - # st.table(df_atv_table_opt_var) - - - df_atv_table_fundamentalista = pd.DataFrame( - np.array([[ 'Portfolio inserido', - np.round(portfolio_stats(array_weights, returns)[0]*100,2), - np.round(portfolio_stats(array_weights, returns)[1]*100,2), - np.round(portfolio_stats(array_weights, returns)[2],2), - np.round(array_weights*100,2)]]), - columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) - # st.write('\nCarteira Fundamentalista') - # st.table(df_atv_table_fundamentalista) - - - df_all_wallet = pd.concat([df_atv_table_dict_data, df_atv_table_opt_sharpe, df_atv_table_opt_var, df_atv_table_fundamentalista]) - # df_all_wallet = pd.DataFrame([wallets_merge]) - st.table( df_all_wallet ) - - - # st.write(f"Retorno : {np.round(portfolio_stats(array_weights)[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(array_weights)[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(array_weights)[2],2)) - # st.write("Pesos : ", np.round(array_weights*100,2)) - - # st.write('\nCarteira Fundamentalista Com maior Indice Sharpe ') - # st.write(f"Retorno : {np.round(portfolio_stats(opt_sharpe['x'])[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(opt_sharpe['x'])[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(opt_sharpe['x'])[2],2)) - # st.write("Pesos : ", np.round(opt_sharpe['x']*100,2)) - # st.write("VaR Paramétrico \n90 :",np.round(p1VaR_90*100,2),"/95 :",np.round(p1VaR_95*100,2),"/99 :",np.round(p1VaR_99*100,2)) - # st.write("VaR Histórico \n90 :",np.round(p1HVaR_90*100,2),"/95 :",np.round(p1HVaR_95*100,2),"/99 :",np.round(p1HVaR_99*100,2)) - # st.write("CVaR Histórico \n 90 :",np.round(p1CVaR_90*100,2),"/95 :",np.round(p1CVaR_95*100,2),"/99 :",np.round(p1CVaR_99*100,2)) - - # st.write('\nCarteira Fundamentalista Com menor volatilidade ') - # st.write(f"Retorno : {np.round(portfolio_stats(opt_var['x'])[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(opt_var['x'])[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(opt_var['x'])[2],2)) - # st.write("Pesos : ", np.round(opt_var['x']*100,2)) - # st.write("VaR Paramétrico \n90 :",np.round(p2VaR_90*100,2),"/95 :",np.round(p2VaR_95*100,2),"/99 :",np.round(p2VaR_99*100,2)) - # st.write("VaR Histórico \n90 :",np.round(p2HVaR_90*100,2),"/95 :",np.round(p2HVaR_95*100,2),"/99 :",np.round(p2HVaR_99*100,2)) - # st.write("CVaR Histórico \n 90 :",np.round(p2CVaR_90*100,2),"/95 :",np.round(p2CVaR_95*100,2),"/99 :",np.round(p2CVaR_99*100,2)) - - # st.write('\nCarteira Fundamentalista ') - # st.write(f"Retorno : {np.round(portfolio_stats(array_weights)[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(array_weights)[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(array_weights)[2],2)) - # st.write("Pesos : ", np.round(array_weights*100,2)) - # st.write("VaR Paramétrico \n 90 :",np.round(p3VaR_90*100,2),"/95 :",np.round(p3VaR_95*100,2),"/99 :",np.round(p3VaR_99*100,2)) - # st.write("VaR Histórico \n 90 :",np.round(p3HVaR_90*100,2),"/95 :",np.round(p3HVaR_95*100,2),"/99 :",np.round(p3HVaR_99*100,2)) - # st.write("CVaR Histórico \n 90 :",np.round(p3CVaR_90*100,2),"/95 :",np.round(p3CVaR_95*100,2),"/99 :",np.round(p3CVaR_99*100,2)) - - return fig - - df = df_symbols.copy(deep=True) - - numofasset = len(df.columns) - numofportfolio = 5000 - - returns = df.pct_change().dropna() - - fig = plot_normalized_price(df) - st.pyplot(fig) - - annual_returns = (returns.mean() * 252) - fig = plot_annualized_returns(annual_returns) - st.pyplot(fig) - - vols = returns.std() - annual_vols = vols*np.sqrt(252) - fig = plot_annualized_volatility(annual_vols) - st.pyplot(fig) - - wts = numofasset * [1./numofasset] - wts = np.array(wts)[:, np.newaxis] - - array_weights = np.full((numofasset, 1), 1/numofasset) - # array_weights = np.array([[0.15], [0.05], [0.07], [0.15], [0.05], [0.14], [0.15], [0.15], [0.05], [0.04]]) - - # Initialize the lists - rets = [] - vols = [] - wts = [] - - # Simulate 5,000 portfoliosplot_index - for i in range(5000): - # Generate random weights - weights = np.random.random(numofasset)[:, np.newaxis] - # st.write(weights) - # Set weights such that sum of weights equals 1 - - weights /= sum(weights) - # st.write(weights) - # Portfolio statistics - rets.append(weights.T @ np.array(returns.mean() * 252)[:, np.newaxis]) - vols.append(np.sqrt(multi_dot([weights.T, returns.cov()*252, weights]))) - wts.append(weights.flatten()) - - # Record values - port_rets = np.array(rets).flatten() - port_vols = np.array(vols).flatten() - port_wts = np.array(wts) - - msrp_df = pd.DataFrame({ - 'returns': port_rets, - 'volatility': port_vols, - 'sharpe_ratio': (port_rets - 0.015)/port_vols, - 'weights': list(port_wts) - }) - - msrp = msrp_df.iloc[msrp_df['sharpe_ratio'].idxmax()] - - fig = plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets) - st.pyplot(fig) - - cons = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) - bnds = tuple((0, 1) for x in range(numofasset)) - initial_wts = numofasset*[1./numofasset] - - opt_sharpe = sco.minimize(min_sharpe_ratio, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=cons) - - opt_var = sco.minimize(min_variance, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=cons) - array_weights = array_weights.flatten() - - targetrets = np.linspace(port_rets.min(), port_rets.max(), 250) - tvols = [] - - tweights = [] - - for tr in targetrets: - ef_cons = ({'type': 'eq', 'fun': lambda x: portfolio_stats(x, returns)[0] - tr}, - {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) - - opt_ef = sco.minimize(min_volatility, initial_wts, args=(returns,), method='SLSQP', bounds=bnds, constraints=ef_cons) - - tvols.append(opt_ef['fun']) - tweights.append(np.round(opt_ef['x'], 2)) - - targetweights = np.array(tweights) - targetvols = np.array(tvols) - - dict_data = {} - - dict_data['retorno'] = targetrets - dict_data['volatilidade'] = targetvols - dict_data['sharpe'] = targetrets/targetvols - dict_data['weight'] = targetweights - - # index_dict = [i for i in range(len(dict_data["retorno"])) if round(dict_data["retorno"][i], 4) % portfolio_stats(array_weights, returns)[0] <= 0.005] - - # retorno_print = np.round(dict_data['retorno'][index_dict[0] - 1], 2) - # vol_print = np.round(dict_data['volatilidade'][index_dict[0] - 1], 2) - # weights_plot = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][index_dict[0] - 1]] - - # df_atv_table = pd.DataFrame( np.array([[retorno_print, vol_print, weights_plot]]), columns=['Retorno', 'Volatilidade', 'Peso']) - # st.table(df_atv_table) - - # st.write(f"Retorno: {retorno_print}") - # st.write(f"volatilidade: {vol_print}") - # st.write(f"weight: {weights_plot}") - # st.write(f"somaweight: {sum(dict_data['weight'][index_dict[0] - 1])*100}") - - index_dict = wallet_reposition("retorno", array_weights, dict_data, opt_sharpe, returns) - - # TODO: when the slider is pressed the page can't reload - plot_index = st.slider('Movimento sua cartira dentro da fronteira eficiente', 0, 249, 1) - fig = plot_int(plot_index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, array_weights, returns, st) - st.pyplot(fig) \ No newline at end of file diff --git a/frontend/pages/markowitz_plot/markowitz_plot.py b/frontend/pages/markowitz_plot/markowitz_plot.py new file mode 100644 index 0000000..a02fc73 --- /dev/null +++ b/frontend/pages/markowitz_plot/markowitz_plot.py @@ -0,0 +1,166 @@ +import matplotlib +import matplotlib.pyplot as plt +matplotlib.rcParams['figure.figsize'] = 16, 8 + +import pandas as pd +import numpy as np + +def plot_normalized_price(df): + fig = plt.figure(figsize=(16, 8)) + ax = plt.axes() + + ax.set_title('Normalized Price Plot') + ax.plot(df[-252:]/df.iloc[-252] * 100) + + ax.legend(df.columns, loc='upper left') + ax.grid(True) + + return fig + +def plot_annualized_returns(annual_returns): + fig = plt.figure() + ax = plt.axes() + + ax.bar(annual_returns.index, annual_returns * + 100, color='royalblue', alpha=0.75) + ax.set_title('Annualized Returns (in %)') + + return fig + +def plot_annualized_volatility(annual_vols): + fig = plt.figure() + ax = plt.axes() + + ax.bar(annual_vols.index, annual_vols*100, color='orange', alpha=0.5) + ax.set_title('Annualized Volatility (in %)') + + return fig + +def plot_monte_carlo_simulated_allocation(msrp, port_vols, port_rets): + fig = plt.figure() + ax = plt.axes() + + ax.set_title('Monte Carlo Simulated Allocation') + + # Simulated portfolios + fig.colorbar(ax.scatter(port_vols, port_rets, c=port_rets / port_vols, marker='o', cmap='RdYlGn', edgecolors='black'), label='Sharpe Ratio') + + # Maximum sharpe ratio portfolio + ax.scatter(msrp['volatility'], msrp['returns'], c='red', marker='*', s=300, label='Max Sharpe Ratio') + + ax.set_xlabel('Expected Volatility') + ax.set_ylabel('Expected Return') + ax.grid(True) + + return fig + +def plot_int(index, targetvols, targetrets, opt_sharpe, opt_var, dict_data, array_weights, returns, st): + # Visualize the simulated portfolio for risk and return + fig = plt.figure() + ax = plt.axes() + + ax.set_title('Efficient Frontier Portfolio') + + # Efficient Frontier + fig.colorbar(ax.scatter(targetvols, targetrets, c=targetrets / targetvols, marker='x', cmap='RdYlGn', edgecolors='black'), label='Sharpe Ratio') + + # Maximum Sharpe Portfolio + ax.plot(portfolio_stats(opt_sharpe['x'], returns)[1], portfolio_stats(opt_sharpe['x'], returns)[0], 'r*', markersize=15.0) + + # Minimum Variance Portfolio + ax.plot(portfolio_stats(opt_var['x'], returns)[1], portfolio_stats(opt_var['x'], returns)[0], 'b*', markersize=15.0) + # Fronteira Eficiente + ax.plot(dict_data["volatilidade"][int(index)], dict_data["retorno"][int(index)], 'o', markersize=10.0) + # Nosso Portifolio + ax.plot(portfolio_stats(array_weights, returns)[1], portfolio_stats(array_weights, returns)[0], 'h', color='green', markersize=15.0) + + ax.set_xlabel('Expected Volatility') + ax.set_ylabel('Expected Return') + ax.grid(True) + # VaR Paramétrico + pVaR_90, pVaR_95, pVaR_99 = Var_Port(dict_data['weight'][int(index)], returns) + + # VaR Histórico + pCVaR_90, pCVaR_95, pCVaR_99, pHVaR_90, pHVaR_95, pHVaR_99 = CVar_Port(dict_data['weight'][int(index)], returns) + + + # dict_data_weights = [f"{str(np.round(i, 2))}%" for i in dict_data['weight'][int(index)]] + df_atv_table_dict_data = pd.DataFrame( + np.array([[ f'Referente ao indice {index} da fronteira eficiente', + np.round(dict_data['retorno'][int(index)]*100,2), + np.round(dict_data['volatilidade'][int(index)]*100,2), + np.round((dict_data['retorno'][int(index)]/dict_data['volatilidade'][int(index)]),2), + dict_data['weight'][int(index)] + ]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write(f"Carteira referente a fronteira eficiente") + # st.table(df_atv_table_dict_data) + + # pesos_acao_print = + # st.write(f"Pesos para cada ação: {pesos_acao_print}") + # st.write("VaR Paramétrico \n90 :", np.round(pVaR_90*100, 2), "/95 :", np.round(pVaR_95*100, 2), "/99 :", np.round(pVaR_99*100, 2)) + # st.write("VaR Histórico \n90 :", np.round(pHVaR_90*100, 2), "/95 :", np.round(pHVaR_95*100, 2), "/99 :", np.round(pHVaR_99*100, 2)) + # st.write("CVaR Histórico \n 90 :", np.round(pCVaR_90*100, 2), "/95 :", np.round(pCVaR_95*100, 2), "/99 :", np.round(pCVaR_99*100, 2)) + + df_atv_table_opt_sharpe = pd.DataFrame( + np.array([[ 'Maior Indice Sharpe', + np.round(portfolio_stats(opt_sharpe['x'], returns)[0]*100,2), + np.round(portfolio_stats(opt_sharpe['x'], returns)[1]*100,2), + np.round(portfolio_stats(opt_sharpe['x'], returns)[2],2), + np.round(opt_sharpe['x']*100,2)]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write('\nCarteira Fundamentalista com maior Indice Sharpe') + # st.table(df_atv_table_opt_sharpe) + + df_atv_table_opt_var = pd.DataFrame( + np.array([[ 'Menor volatilidade', + np.round(portfolio_stats(opt_var['x'], returns)[0]*100, 2), + np.round(portfolio_stats(opt_var['x'], returns)[1]*100, 2), + np.round(portfolio_stats(opt_var['x'], returns)[2], 2), + np.round(opt_var['x']*100, 2)]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write('\nCarteira Fundamentalista com menor volatilidade') + # st.table(df_atv_table_opt_var) + + + df_atv_table_fundamentalista = pd.DataFrame( + np.array([[ 'Portfolio inserido', + np.round(portfolio_stats(array_weights, returns)[0]*100,2), + np.round(portfolio_stats(array_weights, returns)[1]*100,2), + np.round(portfolio_stats(array_weights, returns)[2],2), + np.round(array_weights*100,2)]]), + columns=['Carteira', 'Retorno', 'Volatilidade', 'Indice Sharpe', 'Pesos']) + # st.write('\nCarteira Fundamentalista') + # st.table(df_atv_table_fundamentalista) + + + df_all_wallet = pd.concat([df_atv_table_dict_data, df_atv_table_opt_sharpe, df_atv_table_opt_var, df_atv_table_fundamentalista]) + # df_all_wallet = pd.DataFrame([wallets_merge]) + st.table( df_all_wallet ) + + + # st.write(f"Retorno : {np.round(portfolio_stats(array_weights)[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(array_weights)[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(array_weights)[2],2)) + # st.write("Pesos : ", np.round(array_weights*100,2)) + + # st.write('\nCarteira Fundamentalista Com maior Indice Sharpe ') + # st.write(f"Retorno : {np.round(portfolio_stats(opt_sharpe['x'])[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(opt_sharpe['x'])[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(opt_sharpe['x'])[2],2)) + # st.write("Pesos : ", np.round(opt_sharpe['x']*100,2)) + # st.write("VaR Paramétrico \n90 :",np.round(p1VaR_90*100,2),"/95 :",np.round(p1VaR_95*100,2),"/99 :",np.round(p1VaR_99*100,2)) + # st.write("VaR Histórico \n90 :",np.round(p1HVaR_90*100,2),"/95 :",np.round(p1HVaR_95*100,2),"/99 :",np.round(p1HVaR_99*100,2)) + # st.write("CVaR Histórico \n 90 :",np.round(p1CVaR_90*100,2),"/95 :",np.round(p1CVaR_95*100,2),"/99 :",np.round(p1CVaR_99*100,2)) + + # st.write('\nCarteira Fundamentalista Com menor volatilidade ') + # st.write(f"Retorno : {np.round(portfolio_stats(opt_var['x'])[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(opt_var['x'])[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(opt_var['x'])[2],2)) + # st.write("Pesos : ", np.round(opt_var['x']*100,2)) + # st.write("VaR Paramétrico \n90 :",np.round(p2VaR_90*100,2),"/95 :",np.round(p2VaR_95*100,2),"/99 :",np.round(p2VaR_99*100,2)) + # st.write("VaR Histórico \n90 :",np.round(p2HVaR_90*100,2),"/95 :",np.round(p2HVaR_95*100,2),"/99 :",np.round(p2HVaR_99*100,2)) + # st.write("CVaR Histórico \n 90 :",np.round(p2CVaR_90*100,2),"/95 :",np.round(p2CVaR_95*100,2),"/99 :",np.round(p2CVaR_99*100,2)) + + # st.write('\nCarteira Fundamentalista ') + # st.write(f"Retorno : {np.round(portfolio_stats(array_weights)[0]*100,2)}% \t/ Volatilidade : {np.round(portfolio_stats(array_weights)[1]*100,2)}% \t/ Indice Sharpe : ",np.round(portfolio_stats(array_weights)[2],2)) + # st.write("Pesos : ", np.round(array_weights*100,2)) + # st.write("VaR Paramétrico \n 90 :",np.round(p3VaR_90*100,2),"/95 :",np.round(p3VaR_95*100,2),"/99 :",np.round(p3VaR_99*100,2)) + # st.write("VaR Histórico \n 90 :",np.round(p3HVaR_90*100,2),"/95 :",np.round(p3HVaR_95*100,2),"/99 :",np.round(p3HVaR_99*100,2)) + # st.write("CVaR Histórico \n 90 :",np.round(p3CVaR_90*100,2),"/95 :",np.round(p3CVaR_95*100,2),"/99 :",np.round(p3CVaR_99*100,2)) + + return fig \ No newline at end of file