DEV Community

Cover image for Integrating Japanese Stock APIs: Accessing Tokyo Stock Exchange (TSE) Data for K-Line and MACD Analysis
San Si wu
San Si wu

Posted on

Integrating Japanese Stock APIs: Accessing Tokyo Stock Exchange (TSE) Data for K-Line and MACD Analysis

In this blog post, we'll explore how to connect to the Tokyo Stock Exchange (TSE) via stock APIs to monitor real-time Japanese market data and perform historical analysis. By leveraging stock APIs, high-frequency real-time quote APIs, and market data APIs, you can easily access real-time stock quotes, financial market data, and more from Japanese exchanges. We'll also dive into technical analysis using the classic MACD indicator, which is perfect for financial API development and helping investors grasp market trends.

Tokyo Stock Exchange - iTick API
First, I'll compare several APIs that support the Japanese market. Then, using iTick API as an example, I'll walk you through fetching data and implementing MACD analysis to kickstart your quantitative projects.

1. Comparing Japanese Stock APIs

There are several providers offering Japanese stock APIs, each with strengths in data quality, real-time capabilities, pricing, and use cases.

To help you choose, here's a side-by-side comparison of four popular APIs that provide real-time quotes and historical data from the Tokyo Stock Exchange.

API Name Key Features Pricing Model Best For
iTick API Unified request headers for easy integration. Covers real-time quotes (Tick/Quote), multi-timeframe K-lines, and WebSocket pushes. Comprehensive data with low latency. Free tier available. Personal development, quantitative trading, projects needing structured data.
StockTV API Supports global market integration with built-in indicators like SMA and RSI returned directly. Limited free credits + pay-per-use. Teams needing cross-market data or pre-computed indicators.
Alpha Vantage Free access to basic real-time and historical data across global markets. Completely free, but strict rate limits (e.g., 5 calls/minute). Learning, prototyping non-high-frequency strategies.
Yahoo Finance API Broad data coverage with free access. Free. Educational demos, simple queries—not for high-stability production.

2. Hands-On: Fetching Data and Calculating MACD with iTick API

Let's get practical with iTick API, from setup to data retrieval and MACD computation.

Step 1: Set Up Your Environment and Get Your API Key

  1. Register and Get a Token: Head to the iTick website, sign up, and grab your API token from the dashboard.
  2. Install Python Libraries: Run this in your terminal:
   pip install requests pandas numpy
Enter fullscreen mode Exit fullscreen mode

Step 2: Fetch Japanese Stock K-Line Data

We'll use historical K-line data for MACD calculations. iTick's K-line endpoint is flexible, supporting timeframes from 1-minute to monthly.

Here's code to fetch 50 bars of 5-minute K-line data for Toyota Motor (code: 7203).

import requests
import pandas as pd

# 1. Set up API request headers (common to all iTick endpoints)
headers = {
    "accept": "application/json",
    "token": "your_token_here"  # Replace with your actual token
}

# 2. Build the request URL
# Parameters:
# region=JP for Japanese market
# code=7203 for Toyota Motor
# kType=2 for 5-minute K-lines (1:1-min, 2:5-min, ..., 8:daily)
# limit=50 to get 50 bars
url = "https://api.itick.org/stock/kline?region=JP&code=7203&kType=2&limit=50"

# 3. Send the request and handle the response
response = requests.get(url, headers=headers)
data = response.json()

if data["code"] == 0:  # Success
    kline_list = data["data"]
    # Convert to Pandas DataFrame for easier analysis
    df = pd.DataFrame(kline_list)
    # Rename columns for readability
    df.rename(columns={'t': 'timestamp', 'o': 'open', 'h': 'high',
                       'l': 'low', 'c': 'close', 'v': 'volume'}, inplace=True)
    # Convert timestamp to datetime
    df['datetime'] = pd.to_datetime(df['timestamp'], unit='s')
    df.set_index('datetime', inplace=True)

    print(f"Successfully fetched {len(df)} K-line bars")
    print(df[['open', 'high', 'low', 'close', 'volume']].head())
