Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Fetching Real-Time Precious Metals Prices from Shanghai Gold Exchange via API

Tech 1

The Shanghai Gold Exchange (SGE) price data is served dynamically through a JSONP endpoint that returns structured market quotes. The API accepts a comma-separated list of instrument codes and appends a timestamp to prevent caching.

Instrument identifiers include:

JO_9753,JO_92226,JO_9754,JO_71,JO_70,JO_73,JO_72,JO_75,JO_9751,JO_9752,
JO_92224,JO_92225,JO_92276,JO_76,JO_74,JO_92277,JO_92278

The corresponding endpoint is:

https://api.jijinhao.com/quoteCenter/realTime.htm?codes=JO_9753,...,JO_92278

Response format contains a global quote_json object where each key maps to an instrument code, and values are objects with fields like q1 (open), q2 (close), q3 (high), q4 (low), q5 (bid), q6 (ask), q63 (last), q70 (change), q80 (change percent), time (Unix timestamp in milliseconds), digits (decimal precision), showCode (symbol name), and unit.

Below is a clean Python implemantation that fetches, parses, and normalizes this data with out HTML formatting or UI logic:

import requests
import json
from datetime import datetime
from typing import Dict, Any, Optional

# Mapping from internal code to human-readable name
INSTRUMENT_NAMES = {
    "Au(T+D)": "Gold T+D",
    "mAu(T+D)": "Mini Gold T+D",
    "Ag(T+D)": "Silver T+D",
    "Au9999": "Gold 99.99%",
    "Au9995": "Gold 99.95%",
    "Au100g": "100g Gold Bar",
    "Au50g": "50g Gold Bar",
    "Ag999": "Silver 99.9%",
    "AuT+N1": "Gold T+N1",
    "AuT+N2": "Gold T+N2",
    "SGiAu100g": "Gi 100g Gold",
    "SGiAu9999i": "Gi Gold 99.99%",
    "SGiAu995i": "Gi Gold 99.95%",
    "Ag9999": "Silver 99.99%",
    "PT9995": "Platinum 99.95%",
    "NYAuTN06": "NYMEX Gold TN06",
    "NYAuTN12": "NYMEX Gold TN12"
}

# Correspondence between JO_* codes and symbols
CODE_TO_SYMBOL = {
    "JO_9753": "Au(T+D)",
    "JO_92226": "mAu(T+D)",
    "JO_9754": "Ag(T+D)",
    "JO_71": "Au9999",
    "JO_70": "Au9995",
    "JO_73": "Au100g",
    "JO_72": "Au50g",
    "JO_75": "Ag999",
    "JO_9751": "AuT+N1",
    "JO_9752": "AuT+N2",
    "JO_92224": "SGiAu100g",
    "JO_92225": "SGiAu9999i",
    "JO_92276": "SGiAu995i",
    "JO_76": "Ag9999",
    "JO_74": "PT9995",
    "JO_92277": "NYAuTN06",
    "JO_92278": "NYAuTN12"
}

def fetch_sge_quotes() -> Dict[str, Dict[str, Any]]:
    base_url = "https://api.jijinhao.com/quoteCenter/realTime.htm"
    codes = ",".join(CODE_TO_SYMBOL.keys())
    url = f"{base_url}?codes={codes}"

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    }

    try:
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()

        # Extract JSONP callback: look for 'quote_json = {...};'
        content = response.text.strip()
        start = content.find('{')
        end = content.rfind('}') + 1
        if start == -1 or end == 0:
            raise ValueError("Invalid JSONP response: missing JSON object")

        json_str = content[start:end]
        raw_data = json.loads(json_str)

        result = {}
        for jo_code, quote in raw_data.items():
            if not isinstance(quote, dict):
                continue

            symbol = CODE_TO_SYMBOL.get(jo_code)
            if not symbol:
                continue

            digits = int(quote.get("digits", 2))
            def safe_round(val) -> Optional[float]:
                try:
                    return round(float(val), digits) if val not in (None, "", "----") else None
                except (ValueError, TypeError):
                    return None

            def safe_datetime(ts_ms) -> Optional[str]:
                try:
                    if isinstance(ts_ms, (int, float)) and ts_ms > 1e9:
                        return datetime.fromtimestamp(ts_ms / 1000).strftime("%Y-%m-%d %H:%M:%S")
                except (OSError, ValueError):
                    pass
                return None

            result[symbol] = {
                "name": INSTRUMENT_NAMES.get(symbol, symbol),
                "last": safe_round(quote.get("q63")),
                "change_value": safe_round(quote.get("q70")),
                "change_percent": safe_round(quote.get("q80")),
                "open": safe_round(quote.get("q1")),
                "close": safe_round(quote.get("q2")),
                "high": safe_round(quote.get("q3")),
                "low": safe_round(quote.get("q4")),
                "bid": safe_round(quote.get("q5")),
                "ask": safe_round(quote.get("q6")),
                "timestamp": safe_datetime(quote.get("time")),
                "unit": quote.get("unit", "").strip() or None
            }

        return result

    except Exception as e:
        print(f"Failed to fetch SGE quotes: {e}")
        return {}

# Example usage
if __name__ == "__main__":
    quotes = fetch_sge_quotes()
    for symbol, data in quotes.items():
        if data["last"] is not None:
            print(f"{data['name']} ({symbol}): {data['last']} {data['unit'] or ''} @ {data['timestamp']}")

This script handles malformed responses, missing fields, and type coercion gracefully. It discards presentation logic (e.g., color classes or HTML wrappers), converts timestamps to ISO-style strings, replaces placeholder values (----) with None, and maps internal codes to standardized instrument names and units.

Tags: Python

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.