使用API获取印度尼西亚的股票数据进行展示

0 阅读7分钟

使用API获取印度尼西亚的股票数据进行展示

引言:为什么关注印尼股票市场?

印度尼西亚作为东南亚最大的经济体,其股票市场(IDX)近年来备受全球投资者关注。雅加达综合指数(JKSE)过去5年年化增长率达12%,市场汇聚了中亚银行(BBCA)、印尼电信(TLKM)、人民银行(BBRI)等优质蓝筹股。对于金融科技开发者和量化交易者而言,获取印尼股票实时行情和历史数据是构建区域性投资工具的关键环节。

然而,直接对接印尼证券交易所(IDX)通常涉及高昂的数据授权费和复杂的跨境技术协议。本文将介绍如何通过标准化的金融数据接口,快速获取印尼股票数据并进行可视化展示。

环境准备与基础配置

1. 获取API密钥

首先需要获取访问金融数据接口的认证密钥。您可以通过相关平台申请获取专属的API Key

# 基础配置示例
API_KEY = "your_indonesia_api_key"  # 通过官网申请或联系客服获取
BASE_URL = "https://api.stocktv.top"
INDONESIA_ID = 48  # 印尼国家代码

2. 安装必要依赖库

pip install requests pandas plotly

3. 安全配置建议

import os
from dotenv import load_dotenv

load_dotenv()
API_KEY = os.getenv('STOCKTV_API_KEY')  # 从环境变量读取

核心接口对接方案

1. 获取印尼股票列表

在获取具体股票数据前,需要先查询印尼市场的股票列表及其唯一标识符。

import requests
import pandas as pd

def get_indonesia_stocks(page_size=10, page=1):
    """获取印尼股票列表"""
    url = f"{BASE_URL}/stock/stocks"
    params = {
        "countryId": INDONESIA_ID,
        "pageSize": page_size,
        "page": page,
        "key": API_KEY
    }
    
    response = requests.get(url, params=params)
    if response.status_code == 200:
        data = response.json()
        if data.get("code") == 200:
            return pd.DataFrame(data.get("data", []))
    return pd.DataFrame()

# 获取前10只印尼股票
stocks_df = get_indonesia_stocks()
print(stocks_df[['id', 'symbol', 'name', 'currency']].head())

接口返回的关键字段说明:

  • id: 股票的唯一PID,用于后续接口调用
  • symbol: 股票代码(如BBCA、TLKM)
  • name: 公司全称
  • currency: 货币单位(IDR - 印尼盾)

2. 获取个股实时行情

通过股票的PID获取实时报价和技术指标。

def get_stock_realtime(pid):
    """获取个股实时详情"""
    url = f"{BASE_URL}/stock/queryStocks"
    params = {
        "id": pid,
        "key": API_KEY
    }
    
    response = requests.get(url, params=params)
    if response.status_code == 200:
        data = response.json()
        if data.get("code") == 200:
            return data.get("data", {})
    return {}

# 示例:获取某只股票的实时数据
stock_data = get_stock_realtime("992844")
if stock_data:
    print(f"最新价格: {stock_data.get('last')} IDR")
    print(f"涨跌幅: {stock_data.get('chgPct')}%")
    print(f"技术建议: {stock_data.get('technicalDay')}")
    print(f"市值: {stock_data.get('fundamentalMarketCap')}")

3. 获取历史K线数据

K线数据对于技术分析和回测至关重要。

def get_kline_data(pid, interval="P1D", limit=100):
    """获取历史K线数据"""
    url = f"{BASE_URL}/stock/kline"
    params = {
        "pid": pid,
        "interval": interval,
        "limit": limit,
        "key": API_KEY
    }
    
    response = requests.get(url, params=params)
    if response.status_code == 200:
        data = response.json()
        if data.get("code") == 200:
            return data.get("data", [])
    return []

# 获取日线数据
kline_data = get_kline_data("12345", interval="P1D", limit=30)

