Skip to main content

Overview

The Market News API retrieves the latest market news articles with sentiment analysis for individual stocks. This endpoint provides up to 100 news items per stock with overall sentiment classification (positive, negative, neutral). Source File: fetch_market_news.py

Endpoint Details

URL
string
required
https://news-live.dhan.co/v2/news/getLiveNews
Method
string
required
POST
Content-Type
string
required
application/json

Request Headers

{
  "Content-Type": "application/json",
  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  "Accept": "application/json, text/plain, */*"
}

Request Payload

categories
array
required
News categories filter. Use ["ALL"] for all categories.
page_no
integer
default:"0"
Page number (0-indexed). Use 0 for first page.
limit
integer
default:"50"
Number of news items to fetch. Maximum tested: 100.
first_news_timeStamp
integer
default:"0"
Timestamp of first news item (for pagination). Use 0 for initial request.
last_news_timeStamp
integer
default:"0"
Timestamp of last news item (for pagination). Use 0 for initial request.
news_feed_type
string
required
Feed type - use “live” for latest news.
stock_list
array
required
Array of ISINs. Single ISIN per request for stock-specific news.
entity_id
string
default:""
Entity identifier. Leave empty for stock news.

Example Payload

{
  "categories": ["ALL"],
  "page_no": 0,
  "limit": 50,
  "first_news_timeStamp": 0,
  "last_news_timeStamp": 0,
  "news_feed_type": "live",
  "stock_list": ["INE002A01018"],
  "entity_id": ""
}

Example Request

curl -X POST https://news-live.dhan.co/v2/news/getLiveNews \
  -H "Content-Type: application/json" \
  -H "User-Agent: Mozilla/5.0" \
  -d '{
    "categories": ["ALL"],
    "page_no": 0,
    "limit": 50,
    "first_news_timeStamp": 0,
    "last_news_timeStamp": 0,
    "news_feed_type": "live",
    "stock_list": ["INE002A01018"],
    "entity_id": ""
  }'

Response Structure

data.latest_news
array
Array of news item objects

News Item Fields

news_object.title
string
News headline/title
news_object.text
string
News summary/content
news_object.overall_sentiment
string
Sentiment classification: “positive”, “negative”, or “neutral”
publish_date
integer
Publish timestamp (Unix epoch in milliseconds)
category
string
News source/category

Example Response

{
  "data": {
    "latest_news": [
      {
        "news_object": {
          "title": "Reliance Industries Reports Strong Q3 Results",
          "text": "Reliance Industries posted consolidated net profit of Rs 18,500 crore for Q3 FY24, up 12% YoY...",
          "overall_sentiment": "positive"
        },
        "publish_date": 1705320000000,
        "category": "Business News"
      },
      {
        "news_object": {
          "title": "RIL to Invest $10B in Green Energy",
          "text": "Reliance announces major investment in renewable energy sector...",
          "overall_sentiment": "positive"
        },
        "publish_date": 1705233600000,
        "category": "Market News"
      }
    ]
  }
}

Implementation Details

Configuration

Max Threads
integer
default:"15"
Concurrent threads for parallel processing (conservative for news API)
Timeout
integer
default:"10"
Request timeout in seconds
News Limit
integer
default:"50"
News items per stock (max tested: 100)
Input File
string
required
master_isin_map.json
Output Directory
string
market_news/{SYMBOL}_news.json

Processing Flow

  1. Load Master Map: Read ISINs from master_isin_map.json
  2. Parallel Fetch: Use ThreadPoolExecutor with 15 workers
  3. Extract News: Parse news_object for title, text, sentiment
  4. Structure Data: Create clean news objects with metadata
  5. Save Per Stock: Write individual files per symbol
  6. Track Progress: Log success/empty/error counts

Code Implementation

import requests
import json
from concurrent.futures import ThreadPoolExecutor, as_completed

url = "https://news-live.dhan.co/v2/news/getLiveNews"
NEWS_LIMIT = 50

def fetch_market_news(item):
    symbol = item.get("Symbol")
    isin = item.get("ISIN")
    
    output_path = f"market_news/{symbol}_news.json"
    
    payload = {
        "categories": ["ALL"],
        "page_no": 0,
        "limit": NEWS_LIMIT,
        "first_news_timeStamp": 0,
        "last_news_timeStamp": 0,
        "news_feed_type": "live",
        "stock_list": [isin],
        "entity_id": ""
    }
    
    try:
        response = requests.post(url, json=payload, headers=headers, timeout=10)
        
        if response.status_code == 200:
            data = response.json()
            news_items = data.get("data", {}).get("latest_news", [])
            
            if news_items:
                processed_news = []
                for news in news_items:
                    news_obj = news.get("news_object", {})
                    processed_news.append({
                        "Title": news_obj.get("title", ""),
                        "Summary": news_obj.get("text", ""),
                        "Sentiment": news_obj.get("overall_sentiment", "neutral"),
                        "PublishDate": news.get("publish_date", 0),
                        "Source": news.get("category", "")
                    })
                
                final_output = {
                    "Symbol": symbol,
                    "ISIN": isin,
                    "News": processed_news
                }
                
                with open(output_path, "w") as f:
                    json.dump(final_output, f, indent=4)
                
                return "success"
            else:
                return "empty"
        elif response.status_code == 429:
            time.sleep(2)  # Rate limit backoff
            return "rate_limit"
        else:
            return f"http_{response.status_code}"
    except:
        return "error"

