VicMata's picture
Create app.py
f06512b verified
# app_npv_timeline.py
# -------------------------------------------------------------
# Herramienta interactiva para calcular el Valor Presente Neto
# (NPV) de un proyecto a partir de flujos de caja anuales.
# -------------------------------------------------------------
import streamlit as st
import numpy as np
# 1. CONFIGURACIÓN BÁSICA DE LA PÁGINA
st.set_page_config(page_title="Calculadora de NPV", layout="wide")
# 2. ENCABEZADO
st.title("Calculadora de Valor Presente Neto (NPV)")
# 3. ENTRADAS PRINCIPALES
# 3.1 Tasa de descuento con slider (0 % – 50 %)
discount_rate_pct = st.slider(
"Selecciona la tasa de descuento (%)",
min_value=0.0,
max_value=50.0,
value=10.0,
step=0.1,
help="Costo de oportunidad o rendimiento mínimo aceptable."
)
discount_rate = discount_rate_pct / 100 # Convertir a proporción
# 3.2 Duración del proyecto en años
years = st.slider(
"¿Cuántos años dura el proyecto?",
min_value=1,
max_value=30,
value=5,
step=1
)
st.markdown("---")
# 4. CAPTURA DE FLUJOS DE CAJA MEDIANTE TIMELINE
st.subheader("Ingresa los flujos de caja anuales")
with st.form("cashflow_form", clear_on_submit=False):
# Usamos columnas para generar un "timeline" con recuadros
cols = st.columns(years + 1) # +1 porque suele haber flujo en t=0
cashflows = []
for t in range(years + 1):
with cols[t]:
cf = st.number_input(
f"Año {t}",
value=0.0,
key=f"cf_{t}",
format="%.2f"
)
cashflows.append(cf)
submitted = st.form_submit_button("Calcular NPV")
# 5. CÁLCULO DEL NPV
if submitted:
npv = sum(cf / (1 + discount_rate) ** t for t, cf in enumerate(cashflows))
st.markdown("## Resultado")
st.metric(label="Valor Presente Neto (NPV)", value=f"${npv:,.2f}")
# 6. VISUALIZACIÓN DEL TIMELINE CON ESTILO
st.markdown("### Timeline de Flujos de Caja")
timeline_cols = st.columns(years + 1)
for t, col in enumerate(timeline_cols):
with col:
st.markdown(
f"""
<div style='border:1px solid #999; border-radius:6px;
padding:10px; text-align:center;'>
<strong>Año {t}</strong><br>
${cashflows[t]:,.2f}
</div>
""",
unsafe_allow_html=True
)
# 7. INTERPRETACIÓN BÁSICA
if npv > 0:
st.success("El proyecto genera valor (NPV positivo).")
elif npv < 0:
st.error("El proyecto destruye valor (NPV negativo).")
else:
st.info("El proyecto es neutro (NPV = 0).")