PythonBeginner10 min read

Build a Saudi Stock Tracker in Python with SAHMK API

In this tutorial, you'll learn how to use the SAHMK API to fetch real-time stock data from the Saudi Stock Exchange (Tadawul), track TASI market movers, and build a simple portfolio tracker — all in Python.

1. Prerequisites & Setup

Before we start, you'll need:

  • Python 3.7+ installed on your machine
  • A free SAHMK API key — sign up at sahmk.sa/developers (100 free requests/day)
  • The requests library

Install the requests library:

bash
pip install requests

The SAHMK API gives you access to 350+ companies listed on Tadawul (TASI and Nomu markets), including real-time quotes, historical data, financial statements, dividends, and more. The free tier includes delayed prices (15-minute delay) — perfect for learning and building.

2. Your First API Request — Get a Stock Quote

Let's start by fetching a quote for Aramco (symbol: 2222), the world's largest publicly traded company:

get_quote.py
import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://app.sahmk.sa/api/v1"

headers = {"X-API-Key": API_KEY}

# Fetch Aramco stock quote
response = requests.get(f"{BASE_URL}/quote/2222/", headers=headers)
data = response.json()

print(f"Company: {data['name_en']}")
print(f"Symbol:  {data['symbol']}")
print(f"Price:   {data['price']} SAR")
print(f"Change:  {data['change_value']} ({data['change_percent']}%)")
print(f"Volume:  {data['volume']:,}")
Output
Company: Saudi Aramco
Symbol:  2222
Price:   28.30 SAR
Change:  -0.15 (-0.53%)
Volume:  8,432,150

The /quote/{symbol}/ endpoint returns comprehensive data including price, change, volume, day range, 52-week range, and more. Check the full API reference for all available fields.

3. Market Overview — Gainers, Losers & Volume Leaders

The SAHMK API provides endpoints to get today's top market movers. This is useful for building market dashboards or screening tools:

market_movers.py
import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://app.sahmk.sa/api/v1"

headers = {"X-API-Key": API_KEY}

# Get today's top gainers
gainers = requests.get(f"{BASE_URL}/market/gainers/", headers=headers).json()

print("📈 Top 5 Gainers Today")
print("-" * 50)
for stock in gainers[:5]:
    print(f"  {stock['name_en']:<25} {stock['change_percent']:>+6.2f}%  {stock['price']} SAR")

print()

# Get today's top losers
losers = requests.get(f"{BASE_URL}/market/losers/", headers=headers).json()

print("📉 Top 5 Losers Today")
print("-" * 50)
for stock in losers[:5]:
    print(f"  {stock['name_en']:<25} {stock['change_percent']:>+6.2f}%  {stock['price']} SAR")

print()

# Get market summary (TASI index)
summary = requests.get(f"{BASE_URL}/market/summary/", headers=headers).json()

print("🏛️  Market Summary")
print("-" * 50)
for index_data in summary:
    print(f"  {index_data['name_en']}: {index_data['value']} ({index_data['change_percent']:+.2f}%)")
Output
📈 Top 5 Gainers Today
--------------------------------------------------
  Aldrees Petroleum         +9.97%  142.00 SAR
  Alujain Corp              +7.42%  38.50 SAR
  Saudi Ceramic             +5.18%  61.00 SAR
  Zamil Industrial          +4.85%  27.30 SAR
  Batic Investments         +4.23%  39.75 SAR

📉 Top 5 Losers Today
--------------------------------------------------
  Alinma Bank               -3.12%  27.95 SAR
  Savola Group              -2.87%  32.10 SAR
  Yanbu Cement              -2.45%  54.80 SAR
  Saudi Kayan               -2.31%  12.68 SAR
  Etihad Etisalat           -1.98%  51.20 SAR

🏛️  Market Summary
--------------------------------------------------
  TASI: 12,456.32 (+0.45%)
  Nomu: 28,234.10 (-0.12%)

Other market endpoints include /market/most-volume/, /market/most-value/, and /market/sectors/ for sector-level analysis.

4. Build a Portfolio Tracker

Now let's build something practical — a portfolio tracker that shows your current holdings, their value, and profit/loss:

portfolio_tracker.py
import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://app.sahmk.sa/api/v1"

headers = {"X-API-Key": API_KEY}

