Objetivo prático da aula

Função VPL manual

def calcular_vpl(fluxos_caixa: list[float], taxa_desconto: float) -> float:
    """
    VPL = Soma de Ft / (1+r)^t para t = 0, 1, ..., n
    O fluxo t=0 é o investimento inicial (negativo).
    """
    vpl = 0
    for t, fluxo in enumerate(fluxos_caixa):
        vpl += fluxo / ((1 + taxa_desconto) ** t)
    return vpl

# Exemplo
fluxos = [-500000, 130000, 150000, 175000, 200000, 215000]
vpl = calcular_vpl(fluxos, 0.14)
print(f"VPL: R$ {vpl:,.2f}")

TIR via Newton-Raphson

A TIR é a taxa que zera o VPL. O método de Newton-Raphson converge iterativamente usando a derivada da função VPL.

def calcular_tir(fluxos_caixa: list[float],
                 chute_inicial: float = 0.1,
                 tolerancia: float = 1e-6,
                 max_iter: int = 100) -> float:
    taxa = chute_inicial
    for _ in range(max_iter):
        vpl = sum(f / ((1 + taxa) ** t) for t, f in enumerate(fluxos_caixa))
        derivada = sum(-t * f / ((1 + taxa) ** (t + 1))
                      for t, f in enumerate(fluxos_caixa) if t > 0)
        if abs(derivada) < 1e-10:
            break
        nova_taxa = taxa - vpl / derivada
        if abs(nova_taxa - taxa) < tolerancia:
            return nova_taxa
        taxa = nova_taxa
    return taxa

tir = calcular_tir(fluxos)
print(f"TIR: {tir*100:.2f}% a.a.")

Payback Simples e Descontado

def calcular_payback_simples(fluxos_caixa: list[float]) -> float:
    investimento = -fluxos_caixa[0]
    acumulado = 0
    for t in range(1, len(fluxos_caixa)):
        acumulado += fluxos_caixa[t]
        if acumulado >= investimento:
            retorno_parcial = investimento - (acumulado - fluxos_caixa[t])
            fracao = retorno_parcial / fluxos_caixa[t]
            return (t - 1) + fracao
    return float('inf')

def calcular_payback_descontado(fluxos_caixa: list[float], taxa: float) -> float:
    investimento = -fluxos_caixa[0]
    acumulado = 0
    for t in range(1, len(fluxos_caixa)):
        fd = fluxos_caixa[t] / ((1 + taxa) ** t)
        acumulado += fd
        if acumulado >= investimento:
            fracao = (investimento - (acumulado - fd)) / fd
            return (t - 1) + fracao
    return float('inf')

pb_s = calcular_payback_simples(fluxos)
pb_d = calcular_payback_descontado(fluxos, 0.14)
print(f"Payback Simples: {pb_s:.2f} anos")
print(f"Payback Descontado: {pb_d:.2f} anos")

Visualização com Plotly

import plotly.graph_objects as go

def plotar_sensibilidade_vpl(fluxos, taxa_min=0, taxa_max=0.30):
    taxas = [i/100 for i in range(int(taxa_min*100), int(taxa_max*100)+1)]
    vpls = [calcular_vpl(fluxos, t) for t in taxas]

    fig = go.Figure()
    fig.add_trace(go.Scatter(x=[t*100 for t in taxas], y=vpls,
                             mode='lines', line=dict(color='#2e2640', width=3)))
    fig.add_hline(y=0, line_dash="dash", line_color="red",
                  annotation_text="TIR (VPL=0)")
    fig.update_layout(
        title='Sensibilidade do VPL a Taxa de Desconto',
        xaxis_title='Taxa de Desconto (%)',
        yaxis_title='VPL (R$)',
        hovermode='x unified'
    )
    return fig

fig = plotar_sensibilidade_vpl(fluxos)
fig.show()

App Gradio para análise de investimento

!pip install gradio plotly -q
import gradio as gr
import plotly.graph_objects as go

def analisar_investimento(fluxos_texto, taxa_pct):
    try:
        fluxos = [float(x.strip()) for x in fluxos_texto.split(',')]
        if len(fluxos) < 2:
            return "Erro: mínimo 2 fluxos necessários", "", None
        taxa = float(taxa_pct) / 100
        vpl = calcular_vpl(fluxos, taxa)
        tir = calcular_tir(fluxos)
        pb = calcular_payback_simples(fluxos)
        resultado = (f"VPL: R$ {vpl:,.2f}\n"
                     f"TIR: {tir*100:.2f}% a.a.\n"
                     f"Payback Simples: {pb:.2f} anos")
        decisao = "VIAVEL" if vpl > 0 and tir > taxa else "INVIAVEL"
        fig = plotar_sensibilidade_vpl(fluxos)
        return resultado, decisao, fig
    except Exception as e:
        return f"Erro: {e}", "", None

demo = gr.Interface(
    fn=analisar_investimento,
    inputs=[
        gr.Textbox(label="Fluxos de Caixa (separados por virgula)",
                   value="-500000, 130000, 150000, 175000, 200000, 215000"),
        gr.Number(label="Taxa de Desconto (%)", value=14)
    ],
    outputs=[
        gr.Textbox(label="Resultados"),
        gr.Textbox(label="Decisao"),
        gr.Plot(label="Sensibilidade do VPL")
    ],
    title="Analise de Investimento — VPL/TIR"
)
demo.launch(share=True)

Checklist da atividade ponderada