马来西亚股票数据API对接文档
本文档提供StockTV马来西亚股票市场(Bursa Malaysia)数据API的完整对接指南,包含实时行情、历史数据、公司信息等核心功能
一、接口概览
1.1 支持交易所
交易所代码 | 交易所名称 | 覆盖股票数量 |
---|---|---|
MYX | 马来西亚交易所 | 900+ |
1.2 数据特性
- 实时行情:毫秒级延迟
- 历史数据:支持最长10年历史K线
- 基本面数据:包含PE比率、市值等指标
- 多维度数据:指数、IPO、公司信息等
- 数据格式:统一JSON格式
- 货币单位:所有价格均为马来西亚林吉特(MYR)
二、接入准备
2.1 获取API Key
联系官方获取密钥:https://t.me/CryptoRzz
2.2 请求基础URL
https://api.stocktv.top
2.3 请求头设置
X-Api-Key: YOUR_API_KEY
Content-Type: application/json
三、核心接口说明
3.1 市场列表接口
获取马来西亚交易所股票列表
接口地址:
GET /stock/stocks
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
countryId | 是 | 国家ID(马来西亚为42) | 42 |
exchangeId | 否 | 交易所ID(MYX为62) | 62 |
pageSize | 否 | 每页数量 | 100 |
page | 否 | 页码 | 1 |
响应示例:
{"code": 200,"data": {"records": [{"id": 41602, // 股票唯一ID"symbol": "MAYBANK", // 股票代码"name": "Malayan Banking Berhad","last": 9.25, // 最新价"chgPct": 0.5, // 涨跌幅%"volume": 1241700, // 成交量"high": 9.30, // 当日最高"low": 9.20, // 当日最低"open": true, // 是否开市"cfd": false, // 是否为CFD"marketCap": 105000000000 // 市值(百万MYR)}],"total": 900,"pages": 9}
}
3.2 股票详情查询
获取指定股票实时行情
接口地址:
GET /stock/queryStocks
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
id | 是 | 股票ID | 41602 |
响应示例:
{"code": 200,"data": [{"id": 41602,"symbol": "MAYBANK","name": "Malayan Banking Berhad","last": 9.25,"prevClose": 9.20, // 前收盘价"open": 9.22, // 开盘价"high": 9.30,"low": 9.20,"volume": 1241700,"avgVolume": 1150000, // 平均成交量"peRatio": 12.5, // 市盈率"eps": 0.74, // 每股收益"dividendYield": 5.4, // 股息率"beta": 0.92, // Beta值"sector": "Financial" // 行业分类}]
}
3.3 指数数据
获取马来西亚主要指数行情
接口地址:
GET /stock/indices
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
countryId | 是 | 国家ID(马来西亚为42) | 42 |
响应示例:
{"code": 200,"data": [{"id": 18460,"symbol": "KLSE", // 吉隆坡综合指数"name": "FTSE Bursa Malaysia KLCI","last": 1605.25,"change": 12.45, // 涨跌额"changePct": 0.78, // 涨跌幅%"high": 1608.50,"low": 1598.75,"prevClose": 1592.80,"time": 1716458537 // 更新时间戳}]
}
3.4 历史K线数据
获取股票历史价格数据
接口地址:
GET /stock/kline
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
pid | 是 | 股票ID | 41602 |
interval | 是 | 时间粒度 | PT15M(15分钟) P1D(日线) |
响应示例:
{"code": 200,"data": [{"time": 1725004800000, // 时间戳(ms)"open": 9.22,"high": 9.30,"low": 9.20,"close": 9.25,"volume": 1241700},// 更多K线数据...]
}
四、高级数据接口
4.1 IPO新股日历
获取即将上市的新股信息
接口地址:
GET /stock/getIpo
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
countryId | 是 | 国家ID | 42 |
type | 否 | 1=即将上市, 2=已上市 | 1 |
响应示例:
{"code": 200,"data": [{"id": 28,"company": "Tech Solutions Malaysia","symbol": "TSM","exchange": "MYX","ipoPrice": "1.20", // 发行价"listingDate": "2024-10-15", // 上市日期"ipoValue": "500M", // 发行市值"last": "1.18", // 最新价"pid": 1218998 // 股票ID}]
}
4.2 涨跌排行榜
获取涨幅榜/跌幅榜数据
接口地址:
GET /stock/updownList
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
countryId | 是 | 国家ID | 42 |
type | 是 | 1=涨幅榜, 2=跌幅榜, 3=涨停, 4=跌停 | 1 |
响应示例:
{"code": 200,"data": [{"id": 41605,"symbol": "SIME","name": "Sime Darby Berhad","last": 2.85,"change": 0.25,"changePct": 9.62,"volume": 4500000}]
}
4.3 公司基本面数据
获取公司详细信息
接口地址:
GET /stock/companies
请求参数:
参数 | 必选 | 说明 | 示例值 |
---|---|---|---|
countryId | 是 | 国家ID | 42 |
pageSize | 否 | 每页数量 | 10 |
page | 否 | 页码 | 1 |
响应示例:
{"code": 200,"data": {"records": [{"companyName": "Malayan Banking Berhad","description": "马来西亚最大的银行集团...","industry": "Banking","sector": "Financial Services","employeeCount": 42000,"market": "Malaysia","url": "/equities/maybank","financials": {"revenue": "52.4B MYR", // 营收"netIncome": "8.2B MYR", // 净利润"assets": "890.5B MYR" // 总资产}}],"total": 900,"pages": 90}
}
五、实时数据推送
5.1 WebSocket连接
wss://ws-api.stocktv.top/connect?key=YOUR_API_KEY
5.2 订阅消息
{"action": "subscribe","pids": [41602, 41605] // 订阅的股票ID列表
}
5.3 实时数据格式
{"pid": "41602", // 股票ID"symbol": "MAYBANK", // 股票代码"last": "9.25", // 最新价"change": "0.05", // 涨跌额"changePct": "0.5", // 涨跌幅%"volume": "1241700", // 成交量"bid": "9.24", // 买一价"ask": "9.26", // 卖一价"high": "9.30", // 当日最高"low": "9.20", // 当日最低"open": "9.22", // 开盘价"prevClose": "9.20", // 前收盘"timestamp": 1725008213 // 更新时间
}
5.4 心跳机制
客户端需每30秒发送心跳消息:
{"action": "ping"}
六、代码示例
6.1 Python获取股票数据
import requestsdef get_malaysia_stocks():"""获取马来西亚股票列表"""url = "https://api.stocktv.top/stock/stocks"params = {"countryId": 42, # 马来西亚国家ID"exchangeId": 62, # MYX交易所"pageSize": 100,"key": "YOUR_API_KEY"}try:response = requests.get(url, params=params)if response.status_code == 200:data = response.json()if data["code"] == 200:for stock in data["data"]["records"]:print(f"{stock['symbol']}: {stock['name']} - {stock['last']} MYR")else:print(f"API Error: {data['message']}")else:print(f"Request failed with status: {response.status_code}")except Exception as e:print(f"Error fetching stock list: {str(e)}")# 调用函数
get_malaysia_stocks()
6.2 Java实时数据订阅
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;import java.net.URI;public class MalaysiaStockWS extends WebSocketClient {public MalaysiaStockWS(URI serverUri) {super(serverUri);}@Overridepublic void onOpen(ServerHandshake handshakedata) {System.out.println("Connected to Malaysia Stock API");// 订阅MAYBANK和PUBLIC BANK股票send("{\"action\":\"subscribe\",\"pids\":[41602, 41603]}");}@Overridepublic void onMessage(String message) {System.out.println("Received: " + message);// 实际应用中解析JSON并处理实时数据}@Overridepublic void onClose(int code, String reason, boolean remote) {System.out.println("Connection closed: " + reason);}@Overridepublic void onError(Exception ex) {ex.printStackTrace();}public static void main(String[] args) {String wsUrl = "wss://ws-api.stocktv.top/connect?key=YOUR_API_KEY";MalaysiaStockWS client = new MalaysiaStockWS(URI.create(wsUrl));client.connect();}
}
6.3 Node.js获取K线数据
const axios = require('axios');async function getKlineData() {try {const response = await axios.get('https://api.stocktv.top/stock/kline', {params: {pid: 41602, // MAYBANK股票IDinterval: 'P1D' // 日线数据},headers: {'X-Api-Key': 'YOUR_API_KEY'}});console.log('MAYBANK Historical Data:');response.data.data.forEach(kline => {const date = new Date(kline.time);console.log(`${date.toISOString().split('T')[0]}: ${kline.open} - ${kline.close}`);});} catch (error) {console.error('API Error:', error.response ? error.response.data : error.message);}
}getKlineData();
七、最佳实践
7.1 数据缓存策略
from cachetools import TTLCache
import time# 创建缓存,有效期5秒
stock_cache = TTLCache(maxsize=100, ttl=5)def get_stock_quote(stock_id):"""获取股票行情(带缓存)"""# 检查缓存if stock_id in stock_cache:return stock_cache[stock_id]# 调用API获取数据quote = fetch_from_api(stock_id)# 存入缓存if quote:stock_cache[stock_id] = quotereturn quote
7.2 错误处理与重试
import requests
import timedef fetch_with_retry(url, params, max_retries=3):"""带重试机制的API请求"""for attempt in range(max_retries):try:response = requests.get(url, params=params, timeout=5)if response.status_code == 200:data = response.json()if data.get("code") == 200:return dataelif data.get("code") == 429: # 请求过多retry_after = int(data.get("retryAfter", 10))print(f"请求过于频繁,等待 {retry_after} 秒后重试...")time.sleep(retry_after)else:print(f"API返回错误: {data.get('message')}")else:print(f"请求失败,状态码: {response.status_code}")except Exception as e:print(f"请求异常: {str(e)}")if attempt < max_retries - 1:wait = 2 ** attempt # 指数退避print(f"等待 {wait} 秒后重试 (尝试 {attempt+1}/{max_retries})")time.sleep(wait)print(f"请求失败,已达最大重试次数 {max_retries}")return None
7.3 实时数据批处理
class RealTimeBatchProcessor:def __init__(self, batch_size=10, batch_interval=0.5):self.batch_size = batch_sizeself.batch_interval = batch_intervalself.buffer = {}self.last_process_time = time.time()def add_data(self, symbol, data):"""添加实时数据到缓冲区"""if symbol not in self.buffer:self.buffer[symbol] = []self.buffer[symbol].append(data)# 检查是否达到批处理条件current_time = time.time()if (len(self.buffer[symbol]) >= self.batch_size or current_time - self.last_process_time >= self.batch_interval):self.process_batch(symbol)self.last_process_time = current_timedef process_batch(self, symbol):"""处理缓冲区的数据"""if symbol not in self.buffer or not self.buffer[symbol]:returndata_points = self.buffer[symbol]# 计算统计指标prices = [d["last"] for d in data_points]volumes = [d["volume"] for d in data_points]avg_price = sum(prices) / len(prices)max_price = max(prices)min_price = min(prices)total_volume = sum(volumes)print(f"\n{symbol} 实时数据统计 (最近 {len(data_points)} 个更新):")print(f"平均价格: {avg_price:.2f}, 最高: {max_price:.2f}, 最低: {min_price:.2f}")print(f"总成交量: {total_volume}")# 清空缓冲区self.buffer[symbol] = []
八、数据字典
8.1 马来西亚主要指数
代码 | 指数名称 | 说明 |
---|---|---|
KLSE | 富时大马综合指数 | 马来西亚主要股票指数 |
FBM70 | 富时大马70指数 | 70家市值最大的公司 |
FBMEMAS | 富时大马EMAS指数 | 大马交易所全股指数 |
8.2 交易时间(马来西亚时间)
交易时段 | 时间 | 说明 |
---|---|---|
早盘 | 09:00-12:30 | 上午交易时段 |
午休 | 12:30-14:30 | 市场休市 |
午盘 | 14:30-17:00 | 下午交易时段 |
8.3 行业分类
分类代码 | 行业名称 |
---|---|
FINANCE | 金融 |
PLANTATION | 种植业 |
INDUSTRIAL | 工业 |
PROPERTY | 房地产 |
CONSUMER | 消费 |
十、附录
10.1 常见问题解答
Q: 如何获取马来西亚股票的英文名称?
A: API默认返回英文名称,如需本地名称可在请求头中添加 X-Language: ms
Q: 马来西亚股票的交易单位是多少?
A: 大部分股票交易单位为100股,但API返回的价格为每股价格
Q: 支持哪些历史数据粒度?
A: 支持1分钟、5分钟、15分钟、30分钟、1小时、日线、周线、月线
Q: 是否有盘前盘后数据?
A: 马来西亚股市不提供盘前盘后交易