JC321 commited on
Commit
f6bd766
·
verified ·
1 Parent(s): bbf5389

Upload 2 files

Browse files
Files changed (2) hide show
  1. edgar_client.py +30 -9
  2. financial_analyzer.py +12 -0
edgar_client.py CHANGED
@@ -669,9 +669,6 @@ class EdgarDataClient:
669
  "operating_cash_flow": ["NetCashProvidedByUsedInOperatingActivities", "NetCashProvidedUsedInOperatingActivities", "NetCashFlowsFromUsedInOperatingActivities", "CashFlowsFromUsedInOperatingActivities"],
670
  }
671
 
672
- # Store result
673
- result = {"period": period}
674
-
675
  # Determine target form types to search
676
  if 'Q' in period:
677
  # Quarterly data, mainly search 10-Q (20-F usually doesn't have quarterly reports)
@@ -686,6 +683,17 @@ class EdgarDataClient:
686
  year = int(period)
687
  quarter = None
688
 
 
 
 
 
 
 
 
 
 
 
 
689
  # Detect if company uses 20-F (foreign filer)
690
  is_20f_filer = False
691
  all_filings = self.get_company_filings(cik)
@@ -693,6 +701,8 @@ class EdgarDataClient:
693
  form_types_used = set(f.get('form_type', '') for f in all_filings[:20])
694
  if '20-F' in form_types_used and '10-K' not in form_types_used:
695
  is_20f_filer = True
 
 
696
 
697
  # Get company filings to find accession number and primary document
698
  filings = self.get_company_filings(cik, form_types=target_forms)
@@ -855,17 +865,28 @@ class EdgarDataClient:
855
 
856
  # Generate complete source URL
857
  if primary_document:
858
- result["source_url"] = f"https://www.sec.gov/Archives/edgar/data/{cik}/{accession_number}/{primary_document}"
859
  else:
860
- result["source_url"] = f"https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK={cik}&type={form_type}&dateb=&owner=exclude&count=100"
861
  else:
862
  # Fallback to company browse page if filing not found
863
- result["source_url"] = f"https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK={cik}&type={form_type}&dateb=&owner=exclude&count=100"
 
 
 
 
 
 
864
 
865
- result["source_form"] = form_type
866
- result["data_source"] = data_source
 
 
 
 
 
867
 
868
- # Add detailed information
869
  result[f"{metric_key}_details"] = {
870
  "tag": metric_tag,
871
  "form": matched_entry.get("form", ""),
 
669
  "operating_cash_flow": ["NetCashProvidedByUsedInOperatingActivities", "NetCashProvidedUsedInOperatingActivities", "NetCashFlowsFromUsedInOperatingActivities", "CashFlowsFromUsedInOperatingActivities"],
670
  }
671
 
 
 
 
672
  # Determine target form types to search
673
  if 'Q' in period:
674
  # Quarterly data, mainly search 10-Q (20-F usually doesn't have quarterly reports)
 
683
  year = int(period)
684
  quarter = None
685
 
686
+ # Store result with consolidated meta and sources (added for de-duplication)
687
+ result = {
688
+ "period": period,
689
+ "meta": {
690
+ "year": year,
691
+ "quarter": quarter,
692
+ "is_20f_filer": False # will set below
693
+ },
694
+ "sources": {}
695
+ }
696
+
697
  # Detect if company uses 20-F (foreign filer)
698
  is_20f_filer = False
699
  all_filings = self.get_company_filings(cik)
 
701
  form_types_used = set(f.get('form_type', '') for f in all_filings[:20])
702
  if '20-F' in form_types_used and '10-K' not in form_types_used:
703
  is_20f_filer = True
704
+ # Reflect in meta
705
+ result["meta"]["is_20f_filer"] = is_20f_filer
706
 
707
  # Get company filings to find accession number and primary document
708
  filings = self.get_company_filings(cik, form_types=target_forms)
 
865
 
866
  # Generate complete source URL
867
  if primary_document:
868
+ url = f"https://www.sec.gov/Archives/edgar/data/{cik}/{accession_number}/{primary_document}"
869
  else:
870
+ url = f"https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK={cik}&type={form_type}&dateb=&owner=exclude&count=100"
871
  else:
872
  # Fallback to company browse page if filing not found
