Global market data provides useful context for understanding broader market conditions and their potential influence on the Indonesian stock market.
In this project, we will use two IDX API endpoints:
Global Market Overview
Global Indices Impact
The project consists of five cells covering API configuration, data requests, response normalization, detailed data inspection, and the final IDX Global Market Analysis Dashboard.
Cell 1 — Import Libraries and Configure the API
# ============================================================
# CELL 1 — IMPORT LIBRARY & KONFIGURASI API
# ============================================================
import requests
import pandas as pd
import json
import time
from datetime import datetime
BASE_URL = "https://indonesia-stock-exchange-idx.p.rapidapi.com"
RAPIDAPI_KEY = "YOUR_RAPIDAPI_KEY"
HEADERS = {
"Content-Type": "application/json",
"x-rapidapi-host": "indonesia-stock-exchange-idx.p.rapidapi.com",
"x-rapidapi-key": RAPIDAPI_KEY
}
print("=" * 90)
print("IDX GLOBAL MARKET ANALYSIS")
print("=" * 90)
print("Base URL :", BASE_URL)
print("Status : Konfigurasi siap")
Cell 1 imports the required libraries and prepares the RapidAPI configuration. The original API key is replaced with YOUR_RAPIDAPI_KEY for security, while the remaining code follows the notebook.
Cell 2 — Request Global Market Overview and Indices Impact
# ============================================================
# CELL 2 — REQUEST DATA API
# ============================================================
def request_api(endpoint, timeout=30):
url = BASE_URL + endpoint
print("=" * 90)
print("Endpoint :", endpoint)
try:
response = requests.get(
url,
headers=HEADERS,
timeout=timeout
)
print("Status :", response.status_code)
if response.status_code == 200:
try:
data = response.json()
print("Success : True")
return data
except Exception:
print("Success : False")
print("Pesan : Response bukan JSON valid.")
print(response.text[:500])
return None
print("Success : False")
if response.status_code == 429:
print("Pesan : Rate limit RapidAPI tercapai.")
elif response.status_code == 403:
print("Pesan : Akses ditolak / API belum tersedia pada paket Anda.")
elif response.status_code == 401:
print("Pesan : API Key tidak valid atau belum diisi.")
elif response.status_code == 422:
print("Pesan : Parameter request tidak valid.")
print("\nResponse API:")
print(response.text[:1000])
return None
except requests.exceptions.Timeout:
print("Success : False")
print("Pesan : Request timeout.")
return None
except requests.exceptions.RequestException as e:
print("Success : False")
print("Pesan :", str(e))
return None
# ------------------------------------------------------------
# 1. GLOBAL MARKET OVERVIEW
# ------------------------------------------------------------
global_market_raw = request_api(
"/api/global/market-overview"
)
# Jeda untuk mengurangi risiko 429
print("\n⏳ Memberikan jeda 5 detik sebelum request berikutnya...\n")
time.sleep(5)
# ------------------------------------------------------------
# 2. INDICES IMPACT
# ------------------------------------------------------------
indices_impact_raw = request_api(
"/api/global/indices-impact"
)
Cell 2 defines a reusable request_api() function with handling for invalid JSON, rate limits, access errors, invalid API keys, invalid parameters, timeouts, and other request errors.
The notebook retrieves Global Market Overview first, waits five seconds to reduce the risk of rate limiting, and then requests Global Indices Impact.
Cell 3 — Normalize and Debug the API Response
# ============================================================
# CELL 3 — NORMALISASI & DEBUG DATA
# ============================================================
def extract_data(response):
"""
Mengambil bagian data utama dari berbagai kemungkinan
struktur response API.
"""
if response is None:
return None
if isinstance(response, list):
return response
if isinstance(response, dict):
# Struktur umum: {"success": true, "data": ...}
if "data" in response:
return response["data"]
# Kemungkinan struktur lainnya
for key in ["results", "result", "items"]:
if key in response:
return response[key]
return response
return None
global_market_data = extract_data(global_market_raw)
indices_impact_data = extract_data(indices_impact_raw)
def safe_normalize(data):
"""
Mengubah data menjadi DataFrame tanpa error
jika response berupa dict/list/nested JSON.
"""
if data is None:
return pd.DataFrame()
try:
if isinstance(data, list):
return pd.json_normalize(data)
elif isinstance(data, dict):
return pd.json_normalize(data)
else:
return pd.DataFrame([{"value": data}])
except Exception as e:
print("Normalisasi gagal :", e)
return pd.DataFrame()
global_market_df = safe_normalize(global_market_data)
indices_impact_df = safe_normalize(indices_impact_data)
print("=" * 90)
print("HASIL NORMALISASI")
print("=" * 90)
print("Global Market Records :", len(global_market_df))
print("Indices Impact Records:", len(indices_impact_df))
print("\n" + "=" * 90)
print("DEBUG STRUKTUR RESPONSE")
print("=" * 90)
print("\nGLOBAL MARKET OVERVIEW")
print("-" * 90)
print("Raw Type :", type(global_market_raw).__name__)
print("Data Type:", type(global_market_data).__name__)
if isinstance(global_market_raw, dict):
print("Raw Keys :", list(global_market_raw.keys()))
if isinstance(global_market_data, dict):
print("Data Keys:", list(global_market_data.keys()))
if len(global_market_df):
print("Columns :", list(global_market_df.columns))
print("\nINDICES IMPACT")
print("-" * 90)
print("Raw Type :", type(indices_impact_raw).__name__)
print("Data Type:", type(indices_impact_data).__name__)
if isinstance(indices_impact_raw, dict):
print("Raw Keys :", list(indices_impact_raw.keys()))
if isinstance(indices_impact_data, dict):
print("Data Keys:", list(indices_impact_data.keys()))
if len(indices_impact_df):
print("Columns :", list(indices_impact_df.columns))
Cell 3 extracts the primary dataset from several possible JSON structures and safely converts the results into pandas DataFrames. It also displays record counts, response types, available keys, and columns for debugging.
Cell 4 — Display Global Market and Indices Impact Data
# ============================================================
# CELL 4 — DETAIL GLOBAL MARKET & INDICES IMPACT
# ============================================================
pd.set_option("display.max_columns", None)
pd.set_option("display.max_rows", 100)
pd.set_option("display.max_colwidth", 100)
print("=" * 100)
print("GLOBAL MARKET OVERVIEW")
print("=" * 100)
if len(global_market_df):
display(global_market_df)
else:
print("Tidak ada data Global Market Overview.")
if global_market_raw is not None:
print("\nRaw Response:")
print(
json.dumps(
global_market_raw,
indent=2,
ensure_ascii=False
)[:5000]
)
print("\n\n" + "=" * 100)
print("INDICES IMPACT")
print("=" * 100)
if len(indices_impact_df):
display(indices_impact_df)
else:
print("Tidak ada data Indices Impact.")
if indices_impact_raw is not None:
print("\nRaw Response:")
print(
json.dumps(
indices_impact_raw,
indent=2,
ensure_ascii=False
)[:5000]
)
Cell 4 displays the complete normalized datasets. If a DataFrame is empty but a raw response exists, the original JSON response is displayed as a fallback.
Cell 5 — IDX Global Market Analysis Dashboard
# ============================================================
# CELL 5 — IDX GLOBAL MARKET DASHBOARD
# ============================================================
def format_value(value):
"""Format value agar lebih nyaman dibaca."""
if value is None:
return "-"
if isinstance(value, bool):
return "Ya" if value else "Tidak"
if isinstance(value, float):
if abs(value) >= 1000:
return f"{value:,.2f}"
return f"{value:.2f}"
if isinstance(value, int):
return f"{value:,}"
return str(value)
def flatten_nested(data, parent_key=""):
"""
Mengubah nested dictionary menjadi daftar key-value
tanpa kehilangan informasi penting.
"""
rows = []
if isinstance(data, dict):
for key, value in data.items():
full_key = f"{parent_key}.{key}" if parent_key else key
if isinstance(value, dict):
rows.extend(
flatten_nested(
value,
full_key
)
)
elif isinstance(value, list):
if len(value) == 0:
rows.append(
(full_key, "[]")
)
else:
for i, item in enumerate(value):
item_key = f"{full_key}[{i}]"
if isinstance(item, (dict, list)):
rows.extend(
flatten_nested(
item,
item_key
)
)
else:
rows.append(
(
item_key,
format_value(item)
)
)
else:
rows.append(
(
full_key,
format_value(value)
)
)
elif isinstance(data, list):
for i, item in enumerate(data):
rows.extend(
flatten_nested(
item,
f"[{i}]"
)
)
else:
rows.append(
(
parent_key or "value",
format_value(data)
)
)
return rows
# ============================================================
# FLATTEN DATA
# ============================================================
global_flat = flatten_nested(global_market_data)
indices_flat = flatten_nested(indices_impact_data)
# ============================================================
# DASHBOARD
# ============================================================
print("=" * 110)
print("IDX GLOBAL MARKET ANALYSIS DASHBOARD")
print("=" * 110)
# ============================================================
# GLOBAL MARKET OVERVIEW
# ============================================================
print("\n🌎 GLOBAL MARKET OVERVIEW")
print("-" * 110)
if global_flat:
print(
f"Jumlah Informasi : "
f"{len(global_flat)}"
)
print()
for i, (key, value) in enumerate(global_flat[:40], 1):
print(
f"{i:02d}. "
f"{key:<55} : "
f"{value}"
)
if len(global_flat) > 40:
print(
f"\n... dan "
f"{len(global_flat) - 40} "
f"informasi lainnya."
)
else:
print("Tidak ada data Global Market Overview.")
# ============================================================
# INDICES IMPACT
# ============================================================
print("\n\n📊 GLOBAL INDICES IMPACT")
print("-" * 110)
if indices_flat:
print(
f"Jumlah Informasi : "
f"{len(indices_flat)}"
)
print()
for i, (key, value) in enumerate(indices_flat[:40], 1):
print(
f"{i:02d}. "
f"{key:<55} : "
f"{value}"
)
if len(indices_flat) > 40:
print(
f"\n... dan "
f"{len(indices_flat) - 40} "
f"informasi lainnya."
)
else:
print("Tidak ada data Indices Impact.")
# ============================================================
# RINGKASAN
# ============================================================
print("\n\n" + "=" * 110)
print("RINGKASAN")
print("=" * 110)
print(
"🌎 Global Market Overview :",
f"{len(global_flat)} informasi"
if global_flat
else "Tidak ada data"
)
print(
"📊 Global Indices Impact :",
f"{len(indices_flat)} informasi"
if indices_flat
else "Tidak ada data"
)
print("\nStatus API")
print("-" * 110)
print(
"Global Market Overview :",
"✅ Berhasil"
if global_market_raw is not None
else "❌ Gagal"
)
print(
"Indices Impact :",
"✅ Berhasil"
if indices_impact_raw is not None
else "❌ Gagal"
)
print("\n" + "=" * 110)
print(
"Selesai diproses :",
datetime.now().strftime(
"%d-%m-%Y %H:%M:%S"
)
)
print("=" * 110)
Cell 5 flattens nested Global Market Overview and Global Indices Impact responses into readable key-value information without discarding nested fields. Numeric and boolean values are also formatted for cleaner output.
The dashboard displays up to 40 pieces of information from each endpoint before generating a final summary with record counts, API status, and processing timestamp.
Final Result

After executing all five cells, this project can:
Retrieve Global Market Overview data.
Retrieve Global Indices Impact data.
Handle common RapidAPI errors and request timeouts.
Normalize different JSON response structures.
Display detailed DataFrames.
Preserve nested information through recursive flattening.
Generate a readable global market dashboard.
Display API processing status and completion time.
Conclusion
This project demonstrates how to build an IDX Global Market Analysis Dashboard using Python and RapidAPI.
By combining Global Market Overview with Global Indices Impact, the notebook provides a structured workflow for retrieving and exploring broader market information through the IDX API.
The project handles API requests, response validation, JSON normalization, nested data processing, detailed previews, and dashboard generation within five cells. This structure makes it a useful foundation for developing broader global market monitoring and automated financial analysis workflows.
