Spaces:
Sleeping
Sleeping
# Financial Metrics Calculator.ipynb | |
import pandas as pd | |
import json | |
import numpy as np | |
class FinancialMetricsCalculator: | |
def __init__(self): | |
print("Initializing Financial Metrics Calculator...") | |
def clean_number(self, value): | |
"""Clean and convert numerical values""" | |
try: | |
if isinstance(value, str): | |
value = value.replace('$', '').replace(',', '').strip() | |
if '(' in value and ')' in value: | |
value = '-' + value.replace('(', '').replace(')', '') | |
return float(value or 0) | |
except: | |
return 0.0 | |
def is_valid_markdown(self, file_path): | |
"""Check if a file is a valid Markdown file""" | |
try: | |
with open(file_path, 'r') as f: | |
content = f.read() | |
return any(line.startswith('#') or '|' in line for line in content.split('\n')) | |
except: | |
return False | |
def parse_financial_data(self, content): | |
"""Parse markdown content into structured data""" | |
try: | |
data = {} | |
current_section = "" | |
current_table = [] | |
headers = None | |
for line in content.split('\n'): | |
if line.startswith('#'): | |
if current_table and headers: | |
data[current_section] = self.process_table(headers, current_table) | |
current_section = line.strip('# ') | |
current_table = [] | |
headers = None | |
elif '|' in line: | |
if '-|-' not in line: | |
row = [cell.strip() for cell in line.split('|')[1:-1]] | |
if not headers: | |
headers = row | |
else: | |
current_table.append(row) | |
if current_table and headers: | |
data[current_section] = self.process_table(headers, current_table) | |
return data | |
except Exception as e: | |
print(f"Error parsing financial data: {str(e)}") | |
return {} | |
def process_table(self, headers, rows): | |
"""Process table data into structured format""" | |
try: | |
processed_data = {} | |
for row in rows: | |
if len(row) == len(headers): | |
item_name = row[0].strip('*').strip() | |
processed_data[item_name] = {} | |
for i, value in enumerate(row[1:], 1): | |
processed_data[item_name][headers[i]] = self.clean_number(value) | |
return processed_data | |
except Exception as e: | |
print(f"Error processing table: {str(e)}") | |
return {} | |
def get_nested_value(self, data, section, key, year): | |
"""Safely get nested dictionary value""" | |
try: | |
return data.get(section, {}).get(key, {}).get(str(year), 0) | |
except: | |
return 0 | |
def extract_metrics(self, income_data, balance_data): | |
"""Extract and calculate key financial metrics""" | |
try: | |
metrics = { | |
"Revenue": { | |
"2025": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2025"), | |
"2024": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2024"), | |
"2021": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2021") | |
}, | |
"Profitability": { | |
"Gross_Profit_2025": self.get_nested_value(income_data, "Cost and Gross Profit", "Gross Profit", "2025"), | |
"EBIT_2025": self.get_nested_value(income_data, "Profit Summary", "EBIT", "2025"), | |
"Net_Earnings_2025": self.get_nested_value(income_data, "Profit Summary", "Net Earnings", "2025"), | |
"Operating_Expenses_2025": self.get_nested_value(income_data, "Operating Expenses", "Total Operating Expenses", "2025") | |
}, | |
"Balance_Sheet": { | |
"Total_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Assets", "2025"), | |
"Current_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Assets", "2025"), | |
"Total_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Liabilities", "2025"), | |
"Current_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Liabilities", "2025"), | |
"Equity_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Shareholders_Equity", "2025"), | |
"Inventory_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Inventory", "2025"), | |
"Accounts_Receivable_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Accounts_Receivable", "2025"), | |
"Long_Term_Debt_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Long_Term_Debt", "2025") | |
}, | |
"Cash_Flow": { | |
"Depreciation_2025": self.get_nested_value(income_data, "Operating Expenses", "Depreciation & Amortization", "2025"), | |
"Interest_Expense_2025": self.get_nested_value(income_data, "Profit Summary", "Interest Expense", "2025") | |
} | |
} | |
revenue_2025 = metrics["Revenue"]["2025"] | |
if revenue_2025 != 0: | |
metrics["Ratios"] = self.calculate_financial_ratios(metrics, revenue_2025) | |
return metrics | |
except Exception as e: | |
print(f"Error extracting metrics: {str(e)}") | |
return {} | |
def calculate_financial_ratios(self, metrics, revenue): | |
"""Calculate financial ratios""" | |
return { | |
"Gross_Margin": (metrics["Profitability"]["Gross_Profit_2025"] / revenue) * 100, | |
"Operating_Margin": (metrics["Profitability"]["EBIT_2025"] / revenue) * 100, | |
"Net_Margin": (metrics["Profitability"]["Net_Earnings_2025"] / revenue) * 100, | |
"Current_Ratio": metrics["Balance_Sheet"]["Current_Assets_2025"] / metrics["Balance_Sheet"]["Current_Liabilities_2025"] if metrics["Balance_Sheet"]["Current_Liabilities_2025"] != 0 else 0, | |
"Quick_Ratio": (metrics["Balance_Sheet"]["Current_Assets_2025"] - metrics["Balance_Sheet"]["Inventory_2025"]) / metrics["Balance_Sheet"]["Current_Liabilities_2025"] if metrics["Balance_Sheet"]["Current_Liabilities_2025"] != 0 else 0, | |
"Asset_Turnover": revenue / metrics["Balance_Sheet"]["Total_Assets_2025"] if metrics["Balance_Sheet"]["Total_Assets_2025"] != 0 else 0, | |
"Receivables_Turnover": revenue / metrics["Balance_Sheet"]["Accounts_Receivable_2025"] if metrics["Balance_Sheet"]["Accounts_Receivable_2025"] != 0 else 0, | |
"Debt_to_Equity": metrics["Balance_Sheet"]["Total_Liabilities_2025"] / metrics["Balance_Sheet"]["Equity_2025"] if metrics["Balance_Sheet"]["Equity_2025"] != 0 else 0, | |
"Interest_Coverage": metrics["Profitability"]["EBIT_2025"] / metrics["Cash_Flow"]["Interest_Expense_2025"] if metrics["Cash_Flow"]["Interest_Expense_2025"] != 0 else 0, | |
"Revenue_Growth": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2024"]) - 1) * 100 if metrics["Revenue"]["2024"] != 0 else 0, | |
"5Year_Revenue_CAGR": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2021"]) ** (1/4) - 1) * 100 if metrics["Revenue"]["2021"] != 0 else 0 | |
} | |
def process_financial_statements(self, balance_sheet_file, income_stmt_file): | |
"""Process financial statements and return metrics""" | |
try: | |
if not (self.is_valid_markdown(balance_sheet_file) and self.is_valid_markdown(income_stmt_file)): | |
return "Error: Invalid file format" | |
with open(balance_sheet_file, 'r') as f: | |
balance_sheet = f.read() | |
with open(income_stmt_file, 'r') as f: | |
income_stmt = f.read() | |
income_data = self.parse_financial_data(income_stmt) | |
balance_data = self.parse_financial_data(balance_sheet) | |
metrics = self.extract_metrics(income_data, balance_data) | |
return metrics | |
except Exception as e: | |
print(f"Error processing statements: {str(e)}") | |
return None | |
# Example usage | |
if __name__ == "__main__": | |
calculator = FinancialMetricsCalculator() | |
# Test with your markdown files | |
metrics = calculator.process_financial_statements('balance_sheet.md', 'income_statement.md') | |
print(json.dumps(metrics, indent=2)) | |