873
+ url = f"https://www.sec.gov/cgi-bin/browse-edgar?action=getcompany&CIK={cik}&type={form_type}&dateb=&owner=exclude&count=100"
874
+
875
+ # Backward compatible: only set once to avoid later overwrites
876
+ if "source_url" not in result:
877
+ result["source_url"] = url
878
+ result["source_form"] = form_type
879
+ result["data_source"] = data_source
880
 
881
+ # Consolidated per-metric source info
882
+ result["sources"][metric_key] = {
883
+ "url": url,
884
+ "form": form_type,
885
+ "data_source": data_source,
886
+ "filed": matched_entry.get("filed", "")
887
+ }
888
 
889
+ # Add detailed information (kept for compatibility)
890
  result[f"{metric_key}_details"] = {
891
  "tag": metric_tag,
892
  "form": matched_entry.get("form", ""),
financial_analyzer.py CHANGED
@@ -75,6 +75,10 @@ class FinancialAnalyzer:
75
  # Fast path succeeded, now get detailed info
76
  company_info = self.edgar_client.get_company_info(cik)
77
  if company_info:
 
 
 
 
78
  return company_info
79
  else:
80
  # Fallback to basic info if detailed fetch fails
@@ -82,6 +86,7 @@ class FinancialAnalyzer:
82
  "cik": basic_info['cik'],
83
  "name": basic_info['name'],
84
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
 
85
  "_source": "basic_cik_lookup"
86
  }
87
  else:
@@ -106,6 +111,7 @@ class FinancialAnalyzer:
106
  "cik": basic_info['cik'],
107
  "name": basic_info['name'],
108
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
 
109
  "ein": None, # Not available in basic search
110
  "fiscal_year_end": None, # Not available in basic search
111
  "sic_description": None, # Not available in basic search
@@ -128,6 +134,7 @@ class FinancialAnalyzer:
128
  "cik": basic_info['cik'],
129
  "name": basic_info['name'],
130
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
 
131
  "ein": None,
132
  "fiscal_year_end": None,
133
  "sic_description": None,
@@ -139,6 +146,10 @@ class FinancialAnalyzer:
139
  company_info = self.edgar_client.get_company_info(basic_info['cik'])
140
 
141
  if company_info:
 
 
 
 
142
  return company_info
143
  else:
144
  # Fallback to basic info if detailed fetch fails
@@ -146,6 +157,7 @@ class FinancialAnalyzer:
146
  "cik": basic_info['cik'],
147
  "name": basic_info['name'],
148
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
 
149
  "_source": "basic_search_fallback"
150
  }
151
 
 
75
  # Fast path succeeded, now get detailed info
76
  company_info = self.edgar_client.get_company_info(cik)
77
  if company_info:
78
+ # Ensure 'ticker' exists alongside 'tickers' for compatibility
79
+ if "ticker" not in company_info:
80
+ tks = company_info.get("tickers") or []
81
+ company_info["ticker"] = tks[0] if tks else None
82
  return company_info
83
  else:
84
  # Fallback to basic info if detailed fetch fails
 
86
  "cik": basic_info['cik'],
87
  "name": basic_info['name'],
88
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
89
+ "ticker": basic_info.get('ticker'),
90
  "_source": "basic_cik_lookup"
91
  }
92
  else:
 
111
  "cik": basic_info['cik'],
112
  "name": basic_info['name'],
113
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
114
+ "ticker": basic_info.get('ticker'),
115
  "ein": None, # Not available in basic search
116
  "fiscal_year_end": None, # Not available in basic search
117
  "sic_description": None, # Not available in basic search
 
134
  "cik": basic_info['cik'],
135
  "name": basic_info['name'],
136
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
137
+ "ticker": basic_info.get('ticker'),
138
  "ein": None,
139
  "fiscal_year_end": None,
140
  "sic_description": None,
 
146
  company_info = self.edgar_client.get_company_info(basic_info['cik'])
147
 
148
  if company_info:
149
+ # Ensure 'ticker' exists alongside 'tickers' for compatibility
150
+ if "ticker" not in company_info:
151
+ tks = company_info.get("tickers") or []
152
+ company_info["ticker"] = tks[0] if tks else None
153
  return company_info
154
  else:
155
  # Fallback to basic info if detailed fetch fails
 
157
  "cik": basic_info['cik'],
158
  "name": basic_info['name'],
159
  "tickers": [basic_info['ticker']] if basic_info.get('ticker') else [],
160
+ "ticker": basic_info.get('ticker'),
161
  "_source": "basic_search_fallback"
162
  }
163