else:
    print(f"Request failed: {data['msg']}")
Enter fullscreen mode Exit fullscreen mode

Step 3: Calculate the MACD Indicator

MACD (Moving Average Convergence Divergence) is a popular momentum indicator consisting of three components: DIF (Difference), DEA (Signal Line), and MACD Histogram. The standard parameters are (12, 26, 9).

We can implement it easily with Pandas and NumPy:

import numpy as np

def calculate_ema(series, period):
    """Calculate Exponential Moving Average (EMA)"""
    return series.ewm(span=period, adjust=False).mean()

def calculate_macd(df, fast=12, slow=26, signal=9):
    """
    Calculate MACD and add to DataFrame
    :param df: DataFrame with 'close' prices
    :param fast: Fast EMA period
    :param slow: Slow EMA period
    :param signal: Signal EMA period
    """
    # Calculate fast and slow EMAs
    df['EMA_fast'] = calculate_ema(df['close'], fast)
    df['EMA_slow'] = calculate_ema(df['close'], slow)

    # Calculate DIF (Difference)
    df['DIF'] = df['EMA_fast'] - df['EMA_slow']

    # Calculate DEA (Signal line, EMA of DIF)
    df['DEA'] = calculate_ema(df['DIF'], signal)

    # Calculate MACD Histogram (multiplied by 2 for visual emphasis)
    df['MACD_hist'] = 2 * (df['DIF'] - df['DEA'])

    return df

# Apply MACD to the fetched K-line data
df_with_macd = calculate_macd(df)

# View results
print(df_with_macd[['close', 'DIF', 'DEA', 'MACD_hist']].tail())
Enter fullscreen mode Exit fullscreen mode

Key Insights:

  • Golden/Dead Cross: A "golden cross" (buy signal) occurs when DIF crosses above DEA from below. A "dead cross" (sell signal) is the opposite.
  • Zero Line: DIF and DEA above zero indicate a bullish market; below zero suggests bearish.
  • Histogram: The height shows trend strength; positive bars are bullish, negative are bearish.

Step 4: Simple Visualization

Visualizing the price and MACD together helps spot relationships intuitively.

import matplotlib.pyplot as plt

# Create figure and axes
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), gridspec_kw={'height_ratios': [3, 1]})

# Subplot 1: Plot price and EMAs
ax1.plot(df_with_macd.index, df_with_macd['close'], label='Close Price', linewidth=1.5, color='black')
ax1.plot(df_with_macd.index, df_with_macd['EMA_fast'], label=f'EMA{12}', alpha=0.7)
ax1.plot(df_with_macd.index, df_with_macd['EMA_slow'], label=f'EMA{26}', alpha=0.7)
ax1.set_title('Toyota Motor (7203.T) - Price & MACD')
ax1.set_ylabel('Price')
ax1.legend()
ax1.grid(True, alpha=0.3)

# Subplot 2: Plot MACD DIF, DEA, and Histogram
ax2.plot(df_with_macd.index, df_with_macd['DIF'], label='DIF', color='blue', linewidth=1.5)
ax2.plot(df_with_macd.index, df_with_macd['DEA'], label='DEA', color='red', linewidth=1.5)
# Histogram bars: green for positive, red for negative
colors = ['green' if x >= 0 else 'red' for x in df_with_macd['MACD_hist']]
ax2.bar(df_with_macd.index, df_with_macd['MACD_hist'], color=colors, alpha=0.5, width=0.01, label='MACD Hist')
ax2.axhline(y=0, color='grey', linestyle='--', linewidth=0.8)
ax2.set_ylabel('MACD')
ax2.legend()
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()
Enter fullscreen mode Exit fullscreen mode

Step 5: Real-Time MACD Monitoring with WebSocket

WebSocket enables real-time, bidirectional communication for live data. Use it to monitor stock quotes and update MACD dynamically.

