walaa2022 commited on
Commit
db20fd6
·
verified ·
1 Parent(s): 1ef03df

Upload 2 files

Browse files
financial-ai-analyzer.txt ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Financial AI Analyzer.ipynb
2
+
3
+ import torch
4
+ from transformers import (
5
+ AutoTokenizer,
6
+ AutoModelForCausalLM,
7
+ AutoModelForSequenceClassification
8
+ )
9
+ import gradio as gr
10
+ from financial_metrics_calculator import FinancialMetricsCalculator # Import from first notebook
11
+
12
+ class FinancialAIAnalyzer:
13
+ def __init__(self):
14
+ print("Initializing AI Models...")
15
+ self.metrics_calculator = FinancialMetricsCalculator()
16
+ self.initialize_models()
17
+ self.last_metrics = {}
18
+ print("Initialization complete!")
19
+
20
+ def initialize_models(self):
21
+ """Initialize both TinyLlama and FinBERT models"""
22
+ try:
23
+ # Initialize TinyLlama
24
+ self.llama_tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
25
+ self.llama_model = AutoModelForCausalLM.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0")
26
+ self.llama_model.eval()
27
+
28
+ # Initialize FinBERT
29
+ self.finbert_tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
30
+ self.finbert_model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
31
+ self.finbert_model.eval()
32
+
33
+ print("Models loaded successfully!")
34
+ except Exception as e:
35
+ print(f"Error initializing models: {str(e)}")
36
+ raise
37
+
38
+ def get_sentiment_analysis(self, metrics):
39
+ """Get financial sentiment analysis using FinBERT"""
40
+ try:
41
+ financial_text = f"""
42
+ Revenue growth: {metrics['Ratios'].get('Revenue_Growth', 0):.2f}%
43
+ Profit margin: {metrics['Ratios'].get('Net_Margin', 0):.2f}%
44
+ Debt to equity: {metrics['Ratios'].get('Debt_to_Equity', 0):.2f}
45
+ Interest coverage: {metrics['Ratios'].get('Interest_Coverage', 0):.2f}%
46
+ Current ratio: {metrics['Ratios'].get('Current_Ratio', 0):.2f}
47
+ """
48
+
49
+ inputs = self.finbert_tokenizer(financial_text, return_tensors="pt", padding=True, truncation=True)
50
+ outputs = self.finbert_model(**inputs)
51
+ probabilities = torch.nn.functional.softmax(outputs.logits, dim=-1)
52
+ sentiment_scores = probabilities.detach().numpy()[0]
53
+
54
+ sentiments = ['negative', 'neutral', 'positive']
55
+ sentiment_dict = dict(zip(sentiments, [float(score) for score in sentiment_scores]))
56
+
57
+ return sentiment_dict
58
+ except Exception as e:
59
+ print(f"Error in sentiment analysis: {str(e)}")
60
+ return {}
61
+
62
+ def generate_prompt(self, metrics, sentiment_dict):
63
+ """Create analysis prompt"""
64
+ try:
65
+ # [Previous generate_prompt code remains the same]
66
+ pass
67
+ except Exception as e:
68
+ print(f"Error generating prompt: {str(e)}")
69
+ return ""
70
+
71
+ def generate_analysis(self, prompt):
72
+ """Generate analysis using TinyLlama"""
73
+ try:
74
+ # [Previous generate_analysis code remains the same]
75
+ pass
76
+ except Exception as e:
77
+ print(f"Error generating analysis: {str(e)}")
78
+ return self.generate_fallback_analysis(self.last_metrics)
79
+
80
+ def generate_fallback_analysis(self, metrics):
81
+ """Generate fallback analysis"""
82
+ try:
83
+ # [Previous generate_fallback_analysis code remains the same]
84
+ pass
85
+ except Exception as e:
86
+ return f"Error generating fallback analysis: {str(e)}"
87
+
88
+ def analyze_financials(self, balance_sheet_file, income_stmt_file):
89
+ """Main analysis function"""
90
+ try:
91
+ # Get metrics from calculator
92
+ metrics = self.metrics_calculator.process_financial_statements(balance_sheet_file, income_stmt_file)
93
+ if isinstance(metrics, str): # Error message
94
+ return metrics
95
+
96
+ self.last_metrics = metrics
97
+ sentiment_dict = self.get_sentiment_analysis(metrics)
98
+ prompt = self.generate_prompt(metrics, sentiment_dict)
99
+ analysis = self.generate_analysis(prompt)
100
+
101
+ results = {
102
+ "Financial Analysis": {
103
+ "Key Metrics": metrics,
104
+ "Market Sentiment": sentiment_dict,
105
+ "AI Insights": analysis,
106
+ "Analysis Period": "2021-2025",
107
+ "Note": "All monetary values in millions ($M)"
108
+ }
109
+ }
110
+
111
+ return json.dumps(results, indent=2)
112
+ except Exception as e:
113
+ return f"Error in analysis: {str(e)}"
114
+
115
+ def create_interface():
116
+ analyzer = FinancialAIAnalyzer()
117
+
118
+ iface = gr.Interface(
119
+ fn=analyzer.analyze_financials,
120
+ inputs=[
121
+ gr.File(label="Balance Sheet (Markdown)", type="filepath"),
122
+ gr.File(label="Income Statement (Markdown)", type="filepath")
123
+ ],
124
+ outputs=gr.Textbox(label="Analysis Results", lines=25),
125
+ title="AI Financial Statement Analyzer",
126
+ description="Upload financial statements in Markdown format for AI-
financial-metrics-calculator.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Financial Metrics Calculator.ipynb
2
+
3
+ import pandas as pd
4
+ import json
5
+ import numpy as np
6
+
7
+ class FinancialMetricsCalculator:
8
+ def __init__(self):
9
+ print("Initializing Financial Metrics Calculator...")
10
+
11
+ def clean_number(self, value):
12
+ """Clean and convert numerical values"""
13
+ try:
14
+ if isinstance(value, str):
15
+ value = value.replace('$', '').replace(',', '').strip()
16
+ if '(' in value and ')' in value:
17
+ value = '-' + value.replace('(', '').replace(')', '')
18
+ return float(value or 0)
19
+ except:
20
+ return 0.0
21
+
22
+ def is_valid_markdown(self, file_path):
23
+ """Check if a file is a valid Markdown file"""
24
+ try:
25
+ with open(file_path, 'r') as f:
26
+ content = f.read()
27
+ return any(line.startswith('#') or '|' in line for line in content.split('\n'))
28
+ except:
29
+ return False
30
+
31
+ def parse_financial_data(self, content):
32
+ """Parse markdown content into structured data"""
33
+ try:
34
+ data = {}
35
+ current_section = ""
36
+ current_table = []
37
+ headers = None
38
+
39
+ for line in content.split('\n'):
40
+ if line.startswith('#'):
41
+ if current_table and headers:
42
+ data[current_section] = self.process_table(headers, current_table)
43
+ current_section = line.strip('# ')
44
+ current_table = []
45
+ headers = None
46
+ elif '|' in line:
47
+ if '-|-' not in line:
48
+ row = [cell.strip() for cell in line.split('|')[1:-1]]
49
+ if not headers:
50
+ headers = row
51
+ else:
52
+ current_table.append(row)
53
+
54
+ if current_table and headers:
55
+ data[current_section] = self.process_table(headers, current_table)
56
+
57
+ return data
58
+ except Exception as e:
59
+ print(f"Error parsing financial data: {str(e)}")
60
+ return {}
61
+
62
+ def process_table(self, headers, rows):
63
+ """Process table data into structured format"""
64
+ try:
65
+ processed_data = {}
66
+ for row in rows:
67
+ if len(row) == len(headers):
68
+ item_name = row[0].strip('*').strip()
69
+ processed_data[item_name] = {}
70
+ for i, value in enumerate(row[1:], 1):
71
+ processed_data[item_name][headers[i]] = self.clean_number(value)
72
+ return processed_data
73
+ except Exception as e:
74
+ print(f"Error processing table: {str(e)}")
75
+ return {}
76
+
77
+ def get_nested_value(self, data, section, key, year):
78
+ """Safely get nested dictionary value"""
79
+ try:
80
+ return data.get(section, {}).get(key, {}).get(str(year), 0)
81
+ except:
82
+ return 0
83
+
84
+ def extract_metrics(self, income_data, balance_data):
85
+ """Extract and calculate key financial metrics"""
86
+ try:
87
+ metrics = {
88
+ "Revenue": {
89
+ "2025": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2025"),
90
+ "2024": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2024"),
91
+ "2021": self.get_nested_value(income_data, "Revenue", "Total Net Revenue", "2021")
92
+ },
93
+ "Profitability": {
94
+ "Gross_Profit_2025": self.get_nested_value(income_data, "Cost and Gross Profit", "Gross Profit", "2025"),
95
+ "EBIT_2025": self.get_nested_value(income_data, "Profit Summary", "EBIT", "2025"),
96
+ "Net_Earnings_2025": self.get_nested_value(income_data, "Profit Summary", "Net Earnings", "2025"),
97
+ "Operating_Expenses_2025": self.get_nested_value(income_data, "Operating Expenses", "Total Operating Expenses", "2025")
98
+ },
99
+ "Balance_Sheet": {
100
+ "Total_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Assets", "2025"),
101
+ "Current_Assets_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Assets", "2025"),
102
+ "Total_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Liabilities", "2025"),
103
+ "Current_Liabilities_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Current_Liabilities", "2025"),
104
+ "Equity_2025": self.get_nested_value(balance_data, "Key Totals", "Total_Shareholders_Equity", "2025"),
105
+ "Inventory_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Inventory", "2025"),
106
+ "Accounts_Receivable_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Accounts_Receivable", "2025"),
107
+ "Long_Term_Debt_2025": self.get_nested_value(balance_data, "Balance Sheet Data 2021-2025", "Long_Term_Debt", "2025")
108
+ },
109
+ "Cash_Flow": {
110
+ "Depreciation_2025": self.get_nested_value(income_data, "Operating Expenses", "Depreciation & Amortization", "2025"),
111
+ "Interest_Expense_2025": self.get_nested_value(income_data, "Profit Summary", "Interest Expense", "2025")
112
+ }
113
+ }
114
+
115
+ revenue_2025 = metrics["Revenue"]["2025"]
116
+ if revenue_2025 != 0:
117
+ metrics["Ratios"] = self.calculate_financial_ratios(metrics, revenue_2025)
118
+
119
+ return metrics
120
+ except Exception as e:
121
+ print(f"Error extracting metrics: {str(e)}")
122
+ return {}
123
+
124
+ def calculate_financial_ratios(self, metrics, revenue):
125
+ """Calculate financial ratios"""
126
+ return {
127
+ "Gross_Margin": (metrics["Profitability"]["Gross_Profit_2025"] / revenue) * 100,
128
+ "Operating_Margin": (metrics["Profitability"]["EBIT_2025"] / revenue) * 100,
129
+ "Net_Margin": (metrics["Profitability"]["Net_Earnings_2025"] / revenue) * 100,
130
+ "Current_Ratio": metrics["Balance_Sheet"]["Current_Assets_2025"] / metrics["Balance_Sheet"]["Current_Liabilities_2025"] if metrics["Balance_Sheet"]["Current_Liabilities_2025"] != 0 else 0,
131
+ "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,
132
+ "Asset_Turnover": revenue / metrics["Balance_Sheet"]["Total_Assets_2025"] if metrics["Balance_Sheet"]["Total_Assets_2025"] != 0 else 0,
133
+ "Receivables_Turnover": revenue / metrics["Balance_Sheet"]["Accounts_Receivable_2025"] if metrics["Balance_Sheet"]["Accounts_Receivable_2025"] != 0 else 0,
134
+ "Debt_to_Equity": metrics["Balance_Sheet"]["Total_Liabilities_2025"] / metrics["Balance_Sheet"]["Equity_2025"] if metrics["Balance_Sheet"]["Equity_2025"] != 0 else 0,
135
+ "Interest_Coverage": metrics["Profitability"]["EBIT_2025"] / metrics["Cash_Flow"]["Interest_Expense_2025"] if metrics["Cash_Flow"]["Interest_Expense_2025"] != 0 else 0,
136
+ "Revenue_Growth": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2024"]) - 1) * 100 if metrics["Revenue"]["2024"] != 0 else 0,
137
+ "5Year_Revenue_CAGR": ((metrics["Revenue"]["2025"] / metrics["Revenue"]["2021"]) ** (1/4) - 1) * 100 if metrics["Revenue"]["2021"] != 0 else 0
138
+ }
139
+
140
+ def process_financial_statements(self, balance_sheet_file, income_stmt_file):
141
+ """Process financial statements and return metrics"""
142
+ try:
143
+ if not (self.is_valid_markdown(balance_sheet_file) and self.is_valid_markdown(income_stmt_file)):
144
+ return "Error: Invalid file format"
145
+
146
+ with open(balance_sheet_file, 'r') as f:
147
+ balance_sheet = f.read()
148
+ with open(income_stmt_file, 'r') as f:
149
+ income_stmt = f.read()
150
+
151
+ income_data = self.parse_financial_data(income_stmt)
152
+ balance_data = self.parse_financial_data(balance_sheet)
153
+ metrics = self.extract_metrics(income_data, balance_data)
154
+
155
+ return metrics
156
+ except Exception as e:
157
+ print(f"Error processing statements: {str(e)}")
158
+ return None
159
+
160
+ # Example usage
161
+ if __name__ == "__main__":
162
+ calculator = FinancialMetricsCalculator()
163
+ # Test with your markdown files
164
+ metrics = calculator.process_financial_statements('balance_sheet.md', 'income_statement.md')
165
+ print(json.dumps(metrics, indent=2))