bullm commited on
Commit
025632f
1 Parent(s): 06773c7
README.md CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
  oid sha256:211cb91d6d7d65b8e74afe1e4257af5ee70faf2d6c4cda8bb589d812e0fbe1a7
3
- size 248
1
  version https://git-lfs.github.com/spec/v1
2
  oid sha256:211cb91d6d7d65b8e74afe1e4257af5ee70faf2d6c4cda8bb589d812e0fbe1a7
3
+ size 248
apps/.DS_Store CHANGED
Binary files a/apps/.DS_Store and b/apps/.DS_Store differ
apps/Clustering.py CHANGED
@@ -1,3 +1,183 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:a11b565bd5dee71b1c3d05476f1d68629a468190c0b46f8ffd58200af4514039
3
- size 8727
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+ import streamlit as st
3
+ import pandas as pd
4
+ from scipy.cluster.hierarchy import linkage
5
+ from datetime import date
6
+ from dateutil.relativedelta import relativedelta
7
+ import plotly.figure_factory as ff
8
+ from fastdtw import fastdtw
9
+ from scipy.spatial.distance import euclidean
10
+ import numpy as np
11
+ from modules import tables
12
+
13
+
14
+ @st.cache(suppress_st_warning=True)
15
+ def data_request(country_to_request, start, currency='USD', end=date.today()):
16
+ data = tables.EquityMaster(country=country_to_request, field='IQ_CLOSEPRICE_ADJ', currency=currency).query(rename=['asset'],
17
+ start=start, end=str(end))
18
+ adtv = tables.EquityMaster(country=country_to_request, field='IQ_VALUE_TRADED', currency=currency).query(rename=['asset'],
19
+ start=start, end=str(end)).median()
20
+ marketcap = tables.EquityMaster(country=country_to_request, field='IQ_MARKETCAP', currency=currency).query(rename=['asset'],
21
+ start=start, end=str(end)).median()
22
+ return data, adtv, marketcap
23
+
24
+
25
+ @st.cache(suppress_st_warning=True)
26
+ def data_filter(data, adtv, marketcap, adtv_threshold, mktcap_threshold, p):
27
+ adtv_filter = (adtv >= adtv_threshold)
28
+ adtv = adtv.loc[adtv_filter]
29
+ marketcap_filter = (marketcap >= mktcap_threshold)
30
+ marketcap = marketcap.loc[marketcap_filter]
31
+ data = data.loc[:, data.columns.isin(adtv.index)]
32
+ data = data.loc[:, data.columns.isin(marketcap.index)]
33
+
34
+ file_to_read = 'Data/Company_Base_Definitivo.xlsx'
35
+ company_base = pd.read_excel(file_to_read, sheet_name='Compilado')
36
+ id_to_ticker = {str(row['ID_Quant']): str(row['Ticker Bloomberg']).split()[0] for i, row in company_base.iterrows()}
37
+ data = data.loc[:, data.columns.isin(id_to_ticker.keys())]
38
+ data.columns = [id_to_ticker[col] for col in data.columns]
39
+
40
+ if isinstance(p, str):
41
+ returns_final = data.resample(p).last().pct_change().fillna(0)
42
+ else:
43
+ returns_final = data.iloc[::p].pct_change().fillna(0)
44
+ return returns_final
45
+
46
+
47
+ def dist(correlation):
48
+ return ((1-correlation)/2.)**.5
49
+
50
+
51
+ def to_excel(df_to_write):
52
+ output = BytesIO()
53
+ writer = pd.ExcelWriter(output, engine='xlsxwriter')
54
+ df_to_write.to_excel(writer, index=False, sheet_name='Sheet1')
55
+ workbook = writer.book
56
+ worksheet = writer.sheets['Sheet1']
57
+ format1 = workbook.add_format({'num_format': '0.00'})
58
+ worksheet.set_column('A:A', None, format1)
59
+ writer.save()
60
+ processed_data = output.getvalue()
61
+ return processed_data
62
+
63
+
64
+ @st.cache(suppress_st_warning=True)
65
+ def get_dtw_distance(x, y):
66
+ distance_dtw = fastdtw(x, y, dist=euclidean)[0]
67
+ return distance_dtw
68
+
69
+
70
+ def clustering_basado_en_correlacion():
71
+
72
+ form = st.form("Correlation Clustering")
73
+ posible_countries = ('Todos', 'Argentina', 'Brazil', 'Chile', 'Colombia', 'Mexico', 'Peru')
74
+ countries = form.multiselect('¿Qué países desea visualizar?', posible_countries)
75
+ if 'Todos' in countries:
76
+ countries = ('Argentina', 'Brazil', 'Chile', 'Colombia', 'Mexico', 'Peru')
77
+
78
+ adtv_p = form.number_input('Ingrese el mínimo Average Daily Traded Value que desea considerar', value=1., format="%.2f")
79
+ mktcap_thresh = form.number_input('Ingrese el mínimo Market Cap que desea considerar', value=200., format="%.2f")
80
+ start_date = form.selectbox('Ingrese la fecha de inicio que desea considerar', ('3 Meses', '6 Meses', '1 Año'))
81
+ period = form.number_input('Defina la frecuencia en la que desea las observaciones (en días)', value=1)
82
+ accept = form.form_submit_button('Aceptar')
83
+
84
+ if accept:
85
+ start_date = str(date.today() - relativedelta(months=int(start_date[0])))
86
+ for country in countries:
87
+ data_, adtv_, marketcap_ = data_request(country, start_date)
88
+ # Filtramos para que se cumplan los filtros del usuario en los datos
89
+ returns = data_filter(data_, adtv_, marketcap_, adtv_p, mktcap_thresh, period)
90
+
91
+ # Normalizamos
92
+ base = (returns.subtract(returns.mean(0), axis=1)).div(returns.std(axis=0), axis=1)
93
+ base = base.sort_index(axis=1)
94
+
95
+ # Procedemos a calcular correlación y covarianza
96
+ corr, covs = base.corr(), base.cov()
97
+ file = to_excel(corr)
98
+
99
+ # Definimos la matriz de distancia
100
+ dist_matrix = dist(corr)
101
+
102
+ hierarchy = linkage(dist_matrix)
103
+ ct = 0.54 * max(hierarchy[:, 2])
104
+ fig = ff.create_dendrogram(dist_matrix, orientation='left', labels=list(base.columns),
105
+ color_threshold=ct, linkagefun=linkage)
106
+
107
+ fig.update_layout(title='{} desde {} hasta {}'.format(country,
108
+ returns.index[0].date(),
109
+ returns.index[-1].date()))
110
+ if country == 'Brazil':
111
+ fig.update_layout(height=2000)
112
+ else:
113
+ fig.update_layout(height=900)
114
+
115
+ st.plotly_chart(fig, use_container_width=True)
116
+
117
+ st.download_button(label='Descargar Matriz de Correlación para {}'.format(country), data=file,
118
+ file_name='{}_correlacion.xlsx'.format(country))
119
+
120
+
121
+ def clustering_con_dtw():
122
+ form = st.form("Dynamic Time Warping Clustering")
123
+ posible_countries = ('Todos', 'Brazil', 'Argentina', 'Chile', 'Colombia', 'Mexico', 'Peru')
124
+ countries = form.multiselect('¿Qué países desea visualizar?', posible_countries)
125
+ if 'Todos' in countries:
126
+ countries = ('Brazil', 'Argentina', 'Chile', 'Colombia', 'Mexico', 'Peru')
127
+
128
+ adtv_p = form.number_input('Ingrese el mínimo Average Daily Traded Value que desea considerar', value=1.,
129
+ format="%.2f")
130
+ mktcap_thresh = form.number_input('Ingrese el Mínimo Market Cap que desea considerar', value=200., format="%.2f")
131
+ start_date = form.selectbox('Ingrese la fecha de inicio que desea considerar', ('3 Meses', '6 Meses', '1 Año'))
132
+ period = form.number_input('Defina la frecuencia en la que desea las observaciones (en días)', value=1)
133
+ accept = form.form_submit_button('Aceptar')
134
+
135
+ if accept:
136
+ start_date = str(date.today() - relativedelta(months=int(start_date[0])))
137
+
138
+ for country in countries:
139
+ data_, adtv_, marketcap_ = data_request(country, start_date)
140
+ # Filtramos para que se cumplan los filtros del usuario en los datos
141
+ returns = data_filter(data_, adtv_, marketcap_, adtv_p, mktcap_thresh, period)
142
+ # Normalizamos returns
143
+ base = (returns.subtract(returns.mean(0), axis=1)).div(returns.std(axis=0), axis=1)
144
+ base = base.sort_index(axis=1)
145
+ # Procedemos a calcular correlación y covarianza
146
+ N = len(base[:base.index[0]].T)
147
+ # Creamos la Matriz de Distancias para DTW
148
+ Dist = np.zeros((N, N))
149
+ place = st.empty()
150
+ for i in range(N):
151
+ place.write("Cargando: " + str(round(i*100/N)) + " %")
152
+ for j in range(i - 1, N):
153
+ company_1 = base.columns[i]
154
+ company_2 = base.columns[j]
155
+ Dist[i, j] = get_dtw_distance(base[company_1], base[company_2])
156
+ # La matriz es simétrica
157
+ Dist[j, i] = Dist[i, j]
158
+ # Creamos un DataFrame con la matriz de distancias
159
+ df = pd.DataFrame(Dist)
160
+ df.index = base.columns
161
+ df.columns = base.columns
162
+
163
+ # Pasamos el df a excel para descarga del usuario
164
+ file = to_excel(df)
165
+
166
+ hierarchy = linkage(Dist)
167
+ ct = 0.54 * max(hierarchy[:, 2])
168
+
169
+ fig = ff.create_dendrogram(Dist, orientation='left', labels=list(base.columns),
170
+ color_threshold=ct, linkagefun=linkage)
171
+ fig.update_layout(
172
+ title='{} desde {} hasta {}'.format(country, returns.index[0].date(), returns.index[-1].date()))
173
+
174
+ if country == 'Brazil':
175
+ fig.update_layout(height=2000)
176
+ else:
177
+ fig.update_layout(height=900)
178
+
179
+ st.plotly_chart(fig, use_container_width=True)
180
+
181
+ st.download_button(label='Descargar Matriz de distancias con DTW para {}'.format(country), data=file,
182
+ file_name='{}_correlacion.xlsx'.format(country))
183
+
apps/Comandos_utiles.py CHANGED
@@ -1,3 +1,107 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:40f2f07338967fe215d5b1c06c146afecf2f5c2dac95ddeeb0818076047cc6b5
3
- size 4425
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Tue Aug 31 15:01:56 2021
5
+
6
+ @author: benjaminull
7
+ """
8
+ import streamlit as st
9
+ import pandas as pd
10
+ import numpy as np
11
+ import io
12
+ import pybase64 as base64
13
+ from plotly import graph_objs as go
14
+ from datetime import datetime
15
+ import plotly.express as px
16
+
17
+ def get_table_excel_link(df, selected_stocks):
18
+ towrite = io.BytesIO()
19
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
20
+ header=True)
21
+ towrite.seek(0) # reset pointer
22
+ file_name = 'Data'+ selected_stocks+'.xlsx'
23
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
24
+ name_mark = "Descargar " + selected_stocks + ".xlsx"
25
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
26
+ linko= f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
27
+ return linko
28
+
29
+
30
+ @st.cache(show_spinner=True)
31
+ def charged_data():
32
+ regiones = {}
33
+ regiones['Latam'] = ['Argentina', 'Brazil', 'Chile', 'Colombia',
34
+ 'Mexico', 'Peru']
35
+ regiones['Europa'] = ['Italy', 'Spain', 'Germany', 'United Kingdom',
36
+ 'France']
37
+ regiones['Asia Emergente'] = ['South Korea', 'Taiwan', 'Hong Kong',
38
+ 'India', 'Thailand', 'Indonesia']
39
+ regiones['USA'] = ['United States']
40
+ data_dict=np.load('dict_movilidad.npy', allow_pickle='TRUE').item()
41
+ return data_dict, regiones
42
+
43
+
44
+
45
+
46
+ def comandos_utiles():
47
+ st.code("""CMD o Terminal\n> pip install streamlit """, language='python')
48
+ st.code("""CMD o Terminal\n> cd "ruta vista" \n> streamlit run app.py """,language='python')
49
+ code='''import streamlit as st \ndef comandos_utiles(): \n col1, col2 = st.columns(2) \n ...'''
50
+ st.code(code, language='python')
51
+ st.subheader("Elementos interactivos")
52
+ col1, col2 = st.columns(2)
53
+ col2.header(" ")
54
+ code2=('''var = col1.selectbox("Selectbox", ["Opcion 1", "Opcion 2", "Opcion 3"]) \nst.write(var)''')
55
+ col2.code(code2)
56
+ var = col1.selectbox("Selectbox", ["Opcion 1", "Opcion 2", "Opcion 3"])
57
+ col1.write(var)
58
+ var2 = col1.multiselect("Multiselect", ["Opcion 1", "Opcion 2", "Opcion 3"])
59
+ col1.write(var2)
60
+ code3=('''var = col1.multiselect("Selectbox", ["Opcion 1", "Opcion 2", "Opcion 3"]) \nst.write(var2)''')
61
+ col2.header(" ")
62
+ col2.code(code3)
63
+ var3 = col1.number_input("Number input")
64
+ col1.write(var3)
65
+ code4=('''var3 = col1.number_input("Number input") \nst.write(var3)''')
66
+ col2.header(" ")
67
+ col2.code(code4)
68
+ st.subheader("Tablas")
69
+ col1, col2 = st.columns(2)
70
+ df=pd.DataFrame([["1","2","3"],["2","5","6"],["7","8","9"]])
71
+ col1.write(df)
72
+ col2.header(" ")
73
+ col2.code("col1.write(df)")
74
+ col1.table(df)
75
+ col2.header(" ")
76
+ col2.header(" ")
77
+ col2.code("col1.table(df)")
78
+ col2.header(" ")
79
+ code_exc="""import io \nimport pybase64 as base6 \ndef get_table_excel_link(df, name):
80
+ towrite = io.BytesIO()
81
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
82
+ header=True)
83
+ towrite.seek(0) # reset pointer
84
+ file_name = 'Data'+ name +'.xlsx'
85
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
86
+ name_mark = "Descargar " + name + ".xlsx"
87
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
88
+ linko= f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
89
+ return linko \ncol1.markdown(get_table_excel_link(df, "tabla 1"),unsafe_allow_html=True)
90
+ """
91
+ col1.subheader("Descargar data frame")
92
+ col2.header(" ")
93
+ col1.header(" ")
94
+ col1.header(" ")
95
+ col2.code(code_exc)
96
+ col1.markdown(get_table_excel_link(df, "tabla 1"),unsafe_allow_html=True)
97
+ st.subheader("Graficos")
98
+ col1, col2 = st.columns((2,1))
99
+ col2.code("col1, col2 = st.columns((2,1)) \nfrom plotly import graph_objs as go \nimport plotly.express as px ")
100
+ df = px.data.tips()
101
+ fig = px.scatter(df, x="total_bill", y="tip", trendline="ols")
102
+ st.plotly_chart(fig)
103
+ st.code("""df = px.data.tips() \nfig = px.scatter(df, x="total_bill", y="tip", trendline="ols")\ncol1.plotly_chart(fig)""")
104
+
105
+
106
+
107
+
apps/Comentarios.py CHANGED
@@ -1,3 +1,623 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:4a64b11b219002bef949d29c2f715b777046fa70a5beabcd7d779992f426362f
3
- size 27081
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import plotly.express as px
4
+ import datetime
5
+ from Scheduler.mailer_quant import Mailer
6
+ from sqlalchemy import create_engine
7
+ import psycopg2
8
+ import graphviz as graphviz
9
+ import plotly.graph_objects as go
10
+ from logs_portal import log
11
+ import io
12
+ import boto3
13
+ from Data.credentials import credentials_s3 as creds3
14
+ from Data.credentials import credentials_postgresql as credpost
15
+ from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, DataReturnMode, JsCode
16
+
17
+
18
+ def save_s3(key, secret_key, bucket, df, path):
19
+ with io.BytesIO() as output:
20
+ with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
21
+ df.to_excel(writer, index=False)
22
+ data = output.getvalue()
23
+ s3 = boto3.resource('s3', aws_access_key_id=key,
24
+ aws_secret_access_key=secret_key)
25
+ s3.Bucket(bucket).put_object(Key=path, Body=data)
26
+
27
+
28
+ def read_excel_s3(key, secret_key, bucket, path):
29
+ s3_client = boto3.client('s3', aws_access_key_id=key,
30
+ aws_secret_access_key=secret_key)
31
+ response = s3_client.get_object(Bucket=bucket, Key=path)
32
+ data = response["Body"].read()
33
+ df = pd.read_excel(io.BytesIO(data), engine='openpyxl')
34
+ return df
35
+
36
+
37
+ def display_table(df: pd.DataFrame):
38
+ # Configure AgGrid options
39
+ gb = GridOptionsBuilder.from_dataframe(df)
40
+ gb.configure_selection(selection_mode="single", use_checkbox=True,)
41
+ return AgGrid(
42
+ df, gridOptions=gb.build(),
43
+ update_mode=GridUpdateMode.SELECTION_CHANGED,
44
+ enable_enterprise_modules=True)
45
+
46
+
47
+ def style_table():
48
+ style_table = """
49
+ <style>
50
+ tbody tr:hover {
51
+ color:#BB1114;}
52
+ thead {
53
+ background-color:#BB1114 ;
54
+ color: #E8E8E8;
55
+ }
56
+ tbody tr:nth-child(odd) {
57
+ background-color: #fff;
58
+ }
59
+ # tbody tr:nth-child(even) {
60
+ # background-color: #eee;
61
+ # }
62
+ tbody tr:nth-child(odd)
63
+ stTable {
64
+ border-collapse: collapse;
65
+ margin: 25px 0;
66
+ font-size: 0.9em;
67
+ min-width: 400px;
68
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
69
+ }
70
+ </style>
71
+ """
72
+ st.markdown(style_table, unsafe_allow_html=True)
73
+
74
+
75
+ def mostrar_tabla(info_fil, placeholder, select):
76
+ info_fil2 = info_fil.copy()
77
+ info_fil2 = info_fil2[select]
78
+ placeholder.table(info_fil2)
79
+
80
+
81
+ @st.experimental_memo
82
+ def leer_notas():
83
+ url = credpost["POSTGRESQL"]
84
+ engine = create_engine(url, echo=False)
85
+ data = pd.read_sql_query("SELECT * FROM notas_analistas", con=engine)
86
+ data.columns = ["Analista", "Comentario", "Date", "Empresa", "ID_Quant",
87
+ "LV1", "Nota",
88
+ "Pais", "Ticker Bloomberg", "Tipo de Comentario"]
89
+ data.index = pd.to_datetime(data['Date']).dt.strftime('%d/%m/%Y')
90
+ data.index.name = "Fecha"
91
+ data = data.sort_index(ascending=False)
92
+ return data
93
+
94
+
95
+ @log
96
+ def ver_nota():
97
+ select = ["Analista", "Tipo de Comentario", "Empresa", "Pais", "Nota",
98
+ "Comentario"]
99
+ key = creds3["S3_KEY_ID"]
100
+ secret_key = creds3["S3_SECRET_KEY"]
101
+ bucket = creds3["S3_BUCKET"]
102
+ path ="Analistas Empresa.xlsx"
103
+ style_table()
104
+ col1, col2, col3, col4 = st.columns(4)
105
+ data = leer_notas()
106
+ select = ["Analista", "Pais", "LV1", "Empresa", "Nota",
107
+ "Comentario"]
108
+ data3 = read_excel_s3(key, secret_key, bucket, path)
109
+ data4 = data3.copy()
110
+ autores = sorted(list(set(data4["Analista"].dropna())))
111
+ Autor = col1.selectbox("Analista", ["-"] + autores)
112
+ if Autor != "-":
113
+ data4 = data4[data4["Analista"] == Autor]
114
+ data = data[data["Analista"] == Autor]
115
+ pais = sorted(list(set(data4["Pais"].dropna())))
116
+ Pais = col2.selectbox("Pais", ["-"] + pais)
117
+ if Pais != "-":
118
+ data4 = data4[data4["Pais"] == Pais]
119
+ data = data[data["Pais"] == Pais]
120
+ industria = sorted(list(set(data4["LV1"].dropna())))
121
+ Industria = col3.selectbox("Industria", ["-"] + industria)
122
+ if Industria != "-":
123
+ data4 = data4[data4["LV1"] == Industria]
124
+ data = data[data["LV1"] == Industria]
125
+ empresa = sorted(list(set(data4["Empresa"].dropna())))
126
+ Empresa = col4.selectbox("Empresa", ["-"] + empresa)
127
+ if Empresa != "-":
128
+ data4 = data4[data4["Empresa"] == Empresa]
129
+ data = data[data["Empresa"] == Empresa]
130
+ info_fil = data
131
+ Ordenar_por = col1.selectbox("Ordenar por", ["Date", "Analista", "Pais",
132
+ "LV1", "Empresa"])
133
+ mayor = col2.selectbox("Asc o desc", ["Descendiente",
134
+ "Ascendiente"])
135
+ fec_i = col3.date_input('Fecha de inicio', datetime.date(2021, 7, 1))
136
+ fec_f = col4.date_input('Fecha final')
137
+ placeholder = st.empty()
138
+ if mayor != "-" and Ordenar_por != "-":
139
+ var = Ordenar_por
140
+ if mayor == "Ascendiente":
141
+ info_fil = info_fil.sort_values(var, ascending=True)
142
+ else:
143
+ info_fil = info_fil.sort_values(var, ascending=False)
144
+ info_fil = info_fil[info_fil["Date"].dt.date >= fec_i]
145
+ info_fil = info_fil[info_fil["Date"].dt.date <= fec_f]
146
+ mostrar_tabla(info_fil, placeholder, select)
147
+
148
+
149
+ @st.experimental_memo
150
+ def read_mapeo_analistas():
151
+ key = creds3["S3_KEY_ID"]
152
+ secret_key = creds3["S3_SECRET_KEY"]
153
+ bucket = creds3["S3_BUCKET"]
154
+ path = "Analistas Empresa.xlsx"
155
+ return read_excel_s3(key, secret_key, bucket, path)
156
+
157
+
158
+ @st.experimental_memo
159
+ def read_company_db():
160
+ company_db = pd.pandas.read_excel("Data/Company_Base_Definitivo.xlsx",
161
+ sheet_name="Compilado",
162
+ engine="openpyxl")
163
+ return company_db
164
+
165
+
166
+ def aggrid_notas(data):
167
+ gb = GridOptionsBuilder.from_dataframe(data)
168
+ # make columns editable
169
+ gb.configure_columns(["Nota",
170
+ "Comentario"], editable=True)
171
+ gb.configure_column('Nota',
172
+ cellEditor='agRichSelectCellEditor',
173
+ cellEditorParams={'values': [1, 2, 3, 4, 5]}
174
+ )
175
+ js = JsCode("""
176
+ function(e) {
177
+ let api = e.api;
178
+ let rowIndex = e.rowIndex;
179
+ let col = e.column.colId;
180
+ let rowNode = api.getDisplayedRowAtIndex(rowIndex);
181
+ api.flashCells({
182
+ rowNodes: [rowNode],
183
+ columns: [col],
184
+ flashDelay: 10000000000
185
+ });
186
+ };
187
+ """)
188
+ gb.configure_grid_options(onCellValueChanged=js)
189
+ go = gb.build()
190
+ return AgGrid(data, gridOptions=go, key='grid1',
191
+ allow_unsafe_jscode=True,
192
+ reload_data=False,
193
+ fit_columns_on_grid_load=False,
194
+ enable_enterprise_modules=True)
195
+
196
+
197
+ def ingresar_nota():
198
+ try:
199
+ notas_df = leer_notas()
200
+ companydb_df = read_company_db()
201
+ companies_assigned_df = read_mapeo_analistas()
202
+ notas_df["Comentario"] = notas_df["Comentario"].fillna(" ")
203
+ analista = st.session_state["name"]
204
+ empresa_analista = sorted(
205
+ list(set(companies_assigned_df[companies_assigned_df["Analista"]
206
+ == analista]["Empresa"])))
207
+ companies_fil = companies_assigned_df[
208
+ companies_assigned_df["Analista"] == analista]
209
+ data_fil_a = notas_df[notas_df["Analista"] == analista].drop_duplicates(
210
+ "Empresa")
211
+ data_fil = data_fil_a[["Empresa", "Nota", "Comentario"]]
212
+ data_fil = companies_fil.merge(data_fil,
213
+ on="Empresa",
214
+ how='left').reset_index()
215
+ data_fil["Nota"] = data_fil["Nota"].fillna(0)
216
+ data_fil["Comentario"] = data_fil["Comentario"].fillna(" ")
217
+ data_fil = data_fil[["Empresa",
218
+ "Pais",
219
+ "LV1",
220
+ "Nota",
221
+ "Comentario"]].sort_values("LV1")
222
+ notas = aggrid_notas(data_fil)
223
+ notas_f = notas["data"]
224
+ update_notas = []
225
+ for emp in notas_f.Empresa:
226
+ new_df = notas_f[notas_f.Empresa == emp]
227
+ old_df = data_fil[data_fil.Empresa == emp]
228
+ new_nota = new_df.iloc[0].Nota
229
+ new_comentario = new_df.iloc[0].Comentario
230
+ old_nota = old_df.iloc[0].Nota
231
+ old_comentario = old_df.iloc[0].Comentario
232
+ if old_nota != new_nota or old_comentario != new_comentario:
233
+ update_notas.append(notas_f[notas_f.Empresa == emp])
234
+ update_final = pd.concat(update_notas)
235
+ st.write(update_final)
236
+ submitted_2 = st.button("Update Notas")
237
+ if submitted_2:
238
+ today = datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S')
239
+ for emp in update_final.Empresa:
240
+ df_emp = update_final[update_final.Empresa==emp]
241
+ empresa_df = companydb_df[companydb_df['Short_Name']==emp].iloc[0]
242
+ pais = empresa_df['Portfolio_Country']
243
+ industria = empresa_df["LV1"]
244
+ id_quant = empresa_df["ID_Quant"]
245
+ tbloom = empresa_df['Ticker Bloomberg']
246
+ comentario = df_emp.iloc[0]["Comentario"]
247
+ nota = df_emp.iloc[0]["Nota"]
248
+ var = """(analista, comentario, date_nota, empresa, id_quant, lv1,
249
+ nota, pais, ticker_bloomberg)"""
250
+ if "'" in emp:
251
+ emp = emp.replace("'", "")
252
+ varlist = [analista, comentario, today, emp, id_quant,
253
+ industria, nota, pais, tbloom]
254
+ # try:
255
+ url = credpost["POSTGRESQL"]
256
+ conn = psycopg2.connect(url, sslmode='require')
257
+ cur = conn.cursor()
258
+ cur.execute("INSERT INTO notas_test {Var} VALUES %r; ".
259
+ format(Var=var) % (tuple(varlist),))
260
+ conn.commit()
261
+ cur.close()
262
+ conn.close()
263
+ st.info("Nota ingresada exitosamente")
264
+ if emp != "-":
265
+ asunto = "Actualizacion nota " + emp + " - " + analista
266
+ mensaje = analista + " ha actualizado la nota de la empresa " + emp + " a " + str(nota)
267
+ else:
268
+ asunto = "Actualizacion nota " + industria + " - " + analista
269
+ mensaje = analista + " ha actualizado la nota de la industria " + industria + " a " + str(nota)
270
+ destinatario = st.session_state['mail']
271
+ mail = Mailer(asunto, mensaje, "", "bullm@larrainvial.com")
272
+ mail.send_message([#destinatario,
273
+ "bullm@larrainvial.com,",
274
+ "benjamin.ull.m@gmail.com"])
275
+ # except:
276
+ # st.error("Problemas al ingresar la nota")
277
+ # asunto = "Actualizacion nota " + emp + " - " + analista
278
+ # mensaje = analista + " ha tenido problemas con la nota de" + emp + " a " + str(nota)
279
+ # mail = Mailer(asunto, mensaje, "", "bullm@larrainvial.com")
280
+ # mail.send_message(["bullm@larrainvial.com,",
281
+ # "benjamin.ull.m@gmail.com"])
282
+ st.experimental_memo.clear()
283
+ except Exception as exc:
284
+ st.write(exc)
285
+
286
+
287
+
288
+ def ingresar_nota_ex():
289
+
290
+ Analistas = {
291
+ "fsutter": "Florencia Sutter",
292
+ "alehmann": "Alejandro Lehmann",
293
+ "bcosoi": "Benjamín Cosoi",
294
+ "chinojosa": "Carlos Hinojosa",
295
+ "gcatalan": "Gustavo Catalan",
296
+ "bull": "Benjamin Ul",
297
+ "ftaverne": "Francisca Taverne"
298
+ }
299
+ notas_df = leer_notas()
300
+ companydb_df = read_company_db()
301
+ companies_assigned_df = read_mapeo_analistas()
302
+ notas_df["Comentario"] = notas_df["Comentario"].fillna(" ")
303
+ if st.session_state.key in list(Analistas.keys()):
304
+ analista = Analistas[st.session_state.key]
305
+ data_analista = companies_assigned_df[companies_assigned_df["Analista"] == analista]
306
+ industrias_analista = sorted(list(
307
+ set(companies_assigned_df[companies_assigned_df["Analista"]
308
+ == analista]["LV1"])))
309
+ empresa_analista = sorted(list(
310
+ set(companies_assigned_df[companies_assigned_df["Analista"]
311
+ == analista]["Empresa"])))
312
+ else:
313
+ analista = st.session_state.key
314
+ data_analista = companies_assigned_df[
315
+ companies_assigned_df["Analista"] == analista]
316
+ industrias_analista = sorted(
317
+ list(set(companies_assigned_df[companies_assigned_df["Analista"]
318
+ == analista]["LV1"])))
319
+ empresa_analista = sorted(
320
+ list(set(companies_assigned_df[companies_assigned_df["Analista"]
321
+ == analista]["Empresa"])))
322
+ Countries = sorted(list(set(data_analista["Pais"])))
323
+ LV1s = sorted(list(set(data_analista["LV1"])))
324
+ industrias = []
325
+ for c in Countries:
326
+ for l in LV1s:
327
+ industrias.append(c + " - " + l)
328
+ col1, col2 = st.columns(2)
329
+ placeholder = col2.empty()
330
+ companies_fil = companies_assigned_df[
331
+ companies_assigned_df["Analista"] == analista]
332
+ data_fil_a = notas_df[notas_df["Analista"] == analista].drop_duplicates(
333
+ "Empresa")
334
+ data_fil = data_fil_a[["Empresa", "Nota"]]
335
+ data_fil = companies_fil.merge(data_fil,
336
+ on="Empresa",
337
+ how='left').fillna(0)
338
+ with col1:
339
+ notas_df2 = notas_df
340
+ porc_total = (notas_df.drop_duplicates("Empresa")["Nota"]>0).sum()/len(notas_df)
341
+ porc_emp_notas = (data_fil["Nota"] > 0).sum()/len(data_fil)*100
342
+ delta_per = round(porc_total - porc_emp_notas, 2)
343
+ st.metric("% de empresas con nota", round(porc_emp_notas,2), delta_per)
344
+ notas_table = display_table(data_fil[["Empresa",
345
+ "Pais",
346
+ "LV1",
347
+ "Nota"]].sort_values("LV1"))
348
+
349
+ if len(notas_table["selected_rows"]) > 0:
350
+ emp_name = notas_table["selected_rows"][0]["Empresa"]
351
+ st.subheader("Comentario")
352
+ data_emp_df = data_fil_a[data_fil_a["Empresa"] == emp_name]
353
+ if len(data_emp_df) > 0:
354
+ st.write(data_emp_df.iloc[0]["Comentario"])
355
+ id_quant = data_emp_df.iloc[0]["ID_Quant"]
356
+ country = data_emp_df.iloc[0]["Pais"]
357
+
358
+
359
+ with placeholder.form("my_form2", True):
360
+ # col1, col2, col3, col4 = st.columns((3, 8, 2, 1.5))
361
+ Empresas = ["-"]+sorted(list(empresa_analista) + industrias)
362
+ st.markdown(
363
+ '<p style="font-size:12px; padding-left:0px; margin-bottom:0px;">Analista</p>',
364
+ unsafe_allow_html=True)
365
+ st.markdown('<h3 style="padding-left:0px;; margin-bottom:0px;"">'+analista+"</h3>",
366
+ unsafe_allow_html=True)
367
+ if len(notas_table["selected_rows"]) <1:
368
+ empresa = st.selectbox('Empresa', Empresas)
369
+ else:
370
+ empresa = notas_table["selected_rows"][0]["Empresa"]
371
+ st.subheader(empresa)
372
+ tipo_comentario = "Nota"
373
+ nota = st.selectbox("Nota", [0, 1, 2, 3, 4, 5])
374
+ comentario = st.text_area('Comentario')
375
+ submitted_2 = st.form_submit_button("Publicar ")
376
+ var = """(analista, comentario, date_nota, empresa, id_quant, lv1,
377
+ nota, pais, ticker_bloomberg)"""
378
+ today = datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S')
379
+ if submitted_2:
380
+ st.experimental_memo.clear()
381
+ empresa_df = companydb_df[companydb_df['Short_Name']==empresa].iloc[0]
382
+ pais = empresa_df['Portfolio_Country']
383
+ industria = empresa_df["LV1"]
384
+ id_quant = empresa_df["ID_Quant"]
385
+ tbloom = empresa_df['Ticker Bloomberg']
386
+ if "'" in empresa:
387
+ empresa = empresa.replace("'", "")
388
+ varlist = [analista, comentario, today, empresa, id_quant,
389
+ industria, nota, pais, tbloom]
390
+ try:
391
+ url = credpost["POSTGRESQL"]
392
+ conn = psycopg2.connect(url, sslmode='require')
393
+ cur = conn.cursor()
394
+ cur.execute("INSERT INTO notas_analistas {Var} VALUES %r; ".
395
+ format(Var=var) % (tuple(varlist),))
396
+ conn.commit()
397
+ cur.close()
398
+ conn.close()
399
+ st.info("Nota ingresada exitosamente")
400
+ if empresa != "-":
401
+ asunto = "Actualizacion nota " + empresa + " - " + analista
402
+ mensaje = analista + " ha actualizado la nota de la empresa " + empresa + " a " + str(nota)
403
+ else:
404
+ asunto = "Actualizacion nota " + industria + " - " + analista
405
+ mensaje = analista + " ha actualizado la nota de la industria " + industria + " a " + str(nota)
406
+ destinatario = st.session_state['mail']
407
+ mail = Mailer(asunto, mensaje, "", "bullm@larrainvial.com")
408
+ mail.send_message([destinatario,
409
+ "bullm@larrainvial.com,",
410
+ "benjamin.ull.m@gmail.com"])
411
+ except:
412
+ st.error("Problemas al ingresar la nota")
413
+ asunto = "Actualizacion nota " + empresa + " - " + analista
414
+ mensaje = analista + " ha tenido problemas con la nota de" + empresa + " a " + str(nota)
415
+ mail = Mailer(asunto, mensaje, "", "bullm@larrainvial.com")
416
+ mail.send_message(["bullm@larrainvial.com,",
417
+ "benjamin.ull.m@gmail.com"])
418
+ notas_df = leer_notas()
419
+
420
+ # st.write(data_fil.columns)
421
+ # st.table(data_fil[["Analista","Empresa", "LV1","Nota", "Comentario"]])
422
+
423
+ @log
424
+ def estadisticas():
425
+ data = leer_notas()
426
+ st.subheader("Distribución de notas")
427
+ data = data[data["Nota"] != 0]
428
+ col1, col2 = st.columns((1.681, 1))
429
+ place = col1.empty()
430
+ val = col2.selectbox("Seleccione un analista", list(set(data["Analista"].dropna())))
431
+ data_fil = data[data["Analista"] == val]
432
+ data_fil["count"] = 1
433
+ data_fil2 = data_fil.groupby(by=["Nota"],
434
+ as_index=False).agg({"count": "sum"})
435
+ data_fil3 = data.sort_values("Date", ascending=False)
436
+ data_fil3 = data_fil3[data_fil3["ID_Quant"] == 0]
437
+ data_fil4 = data_fil3.groupby(by=["LV1", "Pais", "Empresa", "Date"],
438
+ as_index=False).agg({"Nota": "mean"})
439
+ data_fil3 = data_fil3.groupby(by=["LV1"],
440
+ as_index=False).agg({"Nota": "mean"})
441
+ l = []
442
+ for i in range(len(data_fil2)):
443
+ l.append(str(round(data_fil2.iloc[i]["Nota"])))
444
+ data_fil2["Nota "] = l
445
+ fig = px.bar(data_fil2, x="Nota ", y="count",
446
+ color_discrete_sequence=['indianred'])
447
+ fig.update_layout(bargap=0.2)
448
+ place.plotly_chart(fig, use_container_width=True)
449
+ col2.header("Media = " + str(round(sum(data_fil2["Nota"]*data_fil2["count"])/sum(data_fil2["count"]),1)))
450
+ data["Datetime"] = pd.to_datetime(data["Date"], format='%Y-%m-%d %H:%M:%S',
451
+ errors='ignore')
452
+ data_fil4["Datetime"] = pd.to_datetime(data_fil4["Date"],
453
+ format='%Y-%m-%d %H:%M:%S',
454
+ errors='ignore')
455
+ st.subheader("Evolución por empresa")
456
+ col1, col2 = st.columns((2, 1))
457
+ placeholder = col1.empty()
458
+ pais = col2.selectbox("Seleccione un pais",
459
+ ["-"] + sorted(list(set(data["Pais"].dropna()))))
460
+ if pais != "-":
461
+ data2 = data[data["Pais"] == pais]
462
+ else:
463
+ data2 = data
464
+ industria = col2.selectbox("Seleccione una industria",
465
+ ["-"] + sorted(list(set(data2["LV1"].dropna()))))
466
+ if industria != "-":
467
+ data2 = data2[data2["LV1"] == industria]
468
+ else:
469
+ data2=data2
470
+ empr = col2.selectbox("Seleccione una empresa",
471
+ ["-"] + sorted(list(set(data2["Empresa"].dropna()))))
472
+ if empr != "-":
473
+ notas_empr = data[data["Empresa"] == empr]
474
+ elif empr == "-" and pais == "-" and industria != "-":
475
+ notas_empr = data_fil4[data_fil4["LV1"]==industria]
476
+ elif empr == "-" and pais != "-" and industria == "-":
477
+ notas_empr = data_fil4[data_fil4["Pais"]==pais]
478
+ else:
479
+ notas_empr = data2
480
+ date_range = pd.date_range(notas_empr['Datetime'].min() - datetime.timedelta(days=4),
481
+ datetime.datetime.today() + datetime.timedelta(days=1))
482
+ hist_notas = pd.DataFrame(index=date_range)
483
+ if empr == "-" and pais == "-" and industria == "-":
484
+ placeholder.empty()
485
+ else:
486
+ for empresa in list(set(notas_empr["Empresa"])):
487
+ l = []
488
+ a = 0
489
+ for i in list(date_range):
490
+ data3 = notas_empr[notas_empr["Empresa"] == empresa]
491
+ data3 = data3[data3["Datetime"].dt.date == i]
492
+ if len(data3) == 0:
493
+ l.append(a)
494
+ else:
495
+ a = data3.iloc[0]["Nota"]
496
+ l.append(a)
497
+ hist_notas[empresa] = l
498
+ hist_notas["Date"] = list(hist_notas.index)
499
+ fig2 = px.line(hist_notas, x="Date", y=hist_notas.columns)
500
+ fig2.update_traces(textposition="bottom right")
501
+ placeholder.plotly_chart(fig2, use_container_width=True)
502
+ col2.header(" ")
503
+ col2.header(" ")
504
+ col1, col2 = st.columns((2, 1))
505
+ col1.subheader("Promedio por industria")
506
+ add_pais = col2.selectbox("Añadir Pais", ["-"] + list(set(data_fil4["Pais"])))
507
+ if add_pais != "-":
508
+ data_fil4 = data_fil4[data_fil4["Pais"] == add_pais]
509
+ data_fil4 = data_fil4.sort_values(by = "Datetime", ascending = False)
510
+ data_fil4 = data_fil4.drop_duplicates("LV1")
511
+ fig3 = go.Figure(data=[
512
+ go.Bar(name='General', x=data_fil3["LV1"], y=data_fil3["Nota"]),
513
+ go.Bar(name=add_pais, x=data_fil4["LV1"], y=data_fil4["Nota"])
514
+ ])
515
+ fig3.update_yaxes(range=[min(min(data_fil3['Nota']),
516
+ min(data_fil4['Nota']))/1.1,
517
+ max(max(data_fil3['Nota']),
518
+ max(data_fil4['Nota']))*1.1])
519
+ else:
520
+ fig3 = go.Figure(data=[
521
+ go.Bar(name='General', x=data_fil3["LV1"], y=data_fil3["Nota"])
522
+ ])
523
+ fig3.update_yaxes(range=[min(data_fil3['Nota'])/1.1,
524
+ max(data_fil3['Nota'])*1.1])
525
+ data_fil3 = data_fil3.sort_values("Nota")
526
+ fig3.update_layout(barmode='group',
527
+ xaxis={'categoryorder': 'total descending'})
528
+
529
+ st.plotly_chart(fig3, use_container_width=True)
530
+
531
+
532
+ def asignar_analista():
533
+ key = creds3["S3_KEY_ID"]
534
+ secret_key = creds3["S3_SECRET_KEY"]
535
+ bucket = creds3["S3_BUCKET"]
536
+ path ="Analistas Empresa.xlsx"
537
+ analista_emp = read_excel_s3(key, secret_key, bucket, path)
538
+ # analista_emp = pd.read_excel("Data/Analistas Empresa.xlsx", engine='openpyxl')
539
+ Analistas = {
540
+ "fsutter": "Florencia Sutter",
541
+ "alehmann": "Alejandro Lehmann",
542
+ "bcosoi": "Benjamín Cosoi",
543
+ "chinojosa": "Carlos Hinojosa",
544
+ "gcatalan": "Gustavo Catalan",
545
+ "bull": "Benjamin Ull",
546
+ "ftaverne": "Francisca Taverne"
547
+ }
548
+ analista_emp2 = analista_emp[["ID_Quant", "Analista", "Empresa", "LV1",
549
+ "Pais"]]
550
+ credenciales = pd.read_csv("Data/Credenciales_h.csv",
551
+ names=['Usuario', 'Password', 'Area',
552
+ 'Cargo','Mail','Nombre'])
553
+ analistas = credenciales[credenciales["Cargo"] == "Investment Analyst"]
554
+ col1, col2, col3 = st.columns(3)
555
+ analista = col1.selectbox("Analista",
556
+ sorted(list(set(Analistas.values()))))
557
+ industria = col2.selectbox("Industria",
558
+ sorted(list(set(analista_emp["LV1"]))))
559
+ col3.title(" ")
560
+ val = col3.checkbox("Seleccionar todos", value=True)
561
+ dicc ={}
562
+ with st.form("form"):
563
+ col1, col2 = st.columns(2)
564
+ col1.write("Asignar a: ")
565
+ col2.write("Industria: ")
566
+ col1.subheader(analista)
567
+ col2.subheader(industria)
568
+ col1.header(" ")
569
+ col2.header(" ")
570
+ col1, col2 = st.columns(2)
571
+ empresas = analista_emp[analista_emp["LV1"]==industria]["Empresa"]
572
+ i = 0
573
+ for empresa in empresas:
574
+ if i%2 == 0:
575
+ dicc[empresa] = col1.checkbox(empresa, value=val)
576
+ i += 1
577
+ else:
578
+ dicc[empresa] = col2.checkbox(empresa, value=val)
579
+ i += 1
580
+ submit = st.form_submit_button("Asignar")
581
+ if submit:
582
+ for empresa in dicc.keys():
583
+ if dicc[empresa]:
584
+ cambio = analista_emp2[analista_emp2["Empresa"] == empresa]
585
+ analista_emp2.loc[analista_emp2.Empresa == empresa, 'Analista'] = analista
586
+ save_s3(key, secret_key, bucket, analista_emp2, path)
587
+ style_table()
588
+ data_f = analista_emp2[["Analista", "Pais", "LV1", "Empresa"]]
589
+ data_f = data_f[data_f["Analista"] == analista]
590
+ graph = graphviz.Digraph()
591
+ for industry in list(set(data_f["LV1"])):
592
+ graph.edge(analista, industry)
593
+ d_ind = data_f[data_f["LV1"]==industry]
594
+ st.subheader("Mapeo Analista - Industrias")
595
+ st.graphviz_chart(graph)
596
+ d_ind = analista_emp2[["Analista", "Pais", "LV1", "Empresa"]]
597
+ d_ind = d_ind[d_ind["LV1"] == industria]
598
+ st.subheader("Analistas asignados a la industria " + industria)
599
+ st.table(d_ind)
600
+
601
+
602
+ def save_password():
603
+ key = creds3["S3_KEY_ID"]
604
+ secret_key = creds3["S3_SECRET_KEY"]
605
+ bucket = creds3["S3_BUCKET"]
606
+ path ='Claves.xlsx'
607
+ claves = read_excel_s3(key, secret_key, bucket, path)
608
+ col1, col2 = st.columns((1, 1.5))
609
+ with col1.form('Nueva clave'):
610
+ new_user = st.text_input("Ingresar usuario")
611
+ password = st.text_input("Ingresar clave")
612
+ plataforma = st.text_input("Plataforma")
613
+ submitted = st.form_submit_button('Ingresar')
614
+ if submitted:
615
+ claves = claves.append({"Clave": password,
616
+ "Usuario": new_user,
617
+ "Plataforma": plataforma
618
+ }, ignore_index=True)
619
+ save_s3(key, secret_key, bucket, claves, path)
620
+ style_table()
621
+ claves.index = claves['Plataforma']
622
+ col2.table(claves[['Usuario','Clave']])
623
+
apps/Google_Trends.py CHANGED
@@ -1,3 +1,490 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:109b974aedf666d1ca13ae246aefa434313a2a271cad85165bb3e2768c23be78
3
- size 25533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules import tables
2
+ from google_tools import trends as gtrends
3
+ import pandas as pd
4
+ import numpy as np
5
+ from datetime import timedelta, date
6
+ from statsmodels.tsa.seasonal import seasonal_decompose
7
+ import plotly.graph_objects as go
8
+ from plotly.subplots import make_subplots
9
+ import streamlit as st
10
+ import io
11
+ import boto3
12
+ import openpyxl
13
+
14
+
15
+ key ='AKIARYMZ4J2YQDB66VX4'
16
+ secret_key = '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'
17
+ bucket='portallvam'
18
+ path ='Momentum.xlsx'
19
+
20
+
21
+ def save_s3(key, secret_key, bucket, df, path):
22
+ with io.BytesIO() as output:
23
+ with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
24
+ for industry in df.keys():
25
+ df[industry].to_excel(writer, sheet_name=industry)
26
+ data = output.getvalue()
27
+ s3 = boto3.resource('s3', aws_access_key_id=key, aws_secret_access_key=secret_key)
28
+ s3.Bucket(bucket).put_object(Key=path, Body=data)
29
+
30
+
31
+ def read_excel_s3(key, secret_key, bucket, path):
32
+ s3_client = boto3.client('s3', aws_access_key_id=key, aws_secret_access_key=secret_key)
33
+ response = s3_client.get_object(Bucket=bucket, Key=path)
34
+ data = response["Body"].read()
35
+ df = pd.read_excel(io.BytesIO(data), sheet_name=None, index_col='Unnamed: 0.1')
36
+ return df
37
+
38
+
39
+ def generar_excel(ruta_guardado, Pestanas, Data):
40
+ wb = openpyxl.Workbook()
41
+ writer = pd.ExcelWriter(ruta_guardado)
42
+ for pestana in Pestanas:
43
+ wb.create_sheet(pestana)
44
+ std = wb.get_sheet_by_name('Sheet')
45
+ wb.remove_sheet(std)
46
+ wb.save(ruta_guardado)
47
+ for i, pestana in enumerate(Pestanas):
48
+ if pestana=='Real Estate Management & Development-CL':
49
+ pestana = 'Real Estate-CL'
50
+ Data['Real Estate Management & Development-CL'].to_excel(writer, sheet_name=pestana)
51
+ elif pestana=='Real Estate Management & Development-BR':
52
+ pestana = 'Real Estate-BR'
53
+ Data['Real Estate Management & Development-BR'].to_excel(writer, sheet_name=pestana)
54
+ else:
55
+ Data[pestana].to_excel(writer, sheet_name=Pestanas[i])
56
+ writer.save()
57
+
58
+
59
+ def colores_corporativos(colors=None):
60
+
61
+ color_dict = {'red': (204, 0, 51),
62
+ 'light_blue': (110, 162, 201),
63
+ 'light_gray': (135, 146, 158),
64
+ 'grey': (105, 105, 105),
65
+ 'yellow': (195, 195, 9),
66
+ 'dark_purple': (119, 28, 95),
67
+ 'blue': (42, 83, 113),
68
+ 'purple': (159, 37, 127),
69
+ 'light_yellow': (252, 252, 196),
70
+ 'light_green': (122, 178, 153),
71
+ 'gray': (66, 74, 82)}
72
+
73
+ for key in color_dict:
74
+ color_dict[key] = tuple(v/255 for v in color_dict[key])
75
+
76
+ if colors is None:
77
+ return color_dict
78
+ else:
79
+ aux = {col: color_dict[col] for col in colors}
80
+ return aux
81
+
82
+
83
+ corp_colors = list(colores_corporativos().values())
84
+ colors2 = []
85
+ for i in range(len(corp_colors)):
86
+ colors2.append("rgb" + str(corp_colors[i]))
87
+
88
+
89
+ company_db = pd.read_excel('Data/Company_Base_Definitivo.xlsx', sheet_name='Compilado')
90
+ id_to_ticker = {str(row['ID_Quant']): str(row['Ticker Bloomberg']).split()[0] for i, row in company_db.iterrows()}
91
+
92
+ countries_dict = {'BR': 'Brazil', 'CL': 'Chile', 'US': 'Brazil',
93
+ 'US-Disease': 'Brazil'}
94
+
95
+
96
+ @st.cache(suppress_st_warning=True)
97
+ def data_request(countries, start, currency='USD'):
98
+ close_price = {'Brazil': [],
99
+ 'Chile': []}
100
+ market_cap = {'Brazil': [],
101
+ 'Chile': []}
102
+ for c in countries:
103
+ close_price[c] = tables.EquityMaster(field='IQ_CLOSEPRICE_ADJ', currency=currency, country=c).query(
104
+ rename=['asset'], start=start, expand=True)
105
+ market_cap[c] = tables.EquityMaster(field='IQ_MARKETCAP', currency=currency, country=c).query(
106
+ start=start, rename=['asset'], expand=True)
107
+
108
+ close_price[c] = close_price[c].loc[:, close_price[c].columns.isin(id_to_ticker.keys())]
109
+ close_price[c].columns = [id_to_ticker[col] for col in close_price[c].columns]
110
+
111
+ market_cap[c] = market_cap[c].loc[:, market_cap[c].columns.isin(id_to_ticker.keys())]
112
+ market_cap[c].columns = [id_to_ticker[col] for col in market_cap[c].columns]
113
+ return [close_price, market_cap]
114
+
115
+
116
+ @st.cache(suppress_st_warning=True)
117
+ def trends_request(keywords, today):
118
+ trends_frames_dict = {}
119
+ for sector, values in keywords.items():
120
+ if not (sector in ['Restaurantes']):
121
+ trends_frames_dict[sector] = {}
122
+ print('Buscando para ' + sector)
123
+ for country_name in values.columns:
124
+ words = values[country_name].dropna()
125
+ if '-' in country_name:
126
+ fixed_country_name = country_name.split('-')[0].strip()
127
+ else:
128
+ fixed_country_name = country_name
129
+ words_index = pd.DataFrame()
130
+ for word in words:
131
+ new_data = gtrends.keyword_trend(word, fixed_country_name, end_date=today)
132
+ if new_data is not None:
133
+ words_index = pd.concat([words_index,
134
+ new_data],
135
+ axis=1)
136
+ else:
137
+ print('No se encuentra data para ' + word)
138
+ trends_frames_dict[sector][country_name] = words_index
139
+ trends_frames_dict[sector][country_name].index.name = None
140
+ return trends_frames_dict
141
+
142
+
143
+ def trends_frames_excel(dicc):
144
+ sheets_cl = []
145
+ sheets_br = []
146
+ for key_1 in dicc.keys():
147
+ for key_2 in dicc[key_1].keys():
148
+ if key_2=='CL':
149
+ sheets_cl .append(key_1 + '-' + key_2)
150
+ else:
151
+ sheets_br.append(key_1 + '-' + key_2)
152
+ trends_frames_dict_cl = {}
153
+ trends_frames_dict_br = {}
154
+ for key_1 in dicc.keys():
155
+ for key_2 in dicc[key_1].keys():
156
+ if key_2=='CL':
157
+ trends_frames_dict_cl[key_1 + '-'+ key_2] = dicc[key_1][key_2]
158
+ elif key_2=='BR':
159
+ trends_frames_dict_br[key_1 + '-' + key_2] = dicc[key_1][key_2]
160
+ elif key_2=='US' or key_2=='US-Disease':
161
+ trends_frames_dict_br[key_1 + '-' + key_2] = dicc[key_1][key_2]
162
+
163
+ generar_excel('Data/GT_CL.xlsx', sheets_cl, trends_frames_dict_cl)
164
+ df_cl = pd.read_excel('Data/GT_CL.xlsx', sheet_name=None)
165
+ st.write(df_cl)
166
+ save_s3(key=key, secret_key=secret_key, bucket=bucket, df=df_cl, path='GT_CL.xlsx')
167
+
168
+ generar_excel('Data/GT_BR.xlsx', sheets_br, trends_frames_dict_br)
169
+ df_br = pd.read_excel('Data/GT_BR.xlsx', sheet_name=None)
170
+ save_s3(key=key, secret_key=secret_key, bucket=bucket, df=df_br, path='GT_BR.xlsx')
171
+
172
+
173
+ def read_trends_frames(country):
174
+ if country=='CL':
175
+ return read_excel_s3(key=key, secret_key=secret_key, bucket=bucket, path='GT_CL.xlsx')
176
+ elif country=='BR':
177
+ return read_excel_s3(key=key, secret_key=secret_key, bucket=bucket, path='GT_BR.xlsx')
178
+
179
+
180
+ def report():
181
+ form = st.form('Report')
182
+ start_date = str(date.today() - timedelta(5 * 365))
183
+ select_countries = form.multiselect('¿Qué país(es) desea visualizar?', ['Todos', 'Chile', 'Brazil'])
184
+ if 'Todos' in select_countries:
185
+ select_countries = ['Chile', 'Brazil']
186
+ update_data = form.form_submit_button("Actualizar Datos")
187
+ accept = form.form_submit_button('Visualizar')
188
+ col1, col2 = st.columns(2)
189
+
190
+ if update_data:
191
+ xls = pd.ExcelFile('Data/keywords_definitivas_mongo.xlsx')
192
+ industry_filter = ['Pesca', 'Agricola', 'Financials-RP']
193
+ keywords_dict = {sheet: xls.parse(sheet) for sheet in xls.sheet_names
194
+ if sheet not in industry_filter}
195
+ xls.close()
196
+ del xls
197
+
198
+ # Arreglamos una llave porque una hoja de excel alcanza el máximo de caracteres posible para un nombre.
199
+ new_key = "Real Estate Management & Development"
200
+ old_key = "Real Estate Management & Develo"
201
+ keywords_dict[new_key] = keywords_dict.pop(old_key)
202
+
203
+ trends_dict = trends_request(keywords_dict, date.today())
204
+ trends_frames_excel(trends_dict)
205
+ ud = pd.read_excel('Data/update_data.xlsx')
206
+ ud = ud[ud['View'] != 'Google Trends']
207
+ today = date.today().strftime('%d-%m-%Y')
208
+ ud = ud.append({"View": 'Google Trends',
209
+ "Last_Update": today}, ignore_index=True)
210
+ ud.to_excel('Data/update_data.xlsx', index=False)
211
+
212
+ if accept:
213
+ close_price_dict, market_cap_dict = data_request(select_countries, start_date)
214
+
215
+ ew_index = {}
216
+ mw_index = {}
217
+ country_index = {}
218
+
219
+ if select_countries == ['Brazil']:
220
+ dates = {'Brazil': sorted(list(set(market_cap_dict['Brazil'].index)
221
+ .union(set(close_price_dict['Brazil'].index))))}
222
+ elif select_countries == ['Chile']:
223
+ dates = {'Chile': sorted(list(set(market_cap_dict['Chile'].index)
224
+ .union(set(close_price_dict['Chile'].index))))}
225
+ else:
226
+ dates = {'Brazil': sorted(list(set(market_cap_dict['Brazil'].index)
227
+ .union(set(close_price_dict['Brazil'].index)))),
228
+ 'Chile': sorted(list(set(market_cap_dict['Chile'].index)
229
+ .union(set(close_price_dict['Chile'].index))))}
230
+
231
+ for country in select_countries:
232
+ mkt = market_cap_dict[country]
233
+ cp = close_price_dict[country]
234
+ w = mkt.div(mkt.sum(1).values, axis=0)
235
+ rets = cp.pct_change()
236
+ country_index[country] = pd.DataFrame({'MW': (w * rets).sum(1),
237
+ 'EW': rets.mean(1)}).fillna(0)
238
+ industries_1 = np.unique(company_db[['LV1']].values)
239
+ industries_2 = np.unique(company_db[['LV2']].values)
240
+ industries = np.unique(np.concatenate([industries_1, industries_2]))
241
+ df_mw_index = pd.DataFrame(columns=industries, index=dates[country])
242
+ df_ew_index = pd.DataFrame(columns=industries, index=dates[country])
243
+ for industry in industries:
244
+ industry = str(industry)
245
+ mc = mkt.loc[:, mkt.columns.isin(company_db[company_db['LV1'] == industry]['Ticker'])]
246
+ prices = cp.loc[:, cp.columns.isin(company_db[company_db['LV1'] == industry]['Ticker'])]
247
+
248
+ w = mc.div(mc.sum(1).values, axis=0)
249
+ rets = prices.pct_change()
250
+ df_mw_index[industry] = (w * rets).sum(1)
251
+ df_ew_index[industry] = rets.mean(1)
252
+ mw_index[country] = df_mw_index.fillna(0)
253
+ ew_index[country] = df_ew_index.fillna(0)
254
+
255
+ xls = pd.ExcelFile('Data/keywords_definitivas_mongo.xlsx')
256
+ industry_filter = ['Pesca', 'Agricola', 'Financials-RP', 'Agriculture']
257
+ keywords_dict = {sheet: xls.parse(sheet) for sheet in xls.sheet_names
258
+ if sheet not in industry_filter}
259
+ xls.close()
260
+ del xls
261
+
262
+ new_key = "Real Estate Management & Development"
263
+ old_key = "Real Estate Management & Develo"
264
+ keywords_dict[new_key] = keywords_dict.pop(old_key)
265
+
266
+ trends_frames = {}
267
+ trends_frames_cl = read_trends_frames('CL')
268
+ trends_frames_br = read_trends_frames('BR')
269
+
270
+ for key_cl in trends_frames_cl.keys():
271
+ trends_frames_cl[key_cl] = trends_frames_cl[key_cl].drop(columns='Unnamed: 0')
272
+
273
+ for key_br in trends_frames_br.keys():
274
+ trends_frames_br[key_br] = trends_frames_br[key_br].drop(columns='Unnamed: 0')
275
+
276
+ for industry in keywords_dict.keys():
277
+ if not industry=='Restaurantes':
278
+ countries_in_industry = keywords_dict[industry].columns
279
+ trends_frames[industry] = {}
280
+ for c in countries_in_industry:
281
+ if c=='CL':
282
+ if industry == 'Real Estate Management & Development':
283
+ index = trends_frames_cl['Real Estate-CL'].index
284
+ trends_frames[industry][c] = pd.DataFrame(columns=trends_frames_cl['Real Estate-CL'].columns,
285
+ index=index)
286
+ else:
287
+ index = trends_frames_cl[industry+'-CL'].index
288
+ trends_frames_cl[industry+'-CL'] = trends_frames_cl[industry+'-CL'].loc[:, trends_frames_cl[industry+'-CL'].columns.notnull()]
289
+ trends_frames[industry][c] = pd.DataFrame(columns=trends_frames_cl[industry+'-CL'].columns,
290
+ index=index)
291
+ elif c=='BR':
292
+ if industry == 'Real Estate Management & Development':
293
+ index = trends_frames_br['Real Estate-BR'].index
294
+ trends_frames[industry][c] = pd.DataFrame(columns=trends_frames_br['Real Estate-BR'].columns,
295
+ index=index)
296
+ else:
297
+ index = trends_frames_br[industry + '-BR'].index
298
+ trends_frames[industry][c] = pd.DataFrame(columns=trends_frames_br[industry+'-BR'].columns,
299
+ index=index)
300
+ if 'CL' in countries_in_industry:
301
+ if industry == 'Real Estate Management & Development':
302
+ for col_cl in trends_frames_cl['Real Estate-CL'].columns:
303
+ if col_cl in keywords_dict[industry]['CL'].values:
304
+ trends_frames[industry]['CL'][col_cl] = trends_frames_cl['Real Estate-CL'][col_cl].dropna()
305
+ else:
306
+ for col_cl in trends_frames_cl[industry+'-CL'].columns:
307
+ if col_cl in keywords_dict[industry]['CL'].values:
308
+ trends_frames[industry]['CL'][col_cl] = trends_frames_cl[industry+'-CL'][col_cl].dropna()
309
+ if 'BR' in countries_in_industry:
310
+ if industry == 'Real Estate Management & Development':
311
+ for col_br in trends_frames_br['Real Estate-BR'].columns:
312
+ if col_br in keywords_dict[industry]['BR'].values:
313
+ trends_frames[industry]['BR'][col_br] = trends_frames_br['Real Estate-BR'][col_br].dropna()
314
+ else:
315
+ for col_br in trends_frames_br[industry+'-BR'].columns:
316
+ if col_br in keywords_dict[industry]['BR'].values:
317
+ trends_frames[industry]['BR'][col_br] = trends_frames_br[industry+'-BR'][col_br].dropna()
318
+ deseason = True
319
+ n_words = 5
320
+ for industry in keywords_dict.keys():
321
+ if not industry == 'Restaurantes':
322
+ countries_in_industry = keywords_dict[industry].columns
323
+ for c in countries_in_industry:
324
+ trends_frames[industry][c] = trends_frames[industry][c].loc[:, trends_frames[industry][c].columns.notnull()]
325
+
326
+ summary = pd.DataFrame()
327
+ fig1 = make_subplots(rows=2, cols=1,
328
+ subplot_titles=['Cambio Semanal', 'Cambio 1 Mes', 'Cambio 3 Meses', 'Cambio YTD'],
329
+ horizontal_spacing=0.6, )
330
+ fig2 = make_subplots(rows=2, cols=1,
331
+ subplot_titles=['Cambio Semanal', 'Cambio 1 Mes', 'Cambio 3 Meses', 'Cambio YTD'],
332
+ horizontal_spacing=0.6)
333
+ for industry, dict_ in trends_frames.items():
334
+ for country, df_ in dict_.items():
335
+ if deseason:
336
+ df_ = pd.DataFrame({col: df_[col] -
337
+ seasonal_decompose(df_[col], period=8).seasonal
338
+ for col in df_.columns})
339
+ summary[f'{industry}-{country}'] = df_.mean(1)
340
+ summary = (summary - summary.mean()) / summary.std()
341
+
342
+ delta_w = summary.diff(1).iloc[-1].sort_values(ascending=True)
343
+ delta_m = summary.diff(4).iloc[-1].sort_values(ascending=True)
344
+ delta_3m = summary.diff(12).iloc[-1].sort_values(ascending=True)
345
+ delta_ytd = summary.resample('Y').last().diff().iloc[-1].sort_values(ascending=True)
346
+
347
+ fig1.add_trace(go.Bar(x=delta_w.array, y=delta_w.index, orientation='h', marker_color=colors2[2],
348
+ showlegend=False), row=1, col=1)
349
+
350
+ fig2.add_trace(go.Bar(x=delta_m.array, y=delta_m.index, orientation='h', marker_color=colors2[2],
351
+ showlegend=False), row=1, col=1)
352
+
353
+ fig1.add_trace(go.Bar(x=delta_3m.array, y=delta_3m.index, orientation='h', marker_color=colors2[2],
354
+ showlegend=False), row=2, col=1)
355
+
356
+ fig2.add_trace(go.Bar(x=delta_ytd.array, y=delta_ytd.index, orientation='h', marker_color=colors2[2],
357
+ showlegend=False), row=2, col=1)
358
+
359
+ fig1.update_layout(title_text='Cambios en las Búsquedas', margin_b=0, margin_t=50, margin_r=0, margin_l=0)
360
+ fig2.update_layout(margin_b=0, margin_t=50, margin_r=0, margin_l=0)
361
+ col1.plotly_chart(fig1, use_container_width=True)
362
+ col2.plotly_chart(fig2, use_container_width=True)
363
+
364
+ for industry in trends_frames:
365
+ for i, (country, data) in enumerate(trends_frames[industry].items()):
366
+ if countries_dict[country] in select_countries:
367
+
368
+ fig_indices1 = make_subplots(rows=2, cols=1, specs=[[{"secondary_y": True}],
369
+ [{"secondary_y": False}]],
370
+ subplot_titles=['GT (zscore) vs Spread Histórico',
371
+ 'Variación YoY GT Histórico'],
372
+ horizontal_spacing=0.)
373
+ fig_indices2 = make_subplots(rows=2, cols=1, specs=[[{"secondary_y": True}],
374
+ [{"secondary_y": False}]],
375
+ subplot_titles=['GT (zscore) vs Spread Último Año',
376
+ 'Variación YoY GT Último año'],
377
+ horizontal_spacing=0.3)
378
+
379
+ aux_df = summary[f'{industry}-{country}']
380
+ aux_df.index.name = ''
381
+ mm_year = aux_df.rolling(52).mean()
382
+ mm_half = aux_df.rolling(26).mean()
383
+ mm_quarter = aux_df.rolling(13).mean()
384
+ mm_month = aux_df.rolling(4).mean()
385
+ mm = pd.concat([mm_year, mm_half, mm_quarter, mm_month], axis=1)
386
+ mm.columns = ['1Y', '6M', '3M', '1M']
387
+ if deseason:
388
+ p = '3M'
389
+ else:
390
+ p = '1Y'
391
+
392
+ fig_indices1.add_trace(go.Scatter(x=mm[p].index, y=mm[p].array, line=dict(color=colors2[0]),
393
+ showlegend=True, name=f'{p} MM GT Index'),
394
+ secondary_y=False, row=1, col=1)
395
+
396
+ fig_indices1.update_layout(title_text=f'{industry} - {country}')
397
+ fig_indices2.add_trace(
398
+ go.Scatter(x=mm[p].iloc[-52:].index, y=mm[p].iloc[-52:].array, line=dict(color=colors2[0]),
399
+ showlegend=False, name=f'{p} MM GT Index'),
400
+ secondary_y=False, row=1, col=1)
401
+
402
+ mm_4w = data.mean(1).rolling(4).mean()
403
+ yoy = mm_4w.pct_change(52)
404
+ aux2 = pd.concat([yoy], axis=1)
405
+ aux2.columns = ['YoY']
406
+ aux2.index.name = ''
407
+
408
+ fig_indices1.add_trace(go.Bar(x=aux2.dropna().index, y=aux2.dropna()['YoY'],
409
+ marker_color=colors2[1], showlegend=False), row=2, col=1)
410
+ fig_indices2.add_trace(go.Bar(x=aux2.dropna().iloc[-52:].index, y=aux2.dropna()['YoY'].iloc[-52:].array,
411
+ marker_color=colors2[1], showlegend=False), row=2, col=1)
412
+
413
+ if country == 'US' and industry == 'Pesca':
414
+ country_ = 'Chile'
415
+ else:
416
+ country_ = countries_dict[country]
417
+
418
+ spread_mw = (mw_index[country_][industry].rolling(52).apply(lambda x: (1 + x).prod()) -
419
+ country_index[country_]['MW'].rolling(52).apply(lambda x: (1 + x).prod()))
420
+ spread_ew = (ew_index[country_][industry].rolling(52).apply(lambda x: (1 + x).prod()) -
421
+ country_index[country_]['EW'].rolling(52).apply(lambda x: (1 + x).prod()))
422
+
423
+ spread = pd.DataFrame({'EW': spread_ew, 'MW': spread_mw})
424
+
425
+ fig_indices1.add_trace(go.Scatter(x=spread['MW'].dropna().index, y=spread['MW'].dropna().array,
426
+ name='Spread MW', line=dict(color=colors2[3])),
427
+ secondary_y=True, row=1, col=1)
428
+
429
+ fig_indices2.add_trace(
430
+ go.Scatter(x=spread['MW'].iloc[-260:].dropna().index, y=spread['MW'].iloc[-260:].dropna().array,
431
+ name='Spread MW', line=dict(color=colors2[3])),
432
+ secondary_y=True, row=1, col=1)
433
+
434
+ fig_indices1.update_xaxes(showticklabels=False)
435
+ fig_indices2.update_xaxes(showticklabels=False)
436
+ fig_indices1.layout.update(xaxis_rangeslider_visible=False, margin_b=20,
437
+ margin_r=20, margin_l=20,
438
+ legend=dict(orientation="h",
439
+ yanchor="top",
440
+ y=0.6,
441
+ xanchor="right",
442
+ x=1))
443
+ fig_indices2.layout.update(xaxis_rangeslider_visible=False,
444
+ margin_b=20,
445
+ margin_r=20, margin_l=20,
446
+ legend=dict(orientation="h",
447
+ yanchor="top",
448
+ y=0.6,
449
+ xanchor="right",
450
+ x=1))
451
+ fig_indices1.update_xaxes(showticklabels=True, row=2,
452
+ col=1)
453
+ fig_indices2.update_xaxes(showticklabels=True, row=2,
454
+ col=1)
455
+
456
+ fig_indices1.update_yaxes(tickformat=',.0%', row=2, col=1)
457
+ fig_indices2.update_yaxes(tickformat=',.0%', row=2, col=1)
458
+
459
+ if deseason:
460
+ df1 = pd.DataFrame({col: data[col] -
461
+ seasonal_decompose(data[col]).seasonal
462
+ for col in data.columns})
463
+ else:
464
+ df1 = data
465
+
466
+ # Top word's table plot
467
+ last_week = df1.iloc[-1].sort_values(ascending=False)[:n_words] / 100
468
+ all_time = df1.mean().sort_values(ascending=False)[:n_words] / 100
469
+
470
+ fig_W = make_subplots(subplot_titles=['Top Words en ' + f'{industry} - {country}'])
471
+
472
+ table = pd.concat([pd.Series(last_week.index),
473
+ pd.Series(all_time.index)], axis=1)
474
+ table.columns = ['Top 1W', 'Top 5Y']
475
+ fig_W.add_trace(go.Table(header=dict(values=table.columns),
476
+ cells=dict(values=[table['Top 1W'].values, table['Top 5Y'].values])))
477
+ fig_W.update_layout(margin_b=0, margin_t=50,
478
+ margin_r=0, margin_l=0,
479
+ height=200)
480
+ fig_indices1.update_layout(margin_b=0, margin_t=50,
481
+ margin_r=0, margin_l=0,
482
+ height=600)
483
+ fig_indices2.update_layout(margin_b=0, margin_t=50,
484
+ margin_r=0, margin_l=0,
485
+ height=600)
486
+ col1.plotly_chart(fig_indices1, use_container_width=True)
487
+ col2.plotly_chart(fig_indices2, use_container_width=True)
488
+
489
+ fig_W.update_layout(margin_b=0, margin_t=30, margin_r=10, margin_l=0)
490
+ st.plotly_chart(fig_W, use_container_width=True)
apps/Home.py CHANGED
@@ -1,3 +1,331 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:13c55d6844ab21cb85b970648c8c8a79a98b401b637549a96dd7f96c6f4f4873
3
- size 14238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ from datetime import date
3
+ from plotly import graph_objs as go
4
+ import pybase64 as base64
5
+ import numpy as np
6
+ import investpy
7
+ import streamlit as st
8
+ import datetime as dt
9
+ import io
10
+
11
+
12
+ def get_table_excel_link(df, selected_stocks):
13
+ towrite = io.BytesIO()
14
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
15
+ header=True)
16
+ towrite.seek(0) # reset pointer
17
+ file_name = 'Data'+ selected_stocks + '.xlsx'
18
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
19
+ name_mark = "Descargar " + selected_stocks + ".xlsx"
20
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
21
+ linko= f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
22
+ return linko
23
+
24
+
25
+ @st.cache
26
+ def tabla_commodity(stocks, TODAY):
27
+ tabla = pd.DataFrame()
28
+ year_ago = date.today() - dt.timedelta(days=365)
29
+ year_ago = year_ago.strftime("%d/%m/%Y")
30
+ for stock in stocks:
31
+ precios = investpy.commodities.get_commodity_historical_data(
32
+ commodity=stock,
33
+ from_date=year_ago,
34
+ to_date=TODAY)
35
+ precios = precios["Close"]
36
+ last_price = precios.iloc[-1]
37
+ oned = precios.iloc[-2]
38
+ onew = precios.iloc[-7]
39
+ onem = precios.iloc[-30]
40
+ oney = precios.iloc[0]
41
+ return1m = str(round((last_price/onem-1)*100, 2))+"%"
42
+ return1d = str(round((last_price/oned-1)*100, 2))+"%"
43
+ return1w = str(round((last_price/onew-1)*100, 2))+"%"
44
+ return1y = str(round((last_price/oney-1)*100, 2))+"%"
45
+ tabla = tabla.append([[return1d, return1w, return1m, return1y]])
46
+ tabla.columns = ["1d", "1w", "1m", "1y"]
47
+ tabla.index = stocks
48
+ return tabla
49
+
50
+
51
+ @st.cache
52
+ def tabla_indices(index, countries, TODAY):
53
+ tabla = pd.DataFrame()
54
+ year_ago = date.today() - dt.timedelta(days=365)
55
+ year_ago = year_ago.strftime("%d/%m/%Y")
56
+ for i in range(len(index)):
57
+ precios = investpy.get_index_historical_data(index=index[i],
58
+ country=countries[i],
59
+ from_date=year_ago,
60
+ to_date=TODAY)
61
+ precios = precios["Close"]
62
+ last_price = precios.iloc[-1]
63
+ oned = precios.iloc[-2]
64
+ onew = precios.iloc[-7]
65
+ onem = precios.iloc[-30]
66
+ oney = precios.iloc[0]
67
+ return1m = str(round((last_price/onem-1)*100, 2))+"%"
68
+ return1d = str(round((last_price/oned-1)*100, 2))+"%"
69
+ return1w = str(round((last_price/onew-1)*100, 2))+"%"
70
+ return1y = str(round((last_price/oney-1)*100, 2))+"%"
71
+ tabla = tabla.append([[return1d, return1w, return1m, return1y]])
72
+ tabla.columns = ["1d", "1w", "1m", "1y"]
73
+ tabla.index = index
74
+ return tabla
75
+
76
+
77
+ @st.cache
78
+ def tabla_bonos(stocks, TODAY):
79
+ tabla = pd.DataFrame()
80
+ year_ago = date.today() - dt.timedelta(days=365)
81
+ year_ago = year_ago.strftime("%d/%m/%Y")
82
+ for stock in stocks:
83
+
84
+ precios = investpy.get_bond_historical_data(bond=stock,
85
+ from_date=year_ago,
86
+ to_date=TODAY)
87
+ precios = precios["Close"]
88
+ last_price = precios.iloc[-1]
89
+ oned = precios.iloc[-2]
90
+ onew = precios.iloc[-7]
91
+ onem = precios.iloc[-30]
92
+ oney = precios.iloc[0]
93
+ return1m = str(round((last_price-onem)*100, 2))+"%"
94
+ return1d = str(round((last_price -oned)*100, 2))+"%"
95
+ return1w = str(round((last_price -onew)*100, 2))+"%"
96
+ return1y = str(round((last_price - oney)*100, 2))+"%"
97
+ tabla = tabla.append([[return1d, return1w, return1m, return1y]])
98
+ tabla.columns = ["1d", "1w", "1m", "1y"]
99
+ tabla.index = stocks
100
+ return tabla
101
+
102
+
103
+ def highlight_max(s):
104
+ if s.dtype == np.object:
105
+ is_neg = [False for _ in range(s.shape[0])]
106
+ else:
107
+ is_neg = s < 0
108
+ return ['color: red;' if cell else 'color:black' for cell in is_neg]
109
+
110
+
111
+ def button_style():
112
+ style_button = """
113
+ <style>
114
+ button {
115
+ display: inline-block;
116
+ background-color: #e8e8e8;
117
+ border-radius: 15px;
118
+ border: 4px #cccccc;
119
+ color: #4a4a4a;
120
+ text-align: center;
121
+ font-size: 12px;
122
+ padding: 2px;
123
+ width: 250px;
124
+ transition: all 0.5s;
125
+ cursor: pointer;
126
+ margin: 5px;
127
+ }
128
+ button span {
129
+ cursor: pointer;
130
+ display: inline-block;
131
+ position: relative;
132
+ transition: 0.5s;
133
+ }
134
+ button span:after {
135
+ content: '\00bb';
136
+ position: absolute;
137
+ opacity: 0;
138
+ top: 0;
139
+ right: -20px;
140
+ transition: 0.5s;
141
+ }
142
+ button:hover {
143
+ background-color: #bb1114;
144
+ color:#e8e8e8;
145
+ }
146
+ button:hover span {
147
+ padding-right: 25px;
148
+ }
149
+ button:hover span:after {
150
+ opacity: 1;
151
+ right: 0;
152
+ }
153
+ .stMarkdown{
154
+ margin-bottom:0px;}
155
+ </style>
156
+ """
157
+ st.markdown(style_button, unsafe_allow_html=True)
158
+
159
+
160
+ def style_table():
161
+ # tr:hover {background-color: #E8E8E8;
162
+ # color:#BB1114;}
163
+ style_table = """
164
+ <style>
165
+ tr { line-height: 5px; }
166
+ thead {
167
+ background-color:#BB1114 ;
168
+ color: #E8E8E8;
169
+ }
170
+ tbody tr:nth-child(odd) {
171
+ background-color: #fff;
172
+ }
173
+ tbody tr:nth-child(even) {
174
+ background-color: #eee;
175
+ }
176
+ .css-1rcck9u{
177
+ padding:0.25rem;}
178
+ tbody tr:nth-child(odd)
179
+ stTable {
180
+ border-collapse: collapse;
181
+ background-color:red;
182
+ margin: 25px 0;
183
+ font-size: 0.9em;
184
+ min-width: 400px;
185
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
186
+ }
187
+ table{
188
+ margin-top:0px;
189
+ font-size:9px;
190
+ padding:0px;
191
+ height:200px;}
192
+ .st-cc, .st-cb{
193
+ padding-top:5px;
194
+ padding-bottom:5px;}
195
+ h3, h1, h2, .svg-container {
196
+ animation-duration: 3s;
197
+ animation-name: slidein;
198
+ }
199
+ @keyframes slidein {
200
+ from {
201
+ margin-left: 100%;
202
+ width: 300%
203
+ }
204
+ to {
205
+ margin-left: 0%;
206
+ width: 100%;
207
+ }
208
+ }
209
+ </style>
210
+ """
211
+ st.markdown(style_table, unsafe_allow_html=True)
212
+
213
+
214
+ def seleccionar_fecha(fecha_select):
215
+ if fecha_select == "1 week":
216
+ fec_in = date.today() - dt.timedelta(days=7)
217
+ elif fecha_select == "1 month":
218
+ fec_in = date.today() - dt.timedelta(days=30)
219
+ elif fecha_select == "3 month":
220
+ fec_in = date.today() - dt.timedelta(days=90)
221
+ elif fecha_select == "6 month":
222
+ fec_in = date.today() - dt.timedelta(days=180)
223
+ elif fecha_select == "1 year":
224
+ fec_in = date.today() - dt.timedelta(days=365)
225
+ elif fecha_select == "5 year":
226
+ fec_in = date.today() - dt.timedelta(days=365*5)
227
+ fec_in = fec_in.strftime("%d/%m/%Y")
228
+ return fec_in
229
+
230
+
231
+ def stock_price():
232
+ style_table()
233
+ button_style()
234
+ TODAY = date.today().strftime("%d/%m/%Y")
235
+ YDAY = date.today() - dt.timedelta(days=1)
236
+ YDAY = YDAY.strftime("%d/%m/%Y")
237
+ commodity = ["Copper", "Silver", "Gold", "Platinum", 'Brent Oil',
238
+ 'Heating Oil']
239
+ # bonos = ["Brazil 10Y", "Mexico 10Y" , "Chile 10Y", "Colombia 10Y"
240
+ # , "Peru 10Y"]
241
+ bonds10y = ["Brazil 10Y", "Mexico 10Y", "Chile 10Y", "Colombia 10Y",
242
+ "Peru 10Y", "China 10Y"]
243
+ index = ["S&P CLX IPSA", "S&P Merval", "Bovespa", "S&P 500"]
244
+ countries = ["chile", "argentina", "brazil", "united states"]
245
+ col1, col2, col3 = st.beta_columns(3)
246
+ cols = st.beta_columns((3, 2, 3, 2, 3, 2))
247
+ col1.markdown('<center><h1 style="font-size:22px;">Principales bonos 10Y</h1><center>', unsafe_allow_html=True)
248
+ col2.markdown('<center><h1 style="font-size:22px;">Principales commodities</h1><center>', unsafe_allow_html=True)
249
+ col3.markdown('<center><h1 style="font-size:22px;">Principales indices</h1><center>', unsafe_allow_html=True)
250
+ selected_com = cols[2].selectbox(" ", commodity)
251
+ selected_index = cols[4].selectbox(" ", index)
252
+ selected_bonds = cols[0].selectbox(" ", bonds10y)
253
+ fecha_select = cols[3].selectbox(" ", ["1 year", "6 month", "3 month",
254
+ "1 month", "1 week"])
255
+ fecha_select2 = cols[5].selectbox(" ", ["1 year", "6 month", "3 month",
256
+ "1 month", "1 week"])
257
+ fecha_select3 = cols[1].selectbox(" ", ["1 year", "6 month", "3 month",
258
+ "1 month", "1 week"])
259
+ # fecha_select =cols[2].button("hola")
260
+ fec_in = seleccionar_fecha(fecha_select)
261
+ fec_in2 = seleccionar_fecha(fecha_select2)
262
+ fec_in3 = seleccionar_fecha(fecha_select3)
263
+ selected_country = countries[index.index(selected_index)]
264
+ data_bonds = investpy.get_bond_historical_data(bond=selected_bonds,
265
+ from_date=fec_in3,
266
+ to_date=TODAY)
267
+ data_com = investpy.commodities.get_commodity_historical_data(
268
+ commodity=selected_com,
269
+ from_date=fec_in,
270
+ to_date=TODAY)
271
+ data_index = investpy.get_index_historical_data(index=selected_index,
272
+ country=selected_country,
273
+ from_date=fec_in2,
274
+ to_date=TODAY)
275
+
276
+ def plot_raw_data(col, data, color, prefijo):
277
+ fig = go.Figure()
278
+ close_ = go.Scatter(x=data.index, y=data['Close'], name="stock_close",
279
+ line=dict(color=color), fill='tonexty')
280
+ fig.add_trace(close_)
281
+ fig.layout.update(title_text="", xaxis_rangeslider_visible=True,
282
+ width=300, height=200, margin_b=0, margin_t=0,
283
+ margin_r=0, margin_l=0)
284
+ fig.update_yaxes(range=[min(data['Close'])/1.05,
285
+ max(data['Close'])*1.05], tickprefix=prefijo)
286
+ col.plotly_chart(fig)
287
+ plot_raw_data(cols[0], data_bonds, 'seagreen', "")
288
+ plot_raw_data(cols[2], data_com, 'midnightblue', "$")
289
+ plot_raw_data(cols[4], data_index, 'dimgrey', "$")
290
+ col1, col2, col3 = st.beta_columns(3)
291
+ cols = st.beta_columns((3, 2, 3, 2, 3, 2))
292
+ last_price = data_bonds.iloc[-1]["Close"]
293
+ first_price = data_bonds.iloc[0]["Close"]
294
+ returns = round((last_price/first_price-1)*100, 2)
295
+ cols[0].markdown('<h4 style="font-size:12px; padding-left:15px; margin-bottom:0px;">'+"Precio"+"</h4>", unsafe_allow_html=True)
296
+ cols[0].markdown('<p style="font-size:25px; padding-left:30px;">'+"{:,}".format(last_price)+"%</p>", unsafe_allow_html=True)
297
+ if returns > 0:
298
+ cols[1].markdown('<p style="font-size:20px; padding-top:22px; color:green;">▲ '+str(returns)+" %</p>", unsafe_allow_html=True)
299
+ else:
300
+ cols[1].markdown('<p style="font-size:20px; padding-top:22px; color:red;">▼ '+str(returns)+" %</p>", unsafe_allow_html=True)
301
+ last_price2 = data_com.iloc[-1]["Close"]
302
+ first_price2 = data_com.iloc[0]["Close"]
303
+ returns2 = round((last_price2/first_price2-1)*100, 2)
304
+ cols[2].markdown('<h4 style="font-size:12px; padding-left:15px; margin-bottom:0px;">'+"Precio"+"</h4>", unsafe_allow_html=True)
305
+ cols[2].markdown('<p style="font-size:25px; padding-left:30px;">$'+"{:,}".format(last_price2)+"</p>", unsafe_allow_html=True)
306
+ if returns2 > 0:
307
+ cols[3].markdown('<p style="font-size:20px; padding-top:22px; color:green;">▲ '+str(returns2)+" %</p>", unsafe_allow_html=True)
308
+ else:
309
+ cols[3].markdown('<p style="font-size:20px; padding-top:22px; color:red;">▼ '+str(returns2)+" %</p>", unsafe_allow_html=True)
310
+ last_price3 = data_index.iloc[-1]["Close"]
311
+ first_price3 = data_index.iloc[0]["Close"]
312
+ returns3 = round((last_price3/first_price3-1)*100, 2)
313
+ cols[4].markdown('<h4 style="font-size:12px; padding-left:15px; margin-bottom:0px;">'+"Precio"+"</h4>", unsafe_allow_html=True)
314
+ cols[4].markdown('<p style="font-size:25px; padding-left:30px;">$'+"{:,}".format(last_price3)+"</p>", unsafe_allow_html=True)
315
+ if returns3 > 0:
316
+ cols[5].markdown('<p style="font-size:20px; padding-top:22px; color:green;">▲ '+str(returns3)+" %</p>", unsafe_allow_html=True)
317
+ else:
318
+ cols[5].markdown('<p style="font-size:20px; padding-top:22px; color:red;">▼ '+str(returns3)+" %</p>", unsafe_allow_html=True)
319
+ col1, col2, col3 = st.beta_columns(3)
320
+ col1.table(tabla_bonos(bonds10y, TODAY))
321
+ col2.table(tabla_commodity(commodity, TODAY))
322
+ col3.table(tabla_indices(index, countries, TODAY))
323
+
324
+ col1, col2, col3 = st.beta_columns(3)
325
+ col2.markdown(get_table_excel_link(data_com, selected_com),
326
+ unsafe_allow_html=True)
327
+ col3.markdown(get_table_excel_link(data_index, selected_index),
328
+ unsafe_allow_html=True)
329
+ col1.markdown(get_table_excel_link(data_bonds, selected_bonds),
330
+ unsafe_allow_html=True)
331
+ get_table_excel_link
apps/Mom_industrias.py CHANGED
@@ -1,3 +1,702 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c0043bb6c64abb60fb7db97c8943f1d27bd9a60bd3acdf824dde73a537c299ba
3
- size 32581
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import os
3
+ from plotly.subplots import make_subplots
4
+ import plotly.graph_objects as go
5
+ from datetime import datetime, timedelta, date
6
+ import streamlit as st
7
+ import sys
8
+ from math import ceil
9
+ from modules import tables
10
+ import io
11
+ import boto3
12
+ from Data.credentials import credentials_s3 as creds3
13
+
14
+
15
+
16
+
17
+
18
+ def save_s3(key, secret_key, bucket, df, path):
19
+ with io.BytesIO() as output:
20
+ with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
21
+ df.to_excel(writer, 'sheet_name')
22
+ data = output.getvalue()
23
+ s3 = boto3.resource('s3', aws_access_key_id=key,
24
+ aws_secret_access_key=secret_key)
25
+ s3.Bucket(bucket).put_object(Key=path, Body=data)
26
+
27
+
28
+ @st.experimental_memo
29
+ def read_excel_s3(key, secret_key, bucket, path):
30
+ s3_client = boto3.client('s3', aws_access_key_id=key,
31
+ aws_secret_access_key=secret_key)
32
+ response = s3_client.get_object(Bucket=bucket, Key=path)
33
+ data = response["Body"].read()
34
+ df = pd.read_excel(io.BytesIO(
35
+ data), sheet_name='sheet_name', index_col='date')
36
+ return df
37
+
38
+
39
+ def sectors_lv1_dicc():
40
+ sectors_dicc = {}
41
+ company_db = pd.read_excel(
42
+ 'Data/Company_Base_Definitivo.xlsx', sheet_name='Compilado')
43
+ sectors = list(company_db['LV1'].unique())
44
+ for sector in sectors:
45
+ sectors_dicc[sector] = list(set(list(company_db[company_db['LV1'] == sector]['Country'].unique()))
46
+ .intersection(['Argentina', 'Brazil', 'Chile', 'Colombia', 'Mexico', 'Peru']))
47
+ return sectors_dicc
48
+
49
+
50
+ def colores_corporativos(colors=None):
51
+
52
+ color_dict = {'green': (55, 95, 77),
53
+ 'light_blue': (110, 162, 201),
54
+ 'light_gray': (135, 146, 158),
55
+ 'dark_purple': (119, 28, 95),
56
+ 'red': (204, 0, 51),
57
+ 'blue': (42, 83, 113),
58
+ 'purple': (159, 37, 127),
59
+ 'light_green': (122, 178, 153),
60
+ 'gray': (66, 74, 82),
61
+ 'yellow': (195, 195, 9),}
62
+
63
+ for key in color_dict:
64
+ color_dict[key] = tuple(v/255 for v in color_dict[key])
65
+
66
+ if colors is None:
67
+ return color_dict
68
+ else:
69
+ aux = {col: color_dict[col] for col in colors}
70
+ return aux
71
+
72
+
73
+ def update_data(start=str(date.today()-timedelta(int(1.5*365))), today=str(date.today())):
74
+ fields = ['IQ_CLOSEPRICE_ADJ', 'IQ_MARKETCAP', 'IQ_VALUE_TRADED']
75
+ key = creds3["S3_KEY_ID"]
76
+ secret_key = creds3["S3_SECRET_KEY"]
77
+ bucket = creds3["S3_BUCKET"]
78
+ path = 'Momentum.xlsx'
79
+ for f in fields:
80
+ # Cargamos de Mongo data de empresas
81
+ save_s3(key=key, secret_key=secret_key, bucket=bucket,
82
+ df=tables.EquityMaster(field=f).query(
83
+ start=start, end=today, rename=['asset']),
84
+ path=f + '.xlsx')
85
+ ud = pd.read_excel('Data/update_data.xlsx')
86
+ ud = ud[ud['View'] != 'Mom Industrias']
87
+ today = date.today().strftime('%d-%m-%Y')
88
+ ud = ud.append({"View": 'Mom Industrias',
89
+ "Last_Update": today}, ignore_index=True)
90
+ ud.to_excel('Data/update_data.xlsx', index=False)
91
+
92
+ @st.cache(suppress_st_warning=True)
93
+ def data_request(today, start, countries, criteria='LV1'):
94
+ """
95
+ Hace las consultas básicas necesarias para poder visaulizar StN.
96
+ :param today: fecha de hoy. Este parámetro está sólo para poder usar st.cache.
97
+ :param start: desde cuándo se está haciendo la consulta.
98
+ :param countries: países que solicita el usuario
99
+ :param criteria: Criterio a usar en country_sector.
100
+ :return: data_dict, company_db, country_sector)
101
+ """""
102
+ key = creds3["S3_KEY_ID"]
103
+ secret_key = creds3["S3_SECRET_KEY"]
104
+ bucket = creds3["S3_BUCKET"]
105
+ path = 'Momentum.xlsx'
106
+ # Cargamos mapeos
107
+ file = 'Data/Company_Base_Definitivo.xlsx'
108
+ company_db = pd.read_excel(file, sheet_name='Compilado', index_col='ID_Quant',
109
+ engine='openpyxl')
110
+ # Pequeño arreglo de meli y globant
111
+ company_db.loc[[7, 72], 'Country'] = 'Brazil'
112
+
113
+ data_dict = {}
114
+
115
+ paths = ['IQ_CLOSEPRICE_ADJ.xlsx',
116
+ 'IQ_MARKETCAP.xlsx', 'IQ_VALUE_TRADED.xlsx']
117
+ for p in paths:
118
+ data_dict[p[:-5]] = read_excel_s3(key=key,
119
+ secret_key=secret_key, bucket=bucket, path=p)
120
+
121
+ # Vemos solo las parejas de pais-sector que existen para ahorrar parejas
122
+ country_sector = (company_db[['Country', criteria]].drop_duplicates().
123
+ sort_values(['Country', criteria]))
124
+
125
+ country_sector = country_sector.loc[country_sector['Country'].isin(
126
+ countries)]
127
+ return data_dict, company_db, country_sector
128
+
129
+
130
+ def mm_eval(series):
131
+ return int(series.iloc[-1] > series.mean())
132
+
133
+
134
+ @st.cache(suppress_st_warning=True)
135
+ def country_request(country, start, end):
136
+ return tables.MacroMaster(country=country, instrument='INDEX').query(start=start, end=end)
137
+
138
+
139
+ @st.cache(suppress_st_warning=True)
140
+ def univ_request(company_db, c):
141
+ return company_db.query(f"Country == '{c}'").index.astype(str)
142
+
143
+
144
+ @st.cache(suppress_st_warning=True)
145
+ def mm_sum(prices_c, p_list):
146
+ return sum([prices_c.rolling(p * 20).apply(mm_eval) for p in p_list])
147
+
148
+
149
+ @st.experimental_memo
150
+ def dictionaries_maker(start, countries, country_sector, criteria, company_db, data_dict):
151
+ rel_rets = {}
152
+ cs_ids = {}
153
+ w_hist = {}
154
+ bm_dict = {c: country_request(c, start, str(date.today()))
155
+ for c in countries}
156
+
157
+ for c in countries:
158
+ bm_rets = tables.MacroMaster(
159
+ country=c, instrument='INDEX').query(start=start)
160
+ rel_ret_c = {}
161
+ for s in country_sector.loc[country_sector['Country'] == c, criteria]:
162
+ univ = (company_db.query(f"Country == '{c}' and {criteria} == '{s}'")
163
+ .index.astype(str))
164
+ univ = list(set(univ & data_dict['IQ_MARKETCAP'].columns
165
+ & data_dict['IQ_CLOSEPRICE_ADJ'].columns))
166
+ w = data_dict['IQ_MARKETCAP'][univ].ffill().fillna(0)
167
+ w = w.div(w.sum(1), axis=0)
168
+ w_hist[f'{c}-{s}'] = w
169
+ p_ind = data_dict['IQ_CLOSEPRICE_ADJ'][univ].ffill()
170
+ ret_ind = (w * p_ind.pct_change()).fillna(0).sum(1)
171
+ rel_ret_c[s] = ret_ind - bm_rets
172
+ cs_ids[f'{c}-{s}'] = univ
173
+
174
+ rel_rets[c] = pd.DataFrame(rel_ret_c)
175
+
176
+ return rel_rets, cs_ids, w_hist, bm_dict
177
+
178
+
179
+ def signal_to_noise():
180
+ """
181
+ Despliega un formulario de streamlit y grafica lo indicado por el usuario.
182
+ :return: None
183
+ """
184
+ form_stn = st.form("StN")
185
+ stn_view = form_stn.selectbox('¿Cómo desea visualizar StN?:',
186
+ ('Nivel o Cambios por País',
187
+ 'Grafico Agregado de StN'))
188
+
189
+ if stn_view == 'Nivel o Cambios por País':
190
+ n = form_stn.slider('Inserte para cuántas semanas desea visualizar cambios (Con 0 se muestra el nivel StN).',
191
+ min_value=0, max_value=12)
192
+ else:
193
+ n = 0
194
+
195
+ # Países a visualizar
196
+ countries = form_stn.multiselect('País : ',
197
+ ('Todos', 'Argentina', 'Brazil',
198
+ 'Chile', 'Colombia', 'Mexico', 'Peru'))
199
+ if 'Todos' in countries:
200
+ countries = ['Argentina', 'Brazil',
201
+ 'Chile', 'Colombia', 'Mexico', 'Peru']
202
+
203
+ countries_q = len(countries)
204
+
205
+ update_button = form_stn.form_submit_button("Actualizar datos")
206
+ if update_button:
207
+ update_data()
208
+
209
+ accept = form_stn.form_submit_button('Visualizar')
210
+
211
+ start = '2017'
212
+ criteria = 'LV1'
213
+
214
+ st.write("### Está visualizando: StN")
215
+
216
+ colors = list(colores_corporativos().values())
217
+ colors2 = []
218
+ for i in range(len(colors)):
219
+ colors2.append("rgb" + str(colors[i]))
220
+
221
+ if accept:
222
+
223
+ today = str(date.today())
224
+ # Acá cargamos los datos necesarios
225
+ data = data_request(today, start, countries)
226
+ data_dict = data[0]
227
+ company_db = data[1]
228
+ country_sector = data[2]
229
+ st.write('Data desde ' + start + ' hasta ' +
230
+ str(data_dict['IQ_CLOSEPRICE_ADJ'].index[-1].date()))
231
+
232
+ rel_rets, cs_ids, w_hist, bm_dict = dictionaries_maker(start,
233
+ countries,
234
+ country_sector,
235
+ criteria,
236
+ company_db,
237
+ data_dict)
238
+
239
+ stn_p = 20 * 5
240
+ signal_to_noise_dict = {c: df.rolling(stn_p).sum() / df.abs().rolling(stn_p).sum().abs()
241
+ for c, df in rel_rets.items()}
242
+ if stn_view == 'Nivel o Cambios por País':
243
+ index = list(range(len(colors2)))
244
+ colors2 = dict(zip(index, colors2))
245
+ if n == 0:
246
+ st.write('### Nivel de StN')
247
+ fig = make_subplots(rows=1, cols=1, subplot_titles=countries)
248
+ if countries_q == 1:
249
+ for i, (c, df) in enumerate(signal_to_noise_dict.items()):
250
+ fig.add_trace(go.Bar(x=df.iloc[-1].sort_values().array, y=df.iloc[-1].sort_values().index,
251
+ orientation='h', showlegend=False,
252
+ marker_color=colors2[3]))
253
+ fig.update_yaxes(visible=True, showticklabels=True)
254
+ fig.update_xaxes(visible=False, showticklabels=False)
255
+ fig.update_layout(height=800)
256
+ with st.container():
257
+ st.plotly_chart(fig, use_container_width=True)
258
+ else:
259
+ col1, col2 = st.columns(2)
260
+ titles_1 = []
261
+ titles_2 = []
262
+ for k in range(countries_q):
263
+ if k % 2 == 0:
264
+ titles_1.append(countries[k])
265
+ else:
266
+ titles_2.append(countries[k])
267
+
268
+ fig1 = make_subplots(rows=1 + (countries_q > 2) + (countries_q > 4), cols=1,
269
+ subplot_titles=titles_1)
270
+ fig2 = make_subplots(rows=1 + (countries_q > 2) + (countries_q > 4), cols=1,
271
+ subplot_titles=titles_2)
272
+
273
+ for i, (c, df) in enumerate(signal_to_noise_dict.items()):
274
+ if i % 2 == 0:
275
+ fig1.add_trace(go.Bar(x=df.iloc[-1].sort_values().array, y=df.iloc[-1].sort_values().index,
276
+ orientation='h', showlegend=False,
277
+ marker_color=colors2[3]),
278
+ row=(i == 0) + 2 *
279
+ (i == 2) + 3 * (i == 4),
280
+ col=1)
281
+ else:
282
+ fig2.add_trace(go.Bar(x=df.iloc[-1].sort_values().array, y=df.iloc[-1].sort_values().index,
283
+ orientation='h', showlegend=False,
284
+ marker_color=colors2[3]),
285
+ row=(i == 1) + 2 *
286
+ (i == 3) + 3 * (i == 5),
287
+ col=1)
288
+
289
+ fig1.update_yaxes(visible=True, showticklabels=True)
290
+ fig2.update_yaxes(visible=True, showticklabels=True)
291
+ fig1.update_xaxes(visible=False, showticklabels=False)
292
+ fig2.update_xaxes(visible=False, showticklabels=False)
293
+ fig1.update_layout(height=800)
294
+ fig2.update_layout(height=800)
295
+ col1.plotly_chart(fig1, use_container_width=True)
296
+ col2.plotly_chart(fig2, use_container_width=True)
297
+ else:
298
+ fig = make_subplots(rows=1, cols=1, subplot_titles=countries)
299
+ if countries_q == 1:
300
+ for i, (c, df) in enumerate(signal_to_noise_dict.items()):
301
+ fig.add_trace(go.Bar(x=df.iloc[-1].sort_values().array, y=df.iloc[-1].sort_values().index,
302
+ orientation='h', showlegend=False,
303
+ marker_color=colors2[3]))
304
+ fig.update_yaxes(visible=True, showticklabels=True)
305
+ fig.update_xaxes(visible=False, showticklabels=False)
306
+ fig.update_layout(height=800)
307
+ with st.container():
308
+ st.plotly_chart(fig, use_container_width=True)
309
+ else:
310
+ st.write('### Cambios en ' + str(n) + ' Semanas')
311
+
312
+ if countries_q == 1:
313
+ fig = make_subplots(
314
+ rows=1, cols=1, subplot_titles=countries)
315
+ for i, (c, df) in enumerate(signal_to_noise_dict.items()):
316
+ fig.add_trace(go.Bar(x=df.diff(5 * n).iloc[-1].sort_values().array,
317
+ y=df.diff(
318
+ 5 * n).iloc[-1].sort_values().index,
319
+ orientation='h', showlegend=False,
320
+ marker_color=colors2[3]))
321
+ fig.update_yaxes(visible=True, showticklabels=True)
322
+ fig.update_xaxes(
323
+ visible=False, showticklabels=False)
324
+ fig.update_layout(height=800)
325
+ with st.container():
326
+ st.plotly_chart(fig, use_container_width=True)
327
+ else:
328
+ col1, col2 = st.columns(2)
329
+ titles_1 = []
330
+ titles_2 = []
331
+ for k in range(countries_q):
332
+ if k % 2 == 0:
333
+ titles_1.append(countries[k])
334
+ else:
335
+ titles_2.append(countries[k])
336
+
337
+ fig1 = make_subplots(rows=1 + (countries_q > 2) + (countries_q > 4),
338
+ cols=1, subplot_titles=titles_1)
339
+ fig2 = make_subplots(rows=1 + (countries_q > 2) + (countries_q > 4),
340
+ cols=1, subplot_titles=titles_2)
341
+ for i, (c, df) in enumerate(signal_to_noise_dict.items()):
342
+ if i % 2 == 0:
343
+ fig1.add_trace(go.Bar(x=df.diff(5 * n).iloc[-1].sort_values().array,
344
+ y=df.diff(
345
+ 5 * n).iloc[-1].sort_values().index,
346
+ orientation='h', showlegend=False,
347
+ marker_color=colors2[3]),
348
+ row=(i == 0) + 2 * (i == 2) + 3 * (i == 4), col=1)
349
+ else:
350
+ fig2.add_trace(go.Bar(x=df.diff(5 * n).iloc[-1].sort_values().array,
351
+ y=df.diff(
352
+ 5 * n).iloc[-1].sort_values().index,
353
+ orientation='h', showlegend=False,
354
+ marker_color=colors2[3]),
355
+ row=(i == 1) + 2 * (i == 3) + 3 * (i == 5), col=1)
356
+ fig1.update_yaxes(visible=True, showticklabels=True)
357
+ fig2.update_yaxes(visible=True, showticklabels=True)
358
+ fig1.update_xaxes(visible=False, showticklabels=False)
359
+ fig2.update_xaxes(visible=False, showticklabels=False)
360
+ fig1.update_layout(height=1000, margin_b=20,
361
+ margin_r=20, margin_l=20)
362
+ fig2.update_layout(height=1000, margin_b=20,
363
+ margin_r=20, margin_l=20)
364
+ col1.plotly_chart(fig1, use_container_width=True)
365
+ col2.plotly_chart(fig2, use_container_width=True)
366
+
367
+ if stn_view == 'Grafico Agregado de StN':
368
+ mc_th = 5000
369
+ aux_stn = pd.concat([df.rename(columns={s: f'{c}-{s}' for s in df.columns})
370
+ for c, df in signal_to_noise_dict.items() if c in countries], axis=1)
371
+ mc_per_ind = pd.Series([data_dict['IQ_MARKETCAP'][cs_ids[cs]].rolling(60, 10).mean().iloc[-1].sum()
372
+ for cs in aux_stn.columns], index=aux_stn.columns)
373
+
374
+ st.markdown('### StN General ')
375
+ col1, col2, col3 = st.columns(3)
376
+ aux_stn = aux_stn.loc[:, (mc_per_ind > mc_th).values]
377
+
378
+ # Ahora creamos los dataframes para cada margen de tiempo
379
+ stn_general = aux_stn.iloc[-1].sort_values() # General
380
+ stn_1week = aux_stn.diff(5).iloc[-1].sort_values() # 1 Week Chg
381
+ stn_1month = aux_stn.diff(20).iloc[-1].sort_values() # 1 Month Chg
382
+
383
+ # Procedemos a graficar
384
+ fig1 = make_subplots(subplot_titles=['General'])
385
+ fig2 = make_subplots(subplot_titles=['1W Chg'])
386
+ fig3 = make_subplots(subplot_titles=['1M Chg'])
387
+ fig1.add_trace(
388
+ go.Bar(x=stn_general.array, y=stn_general.index,
389
+ orientation='h', showlegend=False,
390
+ marker_color=colors2[3]))
391
+ fig2.add_trace(
392
+ go.Bar(x=stn_1week.array, y=stn_1week.index, orientation='h',
393
+ showlegend=False,
394
+ marker_color=colors2[3]))
395
+ fig3.add_trace(
396
+ go.Bar(x=stn_1month.array, y=stn_1month.index, orientation='h',
397
+ showlegend=False,
398
+ marker_color=colors2[3]))
399
+ fig1.update_xaxes(visible=False, showticklabels=False)
400
+ fig2.update_xaxes(visible=False, showticklabels=False)
401
+ fig3.update_xaxes(visible=False, showticklabels=False)
402
+
403
+ col1.plotly_chart(fig1, use_container_width=True)
404
+ col2.plotly_chart(fig2, use_container_width=True)
405
+ col3.plotly_chart(fig3, use_container_width=True)
406
+
407
+
408
+ def medias_moviles():
409
+ """
410
+ Despliega un formulario de streamlit y grafica lo indicado por el usuario.
411
+ :return: None
412
+ """
413
+ sectors_dict = sectors_lv1_dicc()
414
+ select_sector = st.selectbox(
415
+ 'Qué sector desea visualizar?', list(sectors_dict.keys()))
416
+ form_mm = st.form("MM")
417
+ start = form_mm.date_input(
418
+ '¿Desde qué fecha desea visualizar?', value=date.today() - timedelta(365))
419
+ start = datetime.combine(start, datetime.min.time())
420
+ countries = form_mm.multiselect('¿Qué país(es) desea visualizar?', [
421
+ 'Todos'] + sectors_dict[select_sector])
422
+ if 'Todos' in countries:
423
+ countries = sectors_dict[select_sector]
424
+
425
+ update_button = form_mm.form_submit_button("Actualizar datos")
426
+ if update_button:
427
+ update_data()
428
+
429
+ accept = form_mm.form_submit_button('Visualizar')
430
+
431
+ criteria = 'LV1'
432
+
433
+ st.write("### Está visualizando: Medias Moviles")
434
+
435
+ colors = list(colores_corporativos().values())
436
+ colors2 = []
437
+ for i in range(len(colors)):
438
+ colors2.append("rgb" + str(colors[i]))
439
+
440
+ if accept:
441
+
442
+ if not countries:
443
+ countries = sectors_dict[select_sector]
444
+
445
+ today = str(date.today())
446
+ # Acá cargamos los datos necesarios
447
+ data = data_request(today, start, countries)
448
+ data_dict = data[0]
449
+ company_db = data[1]
450
+ country_sector = data[2]
451
+
452
+ st.write('Data desde ' + str(start.date()) + ' hasta ' +
453
+ str(data_dict['IQ_CLOSEPRICE_ADJ'].index[-1].date()))
454
+
455
+ rel_rets, cs_ids, w_hist, bm_dict = dictionaries_maker(start,
456
+ countries,
457
+ country_sector,
458
+ criteria,
459
+ company_db,
460
+ data_dict)
461
+ stn_p = 20 * 5
462
+ signal_to_noise_dict = {
463
+ c: df.rolling(stn_p).sum() / df.abs().rolling(stn_p).sum().abs()
464
+ for c, df in rel_rets.items()}
465
+ st.write('Sector: ' + select_sector)
466
+ ma_p = [20, 60, 250]
467
+ aux_stn = pd.concat(
468
+ [df.rename(columns={s: f'{c}-{s}' for s in df.columns})
469
+ for c, df in signal_to_noise_dict.items() if c in countries],
470
+ axis=1)
471
+ aux_rr = pd.concat(
472
+ [df.rename(columns={s: f'{c}-{s}' for s in df.columns})
473
+ for c, df in rel_rets.items() if c in countries], axis=1)
474
+ aux_rr = aux_rr[aux_stn.columns]
475
+ if len(countries) > 1:
476
+ col1, col2 = st.columns(2)
477
+ titles_1 = []
478
+ titles_2 = []
479
+ dicc_tit_1 = {}
480
+ dicc_tit_2 = {}
481
+ for i, country in enumerate(countries):
482
+ if i % 2 == 0:
483
+ title_1=str(country) + ' - ' + str(select_sector)
484
+ titles_1.append(title_1)
485
+ dicc_tit_1[title_1] = make_subplots()
486
+ else:
487
+ title_2=str(country) + ' - ' + str(select_sector)
488
+ titles_2.append(title_2)
489
+ dicc_tit_2[title_2] = make_subplots()
490
+ countries_q = len(countries)
491
+ indices = list(range(ceil(countries_q / 2)))
492
+ m = 0
493
+ for i, c in enumerate(countries):
494
+ df = (aux_rr[c + '-' + select_sector] + 1).cumprod() - 1
495
+ df_mm = pd.DataFrame(
496
+ {p: df.rolling(p, min_periods=1).mean() for p in ma_p})
497
+ df = df.to_frame()
498
+ df[[f'MA_{p}' for p in ma_p]] = df_mm
499
+ df = df.loc[df.index >= start]
500
+ df.rename(
501
+ columns={c + '-' + select_sector: 'Indice'}, inplace=True)
502
+ df = df - df['Indice'][0]
503
+ if i % 2 == 0:
504
+ list_plot_1 =list(dicc_tit_1.keys())
505
+ for k in range(len(ma_p)):
506
+ if k == 0:
507
+ dicc_tit_1[list_plot_1[i//2 + i % 2]].add_trace(
508
+ go.Scatter(x=df.index, y=df['Indice'],
509
+ line=dict(
510
+ color=colors2[len(ma_p) + 1]),
511
+ name='Indice'),
512
+ row=indices[m] + 1, col=1)
513
+ dicc_tit_1[list_plot_1[i//2 + i % 2]].add_trace(
514
+ go.Scatter(x=df.index,
515
+ y=df['MA_' + str(ma_p[k])],
516
+ line=dict(color=colors2[k]),
517
+ name='MA_' + str(ma_p[k])),
518
+ row=indices[m] + 1, col=1)
519
+ dicc_tit_1[list_plot_1[i//2 + i % 2]].update_layout(
520
+ height=350, width=400)
521
+ dicc_tit_1[list_plot_1[i//2 + i % 2]].layout.update(
522
+ title_text=list_plot_1[i//2 + i % 2],
523
+ xaxis_rangeslider_visible=False, margin_b=20,
524
+ margin_r=20, margin_l=20,
525
+ legend=dict(orientation="h",
526
+ yanchor="bottom",
527
+ y=1.0,
528
+ xanchor="right",
529
+ x=1))
530
+ col1.plotly_chart(dicc_tit_1[list_plot_1[i//2 + i % 2]],
531
+ use_container_width=True)
532
+ else:
533
+ list_plot_2 = list(dicc_tit_2.keys())
534
+ for k in range(len(ma_p)):
535
+ if k == 0:
536
+ dicc_tit_2[list_plot_2[i//2]].add_trace(
537
+ go.Scatter(x=df.index, y=df['Indice'],
538
+ line=dict(
539
+ color=colors2[len(ma_p) + 1]),
540
+ name='Indice'),
541
+ row=indices[m] + 1, col=1)
542
+ dicc_tit_2[list_plot_2[i//2]].add_trace(
543
+ go.Scatter(x=df.index,
544
+ y=df['MA_' + str(ma_p[k])],
545
+ line=dict(color=colors2[k]),
546
+ name='MA_' + str(ma_p[k])),
547
+ row=indices[m] + 1, col=1)
548
+ dicc_tit_2[list_plot_2[i//2]].update_layout(
549
+ height=350, width=400)
550
+
551
+ dicc_tit_2[list_plot_2[i//2]].layout.update(
552
+ title_text=list_plot_2[i//2],
553
+ xaxis_rangeslider_visible=False, margin_b=20,
554
+ margin_r=20, margin_l=20,
555
+ legend=dict(orientation="h",
556
+ yanchor="bottom",
557
+ y=1.0,
558
+ xanchor="right",
559
+ x=1))
560
+ col2.plotly_chart(dicc_tit_2[list_plot_2[i//2]],
561
+ use_container_width=True)
562
+ else:
563
+ country = countries[0]
564
+ titles = [str(country) + ' - ' + str(select_sector)]
565
+ fig1 = make_subplots(rows=len(titles), cols=1,
566
+ subplot_titles=titles)
567
+ df = (aux_rr[country + '-' + select_sector] + 1).cumprod() - 1
568
+ df_mm = pd.DataFrame(
569
+ {p: df.rolling(p, min_periods=1).mean() for p in ma_p})
570
+ df = df.to_frame()
571
+ df[[f'MA_{p}' for p in ma_p]] = df_mm
572
+ df = df.loc[df.index >= start]
573
+ df.rename(columns={country + '-' +
574
+ select_sector: 'Indice'}, inplace=True)
575
+ df = df - df['Indice'][0]
576
+ for k in range(len(ma_p)):
577
+ fig1.add_trace(go.Scatter(x=df.index,
578
+ y=df['MA_' + str(ma_p[k])],
579
+ line=dict(color=colors2[k]),
580
+ name='MA_' + str(ma_p[k]),
581
+ showlegend=True), row=1, col=1)
582
+ fig1.add_trace(go.Scatter(x=df.index, y=df['Indice'],
583
+ line=dict(color=colors2[len(ma_p) + 1]),
584
+ name='Indice',
585
+ showlegend=True),
586
+ row=1, col=1)
587
+
588
+ fig1.update_layout(height=200, width=400, margin_b=0, margin_t=0,
589
+ margin_r=0, margin_l=0)
590
+ st.plotly_chart(fig1, use_container_width=True)
591
+
592
+
593
+ def difusion():
594
+ """
595
+ Despliega un formulario de streamlit y grafica lo indicado por el usuario.
596
+ :return: None
597
+ """
598
+ start = '2017'
599
+
600
+ form_dif = st.form("Difusión")
601
+ countries = form_dif.multiselect('¿Qué países quiere visualizar?',
602
+ ('Todos', 'Argentina', 'Brazil',
603
+ 'Chile', 'Colombia', 'Mexico', 'Peru'))
604
+ if 'Todos' in countries:
605
+ countries = ['Argentina', 'Brazil',
606
+ 'Chile', 'Colombia', 'Mexico', 'Peru']
607
+
608
+ update_button = form_dif.form_submit_button("Actualizar datos")
609
+ if update_button:
610
+ update_data()
611
+
612
+ accept = form_dif.form_submit_button('Visualizar')
613
+
614
+ criteria = 'LV1'
615
+
616
+ st.write("### Está visualizando: Difusión")
617
+
618
+ colores = list(colores_corporativos().values())
619
+ colores2 = []
620
+
621
+ for i in range(len(colores)):
622
+ colores2.append("rgb" + str(colores[i]))
623
+
624
+ if accept:
625
+
626
+ today = str(date.today())
627
+ # Acá cargamos los datos necesarios
628
+ data = data_request(today, start, countries)
629
+ data_dict = data[0]
630
+ company_db = data[1]
631
+ country_sector = data[2]
632
+ st.write('Data desde ' + str(date.today() - timedelta(365)) + ' hasta ' + str(
633
+ data_dict['IQ_CLOSEPRICE_ADJ'].index[-1].date()))
634
+
635
+ rel_rets, cs_ids, w_hist, bm_dict = dictionaries_maker(start,
636
+ countries,
637
+ country_sector,
638
+ criteria,
639
+ company_db,
640
+ data_dict)
641
+
642
+ p_list = [1, 3, 12]
643
+ prices = data_dict['IQ_CLOSEPRICE_ADJ'].ffill()
644
+
645
+ mm_countries = countries
646
+ start = datetime.today() - timedelta(365)
647
+
648
+ fig_mm = make_subplots(specs=[[{"secondary_y":
649
+ True}]]*len(mm_countries),
650
+ subplot_titles=mm_countries,
651
+ rows=len(mm_countries), cols=1)
652
+ for i, c in enumerate(mm_countries):
653
+ univ = univ_request(company_db, c)
654
+ univ = list(set(univ) & set(prices.columns))
655
+ prices_c = prices[univ].iloc[-500:]
656
+ mm_sum_df = sum([prices_c.rolling(p * 20).apply(mm_eval)
657
+ for p in p_list])
658
+ mm_sum_df = mm_sum_df.iloc[-252:].dropna(how='all')
659
+
660
+ bull = (mm_sum_df == len(p_list)).sum(1) / mm_sum_df.notna().sum(1)
661
+ bear = (mm_sum_df == 0).sum(1) / mm_sum_df.notna().sum(1)
662
+ delta = (bull - bear).to_frame()
663
+ delta.columns = [f'Bull-Bear {c}']
664
+ bm_rets = bm_dict[c]
665
+ delta['aux'] = bm_rets
666
+ delta[f'{c} Index'] = (1 + delta['aux']).cumprod()
667
+
668
+ bull = bull.reindex(pd.to_datetime(bull.index))
669
+ bear = bear.reindex(pd.to_datetime(bear.index))
670
+ delta = delta.reindex(pd.to_datetime(delta.index))
671
+
672
+ bull = bull.loc[bull.index >= start]
673
+ bear = bear.loc[bear.index >= start]
674
+ delta = delta.loc[delta.index >= start]
675
+
676
+ # Bull
677
+ fig_mm.add_trace(go.Scatter(x=bull.index, y=bull.array,
678
+ name='Bull',
679
+ line=dict(color=colores2[5]),
680
+ showlegend=(i == 0)),
681
+ secondary_y=False, row=i + 1,
682
+ col=1)
683
+ # Bear
684
+ fig_mm.add_trace(go.Scatter(x=bear.index, y=bear.array, name='Bear', line=dict(color=colores2[0]),
685
+ showlegend=(i == 0)), secondary_y=False, row=i + 1,
686
+ col=1)
687
+ # Bull-Bear
688
+ fig_mm.add_trace(
689
+ go.Scatter(x=delta.index, y=delta[f'Bull-Bear {c}'], name='Bull - Bear', line=dict(color=colores2[6]),
690
+ showlegend=(i == 0)), row=i + 1, col=1)
691
+ # Indice
692
+ fig_mm.add_trace(go.Scatter(x=delta.index, y=delta[f'{c} Index'], name='Index ', line=dict(color='black'),
693
+ showlegend=(i == 0)), secondary_y=True, row=i + 1, col=1)
694
+ fig_mm.update_yaxes(title_text="Valor",
695
+ secondary_y=False, row=i + 1, col=1)
696
+ fig_mm.update_layout(yaxis1={'tickformat': ',.0%'})
697
+ fig_mm.update_yaxes(title_text="Indice",
698
+ secondary_y=True, row=i + 1, col=1)
699
+
700
+ with st.container():
701
+ fig_mm.update_layout(height=400 * len(mm_countries))
702
+ st.plotly_chart(fig_mm, use_container_width=True)
apps/Panel_de_control.py CHANGED
@@ -1,3 +1,95 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:8932e6a2d9f3f8eafe3e73eaca828ec682acf56b40ed2c6e3af3c66829fb8d99
3
- size 2832
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Tue Jan 4 18:23:14 2022
4
+
5
+ @author: bullm
6
+ """
7
+ import plotly.graph_objects as go
8
+ import plotly.express as px
9
+ import pandas as pd
10
+ import streamlit as st
11
+ import numpy as np
12
+ import matplotlib.pyplot as plt
13
+
14
+ # path = 'C:\\Users\\bullm\\Desktop\\Portal_LVAM\\Data\\'
15
+ # for key in stats_competencia.keys():
16
+ # print(key)
17
+ # stats_competencia[key].to_excel(path+key+'.xlsx')
18
+ # tabla_factores_general.to_excel(path+'factores_general.xlsx')
19
+
20
+ def spider_plot(df, title, alpha=0.1, n_dec=1, y=[]):
21
+
22
+ if len(y) == 0:
23
+ min_val = df.min().min()
24
+ min_val = np.floor(min_val-np.abs(min_val)*alpha, n_dec)
25
+ max_val = df.max().max()
26
+ max_val = np.ceil(max_val+np.abs(max_val)*alpha, n_dec)
27
+ mean_val = np.round((min_val + max_val)/2, 1)
28
+
29
+ y = [min_val, mean_val, max_val]
30
+
31
+ categories = list(df.index)
32
+ N = df.shape[0]
33
+
34
+ # We are going to plot the first line of the data frame.
35
+ # But we need to repeat the first value to close the circular graph:
36
+ values = np.round(df.iloc[:, 0].values.flatten().tolist(), 2)
37
+ values = np.hstack((values, values[0])).T
38
+
39
+ values2 = np.round(df.iloc[:, 1].values.flatten().tolist(), 2)
40
+ values2 = np.hstack((values2, values2[0])).T
41
+
42
+ # What will be the angle of each axis in the plot?
43
+ angles = [n / float(N) * 2 * np.pi for n in range(N)]
44
+ angles += angles[:1]
45
+
46
+ # Initialise the spider plot
47
+ fig = plt.figure(figsize=(10, 15))
48
+ ax = plt.subplot(111, polar=True)
49
+ ax.set_title(title, fontsize=20)
50
+
51
+ # Draw one axe per variable + add labels labels yet
52
+ plt.xticks(angles[:-1], categories, color="black", size=18)
53
+
54
+ # Draw ylabels
55
+ ax.set_rlabel_position(0)
56
+ plt.yticks(y, [str(i) for i in y], color="black", size=15)
57
+ plt.ylim(y[0], y[-1])
58
+
59
+
60
+
61
+ # Plot data
62
+ ax.plot(angles, values, linewidth=1, linestyle='solid', c='dimgrey')
63
+ ax.plot(angles, values2, linewidth=1, linestyle='solid', c='darkred')
64
+
65
+ handles, labels = ax.get_legend_handles_labels()
66
+
67
+ ax.legend(labels=['Cartera', 'Benchmark'], loc='lower left',
68
+ fontsize=15, bbox_to_anchor=(-0.1, -0.1))
69
+
70
+ # Fill area
71
+ ax.fill(angles, values, 'b', alpha=0.1)
72
+
73
+ return fig
74
+
75
+
76
+ def panel_de_control():
77
+ df = pd.read_excel("Data/factores_general.xlsx")
78
+
79
+ radar = go.Scatterpolar(
80
+ r = list(df["Benchmark"]),
81
+ theta = list(df['Unnamed: 0']),
82
+ fill = 'toself'
83
+ )
84
+ radar2 = go.Scatterpolar(
85
+ r = list(df["Cartera"]),
86
+ theta = list(df['Unnamed: 0']),
87
+ fill = 'toself'
88
+ )
89
+ data = [radar, radar2]
90
+ fig = go.Figure(data = data)
91
+ col1, col2 = st.columns(2)
92
+ col1.plotly_chart(fig, use_container_width=True)
93
+ df.index= df['Unnamed: 0']
94
+ df = df[["Cartera", 'Benchmark']]
95
+ col2.pyplot(spider_plot(df, '', y=[0, 50, 100] ))
apps/Scoring.py CHANGED
@@ -1,3 +1,303 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:0b057e466c7b6de2eb0bfc84e819aa6e92c8146eec53b36c94a9a13f055efe0b
3
- size 10397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import streamlit as st
3
+ import pybase64 as base64
4
+ import io
5
+ from logs_portal import log
6
+ import os
7
+ from datetime import date
8
+ from modules import tables
9
+ import boto3
10
+ from Data.credentials import credentials_s3 as creds3
11
+ from streamlit_echarts import st_echarts
12
+ from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, DataReturnMode, JsCode
13
+ import numpy as np
14
+ from streamlit_lottie import st_lottie
15
+ import json
16
+
17
+ def generador_variable_pond(name, col_s1):
18
+ col_s1.markdown("""<p style="margin-top:35px;
19
+ font-size:20px;
20
+ text-align:center;
21
+ margin-bottom:30px;
22
+ ">{Var}</p>""".format(Var=name),
23
+ unsafe_allow_html=True)
24
+
25
+
26
+ def button_style():
27
+ style_button = """
28
+ <style>
29
+ button {
30
+ display: inline-block;
31
+ background-color: white;
32
+ border-radius: 15px;
33
+ border: 4px #cccccc;
34
+ color: #4a4a4a;
35
+ text-align: center;
36
+ font-size: 18px;
37
+ padding: 2px;
38
+ width: 200px;
39
+ transition: all 0.5s;
40
+ cursor: pointer;
41
+ margin-top: 25px;
42
+ }
43
+ button span {
44
+ cursor: pointer;
45
+ display: inline-block;
46
+ position: relative;
47
+ transition: 0.5s;
48
+ }
49
+ button span:after {
50
+ content: '\00bb';
51
+ position: absolute;
52
+ opacity: 0;
53
+ top: 0;
54
+ right: -20px;
55
+ transition: 0.5s;
56
+ }
57
+ button:hover {
58
+ background-color: #bb1114;
59
+ color:#e8e8e8;
60
+ }
61
+ button:hover span {
62
+ padding-right: 25px;
63
+ }
64
+ button:hover span:after {
65
+ opacity: 1;
66
+ right: 0;
67
+ }
68
+ </style>
69
+ """
70
+ st.markdown(style_button, unsafe_allow_html=True)
71
+
72
+
73
+
74
+
75
+ def get_table_excel_link(df, name):
76
+ towrite = io.BytesIO()
77
+ writer = pd.ExcelWriter(towrite, engine='xlsxwriter')
78
+ downloaded_file = df.to_excel(writer, encoding='utf-8', index=False,
79
+ header=True)
80
+ workbook = writer.book
81
+ worksheet = writer.sheets["Sheet1"]
82
+ #set the column width as per your requirement
83
+ worksheet.set_column('A:BZ', 18)
84
+ writer.save()
85
+ towrite.seek(0) # reset pointer
86
+ file_name = 'Scoring.xlsx'
87
+ style = 'style="color:black;text-decoration: none; font-size:18px;" '
88
+ name_mark = name
89
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
90
+ linko = f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
91
+ return linko
92
+
93
+
94
+
95
+
96
+
97
+ def read_excel_s3(key, secret_key, bucket, path):
98
+ s3_client = boto3.client('s3', aws_access_key_id = key, aws_secret_access_key= secret_key)
99
+ response = s3_client.get_object(Bucket=bucket, Key=path)
100
+ data = response["Body"].read()
101
+ df = pd.read_excel(io.BytesIO(data), engine='openpyxl')
102
+ return df
103
+
104
+
105
+ def display_table(df: pd.DataFrame, name):
106
+ # Configure AgGrid options
107
+ gb = GridOptionsBuilder.from_dataframe(df)
108
+ gb.configure_selection(selection_mode="multiple", use_checkbox=True,)
109
+ gb.configure_column(name, headerCheckboxSelection = True)
110
+ gb.configure_columns(("TICKER", "COUNTRY", "LV1"), pinned=True)
111
+ return AgGrid(
112
+ df, gridOptions=gb.build(),
113
+ update_mode=GridUpdateMode.SELECTION_CHANGED,
114
+ enable_enterprise_modules=True)
115
+
116
+ @st.experimental_memo
117
+ def read_scoring():
118
+ key = creds3["S3_KEY_ID"]
119
+ secret_key = creds3["S3_SECRET_KEY"]
120
+ bucket = creds3["S3_BUCKET"]
121
+ path ="scoring.xlsx"
122
+ scoring = read_excel_s3(key, secret_key, bucket, path)
123
+ return scoring
124
+
125
+
126
+
127
+
128
+
129
+ # @log
130
+ def general():
131
+
132
+ with open("Data/lotties/99268-laading-22.json", "r") as f:
133
+ spinner = json.load(f)
134
+ cols1, cols2= st.sidebar.columns((3,1))
135
+ place = cols2.empty()
136
+ with place:
137
+ st_lottie(spinner)
138
+ # scoring.index = scoring['Ticker']
139
+ button_style()
140
+ scoring_completo = read_scoring()
141
+ col1, col2, col3 = st.columns((4,1,1))
142
+ col1.write("Last Update: " + scoring_completo.iloc[0]["TODAY"])
143
+ col1.write("Valores en MM USD")
144
+ place1=col2.empty()
145
+ place2 =col3.empty()
146
+ scoring_completo = scoring_completo.drop(columns=["TODAY"])
147
+ scoring_completo[["Nota", 'W Latino', "W Small", 'Nota ESG']] = scoring_completo[["Nota", "W Latino", 'W Small', 'Nota ESG']].fillna(0)
148
+ scoring = scoring_completo.copy()
149
+ # convert just columns "a" and "b"
150
+ metrics = ['MOMENTUM Precio', 'MOMENTUM Fundamental',
151
+ 'VALUE','PROF', 'Distres_Prom', 'PROF', 'Delta 1M', 'QUALITY', 'Nota ESG']
152
+ metrics2 = ['Market_Cap'] + metrics
153
+
154
+ scoring[metrics2] = scoring[metrics2].round()
155
+ scoring[["W Latino", "W Small", "BM Latino", "BM Small"]] = scoring[["W Latino", "W Small", "BM Latino", "BM Small"]] * 100
156
+ scoring[["W Latino", "W Small", "BM Latino", "BM Small"]] = scoring[["W Latino", "W Small", "BM Latino", "BM Small"]].round(2).fillna(0)
157
+ metrics_aggrid = ['Ticker', 'Portfolio_Country', 'LV1', 'Market_Cap',
158
+ 'ADTV','Large/Small', 'Delta 1M','Distres_Prom', 'MOMENTUM Precio', 'MOMENTUM Fundamental',
159
+ 'VALUE','PROF', 'QUALITY', 'Score', "Nota",
160
+ 'Nota ESG', 'Stop Loss', "W Latino", "W Small", "BM Latino","BM Small"]
161
+ scoring = scoring[metrics_aggrid]
162
+ scoring[metrics_aggrid] = scoring[metrics_aggrid].replace(np.nan, -1)
163
+
164
+ metrics3 = ['TICKER', 'COUNTRY', 'LV1', 'MKT CAP', 'ADTV', 'L/S', 'Δ 1M',
165
+ 'DISTRES', 'MOM PREC',
166
+ 'MOM FUND', 'VALUE','PROF', 'QUALITY', 'SCORE',
167
+ "NOTA", 'ESG', 'STOP LOSS', "W LAT", "W SMALL", "BM LAT", "BM SMALL"]
168
+ metrics4 = [
169
+ 'MOM PREC', 'MOM FUND', 'VALUE', 'QUALITY','DISTRES', 'PROF']
170
+ scoring.columns = metrics3
171
+ button = st.button("Refresh")
172
+ r = display_table(scoring, 'TICKER')
173
+ rad = 'Home'
174
+ if button:
175
+ st.experimental_memo.clear()
176
+ st.experimental_rerun()
177
+ with place1:
178
+ link = get_table_excel_link(scoring_completo, "Scoring completo")
179
+ st.markdown(link, unsafe_allow_html=True)
180
+ with place2:
181
+ link2 = get_table_excel_link(scoring, "Scoring resumen")
182
+ st.markdown(link2, unsafe_allow_html=True)
183
+ w_lat = []
184
+ w_small = []
185
+ bm_lat = []
186
+ bm_small = []
187
+ col1, col2, col3, col4, col5 = st.columns((1,1,1,1,3))
188
+ large = col1.checkbox("LUXMEXEQ", True)
189
+ small = col2.checkbox("LUXLATSML", True)
190
+ m1la = col3.checkbox("M1LA")
191
+ msm = col4.checkbox("MSLUELAN")
192
+
193
+ if "large" not in st.session_state:
194
+ st.session_state.large=False
195
+ if "small" not in st.session_state:
196
+ st.session_state.small=False
197
+ if "bm_sm" not in st.session_state:
198
+ st.session_state.bm_sm=False
199
+ if "bm_lat" not in st.session_state:
200
+ st.session_state.bm_lat=False
201
+
202
+ if large:
203
+ st.session_state.large = True
204
+ else:
205
+ st.session_state.large = False
206
+ if small:
207
+ st.session_state.small =True
208
+ else:
209
+ st.session_state.small = False
210
+ if m1la:
211
+ st.session_state.bm_lat = True
212
+ else:
213
+ st.session_state.bm_lat = False
214
+ if msm:
215
+ st.session_state.bm_sm =True
216
+ else:
217
+ st.session_state.bm_sm = False
218
+ col1, col2, col3 = st.columns((2.5, 1, 1))
219
+ try:
220
+ series_data = []
221
+ names=[]
222
+ for metric in metrics4:
223
+ w_lat.append((scoring[metric]*scoring["W LAT"]/100).sum())
224
+ w_small.append((scoring[metric]*scoring["W SMALL"]/100).sum())
225
+ bm_lat.append((scoring[metric]*scoring["BM LAT"]/100).sum())
226
+ bm_small.append((scoring[metric]*scoring["BM SMALL"]/100).sum())
227
+ if st.session_state.large:
228
+ series_data.append({"value":w_lat,
229
+ "name": "LUXMEXEQ"})
230
+ names.append("LUXMEXEQ")
231
+ if st.session_state.small:
232
+ series_data.append({"value":w_small,
233
+ "name": "LUXLATSML"})
234
+ names.append("LUXLATSML")
235
+ if st.session_state.bm_lat:
236
+ series_data.append({"value":bm_lat,
237
+ "name": "M1LA"})
238
+ names.append("M1LA")
239
+ if st.session_state.bm_sm:
240
+ series_data.append({"value":bm_small,
241
+ "name": "MSLUELAN"})
242
+ names.append("MSLUELAN")
243
+
244
+
245
+
246
+
247
+ if len(r['selected_rows'])>0:
248
+ for emp in r['selected_rows']:
249
+ selected = emp.copy()
250
+ name = selected['TICKER']
251
+ names.append(name)
252
+ indicators = []
253
+ series_value = []
254
+ for met in metrics4:
255
+ indicators.append({'name': met, "max": 100})
256
+ series_value.append(selected[met])
257
+ series_data.append({"value": series_value,
258
+ "name": name})
259
+ with col2:
260
+ st.metric('SCORE PROMEDIO - ' + name,
261
+ int(np.array(series_value).mean()))
262
+ else:
263
+ indicators = []
264
+ for met in metrics4:
265
+ indicators.append({'name': met, "max": 100})
266
+ option = {
267
+ "title": {"text": 'Score'},
268
+ "legend": {"data": names},
269
+ "radar": {
270
+ "indicator": indicators
271
+ },
272
+ "series": [
273
+ {
274
+ "name": "",
275
+ "type": "radar",
276
+ "data": series_data,
277
+ }
278
+ ],
279
+ }
280
+ with col1:
281
+ st_echarts(option, height="400px", width="80%")
282
+ except Exception as exc:
283
+ st.write(exc)
284
+ pass
285
+
286
+ # st.image("img/Scoring.png", width="100%")
287
+ place.empty()
288
+
289
+
290
+
291
+ def diagrama():
292
+
293
+ import pandas as pd
294
+ import pandas_profiling
295
+ import streamlit as st
296
+
297
+ from streamlit_pandas_profiling import st_profile_report
298
+ st.image("img/Scoring.png")
299
+ df = read_scoring()
300
+ df=df[['MOMENTUM Precio','MOMENTUM Fundamental', 'VALUE','QUALITY', 'PROF','Distres_Prom','Score' ]]
301
+ pr = df.profile_report()
302
+
303
+ st_profile_report(pr)
apps/Tasas.py CHANGED
@@ -1,3 +1,950 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:c8976b82926ce0f2bfa6c9fd0f4124038ddccbf1d97f62f99ecb2d4d40b5aa34
3
- size 39290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Tue Aug 24 09:38:58 2021
5
+
6
+ @author: benjaminull
7
+ """
8
+ import investpy
9
+ import datetime as dt
10
+ from datetime import date
11
+ import streamlit as st
12
+ from plotly import graph_objs as go
13
+ import pandas as pd
14
+ import pybase64 as base64
15
+ import io
16
+ from plotly.subplots import make_subplots
17
+ from logs_portal import log
18
+
19
+
20
+ def formatnum(numero):
21
+ return '{:,.2f}'.format(numero).replace(",", "@").replace(".", ",").replace("@", ".")
22
+
23
+
24
+ def button_style():
25
+ style_button = """
26
+ <style>
27
+ button {
28
+ display: inline-block;
29
+ background-color: #e8e8e8;
30
+ border-radius: 15px;
31
+ border: 4px #cccccc;
32
+ color: #4a4a4a;
33
+ text-align: center;
34
+ font-size: 20px;
35
+ padding: 2px;
36
+ width: 12em;
37
+ transition: all 0.5s;
38
+ cursor: pointer;
39
+ margin: 0px;
40
+ margin-top: 30px;
41
+ }
42
+ button span {
43
+ cursor: pointer;
44
+ display: inline-block;
45
+ position: relative;
46
+ transition: 0.5s;
47
+ }
48
+ button span:after {
49
+ content: '\00bb';
50
+ position: absolute;
51
+ opacity: 0;
52
+ top: 0;
53
+ right: -20px;
54
+ transition: 0.5s;
55
+ }
56
+ button:hover {
57
+ background-color: #bb1114;
58
+ color:#e8e8e8;
59
+ }
60
+ button:hover span {
61
+ padding-right: 25px;
62
+ }
63
+ button:hover span:after {
64
+ opacity: 1;
65
+ right: 0;
66
+ }
67
+ .stMarkdown{
68
+ margin-bottom:0px;}
69
+ </style>
70
+ """
71
+ st.markdown(style_button, unsafe_allow_html=True)
72
+
73
+
74
+ def get_table_excel_link(df, selected_stocks):
75
+ towrite = io.BytesIO()
76
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
77
+ header=True)
78
+ towrite.seek(0) # reset pointer
79
+ file_name = 'Data ' + selected_stocks+'.xlsx'
80
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
81
+ name_mark = "Descargar " + selected_stocks + ".xlsx"
82
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
83
+ linko= f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
84
+ return linko
85
+
86
+
87
+ def style_table():
88
+ # tr:hover {background-color: #E8E8E8;
89
+ # color:#BB1114;}
90
+ style_table = """
91
+ <style>
92
+ tbody tr:hover {
93
+ color:#BB1114;}
94
+ tr { line-height: 5px; }
95
+ thead {
96
+ background-color:#BB1114 ;
97
+ color: #E8E8E8;
98
+ }
99
+ tbody tr:nth-child(odd) {
100
+ background-color: #fff;
101
+ }
102
+ tbody tr:nth-child(even) {
103
+ background-color: #eee;
104
+ }
105
+ .css-1rcck9u{
106
+ padding:0.25rem;}
107
+ tbody tr:nth-child(odd)
108
+ stTable {
109
+ border-collapse: collapse;
110
+ background-color:red;
111
+ margin: 25px 0;
112
+ font-size: 0.9em;
113
+ min-width: 400px;
114
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
115
+ }
116
+ table{
117
+ margin-top:0px;
118
+ font-size:12px;
119
+ padding:0px;
120
+ height:200px;}
121
+
122
+ @keyframes slidein {
123
+ from {
124
+ margin-left: 100%;
125
+ width: 300%
126
+ }
127
+ to {
128
+ margin-left: 0%;
129
+ width: 100%;
130
+ }
131
+ }
132
+ </style>
133
+ """
134
+ st.markdown(style_table, unsafe_allow_html=True)
135
+
136
+
137
+ def grafico_avanzado_com(col_filter, col_button, col_chart, lista, TODAY):
138
+ titulo = "Commodities"
139
+ options = lista
140
+
141
+ fecha_0 = col_filter.selectbox("Periodo ", ["1 year", "1 week",
142
+ "1 month", "3 month",
143
+ "6 month", "5 year",
144
+ "10 year", "15 year"])
145
+ info = pd.DataFrame()
146
+ orden = ["Date"]
147
+
148
+ fecha1 = seleccionar_fecha(fecha_0)
149
+ fig2 = go.Figure()
150
+ for price in options:
151
+ data = investpy.commodities.get_commodity_historical_data(
152
+ price,
153
+ from_date=fecha1,
154
+ to_date=TODAY)
155
+ info[price] = data['Close']
156
+ close_ = go.Scatter(x=data.index,
157
+ y=data['Close']/data.iloc[0]["Close"],
158
+ name=price)
159
+ fig2.add_trace(close_)
160
+ orden.append(price)
161
+ info["Date"] = info.index
162
+ info["Date"] = info["Date"].dt.date
163
+ info = info[orden]
164
+ col_button.markdown(get_table_excel_link(info, "Commodities"),
165
+ unsafe_allow_html=True)
166
+ fig2.layout.update(title_text=titulo,
167
+ xaxis_rangeslider_visible=True,
168
+ height=500,
169
+ margin_b=20,
170
+ margin_r=20,
171
+ margin_l=20,
172
+ legend=dict(orientation="h",
173
+ yanchor="bottom",
174
+ y=1.02,
175
+ xanchor="right",
176
+ x=1))
177
+ col_chart.plotly_chart(fig2, use_container_width=True)
178
+
179
+
180
+ def grafico_avanzado_div(col_chart, col_filter, col_button, monedabase, lista, TODAY):
181
+ button_style()
182
+ titulo = "Divisas"
183
+ base = "USD"
184
+ options = lista
185
+ fecha_0 = col_filter.selectbox("Periodo", ["1 year",
186
+ "1 week",
187
+ "1 month",
188
+ "3 month",
189
+ "6 month",
190
+ "5 year",
191
+ "10 year",
192
+ "15 year"])
193
+ info = pd.DataFrame()
194
+ orden = ["Date"]
195
+ fig = make_subplots(specs=[[{"secondary_y": True}]])
196
+ fecha1 = seleccionar_fecha(fecha_0)
197
+ i = 0
198
+ for price in options:
199
+ titulo = titulo
200
+ selected_cc = base + "/" + price
201
+ data = investpy.currency_crosses.get_currency_cross_historical_data(selected_cc, from_date=fecha1, to_date=TODAY)
202
+ info[price] = data['Close']
203
+ close_ = go.Scatter(x=data.index,
204
+ y=data['Close']/data.iloc[0]['Close'],
205
+ name=price)
206
+ fig.add_trace(close_)
207
+ orden.append(price)
208
+ i = i+1
209
+ info["Date"] = info.index
210
+ info["Date"] = info["Date"].dt.date
211
+ info = info[orden]
212
+ col_button.markdown(get_table_excel_link(info, "Divisas"),
213
+ unsafe_allow_html=True)
214
+ fig.layout.update(title_text=titulo,
215
+ xaxis_rangeslider_visible=True,
216
+ height=500,
217
+ margin_b=20,
218
+ margin_r=20,
219
+ margin_l=20,
220
+ legend=dict(orientation="h",
221
+ yanchor="bottom",
222
+ y=1.02,
223
+ xanchor="right",
224
+ x=1))
225
+ col_chart.plotly_chart(fig, use_container_width=True)
226
+ import plotly.express as px
227
+
228
+ def grafico_avanzado_ind(col_chart,
229
+ col_filter,
230
+ col_button,
231
+ lista,
232
+ countries,
233
+ today, fechas):
234
+ button_style()
235
+ dict_indices = dict(zip(lista, countries))
236
+ fecha_0 = col_filter.selectbox("Periodo ", fechas)
237
+ fecha1 = seleccionar_fecha(fecha_0)
238
+ titulo = "Indices"
239
+ options = lista
240
+ info = pd.DataFrame()
241
+ orden = ["Date"]
242
+ fig2 = go.Figure()
243
+ i = 0
244
+ for price in options:
245
+
246
+ data = investpy.get_index_historical_data(
247
+ index=price,
248
+ country=dict_indices[price],
249
+ from_date=fecha1,
250
+ to_date=today)
251
+ info[price] = data['Close']
252
+ close_ = go.Scatter(x=data.index,
253
+ y=data['Close']/data.iloc[0]["Close"],
254
+ name=price,
255
+ line=dict(
256
+ color=px.colors.qualitative.Pastel[i]))
257
+
258
+ fig2.add_trace(close_)
259
+ orden.append(price)
260
+ i=i+1
261
+ info["Date"] = info.index
262
+ info["Date"] = info["Date"].dt.date
263
+ info = info[orden]
264
+ col_button.markdown(get_table_excel_link(info, "Indices"),
265
+ unsafe_allow_html=True)
266
+ fig2.layout.update(title_text=titulo,
267
+ xaxis_rangeslider_visible=True,
268
+ height=500,
269
+ margin_b=20,
270
+ margin_r=20,
271
+ margin_l=20,
272
+
273
+ legend=dict(orientation="h",
274
+ yanchor="bottom",
275
+ y=1.02,
276
+ xanchor="right",
277
+ x=1))
278
+ col_chart.plotly_chart(fig2, use_container_width=True)
279
+
280
+
281
+ def grafico_avanzado_tasas(col_filter, col_button, col_chart, bonds, TODAY):
282
+ titulo = "Tasas"
283
+ fecha_0 = col_filter.selectbox("Periodo ", ["1 year", "1 week",
284
+ "1 month", "3 month",
285
+ "6 month", "5 year",
286
+ "10 year", "15 year"])
287
+ fecha1 = seleccionar_fecha(fecha_0)
288
+ options = bonds
289
+ info = pd.DataFrame()
290
+ orden = ["Date"]
291
+ fig2 = go.Figure()
292
+ i = 0
293
+ for price in options:
294
+ i = i + 1
295
+ data = investpy.get_bond_historical_data(bond=price,
296
+ from_date=fecha1,
297
+ to_date=TODAY)
298
+ info[price] = data['Close']
299
+ close_ = go.Scatter(x=data.index,
300
+ y=data['Close']/data.iloc[0]["Close"],
301
+ name=price,
302
+ line=dict(
303
+ color=px.colors.qualitative.Pastel[i]))
304
+ fig2.add_trace(close_)
305
+ orden.append(price)
306
+ info["Date"] = info.index
307
+ info["Date"] = info["Date"].dt.date
308
+ info = info[orden]
309
+ col_button.markdown(get_table_excel_link(info, "Tasas"),
310
+ unsafe_allow_html=True)
311
+ # place0.header(titulo)
312
+ fig2.layout.update(title_text=titulo,
313
+ xaxis_rangeslider_visible=True,
314
+ height=500,
315
+ margin_b=20,
316
+ margin_r=20,
317
+ margin_l=20,
318
+
319
+ legend=dict(orientation="h",
320
+ yanchor="bottom",
321
+ y=1.02,
322
+ xanchor="right",
323
+ x=1))
324
+ col_chart.plotly_chart(fig2, use_container_width=True)
325
+
326
+ def view_macro():
327
+ col_filter1, col_button1, col_filter2, col_button2 = st.columns(4)
328
+ col_chart1, col_chart2 = st.columns(2)
329
+
330
+
331
+ index = ["S&P CLX IPSA",
332
+ "S&P Merval",
333
+ "Bovespa",
334
+ "S&P Lima General",
335
+ "COLCAP",
336
+ "S&P/BMV IPC",
337
+ "S&P 500",]
338
+ # "FTSE 100",
339
+ # "China A50",
340
+ # "Nikkei 225"]
341
+ countries = ["chile",
342
+ "argentina",
343
+ "brazil",
344
+ "peru",
345
+ "colombia",
346
+ "mexico",
347
+ "united states",]
348
+ # "united kingdom",
349
+ # "china",
350
+ # "japan"]
351
+ place2_index_st = st.empty()
352
+ today = date.today().strftime("%d/%m/%Y")
353
+ fechas = ["1 year",
354
+ "1 week",
355
+ "1 month",
356
+ "3 month",
357
+ "6 month",
358
+ "5 year",
359
+ "10 year",
360
+ "15 year"]
361
+ cc2_i = ["USD", "EUR", 'MXN', "GBP"]
362
+ cc2_f = ["CLP", "EUR", "GBP", "MXN", "JPY", "BRL", "PEN"]
363
+ try:
364
+ grafico_avanzado_ind(col_chart1,
365
+ col_filter1,
366
+ col_button1,
367
+ index,
368
+ countries,
369
+ today,
370
+ fechas)
371
+ except Exception as exc:
372
+ st.write(exc)
373
+ grafico_avanzado_div(col_chart2,
374
+ col_filter2,
375
+ col_button2,
376
+ cc2_i,
377
+ cc2_f,
378
+ today)
379
+ commodity = sorted(["Copper",
380
+ "Silver",
381
+ "Gold",
382
+ "Platinum",
383
+ 'Brent Oil',
384
+ 'Crude Oil WTI',
385
+ "Natural Gas"])
386
+ col_filter1, col_button1, col_filter2, col_button2 = st.columns(4)
387
+ col_chart1, col_chart2 = st.columns(2)
388
+
389
+
390
+ grafico_avanzado_com(col_filter1, col_button1, col_chart1, commodity, today)
391
+ bonds = ["Chile 10Y", "Peru 10Y", "China 10Y", "U.S. 10Y", "U.K. 10Y",
392
+ "Germany 10y", "Japan 10Y", "Brazil 10Y"]
393
+ try:
394
+ grafico_avanzado_tasas(col_filter2, col_button2, col_chart2, bonds, today)
395
+ except Exception as exc:
396
+ st.write(exc)
397
+
398
+
399
+
400
+ @st.cache
401
+ def tabla_bonos(stocks, TODAY):
402
+ tabla = pd.DataFrame()
403
+ year_ago = date.today() - dt.timedelta(days=365)
404
+ year_ago = year_ago.strftime("%d/%m/%Y")
405
+ for stock in stocks:
406
+ precios = investpy.get_bond_historical_data(bond=stock,
407
+ from_date=year_ago,
408
+ to_date=TODAY)
409
+ precios = precios["Close"]
410
+ last_price = precios.iloc[-1]
411
+ oned = precios.iloc[-2]
412
+ onew = precios.iloc[-5]
413
+ onem = precios.iloc[-20]
414
+ oney = precios.iloc[0]
415
+ return1m = str(round((last_price - onem), 2))+"%"
416
+ return1d = str(round((last_price - oned), 2))+"%"
417
+ return1w = str(round((last_price - onew), 2))+"%"
418
+ return1y = str(round((last_price - oney), 2))+"%"
419
+ last_price = str(round(last_price, 2))+"%"
420
+ tabla = tabla.append([[last_price, return1d, return1w, return1m,
421
+ return1y]])
422
+ tabla.columns = ["Tasa", "1d", "1w", "1m", "1y"]
423
+ tabla.index = stocks
424
+ return tabla
425
+
426
+
427
+ @st.cache
428
+ def tabla_pendiente(stocks, TODAY):
429
+ tabla = pd.DataFrame()
430
+ year_ago = date.today() - dt.timedelta(days=365)
431
+ year_ago = year_ago.strftime("%d/%m/%Y")
432
+ for stock in stocks:
433
+ precios1 = investpy.get_bond_historical_data(bond=stock + " 2Y",
434
+ from_date=year_ago,
435
+ to_date=TODAY)
436
+ precios2 = investpy.get_bond_historical_data(bond=stock + " 10Y",
437
+ from_date=year_ago,
438
+ to_date=TODAY)
439
+ precios = precios2 - precios1
440
+ precios = precios["Close"]
441
+ last_price = precios.iloc[-1]
442
+ oned = precios.iloc[-2]
443
+ onew = precios.iloc[-5]
444
+ onem = precios.iloc[-20]
445
+ oney = precios.iloc[0]
446
+ return1m = str(round((last_price - onem), 2))+"%"
447
+ return1d = str(round((last_price - oned), 2))+"%"
448
+ return1w = str(round((last_price - onew), 2))+"%"
449
+ return1y = str(round((last_price - oney), 2))+"%"
450
+ last_price = str(round((last_price), 2))+"%"
451
+ tabla = tabla.append([[last_price, return1d, return1w, return1m,
452
+ return1y]])
453
+ tabla.columns = ["Pendiente", "1d", "1w", "1m", "1y"]
454
+ tabla.index = stocks
455
+ return tabla
456
+
457
+
458
+ @st.cache
459
+ def tabla_divisas(stocks, TODAY):
460
+ tabla = pd.DataFrame()
461
+ year_ago = date.today() - dt.timedelta(days=365)
462
+ year_ago = year_ago.strftime("%d/%m/%Y")
463
+ for stock in stocks:
464
+ precios = investpy.currency_crosses.get_currency_cross_historical_data(
465
+ stock,
466
+ from_date=year_ago,
467
+ to_date=TODAY)
468
+ precios = precios["Close"]
469
+ last_price = precios.iloc[-1]
470
+ oned = precios.iloc[-2]
471
+ onew = precios.iloc[-5]
472
+ onem = precios.iloc[-20]
473
+ oney = precios.iloc[0]
474
+ return1m = str(round((last_price/onem-1)*100, 2))+"%"
475
+ return1d = str(round((last_price/oned-1)*100, 2))+"%"
476
+ return1w = str(round((last_price/onew-1)*100, 2))+"%"
477
+ return1y = str(round((last_price/oney-1)*100, 2))+"%"
478
+ last_price = "$" + str(round(last_price, 2))
479
+ tabla = tabla.append([[last_price, return1d, return1w, return1m,
480
+ return1y]])
481
+ tabla.columns = ["Precio","1d", "1w", "1m", "1y"]
482
+ tabla.index = stocks
483
+ return tabla
484
+
485
+
486
+ @st.cache
487
+ def tabla_commodity(stocks, TODAY):
488
+ tabla = pd.DataFrame()
489
+ year_ago = date.today() - dt.timedelta(days=365)
490
+ year_ago = year_ago.strftime("%d/%m/%Y")
491
+ for stock in stocks:
492
+ precios = investpy.commodities.get_commodity_historical_data(
493
+ commodity=stock,
494
+ from_date=year_ago,
495
+ to_date=TODAY)
496
+ precios = precios["Close"]
497
+ last_price = precios.iloc[-1]
498
+ oned = precios.iloc[-2]
499
+ onew = precios.iloc[-5]
500
+ onem = precios.iloc[-20]
501
+ oney = precios.iloc[0]
502
+ return1m = str(round((last_price/onem-1)*100, 2))+"%"
503
+ return1d = str(round((last_price/oned-1)*100, 2))+"%"
504
+ return1w = str(round((last_price/onew-1)*100, 2))+"%"
505
+ return1y = str(round((last_price/oney-1)*100, 2))+"%"
506
+ last_price = "$" + str(round(last_price, 2))
507
+ tabla = tabla.append([[last_price, return1d, return1w, return1m, return1y]])
508
+ tabla.columns = ["Precio","1d", "1w", "1m", "1y"]
509
+ tabla.index = stocks
510
+ return tabla
511
+
512
+
513
+ @st.cache
514
+ def tabla_indices(index, countries, TODAY):
515
+ tabla = pd.DataFrame()
516
+ year_ago = date.today() - dt.timedelta(days=365)
517
+ year_ago = year_ago.strftime("%d/%m/%Y")
518
+ for i in range(len(index)):
519
+ precios = investpy.get_index_historical_data(index=index[i],
520
+ country=countries[i],
521
+ from_date=year_ago,
522
+ to_date=TODAY)
523
+ precios = precios["Close"]
524
+ last_price = precios.iloc[-1]
525
+ oned = precios.iloc[-2]
526
+ onew = precios.iloc[-5]
527
+ onem = precios.iloc[-20]
528
+ oney = precios.iloc[0]
529
+ return1m = str(round((last_price/onem-1)*100, 2))+"%"
530
+ return1d = str(round((last_price/oned-1)*100, 2))+"%"
531
+ return1w = str(round((last_price/onew-1)*100, 2))+"%"
532
+ return1y = str(round((last_price/oney-1)*100, 2))+"%"
533
+ last_price = "$" + str(round(last_price, 2))
534
+ tabla = tabla.append([[last_price, return1d, return1w, return1m, return1y]])
535
+ tabla.columns = ["Precio","1d", "1w", "1m", "1y"]
536
+ tabla.index = index
537
+ return tabla
538
+
539
+
540
+ def to_number(valor):
541
+ if valor == "1w":
542
+ value = 0.25
543
+ if valor == "1m":
544
+ value = 1
545
+ elif valor == "3m":
546
+ value = 3
547
+ elif valor == "6m":
548
+ value = 6
549
+ return value
550
+
551
+
552
+ def seleccionar_fecha(fecha_select):
553
+ if fecha_select == "1 week" or fecha_select == "1w":
554
+ fec_in = date.today() - dt.timedelta(days=7)
555
+ elif fecha_select == "1 month":
556
+ fec_in = date.today() - dt.timedelta(days=30)
557
+ elif fecha_select == "3 month":
558
+ fec_in = date.today() - dt.timedelta(days=90)
559
+ elif fecha_select == "6 month":
560
+ fec_in = date.today() - dt.timedelta(days=180)
561
+ elif fecha_select == "1 year":
562
+ fec_in = date.today() - dt.timedelta(days=365)
563
+ elif fecha_select == "5 year":
564
+ fec_in = date.today() - dt.timedelta(days=365*5)
565
+ elif fecha_select == "10 year":
566
+ fec_in = date.today() - dt.timedelta(days=365*10)
567
+ elif fecha_select == "15 year":
568
+ fec_in = date.today() - dt.timedelta(days=365*15)
569
+ fec_in = fec_in.strftime("%d/%m/%Y")
570
+ return fec_in
571
+
572
+
573
+
574
+
575
+
576
+
577
+ @log
578
+ def curva_yield():
579
+ today = date.today()
580
+ col1, col2 = st.columns(2)
581
+ pais = col1.selectbox("Pais", ["Chile", "Brazil", "Mexico", "Colombia",
582
+ "Peru", "Japan", "U.S."])
583
+ meses = col2.selectbox("periodo", ["1w", "1m", "3m", "6m", "1y"])
584
+ if meses == "1w":
585
+ one_months_ago = seleccionar_fecha(meses)
586
+ elif meses == "1y":
587
+ one_months_ago = today.replace(year=today.year - 1).strftime("%d/%m/%Y")
588
+ else:
589
+ mes = to_number(meses)
590
+ one_months_ago = today.replace(month=today.month - mes).strftime("%d/%m/%Y")
591
+ today = today.strftime("%d/%m/%Y")
592
+ if pais == "Chile":
593
+ bonos = ['Chile 1Y', 'Chile 2Y', 'Chile 3Y', 'Chile 4Y', 'Chile 5Y',
594
+ 'Chile 8Y', 'Chile 10Y']
595
+ proporcion = [1, 2, 3, 4, 5, 8, 10]
596
+ elif pais == "Brazil":
597
+ bonos = ['Brazil 3m', 'Brazil 6m', 'Brazil 1Y', 'Brazil 2Y',
598
+ 'Brazil 3Y', 'Brazil 5Y', 'Brazil 8Y', 'Brazil 10Y']
599
+ proporcion = [0.25, 0.5, 1, 2, 3, 5, 8, 10]
600
+ elif pais == "Mexico":
601
+ bonos = ['Mexico 3m', 'Mexico 6m', 'Mexico 1Y', "Mexico 3Y",
602
+ 'Mexico 5Y', 'Mexico 7Y', 'Mexico 10Y']
603
+ proporcion = [0.25, 0.5, 1, 3, 5, 7, 10]
604
+ elif pais == "Colombia":
605
+ bonos = ['Colombia 1Y', 'Colombia 4Y', 'Colombia 5Y', 'Colombia 10Y']
606
+ proporcion = [1, 4, 5, 10]
607
+ elif pais == "Peru":
608
+ bonos = ['Peru 2Y', 'Peru 5Y', 'Peru 10Y']
609
+ proporcion = [2, 5, 10]
610
+ elif pais == "Japan":
611
+ bonos = ['Japan 3m', 'Japan 6m', 'Japan 1Y', "Japan 2Y",
612
+ 'Japan 3Y', 'Japan 5Y', 'Japan 8Y', 'Japan 10Y']
613
+ proporcion = [0.25, 0.5, 1, 3, 5, 7, 10]
614
+ elif pais == "U.S.":
615
+ bonos = ['U.S. 3m', 'U.S. 6m', 'U.S. 1Y', "U.S. 2Y",
616
+ 'U.S. 3Y', 'U.S. 5Y', 'U.S. 8Y', 'U.S. 10Y']
617
+ proporcion = [0.25, 0.5, 1, 3, 5, 7, 10]
618
+ data_today = []
619
+ data_one_month = []
620
+ delta = []
621
+ for bono in bonos:
622
+ data_bono = investpy.bonds.get_bond_historical_data(bono,
623
+ one_months_ago,
624
+ today)
625
+ data_today.append(data_bono.iloc[-1]["Close"])
626
+ data_one_month.append(data_bono.iloc[0]["Close"])
627
+ delta.append(data_bono.iloc[-1]["Close"] - data_bono.iloc[0]["Close"])
628
+
629
+ def plot_tasas():
630
+ fig = go.Figure()
631
+ today = go.Scatter(x=proporcion, y=data_today, name="Yield today",
632
+ line=dict(color="darkred"))
633
+ onemonth = go.Scatter(x=proporcion, y=data_one_month, name="Yield" +
634
+ meses + " ago", line=dict(color="dimgrey"))
635
+ fig.add_trace(today)
636
+ fig.add_trace(onemonth)
637
+ fig.layout.update(title_text="",
638
+ width=900, height=300, margin_b=0, margin_t=0,
639
+ margin_r=0, margin_l=0, legend=dict(orientation="h",
640
+ yanchor="bottom",
641
+ y=1.0,
642
+ xanchor="right",
643
+ x=1),
644
+ xaxis={'visible': False,
645
+ 'showticklabels': False})
646
+ st.plotly_chart(fig)
647
+ fig2 = go.Figure()
648
+ fig2.add_trace(go.Bar(
649
+ x=proporcion,
650
+ y=delta,
651
+ name='Delta',
652
+ marker_color='dimgrey'
653
+ ))
654
+ if pais == "Brazil" or pais == "Mexico":
655
+ fig2.layout.update(title_text="",
656
+ width=900, height=200, margin_b=0, margin_t=0,
657
+ margin_r=0, margin_l=15,
658
+ xaxis=go.layout.XAxis(tickangle=70))
659
+ fig2.update_xaxes(range=[-0.3, proporcion[-1]+0.5], ticktext=bonos,
660
+ tickvals=proporcion)
661
+ else:
662
+ fig2.layout.update(title_text="",
663
+ width=900, height=200, margin_b=0, margin_t=0,
664
+ margin_r=0, margin_l=0,
665
+ xaxis=go.layout.XAxis(tickangle=70))
666
+ fig2.update_xaxes(ticktext=bonos, tickvals=proporcion,
667
+ range=[0.5, proporcion[-1]+0.5])
668
+ fig2.update_layout(barmode='group')
669
+ st.plotly_chart(fig2)
670
+ plot_tasas()
671
+
672
+
673
+ def plot_raw_data(col, data, color, prefijo, ancho, largo):
674
+ fig = go.Figure()
675
+ close_ = go.Scatter(x=data.index, y=data['Close'], name="stock_close",
676
+ line=dict(color=color), fill='tonexty')
677
+ fig.add_trace(close_)
678
+ fig.layout.update(title_text="", xaxis_rangeslider_visible=True,
679
+ width=ancho, height=largo, margin_b=0, margin_t=0,
680
+ margin_r=0, margin_l=0)
681
+ fig.update_yaxes(range=[min(data['Close'])/1.05,
682
+ max(data['Close'])*1.05], tickprefix=prefijo)
683
+ col.plotly_chart(fig, use_container_width=True)
684
+
685
+
686
+ # Brasil, Mexico, Chile, Colombia, Peru, USA, Alemania, UK, China, Japon
687
+ @log
688
+ def tasa10y_2y():
689
+ button_style()
690
+ TODAY = date.today().strftime("%d/%m/%Y")
691
+ bond_10y = ["Chile 10Y", "Peru 10Y", "China 10Y", "U.S. 10Y", "U.K. 10Y",
692
+ "Germany 10y", "Japan 10Y", "Brazil 10Y"]
693
+ bond_2y = ["Chile 2Y",
694
+ "Peru 2Y", "China 2Y", "U.S. 2Y", "U.K. 2Y", "Germany 2y",
695
+ "Japan 2Y", "Brazil 2Y"]
696
+ paises = ["Chile", "Peru", "China", "U.S.", "U.K.", "Alemania",
697
+ "Japon", "Brasil"]
698
+ col1, col2 = st.columns((1.681, 1))
699
+ selected = col1.selectbox("Seleccionar pais", paises)
700
+ fecha_select = col2.selectbox(" ", ["1 year", "1 week", "1 month",
701
+ "3 month", "6 month", "5 year",
702
+ "10 year", "15 year"])
703
+ fec_in = seleccionar_fecha(fecha_select)
704
+ data_bonds10y = investpy.get_bond_historical_data(
705
+ bond=bond_10y[paises.index(selected)],
706
+ from_date=fec_in,
707
+ to_date=TODAY)
708
+ data_bonds2y = investpy.get_bond_historical_data(
709
+ bond=bond_2y[paises.index(selected)],
710
+ from_date=fec_in,
711
+ to_date=TODAY)
712
+ data_final = data_bonds10y["Close"]-data_bonds2y["Close"]
713
+ fig = go.Figure()
714
+ close_ = go.Scatter(x=data_bonds10y.index, y=data_final, name="Delta",
715
+ line=dict(color="midnightblue"), fill='tonexty')
716
+ fig.add_trace(close_)
717
+ fig.layout.update(title_text="", xaxis_rangeslider_visible=True,
718
+ width=900, height=400, margin_b=0, margin_t=0,
719
+ margin_r=0, margin_l=0)
720
+ fig.update_yaxes(range=[min(data_final)/1.05,
721
+ max(data_final)*1.05])
722
+ cols = st.columns((1.681*2.681, 1.681, 1))
723
+ col1, col2 = st.columns((1.681, 1))
724
+ col1.plotly_chart(fig, use_container_width=True)
725
+ data_final2 = pd.DataFrame()
726
+ data_final2["Date"] = list(data_final.index)
727
+ cierre = list(data_bonds10y["Close"]-data_bonds2y["Close"])
728
+ data_final2["Delta"] = list(data_bonds10y["Close"]-data_bonds2y["Close"])
729
+ last_price = cierre[-1]
730
+ first_price = cierre[0]
731
+ returns = round(((last_price - first_price)), 2)
732
+ cols[1].markdown('<p style="font-size:15px; padding-left:20px; margin-bottom:0px;">'+"Tasa 10Y - 2Y"+"</p>", unsafe_allow_html=True)
733
+ cols[1].markdown('<p style="font-size:35px; padding-left:30px;">'+formatnum(last_price)+"%</p>", unsafe_allow_html=True)
734
+ if returns > 0:
735
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:green;">▲ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
736
+ else:
737
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:red;">▼ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
738
+ st.markdown(get_table_excel_link(data_final2, selected),
739
+ unsafe_allow_html=True)
740
+ paises = ["Brazil", "Chile",
741
+ "Peru", "China", "U.S.", "U.K.", "Germany",
742
+ "Japan"]
743
+ style_table()
744
+ col2.dataframe(tabla_pendiente(paises, TODAY))
745
+
746
+
747
+ @log
748
+ def bonos():
749
+ st.sidebar.subheader("Opciones")
750
+ largo = 350
751
+ ancho = 450
752
+ button_style()
753
+ placeholder = st.empty()
754
+ placeholder1 = st.empty()
755
+ TODAY = date.today().strftime("%d/%m/%Y")
756
+ cols = st.columns((1.681*2.5, 1.681, 1))
757
+ col1, col2 = st.columns((1.6, 1))
758
+ paises = ["Brazil", "Mexico", "Chile", "Colombia",
759
+ "Peru", "China", "U.S.", "U.K.", "Germany",
760
+ "Japan"]
761
+ time = ["2Y", "10Y"]
762
+ # #################
763
+ selected_pais = cols[0].selectbox(" ", paises)
764
+ selected_time = cols[1].selectbox(" ", time)
765
+ fecha_select = cols[2].selectbox(" ", ["1 year", "1 week", "1 month",
766
+ "3 month", "6 month", "5 year",
767
+ "10 year", "15 year"])
768
+ fec_in = seleccionar_fecha(fecha_select)
769
+ selected = selected_pais + " " + selected_time
770
+ data_bonds = investpy.get_bond_historical_data(bond=selected,
771
+ from_date=fec_in,
772
+ to_date=TODAY)
773
+
774
+ plot_raw_data(col1, data_bonds, 'dimgrey', "", ancho, largo)
775
+
776
+ last_price = data_bonds.iloc[-1]["Close"]
777
+ first_price = data_bonds.iloc[0]["Close"]
778
+ returns = round((last_price - first_price), 2)
779
+ cols[0].title("Tasa " + selected)
780
+ cols[1].markdown('<p style="font-size:15px; padding-left:20px; margin-bottom:0px;">'+"Tasa"+"</p>", unsafe_allow_html=True)
781
+ cols[1].markdown('<p style="font-size:35px; padding-left:30px;">'+formatnum(last_price)+"%</p>", unsafe_allow_html=True)
782
+ if returns > 0:
783
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:green;">▲ +'+ formatnum(returns)+" %</p>", unsafe_allow_html=True)
784
+ else:
785
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:red;">▼ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
786
+ # #################
787
+ style_table()
788
+ bonds10y = ["Brazil 10Y",
789
+ "Mexico 10Y",
790
+ "Chile 10Y",
791
+ "Colombia 10Y",
792
+ "Peru 10Y","China 10Y", "U.S. 10Y", "U.K. 10Y", "Germany 10y",
793
+ "Japan 10Y", ]
794
+ col2.dataframe(tabla_bonos(bonds10y, TODAY))
795
+ data_bonds["Date"] = data_bonds.index
796
+ data_bonds["Date"] = data_bonds["Date"].dt.date
797
+ data_toexcel = data_bonds[["Date", "Close"]]
798
+ st.markdown(get_table_excel_link(data_toexcel, selected),
799
+ unsafe_allow_html=True)
800
+ # graph_advance = st.sidebar.checkbox("Graficos avanzados")
801
+ # if graph_advance:
802
+
803
+
804
+
805
+ @log
806
+ def Commodities():
807
+ st.sidebar.subheader("Opciones")
808
+ largo = 350
809
+ ancho = 450
810
+ placeholder = st.empty()
811
+ placeholder1 = st.empty()
812
+ button_style()
813
+ TODAY = date.today().strftime("%d/%m/%Y")
814
+ col1, col2 = st.columns((1.681, 1))
815
+ cols = st.columns((1.681*2.681, 1.681, 1))
816
+ commodity = sorted(["Copper", "Silver", "Gold", "Platinum", 'Brent Oil',
817
+ 'Crude Oil WTI', "Natural Gas"])
818
+ # #################
819
+ selected_com = col1.selectbox(" ", commodity)
820
+ fecha_select = col2.selectbox(" ", ["1 year", "1 week", "1 month",
821
+ "3 month", "6 month", "5 year",
822
+ "10 year", "15 year"])
823
+ fec_in = seleccionar_fecha(fecha_select)
824
+ data_com = investpy.commodities.get_commodity_historical_data(
825
+ commodity=selected_com,
826
+ from_date=fec_in,
827
+ to_date=TODAY)
828
+ col1, col2 = st.columns((1.681, 1))
829
+ plot_raw_data(col1, data_com, 'dimgrey', "", ancho, largo)
830
+ last_price = data_com.iloc[-1]["Close"]
831
+ first_price = data_com.iloc[0]["Close"]
832
+ returns = round(((last_price/first_price-1)*100), 2)
833
+ cols[0].title("Precio " + selected_com)
834
+ cols[1].markdown('<h4 style="font-size:15px; padding-left:20px; margin-bottom:0px;">'+"Precio"+"</h4>", unsafe_allow_html=True)
835
+ cols[1].markdown('<p style="font-size:30px; padding-left:30px;">$'+formatnum(last_price)+"</p>", unsafe_allow_html=True)
836
+ if returns > 0:
837
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:green;">▲ +'+formatnum(returns)+" %</p>", unsafe_allow_html=True)
838
+ else:
839
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:red;">▼ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
840
+ ##################
841
+
842
+ style_table()
843
+ col2.dataframe(tabla_commodity(commodity, TODAY))
844
+ data_com["Date"] = data_com.index
845
+ data_com["Date"] = data_com["Date"].dt.date
846
+ data_com_toexcel = data_com[["Date", "Close"]]
847
+ st.markdown(get_table_excel_link(data_com_toexcel, selected_com),
848
+ unsafe_allow_html=True)
849
+
850
+
851
+
852
+ @log
853
+ def Indices():
854
+ st.sidebar.subheader("Opciones")
855
+ largo = 350
856
+ ancho = 450
857
+ placeholder = st.empty()
858
+ placeholder1 = st.empty()
859
+ button_style()
860
+ TODAY = date.today().strftime("%d/%m/%Y")
861
+ col1, col2 = st.columns((1.681, 1))
862
+ cols = st.columns((1.681*2.681, 1.681, 1.2))
863
+ index = ["S&P CLX IPSA", "S&P Merval", "Bovespa", "S&P Lima General",
864
+ "COLCAP", "S&P/BMV IPC", "S&P 500", "FTSE 100", "China A50",
865
+ "Nikkei 225"]
866
+ countries = ["chile", "argentina", "brazil", "peru", "colombia", "mexico",
867
+ "united states", "united kingdom", "china", "japan"]
868
+ ##################
869
+ selected_index = col1.selectbox(" ", index)
870
+ fecha_select = col2.selectbox(" ", ["1 year", "1 week", "1 month",
871
+ "3 month", "6 month", "5 year",
872
+ "10 year", "15 year"])
873
+ fec_in = seleccionar_fecha(fecha_select)
874
+ data_index = investpy.get_index_historical_data(
875
+ index=selected_index,
876
+ country=countries[index.index(selected_index)],
877
+ from_date=fec_in,
878
+ to_date=TODAY)
879
+ col1, col2 = st.columns((1.681, 1))
880
+ plot_raw_data(col1, data_index, 'dimgrey', "", ancho, largo)
881
+ last_price = data_index.iloc[-1]["Close"]
882
+ first_price = data_index.iloc[0]["Close"]
883
+ returns = round(((last_price/first_price-1)*100), 2)
884
+ cols[0].title("Precio " + selected_index)
885
+ cols[1].markdown('<h4 style="font-size:15px; padding-left:20px; margin-bottom:0px;">'+"Precio"+"</h4>", unsafe_allow_html=True)
886
+ cols[1].markdown('<p style="font-size:30px; padding-left:30px;">$'+formatnum(last_price)+"</p>", unsafe_allow_html=True)
887
+ if returns > 0:
888
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:green;">▲ +'+formatnum(returns)+" %</p>", unsafe_allow_html=True)
889
+ else:
890
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:red;">▼ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
891
+ ##################
892
+ style_table()
893
+ col2.dataframe(tabla_indices(index, countries, TODAY))
894
+ data_index["Date"] = data_index.index
895
+ data_index["Date"] = data_index["Date"].dt.date
896
+ data_index_toexcel = data_index[["Date", "Close"]]
897
+ st.markdown(get_table_excel_link(data_index_toexcel, selected_index),
898
+ unsafe_allow_html=True)
899
+
900
+
901
+
902
+ @log
903
+ def Divisas():
904
+ st.sidebar.subheader("Opciones")
905
+ largo = 350
906
+ ancho = 450
907
+ placeholder = st.empty()
908
+ placeholder1 = st.empty()
909
+ button_style()
910
+ TODAY = date.today().strftime("%d/%m/%Y")
911
+ cols = st.columns(3)
912
+ cc1 = ["USD/CLP", "EUR/CLP", "GBP/CLP", "BRL/CLP", "JPY/CLP", "MXN/CLP",
913
+ "PEN/CLP"]
914
+ ##################
915
+ cc2_i = ["USD", "EUR", 'MXN', "GBP"]
916
+ cc2_f = ["CLP", "USD", "EUR", "GBP", "MXN", "JPY", "BRL", "PEN"]
917
+ ##################
918
+ selected_cc2_i = cols[0].selectbox(" ", cc2_i)
919
+ selected_cc2_f = cols[1].selectbox(" ", cc2_f)
920
+ selected_cc2 = selected_cc2_i + "/" + selected_cc2_f
921
+ fecha_select2 = cols[2].selectbox(" ", ["1 year", "1 week", "1 month",
922
+ "3 month", "6 month",
923
+ "5 year", "10 year",
924
+ "15 year"])
925
+ fec_in2 = seleccionar_fecha(fecha_select2)
926
+ data_cc2 = investpy.currency_crosses.get_currency_cross_historical_data(
927
+ selected_cc2, from_date=fec_in2, to_date=TODAY)
928
+ cols = st.columns((1.681*2.681, 1.681, 1))
929
+ col1, col2 = st.columns((1.681, 1))
930
+ plot_raw_data(col1, data_cc2, 'midnightblue', "", ancho, largo)
931
+ last_price = data_cc2.iloc[-1]["Close"]
932
+ first_price = data_cc2.iloc[0]["Close"]
933
+ returns = round(((last_price/first_price-1)*100), 2)
934
+ cols[0].title(selected_cc2)
935
+ cols[1].markdown('<p style="font-size:15px; padding-left:15px; margin-bottom:0px;">'+"Precio"+"</p>", unsafe_allow_html=True)
936
+ cols[1].markdown('<p style="font-size:30px; padding-left:30px;">' + formatnum(last_price)+ " "+selected_cc2_f +"</p>", unsafe_allow_html=True)
937
+ if returns > 0:
938
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:green;">▲ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
939
+ else:
940
+ cols[2].markdown('<p style="font-size:22px; padding-top:27px; color:red;">▼ '+formatnum(returns)+" %</p>", unsafe_allow_html=True)
941
+ style_table()
942
+ # col1.dataframe(tabla_indices(index, countries, TODAY))
943
+ # col2.dataframe(tabla_indices(index2, countries, TODAY))
944
+ data_cc2["Date"] = data_cc2.index
945
+ data_cc2["Date"] = data_cc2["Date"].dt.date
946
+ data_cc2_toexcel = data_cc2[["Date", "Close"]]
947
+ st.markdown(get_table_excel_link(data_cc2_toexcel, selected_cc2),
948
+ unsafe_allow_html=True)
949
+ col2.dataframe(tabla_divisas(cc1, TODAY))
950
+
apps/analisis_inmob.py CHANGED
@@ -1,3 +1,347 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:606f196cbeba53cf826af70e6575b7cc6d481a544af2f5ddc0f448fc2244e3eb
3
- size 14998
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Imports
2
+ import pandas as pd
3
+ import streamlit as st
4
+ import pybase64 as base64
5
+ # from modules.tables import RealEstateMaste
6
+ from sqlalchemy import create_engine
7
+ import plotly.express as px
8
+ import io
9
+ import urllib.request
10
+ import bs4 as bs
11
+ import scipy.stats as stats
12
+ import plotly.figure_factory as ff
13
+ import scipy.stats as stats
14
+ import plotly.graph_objects as go
15
+ import numpy as np
16
+ from datetime import date
17
+ from datetime import timedelta
18
+ from Data.credentials import credentials_postgresql as credpost
19
+
20
+ def formatnum(numero):
21
+ '''
22
+ Esta función permite dar formato a los montos de saldo y valor cuota en
23
+ las cartolas.
24
+ '''
25
+ return '{:,.0f}'.format(numero).replace(",", "@").replace(".", ",").replace("@", ".")
26
+
27
+
28
+ def get_UF():
29
+ link = "https://valoruf.cl/"
30
+ req = urllib.request.Request(link)
31
+ res = urllib.request.urlopen(req)
32
+ resData = res.read()
33
+ soup = bs.BeautifulSoup(resData)
34
+ uf = soup.find(class_="vpr").contents[0]
35
+ uf_value = uf.split(' ')[1]
36
+ uf_value = uf_value.replace('.', '')
37
+ uf_value = uf_value.replace(',', '.')
38
+ return uf_value
39
+
40
+
41
+ def button_style():
42
+ style_button = """
43
+ <style>
44
+ button {
45
+ display: inline-block;
46
+ background-color: #e8e8e8;
47
+ border-radius: 15px;
48
+ border: 4px #cccccc;
49
+ color: #4a4a4a;
50
+ text-align: center;
51
+ font-size: 18px;
52
+ padding: 2px;
53
+ width: 300px;
54
+ transition: all 0.5s;
55
+ cursor: pointer;
56
+ margin: 5px;
57
+ }
58
+ button span {
59
+ cursor: pointer;
60
+ display: inline-block;
61
+ position: relative;
62
+ transition: 0.5s;
63
+ }
64
+ button span:after {
65
+ content: '\00bb';
66
+ position: absolute;
67
+ opacity: 0;
68
+ top: 0;
69
+ right: -20px;
70
+ transition: 0.5s;
71
+ }
72
+ button:hover {
73
+ background-color: #bb1114;
74
+ color:#e8e8e8;
75
+ }
76
+ button:hover span {
77
+ padding-right: 25px;
78
+ }
79
+ button:hover span:after {
80
+ opacity: 1;
81
+ right: 0;
82
+ }
83
+ </style>
84
+ """
85
+ st.markdown(style_button, unsafe_allow_html=True)
86
+
87
+
88
+ def plot_column(data, column, nom_var_inv, placeholder, sigmas=3, limite=None):
89
+ data = data.rename(columns=nom_var_inv)
90
+ column = nom_var_inv[column]
91
+ limit = data[column].mean() + sigmas * data[column].std()
92
+ data = data.loc[data[column] <= limit]
93
+ if limite is not None:
94
+ data = data.loc[data[column] <= limite]
95
+ fig = px.scatter_mapbox(data_frame=data, lat='latitud', lon='longitud',
96
+ zoom=10, color=column,
97
+ hover_data=['codigo', 'Superficie', 'dormitorios', 'banos', 'Precio en CLP'],
98
+ color_continuous_scale=px.colors.diverging.RdYlBu,
99
+ width=1000, height=800)
100
+ placeholder.plotly_chart(fig, use_container_width=True)
101
+
102
+ def plot_column2(data, column, nom_var_inv, placeholder, zoom, sigmas=10, limite=None):
103
+ data = data.rename(columns=nom_var_inv)
104
+ column = nom_var_inv[column]
105
+ limit = data[column].mean() + sigmas * data[column].std()
106
+ data = data.loc[data[column] <= limit]
107
+ if limite is not None:
108
+ data = data.loc[data[column] <= limite]
109
+ fig = px.scatter_mapbox(data_frame=data, lat='latitud', lon='longitud',
110
+ zoom=zoom, color=column,
111
+ hover_data=['codigo', 'Superficie', 'dormitorios', 'banos', 'Precio en CLP', 'Comuna'],
112
+ color_continuous_scale=px.colors.diverging.RdYlBu,
113
+ width=1000, height=800,size='Superficie',size_max=25)
114
+ placeholder.plotly_chart(fig, use_container_width=True)
115
+
116
+
117
+ def get_comuna(direction):
118
+ values = direction.split(',')
119
+ return values[-2]
120
+
121
+ def unit_separator(string):
122
+ values = string.split(" ")
123
+ return values[0]
124
+
125
+
126
+ def transform_df(scraping_df):
127
+ # Extract numbers from string
128
+ # Change datatype
129
+ # Add 'Comuna' and 'Región'
130
+ scraping_df[["Comuna"]] = scraping_df[["direccion"]].applymap(lambda x: get_comuna(x))
131
+ # Scrap UF value for date
132
+ #scraping_df[["Valor UF"]] = get_UF()
133
+ return scraping_df
134
+
135
+
136
+ def get_table_excel_link(df, name):
137
+ towrite = io.BytesIO()
138
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
139
+ header=True)
140
+ towrite.seek(0) # reset pointer
141
+ file_name = 'Data' + name + '.xlsx'
142
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
143
+ name_mark = "Descargar " + name + ".xlsx"
144
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
145
+ linko= f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
146
+ return linko
147
+
148
+
149
+ @st.cache(allow_output_mutation=True)
150
+ def query_inmob():
151
+ url = credpost["POSTGRESQL"]
152
+ engine = create_engine(url, echo=False)
153
+ semana_pasada = date.today() - timedelta(7)
154
+ semana_pasada = semana_pasada.strftime("%Y-%m-%d")
155
+ data = pd.read_sql_query("""select * from scraping_inmob where Fecha >
156
+ '{Fecha} 00:00:00' ORDER BY Fecha desc""".format(Fecha=semana_pasada) , con=engine)
157
+ return data
158
+
159
+ def run_scrapping():
160
+ button_style()
161
+ px.set_mapbox_access_token('pk.eyJ1IjoibW9rc2VuYmVyZyIsImEiOiJja3QwOTc3dHgyNzBhMnFsczJ2Y2w3bWJlIn0.m8c3duvR5hQVjbjEByorWQ')
162
+ data = query_inmob()
163
+ precio_uf = get_UF()
164
+ data["valor_uf"] = data["valor_peso"]/float(precio_uf)
165
+ data['predicted_venta_por_m2_UF']=data['predicted_venta_por_m2']/float(precio_uf)
166
+ nom_var = {"Precio en UF": "valor_uf",
167
+ "Precio en CLP": "valor_peso",
168
+ "Superficie": "superficie",
169
+ "Predicted venta por M2 en CLP": "predicted_venta_por_m2",
170
+ "Predicted venta por M2 en UF": "predicted_venta_por_m2_UF",
171
+ "Predicted arriendo por M2": "predicted_arriendo_por_m2",
172
+ "Predicted yield anual": "predicted_yield_anual"
173
+ }
174
+ nom_var_inv = {v: k for k, v in nom_var.items()}
175
+ var = list(nom_var.keys())
176
+ with st.form(key='my_form'):
177
+ col1, col2, col3, col4 = st.columns((9, 1, 9, 1))
178
+ cols = st.columns((9, 1, 5, 5))
179
+ pre_selection = col1.selectbox("Variable", var)
180
+ selection = nom_var[pre_selection]
181
+ mercado = col3.selectbox("Mercado", ["Venta", "Arriendo", "Todos"])
182
+ if mercado != "Todos":
183
+ mercado = mercado.lower()
184
+ data_mercado = data[data["mercado"] == mercado]
185
+ else:
186
+ data_mercado = data
187
+ cifras = len(str(int(max(data_mercado[selection]))))
188
+ tipo_prop = cols[0].selectbox("Tipo de propiedad",
189
+ ["Todos", "Casa", "Departamento"])
190
+ if tipo_prop != "Todos":
191
+ tipo_prop2 = tipo_prop.lower()
192
+ data_mercado = data_mercado[data_mercado["tipo_propiedad"] == tipo_prop2]
193
+ if cifras > 3:
194
+ corte = 10 ** (cifras - 3)
195
+ cota_final = (int(max(data_mercado[selection].dropna()))//corte+1) *corte
196
+ cota_inf = cols[2].number_input(label="Valor Mínimo",
197
+ min_value=0,
198
+ value=0,
199
+ max_value=cota_final
200
+ )
201
+ cota_sup = cols[3].number_input(label="Valor Máximo",
202
+ min_value=0,
203
+ value=cota_final,
204
+ max_value=cota_final
205
+ )
206
+ else:
207
+ cota_final = max(data_mercado[selection].dropna())+1
208
+ cota_inf = cols[2].number_input(label="Valor Mínimo",
209
+ min_value=0.0,
210
+ value=0.0,
211
+ step=0.1,
212
+ max_value=cota_final
213
+ )
214
+ cota_sup = cols[3].number_input(label="Valor Máximo",
215
+ min_value=0.0,
216
+ step=0.1,
217
+ value=cota_final,
218
+ max_value=cota_final
219
+ )
220
+ data_final = data_mercado[data_mercado[selection] < cota_sup]
221
+ data_final = data_final[data_final[selection] > cota_inf]
222
+ submit_button = st.form_submit_button(label='Actualizar')
223
+ col1, col2 = st.columns((0.65, 1))
224
+ placeholder = st.empty()
225
+ placeholder2 = st.empty()
226
+ placeholder2.markdown(get_table_excel_link(data, "Data Completa"),
227
+ unsafe_allow_html=True)
228
+ plot_column(data, selection, nom_var_inv, placeholder)
229
+
230
+ if submit_button:
231
+ plot_column(data_final, selection, nom_var_inv, placeholder)
232
+
233
+ st.markdown(get_table_excel_link(data_final, " Data filtrada"),
234
+ unsafe_allow_html=True)
235
+
236
+
237
+
238
+ def scraping_localizado():
239
+ button_style()
240
+ data = query_inmob()
241
+ data = transform_df(data)
242
+ precio_uf = get_UF()
243
+ data["valor_uf"] = data["valor_peso"]/float(precio_uf)
244
+ data['predicted_venta_por_m2_UF'] = data['predicted_venta_por_m2']/float(precio_uf)
245
+ nom_var = {"Precio en UF": "valor_uf",
246
+ "Precio en CLP": "valor_peso",
247
+ "Superficie": "superficie",
248
+ "Predicted venta por M2 en CLP": "predicted_venta_por_m2",
249
+ "Predicted venta por M2 en UF": "predicted_venta_por_m2_UF",
250
+ "Predicted arriendo por M2": "predicted_arriendo_por_m2",
251
+ "Predicted yield anual": "predicted_yield_anual"
252
+ }
253
+ nom_var_inv = {v : k for k, v in nom_var.items()}
254
+ var = list(nom_var.keys())
255
+ with st.form(key='my_form'):
256
+ col1, col2, col3, col4 = st.columns((9, 1, 9, 1))
257
+ cols = st.columns((9, 1, 5, 5))
258
+ pre_selection = col1.selectbox("Variable", var)
259
+ selection = nom_var[pre_selection]
260
+ mercado = col3.selectbox("Mercado", ["Venta", "Arriendo", "Todos"])
261
+ banos = col1.slider("Baños", value=(1, 5), min_value=0, max_value=10)
262
+ dormitorios = col3.slider("Dormitorios", value=(1, 5), min_value=0,
263
+ max_value=10)
264
+ com = ["Todas"] + sorted(list(dict.fromkeys(data["Comuna"])))
265
+ comuna = col1.selectbox("Comuna", com)
266
+ zoom = col3.number_input("Zoom", value=12)
267
+ if mercado != "Todos":
268
+ mercado = mercado.lower()
269
+ data_mercado = data[data["mercado"] == mercado]
270
+ else:
271
+ data_mercado = data
272
+ if comuna != "Todas":
273
+ data_mercado = data_mercado[data_mercado["Comuna"] == comuna]
274
+ if len(data_mercado) > 0:
275
+ cifras = len(str(int(max(data_mercado[selection].dropna()))))
276
+ else:
277
+ cifras = 0
278
+ tipo_prop = cols[0].selectbox("Tipo de Propiedad",
279
+ ["Todos", "Casa", "Departamento"])
280
+ if tipo_prop != "Todos":
281
+ tipo_prop2 = tipo_prop.lower()
282
+ data_mercado = data_mercado[data_mercado["tipo_propiedad"] == tipo_prop2]
283
+ if cifras > 3:
284
+ corte = 10 ** (cifras - 3)
285
+ cota_final = (int(max(data_mercado[selection].dropna()))//corte+1)*corte
286
+ cota_inf = cols[2].number_input(label="Valor Mínimo",
287
+ min_value=0,
288
+ value=0,
289
+ max_value=cota_final
290
+ )
291
+ cota_sup = cols[3].number_input(label="Valor Máximo",
292
+ min_value=0,
293
+ value=cota_final,
294
+ max_value=cota_final
295
+ )
296
+ else:
297
+ cota_final = max(data_mercado[selection].dropna())+1
298
+ cota_inf = cols[2].number_input(label="Valor Mínimo",
299
+ min_value=0.0,
300
+ value=0.0,
301
+ step=0.1,
302
+ max_value=cota_final
303
+ )
304
+ cota_sup = cols[3].number_input(label="Valor Máximo",
305
+ min_value=0.0,
306
+ step=0.1,
307
+ value=cota_final,
308
+ max_value=cota_final
309
+ )
310
+
311
+ data_final = data_mercado[data_mercado[selection] < cota_sup]
312
+ data_final = data_final[data_final[selection] > cota_inf]
313
+ data_final = data_final[data_final["banos"] > banos[0]]
314
+ data_final = data_final[data_final["banos"] < banos[1]]
315
+ data_final = data_final[data_final["dormitorios"] > dormitorios[0]]
316
+ data_final = data_final[data_final["dormitorios"] < dormitorios[1]]
317
+ st.write('Stats principales del análisis')
318
+ st.write('Valor promedio en UF por metro cuadrado: {:.2f} UF'.format((data_final['valor_uf']/data_final['superficie']).mean()))
319
+ st.write('Superficie promedio: {:.0f} m2'.format(data_final['superficie'].mean()))
320
+ st.write('N° de dormitorios promedio: {:.2f}'.format(data_final['dormitorios'].mean()))
321
+ st.write('N° de baños promedio: {:.2f}'.format(data_final['banos'].mean()))
322
+
323
+ submit_button = st.form_submit_button(label='Actualizar')
324
+ col1, col2 = st.columns((0.65, 1))
325
+ placeholder = st.empty()
326
+ placeholder2 = st.empty()
327
+ placeholder3 = st.empty()
328
+ placeholder2.markdown(get_table_excel_link(data, "Data Completa"),
329
+ unsafe_allow_html=True)
330
+ plot_column2(data, selection, nom_var_inv, placeholder, zoom)
331
+ dist_gamma = stats.gamma.rvs(1, scale=250000, size=2965)
332
+ if submit_button:
333
+ plot_column2(data_final, selection, nom_var_inv, placeholder, zoom)
334
+ st.markdown(get_table_excel_link(data_final, " Data filtrada"),
335
+ unsafe_allow_html=True)
336
+ data_hist = data_final[data_final["mercado"] == "venta"]
337
+ data_hist = data_hist[data_hist["valor_peso"] > 40000000]
338
+ data_hist = data_hist[data_hist["valor_peso"] < 1000000000]["valor_peso"] * 0.2
339
+ fig2 = px.histogram((data_hist), x='valor_peso')
340
+ #placeholder3.plotly_chart(fig2)
341
+
342
+ # streamlit run analisis_inmob.py
343
+ # scraping_localizado()
344
+
345
+
346
+
347
+
apps/mailer_quant.py CHANGED
@@ -1,3 +1,63 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:7d46e155d92c4daa20d3bd4e2e77b01895a32a82efd297ccb9e849f4daaa79d7
3
- size 2444
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import email, smtplib, ssl
2
+ from datetime import datetime
3
+ from email import encoders
4
+ from email.mime.base import MIMEBase
5
+ from email.mime.multipart import MIMEMultipart
6
+ from email.mime.text import MIMEText
7
+ import os
8
+
9
+ class Mailer():
10
+
11
+ def __init__(self, subject, body, html, receiver):
12
+ self.subject = subject
13
+ self.body = body
14
+ self.html = html
15
+ self.sender_email = os.environ.get('EMAIL_SENDER')
16
+ self.receiver_email = receiver
17
+ self.password = os.environ.get('EMAIL_PASSWORD')
18
+ self.message = None
19
+ self.create_message()
20
+
21
+
22
+ def create_message(self, filepath=None, filename=None):
23
+ # Create a multipart message and set headers
24
+ message = MIMEMultipart()
25
+ message["From"] = self.sender_email
26
+ message["To"] = self.receiver_email
27
+ message["Subject"] = self.subject
28
+ message["Bcc"] = self.receiver_email # Recommended for mass emails
29
+ # Add body to email
30
+ if self.html:
31
+ message.attach(MIMEText(self.html, "html"))
32
+ elif self.body:
33
+ message.attach(MIMEText(self.body, "plain"))
34
+ #filename = "test.pdf" # In same directory as script
35
+ # Open PDF file in binary mode
36
+ if filepath and filename:
37
+ with open(filepath, "rb") as attachment:
38
+ # Add file as application/octet-stream
39
+ # Email client can usually download this automatically as attachment
40
+ part = MIMEBase("application", "octet-stream")
41
+ part.set_payload(attachment.read())
42
+
43
+ # Encode file in ASCII characters to send by email
44
+ encoders.encode_base64(part)
45
+
46
+ # Add header as key/value pair to attachment part
47
+ part.add_header(
48
+ "Content-Disposition",
49
+ f"attachment; filename= {filename}",
50
+ )
51
+
52
+ # Add attachment to message and convert message to string
53
+ message.attach(part)
54
+ self.text = message.as_string()
55
+ return
56
+
57
+ def send_message(self, receiver):
58
+ # Log in to server using secure context and send email
59
+ context = ssl.create_default_context()
60
+ with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
61
+ server.login(self.sender_email, self.password)
62
+ server.sendmail(self.sender_email, receiver, self.text)
63
+
apps/simulacion_vc.py CHANGED
@@ -1,3 +1,1414 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:e147bfa570fa63c05c0a2a0bce32de8c76ab8270ab302b9ba16eb4c6861a859b
3
- size 57640
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Tue Sep 21 11:53:13 2021
5
+
6
+ @author: benjaminull
7
+ """
8
+
9
+ import numpy as np
10
+ import streamlit as st
11
+ import plotly.express as px
12
+ import pandas as pd
13
+ import scipy.stats as stats
14
+ import plotly.express as px
15
+ import scipy.stats as stats
16
+ import plotly.graph_objects as go
17
+ from sqlalchemy import create_engine
18
+ import pybase64 as base64
19
+ import io
20
+ import matplotlib.pyplot as plt
21
+ from io import StringIO
22
+ import pandas as pd
23
+
24
+ @st.cache(allow_output_mutation=True)
25
+ def read_excel(path):
26
+ df = pd.read_excel(path)
27
+ return df
28
+
29
+ @st.cache(allow_output_mutation=True)
30
+ def read_excel2(path):
31
+ df = pd.read_excel(path)
32
+ return df
33
+
34
+ def explorar_data():
35
+ df = read_excel('base_personas.xlsx')
36
+ df2 = read_excel2('base_personas.xlsx')
37
+ data = df.copy()
38
+ data2 = df2.copy()
39
+ l=[]
40
+
41
+ variable = st.selectbox(" ",list(data.columns))
42
+ for i in list(data2.columns):
43
+ if i not in ["FE", "EDAD", variable]:
44
+ try:
45
+ data2[i] = data2[i]* data2["FE"]
46
+ except:
47
+ pass
48
+ col1, col2 = st.beta_columns(2)
49
+ minim = col1.number_input("Edad minima", min_value=0, max_value=105)
50
+ maxim = col2.number_input("Edad maxima", min_value=0, max_value=105, value=105)
51
+ data = data[data["EDAD"] < maxim]
52
+ data = data[data["EDAD"] > minim]
53
+ data2 = data2[data2["EDAD"] < maxim]
54
+ data2 = data2[data2["EDAD"] > minim]
55
+ pond = st.checkbox("Ponderar por FE")
56
+ import plotly.graph_objects as go
57
+ if pond:
58
+ data_f3 = data2.groupby([ variable, "EDAD"]).sum()
59
+ data_f3 = data_f3.loc[:,data_f3.columns[0]].unstack(level=1).replace(np.nan, 0)
60
+ st.write(data_f3)
61
+
62
+
63
+ fig = go.Figure()
64
+ for i in list(data_f3.index):
65
+ fig.add_trace(go.Scatter(
66
+ x=list(data_f3.columns), y=list(data_f3.loc[i,:]),
67
+ mode='lines',
68
+ line=dict(width=0.5),
69
+ stackgroup='one',
70
+ groupnorm='percent' # sets the normalization for the sum of the stackgroup
71
+ ))
72
+
73
+ fig.update_layout(
74
+ showlegend=True,
75
+ xaxis_type='category',
76
+ yaxis=dict(
77
+ type='linear',
78
+ range=[1, 100],
79
+ ticksuffix='%'))
80
+
81
+ st.plotly_chart(fig, use_container_width=True)
82
+
83
+ else:
84
+ data_f = data.groupby([ variable, "EDAD"]).count()
85
+ data_f2 = data_f.loc[:,data_f.columns[0]].unstack(level=1).replace(np.nan, 0)
86
+ st.write(data_f2)
87
+ fig = go.Figure()
88
+ for i in list(data_f2.index):
89
+ fig.add_trace(go.Scatter(
90
+ x=list(data_f2.columns), y=list(data_f2.loc[i,:]),
91
+ mode='lines',
92
+ line=dict(width=0.5),
93
+ stackgroup='one',
94
+ groupnorm='percent' # sets the normalization for the sum of the stackgroup
95
+ ))
96
+
97
+ fig.update_layout(
98
+ showlegend=True,
99
+ xaxis_type='category',
100
+ yaxis=dict(
101
+ type='linear',
102
+ range=[1, 100],
103
+ ticksuffix='%'))
104
+
105
+ st.plotly_chart(fig, use_container_width=True)
106
+
107
+
108
+ # pr = data_f2.profile_report()
109
+
110
+ # st_profile_report(data_f2)
111
+
112
+ def transform_df(scraping_df):
113
+ # Extract numbers from string
114
+ # Change datatype
115
+ # Add 'Comuna' and 'Región'
116
+ scraping_df[["Comuna"]] = scraping_df[[
117
+ "direccion"]].applymap(lambda x: get_comuna(x))
118
+ # Scrap UF value for date
119
+ #scraping_df[["Valor UF"]] = get_UF()
120
+ return scraping_df
121
+
122
+
123
+ def get_table_excel_link(df, name):
124
+ towrite = io.BytesIO()
125
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
126
+ header=True)
127
+ towrite.seek(0) # reset pointer
128
+ file_name = 'Data' + name + '.xlsx'
129
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
130
+ name_mark = "Descargar " + name + ".xlsx"
131
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
132
+ linko = f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" ' + \
133
+ style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
134
+ return linko
135
+
136
+
137
+ def get_comuna(direction):
138
+ values = direction.split(',')
139
+ return values[-2]
140
+
141
+
142
+ def formatnum(numero):
143
+ '''
144
+ Esta función permite dar formato a los montos de saldo y valor cuota en
145
+ las cartolas.
146
+ '''
147
+ return '{:,.0f}'.format(numero).replace(",", "@").replace(".", ",").replace("@", ".")
148
+
149
+
150
+ def sim_norm():
151
+ with st.form(key='my_form'):
152
+ col1, col2 = st.beta_columns(2)
153
+ sim = col1.number_input("Nº Simulaciones", min_value=1, value=100)
154
+ vc = col2.number_input("Cuota inicial", min_value=100)
155
+ col1, col2, col3 = st.beta_columns(3)
156
+ mu = col1.number_input("µ Fondo Arriesgado", value=0.1)
157
+ sigma = col1.number_input("σ Fondo Arriesgado", value=0.1)
158
+ mu2 = col2.number_input("µ Fondo Intermedio ", value=0.05)
159
+ sigma2 = col2.number_input("σ Fondo Intermedio", value=0.05)
160
+ mu3 = col3.number_input("µ Fondo Conservador", value=-0.01)
161
+ sigma3 = col3.number_input("σ Fondo Conservador", value=0.03)
162
+ # t= col1.number_input("Periodo", value=288)
163
+ # t2 = col2.number_input("Periodo ", value=120)
164
+ # t3 = col3.number_input("Periodo ", value=72)
165
+ values = st.slider(
166
+ 'Seleccione los años de cambio de fondo', 0, 40, (33, 38))
167
+ with st.beta_expander("Ajustar parámetros de distribucion de permanencia del cliente (gamma)"):
168
+ col1, col2 = st.beta_columns(2)
169
+ alpha = col1.number_input("alpha", value=1.5)
170
+ beta = col2.number_input("lambda", value=71.1)
171
+ submit_button = st.form_submit_button(label='Actualizar')
172
+ if submit_button:
173
+ t = values[0]*12
174
+ t2 = values[1]*12-t
175
+ t3 = 480-t2-t
176
+ mu = mu / 12
177
+ mu2 = mu2 / 12
178
+ mu3 = mu3 / 12
179
+ sigma = sigma / (12**(1/2))
180
+ sigma2 = sigma2 / (12**(1/2))
181
+ sigma3 = sigma3 / (12**(1/2))
182
+ var_al = np.random.normal(mu, sigma, size=(t, sim))
183
+ var_al2 = np.random.normal(mu2, sigma2, size=(t2, sim))
184
+ var_al3 = np.random.normal(mu3, sigma3, size=(t3, sim))
185
+ simulacion = np.zeros((t + t2 + t3, sim))
186
+ simulacion[0, :] = vc
187
+ dist_gamma = stats.gamma.rvs(alpha, scale=beta, size=sim).astype(int)+1
188
+ for i in range(1, t):
189
+ simulacion[i, :] = simulacion[i - 1, :] * (1 + var_al[i-1, :])
190
+ for i in range(t, t+t2):
191
+ simulacion[i, :] = simulacion[i - 1, :] * (1 + var_al2[t-i-1, :])
192
+ for i in range(t+t2, t+t2+t3):
193
+ simulacion[i, :] = simulacion[i - 1, :] * \
194
+ (1 + var_al3[t2+t-i-1, :])
195
+ retornos = np.zeros(sim)
196
+ for j in range(sim):
197
+ ingreso = 480-dist_gamma[j]
198
+ simulacion[0:ingreso, j] = None
199
+ simulacion[ingreso:480, j] = simulacion[ingreso:480, j] * \
200
+ vc/simulacion[ingreso, j]
201
+ retorno = (simulacion[-1, j]/simulacion[ingreso, j]
202
+ )**(1/(dist_gamma[j]/12))-1
203
+ retornos[j] = retorno
204
+ df = pd.DataFrame(simulacion)
205
+ df["meses"] = list(df.index)
206
+ fig = px.line(df, x="meses", y=df.columns,
207
+ title='Simulaciones')
208
+ fig.layout.update(xaxis_rangeslider_visible=True)
209
+ fig.add_vline(x=t, line_width=3, line_dash="dash", line_color="grey")
210
+ fig.add_vline(x=t+t2, line_width=3,
211
+ line_dash="dash", line_color="grey")
212
+ fig.add_vrect(x0=0, x1=t, annotation_text="Arries",
213
+ annotation_position="top",
214
+ fillcolor="red", opacity=0.15, line_width=0)
215
+ fig.add_vrect(x0=t, x1=t+t2,
216
+ annotation_text="Inter", annotation_position="top",
217
+ fillcolor="midnightblue", opacity=0.15, line_width=0)
218
+ fig.add_vrect(x0=t + t2, x1=t + t2 + t3,
219
+ annotation_text="Cons", annotation_position="top",
220
+ fillcolor="seagreen", opacity=0.15, line_width=0)
221
+ fig.update_layout(height=600, width=950)
222
+ st.plotly_chart(fig, use_container_width=True)
223
+ st.subheader("Distribución de duracion de clientes")
224
+ df_in = pd.DataFrame(dist_gamma//12, columns=["ingreso"])
225
+ fig = px.histogram(df_in, x="ingreso", nbins=40)
226
+ fig.add_vline(x=(dist_gamma//12).mean(), line_width=3,
227
+ line_dash="dash", line_color="midnightblue")
228
+ col1, col2 = st.beta_columns((3, 1))
229
+ col1.plotly_chart(fig, use_container_width=True)
230
+ col2.title(" ")
231
+ col2.header("µ = "+str((dist_gamma//12).mean())[0:4] + " años")
232
+ col2.subheader("σ = "+str((dist_gamma//12).std())[0:4] + " años")
233
+ st.subheader("Distribución de retorno anual")
234
+ col1, col2 = st.beta_columns((3, 1))
235
+ df_ret = pd.DataFrame(retornos, columns=["retornos"])
236
+ col2.title(" ")
237
+ col2.header("µ = "+str((retornos.mean()*100))[0:4] + "%")
238
+ col2.subheader("σ = "+str((retornos.std())*100)[0:4] + "%")
239
+ fig2 = px.histogram(df_ret, x="retornos", nbins=50)
240
+ retorno_fc = (1.053)*(1.0312)-1
241
+ if retornos.mean() > 0.0312:
242
+ posicion1 = "top right"
243
+ posicion2 = "top left"
244
+ else:
245
+ posicion2 = "top right"
246
+ posicion1 = "top left"
247
+ fig2.add_vline(x=retornos.mean(), line_width=3, line_dash="dash",
248
+ line_color="midnightblue", annotation_font_color="midnightblue",
249
+ annotation_position=posicion1,
250
+ annotation_text=str(round(retornos.mean()*100, 1))+"%")
251
+ fig2.add_vline(x=0.0312, line_width=3, line_dash="dash",
252
+ annotation_font_color="red",
253
+ annotation_position=posicion2,
254
+ line_color="red", annotation_text="3,12%")
255
+ fig2.add_vline(x=retorno_fc, line_width=3, line_dash="dash",
256
+ annotation_font_color="green",
257
+ annotation_position=posicion2,
258
+ line_color="green", annotation_text=str(round(retorno_fc, 2)*100)+"%")
259
+ fig2.add_vline(x=0.00, line_width=3, line_dash="dash",
260
+ line_color="yellow")
261
+ col1.plotly_chart(fig2, use_container_width=True)
262
+ col1, col2 = st.beta_columns((1, 8))
263
+ col2.write(str(round(sum(df_ret["retornos"] > 0.00)/len(df_ret)*100, 0)) +
264
+ "%: Probabilidad de que un clientes tenga retorno mayor a 0%")
265
+ col2.write(str(round(sum(df_ret["retornos"] > 0.0312)/len(df_ret)*100, 0)) +
266
+ "%: Probabilidad de que un clientes tenga un retorno mayor a 3,12% (Inflación)")
267
+ col2.write(str(round(sum(df_ret["retornos"] > retorno_fc)/len(df_ret)*100, 0)) +
268
+ "%: Probabilidad de que un clientes tenga retorno mayor a "+str(round(retorno_fc, 2)*100)+"% (Fondo C)")
269
+
270
+
271
+ def sim_2():
272
+ with st.form(key='my_form'):
273
+ col1, col2 = st.beta_columns(2)
274
+ sim = col1.number_input("Nº Simulaciones", min_value=1, value=100)
275
+ vc = col2.number_input("Cuota inicial", min_value=100)
276
+ col1, col2, col3 = st.beta_columns(3)
277
+ mu = col1.number_input("µ Fondo Arriesgado", value=0.1)
278
+ sigma = col1.number_input("σ Fondo Arriesgado", value=0.1)
279
+ mu2 = col2.number_input("µ Fondo Intermedio ", value=0.05)
280
+ sigma2 = col2.number_input("σ Fondo Intermedio", value=0.05)
281
+ mu3 = col3.number_input("µ Fondo Conservador", value=-0.01)
282
+ sigma3 = col3.number_input("σ Fondo Conservador", value=0.03)
283
+ values = st.slider('Seleccione los años de cambio de fondo', 0, 40,
284
+ (33, 38))
285
+ with st.beta_expander("Ajustar parámetros de distribucion de permanencia del cliente (gamma)"):
286
+ col1, col2 = st.beta_columns(2)
287
+ alpha = col1.number_input("alpha", value=1.5)
288
+ beta = col2.number_input("lambda", value=71.1)
289
+ submit_button = st.form_submit_button(label='Actualizar')
290
+ if submit_button:
291
+ t = values[0]*12
292
+ t2 = values[1]*12-t
293
+ t3 = 480-t2-t
294
+ mu = mu / 12
295
+ mu2 = mu2 / 12
296
+ mu3 = mu3 / 12
297
+ sigma = sigma / (12 ** (1/2))
298
+ sigma2 = sigma2 / (12 ** (1/2))
299
+ sigma3 = sigma3 / (12 ** (1/2))
300
+ var_al = np.random.normal(mu, sigma, size=(t, sim))
301
+ var_al2 = np.random.normal(mu2, sigma2, size=(t2, sim))
302
+ var_al3 = np.random.normal(mu3, sigma3, size=(t3, sim))
303
+ simulacion = np.zeros((t + t2 + t3, sim))
304
+ simulacion[0, :] = vc
305
+ dist_gamma = stats.gamma.rvs(alpha, scale=beta, size=sim).astype(int)+1
306
+ for i in range(1, t):
307
+ simulacion[i, :] = simulacion[i - 1, :] * (1 + var_al[i-1, :])
308
+ for i in range(t, t+t2):
309
+ simulacion[i, :] = simulacion[i - 1, :] * (1 + var_al2[t-i-1, :])
310
+ for i in range(t+t2, t+t2+t3):
311
+ simulacion[i, :] = simulacion[i - 1, :] * \
312
+ (1 + var_al3[t2+t-i-1, :])
313
+ retornos = np.zeros(sim)
314
+ for j in range(sim):
315
+ ingreso = 480-dist_gamma[j]
316
+ simulacion[0:ingreso, j] = None
317
+ simulacion[ingreso:480, j] = simulacion[ingreso:480, j] * \
318
+ vc/simulacion[ingreso, j]
319
+ retorno = (simulacion[-1, j]/simulacion[ingreso, j]
320
+ )**(1/(dist_gamma[j]/12))-1
321
+ retornos[j] = retorno
322
+ df = pd.DataFrame(simulacion)
323
+ df["meses"] = list(df.index)
324
+ fig = px.line(df, x="meses", y=df.columns,
325
+ title='Simulaciones')
326
+ fig.layout.update(xaxis_rangeslider_visible=True)
327
+ fig.add_vline(x=t, line_width=3, line_dash="dash", line_color="grey")
328
+ fig.add_vline(x=t+t2, line_width=3, line_dash="dash",
329
+ line_color="grey")
330
+ fig.add_vrect(x0=0, x1=t, annotation_text="Arries",
331
+ annotation_position="top",
332
+ fillcolor="red", opacity=0.15, line_width=0)
333
+ fig.add_vrect(x0=t, x1=t+t2,
334
+ annotation_text="Inter", annotation_position="top",
335
+ fillcolor="midnightblue", opacity=0.15, line_width=0)
336
+ fig.add_vrect(x0=t + t2, x1=t + t2 + t3,
337
+ annotation_text="Cons", annotation_position="top",
338
+ fillcolor="seagreen", opacity=0.15, line_width=0)
339
+ fig.update_layout(height=600, width=950)
340
+ st.plotly_chart(fig, use_container_width=True)
341
+ sigma_sim1 = np.random.normal(sigma, 0.009, size=480)
342
+ sigma_sim2 = np.random.normal(sigma2, 0.004, size=480)
343
+ sigma_sim3 = np.random.normal(sigma3, 0.001, size=480)
344
+ sigma_comb = np.zeros(480)
345
+ sigma_comb[0:t] = sigma_sim1[0:t]
346
+ sigma_comb[t:t+t2] = sigma_sim2[t:t+t2]
347
+ sigma_comb[t+t2:480] = sigma_sim3[t+t2:480]
348
+ sigma_comb2 = np.zeros(480)
349
+ retorno_comb = np.zeros(480)
350
+ for i in range(t):
351
+ sigma_comb2[i] = sigma_sim1[i] * (1-i/t) + sigma_sim2[i] * i/t
352
+ retorno_comb[i] = mu * (1-i/t) + mu2 * i/t
353
+ for j in range(480-t):
354
+ sigma_comb2[t + j] = sigma_sim2[t + j] * \
355
+ (1-j/(480-t)) + sigma_sim3[t + j] * j/(480-t)
356
+ retorno_comb[i] = mu2 * (1-j/(480-t)) + mu3 * j/(480-t)
357
+ dfsig = pd.DataFrame(sigma_sim1, columns=["sig"])
358
+ dfsig["mes"] = list(dfsig.index)
359
+ dfsig["sigma inter"] = sigma_sim2
360
+ dfsig["sigma cons"] = sigma_sim3
361
+ dfsig["sigma por periodos"] = sigma_comb
362
+ dfsig["sigma combinacion lineal"] = sigma_comb2
363
+ dfsig["sigma combinacion lineal"] = dfsig["sigma combinacion lineal"].abs()
364
+ var_al_comb = np.zeros(480)
365
+ patr_al_comb = np.zeros(480)
366
+ patr_al_comb[0] = vc
367
+ for i in range(1, 480):
368
+ var_al_comb[i] = np.random.normal(
369
+ retorno_comb[i],
370
+ dfsig["sigma combinacion lineal"].iloc[i],
371
+ size=1)
372
+ patr_al_comb[i] = patr_al_comb[i-1]*(1 + var_al_comb[i-1])
373
+ ingreso = 480-dist_gamma[0]
374
+
375
+ data_comb = pd.DataFrame(patr_al_comb, columns=["Precio"])
376
+ data_comb["mes"] = list(data_comb.index)
377
+ data_comb = data_comb[data_comb["mes"] >= ingreso]
378
+ data_comb["Precio"] = data_comb["Precio"]/data_comb.iloc[0]["Precio"]
379
+ fig2 = px.line(dfsig, x='mes', y=dfsig.columns,
380
+ title='Simulaciones')
381
+ st.plotly_chart(fig2)
382
+ fig3 = px.line(data_comb, x='mes', y=data_comb.columns,
383
+ title='Simulaciones')
384
+ st.plotly_chart(fig3)
385
+
386
+
387
+ def sim_inmob():
388
+ url = """postgresql://tbgxsndupdarfp:5578576bc884e31a4f7e117a66a9dad8b13917e6a5262d85ff20f1f69cb4bf49@ec2-52-205-45-219.compute-1.amazonaws.com:5432/db5ktai215krcv"""
389
+ engine = create_engine(url, echo=False)
390
+ data = pd.read_sql_query("SELECT * FROM Scraping_inmob", con=engine)
391
+ data = transform_df(data)
392
+ col1, col2 = st.beta_columns((0.65, 1))
393
+ placeholder = st.empty()
394
+ placeholder2 = st.empty()
395
+ placeholder3 = st.empty()
396
+ placeholder4 = st.empty()
397
+ dist_gamma = stats.gamma.rvs(1, scale=250000, size=2965)
398
+ dist_norm = np.random.normal(734874, 1250, size=2965)
399
+ data_hist = data[data["mercado"] == "venta"]
400
+ data_hist = data_hist[data_hist["valor_peso"]
401
+ < 400000000]["valor_peso"] * 0.2
402
+ fig2 = go.Figure()
403
+ fig3 = go.Figure()
404
+ fig4 = go.Figure()
405
+ fig2.add_trace(go.Histogram(x=dist_norm, name='Dist Ingreso'))
406
+ # fig2.add_vline(x=data_hist.mean(), line_width=3, line_dash="dash", line_color="darkred")
407
+ # fig2.add_vline(x=dist_gamma.mean(), line_width=3, line_dash="dash", line_color="darkblue")
408
+ fig3.add_trace(go.Histogram(x=data_hist, name='Data real'))
409
+ a = sorted(data_hist)
410
+ b = sorted(dist_norm)
411
+ dist_periodo = [(x)/y for x, y in zip(a, b)]
412
+ dist_periodo = [i for i in dist_periodo if i < 480]
413
+ fig4.add_trace(go.Histogram(x=dist_periodo, name='Dist periodo'))
414
+ # Overlay both histograms
415
+ # fig2.update_layout(barmode='overlay')
416
+ # Reduce opacity to see both histograms
417
+ fig2.update_traces(opacity=0.75)
418
+ #fig2 = px.histogram((data_hist), x='valor_peso', color_discrete_sequence=['indianred'])
419
+ placeholder2.plotly_chart(fig2, use_container_width=True)
420
+ placeholder.subheader("µ Capacidad de ahorro: $" +
421
+ formatnum(dist_norm.mean()))
422
+ placeholder4.plotly_chart(fig3, use_container_width=True)
423
+ placeholder3.subheader("µ Pie vivienda: $" + formatnum(data_hist.mean()))
424
+ st.plotly_chart(fig4, use_container_width=True)
425
+ st.subheader("µ Period: " + formatnum(np.array(dist_periodo).mean()))
426
+ df = pd.DataFrame([a, b, dist_periodo])
427
+ df2 = df.T
428
+ st.markdown(get_table_excel_link(df2[df2[2] < 480], "Distribucion"),
429
+ unsafe_allow_html=True)
430
+ data_hist = data[data["mercado"] == "venta"]
431
+ data_hist = data_hist[data_hist["valor_peso"] > 40000000]
432
+ data_hist = data_hist[data_hist["valor_peso"]
433
+ < 1000000000]["valor_peso"] * 0.2
434
+ fig2 = px.histogram((data_hist), x='valor_peso')
435
+
436
+
437
+ def sim_ingreso_clientes():
438
+ with st.form(key='my_form'):
439
+ col1, col2 = st.beta_columns(2)
440
+ clientes1 = col1.number_input("Clientes nuevos año 1", value=1250)
441
+ clientes2 = col2.number_input("Clientes nuevos año 2", value=6750)
442
+ clientes3 = col1.number_input("Clientes nuevos año 3", value=17000)
443
+ clientes4 = col2.number_input("Clientes nuevos año 4", value=17000)
444
+ clientes5 = col1.number_input("Clientes nuevos año 5", value=8000)
445
+ col1, col2 = st.beta_columns(2)
446
+ cap_ahorro = col1.number_input("Capacidad de ahorro", 735000)
447
+ de_cap = col2.number_input("Desviacion estandar C.A.", 1250)
448
+ submit_button = st.form_submit_button(label='Actualizar')
449
+ if submit_button:
450
+ clientesm1 = clientes1/12
451
+ clientesm2 = clientes2/12
452
+ clientesm3 = clientes3/12
453
+ clientesm4 = clientes4/12
454
+ clientesm5 = clientes5/12
455
+ porc_mult = 0.46
456
+ porc_cp = 0.19
457
+ porc_lp = 0.35
458
+ inmob = np.zeros(60)
459
+ a = np.zeros(60)
460
+ b = np.zeros(60)
461
+ c = np.zeros(60)
462
+ cp = np.zeros(60)
463
+ lp = np.zeros(60)
464
+ inmob[0] = int(clientesm1 * porc_mult)
465
+ cp[0] = int(clientesm1 * porc_cp)
466
+ lp[0] = int(clientesm1 * porc_lp)
467
+ for i in range(1, 60):
468
+ if i < 12:
469
+ inmob[i] =int( clientesm1 * porc_mult + inmob[i-1])
470
+ cp[i] = int(clientesm1 * porc_cp + cp[i-1])
471
+ lp[i] = int(clientesm1 * porc_lp + lp[i-1])
472
+ a[i] = cp[i]
473
+ b[i] = lp[i]
474
+ c[i] = inmob[i]
475
+ elif i < 24:
476
+ inmob[i] = int(clientesm2 * porc_mult + inmob[i-1])
477
+ cp[i] = int(clientesm2 * porc_cp + cp[i-1]) + clientesm1 * porc_cp*0.8
478
+ lp[i] = int(clientesm2 * porc_lp + lp[i-1])
479
+ a[i] = cp[i]
480
+ b[i] = lp[i] + c[i-12]
481
+ c[i] = inmob[i] - c[i-12]
482
+ elif i < 36:
483
+ inmob[i] = int(clientesm3 * porc_mult + inmob[i-1])
484
+ cp[i] = int(clientesm3 * porc_cp + cp[i-1]) + clientesm2 * porc_cp*0.8
485
+ lp[i] = int(clientesm3 * porc_lp + lp[i-1])
486
+ a[i] = cp[i]
487
+ b[i] = lp[i] + c[i-24] + c[i-12]
488
+ c[i] = inmob[i] - c[i-24] - c[i-12]
489
+ elif i < 48:
490
+ inmob[i] = int(clientesm4 * porc_mult + inmob[i-1])
491
+ cp[i] = int(clientesm4 * porc_cp + cp[i-1]) - clientesm3 * porc_cp*0.8
492
+ lp[i] = int(clientesm4 * porc_lp + lp[i-1])
493
+ a[i] = cp[i] + c[i-36]
494
+ b[i] = lp[i] + c[i-24] + c[i-12]
495
+ c[i] = inmob[i] - c[i-24] - c[i-12] - c[i-36]
496
+ elif i < 60:
497
+ inmob[i] = int(clientesm5 * porc_mult + inmob[i-1])
498
+ cp[i] = int(clientesm5 * porc_cp + cp[i-1]) + clientesm4 * porc_cp*0.8
499
+ lp[i] = int(clientesm5 * porc_lp + lp[i-1])
500
+ a[i] = cp[i] + c[i-36]
501
+ b[i] = lp[i] + c[i-24] + c[i-12]
502
+ c[i] = inmob[i] - c[i-24] - c[i-12] - c[i-36] - c[i-48]
503
+
504
+ inmob_res = np.zeros(60)
505
+ cp_res = np.zeros(60)
506
+ lp_res = np.zeros(60)
507
+ a_res = np.zeros(60)
508
+ b_res = np.zeros(60)
509
+ c_res = np.zeros(60)
510
+ for i in range(1, 60):
511
+ if i<12:
512
+ pass
513
+ elif i < 24:
514
+ cp_res[i] = - clientes1 * porc_cp*0.2
515
+ b_res[i] = clientes1 * porc_mult
516
+ c_res[i] = -clientes1 * porc_mult
517
+ elif i < 36:
518
+ cp_res[i] = - clientes2 * porc_cp * 0.2
519
+ b_res[i] = clientes2 * porc_mult
520
+ c_res[i] = -clientes2 * porc_mult
521
+ elif i < 48:
522
+ cp_res[i] = - clientes3 * porc_cp * 0.2
523
+ a_res[i] = clientes1 * porc_mult * 3
524
+ b_res[i] = clientes3 * porc_mult - clientes1 * 3 * porc_mult
525
+ c_res[i] = -clientes3 * porc_mult
526
+ elif i < 60:
527
+ cp_res[i] = - clientes4 * porc_mult * 0.2
528
+ a_res[i] = clientes2 * 3 *porc_mult
529
+ b_res[i] = clientes3 * porc_mult - clientes2 * 3 *porc_mult
530
+ c_res[i] = -clientes3 * porc_mult
531
+ st.write(cp-cp_res)
532
+ inmob[0] = int(clientesm1 * porc_mult)
533
+ cp[0] = int(clientesm1 * porc_cp)
534
+ lp[0] = int(clientesm1 * porc_lp)
535
+ anual = np.zeros((5,4))
536
+ anual_aum = np.zeros((5,4))
537
+ for i in range(5):
538
+ anual[i, 0] = int(sum(a[i*12:(i+1)*12]))
539
+ anual[i, 1] = int(sum(b[i*12:(i+1)*12]))
540
+ anual[i, 2] = int((sum(c[i*12:(i+1)*12])))
541
+ anual[:,3] = anual[:,0] + anual[:,1] + anual[:,2]
542
+ for i in range(5):
543
+ anual_aum[i, 0] = sum(((a - a_res)*cap_ahorro)[0:(i+1)*12])
544
+ anual_aum[i, 1] = sum(((b - b_res)*cap_ahorro)[0:(i+1)*12])
545
+ anual_aum[i, 2] = sum(((c - c_res)*cap_ahorro)[0:(i+1)*12])
546
+ anual_aum[:,3] = anual_aum[:,0] + anual_aum[:,1] + anual_aum[:,2]
547
+ data = pd.DataFrame([cp, lp, inmob, (cp - cp_res)*cap_ahorro, lp*cap_ahorro,
548
+ (inmob - inmob_res)*cap_ahorro])
549
+
550
+ anual[:,3] = anual[:,0] + anual[:,1] + anual[:,2]
551
+ cambios = np.zeros(5)
552
+ cambios[0] = 0
553
+ cambios[1] = int(clientes1 * porc_mult)
554
+ cambios[2] = int(clientes2* porc_mult)
555
+ cambios[3] = int((clientes3 + clientes1)* porc_mult)
556
+ cambios[4] = int((clientes2 + clientes4) * porc_mult)
557
+ retiros = np.zeros(5)
558
+ retiros[0] = 0
559
+ retiros[1] = int(clientes1 * porc_cp)
560
+ retiros[2] = int(clientes2 * porc_cp)
561
+ retiros[3] = int(clientes3 * porc_cp)
562
+ retiros[4] = int(clientes4 * porc_cp +clientes1 * porc_cp*porc_mult)
563
+ clientes_a = np.zeros(5)
564
+ clientes_b = np.zeros(5)
565
+ clientes_c = np.zeros(5)
566
+ clientes_a[0] = int(clientes1 * porc_cp)
567
+ clientes_b[0] = int(clientes1 * porc_lp)
568
+ clientes_c[0] = int(clientes1 * porc_mult)
569
+
570
+ clientes_a[1] = int(clientes2 * porc_cp + clientes1 * porc_cp * 0.8)
571
+ clientes_b[1] = int(clientes1 * porc_lp + clientes2 * porc_lp + clientes1 * porc_mult)
572
+ clientes_c[1] = int(clientes2 * porc_mult)
573
+
574
+ clientes_a[2] = int(clientes3 * porc_cp + clientes2 * porc_cp * 0.8 + clientes1 * porc_cp * 0.8)
575
+ clientes_b[2] = int(clientes_b[1] + clientes2 * porc_mult + clientes3 * porc_lp )
576
+ clientes_c[2] = int(clientes3 * porc_mult)
577
+
578
+ clientes_a[3] = int(clientes4 * porc_cp + clientes1 * porc_mult + clientes2 * porc_cp * 0.8 + clientes1 * porc_cp * 0.8 + clientes3 * porc_cp * 0.8)
579
+ clientes_b[3] = int(clientes_b[2] - clientes1 * porc_mult + clientes3 * porc_mult + clientes4 * porc_lp)
580
+ clientes_c[3] = int(clientes4 * porc_mult)
581
+
582
+ clientes_a[4] = int(clientes5 * porc_cp + clientes1 * porc_mult + clientes2 * porc_mult + clientes4 *0.8* porc_cp + clientes2 * porc_cp * 0.8 + clientes1 * porc_cp * 0.8 + clientes3 * porc_cp * 0.8)
583
+ clientes_b[4] = int(clientes_b[3] - clientes2 * porc_mult + clientes4 * porc_mult + clientes5 * porc_lp )
584
+ clientes_c[4] = int(clientes5 * porc_mult)
585
+
586
+
587
+
588
+ data2 = pd.DataFrame(anual, columns = ["Depositos a", "Depositos b", "Depositos c", "Dep Total"])
589
+ data3 = pd.DataFrame(anual_aum, columns = ["a AUM", "b AUM", "c Aum", "Aum Total"])
590
+ data4 = pd.DataFrame([a,b,c])
591
+ st.write(data4)
592
+ data = data.T
593
+ data4 = data4.T
594
+ data4.columns = ["Fondo A", "Fondo B", "Fondo C"]
595
+ data3["Cambios"] = cambios
596
+ data3["Retiros"] = retiros
597
+ data3["Clientes a"] = clientes_a
598
+ data3["Clientes b"] = clientes_b
599
+ data3["Clientes c"] = clientes_c
600
+ data3["Dep totales"] = data2["Dep Total"]
601
+ fig = px.line(data4, x=data4.index, y=data4._)
602
+ st.plotly_chart(fig, use_container_width=True)
603
+ st.write(data3.T)
604
+ st.markdown(get_table_excel_link(data3.T, "Estimación demanda"),
605
+ unsafe_allow_html=True)
606
+
607
+
608
+ import matplotlib.pyplot as plt
609
+ import numpy as np
610
+ import streamlit as st
611
+ import time
612
+ import statistics
613
+ def simulacion_final():
614
+ import altair as alt
615
+ from altair import datum
616
+ with st.form("Form"):
617
+ cols = st.columns(3)
618
+ capital_inicial = cols[0].number_input("Capital inicial", value=1000000, format="%d")
619
+ cap_ahorro = cols[1].number_input("Capacidad de ahorro", value=750000, format='%d')
620
+ objetivo = cols[2].number_input("Objetivo", value=40000000, format="%u")
621
+
622
+ button_2 = st.form_submit_button("Comenzar simulacion")
623
+ my_bar = st.sidebar.progress(0)
624
+ progress = 0
625
+ periodo = int(objetivo/cap_ahorro)+1
626
+ periodo_cambio = int(periodo*3/5)
627
+ periodo_cambio = int(periodo*3/5)
628
+ periodo_cambio2 = int(periodo*4/5)
629
+ l_1=[capital_inicial]
630
+ l_2=[0]
631
+ l_3 = []
632
+ l_4 = []
633
+ l_5 = []
634
+ l_6 = []
635
+ volatilidad = []
636
+ drawdown = False
637
+ corte_antes = False
638
+ cambio = 0
639
+ lista2=l_1+l_2+l_3
640
+ chart_row = st.empty()
641
+ if button_2:
642
+
643
+
644
+ for j in range(1,periodo+4):
645
+ lista =np.array(l_1+l_3+l_5)
646
+ if lista[-1] > objetivo:
647
+ corte_antes = True
648
+ corte = j
649
+ periodo = j
650
+ break
651
+ else:
652
+ if j <= 12:
653
+ volatilidad.append(0)
654
+ # elif j < 12 and j >3:
655
+
656
+ # volatilidad.append(statistics.stdev((lista[1:j]/lista[0:j-1])))
657
+ else:
658
+ retornos = ((lista[j-11:j]-cap_ahorro)/lista[j-12:j-1])
659
+ volatilidad.append(statistics.stdev(retornos))
660
+ if statistics.stdev(retornos) > 0.13 and j==periodo_cambio:
661
+ drawdown=True
662
+ cambio =+ 6
663
+
664
+ if j < periodo_cambio:
665
+ sig = abs(np.random.normal(0.04,0.1))
666
+ a = np.random.normal(0.018,sig)
667
+
668
+ elif j < periodo_cambio2 and not drawdown:
669
+ sig = abs(np.random.normal(0.03,0.04))
670
+ a = np.random.normal(0.01,sig)
671
+
672
+
673
+ elif j < periodo_cambio2 and drawdown:
674
+ sig = abs(np.random.normal(0.04,0.1))
675
+ a = np.random.normal(0.018,sig)
676
+
677
+ drawdown=False
678
+ else:
679
+ sig = abs(np.random.normal(0.005,0.01))
680
+ a = np.random.normal(0,sig)
681
+
682
+
683
+ if j < (periodo_cambio + cambio):
684
+ l_1.append(l_1[j-1]*(1+a) + cap_ahorro )
685
+ l_2.append(j)
686
+
687
+ if j >= (periodo_cambio + cambio) and j <periodo_cambio2:
688
+ if (periodo_cambio + cambio) == j:
689
+ l_3.append(l_1[j-1])
690
+ l_4.append(j-1)
691
+ l_3.append(l_3[j- periodo_cambio- cambio]*(1+a) + cap_ahorro )
692
+ l_4.append(j)
693
+
694
+ if j >= periodo_cambio2:
695
+ if periodo_cambio2 == j:
696
+ l_5.append(l_3[j - periodo_cambio - cambio])
697
+ l_6.append(j-1)
698
+ l_5.append(l_5[j- periodo_cambio2]*(1+a) + cap_ahorro )
699
+ l_6.append(j)
700
+
701
+ vol =pd.DataFrame(volatilidad)
702
+ cols = st.columns(3)
703
+ col1, col2 = st.columns(2)
704
+ #st.line_chart(vol)
705
+ mas_tmpo = False
706
+ if lista[-1] < objetivo:
707
+ delta = objetivo-l_5[-1]
708
+ t_extra = int(delta/cap_ahorro)+1
709
+ periodo_ant=periodo
710
+ mas_tmpo=True
711
+ periodo = periodo + t_extra
712
+ for i in range(t_extra):
713
+ l_5.append(l_5[-1]+ cap_ahorro)
714
+ l_6.append(l_6[-1]+ 1)
715
+ lista =np.array(l_1+l_3+l_5)
716
+ col1.subheader("Analista")
717
+ col2.subheader("Cliente")
718
+
719
+
720
+ for i in range(periodo+2):
721
+ time.sleep(0.01)
722
+ if mas_tmpo==True and i == periodo_ant:
723
+ st.write(t_extra)
724
+ col2.error("Mes " + str(i) +": Te faltan " + str(t_extra) + " meses para la meta")
725
+ time.sleep(3)
726
+ if corte_antes==True and i == corte:
727
+ col2.success("Mes " + str(i) +": Felcidiades llegaste antes a la meta")
728
+ time.sleep(3)
729
+ if cambio == 6 and i==(periodo_cambio):
730
+ col1.error("Mes " + str(i) +": Estas en drawdown se recomienda esperar 6 meses más")
731
+ col2.warning("Mes " + str(i) +": Debes esperar 6 mes mas para cambiarte")
732
+ time.sleep(3)
733
+ df = pd.DataFrame()
734
+ df2 = pd.DataFrame()
735
+ df3 = pd.DataFrame()
736
+ df["Mes"]=l_2[0:i+1]
737
+ df["Valor"]=l_1[0:i+1]
738
+
739
+ if i >= (periodo_cambio+cambio):
740
+
741
+ df2["Mes"]=l_4[0:i-periodo_cambio - cambio+1]
742
+ df2["Valor"] =l_3[0:i-periodo_cambio - cambio+1]
743
+ if i >= periodo_cambio2:
744
+ df3["Mes"]=l_6[0:i-periodo_cambio2+2]
745
+ df3["Valor"] =l_5[0:i-periodo_cambio2+2]
746
+ df["Fondo"] = ["Fondo Arriesgado"]*len(df)
747
+ df2["Fondo"] = ["Fondo Intermedio"]*len(df2)
748
+ df3["Fondo"] = ["Fondo Conservador"]*len(df3)
749
+
750
+ df_f = pd.concat([df,df2, df3])
751
+
752
+ df_f["Ahorro"] = df_f["Mes"]*cap_ahorro + capital_inicial
753
+ if i == (periodo_cambio+cambio):
754
+ col2.success("Mes " + str(i) +": Debes cambiarte al Fondo Intermedio")
755
+ time.sleep(3)
756
+ if i == periodo_cambio2:
757
+ col2.success("Mes " + str(i) +": Debes cambiarte al Fondo Conservador")
758
+ time.sleep(3)
759
+ fig = alt.Chart(df_f).mark_area(opacity=0.6).encode(
760
+ x=alt.X('Mes',
761
+ scale=alt.Scale(domain=(0, periodo - 1))
762
+ ),
763
+ y=alt.X('Valor',
764
+ scale=alt.Scale(domain=(0, max(lista)*1.1))
765
+ ),
766
+ color=alt.Color("Fondo", scale=alt.Scale(scheme='pastel1'))
767
+ )
768
+ bar = fig.mark_bar().encode(y='Ahorro')
769
+
770
+
771
+ chart_row.altair_chart(bar + fig, use_container_width=True)
772
+
773
+ my_bar.empty()
774
+ # from st_card import st_card
775
+ # with cols[0]:
776
+ # st_card('Capital proyectado', value=df_f.iloc[-1]["Valor"], show_progress=True)
777
+ # with cols[1]:
778
+ # st_card('Ganancia proyectada', value = df_f.iloc[-1]["Valor"] - df_f.iloc[-1]["Ahorro"],
779
+ # delta=round((df_f.iloc[-1]["Valor"]/df_f.iloc[-1]["Ahorro"]-1)*100,0) ,
780
+ # use_percentage_delta=True, delta_description='de retorno')
781
+ # with cols[2]:
782
+ # st_card('Meses', value=int(df_f.iloc[-1]["Mes"]), delta=periodo_cambio, delta_description='En el Fondo Arriesgado')
783
+ # st.write(df_f)
784
+ import streamlit.components.v1 as components
785
+ def candidatos():
786
+ html_str ="""
787
+ <!DOCTYPE html>
788
+ <html lang="es">
789
+ <head>
790
+ <title>D3.js - Mapas</title>
791
+ <meta charset="utf-8"/>
792
+ <!-- d3 😍-->
793
+ <script src="https://d3js.org/d3.v7.min.js"></script>
794
+ <!--nuestro estilo -->
795
+ <link type="text/css" rel="stylesheet" href="style.css"/>
796
+ </head>
797
+ <body>
798
+ <h1>
799
+ Mapa por región de votos a Gabriel Boric
800
+ </h1>
801
+ <p>
802
+ <u>Fuente: https://www.futuro.cl/2021/11/elecciones-presidenciales-chile-2021-resultados-region-por-region-en-vivo/</u>
803
+ </p>
804
+ <div>
805
+ <div id="viz1", style = "width:50%">
806
+ <svg id="geoOrthographic1"></svg>
807
+ </div>
808
+ <script>
809
+ //Nos sirve para poder cargar los archivos y luego ejecutar createMap
810
+ Promise
811
+ .all([
812
+ d3.json('chile.geojson'),
813
+ d3.json('chile.geojson')
814
+ ])
815
+ .then(resolve => {
816
+ createMap1(resolve[1]);
817
+ createMap2(resolve[0]);
818
+ });
819
+ //creamos el mapa2
820
+ function createMap1(countries) {
821
+ const viz1 = d3.select("#viz1");
822
+ const ancho = viz1.style("width").substring(0, viz1.style("width").length - 2) - 10;
823
+ console.log("Ancho: " + ancho);
824
+ //como proyectamos lo que vamos a dibujar
825
+ //https://github.com/d3/d3-geo/blob/master/README.md#d3-geo
826
+ //https://github.com/d3/d3-geo-projection#geoConicEqualArea
827
+ const projection = d3.geoMercator()
828
+ //que tan cercano
829
+ .scale(550)
830
+ // .translate([ancho / 2, 250])
831
+ //desde el centro, lo podemos mover
832
+ .center([-55.6, -40]);
833
+ //definimos nuestro geoPath, lo que queremos dibujar
834
+ const geoPath = d3.geoPath().projection(projection);
835
+ //solo datos
836
+ const poblacion = [
837
+ {comuna: "Puente Alto", cantidad: 31.07},
838
+ {comuna: "Río Ibáñez", cantidad: 25},
839
+ {comuna: "Tocopilla", cantidad: 20.67},
840
+ {comuna: "Juan Fernández", cantidad: 28.12},
841
+ {comuna: "Caldera", cantidad: 19.24},
842
+ {comuna: "Castro", cantidad: 20.43},
843
+ {comuna: "Cañete", cantidad: 19.09},
844
+ {comuna: "La Unión", cantidad: 23.05},
845
+ {comuna: "Iquique", cantidad: 18.27},
846
+ {comuna: "San Esteban", cantidad: 28.12},
847
+ {comuna: "Putre", cantidad: 17.79},
848
+ {comuna: "Río Hurtado", cantidad: 25.92},
849
+ {comuna: "Torres del Paine", cantidad: 30.64},
850
+ {comuna: "Carahue", cantidad: 16.58},
851
+ {comuna: "Pelluhue", cantidad: 19.58},
852
+ {comuna: "Malloa", cantidad: 24.14},
853
+ ];
854
+ //geoArea nos da el area dado un GeoJson
855
+ //extent nos devuelve el minimo y maximo valor
856
+ const realFeatureSize = d3.extent(poblacion, function (d) {
857
+ return +d.cantidad
858
+ });
859
+ console.log("Mínimo y Máximo: ");
860
+ console.log(realFeatureSize);
861
+ //hacemos un escala para los colores
862
+ //veamos cual es el rango
863
+ //https://github.com/d3/d3-scale#scaleQuantize
864
+ const newFeatureColor = d3.scaleQuantize()
865
+ .domain(realFeatureSize)
866
+ .range(['#fee0d2','#fc9272','#de2d26']);
867
+ //Nada nuevo, aqui hacemos el dibujo
868
+ d3.select("#geoOrthographic1").selectAll("path")
869
+ .data(countries.features).enter()
870
+ .append("path")
871
+ .attr("d", geoPath)
872
+ .attr("id", d => d.id)
873
+ .attr("class", "countries")
874
+ .style("fill", d => {
875
+ //comentar la linea de abajo para ver que hace el resto
876
+ //return "grey"
877
+ console.log(d.properties.NOM_COM);
878
+ let poblacionEncontrada;
879
+ poblacion.forEach(function (e) {
880
+ console.log(d.properties.NOM_COM);
881
+ console.log(e.comuna);
882
+ if (e.comuna === d.properties.NOM_COM) {
883
+ poblacionEncontrada = e.cantidad;
884
+ }
885
+ });
886
+ return newFeatureColor(poblacionEncontrada)
887
+ })
888
+ .style("stroke", d => d3.rgb(newFeatureColor(d3.geoArea(d))).darker());
889
+ // //generamos la "grilla"
890
+ // const graticule = d3.geoGraticule();
891
+ //
892
+ // //dibujamos la grilla
893
+ // d3.select("#geoOrthographic1").insert("path", "path.countries")
894
+ // .datum(graticule)
895
+ // .attr("class", "graticule line")
896
+ // .attr("d", geoPath);
897
+ const zoom = d3.zoom()
898
+ .scaleExtent([1, 8])
899
+ .on('zoom', function (event) {
900
+ d3.select("#geoOrthographic1").selectAll('path')
901
+ .attr('transform', event.transform);
902
+ });
903
+ d3.select("#geoOrthographic1").call(zoom);
904
+ }
905
+ //creamos el mapa
906
+ //Nos sirve para poder cargar los archivos y luego ejecutar createMap
907
+ //creamos el mapa2
908
+ function createMap2(countries) {
909
+ const viz1 = d3.select("#viz2");
910
+ const ancho = viz1.style("width").substring(0, viz1.style("width").length - 2) - 10;
911
+ console.log("Ancho: " + ancho);
912
+ //como proyectamos lo que vamos a dibujar
913
+ //https://github.com/d3/d3-geo/blob/master/README.md#d3-geo
914
+ //https://github.com/d3/d3-geo-projection#geoConicEqualArea
915
+ const projection = d3.geoMercator()
916
+ //que tan cercano
917
+ .scale(550)
918
+ // .translate([ancho / 2, 250])
919
+ //desde el centro, lo podemos mover
920
+ .center([-55.6, -40]);
921
+ //definimos nuestro geoPath, lo que queremos dibujar
922
+ const geoPath = d3.geoPath().projection(projection);
923
+ //solo datos
924
+ const poblacion = [
925
+ {comuna: "Puente Alto", cantidad: 31.07},
926
+ {comuna: "Río Ibáñez", cantidad: 25},
927
+ {comuna: "Tocopilla", cantidad: 20.67},
928
+ {comuna: "Juan Fernández", cantidad: 28.12},
929
+ {comuna: "Caldera", cantidad: 19.24},
930
+ {comuna: "Castro", cantidad: 20.43},
931
+ {comuna: "Cañete", cantidad: 19.09},
932
+ {comuna: "La Unión", cantidad: 23.05},
933
+ {comuna: "Iquique", cantidad: 18.27},
934
+ {comuna: "San Esteban", cantidad: 28.12},
935
+ {comuna: "Putre", cantidad: 17.79},
936
+ {comuna: "Río Hurtado", cantidad: 25.92},
937
+ {comuna: "Torres del Paine", cantidad: 30.64},
938
+ {comuna: "Carahue", cantidad: 16.58},
939
+ {comuna: "Pelluhue", cantidad: 19.58},
940
+ {comuna: "Malloa", cantidad: 24.14},
941
+ ];
942
+ //geoArea nos da el area dado un GeoJson
943
+ //extent nos devuelve el minimo y maximo valor
944
+ const realFeatureSize = d3.extent(poblacion, function (d) {
945
+ return +d.cantidad
946
+ });
947
+ console.log("Mínimo y Máximo: ");
948
+ console.log(realFeatureSize);
949
+ //hacemos un escala para los colores
950
+ //veamos cual es el rango
951
+ //https://github.com/d3/d3-scale#scaleQuantize
952
+ const newFeatureColor = d3.scaleQuantize()
953
+ .domain(realFeatureSize)
954
+ .range(['#fee0d2','#fc9272','#de2d26']);
955
+ //Nada nuevo, aqui hacemos el dibujo
956
+ d3.select("#geoOrthographic2").selectAll("path")
957
+ .data(countries.features).enter()
958
+ .append("path")
959
+ .attr("d", geoPath)
960
+ .attr("id", d => d.id)
961
+ .attr("class", "countries")
962
+ .style("fill", d => {
963
+ //comentar la linea de abajo para ver que hace el resto
964
+ //return "grey"
965
+ console.log(d.properties.NOM_COM);
966
+ let poblacionEncontrada;
967
+ poblacion.forEach(function (e) {
968
+ console.log(d.properties.NOM_COM);
969
+ console.log(e.comuna);
970
+ if (e.comuna === d.properties.NOM_COM) {
971
+ poblacionEncontrada = e.cantidad;
972
+ }
973
+ });
974
+ return newFeatureColor(poblacionEncontrada)
975
+ })
976
+ .style("stroke", d => d3.rgb(newFeatureColor(d3.geoArea(d))).darker());
977
+ // //generamos la "grilla"
978
+ // const graticule = d3.geoGraticule();
979
+ //
980
+ // //dibujamos la grilla
981
+ // d3.select("#geoOrthographic1").insert("path", "path.countries")
982
+ // .datum(graticule)
983
+ // .attr("class", "graticule line")
984
+ // .attr("d", geoPath);
985
+ const zoom = d3.zoom()
986
+ .scaleExtent([1, 8])
987
+ .on('zoom', function (event) {
988
+ d3.select("#geoOrthographic2").selectAll('path')
989
+ .attr('transform', event.transform);
990
+ });
991
+ d3.select("#geoOrthographic2").call(zoom);
992
+ }
993
+ //creamos el mapa1
994
+ </script>
995
+ </div>
996
+ </body>
997
+ </html>
998
+ """
999
+ components.html(html_str, height=1000)
1000
+ # def simulacion_final():
1001
+ # import altair as alt
1002
+ # from altair import datum
1003
+ # with st.form("Form"):
1004
+ # cols = st.beta_columns(3)
1005
+ # capital_inicial = cols[0].number_input("Objetivo", value=1000000, format="%d")
1006
+ # cap_ahorro = cols[1].number_input("Capacidad de ahorro", value=750000, format='%d')
1007
+ # objetivo = cols[2].number_input("Objetivo", value=40000000, format="%u")
1008
+
1009
+ # button_2 = st.form_submit_button("Comenzar simulacion")
1010
+ # l_1=[capital_inicial]
1011
+ # l_2=[0]
1012
+ # l_3=[np.nan]
1013
+ # l_4=[np.nan]
1014
+ # text=[]
1015
+
1016
+
1017
+
1018
+ # chart_row = st.empty()
1019
+ # if button_2:
1020
+ # my_bar = st.sidebar.progress(0)
1021
+ # progress = 0
1022
+ # periodo = int(objetivo/cap_ahorro)+1
1023
+ # periodo_cambio = int(periodo*3/5)
1024
+ # periodo_cambio2 = int(periodo*4/5)
1025
+
1026
+ # for j in range(1,periodo):
1027
+
1028
+ # a = np.random.normal(0.03,0.10)
1029
+ # if j <periodo_cambio:
1030
+ # l_1.append(l_1[j-1]*(1+a) + cap_ahorro )
1031
+ # l_3.append(np.nan)
1032
+ # l_4.append(np.nan)
1033
+ # text.append("")
1034
+ # elif j ==periodo_cambio:
1035
+ # l_1.append(l_1[j-1]*(1+a) + cap_ahorro )
1036
+ # l_3.append(l_1[j-1]*(1+a) + cap_ahorro )
1037
+ # l_4.append(np.nan)
1038
+ # text.append("")
1039
+ # elif j > periodo_cambio and j < periodo_cambio2 :
1040
+ # a = a/3
1041
+ # l_1.append(np.nan)
1042
+ # l_3.append(l_3[j-1]*(1+a) + cap_ahorro)
1043
+ # l_4.append(np.nan)
1044
+ # text.append("")
1045
+ # elif j == periodo_cambio2:
1046
+ # a = a/3
1047
+ # l_1.append(np.nan)
1048
+ # l_3.append(l_3[j-1]*(1+a) + cap_ahorro)
1049
+ # l_4.append(l_3[j-1]*(1+a) + cap_ahorro)
1050
+ # text.append("")
1051
+ # else:
1052
+ # a = a/5
1053
+ # l_1.append(np.nan)
1054
+ # l_3.append(np.nan)
1055
+ # l_4.append(l_4[j-1]*(1+a) + cap_ahorro)
1056
+ # text.append("")
1057
+ # l_2.append(j)
1058
+ # drawd =[]
1059
+ # for k in range(2,len(l_1)):
1060
+
1061
+ # if (l_1[k] - l_1[k-1])/(l_1[k]) < -0.01:
1062
+ # periodo_cambio1_2 = periodo_cambio + 1
1063
+ # drawd.append(k)
1064
+ # else:
1065
+ # periodo_cambio1_2=periodo_cambio
1066
+
1067
+ # for i in range(periodo):
1068
+ # progress = (i/periodo)
1069
+ # my_bar = my_bar.progress(progress)
1070
+ # time.sleep(0.001)
1071
+ # df = pd.DataFrame()
1072
+ # df["Mes"]=l_2[0:i+1]+l_2[0:i+1] + l_2[0:i+1]
1073
+ # df["Valor"]=l_1[0:i+1]+l_3[0:i+1] + l_4[0:i+1]
1074
+ # if i <= periodo_cambio:
1075
+ # df["Fondo"]=["Fondo Arriesgado"]*len(df)
1076
+ # if i in drawd:
1077
+ # st.warning("Drawdown")
1078
+ # time.sleep(2)
1079
+ # elif i > periodo_cambio and i <= periodo_cambio2:
1080
+ # df["Fondo"]=["Fondo Arriesgado"]*(periodo_cambio+1) + ["Fondo Intermedio"]*(i-periodo_cambio) + ["Fondo Arriesgado"]*(periodo_cambio + 1) + ["Fondo Intermedio"]*(i-periodo_cambio) + ["Fondo Arriesgado"]*(periodo_cambio+1) + ["Fondo Intermedio"]*(i-periodo_cambio)
1081
+ # else:
1082
+ # a = ["Fondo Arriesgado"] * periodo_cambio
1083
+ # b = ["Fondo Intermedio"] * (periodo_cambio2 - periodo_cambio-1)
1084
+ # c = ["Fondo Conservador"] * (i-periodo_cambio2)
1085
+ # d = ["Fondo Arriesgado"] * (periodo_cambio+2)
1086
+ # e = ["Fondo Intermedio"] * (periodo_cambio2 - (periodo_cambio+2))
1087
+ # f = ["Fondo Conservador"]*(i-periodo_cambio2+2)
1088
+ # df["Fondo"]= a + b + c + d + e + f + d + e + f
1089
+ # df = df.dropna()
1090
+
1091
+
1092
+
1093
+
1094
+ # if i == periodo_cambio:
1095
+ # placeholder=st.empty()
1096
+ # placeholder.info("Debes cambiarte al fondo intermedio")
1097
+ # time.sleep(3)
1098
+ # placeholder.empty()
1099
+ # if i == periodo_cambio2:
1100
+ # placeholder=st.empty()
1101
+ # placeholder.info("Debes cambiarte al fondo conservador")
1102
+ # time.sleep(3)
1103
+ # placeholder.empty()
1104
+ # # df=df.dropna()
1105
+
1106
+ # fig = alt.Chart(df).mark_area(opacity=0.6).encode(
1107
+ # x=alt.X('Mes',
1108
+ # scale=alt.Scale(domain=(0, periodo - 1))
1109
+ # ),
1110
+ # y=alt.X('Valor',
1111
+ # scale=alt.Scale(domain=(0, max(l_1+l_3+l_4)*1.1))
1112
+ # ),
1113
+ # color=alt.Color("Fondo", scale=alt.Scale(scheme='category20'))
1114
+ # )
1115
+ # if i > periodo_cambio and i <= periodo_cambio2:
1116
+ # df["Cambio"]="Cambiate al fondo intermedio"
1117
+ # text = (
1118
+ # alt.Chart(df[df["Mes"]==periodo_cambio])
1119
+ # .mark_text(dy=-25, color="black")
1120
+ # .encode(x=alt.X("Mes"), y=alt.Y("Valor"), text="Cambio")
1121
+ # )
1122
+
1123
+ # chart_row.altair_chart(fig + text, use_container_width=True)
1124
+ # if i > periodo_cambio2:
1125
+ # df["Cambio"]="Cambiate al fondo conservador"
1126
+ # text = (
1127
+ # alt.Chart(df[df["Mes"]==periodo_cambio2])
1128
+ # .mark_text(dy=-25, color="black")
1129
+ # .encode(x=alt.X("Mes"), y=alt.Y("Valor"), text="Cambio")
1130
+ # )
1131
+ # chart_row.altair_chart(fig, use_container_width=True)
1132
+ # else:
1133
+ # chart_row.altair_chart(fig, use_container_width=True)
1134
+ # cols = st.columns(3)
1135
+ # ganancia=value=l_3[-1] - cap_ahorro * l_2[-1]
1136
+ # my_bar.empty()
1137
+ # # with cols[0]:
1138
+ # # st_card('Capital proyectado', value=l_3[-1], show_progress=True)
1139
+ # # with cols[1]:
1140
+ # # st_card('Ganancia proyectada', value=ganancia, delta=round(ganancia/(cap_ahorro * l_2[-1])*100,0) ,
1141
+ # # use_percentage_delta=True, delta_description='de retorno')
1142
+ # # with cols[2]:
1143
+ # # st_card('Meses', value=l_2[-1], delta=periodo_cambio, delta_description='En el Fondo Arriesgado')
1144
+ # st.write(df)
1145
+ def prototipo_simulacion():
1146
+ # import streamlit as st
1147
+ # import time
1148
+ # import numpy as np
1149
+ # progress_bar = st.sidebar.progress(0)
1150
+ # status_text = st.sidebar.empty()
1151
+ # last_rows = np.random.randn(1, 1)
1152
+ # chart = st.line_chart(last_rows)
1153
+ # for i in range(1, 101):
1154
+ # new_rows = last_rows[-1, :] + np.random.randn(50, 1).cumsum(axis=0)
1155
+ # status_text.text("%i%% Complete" % i)
1156
+ # chart.add_rows(new_rows)
1157
+ # progress_bar.progress(i)
1158
+ # last_rows = new_rows
1159
+ # time.sleep(0.001)
1160
+
1161
+ # progress_bar.empty()
1162
+ # # Streamlit widgets automatically run the script from top to bottom. Since
1163
+ # # this button is not connected to any other logic, it just causes a plain
1164
+ # # rerun.
1165
+ # st.button("Re-run")
1166
+ # import numpy as np
1167
+ # import matplotlib.pyplot as plt
1168
+ # import matplotlib.animation as animation
1169
+ # import streamlit as st
1170
+ # import streamlit.components.v1 as components
1171
+
1172
+ # def update_line(num, data, line):
1173
+ # line.set_data(data[..., :num])
1174
+ # return line,
1175
+
1176
+ # fig = plt.figure()
1177
+
1178
+ # # Fixing random state for reproducibility
1179
+ # np.random.seed(19680801)
1180
+
1181
+ # data = np.random.rand(2, 25)
1182
+ # l, = plt.plot([], [], 'r-')
1183
+ # plt.xlim(0, 1)
1184
+ # plt.ylim(0, 1)
1185
+ # plt.xlabel('x')
1186
+ # plt.title('test')
1187
+ # line_ani = animation.FuncAnimation(fig, update_line, 25, fargs=(data, l), interval=50, blit=True)
1188
+
1189
+ # st.title("Embed Matplotlib animation in Streamlit")
1190
+ # st.markdown("https://matplotlib.org/gallery/animation/basic_example.html")
1191
+ # components.html(line_ani.to_jshtml(), height=1000)
1192
+ # import matplotlib.pyplot as plt
1193
+ # import numpy as np
1194
+ # import streamlit as st
1195
+ # import time
1196
+
1197
+ # fig, ax = plt.subplots()
1198
+
1199
+ # max_x = 5
1200
+ # max_rand = 10
1201
+
1202
+ # x = np.arange(0, max_x)
1203
+ # ax.set_ylim(0, max_rand)
1204
+ # line, = ax.plot(x, np.random.randint(0, max_rand, max_x))
1205
+ # the_plot = st.pyplot(plt)
1206
+
1207
+ # def init(): # give a clean slate to start
1208
+ # line.set_ydata([np.nan] * len(x))
1209
+
1210
+ # def animate(i): # update the y values (every 1000ms)
1211
+ # line.set_ydata(np.random.randint(0, max_rand, max_x))
1212
+ # the_plot.pyplot(plt)
1213
+
1214
+ # init()
1215
+ # for i in range(100):
1216
+ # animate(i)
1217
+ # time.sleep(0.1)
1218
+ import plotly.express as px
1219
+ from datetime import date
1220
+ from datetime import timedelta
1221
+ import numpy as np
1222
+ df = px.data.gapminder()
1223
+ cap_ahorro = 750000
1224
+ Data = pd.DataFrame()
1225
+ today =date.today()
1226
+ l=[]
1227
+ l2=[]
1228
+ l3=[]
1229
+ l4=[]
1230
+ for i in range(53):
1231
+
1232
+ for j in range(53):
1233
+ l.append(i)
1234
+ l2.append(j)
1235
+ if j<=i:
1236
+ l3.append(cap_ahorro*j)
1237
+ else:
1238
+ l3.append(0)
1239
+ if j<40:
1240
+ l4.append("Arriesgado")
1241
+ elif j<47:
1242
+ l4.append("Intermedio")
1243
+ else:
1244
+ l4.append("Conservador")
1245
+ l5 = []
1246
+ l6 = []
1247
+ Data["Mes"] = l
1248
+ Data["Ahorro"] = l2
1249
+ Data["Total"] = l3
1250
+ Data["Fondo"] = l4
1251
+ fig = px.bar(Data, x="Ahorro", y="Total", color="Fondo",
1252
+ animation_frame="Mes")
1253
+ fig.update_yaxes(range=[0, 50000000])
1254
+ fig.update_xaxes(range=[0, 53])
1255
+ st.plotly_chart(fig)
1256
+ button = st.button("Activar")
1257
+ if button:
1258
+ chart_data = pd.DataFrame()
1259
+ chart = st.area_chart(chart_data)
1260
+ for i in range(100):
1261
+ if i<70:
1262
+ chart.add_rows(pd.DataFrame([[i*cap_ahorro,0, 0]], columns=['Fondo 1', 'Fondo 2', 'Fondo 3']))
1263
+ elif i==70:
1264
+ chart.add_rows(pd.DataFrame([[i*cap_ahorro,i*cap_ahorro,0]], columns=['Fondo 1', 'Fondo 2', 'Fondo 3']))
1265
+ st.success("Debes cambiarte al fondo intermedio")
1266
+ elif i<85:
1267
+ chart.add_rows(pd.DataFrame([[0,i*cap_ahorro,0]], columns=['Fondo 1', 'Fondo 2', 'Fondo 3']))
1268
+ elif i==85:
1269
+ chart.add_rows(pd.DataFrame([[0,i*cap_ahorro,i*cap_ahorro]], columns=['Fondo 1', 'Fondo 2', 'Fondo 3']))
1270
+ st.success("Debes cambiarte al fondo arriesgado")
1271
+ else:
1272
+ chart.add_rows(pd.DataFrame([[0,0, i*cap_ahorro]], columns=['Fondo 1', 'Fondo 2', 'Fondo 3']))
1273
+ time.sleep(0.1)
1274
+
1275
+ cap_ahorro = 750000
1276
+ from plotly.subplots import make_subplots
1277
+ import plotly.graph_objects as go
1278
+ import numpy as np
1279
+ import plotly.graph_objects as go
1280
+ Frames=[]
1281
+ Frames2 =[]
1282
+
1283
+ l_1=[]
1284
+ l_2=[]
1285
+ l_3=[]
1286
+ text=[]
1287
+ fig = make_subplots(rows=1, cols=1, subplot_titles = ('Subplot (1,1)'))
1288
+ for i in range(53):
1289
+ if i <40:
1290
+ l_1.append(cap_ahorro*i)
1291
+ l_3.append(np.nan)
1292
+ text.append("")
1293
+ elif i ==40:
1294
+ l_1.append(cap_ahorro*i)
1295
+ l_3.append(cap_ahorro*i)
1296
+ text.append("")
1297
+ else:
1298
+ l_1.append(np.nan)
1299
+ l_3.append(cap_ahorro*i)
1300
+ text.append("")
1301
+ l_2.append(i)
1302
+
1303
+ Frames.append(go.Scatter(x=l_2, y=l_1,
1304
+ mode="lines+text",
1305
+ text=text,
1306
+ textposition="bottom center",
1307
+ textsrc="bottom center",
1308
+ textfont=dict(
1309
+ family="sans serif",
1310
+ size=10,
1311
+ color="Black"
1312
+ ), fill='tozeroy'))
1313
+ Frames2.append(go.Scatter(x=l_2, y=l_3, fill='tozeroy'))
1314
+ go.Annotations
1315
+ Frames_finales=[Frames, Frames2]
1316
+ fig.add_trace(go.Scatter(
1317
+ x= [0],
1318
+ y= [0],
1319
+ mode = 'lines',
1320
+ hoverinfo='name',
1321
+ legendgroup= 'Fondo Arriesgado',
1322
+ line_color= 'rgb(255, 79, 38)',
1323
+ name= 'Fondo Arriesgado',
1324
+ showlegend= True), row=1, col=1)
1325
+ fig.add_trace(go.Scatter(
1326
+ x= [0],
1327
+ y= [0],
1328
+ mode = 'lines',
1329
+ hoverinfo='name',
1330
+ legendgroup= 'Fondo Conservador',
1331
+ line_color= 'rgb(79, 38, 255)',
1332
+ name= 'Fondo Conservador',
1333
+ showlegend= True), row=1, col=1)
1334
+ frames =[dict(name = k,
1335
+ data = [Frames[k],Frames2[k]],
1336
+ traces=[0,1]) for k in range(53)
1337
+ ]
1338
+ updatemenus=[dict(
1339
+ type="buttons",
1340
+ buttons=[dict(label="Play",
1341
+ method="animate",
1342
+ args=[None])])]
1343
+ fig.update_yaxes(range=[0, 50000000])
1344
+ fig.update_xaxes(range=[0, 53])
1345
+ annotations1 = [dict(
1346
+ x=40,
1347
+ y=40*cap_ahorro,
1348
+ text=text,
1349
+ xanchor='auto',
1350
+ yanchor='bottom',
1351
+ showarrow=False,
1352
+ )]
1353
+
1354
+ fig.update(frames=frames),
1355
+ fig.update_layout(updatemenus=updatemenus)
1356
+
1357
+ st.plotly_chart(fig)
1358
+ import altair as alt
1359
+ from altair import datum
1360
+ l_1=[]
1361
+ l_2=[]
1362
+ l_3=[]
1363
+ for i in range(51):
1364
+ if i <41:
1365
+ l_1.append(cap_ahorro*i)
1366
+ l_3.append(np.nan)
1367
+ text.append("")
1368
+ elif i ==41:
1369
+ l_1.append(cap_ahorro*i)
1370
+ l_3.append(cap_ahorro*i)
1371
+ text.append("")
1372
+ else:
1373
+ l_1.append(np.nan)
1374
+ l_3.append(cap_ahorro*i)
1375
+ text.append("")
1376
+ l_2.append(i)
1377
+ chart_row = st.empty()
1378
+ button_2 = st.button("Comenzar simulació")
1379
+ if button_2:
1380
+ for i in range(51):
1381
+ time.sleep(0.1)
1382
+ df = pd.DataFrame()
1383
+
1384
+ df["Mes"]=l_2[0:i+1]+l_2[0:i+1]
1385
+ print(df["Mes"])
1386
+ df["Valor"]=l_1[0:i+1]+l_3[0:i+1]
1387
+ if i <= 41:
1388
+ df["Fondo"]=["Fondo Arriesgado"]*len(df)
1389
+ else:
1390
+ df["Fondo"]=["Fondo Arriesgado"]*41 + ["Fondo Conservador"]*(i-41) + ["Fondo Arriesgado"]*43 + ["Fondo Conservador"]*(i-41)
1391
+ if i == 41:
1392
+ st.success("Debes cambiarte al fondo conservador")
1393
+ time.sleep(1)
1394
+ df=df.dropna()
1395
+ fig = alt.Chart(df).mark_area(opacity=0.6).encode(
1396
+ x=alt.X('Mes',
1397
+ scale=alt.Scale(domain=(0, 50))
1398
+ ),
1399
+ y=alt.X('Valor',
1400
+ scale=alt.Scale(domain=(0, max(l_1+l_3)*1.1))
1401
+ ),
1402
+ color=alt.Color("Fondo", scale=alt.Scale(scheme='category20'))
1403
+ )
1404
+ if i > 41:
1405
+ df["Cambio"]="Cambiate al fondo conservador"
1406
+ text = (
1407
+ alt.Chart(df[df["Mes"]==41])
1408
+ .mark_text(dy=-25, color="black")
1409
+ .encode(x=alt.X("Mes"), y=alt.Y("Valor"), text="Cambio")
1410
+ )
1411
+
1412
+ chart_row.altair_chart(fig + text, use_container_width=True)
1413
+ else:
1414
+ chart_row.altair_chart(fig, use_container_width=True)
apps/streamlit_larra.py CHANGED
@@ -1,3 +1,131 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:426bf14fd18c7d386f1d0cb546bb956b295ac478fcce12cd3fabf5571930611e
3
- size 4020
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Tue Nov 2 10:06:46 2021
5
+
6
+ @author: benjaminull
7
+ """
8
+
9
+
10
+ import pybase64 as base64
11
+ import io
12
+ import streamlit as st
13
+ from plotly import graph_objs as go
14
+
15
+
16
+ def formatnum_0(numero):
17
+ '''
18
+ Esta función permite dar formato a los montos de saldo y valor cuota en
19
+ las cartolas.
20
+ '''
21
+ return '{:,.0f}'.format(numero).replace(",", "@").replace(".", ",").replace("@", ".")
22
+
23
+
24
+ def formatnum_2(numero):
25
+ return '{:,.2f}'.format(numero).replace(",", "@").replace(".", ",").replace("@", ".")
26
+
27
+
28
+ def macro_plot(col, data, color, prefijo, ancho, largo):
29
+ fig = go.Figure()
30
+ close_ = go.Scatter(x=data.index, y=data['Close'], name="stock_close",
31
+ line=dict(color=color), fill='tonexty')
32
+ fig.add_trace(close_)
33
+ fig.layout.update(title_text="", xaxis_rangeslider_visible=True,
34
+ width=ancho, height=largo, margin_b=0, margin_t=0,
35
+ margin_r=0, margin_l=0)
36
+ fig.update_yaxes(range=[min(data['Close'])/1.05,
37
+ max(data['Close'])*1.05], tickprefix=prefijo)
38
+ col.plotly_chart(fig, use_container_width=True)
39
+
40
+
41
+ def get_table_excel_link(df, name):
42
+ towrite = io.BytesIO()
43
+ downloaded_file = df.to_excel(towrite, encoding='utf-8', index=False,
44
+ header=True)
45
+ towrite.seek(0) # reset pointer
46
+ file_name = 'Data' + name + '.xlsx'
47
+ style = 'style="color:black;text-decoration: none; font-size:18px;"'
48
+ name_mark = "Descargar " + name + ".xlsx"
49
+ b64 = base64.b64encode(towrite.read()).decode() # some strings
50
+ linko= f'<center><a href="data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}" '+style+'download="'+file_name+'"><button>'+name_mark+'</button></a></center>'
51
+ return linko
52
+
53
+
54
+ def selectbox_larra(label, options):
55
+ var = st.selectbox(label, sorted(list(set(options))))
56
+ return var
57
+
58
+ def style_table():
59
+ style_table = """
60
+ <style>
61
+ tbody tr:hover {
62
+ color:#BB1114;}
63
+ thead {
64
+ background-color:#BB1114 ;
65
+ color: #E8E8E8;
66
+ }
67
+ tbody tr:nth-child(odd) {
68
+ background-color: #fff;
69
+ }
70
+ tbody tr:nth-child(even) {
71
+ background-color: #eee;
72
+ }
73
+ tbody tr:nth-child(odd)
74
+ stTable {
75
+ border-collapse: collapse;
76
+ margin: 25px 0;
77
+ font-size: 0.9em;
78
+ min-width: 400px;
79
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
80
+ }
81
+ </style>
82
+ """
83
+ st.markdown(style_table, unsafe_allow_html=True)
84
+
85
+
86
+
87
+ def button_style():
88
+ style_button = """
89
+ <style>
90
+ button {
91
+ display: inline-block;
92
+ background-color: #e8e8e8;
93
+ border-radius: 15px;
94
+ border: 4px #cccccc;
95
+ color: #4a4a4a;
96
+ text-align: center;
97
+ font-size: 18px;
98
+ padding: 2px;
99
+ width: 300px;
100
+ transition: all 0.5s;
101
+ cursor: pointer;
102
+ margin: 5px;
103
+ }
104
+ button span {
105
+ cursor: pointer;
106
+ display: inline-block;
107
+ position: relative;
108
+ transition: 0.5s;
109
+ }
110
+ button span:after {
111
+ content: '\00bb';
112
+ position: absolute;
113
+ opacity: 0;
114
+ top: 0;
115
+ right: -20px;
116
+ transition: 0.5s;
117
+ }
118
+ button:hover {
119
+ background-color: #bb1114;
120
+ color:#e8e8e8;
121
+ }
122
+ button:hover span {
123
+ padding-right: 25px;
124
+ }
125
+ button:hover span:after {
126
+ opacity: 1;
127
+ right: 0;
128
+ }
129
+ </style>
130
+ """
131
+ st.markdown(style_button, unsafe_allow_html=True)