class RealTimeMACDMonitor:
    """Real-Time MACD Monitor"""
    def __init__(self, stock_codes, token, fast_period=12, slow_period=26, signal_period=9):
        self.stock_codes = stock_codes if isinstance(stock_codes, list) else [stock_codes]
        self.token = token
        self.fast_period = fast_period
        self.slow_period = slow_period
        self.signal_period = signal_period

        # Store historical data
        self.historical_data = {code: pd.DataFrame() for code in self.stock_codes}

        # MACD states
        self.macd_states = {code: {
            'dif': None,
            'dea': None,
            'histogram': None,
            'signal': 0  # 0: no signal, 1: golden cross, -1: dead cross
        } for code in self.stock_codes}

    def update_data(self, stock_code, new_price_data):
        """Update stock data and recalculate MACD"""
        if stock_code not in self.historical_data:
            return

        # Add new data
        df = self.historical_data[stock_code]
        new_df = pd.DataFrame([new_price_data])

        if len(df) == 0:
            self.historical_data[stock_code] = new_df
        else:
            self.historical_data[stock_code] = pd.concat([df, new_df])

        # Keep recent data (e.g., last 100 bars)
        if len(self.historical_data[stock_code]) > 100:
            self.historical_data[stock_code] = self.historical_data[stock_code].iloc[-100:]

        # Calculate MACD if enough data
        if len(self.historical_data[stock_code]) >= self.slow_period + 10:
            df_with_macd = calculate_macd(
                self.historical_data[stock_code],
                self.fast_period,
                self.slow_period,
                self.signal_period
            )

            # Update MACD state
            last_row = df_with_macd.iloc[-1]
            prev_row = df_with_macd.iloc[-2] if len(df_with_macd) > 1 else None

            self.macd_states[stock_code]['dif'] = last_row['DIF']
            self.macd_states[stock_code]['dea'] = last_row['DEA']
            self.macd_states[stock_code]['histogram'] = last_row['MACD_hist']

            # Detect signal changes
            if prev_row is not None:
                # Golden cross detection
                if last_row['DIF'] > last_row['DEA'] and prev_row['DIF'] <= prev_row['DEA']:
                    self.macd_states[stock_code]['signal'] = 1
                    print(f"⚠️ {stock_code} MACD Golden Cross Signal! DIF={last_row['DIF']:.2f}, DEA={last_row['DEA']:.2f}")

                # Dead cross detection
                elif last_row['DIF'] < last_row['DEA'] and prev_row['DIF'] >= prev_row['DEA']:
                    self.macd_states[stock_code]['signal'] = -1
                    print(f"⚠️ {stock_code} MACD Dead Cross Signal! DIF={last_row['DIF']:.2f}, DEA={last_row['DEA']:.2f}")

    def get_macd_summary(self):
        """Get MACD status summary for all monitored stocks"""
        summary = []
        for code, state in self.macd_states.items():
            if state['dif'] is not None:
                signal_text = "No Signal"
                if state['signal'] == 1:
                    signal_text = "Golden Cross (Buy)"
                elif state['signal'] == -1:
                    signal_text = "Dead Cross (Sell)"

                summary.append({
                    'Stock Code': code,
                    'DIF': state['dif'],
                    'DEA': state['dea'],
                    'Histogram': state['histogram'],
                    'Signal': signal_text
                })

        return pd.DataFrame(summary)
Enter fullscreen mode Exit fullscreen mode

3. Wrapping Up and Tips

Connecting to the Tokyo Stock Exchange for quantitative analysis is straightforward, as shown in this guide.

  • API Selection: Start with free or low-cost options like iTick's free tier to test ideas. Upgrade to paid plans for higher frequency and reliability once your strategy is solid.
  • Data Fundamentals: No matter the API, reliable and accurate data is key to successful quant strategies. Cross-verify sources for critical decisions.
  • Beyond MACD: This is just an entry point. Combine MACD with RSI, Bollinger Bands, or integrate real-time quote APIs for more advanced trading systems.

Note: This post is for informational purposes only and not investment advice. Markets involve risk—invest wisely.

Reference: https://blog.itick.org/stock-api/free-japan-stock-api-comparison

GitHub: https://github.com/itick-org/

Top comments (0)