支持的周期参数:

  • PT1M: 1分钟线
  • PT1H: 1小时线
  • P1D: 日线
  • P1W: 周线
  • P1M: 月线

4. 获取市场指数信息

监控印尼大盘整体走势。

def get_indices():
    """获取印尼市场指数"""
    url = f"{BASE_URL}/stock/indices"
    params = {
        "countryId": INDONESIA_ID,
        "key": API_KEY
    }
    
    response = requests.get(url, params=params)
    if response.status_code == 200:
        data = response.json()
        if data.get("code") == 200:
            return data.get("data", [])
    return []

# 获取雅加达综合指数
indices = get_indices()
for index in indices:
    if index.get('symbol') == 'JKSE':
        print(f"雅加达综合指数: {index.get('last')}")
        print(f"市场状态: {'开盘' if index.get('isOpen') == 1 else '休市'}")

数据可视化展示

1. K线图绘制

使用Plotly创建交互式K线图。

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd

def plot_kline_chart(kline_data, title="印尼股票K线图"):
    """绘制K线图"""
    if not kline_data:
        print("无有效数据")
        return
    
    # 转换数据格式
    df = pd.DataFrame(kline_data)
    df['time'] = pd.to_datetime(df['time'], unit='ms')
    
    # 创建图表
    fig = make_subplots(
        rows=2, cols=1,
        shared_xaxes=True,
        vertical_spacing=0.03,
        subplot_titles=(title, '成交量'),
        row_width=[0.2, 0.7]
    )
    
    # 添加K线
    fig.add_trace(
        go.Candlestick(
            x=df['time'],
            open=df['open'],
            high=df['high'],
            low=df['low'],
            close=df['close'],
            name="价格"
        ),
        row=1, col=1
    )
    
    # 添加成交量
    fig.add_trace(
        go.Bar(
            x=df['time'],
            y=df['volume'],
            name="成交量",
            marker_color='rgba(100, 100, 100, 0.5)'
        ),
        row=2, col=1
    )
    
    # 更新布局
    fig.update_layout(
        title=title,
        yaxis_title="价格 (IDR)",
        xaxis_rangeslider_visible=False,
        height=600
    )
    
    fig.show()

# 使用示例
kline_data = get_kline_data("12345", interval="P1D", limit=50)
plot_kline_chart(kline_data, "BBCA日线图")

2. 实时行情监控面板

创建实时行情监控界面。

import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import threading
import time

def create_realtime_dashboard():
    """创建实时行情监控面板"""
    app = dash.Dash(__name__)
    
    app.layout = html.Div([
        html.H1("印尼股票实时监控"),
        html.Div(id='price-display'),
        dcc.Graph(id='price-chart'),
        dcc.Interval(
            id='interval-component',
            interval=10*1000,  # 10秒更新一次
            n_intervals=0
        )
    ])
    
    @app.callback(
        [Output('price-display', 'children'),
         Output('price-chart', 'figure')],
        [Input('interval-component', 'n_intervals')]
    )
    def update_display(n):
        # 获取实时数据
        stock_data = get_stock_realtime("992844")
        
        if not stock_data:
            return "数据获取失败", go.Figure()
        
        # 创建价格显示
        price_display = html.Div([
            html.H2(f"{stock_data.get('symbol')}: {stock_data.get('last')} IDR"),
            html.P(f"涨跌幅: {stock_data.get('chgPct')}%"),
            html.P(f"技术建议: {stock_data.get('technicalDay')}")
        ])
        
        # 创建简单价格图表
        fig = go.Figure(
            go.Indicator(
                mode="gauge+number+delta",
                value=float(stock_data.get('last', 0)),
                delta={'reference': float(stock_data.get('prevClose', 0))},
                title={'text': "实时价格"},
                gauge={'axis': {'range': [None, float(stock_data.get('last', 0)) * 1.2]}}
            )
        )
        
        return price_display, fig
    
    return app

# 启动监控面板
if __name__ == '__main__':
    app = create_realtime_dashboard()
    app.run_server(debug=True)

