Get A-Share Real-Time Quotes with Python: Tencent Finance API Tutorial
Don't want to pay for market data? This tutorial shows you how to get A-share real-time quotes for free using Python. With a 15-minute delay, it's perfect for quantitative research and strategy validation.
Why Choose Tencent Finance API?
Free Market Data Comparison
| Source | Delay | Cost | Stability | Quality |
|---|---|---|---|---|
| Tencent Finance | 15 min | Free | ⭐⭐⭐⭐ | Good |
| Sina Finance | 15 min | Free | ⭐⭐⭐⭐ | Good |
| TongdaXin VIP | Real-time | ¥300/year | ⭐⭐⭐⭐⭐ | Excellent |
| JoinQuant | Real-time | ¥3000+/year | ⭐⭐⭐⭐⭐ | Excellent |
| Exchange Official | Real-time | ¥10000+/year | ⭐⭐⭐⭐⭐ | Best |
Conclusion: Among free options, Tencent and Sina are most reliable. Tencent's response format is cleaner and easier to parse.
Complete Implementation
1. Core Fetcher
# -*- coding: utf-8 -*-
"""
Tencent Finance Real-Time Quote Fetcher
Supports:
- A-share real-time quotes (15-min delay)
- 5-level order book
- Real-time trades
- Intraday data
Data Source: Tencent Finance API (Free, 15-min delayed)
"""
import requests
import pandas as pd
from datetime import datetime
from typing import Optional, List, Dict
class TencentStockFetcher:
"""Tencent Finance Real-Time Quote Fetcher"""
QUOTE_URL = "https://qt.gtimg.cn/q="
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
'Referer': 'https://stockapp.finance.qq.com',
'User-Agent': 'Mozilla/5.0'
})
def get_realtime_quote(self, symbols: List[str]) -> pd.DataFrame:
"""
Get real-time quotes
Args:
symbols: Stock codes, e.g., ['sh600000', 'sz000001']
Returns:
DataFrame with real-time quote data
"""
if not symbols:
return pd.DataFrame()
# Build code list (Tencent format)
codes = []
for symbol in symbols:
if symbol.startswith('6') or symbol.startswith('9'):
codes.append(f'sh{symbol}')
else:
codes.append(f'sz{symbol}')
# Request quote data
code_str = ','.join(codes)
url = f"{self.QUOTE_URL}{code_str}"
try:
resp = self.session.get(url, timeout=10)
resp.encoding = 'gbk' # Tencent returns GBK encoding
data = resp.text
return self._parse_quote_data(data)
except Exception as e:
print(f"Failed to fetch quotes: {e}")
return pd.DataFrame()
def _parse_quote_data(self, data: str) -> pd.DataFrame:
"""Parse Tencent quote data"""
results = []
for line in data.strip().split('\n'):
if not line.startswith('v_'):
continue
try:
# Format: v_sh600000="51~浦发银行~600000~7.85~7.84~7.86~..."
parts = line.split('~')
if len(parts) < 50:
continue
symbol = parts[2]
name = parts[1]
row = {
'symbol': symbol,
'name': name,
'price': float(parts[3]) if parts[3] else 0,
'open': float(parts[5]) if parts[5] else 0,
'high': float(parts[33]) if parts[33] else 0,
'low': float(parts[34]) if parts[34] else 0,
'close': float(parts[4]) if parts[4] else 0,
'volume': float(parts[6]) if parts[6] else 0,
'amount': float(parts[37]) if parts[37] else 0,
'bid': float(parts[11]) if parts[11] else 0,
'ask': float(parts[13]) if parts[13] else 0,
'bid_vol': float(parts[10]) if parts[10] else 0,
'ask_vol': float(parts[12]) if parts[12] else 0,
'change': float(parts[3]) - float(parts[4]) if parts[3] and parts[4] else 0,
'change_pct': float(parts[32]) if parts[32] else 0,
'timestamp': datetime.now()
}
results.append(row)
except Exception as e:
print(f"Failed to parse data: {e}")
continue
return pd.DataFrame(results)2. Real-Time Monitor
# -*- coding: utf-8 -*-
"""
Tencent Finance Real-Time Monitor
Usage:
python monitor.py # Monitor default stocks
python monitor.py 600000,000001 # Monitor specific stocks
"""
import argparse
import time
from datetime import datetime
from tencent_fetcher import TencentStockFetcher
def main():
parser = argparse.ArgumentParser(description='Tencent Finance Real-Time Monitor')
parser.add_argument('symbols', nargs='?', default='600000,000001,300750',
help='Stock codes, comma-separated')
parser.add_argument('--interval', type=int, default=60,
help='Refresh interval in seconds, default 60')
args = parser.parse_args()
fetcher = TencentStockFetcher()
symbols = args.symbols.split(',')
print(f"\nMonitoring: {symbols}")
print("Data delay: ~15 minutes")
print("Press Ctrl+C to stop\n")
try:
while True:
df = fetcher.get_realtime_quote(symbols)
if df.empty:
print("Failed to fetch data, retrying in 5s...")
time.sleep(5)
continue
# Clear screen
print("\033[2J\033[H", end='')
print(f"Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
# Display quotes
for _, row in df.iterrows():
icon = '📈' if row['change'] > 0 else '📉' if row['change'] < 0 else '➖'
print(f"{icon} {row['symbol']} {row['name']:<10} "
f"¥{row['price']:.2f} "
f"({row['change_pct']:+.2f}%) "
f"Change: {row['change']:.2f}")
print(f"\nNext update: {args.interval}s")
time.sleep(args.interval)
except KeyboardInterrupt:
print("\nMonitoring stopped")
if __name__ == "__main__":
main()Usage Examples
Install Dependencies
pip install requests pandasGet Single Stock Quote
from tencent_fetcher import TencentStockFetcher
fetcher = TencentStockFetcher()
# Get real-time quotes
df = fetcher.get_realtime_quote(['600000', '000001', '300750'])
print(df[['symbol', 'name', 'price', 'change_pct']])Output:
symbol name price change_pct
0 600000 浦发银行 7.85 +1.28
1 000001 平安银行 10.23 -0.58
2 300750 宁德时代 180.50 +0.00Monitor Multiple Stocks
# Monitor default stocks (refresh every 60s)
python monitor.py
# Monitor specific stocks
python monitor.py 600000,000001,300750
# Custom refresh interval (30s)
python monitor.py 600000,000001 --interval 30Integrate into Your Project
from tencent_fetcher import TencentStockFetcher
fetcher = TencentStockFetcher()
# Get stock price
df = fetcher.get_realtime_quote(['600000'])
current_price = df.iloc[0]['price']
change_pct = df.iloc[0]['change_pct']
# Check if price is up
if change_pct > 0:
print(f"📈 Up {change_pct}%")
elif change_pct < 0:
print(f"📉 Down {abs(change_pct)}%")
else:
print("➖ Unchanged")Data Fields
| Field | Description | Example |
|---|---|---|
| symbol | Stock code | 600000 |
| name | Stock name | 浦发银行 |
| price | Current price | 7.85 |
| open | Open price | 7.80 |
| high | High price | 7.92 |
| low | Low price | 7.78 |
| close | Previous close | 7.75 |
| volume | Volume (lots) | 123456 |
| amount | Turnover (CNY) | 98765432 |
| bid | Bid price (buy 1) | 7.84 |
| ask | Ask price (sell 1) | 7.86 |
| bid_vol | Bid volume | 1000 |
| ask_vol | Ask volume | 1500 |
| change | Price change | +0.10 |
| change_pct | Change % | +1.28 |
Important Notes
1. Data Delay
- Free API, ~15 minute delay
- Suitable for: quantitative research, strategy validation, offline analysis
- NOT suitable for: live trading, high-frequency trading
2. Trading Hours
Real-time data only available during trading hours (9:30-15:00 on trading days):
- Morning: 9:30 - 11:30
- Afternoon: 13:00 - 15:00
Outside trading hours, returns closing price.
3. Rate Limits
- Recommended refresh interval ≥ 30 seconds
- Avoid大量 requests in short time (may get IP blocked)
- Monitoring 10-20 stocks is fine
4. Encoding
Tencent returns GBK encoding, handled in code:
resp.encoding = 'gbk'5. Stock Code Format
Tencent format:
- Shanghai:
sh600000 - Shenzhen:
sz000001
Auto-converted in the code.
Advanced Usage
1. Get All A-Share List
def get_stock_list(self) -> pd.DataFrame:
"""Get A-share stock list"""
all_stocks = []
for i in range(1, 100):
url = f"http://vip.stock.finance.sina.com.cn/quotes_service/api/json_v2.php/Market_Center.getHQNodeData?page={i}&num=80&sort=symbol&asc=1&node=hs_a"
resp = self.session.get(url, timeout=10)
data = resp.json()
if not data:
break
all_stocks.extend(data)
return pd.DataFrame(all_stocks)2. Combine with SimTradeData
# SimTradeData for historical data
from simtradedata.fetchers.baostock_fetcher import BaoStockFetcher
# Tencent for real-time data
from tencent_fetcher import TencentStockFetcher
# Historical + Real-time = Complete data pipeline
historical = baostock_fetcher.fetch_daily('600000', '2026-01-01', '2026-03-10')
realtime = tencent_fetcher.get_realtime_quote(['600000'])3. Data Persistence
import sqlite3
# Save to database
conn = sqlite3.connect('stock_data.db')
df.to_sql('realtime_quotes', conn, if_exists='append', index=False)How It Works
Tencent Quote API
https://qt.gtimg.cn/q=sh600000,sz000001Response format (GBK encoded):
v_sh600000="51~浦发银行~600000~7.85~7.84~7.86~7.80~7.92~7.78~..."Fields separated by ~, parsed by position.
API Features
- No API Key required - Direct access
- Batch support - Up to 100 stocks per request
- Fast response - Typically < 500ms
- Stable - Official Tencent API
Summary
Pros
✅ Completely free ✅ No registration required ✅ Good data quality ✅ Stable API ✅ Batch queries supported
Cons
❌ 15-minute delay ❌ Unofficial API (may change) ❌ Not suitable for live trading
Use Cases
- ✅ Quantitative strategy research
- ✅ Historical backtesting validation
- ✅ Stock monitoring tools
- ✅ Learning projects
Full code available: https://github.com/your-username/tencent-realtime
Related Projects:
- SimTradeData - A-share historical data downloader
- SimTradeLab - Quantitative backtesting framework
If this article helped you, please like, bookmark, and share!
Questions? Email me: cnyfdr@gmail.com 🐶