walaa2022 commited on
Commit
ab0bea5
·
verified ·
1 Parent(s): f712719

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +195 -160
app.py CHANGED
@@ -2,198 +2,233 @@ import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
  import json
5
- import chromadb
6
- from chromadb.config import Settings
7
- from datetime import datetime
8
 
9
- class FastFinancialAnalyzer:
10
  def __init__(self):
11
- # Initialize ChromaDB
12
- self.client = chromadb.Client(Settings(anonymized_telemetry=False))
 
 
 
 
 
 
13
 
14
- # Create financial metrics collection
15
- self.collection = self.client.create_collection(
16
- name="financial_metrics_" + datetime.now().strftime("%Y%m%d_%H%M%S")
17
- )
18
-
19
- # Initialize ratio benchmarks
20
- self.initialize_ratio_benchmarks()
21
-
22
- def initialize_ratio_benchmarks(self):
23
- """Initialize benchmark ratios for comparison"""
24
- self.benchmarks = {
25
- "liquidity_ratios": {
26
- "current_ratio": {"good": 2.0, "warning": 1.0},
27
- "quick_ratio": {"good": 1.0, "warning": 0.5}
28
  },
29
- "profitability_ratios": {
30
- "gross_margin": {"good": 0.4, "warning": 0.2},
31
- "net_margin": {"good": 0.1, "warning": 0.05}
 
32
  },
33
- "efficiency_ratios": {
34
- "inventory_turnover": {"good": 4, "warning": 2},
35
- "asset_turnover": {"good": 0.5, "warning": 0.25}
36
  }
37
  }
38
 
39
- def calculate_ratios(self, balance_sheet_df, income_stmt_df):
40
- """Calculate key financial ratios"""
 
 
 
 
41
  try:
