walaa2022 commited on
Commit
cd3edfb
·
verified ·
1 Parent(s): db53aac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +106 -66
app.py CHANGED
@@ -25,9 +25,7 @@ class FinancialAnalyzer:
25
  """Clean and convert numerical values"""
26
  try:
27
  if isinstance(value, str):
28
- # Remove currency symbols, commas, spaces
29
  value = value.replace('$', '').replace(',', '').strip()
30
- # Handle parentheses for negative numbers
31
  if '(' in value and ')' in value:
32
  value = '-' + value.replace('(', '').replace(')', '')
33
  return float(value or 0)
@@ -39,7 +37,6 @@ class FinancialAnalyzer:
39
  try:
40
  with open(file_path, 'r') as f:
41
  content = f.read()
42
- # Simple check for Markdown structure
43
  return any(line.startswith('#') or '|' in line for line in content.split('\n'))
44
  except:
45
  return False
@@ -60,14 +57,13 @@ class FinancialAnalyzer:
60
  current_table = []
61
  headers = None
62
  elif '|' in line:
63
- if '-|-' not in line: # Skip separator lines
64
  row = [cell.strip() for cell in line.split('|')[1:-1]]
65
  if not headers:
66
  headers = row
67
  else:
68
  current_table.append(row)
69
 
70
- # Process last table
71
  if current_table and headers:
72
  data[current_section] = self.process_table(headers, current_table)
73
 
@@ -91,69 +87,122 @@ class FinancialAnalyzer:
91
  print(f"Error processing table: {str(e)}")
92
  return {}
93
 
 
 
 
 
 
 
 
94
  def extract_metrics(self, income_data, balance_data):
95
  """Extract and calculate key financial metrics"""
96
  try:
97
- # Get current and previous year values for growth calculations
98
  metrics = {
99
- "Revenue": {
100
- "2025": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2025"),
101
- "2024": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2024"),
102
- "2021": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2021")
103
- },
104
- "Profitability": {
105
- "Gross_Profit_2025": self.get_nested_value(income_data, "Cost and Gross Profit", "Gross Profit", "2025"),
106
- "EBIT_2025": self.get_nested_value(income_data, "Profit Summary", "EBIT", "2025"),
107
- "Net_Earnings_2025": self.get_nested_value(income_data, "Profit Summary", "Net Earnings", "2025"),
108
- "Operating_Expenses_2025": self.get_nested_value(income_data, "Operating Expenses", "Total Operating Expenses", "2025")
109
- },
110
- "Balance_Sheet": {
111
- "Total_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Assets", "2025"),
112
- "Current_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Assets", "2025"),
113
- "Total_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Liabilities", "2025"),
114
- "Current_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Liabilities", "2025"),
115
- "Equity_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Shareholders_Equity", "2025"),
116
- "Inventory_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Inventory", "2025"),
117
- "Accounts_Receivable_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Accounts_Receivable", "2025"),
118
- "Long_Term_Debt_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Long_Term_Debt", "2025")
119
- },
120
- "Cash_Flow": {
121
- "Depreciation_2025": self.get_nested_value(income_data, "Operating Expenses", "Depreciation & Amortization", "2025"),
122
- "Interest_Expense_2025": self.get_nested_value(income_data, "Profit Summary", "Interest Expense", "2025")
 
123
  }
124
- }
125
-
126
- # Calculate financial ratios
127
  revenue_2025 = metrics["Revenue"]["2025"]
128
  if revenue_2025 != 0:
