使用StockTV数据源对接印度股票数据:完整开发指南
1 准备工作与基础配置
在开始对接StockTV印度股票数据API之前,需要进行一些基础准备工作。首先,您需要联系StockTV官方获取API密钥(Key),这是访问所有API接口的必要凭证。可以通过Telegram联系官方客服(@stocktvpaopao)申请密钥,通常密钥格式类似于"MY4b781f618e3f43c4b055f25fa61941ad"。
接下来需要安装必要的Python库,使用以下命令安装基础依赖包:
pip install requests websocket-client pandas
这些库分别用于HTTP请求、WebSocket连接和数据处理。
对于印度市场,有几个关键参数需要特别注意:
- 国家ID(countryId):印度固定为14
- 交易所ID(exchangeId):NSE为46,BSE为74
- 基础URL:https://api.stocktv.top
可以设置基础配置如下:
import requests
import pandas as pd
BASE_URL = "https://api.stocktv.top/stock"
API_KEY = "YOUR_API_KEY" # 替换为实际密钥
# 请求头设置
HEADERS = {
"User-Agent": "PythonStockClient/1.0",
"Accept-Encoding": "gzip"
}
这样的基础配置为后续API调用奠定了基础。
2 核心API接口详解与代码实战
2.1 获取印度市场列表接口
获取印度交易所(NSE和BSE)所有股票清单是数据对接的第一步。使用市场列表接口可以获取完整的股票基本信息,包括股票代码、名称、最新价格等关键字段。
以下是一个完整的函数示例:
def get_indian_stocks(page=1, page_size=50):
"""
获取印度股票市场列表
page: 页码,默认第1页
page_size: 每页数量,默认50条
"""
url = f"{BASE_URL}/stocks"
params = {
"countryId": 14, # 印度国家ID
"pageSize": page_size, # 分页大小
"page": page, # 页码
"key": API_KEY # API密钥
}
try:
response = requests.get(url, params=params, headers=HEADERS, timeout=10)
response.raise_for_status() # 检查请求状态
data = response.json()
# 转换为DataFrame便于处理
if data['code'] == 200:
records = data['data']['records']
df = pd.DataFrame(records)
# 处理时间戳字段
if 'time' in df.columns:
df['time'] = pd.to_datetime(df['time'], unit='s')
return df[['id', 'symbol', 'name', 'last', 'chgPct', 'volume', 'time']]
else:
print(f"API返回错误: {data['message']}")
return None
except requests.exceptions.RequestException as e:
print(f"请求失败: {str(e)}")
return None
# 调用示例
stocks_df = get_indian_stocks(page_size=10)
print(f"获取到{len(stocks_df)}只印度股票")
print(stocks_df.head())
此函数返回的字段包括股票ID(id)、代码(symbol)、名称(name)、最新价(last)、涨跌幅(chgPct)、成交量(volume)和时间戳(time)。股票ID是后续查询详细信息的必要参数。
2.2 个股实时行情查询
获取单只股票的实时行情是股票API的核心功能。StockTV提供多种查询方式,既可以通过股票ID查询,也可以通过股票代码查询。
def query_stock(stock_id=None, symbol=None):
"""
查询单只股票实时行情
stock_id: 股票ID(优先级高)
symbol: 股票代码(如"RELIANCE.NS")
"""
url = f"{BASE_URL}/queryStocks"
params = {"key": API_KEY}
if stock_id:
params["id"] = stock_id
elif symbol:
params["symbol"] = symbol
else:
raise ValueError("必须提供stock_id或symbol参数")
try:
response = requests.get(url, params=params, headers=HEADERS, timeout=5)
data = response.json()
if data['code'] == 200 and len(data['data']) > 0:
stock_data = data['data'][0]
return stock_data
else:
print(f"未找到股票数据: {data['message']}")
return None
except Exception as e:
print(f"查询股票数据失败: {str(e)}")
return None
# 查询示例:通过ID查询Infosys
infosys_data = query_stock(stock_id=7310)
if infosys_data:
print(f"股票名称: {infosys_data['name']}")
print(f"当前价格: {infosys_data['last']}")
print(f"日涨跌幅: {infosys_data['chgPct']}%")
print(f"成交量: {infosys_data['volume']:,}")
此接口返回的实时数据包含最新价、涨跌幅、成交量等关键信息,更新频率通常为秒级。
2.3 印度指数行情查询
印度股市的主要指数包括Nifty 50和Sensex等,这些指数反映了整体市场走势。通过指数接口可以获取这些重要指标的实时数据。
def get_indian_indices():
"""获取印度主要指数数据"""
url = f"{BASE_URL}/indices"
params = {
"countryId": 14, # 印度
"key": API_KEY
}
response = requests.get(url, params=params)
data = response.json()
if data['code'] == 200:
# 提取主要指数
indices = {}
for index in data['data']:
indices[index['symbol']] = {
'name': index['name'],
'last': index['last'],
'chgPct': index['chgPct'],
'isOpen': index['isOpen'] # 是否交易中
}
return indices
return None
# 调用示例
indices = get_indian_indices()
if indices:
nifty50 = indices.get('NSEI', {})
print(f"Nifty 50指数: {nifty50.get('last')} ({nifty50.get('chgPct')}%)")
响应数据包含指数代码、最新点位、涨跌幅以及是否处于交易状态等字段。
2.4 历史K线数据获取
历史K线数据对于技术分析和策略回测至关重要。StockTV API支持从5分钟到月线的多种时间粒度,满足不同分析需求。
def get_kline_data(pid, interval="PT15M", count=100):
"""
获取股票K线数据
pid: 股票ID
interval: 时间间隔 PT5M(5分钟)/PT15M(15分钟)/PT1H(1小时)/P1D(日线)
count: 获取数据条数
"""
url = f"{BASE_URL}/kline"
params = {
"pid": pid,
"interval": interval,
"key": API_KEY
}
# 注:实际接口可能需要使用不同参数控制条数
response = requests.get(url, params=params)
data = response.json()
if data['code'] == 200:
kline_data = data['data']
df = pd.DataFrame(kline_data)
# 处理时间戳
if 'time' in df.columns:
df['time'] = pd.to_datetime(df['time'], unit='ms')
df.set_index('time', inplace=True)
return df
return None
# 获取Reliance Industries的15分钟K线数据
reliance_kline = get_kline_data(12345, "PT15M")
print(f"获取到{len(reliance_kline)}条K线数据")
K线数据包含开盘价(open)、最高价(high)、最低价(low)、收盘价(close)和成交量(volume),是技术分析的基础。
表:K线时间间隔参数说明
| 参数值 | 说明 | 适用场景 |
|---|---|---|
| PT5M | 5分钟K线 | 短线交易分析 |
| PT15M | 15分钟K线 | 中短线分析 |
| PT1H | 1小时K线 | 中长线分析 |
| P1D | 日K线 | 长线趋势分析 |
3 WebSocket实时行情推送
对于需要实时价格的场景(如交易系统、实时监控),WebSocket推送相比HTTP轮询具有明显优势,它能实现毫秒级的延迟。
3.1 基础WebSocket连接
以下是一个完整的WebSocket实时行情订阅示例:
import websocket
import json
import threading
import time
class IndiaStockWebSocket:
def __init__(self, api_key):
self.api_key = api_key
self.ws_url = f"wss://ws-api.stocktv.top/connect?key={api_key}"
self.ws = None
self.is_connected = False
def on_message(self, ws, message):
"""处理实时行情推送"""
try:
data = json.loads(message)
# 股票实时数据推送
if data.get('type') == 1: # 类型1为股票
symbol = data.get('symbol', 'Unknown')
price = data.get('last_numeric', 0)
change_percent = data.get('pcp', 0)
volume = data.get('turnover_numeric', 0)
print(f"\n实时行情 [{symbol}]:")
print(f"最新价: {price}")
print(f"涨跌幅: {change_percent}%")
print(f"成交量: {volume}")
# 这里可以添加业务逻辑,如预警判断、数据存储等
except json.JSONDecodeError as e:
print(f"消息解析失败: {str(e)}")
def on_error(self, ws, error):
print(f"WebSocket错误: {str(error)}")
self.is_connected = False
def on_close(self, ws, close_status_code, close_msg):
print("WebSocket连接关闭")
self.is_connected = False
def on_open(self, ws):
print("实时行情连接成功")
self.is_connected = True
# 连接成功后订阅指定股票
subscribe_msg = json.dumps({
"action": "subscribe",
"symbols": ["RELIANCE", "TCS", "INFY"] # 订阅股票代码
})
ws.send(subscribe_msg)
def start(self):
"""启动WebSocket连接"""
self.ws = websocket.WebSocketApp(
self.ws_url,
on_message=self.on_message,
on_error=self.on_error,
on_close=self.on_close,
on_open=self.on_open
)
# 启动心跳线程
heartbeat_thread = threading.Thread(target=self.heartbeat)
heartbeat_thread.daemon = True
heartbeat_thread.start()
# 运行WebSocket(阻塞式)
self.ws.run_forever()
def heartbeat(self):
"""心跳维持,每30秒发送一次"""
while True:
time.sleep(30)
if self.ws and self.is_connected:
try:
self.ws.send(json.dumps({"action": "ping"}))
except Exception as e:
print(f"心跳发送失败: {str(e)}")
# 使用示例
if __name__ == "__main__":
ws_client = IndiaStockWebSocket(API_KEY)
ws_client.start()
WebSocket连接成功后,服务器会持续推送订阅股票的实时价格变化,包括最新价、涨跌幅、成交量等字段。
3.2 连接管理与重连机制
在生产环境中,需要实现完整的连接管理和重连机制,确保实时行情的稳定性:
def start_websocket_with_reconnect():
"""带自动重连的WebSocket启动函数"""
reconnect_attempts = 0
max_reconnect_attempts = 5
while reconnect_attempts < max_reconnect_attempts:
try:
ws_client = IndiaStockWebSocket(API_KEY)
ws_client.start()
except Exception as e:
print(f"连接异常: {str(e)}")
reconnect_attempts += 1
wait_time = min(2 ** reconnect_attempts, 30) # 指数退避,最大30秒
print(f"{wait_time}秒后尝试重连...")
time.sleep(wait_time)
print("超过最大重试次数,连接终止")
这种机制能够应对网络波动或服务端重启等异常情况,保证服务的可靠性。
4 高级功能与应用场景
4.1 涨跌排行榜监控
涨跌排行榜是发现市场热点的重要工具,通过API可以获取当日涨幅榜、跌幅榜等数据。
def get_top_movers(mover_type=1):
"""
获取涨跌排行榜
mover_type: 1=涨幅榜 2=跌幅榜 3=涨停榜 4=跌停榜
"""
url = f"{BASE_URL}/updownList"
params = {
"countryId": 14, # 印度
"type": mover_type, # 排行榜类型
"key": API_KEY
}
response = requests.get(url, params=params)
data = response.json()
if data['code'] == 200:
return data['data'][:10] # 返回前十名
return []
# 获取当日涨幅榜
top_gainers = get_top_movers(1)
print("当日涨幅榜前十:")
for i, stock in enumerate(top_gainers, 1):
print(f"{i}. {stock['name']}: {stock['chgPct']}%")
这一功能可用于追踪市场热点股票,及时发现投资机会。
4.2 IPO新股日历
IPO新股日历提供了即将上市和已上市新股的信息,对于打新投资者尤为重要。
def get_ipo_calendar(ipo_type=1):
"""
获取IPO新股日历
ipo_type: 1=即将上市 2=已上市
"""
url = f"{BASE_URL}/getIpo"
params = {
"countryId": 14,
"type": ipo_type,
"key": API_KEY
}
response = requests.get(url, params=params)
data = response.json()
if data['code'] == 200:
return data['data']
return []
# 获取即将上市的IPO
upcoming_ipos = get_ipo_calendar(1)
print("近期即将上市的IPO:")
for ipo in upcoming_ipos:
print(f"公司: {ipo['company']}")
print(f"交易所: {ipo['exchange']}")
print(f"发行价: {ipo['ipoPrice']}")
print(f"上市时间: {ipo['ipoListing']}")
IPO接口返回公司名称、交易所、发行价和上市时间等关键信息,帮助投资者把握新股申购机会。
4.3 完整示例:印度股票监控系统
结合多个API接口,我们可以构建一个完整的股票监控系统:
import time
from threading import Thread
from datetime import datetime
class IndiaStockMonitor:
def __init__(self, api_key):
self.api_key = api_key
self.tracked_stocks = {} # 监控的股票列表
self.alert_log = []
def add_stock(self, stock_id, stock_name, alert_rules):
"""
添加监控股票
alert_rules: 预警规则字典
- price_above: 价格突破上限
- price_below: 价格跌破下限
- change_above: 涨跌幅超过阈值
"""
self.tracked_stocks[stock_id] = {
'name': stock_name,
'alert_rules': alert_rules,
'current_price': None,
'last_check': None
}
def check_alerts(self, stock_id, current_data):
"""检查是否触发预警规则"""
stock_info = self.tracked_stocks[stock_id]
rules = stock_info['alert_rules']
alerts_triggered = []
current_price = current_data['last']
change_percent = current_data['chgPct']
# 价格突破上限预警
if 'price_above' in rules and current_price >= rules['price_above']:
alerts_triggered.append(f"价格突破 {rules['price_above']}")
# 价格跌破下限预警
if 'price_below' in rules and current_price <= rules['price_below']:
alerts_triggered.append(f"价格跌破 {rules['price_below']}")
# 涨跌幅预警
if 'change_above' in rules and abs(change_percent) >= rules['change_above']:
direction = "上涨" if change_percent > 0 else "下跌"
alerts_triggered.append(f"涨跌幅{abs(change_percent)}% {direction}超过阈值")
return alerts_triggered
def start_monitoring(self, interval=60):
"""启动监控线程"""
def monitor_loop():
while True:
for stock_id, info in self.tracked_stocks.items():
# 查询股票数据
stock_data = query_stock(stock_id)
if stock_data:
# 检查预警条件
alerts = self.check_alerts(stock_id, stock_data)
if alerts:
alert_msg = f"{datetime.now()}: {info['name']} {' | '.join(alerts)}"
print(f"🚨 预警: {alert_msg}")
self.alert_log.append(alert_msg)
# 更新当前价格
info['current_price'] = stock_data['last']
info['last_check'] = datetime.now()
# 等待指定间隔
time.sleep(interval)
# 在后台线程中运行监控
monitor_thread = Thread(target=monitor_loop)
monitor_thread.daemon = True
monitor_thread.start()
# 使用示例
monitor = IndiaStockMonitor(API_KEY)
# 添加监控股票和规则
monitor.add_stock(7310, "Infosys", {
"price_above": 1800, # 价格突破1800预警
"price_below": 1700, # 价格跌破1700预警
"change_above": 5 # 单日涨跌幅超过5%预警
})
monitor.add_stock(12345, "Reliance Industries", {
"price_above": 2800,
"change_above": 3
})
# 启动监控(每分钟检查一次)
monitor.start_monitoring(interval=60)
这一监控系统可以扩展为更复杂的量化交易策略基础,满足个人投资者和机构的不同需求。
表:典型应用场景及所需API
| 应用场景 | 核心功能 | 所需API接口 |
|---|---|---|
| 投资组合监控仪表盘 | 实时股价、涨跌幅显示 | 实时行情接口、WebSocket |
| 量化交易策略回测 | 历史K线数据获取 | K线接口 |
| 手机端实时行情推送 | 价格预警、实时通知 | WebSocket、个股查询接口 |
| IPO新股申购提醒 | 新股上市信息 | IPO日历接口 |
| 技术分析工具 | 历史价格和指标计算 | K线接口、实时行情接口 |
5 最佳实践与常见问题处理
5.1 错误处理与重试机制
在生产环境中,完善的错误处理机制是保证系统稳定性的关键。以下是一个带有重试功能的API请求封装示例:
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
@retry(
stop=stop_after_attempt(3), # 最大重试3次
wait=wait_exponential(multiplier=1, min=4, max=10), # 指数退避
retry=retry_if_exception_type((requests.exceptions.RequestException,))
)
def safe_api_call(url, params, headers):
"""带重试机制的API调用"""
response = requests.get(url, params=params, headers=headers, timeout=10)
response.raise_for_status() # 检查HTTP状态码
data = response.json()
# 检查API返回码
if data['code'] != 200:
# 处理特定错误码
if data['code'] == 401:
raise Exception("API密钥无效")
elif data['code'] == 429:
raise Exception("请求频率超限")
elif data['code'] == 500:
raise Exception("服务器内部错误")
else:
raise Exception(f"API错误: {data['message']}")
return data
# 使用示例
try:
stock_list = safe_api_call(
f"{BASE_URL}/stocks",
params={"countryId": 14, "key": API_KEY},
headers=HEADERS
)
except Exception as e:
print(f"API请求失败: {str(e)}")
常见的错误代码包括401(密钥无效)、429(请求频率超限)和500(服务器内部错误),需要针对不同错误采取相应处理策略。
5.2 缓存策略与性能优化
合理使用缓存可以显著提升应用程序性能,减少API调用次数:
from cachetools import cached, TTLCache
# 创建缓存(最大100条,有效期5分钟)
stock_cache = TTLCache(maxsize=100, ttl=300)
@cached(stock_cache)
def get_cached_stock_data(stock_id):
"""带缓存功能的股票数据查询"""
return query_stock(stock_id)
# 公司信息等变化不频繁的数据可缓存更长时间
company_cache = TTLCache(maxsize=50, ttl=3600) # 1小时缓存
@cached(company_cache)
def get_company_info(company_id):
"""获取公司信息(缓存1小时)"""
url = f"{BASE_URL}/companyInfo"
params = {"id": company_id, "key": API_KEY}
response = requests.get(url, params=params)
return response.json()
缓存策略应根据数据更新频率灵活设置,实时行情缓存时间较短,而公司基本信息等变化不频繁的数据可设置较长缓存时间。
5.3 频率限制与合规使用
StockTV API设有请求频率限制,默认约为10次/秒。为避免触发限流,建议遵循以下最佳实践:
import time
from threading import Semaphore
class RateLimitedAPI:
"""简单限流包装器"""
def __init__(self, calls_per_second=8):
self.semaphore = Semaphore(calls_per_second)
self.interval = 1.0 / calls_per_second
def call(self, func, *args, **kwargs):
"""限流调用"""
self.semaphore.acquire()
try:
return func(*args, **kwargs)
finally:
# 在后台线程中释放信号量
threading.Timer(self.interval, self.semaphore.release).start()
# 使用示例
rate_limiter = RateLimitedAPI(calls_per_second=8) # 保守限制
# 所有API调用通过限流器
stock_data = rate_limiter.call(query_stock, stock_id=7310)
此外,需要注意印度市场的交易时间(IST 9:15-15:30),在非交易时段部分数据可能不更新。
5.4 数据质量与时区处理
印度股市使用IST时区(UTC+5:30),在处理时间数据时需要进行适当的时区转换:
from pytz import timezone
import datetime
def convert_to_ist(utc_timestamp):
"""将UTC时间戳转换为IST时间"""
utc_time = datetime.datetime.utcfromtimestamp(utc_timestamp)
utc_time = utc_time.replace(tzinfo=datetime.timezone.utc)
ist_timezone = timezone('Asia/Kolkata')
ist_time = utc_time.astimezone(ist_timezone)
return ist_time
# 使用示例
kline_data = get_kline_data(7310, "P1D")
if kline_data is not None:
kline_data['ist_time'] = kline_data['time'].apply(
lambda x: convert_to_ist(x) if pd.notnull(x) else x
)
正确处理时区对于显示准确的市场时间和K线数据至关重要。
6 总结
本文详细介绍了如何使用StockTV API对接印度股票数据,从基础配置到高级功能实现,涵盖了REST API和WebSocket实时数据推送。通过合理的错误处理、缓存策略和频率控制,可以构建稳定可靠的印度股票数据应用。
StockTV API的优势在于其覆盖全面(包含NSE和BSE两大交易所)、接口简单易用、支持实时推送,并且提供免费测试额度,适合个人开发者和小型项目快速启动。
对于希望进入印度市场的投资者和开发者,StockTV提供了一个高效的数据入口。建议从免费API Key开始测试,逐步构建完整应用,并根据实际需求考虑升级到商业版以获得更高的请求频率和更全面的数据支持。
官方资源链接:
- API文档:https://documenter.getpostman.com/view/42914868/2sB2ixkEZR
- 技术支持:https://t.me/stocktvpaopao
28万+

被折叠的 条评论
为什么被折叠?