42
- ratios = {}
43
-
44
- # Clean numeric data
45
- for df in [balance_sheet_df, income_stmt_df]:
46
- for col in df.select_dtypes(include=['object']).columns:
47
- df[col] = pd.to_numeric(df[col].astype(str).str.replace(r'[^\d.-]', ''), errors='coerce')
48
-
49
- # Calculate ratios for each year
50
- years = [col for col in balance_sheet_df.columns if str(col).isdigit()]
51
- for year in years:
52
- ratios[year] = {
53
- "liquidity": {
54
- "current_ratio": balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Assets', year].values[0] /
55
- balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Liabilities', year].values[0],
56
- "quick_ratio": (balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Assets', year].values[0] -
57
- balance_sheet_df.loc[balance_sheet_df['Account'] == 'Inventory', year].values[0]) /
58
- balance_sheet_df.loc[balance_sheet_df['Account'] == 'Total_Current_Liabilities', year].values[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  },
60
- "profitability": {
61
- "gross_margin": income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Gross Profit', year].values[0] /
62
- income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', year].values[0],
63
- "net_margin": income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Net Earnings', year].values[0] /
64
- income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', year].values[0]
65
  },
66
- "growth": {
67
- "revenue_growth": None if year == years[0] else
68
- (income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', year].values[0] -
69
- income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', str(int(year)-1)].values[0]) /
70
- income_stmt_df.loc[income_stmt_df['Revenue Items'] == 'Total Net Revenue', str(int(year)-1)].values[0] * 100
 
 
 
71
  }
72
  }
73
-
74
- return ratios
75
-
76
- except Exception as e:
77
- return f"Error calculating ratios: {str(e)}"
78
-
79
- def analyze_trends(self, ratios):
80
- """Analyze financial trends"""
81
- trends = {
82
- "liquidity": self.analyze_ratio_trend("current_ratio", ratios),
83
- "profitability": self.analyze_ratio_trend("net_margin", ratios),
84
- "growth": self.analyze_revenue_growth(ratios)
85
- }
86
- return trends
87
 
88
- def analyze_ratio_trend(self, ratio_name, ratios):
89
- """Analyze trend for a specific ratio"""
90
- values = []
91
- years = sorted(ratios.keys())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
- for year in years:
94
- if ratio_name in ratios[year].get("liquidity", {}):
95
- values.append(ratios[year]["liquidity"][ratio_name])
96
- elif ratio_name in ratios[year].get("profitability", {}):
97
- values.append(ratios[year]["profitability"][ratio_name])
98
 
99
- if not values:
100
- return "No data available"
 
 
 
 
 
 
101
 
102
- trend = np.polyfit(range(len(values)), values, 1)[0]
103
-
104
- if trend > 0.05:
105
- return "Strong upward trend"
106
- elif trend > 0:
107
- return "Slight upward trend"
108
- elif trend > -0.05:
109
- return "Stable"
110
- else:
111
- return "Downward trend"
112
-
113
- def analyze_revenue_growth(self, ratios):
114
- """Analyze revenue growth trend"""
115
- growth_rates = []
116
- years = sorted(ratios.keys())[1:] # Skip first year as it won't have growth rate
117
-
118
- for year in years:
119
- if ratios[year]["growth"]["revenue_growth"] is not None:
120
- growth_rates.append(ratios[year]["growth"]["revenue_growth"])
121
-
122
- if not growth_rates:
123
- return "No growth data available"
124
-
125
- avg_growth = np.mean(growth_rates)
126
- if avg_growth > 10:
127
- return f"Strong growth (avg {avg_growth:.1f}%)"
128
- elif avg_growth > 0:
129
- return f"Moderate growth (avg {avg_growth:.1f}%)"
130
- else:
131
- return f"Declining growth (avg {avg_growth:.1f}%)"
132
-
133
- def generate_insights(self, ratios, trends):
134
- """Generate actionable insights"""
135
- insights = []
136
-
137
- # Liquidity insights
138
- current_ratio = ratios[max(ratios.keys())]["liquidity"]["current_ratio"]
139
- if current_ratio < self.benchmarks["liquidity_ratios"]["current_ratio"]["warning"]:
140
- insights.append("ALERT: Liquidity needs immediate attention")
141
- elif current_ratio < self.benchmarks["liquidity_ratios"]["current_ratio"]["good"]:
142
- insights.append("WATCH: Liquidity is below ideal levels")
143
-
144
- # Profitability insights
145
- net_margin = ratios[max(ratios.keys())]["profitability"]["net_margin"]
146
- if net_margin > self.benchmarks["profitability_ratios"]["net_margin"]["good"]:
147
- insights.append("STRONG: Excellent profit margins")
148
- elif net_margin < self.benchmarks["profitability_ratios"]["net_margin"]["warning"]:
149
- insights.append("ALERT: Profit margins need improvement")
150
-
151
- # Growth insights
152
- if "growth" in trends:
153
- if "Strong" in trends["growth"]:
154
- insights.append("POSITIVE: Strong revenue growth trend")
155
- elif "Declining" in trends["growth"]:
156
- insights.append("WATCH: Revenue growth is slowing")
157
-
158
- return insights
159
 
160
  def analyze_financials(self, balance_sheet_file, income_stmt_file):
161
- """Main analysis function"""
162
  try:
163
  # Read files
164
  balance_sheet_df = pd.read_csv(balance_sheet_file)
165
  income_stmt_df = pd.read_csv(income_stmt_file)
166
 
167
- # Calculate ratios
168
- ratios = self.calculate_ratios(balance_sheet_df, income_stmt_df)
169
-
170
- # Analyze trends
171
- trends = self.analyze_trends(ratios)
 
 
 
172
 
173
  # Generate insights
174
- insights = self.generate_insights(ratios, trends)
 
175
 
176
- # Prepare comprehensive analysis
 
 
 
 
177
  analysis = {
178
- "Financial Ratios": ratios,
179
- "Trend Analysis": trends,
180
- "Key Insights": insights,
181
- "Summary": {
182
- "Latest Year Analysis": {
183
- "Current Ratio": f"{ratios[max(ratios.keys())]['liquidity']['current_ratio']:.2f}",
184
- "Net Margin": f"{ratios[max(ratios.keys())]['profitability']['net_margin']:.2%}",
185
- "Revenue Growth": f"{ratios[max(ratios.keys())]['growth']['revenue_growth']:.2f}%" if ratios[max(ratios.keys())]['growth']['revenue_growth'] else "N/A"
186
- }
187
- }
188
  }
189
-
190
  return json.dumps(analysis, indent=2)
191
 
192
  except Exception as e:
193
  return f"Error in analysis: {str(e)}"
194
 
195
  def create_interface():
196
- analyzer = FastFinancialAnalyzer()
197
 
198
  iface = gr.Interface(
199
  fn=analyzer.analyze_financials,
@@ -201,9 +236,9 @@ def create_interface():
201
  gr.File(label="Balance Sheet (CSV)", type="filepath"),
202
  gr.File(label="Income Statement (CSV)", type="filepath")
203
  ],
204
- outputs=gr.Textbox(label="Analysis Results", lines=20),
205
- title="Fast Financial Statement Analyzer",
206
- description="Upload financial statements for instant analysis with ratio calculations and trend detection."
207
  )
208
 
209
  return iface
 
2
  import pandas as pd
3
  import numpy as np
4
  import json
5
+ from transformers import AutoTokenizer, AutoModelForCausalLM, AutoModelForSequenceClassification
6
+ import torch
 
7
 
8
+ class FinancialAnalyzer:
9
  def __init__(self):
10
+ print("Initializing Financial Analyzer...")
11
+ self.initialize_models()
12
+ self.initialize_benchmarks()
13
+
14
+ def initialize_models(self):
15
+ print("Loading models...")
16
+ self.tiny_tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
17
+ self.tiny_model = AutoModelForCausalLM.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
18
 
19
+ self.finbert_tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
20
+ self.finbert_model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
21
+ print("Models loaded successfully!")
22
+
23
+ def initialize_benchmarks(self):
24
+ self.industry_benchmarks = {
25
+ "Liquidity": {
26
+ "Current Ratio": 2.0,
27
+ "Quick Ratio": 1.0
 
 
 
 
 
28
  },
29
+ "Profitability": {
30
+ "Gross Margin": 40.0,
31
+ "Operating Margin": 15.0,
32
+ "Net Margin": 10.0
33
  },
34
+ "Efficiency": {
35
+ "Asset Turnover": 2.0,
36
+ "Inventory Turnover": 6.0
37
  }
38
  }
39
 
40
+ def clean_number(self, value):
41
+ """Clean numerical values from files (all in thousands)"""
42
+ if isinstance(value, str):
43
+ # Remove currency symbols, commas, spaces and handle parentheses
44
+ value = value.replace(',', '').replace('$', '').replace(' ', '')
45
+ value = value.replace('(', '-').replace(')', '')
46
  try:
47
+ return float(value)
48
+ except:
49
+ return 0.0
50
+
51
+ def calculate_metrics(self, balance_sheet_df, income_stmt_df):
52
+ """Calculate financial metrics (all values in thousands)"""
53
+ metrics = {}
54
+ years = [str(year) for year in range(2021, 2026)]
55
+
56
+ for year in years:
57
+ try:
58
+ # Balance Sheet metrics
59
+ total_current_assets = self.clean_number(balance_sheet_df.loc[balance_sheet_df['Total_Type'] == 'Total_Current_Assets', year].iloc[0])
60
+ total_assets = self.clean_number(balance_sheet_df.loc[balance_sheet_df['Total_Type'] == 'Total_Assets', year].iloc[0])
61
+ total_current_liabilities = self.clean_number(balance_sheet_df.loc[balance_sheet_df['Total_Type'] == 'Total_Current_Liabilities', year].iloc[0])
62
+ total_liabilities = self.clean_number(balance_sheet_df.loc[balance_sheet_df['Total_Type'] == 'Total_Liabilities', year].iloc[0])
63
+ total_equity = self.clean_number(balance_sheet_df.loc[balance_sheet_df['Total_Type'] == 'Total_Shareholders_Equity', year].iloc[0])
64
+ inventory = self.clean_number(balance_sheet_df.loc[balance_sheet_df['Account'] == 'Inventory', year].iloc[0])
65
+
66
+ # Income Statement metrics
67
+ revenue = self.clean_number(income_stmt_df.loc[income_stmt_df.get('Revenue Items') == 'Total Net Revenue', year].iloc[0])
68
+ gross_profit = self.clean_number(income_stmt_df.loc[income_stmt_df.get('Item') == 'Gross Profit', year].iloc[0])
69
+ operating_expenses = self.clean_number(income_stmt_df.loc[income_stmt_df.get('Expense Category') == 'Total Operating Expenses', year].iloc[0])
70
+ ebit = self.clean_number(income_stmt_df.loc[income_stmt_df.get('Item') == 'EBIT', year].iloc[0])
71
+ net_earnings = self.clean_number(income_stmt_df.loc[income_stmt_df.get('Item') == 'Net Earnings', year].iloc[0])
72
+
73
+ metrics[year] = {
74
+ "Liquidity": {
75
+ "Current Ratio": round(total_current_assets / total_current_liabilities, 2) if total_current_liabilities != 0 else 0,
76
+ "Quick Ratio": round((total_current_assets - inventory) / total_current_liabilities, 2) if total_current_liabilities != 0 else 0
77
+ },
78
+ "Profitability": {
79
+ "Gross Margin": round((gross_profit / revenue * 100), 2) if revenue != 0 else 0,
80
+ "Operating Margin": round((ebit / revenue * 100), 2) if revenue != 0 else 0,
81
+ "Net Margin": round((net_earnings / revenue * 100), 2) if revenue != 0 else 0,
82
+ "ROE": round((net_earnings / total_equity * 100), 2) if total_equity != 0 else 0,
83
+ "ROA": round((net_earnings / total_assets * 100), 2) if total_assets != 0 else 0
84
  },
85
+ "Efficiency": {
86
+ "Asset Turnover": round(revenue / total_assets, 2) if total_assets != 0 else 0,
87
+ "Inventory Turnover": round(operating_expenses / inventory, 2) if inventory != 0 else 0
 
 
88
  },
89
+ "Leverage": {
90
+ "Debt to Equity": round(total_liabilities / total_equity, 2) if total_equity != 0 else 0,
91
+ "Debt Ratio": round(total_liabilities / total_assets, 2) if total_assets != 0 else 0
92
+ },
93
+ "Growth": {
94
+ "Revenue": None if year == '2021' else
95
+ round(((revenue - self.clean_number(income_stmt_df.loc[income_stmt_df.get('Revenue Items') == 'Total Net Revenue', str(int(year)-1)].iloc[0])) /
96
+ self.clean_number(income_stmt_df.loc[income_stmt_df.get('Revenue Items') == 'Total Net Revenue', str(int(year)-1)].iloc[0]) * 100), 2)
97
  }
98
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
+ # Add key absolute values (in thousands)
101
+ metrics[year]["Key Values"] = {
102
+ "Total Assets": total_assets,
103
+ "Total Liabilities": total_liabilities,
104
+ "Total Equity": total_equity,
105
+ "Revenue": revenue,
106
+ "Net Earnings": net_earnings
107
+ }
108
+
109
+ except Exception as e:
110
+ print(f"Error calculating metrics for year {year}: {str(e)}")
111
+ metrics[year] = "Error in calculation"
112
+
113
+ return metrics
114
+
115
+ def create_insights_prompt(self, metrics, balance_sheet, income_stmt):
116
+ latest_year_metrics = metrics['2025']
117
+ return f"""<human>Analyze these financial statements (all values in thousands) and provide detailed insights:
118
+
119
+ Key Metrics for Latest Year (2025):
120
+ - Current Ratio: {latest_year_metrics['Liquidity']['Current Ratio']}
121
+ - Net Margin: {latest_year_metrics['Profitability']['Net Margin']}%
122
+ - Revenue: {latest_year_metrics['Key Values']['Revenue']:,.0f}
123
+ - Net Earnings: {latest_year_metrics['Key Values']['Net Earnings']:,.0f}
124
+
125
+ Balance Sheet Trends:
126
+ {balance_sheet[:800]}
127
+
128
+ Income Statement Trends:
129
+ {income_stmt[:800]}
130
+
131
+ Provide specific analysis on:
132
+ 1. Financial Health and Stability
133
+ 2. Profitability and Efficiency
134
+ 3. Growth Trends and Patterns
135
+ 4. Risk Factors and Concerns
136
+ 5. Strategic Recommendations
137
+ 6. Future Outlook</human>"""
138
+
139
+ def generate_ai_insights(self, prompt):
140
+ inputs = self.tiny_tokenizer(prompt, return_tensors="pt", truncation=True)
141
+ outputs = self.tiny_model.generate(
142
+ inputs["input_ids"],
143
+ max_length=1000,
144
+ temperature=0.7,
145
+ top_p=0.95,
146
+ do_sample=True
147
+ )
148
+ return self.tiny_tokenizer.decode(outputs[0], skip_special_tokens=True)
149
+
150
+ def analyze_sentiment(self, metrics):
151
+ latest_metrics = json.dumps(metrics['2025'])
152
+ inputs = self.finbert_tokenizer(latest_metrics, return_tensors="pt", truncation=True)
153
+ outputs = self.finbert_model(**inputs)
154
+ probs = torch.nn.functional.softmax(outputs.logits, dim=1)
155
+ sentiment_labels = ['negative', 'neutral', 'positive']
156
 
157
+ return {
158
+ 'sentiment': sentiment_labels[probs.argmax().item()],
159
+ 'confidence': f"{probs.max().item():.2f}"
160
+ }
 
161
 
162
+ def generate_roadmap(self, metrics):
163
+ latest_metrics = metrics['2025']
164
+ roadmap = {
165
+ "Immediate Actions (0-6 months)": [],
166
+ "Short-term Goals (6-12 months)": [],
167
+ "Medium-term Strategy (1-2 years)": [],
168
+ "Long-term Vision (3-5 years)": []
169
+ }
170
 
171
+ # Generate recommendations based on metrics comparison
172
+ current_ratio = latest_metrics["Liquidity"]["Current Ratio"]
173
+ net_margin = latest_metrics["Profitability"]["Net Margin"]
174
+ asset_turnover = latest_metrics["Efficiency"]["Asset Turnover"]
175
+
176
+ # Add specific recommendations based on metric analysis
177
+ if current_ratio > self.industry_benchmarks["Liquidity"]["Current Ratio"] * 1.5:
178
+ roadmap["Short-term Goals (6-12 months)"].append("Consider optimizing excess working capital")
179
+ elif current_ratio < self.industry_benchmarks["Liquidity"]["Current Ratio"]:
180
+ roadmap["Immediate Actions (0-6 months)"].append("Improve working capital management")
181
+
182
+ if net_margin < self.industry_benchmarks["Profitability"]["Net Margin"]:
183
+ roadmap["Immediate Actions (0-6 months)"].append("Review cost structure")
184
+ roadmap["Short-term Goals (6-12 months)"].append("Implement margin improvement initiatives")
185
+
186
+ if asset_turnover < self.industry_benchmarks["Efficiency"]["Asset Turnover"]:
187
+ roadmap["Medium-term Strategy (1-2 years)"].append("Optimize asset utilization")
188
+ roadmap["Long-term Vision (3-5 years)"].append("Consider strategic asset restructuring")
189
+
190
+ return roadmap
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
  def analyze_financials(self, balance_sheet_file, income_stmt_file):
 
193
  try:
194
  # Read files
195
  balance_sheet_df = pd.read_csv(balance_sheet_file)
196
  income_stmt_df = pd.read_csv(income_stmt_file)
197
 
198
+ # Also read raw content for context
199
+ with open(balance_sheet_file, 'r') as f:
200
+ balance_sheet_content = f.read()
201
+ with open(income_stmt_file, 'r') as f:
202
+ income_stmt_content = f.read()
203
+
204
+ # Calculate metrics
205
+ metrics = self.calculate_metrics(balance_sheet_df, income_stmt_df)
206
 
207
  # Generate insights
208
+ insights_prompt = self.create_insights_prompt(metrics, balance_sheet_content, income_stmt_content)
209
+ insights = self.generate_ai_insights(insights_prompt)
210
 
211
+ # Generate sentiment and roadmap
212
+ sentiment = self.analyze_sentiment(metrics)
213
+ roadmap = self.generate_roadmap(metrics)
214
+
215
+ # Compile analysis
216
  analysis = {
217
+ "Financial Metrics": metrics,
218
+ "AI Insights": insights,
219
+ "Sentiment Analysis": sentiment,
220
+ "Strategic Roadmap": roadmap,
221
+ "Analysis Period": "2021-2025",
222
+ "Note": "All values in thousands"
 
 
 
 
223
  }
224
+
225
  return json.dumps(analysis, indent=2)
226
 
227
  except Exception as e:
228
  return f"Error in analysis: {str(e)}"
229
 
230
  def create_interface():
231
+ analyzer = FinancialAnalyzer()
232
 
233
  iface = gr.Interface(
234
  fn=analyzer.analyze_financials,
 
236
  gr.File(label="Balance Sheet (CSV)", type="filepath"),
237
  gr.File(label="Income Statement (CSV)", type="filepath")
238
  ],
239
+ outputs=gr.Textbox(label="Analysis Results", lines=25),
240
+ title="Financial Statement Analyzer",
241
+ description="Upload financial statements for comprehensive analysis including AI insights, sentiment analysis, and strategic roadmap. (All values in thousands)"
242
  )
243
 
244
  return iface