129
- # Profitability Ratios
130
  metrics["Ratios"] = {
131
- "Gross_Margin": (metrics["Profitability"]["Gross_Profit_2025"] / revenue_2025) * 100,
132
- "Operating_Margin": (metrics["Profitability"]["EBIT_2025"] / revenue_2025) * 100,
133
- "Net_Margin": (metrics["Profitability"]["Net_Earnings_2025"] / revenue_2025) * 100,
134
-
135
- # Liquidity Ratios
136
- "Current_Ratio": metrics["Balance_Sheet"]["Current_Assets_2025"] / metrics["Balance_Sheet"]["Current_Liabilities_2025"],
137
- "Quick_Ratio": (metrics["Balance_Sheet"]["Current_Assets_2025"] - metrics["Balance_Sheet"]["Inventory_2025"]) / metrics["Balance_Sheet"]["Current_Liabilities_2025"],
138
-
139
- # Efficiency Ratios
140
- "Asset_Turnover": revenue_2025 / metrics["Balance_Sheet"]["Total_Assets_2025"],
141
- "Receivables_Turnover": revenue_2025 / metrics["Balance_Sheet"]["Accounts_Receivable_2025"],
142
-
143
- # Solvency Ratios
144
- "Debt_to_Equity": metrics["Balance_Sheet"]["Total_Liabilities_2025"] / metrics["Balance_Sheet"]["Equity_2025"],
145
- "Interest_Coverage": metrics["Profitability"]["EBIT_2025"] / metrics["Cash_Flow"]["Interest_Expense_2025"] if metrics["Cash_Flow"]["Interest_Expense_2025"] != 0 else 0,
146
-
147
- # Growth Rates
148
- "Revenue_Growth": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2024"]) - 1) * 100,
149
- "5Year_Revenue_CAGR": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2021"]) ** (1/4) - 1) * 100
150
  }
151
-
152
  return metrics
153
  except Exception as e:
154
  print(f"Error extracting metrics: {str(e)}")
155
  return {}
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  def generate_analysis(self, prompt):
158
  """Generate analysis using TinyLlama"""
159
  try:
@@ -161,7 +210,7 @@ class FinancialAnalyzer:
161
 
162
  outputs = self.model.generate(
163
  inputs["input_ids"],
164
- max_new_tokens=800, # Increased from 500 to 800 for more detailed analysis
165
  temperature=0.7,
166
  top_p=0.9,
167
  do_sample=True,
@@ -170,7 +219,6 @@ class FinancialAnalyzer:
170
  )
171
 
172
  analysis = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
173
- # Clean up the response
174
  analysis = analysis.split("<human>")[-1].strip()
175
  return analysis
176
  except Exception as e:
@@ -179,28 +227,20 @@ class FinancialAnalyzer:
179
  def analyze_financials(self, balance_sheet_file, income_stmt_file):
180
  """Main analysis function"""
181
  try:
182
- # Validate files
183
  if not (self.is_valid_markdown(balance_sheet_file) and self.is_valid_markdown(income_stmt_file)):
184
  return "Error: One or both files are invalid or not in Markdown format."
185
 
186
- # Read files
187
  with open(balance_sheet_file, 'r') as f:
188
  balance_sheet = f.read()
189
  with open(income_stmt_file, 'r') as f:
190
  income_stmt = f.read()
191
 
192
- # Parse financial data
193
  income_data = self.parse_financial_data(income_stmt)
194
  balance_data = self.parse_financial_data(balance_sheet)
195
-
196
- # Extract key metrics
197
  metrics = self.extract_metrics(income_data, balance_data)
198
-
199
- # Generate and get analysis
200
- prompt = self.generate_analysis_prompt(metrics)
201
  analysis = self.generate_analysis(prompt)
202
 
