rajat5ranjan commited on
Commit
b9c076d
·
verified ·
1 Parent(s): a067f83

Create core/stock_analysis.py

Browse files
Files changed (1) hide show
  1. core/stock_analysis.py +108 -0
core/stock_analysis.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # core/stock_analysis.py
2
+
3
+ import requests
4
+ import json
5
+ from datetime import datetime, timedelta
6
+ from tradingview_ta import TA_Handler, Interval
7
+ from langchain.document_loaders import WebBaseLoader
8
+ from langchain.docstore.document import Document
9
+ from bs4 import BeautifulSoup
10
+ from GoogleNews import GoogleNews
11
+ from langchain.prompts import PromptTemplate
12
+ from langchain.chains import StuffDocumentsChain, LLMChain
13
+
14
+ def clean_google_news_url(url: str):
15
+ for ext in [".html", ".cms"]:
16
+ if ext in url:
17
+ return url.split(ext)[0] + ext
18
+ return url.split("&")[0]
19
+
20
+ def get_google_news_documents(query: str, max_articles: int = 10, timeout: int = 10):
21
+ googlenews = GoogleNews(lang="en")
22
+ end_date = datetime.today()
23
+ start_date = end_date - timedelta(days=2)
24
+ googlenews.set_time_range(start_date.strftime("%m/%d/%Y"), end_date.strftime("%m/%d/%Y"))
25
+ googlenews.search(query)
26
+ articles = googlenews.result()
27
+
28
+ documents = []
29
+ for article in articles[:max_articles]:
30
+ url = clean_google_news_url(article.get("link"))
31
+ try:
32
+ response = requests.get(url, timeout=timeout, headers={"User-Agent": "Mozilla/5.0"})
33
+ response.raise_for_status()
34
+ soup = BeautifulSoup(response.text, "html.parser")
35
+ paragraphs = soup.find_all("p")
36
+ content = "\n".join([p.get_text(strip=True) for p in paragraphs if p.get_text(strip=True)])
37
+ if content and len(content) > 200:
38
+ doc = Document(
39
+ page_content=content,
40
+ metadata={
41
+ "source": "Google News",
42
+ "title": article.get("title", ""),
43
+ "published": article.get("date", ""),
44
+ "link": url,
45
+ }
46
+ )
47
+ documents.append(doc)
48
+ except Exception:
49
+ continue
50
+ return documents
51
+
52
+ def analyze_stock(ticker, llm):
53
+ try:
54
+ handler = TA_Handler(symbol=ticker, screener="india", exchange="NSE", interval=Interval.INTERVAL_1_DAY)
55
+ summary = handler.get_analysis().summary
56
+ except Exception:
57
+ return {"error": "Invalid ticker or failed to fetch trading data"}
58
+
59
+ urls = [
60
+ f"https://www.google.com/finance/quote/{ticker}:NSE?hl=en",
61
+ f"https://in.tradingview.com/symbols/NSE-{ticker}/",
62
+ f"https://in.tradingview.com/symbols/NSE-{ticker}/news/",
63
+ f"https://in.tradingview.com/symbols/NSE-{ticker}/minds/"
64
+ ]
65
+
66
+ loader = WebBaseLoader(urls)
67
+ web_docs = loader.load()
68
+
69
+ news_docs = get_google_news_documents(f"Trending News for {ticker}", max_articles=10)
70
+ docs = web_docs + news_docs
71
+
72
+ prompt_template = """You are an expert Stock Market Trader...
73
+
74
+ Context:
75
+ {input_documents}
76
+
77
+ Task:
78
+ Summarize the stock...
79
+ RETURN JSON with this schema:
80
+
81
+ ```json
82
+ {{
83
+ "stock_summary": {{
84
+ "company_name": "",
85
+ "ticker": "",
86
+ "exchange": "",
87
+ ...
88
+ }},
89
+ ...
90
+ }}
91
+ ```
92
+ """
93
+
94
+ prompt = PromptTemplate.from_template(prompt_template)
95
+ chain = StuffDocumentsChain(llm_chain=LLMChain(llm=llm, prompt=prompt), document_variable_name="input_documents")
96
+ response = chain.invoke({"input_documents": docs})
97
+ raw = response["output_text"].strip()
98
+
99
+ # Clean code block markdown if present
100
+ if raw.startswith("```json"):
101
+ raw = raw[len("```json"):]
102
+ if raw.endswith("```"):
103
+ raw = raw[:-3]
104
+
105
+ try:
106
+ return json.loads(raw.strip())
107
+ except json.JSONDecodeError:
108
+ return {"error": "Failed to parse model output", "raw": raw}