高级功能:WebSocket实时推送

对于需要低延迟实时数据的场景,可以使用WebSocket接口。

import websocket
import json
import threading

class IndonesiaStockWebSocket:
    def __init__(self, api_key):
        self.api_key = api_key
        self.ws_url = "wss://api.stocktv.top/ws"
        self.ws = None
        
    def on_message(self, ws, message):
        """处理接收到的消息"""
        data = json.loads(message)
        print(f"收到实时数据: {data}")
        
        # 解析数据
        if data.get('type') == 1:  # 实时行情
            print(f"股票PID: {data.get('pid')}")
            print(f"最新价: {data.get('last_numeric')}")
            print(f"成交量: {data.get('volume')}")
    
    def on_error(self, ws, error):
        print(f"WebSocket错误: {error}")
    
    def on_close(self, ws, close_status_code, close_msg):
        print("WebSocket连接关闭")
    
    def on_open(self, ws):
        print("WebSocket连接已建立")
        # 发送订阅消息
        subscribe_msg = {
            "action": "subscribe",
            "key": self.api_key,
            "pids": ["992844", "992845"]  # 要订阅的股票PID列表
        }
        ws.send(json.dumps(subscribe_msg))
        
        # 启动心跳线程
        threading.Thread(target=self.heartbeat, args=(ws,)).start()
    
    def heartbeat(self, ws):
        """发送心跳包保持连接"""
        while True:
            time.sleep(30)
            try:
                ws.send(json.dumps({"action": "ping"}))
            except:
                break
    
    def connect(self):
        """建立WebSocket连接"""
        self.ws = websocket.WebSocketApp(
            self.ws_url,
            on_open=self.on_open,
            on_message=self.on_message,
            on_error=self.on_error,
            on_close=self.on_close
        )
        
        self.ws.run_forever()

# 使用示例
# ws_client = IndonesiaStockWebSocket(API_KEY)
# ws_client.connect()

印尼市场特点与注意事项

市场特点

  1. 交易时间: 雅加达时间09:00-16:00(连续交易,无午休),与北京时间相同
  2. 货币单位: 印尼盾(IDR),数值较大需注意单位转换
  3. 特色板块: 棕榈油、煤炭、镍矿等资源类股票交易活跃
  4. IPO活跃: 2023年印尼IPO数量位居东南亚首位

主流股票代码参考

  • BBCA: 中亚银行
  • TLKM: 印尼电信
  • BBRI: 人民银行
  • ASII: 阿斯特拉
  • GOTO: 科技股

开发注意事项

  1. 错误处理: 务必检查API返回的code字段,200表示成功
  2. 性能优化: 避免高频HTTP轮询,对多只股票监控应使用WebSocket接口
  3. 数据缓存: 对不频繁变化的数据(如股票列表)进行本地缓存
  4. 限流处理: 注意API调用频率限制,实现适当的重试机制

总结

通过本文介绍的方法,您可以快速构建印尼股票数据获取和展示系统。核心步骤包括:

  1. 获取认证密钥,建立基础连接
  2. 查询股票列表,获取唯一标识符PID
  3. 调用实时接口,获取最新行情和技术指标
  4. 获取历史数据,进行技术分析和回测
  5. 实现可视化,创建监控面板和图表

对于需要实时监控的场景,建议使用WebSocket接口以获得更低延迟的数据推送。印尼股票市场作为东南亚重要的投资目的地,为金融科技开发者提供了丰富的应用场景。

资源与支持

  • 官方文档: 详细接口文档和示例代码可参考相关平台的技术文档
  • 社区支持: 开发过程中遇到的问题可以在技术社区交流讨论
  • API密钥申请: 需要接入服务的开发者可通过官方渠道获取认证密钥

通过合理的接口设计和数据展示,您可以构建功能完善的印尼股票监控和分析工具,为投资决策提供数据支持。

本文介绍的技术方案基于公开的金融数据接口,具体实现可能因接口版本更新而有所调整。建议在实际开发前查阅最新的官方文档。