203
- # Prepare results
204
  results = {
205
  "Financial Analysis": {
206
  "Key Metrics": metrics,
@@ -233,4 +273,4 @@ def create_interface():
233
 
234
  if __name__ == "__main__":
235
  iface = create_interface()
236
- iface.launch()
 
25
  """Clean and convert numerical values"""
26
  try:
27
  if isinstance(value, str):
 
28
  value = value.replace('$', '').replace(',', '').strip()
 
29
  if '(' in value and ')' in value:
30
  value = '-' + value.replace('(', '').replace(')', '')
31
  return float(value or 0)
 
37
  try:
38
  with open(file_path, 'r') as f:
39
  content = f.read()
 
40
  return any(line.startswith('#') or '|' in line for line in content.split('\n'))
41
  except:
42
  return False
 
57
  current_table = []
58
  headers = None
59
  elif '|' in line:
60
+ if '-|-' not in line:
61
  row = [cell.strip() for cell in line.split('|')[1:-1]]
62
  if not headers:
63
  headers = row
64
  else:
65
  current_table.append(row)
66
 
 
67
  if current_table and headers:
68
  data[current_section] = self.process_table(headers, current_table)
69
 
 
87
  print(f"Error processing table: {str(e)}")
88
  return {}
89
 
90
+ def get_nested_value(self, data, section, key, year):
91
+ """Safely get nested dictionary value"""
92
+ try:
93
+ return data.get(section, {}).get(key, {}).get(str(year), 0)
94
+ except:
95
+ return 0
96
+
97
  def extract_metrics(self, income_data, balance_data):
98
  """Extract and calculate key financial metrics"""
99
  try:
 
100
  metrics = {
101
+ "Revenue": {
102
+ "2025": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2025"),
103
+ "2024": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2024"),
104
+ "2021": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2021")
105
+ },
106
+ "Profitability": {
107
+ "Gross_Profit_2025": self.get_nested_value(income_data, "Cost and Gross Profit", "Gross Profit", "2025"),
108
+ "EBIT_2025": self.get_nested_value(income_data, "Profit Summary", "EBIT", "2025"),
109
+ "Net_Earnings_2025": self.get_nested_value(income_data, "Profit Summary", "Net Earnings", "2025"),
110
+ "Operating_Expenses_2025": self.get_nested_value(income_data, "Operating Expenses", "Total Operating Expenses", "2025")
111
+ },
112
+ "Balance_Sheet": {
113
+ "Total_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Assets", "2025"),
114
+ "Current_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Assets", "2025"),
115
+ "Total_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Liabilities", "2025"),
116
+ "Current_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Liabilities", "2025"),
117
+ "Equity_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Shareholders_Equity", "2025"),
118
+ "Inventory_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Inventory", "2025"),
119
+ "Accounts_Receivable_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Accounts_Receivable", "2025"),
120
+ "Long_Term_Debt_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Long_Term_Debt", "2025")
121
+ },
122
+ "Cash_Flow": {
123
+ "Depreciation_2025": self.get_nested_value(income_data, "Operating Expenses", "Depreciation & Amortization", "2025"),
124
+ "Interest_Expense_2025": self.get_nested_value(income_data, "Profit Summary", "Interest Expense", "2025")
125
+ }
126
  }
127
+
 
 
128
  revenue_2025 = metrics["Revenue"]["2025"]
129
  if revenue_2025 != 0:
 
130
  metrics["Ratios"] = {
131
+ "Gross_Margin": (metrics["Profitability"]["Gross_Profit_2025"] / revenue_2025) * 100,
132
+ "Operating_Margin": (metrics["Profitability"]["EBIT_2025"] / revenue_2025) * 100,
133
+ "Net_Margin": (metrics["Profitability"]["Net_Earnings_2025"] / revenue_2025) * 100,
134
+
135
+ "Current_Ratio": metrics["Balance_Sheet"]["Current_Assets_2025"] / metrics["Balance_Sheet"]["Current_Liabilities_2025"] if metrics["Balance_Sheet"]["Current_Liabilities_2025"] != 0 else 0,
136
+ "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,
137
+
138
+ "Asset_Turnover": revenue_2025 / metrics["Balance_Sheet"]["Total_Assets_2025"] if metrics["Balance_Sheet"]["Total_Assets_2025"] != 0 else 0,
139
+ "Receivables_Turnover": revenue_2025 / metrics["Balance_Sheet"]["Accounts_Receivable_2025"] if metrics["Balance_Sheet"]["Accounts_Receivable_2025"] != 0 else 0,
140
+
141
+ "Debt_to_Equity": metrics["Balance_Sheet"]["Total_Liabilities_2025"] / metrics["Balance_Sheet"]["Equity_2025"] if metrics["Balance_Sheet"]["Equity_2025"] != 0 else 0,
142
+ "Interest_Coverage": metrics["Profitability"]["EBIT_2025"] / metrics["Cash_Flow"]["Interest_Expense_2025"] if metrics["Cash_Flow"]["Interest_Expense_2025"] != 0 else 0,
143
+
144
+ "Revenue_Growth": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2024"]) - 1) * 100 if metrics["Revenue"]["2024"] != 0 else 0,
145
+ "5Year_Revenue_CAGR": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2021"]) ** (1/4) - 1) * 100 if metrics["Revenue"]["2021"] != 0 else 0
 
 
 
 
146
  }
147
+
148
  return metrics
149
  except Exception as e:
150
  print(f"Error extracting metrics: {str(e)}")
151
  return {}
152
 