# Define your portfolio: symbol, shares, avg cost
portfolio = [
    {"symbol": "2222", "shares": 100, "avg_cost": 27.50},  # Aramco
    {"symbol": "1180", "shares": 50,  "avg_cost": 32.00},  # Al Rajhi Bank
    {"symbol": "2350", "shares": 200, "avg_cost": 8.50},   # Saudi Kayan
    {"symbol": "7010", "shares": 75,  "avg_cost": 98.00},  # STC
]

print("📊 Portfolio Summary")
print("=" * 70)
print(f"  {'Stock':<20} {'Shares':>6} {'Avg Cost':>10} {'Price':>10} {'P/L':>12}")
print("-" * 70)

total_cost = 0
total_value = 0

for holding in portfolio:
    response = requests.get(
        f"{BASE_URL}/quote/{holding['symbol']}/",
        headers=headers
    )
    stock = response.json()

    current_price = float(stock["price"])
    cost_basis = holding["shares"] * holding["avg_cost"]
    market_value = holding["shares"] * current_price
    pnl = market_value - cost_basis
    pnl_pct = (pnl / cost_basis) * 100

    total_cost += cost_basis
    total_value += market_value

    sign = "+" if pnl >= 0 else ""
    print(
        f"  {stock['name_en']:<20} "
        f"{holding['shares']:>6} "
        f"{holding['avg_cost']:>9.2f} "
        f"{current_price:>9.2f} "
        f"{sign}{pnl:>8.2f} ({sign}{pnl_pct:.1f}%)"
    )

total_pnl = total_value - total_cost
total_pnl_pct = (total_pnl / total_cost) * 100
sign = "+" if total_pnl >= 0 else ""

print("=" * 70)
print(f"  Total Cost:   {total_cost:>10,.2f} SAR")
print(f"  Market Value: {total_value:>10,.2f} SAR")
print(f"  Total P/L:    {sign}{total_pnl:>10,.2f} SAR ({sign}{total_pnl_pct:.1f}%)")
Output
📊 Portfolio Summary
======================================================================
  Stock                Shares   Avg Cost      Price          P/L
----------------------------------------------------------------------
  Saudi Aramco            100      27.50      28.30   +80.00 (+2.9%)
  Al Rajhi Bank            50      32.00      88.40 +2,820.00 (+176.3%)
  Saudi Kayan             200       8.50      12.68  +836.00 (+49.2%)
  STC                      75      98.00     168.80 +5,310.00 (+72.2%)
======================================================================
  Total Cost:    12,200.00 SAR
  Market Value:  21,246.00 SAR
  Total P/L:    +9,046.00 SAR (+74.1%)

5. Batch Quotes — Multiple Stocks in One Request

Instead of making separate requests for each stock, you can use the batch endpoint to fetch multiple quotes at once. This is more efficient and uses fewer API calls:

batch_quotes.py
import requests

API_KEY = "your_api_key_here"
BASE_URL = "https://app.sahmk.sa/api/v1"

headers = {"X-API-Key": API_KEY}

# Fetch multiple stock quotes in a single request
symbols = "2222,1180,2350,7010,1010,2010"

response = requests.get(
    f"{BASE_URL}/quote/batch/",
    headers=headers,
    params={"symbols": symbols}
)
stocks = response.json()

print(f"{'Symbol':<8} {'Company':<25} {'Price':>8} {'Change':>10}")
print("-" * 55)

for stock in stocks:
    change = f"{stock['change_percent']:+.2f}%"
    print(f"{stock['symbol']:<8} {stock['name_en']:<25} {stock['price']:>8} {change:>10}")
Output
Symbol   Company                      Price     Change
-------------------------------------------------------
2222     Saudi Aramco                  28.30     -0.53%
1180     Al Rajhi Bank                 88.40     +1.26%
2350     Saudi Kayan                   12.68     -2.31%
7010     STC                          168.80     +0.84%
1010     Riyad Bank                    27.65     +0.36%
2010     SABIC                         82.30     -0.48%

The batch endpoint accepts up to 20 symbols per request, making it ideal for portfolio dashboards and watchlists.

6. Next Steps

You now have a working Saudi stock tracker. Here are some ideas to take it further:

  • Historical data: Use the /history/{symbol}/ endpoint to chart price trends (Starter plan)
  • Financial statements: Fetch balance sheets and income statements via /financials/ (Starter plan)
  • Real-time streaming: Connect via WebSocket for live price updates (Pro plan)
  • Dividends: Track dividend announcements with /dividends/
  • Build a web dashboard: Combine with Flask or Streamlit for a visual interface

Ready to start building?

Get your free API key and start fetching Tadawul stock data in minutes. 100 free requests per day, no credit card required.