Jitendra12421 commited on
Commit
c975193
·
verified ·
1 Parent(s): bc2ae54

Completely replace Screener network block with Finology scraping

Browse files
Files changed (1) hide show
  1. forecaster_cli.py +51 -61
forecaster_cli.py CHANGED
@@ -31,80 +31,70 @@ def get_current_historic_val(table_data, row_name):
31
  return np.nan
32
 
33
  def fetch_live_features(ticker):
 
 
 
 
 
34
  try:
35
- scraper = ScreenerScraper()
36
- data = None
37
- for _ in range(3):
38
- try:
39
- data = scraper.get_stock_info(ticker)
40
- if "error" in data and "429" in data["error"]:
41
- time.sleep(1.5)
42
- continue
43
- break
44
- except Exception:
45
- time.sleep(1)
46
 
47
- if not data or "error" in data: return None
 
 
 
48
 
49
- pl = data['history'].get('profit-loss', {})
50
- bs = data['history'].get('balance-sheet', {})
51
- ratios = data['history'].get('ratios', {})
52
-
53
- sales_row = None
54
- for row in pl.get('rows', []):
55
- if row and row[0].lower() == 'sales':
56
- sales_row = row
57
- break
58
-
59
- sales = np.nan
60
- prev_sales = np.nan
61
- if sales_row and len(sales_row) >= 3:
62
- try:
63
- sales = float(str(sales_row[-1]).replace(',', '').strip())
64
- prev_sales = float(str(sales_row[-2]).replace(',', '').strip())
65
- except:
66
- pass
67
-
68
- opm = get_current_historic_val(pl, 'OPM %')
69
- net_profit = get_current_historic_val(pl, 'Net Profit')
70
- equity = get_current_historic_val(bs, 'Equity Capital')
71
- reserves = get_current_historic_val(bs, 'Reserves')
72
- borrowings = get_current_historic_val(bs, 'Borrowings')
73
- roce = get_current_historic_val(ratios, 'ROCE %')
74
-
75
- sales_growth = ((sales - prev_sales) / prev_sales * 100) if pd.notnull(prev_sales) and prev_sales > 0 else np.nan
76
- total_eq = equity + reserves if pd.notnull(equity) and pd.notnull(reserves) else np.nan
77
- roe = (net_profit / total_eq * 100) if pd.notnull(total_eq) and total_eq > 0 else np.nan
78
- debt_to_equity = (borrowings / total_eq) if pd.notnull(total_eq) and total_eq > 0 else np.nan
79
-
80
- pe = np.nan
81
- for metric in data.get('metrics', []):
82
- if metric['name'] == 'Stock P/E':
83
- pe = metric['value']
84
- break
85
-
86
  return {
87
  'Ticker': ticker,
88
- 'Sales_Growth': sales_growth,
89
- 'OPM': opm,
90
- 'ROCE': roce,
91
- 'ROE': roe,
92
  'Debt_to_Equity': debt_to_equity,
93
- 'PE_Ratio': pe
94
  }
95
  except Exception:
96
  return None
97
 
98
  def get_market_cap_tier(ticker):
99
- print(f"[{ticker}] Resolving market cap classification via Screener...")
100
  try:
101
- scraper = ScreenerScraper()
102
- cap_class = scraper.get_cap_info(ticker)['market_cap_class']
103
-
104
- if "Large" in cap_class: return "Large"
105
- if "Mid" in cap_class: return "Mid"
106
- if "Small" in cap_class: return "Small"
107
 
 
 
 
 
 
 
 
 
 
 
108
  except Exception as e:
109
  print(f"Warning: Could not fetch market cap ({e}). Defaulting to Small.")
110
 
 
31
  return np.nan
32
 
33
  def fetch_live_features(ticker):
34
+ import requests
35
+ from bs4 import BeautifulSoup
36
+ import re
37
+ import numpy as np
38
+
39
  try:
40
+ url = f"https://ticker.finology.in/company/{ticker}"
41
+ html = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'}).text
42
+ soup = BeautifulSoup(html, 'html.parser')
 
 
 
 
 
 
 
 
43
 
44
+ def clean(val):
45
+ if not val: return np.nan
46
+ try: return float(re.sub(r'[^\d.]', '', val))
47
+ except: return np.nan
48
 
49
+ data = {}
50
+ for div in soup.find_all('div', class_=re.compile(r'compess')):
51
+ text = div.get_text(" ", strip=True)
52
+ if "P/E" in text: data['PE_Ratio'] = clean(text.replace('P/E', ''))
53
+ if "Sales Growth" in text: data['Sales_Growth'] = clean(text.replace('Sales Growth', ''))
54
+ if "ROE" in text: data['ROE'] = clean(text.replace('ROE', ''))
55
+ if "ROCE" in text: data['ROCE'] = clean(text.replace('ROCE', ''))
56
+ if "CASH" in text: data['CASH'] = clean(text.replace('CASH', ''))
57
+ if "DEBT " in text: data['DEBT'] = clean(text.replace('DEBT', ''))
58
+ if "Book Value" in text: data['BV'] = clean(text.replace('Book Value', ''))
59
+ if "No. of Shares" in text: data['Shares'] = clean(text.replace('No. of Shares', ''))
60
+
61
+ debt_to_equity = np.nan
62
+ if 'DEBT' in data and 'BV' in data and 'Shares' in data and data['BV'] > 0 and data['Shares'] > 0:
63
+ total_equity = data['BV'] * data['Shares']
64
+ debt_to_equity = data['DEBT'] / total_equity if total_equity > 0 else 0
65
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  return {
67
  'Ticker': ticker,
68
+ 'Sales_Growth': data.get('Sales_Growth', np.nan),
69
+ 'OPM': np.nan, # Imputer will naturally handle this gracefully
70
+ 'ROCE': data.get('ROCE', np.nan),
71
+ 'ROE': data.get('ROE', np.nan),
72
  'Debt_to_Equity': debt_to_equity,
73
+ 'PE_Ratio': data.get('PE_Ratio', np.nan)
74
  }
75
  except Exception:
76
  return None
77
 
78
  def get_market_cap_tier(ticker):
79
+ print(f"[{ticker}] Resolving market cap classification via Finology...")
80
  try:
81
+ import requests
82
+ from bs4 import BeautifulSoup
83
+ import re
84
+ url = f"https://ticker.finology.in/company/{ticker}"
85
+ html = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'}).text
86
+ soup = BeautifulSoup(html, 'html.parser')
87
 
88
+ cap = 0
89
+ for div in soup.find_all('div', class_=re.compile(r'compess')):
90
+ text = div.get_text(" ", strip=True)
91
+ if "Market Cap" in text:
92
+ try: cap = float(re.sub(r'[^\d.]', '', text.replace('Market Cap', '')))
93
+ except: pass
94
+
95
+ if cap >= 20000: return "Large"
96
+ if cap >= 5000: return "Mid"
97
+ return "Small"
98
  except Exception as e:
99
  print(f"Warning: Could not fetch market cap ({e}). Defaulting to Small.")
100