Spaces:
Sleeping
Sleeping
File size: 17,769 Bytes
b16492a 4477750 7922418 a0f1ca1 7922418 1ec8606 7922418 f299934 ee760b7 e08c501 ee760b7 f299934 e08c501 ee760b7 f299934 ee760b7 e08c501 1ec8606 4c3c53a e08c501 4c3c53a e08c501 4c3c53a e08c501 1ec8606 e08c501 b9da37d 1ec8606 f299934 4c3c53a 1ec8606 df3cdd5 040c5fa 0b95db3 1ec8606 e08c501 0b95db3 1ec8606 ee760b7 b9da37d 4c3c53a f299934 ee760b7 a0f1ca1 ee760b7 7d1db74 0b95db3 4c3c53a 0b95db3 f299934 5de7dfa f299934 ee760b7 7d1db74 0b95db3 4c3c53a b16492a f299934 ee760b7 0b95db3 4c3c53a f299934 ee760b7 f299934 72c82aa 5de7dfa f299934 72c82aa f299934 4c3c53a f299934 ee760b7 f299934 4c3c53a ee760b7 f299934 b16492a 4c3c53a ee760b7 e08c501 4c3c53a f299934 ee760b7 f299934 ee760b7 1ec8606 ee760b7 f299934 ee760b7 1ec8606 f299934 ee760b7 f299934 ee760b7 f299934 ee760b7 f299934 4c3c53a f299934 ee760b7 f299934 ee760b7 0b95db3 ee760b7 e08c501 ee760b7 f299934 ee760b7 e08c501 f299934 b9da37d f299934 ee760b7 f299934 ee760b7 4c3c53a f299934 a0f1ca1 b9da37d f299934 ee760b7 f299934 0b95db3 ee760b7 b16492a ee760b7 e08c501 4c3c53a f299934 ee760b7 f299934 a0f1ca1 e08c501 f299934 ee760b7 f299934 ee760b7 e08c501 ee760b7 e08c501 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# --- 1. IMPORTAÇÕES E CONFIGURAÇÃO DA PÁGINA ---
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import numpy_financial as npf
st.set_page_config(
layout="wide",
page_title="Dashboard Estratégico de Reciclagem",
page_icon="♻️"
)
# --- 2. ESTILO CSS PROFISSIONAL ---
st.markdown("""
<style>
.stMetric {
border-radius: 10px; padding: 15px; background-color: #FFFFFF;
border: 1px solid #E6E6E6; box-shadow: 0 4px 8px rgba(0,0,0,0.04);
}
.stTabs [data-baseweb="tab-list"] { gap: 24px; }
.stTabs [data-baseweb="tab"] {
height: 50px; background-color: #F0F2F6; border-radius: 4px 4px 0px 0px; padding: 10px 15px;
}
.stTabs [aria-selected="true"] { background-color: #FFFFFF; }
</style>
""", unsafe_allow_html=True)
# --- 3. DEFINIÇÃO DAS FUNÇÕES GLOBAIS ---
def formatar_brl(valor): return f"R$ {valor:,.2f}"
def formatar_percentual(valor): return f"{valor:.2%}" if pd.notna(valor) and not np.isinf(valor) else "N/A"
def calcular_vpl(fluxo_caixa, taxa_desconto):
try: return npf.npv(taxa_desconto, fluxo_caixa)
except: return np.nan
def calcular_tir(fluxo_caixa):
try:
return npf.irr(fluxo_caixa) if np.any(np.sign(fluxo_caixa)) and np.any(np.sign(fluxo_caixa) * -1) else np.nan
except: return np.nan
def calcular_mtir(fluxo_caixa, taxa_desconto, taxa_reinvestimento):
try:
return npf.mirr(fluxo_caixa, taxa_desconto, taxa_reinvestimento) if np.any(np.sign(fluxo_caixa)) and np.any(np.sign(fluxo_caixa) * -1) else np.nan
except: return np.nan
def calcular_payback_descontado(fluxo_caixa, taxa_desconto):
investimento_inicial = abs(fluxo_caixa[0])
fluxo_acumulado_descontado = 0
for periodo, valor in enumerate(fluxo_caixa[1:], 1):
fluxo_acumulado_descontado += valor / ((1 + taxa_desconto) ** periodo)
if fluxo_acumulado_descontado >= investimento_inicial:
ultimo_fluxo_necessario = investimento_inicial - (fluxo_acumulado_descontado - (valor / ((1 + taxa_desconto) ** periodo)))
return (periodo - 1) + (ultimo_fluxo_necessario / (valor / ((1 + taxa_desconto) ** periodo)))
return np.inf
@st.cache_data
def simular_faturamento_bootstrap(_df_dados_mensais_numeric, precos_dict, cenarios_dict, eficiencia_geral_coleta, n_simulacoes=2000, seed=42):
np.random.seed(seed)
faturamentos_simulados = {nome: [] for nome in cenarios_dict.keys()}
for nome_cen, fator_cenario in cenarios_dict.items():
for _ in range(n_simulacoes):
df_amostrado = _df_dados_mensais_numeric.sample(n=12, replace=True)
faturamento_bruto_iteracao = sum(df_amostrado[material].sum() * preco for material, preco in precos_dict.items())
faturamento_liquido = faturamento_bruto_iteracao * eficiencia_geral_coleta * fator_cenario
faturamentos_simulados[nome_cen].append(faturamento_liquido)
return {nome: np.array(data) for nome, data in faturamentos_simulados.items()}
def gerar_fluxo_caixa_projeto(investimento_inicial, receita_anual_base, custos_operacionais_anuais, horizonte_anos, taxa_crescimento):
fluxo_caixa = [-abs(investimento_inicial)]
for ano in range(1, horizonte_anos + 1):
fator_crescimento = (1 + taxa_crescimento) ** (ano - 1)
fluxo_liquido_ano = (receita_anual_base * fator_crescimento) - (custos_operacionais_anuais * fator_crescimento)
fluxo_caixa.append(fluxo_liquido_ano)
return fluxo_caixa
# --- 4. CARREGAMENTO DE DADOS (FUNÇÃO CACHEADA) ---
@st.cache_data
def carregar_dados():
meses = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez']
dados_2024 = {
'Mes': meses, 'Papel_Papelao': [8047, 11287, 8184, 10183, 5699, 5830, 7465, 5600, 2960, 5175, 9656, 3960],
'Plastico': [6353, 8771, 6993, 8050, 4880, 5296, 5937, 4747, 2446, 4109, 7667, 3367],
'Metal': [1061, 2025, 1121, 1832, 716, 936, 1553, 904, 361, 630, 1904, 569],
'Vidro': [5248, 6929, 6014, 5821, 3697, 3655, 4950, 3360, 1580, 3261, 6173, 2357]
}
df_2024 = pd.DataFrame(dados_2024)
df_2024_numeric = df_2024.drop(columns='Mes')
dados_anuais = {'Ano': [2022, 2023, 2024], 'Papel_Papelao': [18780, 58718, df_2024_numeric['Papel_Papelao'].sum()], 'Plastico': [5340, 1041, df_2024_numeric['Plastico'].sum()], 'Metal': [1300, 1737, df_2024_numeric['Metal'].sum()], 'Vidro': [0, 725, df_2024_numeric['Vidro'].sum()]}
df_anuais = pd.DataFrame(dados_anuais).set_index('Ano')
precos_iniciais = {'Papel_Papelao': 0.50, 'Plastico': 2.00, 'Metal': 2.30, 'Vidro': 0.90}
custos_mensais_iniciais = {"Locacao_Maquina": 4400, "Coleta_Destinacao": 1400, "Outros": 500}
return df_2024, df_anuais, precos_iniciais, df_2024_numeric, custos_mensais_iniciais
# --- 5. EXECUÇÃO INICIAL E SIDEBAR DE CONTROLES ---
df_2024, df_anuais, precos_iniciais, df_2024_numeric, custos_mensais_iniciais = carregar_dados()
st.sidebar.title(" Painel de Controle")
st.sidebar.markdown("Use os menus abaixo para navegar entre as análises e ajustar os parâmetros do projeto.")
st.sidebar.divider()
pagina_selecionada = st.sidebar.radio("Menu de Navegação",
["🔎 Análise Exploratória (EDA)", "🎯 Simulação de Faturamento", "📊 Análise de Viabilidade"],
captions=["Análise dos dados históricos", "Projeção de receitas via simulação", "Cálculos de VPL, TIR e Risco"]
)
st.sidebar.divider()
with st.sidebar.expander("⚙️ Premissas Financeiras do Projeto", expanded=True):
investimento_inicial = st.number_input("Investimento Inicial (R$)", min_value=1000.0, value=5000.0, step=1000.0)
st.markdown("**Custos Fixos Mensais (R$)**")
custos_mensais_editaveis = {custo: st.number_input(custo.replace("_", " "), value=valor, step=50, key=custo) for custo, valor in custos_mensais_iniciais.items()}
custos_operacionais_anuais = sum(custos_mensais_editaveis.values()) * 12
st.info(f"Custo Anual Calculado: **{formatar_brl(custos_operacionais_anuais)}**")
horizonte_projeto = st.slider("Horizonte do Projeto (anos)", 3, 20, 10)
taxa_desconto = st.slider("Taxa de Desconto (TMA) (%)", 5.0, 25.0, 12.0, 0.5) / 100
taxa_crescimento = st.slider("Crescimento Anual (Receitas/Custos) (%)", 0.0, 10.0, 3.0, 0.5) / 100
taxa_reinvestimento = st.slider("Taxa de Reinvestimento (MTIR) (%)", 2.0, 18.0, 10.0, 0.5) / 100
with st.sidebar.expander("📈 Preços e Cenários de Simulação", expanded=False):
eficiencia_coleta_geral = st.slider("Eficiência Geral da Coleta (%)", 0, 100, 30, help="Fator mestre que afeta a quantidade de material coletado em todos os cenários.") / 100
st.markdown("**Preços dos Materiais (R$/kg)**")
precos_editaveis = {material: st.number_input(f"{material.replace('_', ' ')}", value=preco, step=0.1, key=f"preco_{material}") for material, preco in precos_iniciais.items()}
st.markdown("**Fatores de Variação de Cenário**")
fator_pessimista = st.slider("Cenário Pessimista (%)", 0, 100, 80) / 100
fator_otimista = st.slider("Cenário Otimista (%)", 100, 200, 115) / 100
st.sidebar.divider()
st.sidebar.info(f"Última atualização: {pd.Timestamp.now(tz='America/Sao_Paulo').strftime('%d/%m/%Y %H:%M')}")
# --- 6. LÓGICA DE RENDERIZAÇÃO DAS PÁGINAS ---
if pagina_selecionada == "🔎 Análise Exploratória (EDA)":
st.title("🔎 Análise Exploratória dos Dados de Coleta")
st.markdown("O primeiro passo para qualquer projeção é entender o passado. Aqui, exploramos os dados históricos de coleta para identificar padrões, sazonalidades e anomalias.")
st.divider()
st.subheader("Evolução da Coleta Total Anual (Histórico)")
df_coleta_anual = df_anuais.sum(axis=1).reset_index()
df_coleta_anual.columns = ['Ano', 'Coleta Total (kg)']
fig_evol_coleta = px.bar(df_coleta_anual, x='Ano', y='Coleta Total (kg)', text_auto='.3s', title="Volume Total Anual de Materiais Coletados")
st.plotly_chart(fig_evol_coleta, use_container_width=True)
st.warning("**Observação:** Note a queda acentuada na coleta de Plástico e Metal em 2023 em comparação com 2022 nos dados fornecidos. É crucial investigar se isso reflete a realidade operacional ou uma anomalia nos dados antes de prosseguir com projeções críticas.")
# CORREÇÃO: Este bloco de colunas agora está DENTRO da condição da página EDA
col1, col2 = st.columns(2)
with col1:
st.subheader("Coleta Mensal por Material (2024)")
df_melt_mensal = df_2024.melt(id_vars='Mes', var_name='Material', value_name='Quantidade (kg)')
fig_evol_mensal = px.line(df_melt_mensal, x='Mes', y='Quantidade (kg)', color='Material', title="Variação Mensal da Coleta por Material", markers=True)
st.plotly_chart(fig_evol_mensal, use_container_width=True)
with col2:
st.subheader("Distribuição da Coleta Mensal (2024)")
fig_boxplot = px.box(df_melt_mensal, x='Material', y='Quantidade (kg)', color='Material', title="Variação e Volatilidade da Coleta Mensal")
st.plotly_chart(fig_boxplot, use_container_width=True)
st.info("O **gráfico de linhas** mostra a tendência e sazonalidade ao longo do ano. O **boxplot** revela a volatilidade de cada material: caixas mais 'altas' indicam maior variação mensal, o que se traduz em maior risco e incerteza no faturamento.")
elif pagina_selecionada == "🎯 Simulação de Faturamento":
st.title("🎯 Simulação e Projeção de Faturamento Anual")
st.markdown("Utilizando a técnica de bootstrapping, simulamos 2.000 possíveis anos de faturamento com base na volatilidade dos dados de 2024 e na eficiência de coleta definida.")
st.divider()
cenarios = {'Pessimista': fator_pessimista, 'Base': 1.0, 'Otimista': fator_otimista}
simulacoes_faturamento = simular_faturamento_bootstrap(df_2024_numeric, precos_editaveis, cenarios, eficiencia_coleta_geral)
kpi1, kpi2, kpi3 = st.columns(3)
media_faturamento_base = np.mean(simulacoes_faturamento['Base'])
desvio_padrao_base = np.std(simulacoes_faturamento['Base'])
faturamento_material_base = {m: df_2024_numeric[m].sum() * p * eficiencia_coleta_geral for m, p in precos_editaveis.items()}
material_mais_rentavel = max(faturamento_material_base, key=faturamento_material_base.get)
kpi1.metric("Faturamento Anual Médio (Base)", formatar_brl(media_faturamento_base))
kpi2.metric("Desvio Padrão do Faturamento", formatar_brl(desvio_padrao_base), help="Mede a volatilidade ou risco do faturamento. Valores mais altos indicam maior incerteza.")
kpi3.metric("Material Mais Rentável (Base 2024)", material_mais_rentavel.replace('_', ' '))
st.divider()
col_g1, col_g2 = st.columns([6, 4])
with col_g1:
st.subheader("Distribuição do Faturamento Anual Simulado")
fig_dist = go.Figure()
for nome, data in simulacoes_faturamento.items():
fig_dist.add_trace(go.Histogram(x=data, name=nome, histnorm='probability density', opacity=0.75))
fig_dist.update_layout(barmode='overlay', title_text="Comparativo de Cenários de Faturamento", xaxis_title="Faturamento Anual (R$)", yaxis_title="Densidade de Probabilidade", legend_title_text='Cenário')
st.plotly_chart(fig_dist, use_container_width=True)
with col_g2:
st.subheader("Composição do Faturamento (Base 2024)")
df_faturamento_material = pd.DataFrame(list(faturamento_material_base.items()), columns=['Material', 'Faturamento'])
fig_comp = px.pie(df_faturamento_material, values='Faturamento', names='Material', hole=0.4, title="Faturamento por Material")
st.plotly_chart(fig_comp, use_container_width=True)
elif pagina_selecionada == "📊 Análise de Viabilidade":
st.title("📊 Análise de Viabilidade Financeira e Risco")
st.markdown("Esta é a etapa final, onde combinamos as projeções de receita com as premissas de investimento e custos para avaliar a viabilidade do projeto sob a ótica do risco.")
cenarios = {'Pessimista': fator_pessimista, 'Base': 1.0, 'Otimista': fator_otimista}
simulacoes_faturamento = simular_faturamento_bootstrap(df_2024_numeric, precos_editaveis, cenarios, eficiencia_coleta_geral)
cenario_analise = st.radio("Selecione o cenário para a análise detalhada:", options=list(cenarios.keys()), index=1, horizontal=True)
st.divider()
receita_anual_media = np.mean(simulacoes_faturamento[cenario_analise])
fluxo_caixa_projeto = gerar_fluxo_caixa_projeto(investimento_inicial, receita_anual_media, custos_operacionais_anuais, horizonte_projeto, taxa_crescimento)
vpl = calcular_vpl(fluxo_caixa_projeto, taxa_desconto)
tir = calcular_tir(fluxo_caixa_projeto)
mtir = calcular_mtir(fluxo_caixa_projeto, taxa_desconto, taxa_reinvestimento)
payback_desc = calcular_payback_descontado(fluxo_caixa_projeto, taxa_desconto)
tab_kpis, tab_fluxo, tab_risco, tab_resumo = st.tabs(["📈 Indicadores Chave", "📂 Fluxo de Caixa", "🎲 Análise de Risco (Monte Carlo)", "📋 Resumo Executivo"])
with tab_kpis:
st.subheader(f"Indicadores para o Cenário: {cenario_analise}")
col1, col2, col3, col4 = st.columns(4)
col1.metric("VPL", formatar_brl(vpl), "Viável" if vpl >= 0 else "Inviável")
col2.metric("TIR", formatar_percentual(tir), "Superior à TMA" if pd.notna(tir) and tir > taxa_desconto else "Inferior à TMA")
col3.metric("MTIR", formatar_percentual(mtir), "Superior à TMA" if pd.notna(mtir) and mtir > taxa_desconto else "Inferior à TMA")
col4.metric("Payback Descontado", f"{payback_desc:.1f} anos" if not np.isinf(payback_desc) else "Não recupera")
with tab_fluxo:
st.subheader("Visualização do Fluxo de Caixa do Projeto")
df_fluxo = pd.DataFrame({'Ano': list(range(horizonte_projeto + 1)), 'Fluxo de Caixa': fluxo_caixa_projeto})
df_fluxo['Fluxo Acumulado'] = df_fluxo['Fluxo de Caixa'].cumsum()
fig_fluxo = go.Figure(data=[go.Bar(name='Fluxo Anual', x=df_fluxo['Ano'], y=df_fluxo['Fluxo de Caixa'], marker_color=['#d62728' if x < 0 else '#2ca02c' for x in df_fluxo['Fluxo de Caixa']]), go.Scatter(name='Fluxo Acumulado', x=df_fluxo['Ano'], y=df_fluxo['Fluxo Acumulado'], mode='lines+markers')])
fig_fluxo.update_layout(title_text="Fluxo de Caixa Anual e Acumulado", hovermode='x unified')
st.plotly_chart(fig_fluxo, use_container_width=True)
with tab_risco:
st.subheader(f"Simulação Monte Carlo para o VPL (Cenário: {cenario_analise})")
receitas_mc = np.random.choice(simulacoes_faturamento[cenario_analise], size=5000, replace=True)
vpls_mc = [calcular_vpl(gerar_fluxo_caixa_projeto(investimento_inicial, r, custos_operacionais_anuais, horizonte_projeto, taxa_crescimento), taxa_desconto) for r in receitas_mc]
prob_viabilidade = (np.array(vpls_mc) >= 0).mean()
vpl_medio_mc = np.mean(vpls_mc)
vpl_std_mc = np.std(vpls_mc)
mc1, mc2, mc3 = st.columns(3)
mc1.metric("VPL Médio Simulado", formatar_brl(vpl_medio_mc))
mc2.metric("Probabilidade de Viabilidade", formatar_percentual(prob_viabilidade))
mc3.metric("Desvio Padrão do VPL", formatar_brl(vpl_std_mc), help="Mede a volatilidade ou risco do VPL. Valores mais altos indicam maior incerteza.")
fig_mc = px.histogram(x=vpls_mc, nbins=50, title=f"Distribuição do VPL ({len(vpls_mc)} Simulações)")
fig_mc.add_vline(x=0, line_dash="dash", line_color="red", annotation_text="Viabilidade")
st.plotly_chart(fig_mc, use_container_width=True)
with tab_resumo:
st.subheader("Resumo Executivo e Parecer Final")
conclusoes = []
if vpl >= 0: conclusoes.append(f"✅ **Projeto VIÁVEL** no cenário '{cenario_analise}', com um VPL de **{formatar_brl(vpl)}**.")
else: conclusoes.append(f"❌ **Projeto INVIÁVEL** no cenário '{cenario_analise}', com um VPL de **{formatar_brl(vpl)}**.")
if not pd.isna(tir) and tir > taxa_desconto: conclusoes.append(f"✅ A **TIR de {formatar_percentual(tir)} é superior à TMA de {formatar_percentual(taxa_desconto)}**, reforçando a atratividade.")
else: conclusoes.append(f"❌ A **TIR de {formatar_percentual(tir)} é inferior à TMA**, um forte indicador contra o investimento.")
if prob_viabilidade > 0.75: conclusoes.append(f"✅ A simulação de Monte Carlo aponta uma **alta probabilidade de sucesso de {formatar_percentual(prob_viabilidade)}**.")
elif prob_viabilidade > 0.5: conclusoes.append(f"⚠️ A probabilidade de sucesso de **{formatar_percentual(prob_viabilidade)} é moderada**.")
else: conclusoes.append(f"❌ A probabilidade de sucesso de **{formatar_percentual(prob_viabilidade)} é baixa**, indicando risco elevado.")
st.markdown("#### Conclusões Chave:")
for c in conclusoes: st.markdown(f"- {c}")
st.markdown("#### Parecer Final:")
if vpl > 0 and prob_viabilidade > 0.7:
st.success("**RECOMENDAÇÃO: APROVAR O PROJETO.** Os indicadores são fortemente positivos e a análise de risco confere robustez à decisão.")
elif vpl > 0 and prob_viabilidade > 0.5:
st.warning("**RECOMENDAÇÃO: APROVAR COM CAUTELA.** O projeto é viável, mas a análise de risco mostra sensibilidade. Recomenda-se um plano de monitoramento de riscos focado em garantir as receitas projetadas.")
else:
st.error("**RECOMENDAÇÃO: REAVALIAR OU REJEITAR O PROJETO.** Os indicadores atuais, combinados com o perfil de risco, não justificam o investimento. Revisar premissas de receita, custos ou investimento inicial.") |