# Load master list
with open("master_isin_map.json", "r") as f:
    stock_list = json.load(f)

# Parallel processing
with ThreadPoolExecutor(max_workers=15) as executor:
    future_to_stock = {executor.submit(fetch_market_news, item): item["Symbol"] 
                       for item in stock_list}
    
    for future in as_completed(future_to_stock):
        result = future.result()
        # Track success/empty/error counts

Output Structure

Each stock gets its own JSON file:
market_news/
├── RELIANCE_news.json
├── TCS_news.json
└── HDFCBANK_news.json
File format:
{
  "Symbol": "RELIANCE",
  "ISIN": "INE002A01018",
  "News": [
    {
      "Title": "Reliance Industries Reports Strong Q3 Results",
      "Summary": "Reliance Industries posted consolidated net profit...",
      "Sentiment": "positive",
      "PublishDate": 1705320000000,
      "Source": "Business News"
    }
  ]
}

Performance Metrics

  • Total Stocks: ~2,775
  • Threads: 15 concurrent requests
  • Time per Stock: ~2-3 seconds
  • Total Time: ~6-8 minutes for full market
  • Avg News per Stock: 10-30 (varies significantly)
  • Success Rate: ~85% (some stocks have no news)
  • Empty Response Rate: ~15%

Progress Tracking

[50/2775] | Success: 42 | Empty: 7 | Errors: 1 | Elapsed: 85.3s
[100/2775] | Success: 83 | Empty: 15 | Errors: 2 | Elapsed: 165.1s
...
News Found: 2350 stocks | No News: 420 | Errors: 5

Pagination Support

For stocks with >100 news items, use pagination:
def fetch_all_news(isin):
    all_news = []
    page_no = 0
    limit = 100
    
    while True:
        payload = {
            "categories": ["ALL"],
            "page_no": page_no,
            "limit": limit,
            "news_feed_type": "live",
            "stock_list": [isin]
        }
        
        response = requests.post(url, json=payload, headers=headers)
        news_items = response.json().get("data", {}).get("latest_news", [])
        
        if not news_items:
            break
        
        all_news.extend(news_items)
        page_no += 1
    
    return all_news

Sentiment Analysis

positive
string
Bullish news - earnings beats, new contracts, positive outlook
negative
string
Bearish news - earnings misses, regulatory issues, downgrades
neutral
string
Informational news - general updates, announcements

Sentiment Distribution Examples

# Analyze sentiment distribution
with open("market_news/RELIANCE_news.json", "r") as f:
    data = json.load(f)

sentiments = [item["Sentiment"] for item in data["News"]]
positive = sentiments.count("positive")
negative = sentiments.count("negative")
neutral = sentiments.count("neutral")

print(f"Positive: {positive}, Negative: {negative}, Neutral: {neutral}")

Rate Limiting

The API implements rate limiting:
  • 429 Response: Too many requests
  • Backoff Strategy: Sleep 2 seconds on 429
  • Thread Limit: 15 concurrent (conservative)
  • Retry Logic: Automatic retry on rate limit
if response.status_code == 429:
    time.sleep(2)  # Backoff
    return "rate_limit"

Use Cases

  1. News Aggregation: Build comprehensive news database per stock
  2. Sentiment Analysis: Track sentiment trends over time
  3. Event Detection: Identify major news events impacting stocks
  4. Portfolio Monitoring: Get news alerts for portfolio holdings
  5. Earnings Coverage: Track quarterly result announcements
  6. Market Research: Analyze news flow for stock screening

Filtering Examples

Recent News Only

from datetime import datetime, timedelta

# Last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).timestamp() * 1000

recent_news = [
    item for item in news_list
    if item["PublishDate"] >= seven_days_ago
]

Positive Sentiment Only

positive_news = [
    item for item in news_list
    if item["Sentiment"] == "positive"
]

By Source

business_news = [
    item for item in news_list
    if item["Source"] == "Business News"
]

Notes

  • News availability varies by stock (large caps have more coverage)
  • Small/micro caps may have limited or no news
  • Sentiment is auto-generated using NLP algorithms
  • News sources include major business publications and wire services
  • The API updates in real-time as news is published
  • Historical news depth: typically 30-90 days
  • Limit=100 is maximum tested; higher values may not work
  • Use per-stock files for efficient incremental updates

Build docs developers (and LLMs) love