Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import numpy as np
|
| 3 |
+
import pandas as pd
|
| 4 |
+
import numpy_financial as npf
|
| 5 |
+
import warnings
|
| 6 |
+
|
| 7 |
+
# Suppress RunTimeWarning from numpy_financial if IRR cannot be computed
|
| 8 |
+
warnings.filterwarnings("ignore", category=RuntimeWarning, module='numpy_financial')
|
| 9 |
+
|
| 10 |
+
def financial_projection(initial_investment, passive_income_investment, return_rate, units_year1, revenue_per_unit_year1, cogs_per_unit_year1, fixed_expenses_year1, variable_expenses_year1, units_growth_rate, revenue_growth_rate, cogs_growth_rate, fixed_expenses_growth_rate, variable_expenses_growth_rate):
|
| 11 |
+
"""
|
| 12 |
+
Calculates the 5-year financial projection for a business.
|
| 13 |
+
Inputs are assumed to be in Lacs where applicable.
|
| 14 |
+
"""
|
| 15 |
+
# Handle potential None inputs from Gradio startup
|
| 16 |
+
initial_investment = initial_investment or 0
|
| 17 |
+
passive_income_investment = passive_income_investment or 0 # Note: This input is not currently used
|
| 18 |
+
return_rate = return_rate or 0 # Note: This input is not currently used
|
| 19 |
+
units_year1 = units_year1 or 0
|
| 20 |
+
revenue_per_unit_year1 = revenue_per_unit_year1 or 0
|
| 21 |
+
cogs_per_unit_year1 = cogs_per_unit_year1 or 0
|
| 22 |
+
fixed_expenses_year1 = fixed_expenses_year1 or 0
|
| 23 |
+
variable_expenses_year1 = variable_expenses_year1 or 0
|
| 24 |
+
units_growth_rate = units_growth_rate or 0
|
| 25 |
+
revenue_growth_rate = revenue_growth_rate or 0
|
| 26 |
+
cogs_growth_rate = cogs_growth_rate or 0
|
| 27 |
+
fixed_expenses_growth_rate = fixed_expenses_growth_rate or 0
|
| 28 |
+
variable_expenses_growth_rate = variable_expenses_growth_rate or 0
|
| 29 |
+
|
| 30 |
+
years = 5
|
| 31 |
+
revenue = []
|
| 32 |
+
expenses = []
|
| 33 |
+
net_profit = []
|
| 34 |
+
cash_flow_for_npv_irr = []
|
| 35 |
+
cumulative_net_profit = 0
|
| 36 |
+
cumulative_net_profits = []
|
| 37 |
+
|
| 38 |
+
# Initialize lists with first year values
|
| 39 |
+
units = [units_year1]
|
| 40 |
+
revenue_per_unit = [revenue_per_unit_year1]
|
| 41 |
+
cogs_per_unit = [cogs_per_unit_year1]
|
| 42 |
+
fixed_expenses = [fixed_expenses_year1]
|
| 43 |
+
variable_expenses_per_unit = [variable_expenses_year1] # Assume variable expense input is per unit
|
| 44 |
+
|
| 45 |
+
# Calculate projections for 5 years
|
| 46 |
+
for year in range(years):
|
| 47 |
+
if year > 0:
|
| 48 |
+
units.append(units[year-1] * (1 + units_growth_rate/100))
|
| 49 |
+
revenue_per_unit.append(revenue_per_unit[year-1] * (1 + revenue_growth_rate/100))
|
| 50 |
+
cogs_per_unit.append(cogs_per_unit[year-1] * (1 + cogs_growth_rate/100))
|
| 51 |
+
fixed_expenses.append(fixed_expenses[year-1] * (1 + fixed_expenses_growth_rate/100))
|
| 52 |
+
variable_expenses_per_unit.append(variable_expenses_per_unit[year-1] * (1 + variable_expenses_growth_rate/100))
|
| 53 |
+
|
| 54 |
+
# Revenue, Expenses, and Net Profit calculations
|
| 55 |
+
revenue_year = units[year] * revenue_per_unit[year]
|
| 56 |
+
cogs_year = units[year] * cogs_per_unit[year]
|
| 57 |
+
variable_expenses_year_total = units[year] * variable_expenses_per_unit[year]
|
| 58 |
+
expenses_year = cogs_year + fixed_expenses[year] + variable_expenses_year_total
|
| 59 |
+
net_profit_year = revenue_year - expenses_year
|
| 60 |
+
|
| 61 |
+
revenue.append(revenue_year)
|
| 62 |
+
expenses.append(expenses_year)
|
| 63 |
+
net_profit.append(net_profit_year)
|
| 64 |
+
cash_flow_for_npv_irr.append(net_profit_year) # Using net profit as proxy for cash flow
|
| 65 |
+
|
| 66 |
+
cumulative_net_profit += net_profit_year
|
| 67 |
+
cumulative_net_profits.append(cumulative_net_profit)
|
| 68 |
+
|
| 69 |
+
# --- Performance Measures Calculations ---
|
| 70 |
+
|
| 71 |
+
revenue_np = np.array(revenue)
|
| 72 |
+
net_profit_np = np.array(net_profit)
|
| 73 |
+
units_np = np.array(units)
|
| 74 |
+
cogs_per_unit_np = np.array(cogs_per_unit)
|
| 75 |
+
cogs_np = units_np * cogs_per_unit_np
|
| 76 |
+
|
| 77 |
+
# Margins
|
| 78 |
+
total_revenue = np.sum(revenue_np)
|
| 79 |
+
avg_net_profit_margin = (np.sum(net_profit_np) / total_revenue * 100) if total_revenue != 0 else 0
|
| 80 |
+
# Calculate Gross Profit per year before averaging the margin
|
| 81 |
+
gross_profit_yearly = revenue_np - cogs_np
|
| 82 |
+
# Avoid division by zero if revenue is zero in any year
|
| 83 |
+
gross_profit_margin_yearly = np.divide(gross_profit_yearly * 100, revenue_np, out=np.zeros_like(revenue_np), where=revenue_np!=0)
|
| 84 |
+
avg_gross_profit_margin = np.mean(gross_profit_margin_yearly)
|
| 85 |
+
avg_operating_profit_margin = avg_net_profit_margin # Assuming Net Profit = Operating Profit for this model
|
| 86 |
+
|
| 87 |
+
# ROI
|
| 88 |
+
roi = (cumulative_net_profit / initial_investment * 100) if initial_investment != 0 else float('inf') if cumulative_net_profit > 0 else 0
|
| 89 |
+
|
| 90 |
+
# Break-even Year calculation
|
| 91 |
+
break_even_year = "N/A (or Profitable from Year 1 if Inv=0)" if initial_investment == 0 else "Never within 5 years"
|
| 92 |
+
if initial_investment > 0:
|
| 93 |
+
for year_index in range(years):
|
| 94 |
+
if cumulative_net_profits[year_index] >= initial_investment:
|
| 95 |
+
break_even_year = year_index + 1
|
| 96 |
+
break
|
| 97 |
+
|
| 98 |
+
# NPV & IRR calculation (using 10% discount rate)
|
| 99 |
+
# Include initial investment as outflow at time 0
|
| 100 |
+
cash_flows_for_calc = [-initial_investment] + cash_flow_for_npv_irr if initial_investment is not None else cash_flow_for_npv_irr
|
| 101 |
+
npv = npf.npv(0.10, cash_flows_for_calc) if cash_flows_for_calc else 0 # Handle empty cash flows
|
| 102 |
+
|
| 103 |
+
irr = "N/A"
|
| 104 |
+
try:
|
| 105 |
+
# IRR calculation requires at least one positive and one negative cash flow
|
| 106 |
+
if any(cf > 0 for cf in cash_flows_for_calc) and any(cf < 0 for cf in cash_flows_for_calc):
|
| 107 |
+
irr_calc = npf.irr(cash_flows_for_calc)
|
| 108 |
+
irr = f"{irr_calc * 100:.2f}" if not np.isnan(irr_calc) else "N/A (Calculation Error)"
|
| 109 |
+
elif initial_investment == 0 and all(cf >= 0 for cf in cash_flow_for_npv_irr):
|
| 110 |
+
irr = "Infinite (No Investment)" # Or technically undefined
|
| 111 |
+
else:
|
| 112 |
+
irr = "N/A (Cannot Calculate)" # e.g., all negative or all zero flows after investment
|
| 113 |
+
except Exception: # Catch potential errors in IRR calculation
|
| 114 |
+
irr = "N/A (Calculation Error)"
|
| 115 |
+
|
| 116 |
+
# --- Prepare Results ---
|
| 117 |
+
years_list = list(range(1, years + 1))
|
| 118 |
+
results = {
|
| 119 |
+
"Revenue DF": pd.DataFrame({'Year': years_list, 'Revenue': revenue}),
|
| 120 |
+
"Expenses DF": pd.DataFrame({'Year': years_list, 'Expenses': expenses}),
|
| 121 |
+
"Net Profit DF": pd.DataFrame({'Year': years_list, 'Net Profit': net_profit}),
|
| 122 |
+
"Cumulative Net Profit DF": pd.DataFrame({'Year': years_list, 'Cumulative Net Profit': cumulative_net_profits}),
|
| 123 |
+
"Net Profit Margin": f"{avg_net_profit_margin:.2f}",
|
| 124 |
+
"Gross Profit Margin": f"{avg_gross_profit_margin:.2f}",
|
| 125 |
+
"Operating Profit Margin": f"{avg_operating_profit_margin:.2f}",
|
| 126 |
+
"Final Cumulative Net Profit": f"{cumulative_net_profit:.2f}", # Use a distinct key for the text output
|
| 127 |
+
"ROI": f"{roi:.2f}" if roi != float('inf') else "Infinite (No Investment)",
|
| 128 |
+
"Break-even Year": str(break_even_year),
|
| 129 |
+
"NPV": f"{npv:.2f}",
|
| 130 |
+
"IRR": irr # Already formatted or N/A string
|
| 131 |
+
}
|
| 132 |
+
|
| 133 |
+
# Return values in the order expected by the outputs list
|
| 134 |
+
return (
|
| 135 |
+
results["Revenue DF"],
|
| 136 |
+
results["Expenses DF"],
|
| 137 |
+
results["Net Profit DF"],
|
| 138 |
+
results["Cumulative Net Profit DF"], # DataFrame for the plot
|
| 139 |
+
results["Net Profit Margin"],
|
| 140 |
+
results["Gross Profit Margin"],
|
| 141 |
+
results["Operating Profit Margin"],
|
| 142 |
+
results["Final Cumulative Net Profit"], # String for the text output
|
| 143 |
+
results["ROI"],
|
| 144 |
+
results["Break-even Year"],
|
| 145 |
+
results["NPV"],
|
| 146 |
+
results["IRR"]
|
| 147 |
+
)
|
| 148 |
+
|
| 149 |
+
if __name__ == "__main__":
|
| 150 |
+
# Define input components
|
| 151 |
+
initial_investment_input = gr.Number(label="Initial Investment (Lacs)", value=10) # Added default values for quicker testing
|
| 152 |
+
passive_income_investment_input = gr.Number(label="Passive Income Investment (Lacs) [Not Used]", value=0)
|
| 153 |
+
return_rate_input = gr.Number(label="Return Rate (%) [Not Used]", value=0)
|
| 154 |
+
units_year1_input = gr.Number(label="Units Sold Year 1", value=1000)
|
| 155 |
+
revenue_per_unit_year1_input = gr.Number(label="Revenue per Unit Year 1 (Lacs)", value=0.005) # e.g., 500 Rs
|
| 156 |
+
cogs_per_unit_year1_input = gr.Number(label="COGS per Unit Year 1 (Lacs)", value=0.002) # e.g., 200 Rs
|
| 157 |
+
fixed_expenses_year1_input = gr.Number(label="Fixed Expenses Year 1 (Lacs)", value=1)
|
| 158 |
+
# Clarified label: Variable expenses *per unit*
|
| 159 |
+
variable_expenses_per_unit_year1_input = gr.Number(label="Variable Expenses per Unit Year 1 (Lacs)", value=0.001) # e.g., 100 Rs
|
| 160 |
+
units_growth_rate_input = gr.Number(label="Units Growth Rate (%)", value=10)
|
| 161 |
+
revenue_growth_rate_input = gr.Number(label="Revenue per Unit Growth Rate (%)", value=5) # Clarified label
|
| 162 |
+
cogs_growth_rate_input = gr.Number(label="COGS per Unit Growth Rate (%)", value=3) # Clarified label
|
| 163 |
+
fixed_expenses_growth_rate_input = gr.Number(label="Fixed Expenses Growth Rate (%)", value=4)
|
| 164 |
+
variable_expenses_growth_rate_input = gr.Number(label="Variable Expenses per Unit Growth Rate (%)", value=3) # Clarified label
|
| 165 |
+
|
| 166 |
+
# Define output components
|
| 167 |
+
# Specify x and y for LinePlots
|
| 168 |
+
revenue_output = gr.LinePlot(x="Year", y="Revenue", label="Revenue (Lacs)", title="5-Year Revenue Projection")
|
| 169 |
+
expenses_output = gr.LinePlot(x="Year", y="Expenses", label="Expenses (Lacs)", title="5-Year Expenses Projection")
|
| 170 |
+
profit_output = gr.LinePlot(x="Year", y="Net Profit", label="Net Profit (Lacs)", title="5-Year Net Profit Projection")
|
| 171 |
+
cumulative_profit_plot_output = gr.LinePlot(x="Year", y="Cumulative Net Profit", label="Cumulative Net Profit (Lacs)", title="5-Year Cumulative Net Profit") # Renamed for clarity
|
| 172 |
+
|
| 173 |
+
net_profit_margin_output = gr.Text(label="Avg. Net Profit Margin (%)", info="Average percentage of revenue kept as profit after ALL expenses over 5 years.")
|
| 174 |
+
gross_profit_margin_output = gr.Text(label="Avg. Gross Profit Margin (%)", info="Average percentage of revenue left after paying direct costs (COGS) over 5 years.")
|
| 175 |
+
operating_profit_margin_output = gr.Text(label="Avg. Operating Profit Margin (%)", info="Average percentage of revenue left after COGS and operating expenses (fixed + variable) over 5 years. (Same as Net Profit Margin in this model).")
|
| 176 |
+
# Renamed component variable for clarity
|
| 177 |
+
final_cumulative_net_profit_output = gr.Text(label="Total Cumulative Net Profit (Lacs)", info="The total profit accumulated over the 5-year period.")
|
| 178 |
+
roi_output = gr.Text(label="Simple ROI (%)", info="Return on Investment: (Total 5yr Net Profit / Initial Investment) * 100. Doesn't account for time value of money.")
|
| 179 |
+
break_even_year_output = gr.Text(label="Break-even Year", info="The year when cumulative net profit first equals or exceeds the initial investment.")
|
| 180 |
+
npv_output = gr.Text(label="NPV (Lacs)", info="Net Present Value at a 10% discount rate. Positive value suggests the investment exceeds the required return.")
|
| 181 |
+
irr_output = gr.Text(label="IRR (%)", info="Internal Rate of Return. The effective annual rate of return generated by the investment. Compare to your minimum acceptable rate.")
|
| 182 |
+
|
| 183 |
+
# Create the interface
|
| 184 |
+
iface = gr.Interface(
|
| 185 |
+
fn=financial_projection,
|
| 186 |
+
inputs=[initial_investment_input, passive_income_investment_input, return_rate_input, units_year1_input, revenue_per_unit_year1_input, cogs_per_unit_year1_input, fixed_expenses_year1_input, variable_expenses_per_unit_year1_input, units_growth_rate_input, revenue_growth_rate_input, cogs_growth_rate_input, fixed_expenses_growth_rate_input, variable_expenses_growth_rate_input],
|
| 187 |
+
# Ensure the outputs list matches the return statement order and types
|
| 188 |
+
outputs=[
|
| 189 |
+
revenue_output, # Expects DataFrame
|
| 190 |
+
expenses_output, # Expects DataFrame
|
| 191 |
+
profit_output, # Expects DataFrame
|
| 192 |
+
cumulative_profit_plot_output, # Expects DataFrame (Corrected name)
|
| 193 |
+
net_profit_margin_output, # Expects String
|
| 194 |
+
gross_profit_margin_output, # Expects String
|
| 195 |
+
operating_profit_margin_output, # Expects String
|
| 196 |
+
final_cumulative_net_profit_output, # Expects String (Corrected name)
|
| 197 |
+
roi_output, # Expects String
|
| 198 |
+
break_even_year_output, # Expects String
|
| 199 |
+
npv_output, # Expects String
|
| 200 |
+
irr_output # Expects String
|
| 201 |
+
],
|
| 202 |
+
title="5-Year Financial Projection Calculator (Amounts in Lacs)",
|
| 203 |
+
description="Enter business assumptions (in Lacs where specified) to project financials and key performance indicators over 5 years.",
|
| 204 |
+
theme=gr.themes.Soft(primary_hue="green", secondary_hue="blue"),
|
| 205 |
+
allow_flagging='never' # Optional: disable flagging
|
| 206 |
+
)
|
| 207 |
+
|
| 208 |
+
# Launch the app
|
| 209 |
+
iface.launch()
|