rajat5ranjan commited on
Commit
d6b24f6
·
verified ·
1 Parent(s): 2970e1e

Create market_stock_sentiment.py

Browse files
Files changed (1) hide show
  1. core/market_stock_sentiment.py +109 -0
core/market_stock_sentiment.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import json
3
+ from datetime import datetime, timedelta
4
+ from tradingview_ta import TA_Handler, Interval
5
+ from langchain.document_loaders import WebBaseLoader
6
+ from langchain.docstore.document import Document
7
+ from bs4 import BeautifulSoup
8
+ from GoogleNews import GoogleNews
9
+ from langchain.prompts import PromptTemplate
10
+ from langchain.chains import StuffDocumentsChain, LLMChain
11
+
12
+ def clean_google_news_url(url: str):
13
+ for ext in [".html", ".cms"]:
14
+ if ext in url:
15
+ return url.split(ext)[0] + ext
16
+ return url.split("&")[0]
17
+
18
+ def get_google_news_documents(query: str, max_articles: int = 10, timeout: int = 10):
19
+ googlenews = GoogleNews(lang="en")
20
+ end_date = datetime.today()
21
+ start_date = end_date - timedelta(days=2)
22
+ googlenews.set_time_range(start_date.strftime("%m/%d/%Y"), end_date.strftime("%m/%d/%Y"))
23
+ googlenews.search(query)
24
+ articles = googlenews.result()
25
+
26
+ documents = []
27
+ for article in articles[:max_articles]:
28
+ url = clean_google_news_url(article.get("link"))
29
+ try:
30
+ response = requests.get(url, timeout=timeout, headers={"User-Agent": "Mozilla/5.0"})
31
+ response.raise_for_status()
32
+ soup = BeautifulSoup(response.text, "html.parser")
33
+ paragraphs = soup.find_all("p")
34
+ content = "\n".join([p.get_text(strip=True) for p in paragraphs if p.get_text(strip=True)])
35
+ if content and len(content) > 200:
36
+ doc = Document(
37
+ page_content=content,
38
+ metadata={
39
+ "source": "Google News",
40
+ "title": article.get("title", ""),
41
+ "published": article.get("date", ""),
42
+ "link": url,
43
+ }
44
+ )
45
+ documents.append(doc)
46
+ except Exception:
47
+ continue
48
+ return documents
49
+
50
+ def get_market_stock_sentiment(ticker, llm):
51
+ urls = [
52
+ f"https://economictimes.indiatimes.com/markets/stocks/news",
53
+ f"https://www.livemint.com/market/stock-market-news/",
54
+ f"https://in.tradingview.com/ideas/editors-picks/?type=trade",
55
+ f"https://pulse.zerodha.com/",
56
+ "https://upstox.com/news/market-news/stocks/",
57
+ ]
58
+
59
+ loader = WebBaseLoader(urls)
60
+ web_docs = loader.load()
61
+
62
+ google_docs = get_google_news_documents("Indian Stock market news NSE, Stocks in Action, Stocks in News, Stocks to Buy in next few weeks", max_articles=10)
63
+ web_docs.extend(google_docs)
64
+
65
+ prompt_template = """You are an expert Stock Market Trader specializing in stock market insights derived from fundamental analysis, analytical trends, profit-based evaluations, news indicators from different sites and detailed company financials.
66
+ You will receive stock market news articles or stocks in news from various news websites which have India stock news feed. For the below context/input_documents, perform the following tasks:
67
+ Context:
68
+ {input_documents}
69
+ 1. **Top picks**: After analyzing all provided data, rank the top 5-10 stocks to look at this week, including tickers, current sentiment, and why they made the list.
70
+ 2. **Identify the stock(s)** mentioned (by ticker and company name).
71
+ 3. **Sentiment analysis**: classify as Bullish, Bearish, or Neutral.
72
+ 4. **Extract critical news**: What is the main event or update? (e.g., earnings beat, regulatory approval, management change, major contract or macro impact).
73
+ 5. **Summarize impact**: Briefly explain how this news might affect stock price and investor behavior (e.g., “could boost investor confidence”, “sign indicates profit pressure”, etc.).
74
+ 6. **Actionable signal**: Based on the sentiment and news, suggest whether this is a “Buy”, “Sell”, “Hold”, or “Watch” recommendation, and the rationale.
75
+ PROVIDE THE DETAILS based on just the FACTS present in the document. Do NOT DUPLICATE the Output & hallucinate.
76
+ ***Format your output as JSON*** with the following structure:
77
+
78
+ ```json
79
+ {{
80
+ "top_picks": [
81
+ {{
82
+ "ticker": "TICKER",
83
+ "company": "Company Name",
84
+ "sentiment": "Bullish|Bearish|Neutral",
85
+ "critical_news": "Brief summary of the key event",
86
+ "impact_summary": "How this may affect the stock",
87
+ "action": "Buy|Sell|Hold|Watch",
88
+ "reason": "Why this stock ranks among top picks"
89
+ }},
90
+ ...
91
+ ]
92
+ }}
93
+ """
94
+
95
+ prompt = PromptTemplate.from_template(prompt_template)
96
+ chain = StuffDocumentsChain(llm_chain=LLMChain(llm=llm, prompt=prompt), document_variable_name="input_documents")
97
+ response = chain.invoke({"input_documents": docs})
98
+ raw = response["output_text"].strip()
99
+
100
+ # Clean code block markdown if present
101
+ if raw.startswith("```json"):
102
+ raw = raw[len("```json"):]
103
+ if raw.endswith("```"):
104
+ raw = raw[:-3]
105
+
106
+ try:
107
+ return json.loads(raw.strip())
108
+ except json.JSONDecodeError:
109
+ return {"error": "Failed to parse model output", "raw": raw}