马来西亚股票数据API对接文档

马来西亚股票数据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 requests

def 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);
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        System.out.println("Connected to Malaysia Stock API");
        // 订阅MAYBANK和PUBLIC BANK股票
        send("{\"action\":\"subscribe\",\"pids\":[41602, 41603]}");
    }

    @Override
    public void onMessage(String message) {
        System.out.println("Received: " + message);
        // 实际应用中解析JSON并处理实时数据
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        System.out.println("Connection closed: " + reason);
    }

    @Override
    public 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股票ID
        interval: '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] = quote
    
    return quote

7.2 错误处理与重试

import requests
import time

def 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 data
                elif 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_size
        self.batch_interval = batch_interval
        self.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_time
    
    def process_batch(self, symbol):
        """处理缓冲区的数据"""
        if symbol not in self.buffer or not self.buffer[symbol]:
            return
        
        data_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: 马来西亚股市不提供盘前盘后交易

posted @ 2025-09-23 10:30  CryptoRzz  阅读(32)  评论(0)    收藏  举报