Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Anny26022/chartsmaze_clone/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Circuit Stocks API retrieves lists of stocks that have hit upper or lower circuit limits during the trading day. It uses a triple-fallback strategy: Dhan ScanX Analytics API (primary), Next.js API (secondary), and web scraping (tertiary) for maximum reliability.
Source File: fetch_circuit_stocks.py
Endpoint Details
Primary Source: ScanX Analytics API
https://ow-scanx-analytics.dhan.co/customscan/fetchdt
Secondary Source: Dhan Next.js API
https://dhan.co/_next/data/{BUILD_ID}/{PAGE_KEY}.json
Tertiary Source: Web Scraping
https://dhan.co/{PAGE_URL}/
Configuration
Upper Circuit
LiveData.UpperCircuitBreak
"1" (stocks at upper circuit)
https://dhan.co/stocks/market/shares-with-upper-circuit/
upper_circuit_stocks.json
Lower Circuit
LiveData.LowerCircuitBreak
"1" (stocks at lower circuit)
https://dhan.co/stocks/market/lower-circuit-stocks/
lower_circuit_stocks.json
{
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
"Content-Type": "application/json"
}
Request Payload (Primary API)
Maximum results to return
Filter parameters including circuit flag
Example Payload (Upper Circuit)
{
"data": {
"sort": "Mcap",
"sorder": "desc",
"count": 500,
"fields": [
"Sym", "DispSym", "Ltp", "PPerchange", "Mcap", "Volume",
"High5yr", "Low1Yr", "High1Yr", "Pe", "Pb", "DivYeild"
],
"params": [
{"field": "LiveData.UpperCircuitBreak", "op": "", "val": "1"},
{"field": "OgInst", "op": "", "val": "ES"},
{"field": "Seg", "op": "", "val": "E"}
],
"pgno": 1
}
}
Example Payload (Lower Circuit)
{
"data": {
"sort": "Mcap",
"sorder": "desc",
"count": 500,
"fields": [
"Sym", "DispSym", "Ltp", "PPerchange", "Mcap", "Volume",
"High5yr", "Low1Yr", "High1Yr", "Pe", "Pb", "DivYeild"
],
"params": [
{"field": "LiveData.LowerCircuitBreak", "op": "", "val": "1"},
{"field": "OgInst", "op": "", "val": "ES"},
{"field": "Seg", "op": "", "val": "E"}
],
"pgno": 1
}
}
Example Request
curl -X POST https://ow-scanx-analytics.dhan.co/customscan/fetchdt \
-H "Content-Type: application/json" \
-H "User-Agent: Mozilla/5.0" \
-d '{
"data": {
"sort": "Mcap",
"sorder": "desc",
"count": 500,
"fields": ["Sym", "DispSym", "Ltp", "PPerchange", "Mcap", "Volume"],
"params": [
{"field": "LiveData.UpperCircuitBreak", "op": "", "val": "1"},
{"field": "OgInst", "op": "", "val": "ES"},
{"field": "Seg", "op": "", "val": "E"}
],
"pgno": 1
}
}'
Response Structure
Array of stock objects at circuit limits
Stock Object Fields
Percentage change from previous close
Example Response
{
"data": [
{
"Sym": "EXAMPLE",
"DispSym": "Example Company Ltd.",
"Ltp": 550.0,
"PPerchange": 20.0,
"Mcap": 25000.0,
"Volume": 1500000,
"High5yr": 600.0,
"High1Yr": 580.0,
"Low1Yr": 350.0,
"Pe": 25.5,
"Pb": 3.2,
"DivYeild": 1.5
}
]
}
Implementation Details
Triple-Fallback Strategy
import requests
import json
import re
from bs4 import BeautifulSoup
api_url = "https://ow-scanx-analytics.dhan.co/customscan/fetchdt"
scans_config = {
"upper_circuit_stocks.json": {
"val": "1",
"field": "LiveData.UpperCircuitBreak",
"web_key": "stocks/market/shares-with-upper-circuit",
"web_url": "https://dhan.co/stocks/market/shares-with-upper-circuit/"
},
"lower_circuit_stocks.json": {
"val": "1",
"field": "LiveData.LowerCircuitBreak",
"web_key": "stocks/market/lower-circuit-stocks",
"web_url": "https://dhan.co/stocks/market/lower-circuit-stocks/"
}
}
build_id = get_build_id()
for filename, config in scans_config.items():
cleaned_list = []
success = False
# Attempt 1: ScanX Analytics API
try:
payload = {
"data": {
"sort": "Mcap", "sorder": "desc", "count": 500,
"fields": ["Sym", "DispSym", "Ltp", "PPerchange", "Mcap", "Volume",
"High5yr", "Low1Yr", "High1Yr", "Pe", "Pb", "DivYeild"],
"params": [
{"field": config['field'], "op": "", "val": config['val']},
{"field": "OgInst", "op": "", "val": "ES"},
{"field": "Seg", "op": "", "val": "E"}
],
"pgno": 1
}
}
response = requests.post(api_url, json=payload, headers=headers, timeout=10)
if response.status_code == 200:
stocks = response.json().get('data', [])
for item in stocks:
cleaned_list.append({
"Symbol": item.get('Sym'),
"Name": item.get('DispSym'),
"LTP": item.get('Ltp'),
"ChangePercent": item.get('PPerchange'),
"MarketCap": item.get('Mcap'),
"Volume": item.get('Volume'),
"High5Yr": item.get('High5yr'),
"High1Yr": item.get('High1Yr'),
"Low1Yr": item.get('Low1Yr'),
"PE": item.get('Pe'),
"PB": item.get('Pb'),
"DivYield": item.get('DivYeild')
})
success = True
except Exception as e:
print(f"ScanX API Failed: {e}")
# Attempt 2: Next.js API (if primary failed)
# Attempt 3: Web scraping (if both failed)
if success:
with open(filename, "w") as f:
json.dump(cleaned_list, f, indent=4)
Output Structure
upper_circuit_stocks.json
[
{
"Symbol": "EXAMPLE",
"Name": "Example Company Ltd.",
"LTP": 550.0,
"ChangePercent": 20.0,
"MarketCap": 25000.0,
"Volume": 1500000,
"High5Yr": 600.0,
"High1Yr": 580.0,
"Low1Yr": 350.0,
"PE": 25.5,
"PB": 3.2,
"DivYield": 1.5
}
]
lower_circuit_stocks.json
[
{
"Symbol": "DOWNSTOCK",
"Name": "Downtrend Company Ltd.",
"LTP": 80.0,
"ChangePercent": -20.0,
"MarketCap": 5000.0,
"Volume": 2000000,
"High5Yr": 250.0,
"High1Yr": 150.0,
"Low1Yr": 75.0,
"PE": 8.5,
"PB": 0.9,
"DivYield": 0.0
}
]
Circuit Limit Rules
Standard Stocks
- Upper Circuit: +20% from previous close
- Lower Circuit: -20% from previous close
Surveillance/Special Stocks
- Upper/Lower: ±10%, ±5%, or ±2% (varies by category)
Newly Listed Stocks
- First Day: No upper circuit (but lower circuit applies)
- Subsequent Days: Standard limits apply
Use Cases
- Momentum Trading: Identify stocks with extreme buying/selling pressure
- Breakout Detection: Upper circuit stocks showing strong breakouts
- Panic Selling: Lower circuit stocks in distress
- Volume Analysis: Circuit stocks with high volume indicate conviction
- Risk Management: Avoid entering positions in circuit-locked stocks
- News Correlation: Cross-reference with news API for circuit triggers
- Upper Circuit Count: 10-50 stocks (typical trading day)
- Lower Circuit Count: 5-30 stocks (typical trading day)
- Fetch Time: 2-5 seconds per list
- Success Rate: >99% (triple fallback)
- Update Frequency: Real-time during market hours
Circuit Analysis
Strong Momentum (Upper Circuit)
# High volume + upper circuit = strong momentum
strong_momentum = [
stock for stock in upper_circuit
if stock["Volume"] > 1000000 and stock["ChangePercent"] >= 20
]
Near 52-Week High
# Upper circuit near 1-year high = breakout
breakout_candidates = [
stock for stock in upper_circuit
if stock["LTP"] >= stock["High1Yr"] * 0.95
]
Oversold Bounce (Lower Circuit)
# Lower circuit with low P/B = potential value
value_plays = [
stock for stock in lower_circuit
if stock["PB"] < 1.0 and stock["PE"] > 0
]
Trading Considerations
Upper Circuit
- Buying: Difficult or impossible (no sellers)
- Selling: Easy (strong demand)
- Next Day: Often opens gap up and continues higher
- Risk: FOMO-driven, potential reversal
Lower Circuit
- Selling: Difficult or impossible (no buyers)
- Buying: Risky (catching falling knife)
- Next Day: Often opens gap down and continues lower
- Risk: Further decline, liquidity issues
Integration Example
# Load circuit stocks
with open("upper_circuit_stocks.json", "r") as f:
upper_circuit = json.load(f)
with open("lower_circuit_stocks.json", "r") as f:
lower_circuit = json.load(f)
# Combine for analysis
circuit_symbols = set(
[s["Symbol"] for s in upper_circuit] +
[s["Symbol"] for s in lower_circuit]
)
# Filter watchlist
watchlist_safe = [
stock for stock in watchlist
if stock["Symbol"] not in circuit_symbols
]
Error Handling
try:
response = requests.post(api_url, json=payload, headers=headers, timeout=10)
if response.status_code == 200:
stocks = response.json().get('data', [])
# Process stocks
else:
print(f"HTTP Error: {response.status_code}")
except Exception as e:
print(f"ScanX API Failed: {e}")
# Fall back to Next.js API or web scraping
Notes
- Circuit data is only relevant during market hours (9:15 AM - 3:30 PM IST)
- Post-market, circuit flags reset for next trading day
- Some stocks may hit circuit multiple days in a row
- Circuit limits are based on previous day’s closing price
- Stocks can lock at circuit with zero trades (all buyers/sellers)
- Run during market hours for real-time circuit monitoring
- Small caps more likely to hit circuits than large caps
- Corporate actions (bonus, split) affect circuit calculation on ex-date