153
+ def generate_prompt(self, metrics):
154
+ """Create analysis prompt from metrics"""
155
+ try:
156
+ return f"""<human>
157
+ Please provide a comprehensive financial analysis for 2025 with detailed insights on:
158
+
159
+ 1. Revenue and Growth:
160
+ - Total Revenue: ${metrics['Revenue']['2025']:,.1f}M
161
+ - YoY Growth Rate: {metrics['Ratios'].get('Revenue_Growth', 0):,.1f}%
162
+ - 5-Year CAGR: {metrics['Ratios'].get('5Year_Revenue_CAGR', 0):,.1f}%
163
+
164
+ 2. Profitability Analysis:
165
+ - Gross Profit: ${metrics['Profitability']['Gross_Profit_2025']:,.1f}M
166
+ - EBIT: ${metrics['Profitability']['EBIT_2025']:,.1f}M
167
+ - Net Earnings: ${metrics['Profitability']['Net_Earnings_2025']:,.1f}M
168
+ - Margin Analysis:
169
+ * Gross Margin: {metrics['Ratios'].get('Gross_Margin', 0):,.1f}%
170
+ * Operating Margin: {metrics['Ratios'].get('Operating_Margin', 0):,.1f}%
171
+ * Net Margin: {metrics['Ratios'].get('Net_Margin', 0):,.1f}%
172
+
173
+ 3. Balance Sheet Strength:
174
+ - Total Assets: ${metrics['Balance_Sheet']['Total_Assets_2025']:,.1f}M
175
+ - Total Liabilities: ${metrics['Balance_Sheet']['Total_Liabilities_2025']:,.1f}M
176
+ - Shareholders' Equity: ${metrics['Balance_Sheet']['Equity_2025']:,.1f}M
177
+
178
+ 4. Key Financial Ratios:
179
+ - Liquidity:
180
+ * Current Ratio: {metrics['Ratios'].get('Current_Ratio', 0):,.2f}
181
+ * Quick Ratio: {metrics['Ratios'].get('Quick_Ratio', 0):,.2f}
182
+ - Efficiency:
183
+ * Asset Turnover: {metrics['Ratios'].get('Asset_Turnover', 0):,.2f}
184
+ * Receivables Turnover: {metrics['Ratios'].get('Receivables_Turnover', 0):,.2f}
185
+ - Solvency:
186
+ * Debt-to-Equity: {metrics['Ratios'].get('Debt_to_Equity', 0):,.2f}
187
+ * Interest Coverage: {metrics['Ratios'].get('Interest_Coverage', 0):,.2f}
188
+
189
+ Please provide:
190
+ 1. An assessment of overall financial health and performance trends
191
+ 2. Key strengths and potential areas of concern
192
+ 3. Analysis of operational efficiency and working capital management
193
+ 4. Evaluation of capital structure and debt management
194
+ 5. Specific recommendations for:
195
+ - Improving operational efficiency
196
+ - Optimizing capital structure
197
+ - Enhancing shareholder value
198
+ - Managing key risks identified
199
+
200
+ Include quantitative support for your analysis and recommendations.
201
+ </human>"""
202
+ except Exception as e:
203
+ print(f"Error generating prompt: {str(e)}")
204
+ return ""
205
+
206
  def generate_analysis(self, prompt):
207
  """Generate analysis using TinyLlama"""
208
  try:
 
210
 
211
  outputs = self.model.generate(
212
  inputs["input_ids"],
213
+ max_new_tokens=800,
214
  temperature=0.7,
215
  top_p=0.9,
216
  do_sample=True,
 
219
  )
220
 
221
  analysis = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
 
222
  analysis = analysis.split("<human>")[-1].strip()
223
  return analysis
224
  except Exception as e:
 
227
  def analyze_financials(self, balance_sheet_file, income_stmt_file):
228
  """Main analysis function"""
229
  try:
 
230
  if not (self.is_valid_markdown(balance_sheet_file) and self.is_valid_markdown(income_stmt_file)):
231
  return "Error: One or both files are invalid or not in Markdown format."
232
 
 
233
  with open(balance_sheet_file, 'r') as f:
234
  balance_sheet = f.read()
235
  with open(income_stmt_file, 'r') as f:
236
  income_stmt = f.read()
237
 
 
238
  income_data = self.parse_financial_data(income_stmt)
239
  balance_data = self.parse_financial_data(balance_sheet)
 
 
240
  metrics = self.extract_metrics(income_data, balance_data)
241
+ prompt = self.generate_prompt(metrics)
 
 
242
  analysis = self.generate_analysis(prompt)
243
 
 
244
  results = {
245
  "Financial Analysis": {
246
  "Key Metrics": metrics,
 
273
 
274
  if __name__ == "__main__":
275
  iface = create_interface()
276
+ iface.launch()