Historical HKMA (HKMA_BASE) Rates

Historical HKMA (HKMA_BASE) Rates

You need reliable, queryable history for the HKMA Base Rate to drive pricing, risk, and reporting. By the end of this guide, you will fetch, analyze, and chart historical HKMA_BASE data via the Interest Rates API, handle monthly frequency nuances, compute spreads and payments from the returned values, and productionize a Python pipeline that writes clean CSV/Parquet outputs.

What HKMA_BASE represents and how it’s expressed

HKMA_BASE is the Hong Kong Monetary Authority Base Rate. In the Interest Rates API, this symbol is categorized as a central bank benchmark and delivered as a numeric percentage rate. The value is expressed in percent (e.g., 4.25 means 4.25% per annum) and is tied to HKD as its currency context.

Frequency: monthly. For point-in-time lookups across weekends and holidays, monthly symbols use the “last day with data within that month.” This matters when you request a historical date that falls on a non-business day or early in a month before publication—your application should interpret the effective date accordingly.

Quick verification: find the symbol

Before integrating, it’s good practice to validate that HKMA_BASE exists in the catalogue. You can filter by category or currency. The /symbols endpoint is a lightweight way to bootstrap configuration or preflight a deployment.

curl -s "https://interestratesapi.com/api/v1/latest?api_key=YOUR_API_KEY&symbols=HKMA_BASE"

Result fields include the symbol, human-readable name, category, currency_code, and frequency. Use this information to confirm monthly cadence and to wire symbol metadata into tooltips or docs in your codebase.

Latest snapshot for HKMA_BASE (official sample)

Many integrations start by reading the latest rate, then backfilling a time series for trend analysis. Below is the official, copy-pasteable example for HKMA_BASE from the Interest Rates API.

{
    "success": true,
    "date": "2026-09-30",
    "base": "HKD",
    "rates": {
        "HKMA_BASE": 4.25
    },
    "dates": {
        "HKMA_BASE": "2026-09-30"
    },
    "currencies": {
        "HKMA_BASE": "HKD"
    },
    "base_filter_note": null
}

How to read it:

  • rates.HKMA_BASE is the rate value expressed in percent per annum.
  • dates.HKMA_BASE is the effective date of that rate.
  • base and currencies.HKMA_BASE indicate the currency context (HKD).

Tip: cache this result and respect HTTP caching headers where available. If your app polls intraday, a modest cache TTL (e.g., 15–60 minutes) is usually fine for a monthly series while you wait for the next effective month.

Time series first: multi-year history with /timeseries

The /timeseries endpoint should be your default for historical analysis and backtesting. It returns a contiguous date range bounded by start and end dates and is optimized for bulk ingestion and analytics pipelines.

/timeseries — cURL

/timeseries — Python (requests)

import requests
import pandas as pd

url = "https://interestratesapi.com/api/v1/timeseries"
params = dict(
start="2025-11-02",
end="2026-11-02",
symbols="HKMA_BASE",
api_key="YOUR_API_KEY"
)
resp = requests.get(url, params=params)
resp.raise_for_status()
data = resp.json()

series = data["rates"]["HKMA_BASE"] # dict: date string -> rate (percent)
df = (pd.Series(series, name="hkma_base")
.sort_index()
.to_frame())
df.index.name = "date"

print(df.head())

/timeseries — JavaScript (fetch)

const url = "https://interestratesapi.com/api/v1/timeseries?start=2025-11-02&end=2026-11-02&symbols=HKMA_BASE&api_key=YOUR_API_KEY";
const response = await fetch(url);
const data = await response.json();

const series = data.rates["HKMA_BASE"]; // { "YYYY-MM-DD": value, ... }
const rows = Object.entries(series)
.sort(([d1], [d2]) => d1.localeCompare(d2))
.map(([date, value]) => ({ date, value }));

console.log(rows.slice(0, 5));

/timeseries — PHP

<?php
$ch = curl_init("https://interestratesapi.com/api/v1/timeseries?start=2025-11-02&end=2026-11-02&symbols=HKMA_BASE&api_key=YOUR_API_KEY");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($ch);
if ($out === false) {
throw new Exception("cURL error: " . curl_error($ch));
}
curl_close($ch);
$data = json_decode($out, true);
$series = $data["rates"]["HKMA_BASE"]; // associative array date -> value
print_r(array_slice($series, 0, 5, true));
?

Understanding the returned structure

The response includes top-level metadata (success, start_date, end_date, base) and a rates object keyed by symbol. For each symbol, you receive a date-to-value mapping. For HKMA_BASE (monthly), the service emits the values on the appropriate effective dates within your requested range. When rendering charts, keep in mind that monthly series will not have entries for every calendar day.

Data quality tip: if you rely on continuous daily indices, forward-fill monthly rates within your application for valuation or accrual models, but always keep the canonical effective dates for audit trails.

Learn more about endpoints and behaviors: Explore Interest Rates API features and MCP.

Point-in-time lookup with /historical

Use /historical to fetch the HKMA Base Rate as of a particular calendar date. For monthly symbols, the API resolves to the last day with data within that month. This helps standardize reporting when month-end falls on a non-business day or publication lags occur.

/historical — cURL

/historical — Python

import requests

resp = requests.get(
"https://interestratesapi.com/api/v1/historical",
params=dict(date="2025-06-15", symbols="HKMA_BASE", api_key="YOUR_API_KEY")
)
data = resp.json()
rate = data["rates"]["HKMA_BASE"] # percent per annum
currency = data["currencies"]["HKMA_BASE"]
print("HKMA_BASE as-of 2025-06-15:", rate, currency)

/historical — JavaScript

const res = await fetch("https://interestratesapi.com/api/v1/historical?date=2025-06-15&symbols=HKMA_BASE&api_key=YOUR_API_KEY");
const data = await res.json();
console.log(data.rates["HKMA_BASE"], data.currencies["HKMA_BASE"]);

/historical — PHP

<?php
$q = http_build_query([
"date" => "2025-06-15",
"symbols" => "HKMA_BASE",
"api_key" => "YOUR_API_KEY"
]);
$resp = file_get_contents("https://interestratesapi.com/api/v1/historical?$q");
$data = json_decode($resp, true);
echo "HKMA_BASE: " . $data["rates"]["HKMA_BASE"] . " " . $data["currencies"]["HKMA_BASE"] . PHP_EOL;
?

Edge cases to design for:

  • Weekends/holidays: the returned value will correspond to the month’s effective rate as per the API’s monthly symbol rule.
  • Early-month queries: if a new month’s rate is not yet effective, you will receive the last effective monthly value.
  • 404 when out of range: handle 404 errors (with optional details) if you query a date before the start of coverage.

OHLC for candlesticks and dashboards

To build candlesticks or summary panels, /ohlc computes open, high, low, and close values over monthly, weekly, or quarterly buckets. For HKMA_BASE, monthly buckets are the natural fit. Each bucket also returns data_points, indicating how many underlying data observations were used.

/ohlc — cURL

/ohlc — Python

import requests
import pandas as pd

params = dict(
symbols="HKMA_BASE",
period="monthly",
start="2025-11-02",
end="2026-11-02",
api_key="YOUR_API_KEY"
)
r = requests.get("https://interestratesapi.com/api/v1/ohlc", params=params)
data = r.json()
rows = data["rates"]["HKMA_BASE"] # list of OHLC bars
df = pd.DataFrame(rows) # columns: period, open, high, low, close, data_points
print(df.head())

/ohlc — JavaScript (with Plotly candlestick)

The snippet below transforms /ohlc output into a Plotly candlestick. Because HKMA_BASE is monthly, we use the period field (YYYY-MM) as the X-axis.

const url = "https://interestratesapi.com/api/v1/ohlc?symbols=HKMA_BASE&period=monthly&start=2025-11-02&end=2026-11-02&api_key=YOUR_API_KEY";
const res = await fetch(url);
const data = await res.json();
const bars = data.rates["HKMA_BASE"];

const x = bars.map(b => b.period + "-01"); // anchor to first day for timeline
const open = bars.map(b => b.open);
const high = bars.map(b => b.high);
const low = bars.map(b => b.low);
const close = bars.map(b => b.close);

const trace = {
x, open, high, low, close, type: "candlestick", name: "HKMA_BASE"
};
const layout = { title: "HKMA_BASE Monthly OHLC", xaxis: { type: "date" }, yaxis: { title: "% (annualized)" } };
Plotly.newPlot("chart", [trace], layout);

/ohlc — PHP

<?php
$qs = http_build_query([
"symbols" => "HKMA_BASE",
"period" => "monthly",
"start" => "2025-11-02",
"end" => "2026-11-02",
"api_key" => "YOUR_API_KEY"
]);
$json = file_get_contents("https://interestratesapi.com/api/v1/ohlc?$qs");
$data = json_decode($json, true);
foreach ($data["rates"]["HKMA_BASE"] as $bar) {
echo $bar["period"] . " O:" . $bar["open"] . " H:" . $bar["high"] . " L:" . $bar["low"] . " C:" . $bar["close"] . " (" . $bar["data_points"] . ")\n";
}
?

Data points note: data_points counts underlying observations within each bucket. For a monthly series this may reflect how many effective data entries contributed to that period. Do not assume it equals the number of calendar days.

Change statistics and ranges with /fluctuation

For dashboards and reports, /fluctuation returns start and end values, absolute and percent change, and the high/low across your requested window. Use it to quantify how HKMA_BASE moved over a policy cycle or within fiscal periods.

/fluctuation — cURL

/fluctuation — Python

import requests

params = dict(
start="2025-11-02",
end="2026-11-02",
symbols="HKMA_BASE",
api_key="YOUR_API_KEY"
)
res = requests.get("https://interestratesapi.com/api/v1/fluctuation", params=params)
stats = res.json()["rates"]["HKMA_BASE"]
print(stats) # keys: start_date, end_date, start_value, end_value, change, change_pct, high, low

/fluctuation — JavaScript

const urlFl = "https://interestratesapi.com/api/v1/fluctuation?start=2025-11-02&end=2026-11-02&symbols=HKMA_BASE&api_key=YOUR_API_KEY";
const resFl = await fetch(urlFl);
const flData = await resFl.json();
console.log(flData.rates["HKMA_BASE"]);

/fluctuation — PHP

<?php
$query = http_build_query([
"start" => "2025-11-02",
"end" => "2026-11-02",
"symbols" => "HKMA_BASE",
"api_key" => "YOUR_API_KEY"
]);
$resp = file_get_contents("https://interestratesapi.com/api/v1/fluctuation?$query");
$data = json_decode($resp, true);
print_r($data["rates"]["HKMA_BASE"]);
?

Production pipeline: fetch ➜ pandas DataFrame ➜ CSV/Parquet

The following end-to-end Python example pulls a multi-year HKMA_BASE series, normalizes the index, adds helper columns (year, month), calculates simple transforms (e.g., monthly spread vs. your chosen baseline), and writes both CSV and Parquet. It also includes basic retries and error handling for 429s and input validation errors.

import time
import requests
import pandas as pd
from datetime import datetime

API = "https://interestratesapi.com/api/v1/timeseries"
API_KEY = "YOUR_API_KEY"

def get_timeseries(start, end, symbol="HKMA_BASE", max_retries=3, backoff=2.0):
params = dict(start=start, end=end, symbols=symbol, api_key=API_KEY)
for attempt in range(1, max_retries+1):
r = requests.get(API, params=params)
if r.status_code == 429:
retry_after = float(r.headers.get("Retry-After", "1"))
time.sleep(retry_after if retry_after > 0 else backoff * attempt)
continue
r.raise_for_status()
js = r.json()
if not js.get("success", False):
# Common error shape: {"success": false, "error": "...", ...}
raise RuntimeError(js.get("error", "Unknown API error"))
return js
raise RuntimeError("Exceeded max retries")

def to_dataframe(ts_json):
series = ts_json["rates"]["HKMA_BASE"]
df = (pd.Series(series, name="hkma_base")
.sort_index()
.to_frame())
df.index = pd.to_datetime(df.index, format="%Y-%m-%d", errors="coerce")
df.index.name = "date"
df["year"] = df.index.year
df["month"] = df.index.month
# Example transform: compute a spread against an internal baseline (e.g., 4.00%)
# Keep constants out of code in production by reading config/env.
baseline = 4.00
df["spread_vs_4pct"] = df["hkma_base"] - baseline
return df

if __name__ == "__main__":
js = get_timeseries(start="2015-01-01", end=datetime.today().strftime("%Y-%m-%d"))
df = to_dataframe(js)
df.to_csv("hkma_base_history.csv", float_format="%.4f")
df.to_parquet("hkma_base_history.parquet")
print("Wrote", len(df), "rows to CSV and Parquet")

Notes:

  • Spread calculation: subtract your reference rate or internal cost of funds directly from the returned HKMA_BASE percentage values. All values are in percent per annum; keep units consistent.
  • Missing dates: monthly series won’t fill every day. If you need daily rows, reindex to a daily DateRange and forward-fill for accrual use cases, but store the canonical effective dates for controls and audit.
  • Caching: persist the DataFrame after each successful fetch. On startup, read the last stored date and append only the new months, not the entire history.

Computing spreads and monthly payments safely

Spreads: for HKMA_BASE, a rate spread is value_A - value_B where both are percentages. If you compare HKMA_BASE to your internal lending rate, ensure they share the same compounding convention in your business logic (the API returns percent per annum; compounding is your application’s responsibility).

Monthly payment: convert the percent per annum to a monthly rate by dividing by 12 (simple approximation) or applying your compounding rule. For example, if r is the annual percentage from HKMA_BASE, the approximate monthly rate r_m ≈ r / 12 (expressed in percent). For an amortized loan with principal P and n months at monthly decimal rate i = r_m/100, payment M = P * i * (1+i)^n / ((1+i)^n - 1). Use the rate returned by the API as r, keeping units clear. Do not assume publication-day changes mid-month unless your product explicitly reprices intra-month.

Operational considerations: business days, frequency, and errors

Business days and monthly cadence:

  • HKMA_BASE is monthly. When you query /historical for a date, the API applies “last day with data within that month.” If you need exact policy decision timestamps, store the effective dates from the response.
  • For /timeseries windows, don’t expect daily granularity. Combine with /ohlc for chart summaries if you need quick min/max/close per month.

Error handling and rate limits:

  • 401/403: handle authentication and plan checks generically. All endpoints require GET with api_key as a query parameter.
  • 404: no symbols matched or out-of-range dates—surface the message and optional details to users.
  • 422: validate Y-m-d input locally before calling the API.
  • 429: observe Retry-After and X-RateLimit-* headers to back off automatically.

Monitoring: log success flags, date ranges, and the count of returned entries. For OHLC, store data_points to inform QA if a bucket looks sparse.

Explore the platform and endpoints at Try Interest Rates API and Get started with Interest Rates API.

Full reference examples for HKMA_BASE

Below are the official sample responses for core endpoints relevant to HKMA_BASE analytics. Values shown in these blocks are illustrative samples from the documentation—always rely on live queries for production decisions.

/latest — official cURL and JSON (provided above)

Use the previous “Latest snapshot” section for the official curl and JSON block. Integrate that shape into your DTOs so your code works identically across QA and prod.

/timeseries — example JSON shape

Field guide:

  • rates.HKMA_BASE maps dates to percentage values.
  • start_date and end_date echo your request window.
  • currencies provide currency context per symbol.

/historical — example JSON shape

Use this when you need a single effective value tied to a report date (month-end, quarter-end, or any specific day).

/fluctuation — example JSON shape

This is a fast, single-call way to populate “Change since last year” or “12M high/low” KPI cards.

/ohlc — example JSON shape

Interpretation: open/close are the first/last observed values in the bucket; high/low are extremes; data_points is the count of observations the API used to compute this bar.

Security and deployment checklists

  • Authentication: always send api_key through the query string parameter api_key. Do not place it in headers for this API.
  • GET-only: all endpoints use GET—no POST/PUT/DELETE—simplifying proxy and firewall rules.
  • Time windows: keep your start/end windows aligned with your reporting periods. For month-aligned runs, close start at the first calendar day and end at the last calendar day.
  • Idempotency: recorded results for historical dates are stable—cache and pin them to reduce traffic and ensure reproducibility.

Frequently asked questions

Q1: What units does the API return for HKMA_BASE?
A: Percent per annum. Treat values as numeric percentages (e.g., 4.25 means 4.25%). Convert to decimal as needed in your formulas.

Q2: How are weekends and holidays handled for HKMA_BASE?
A: HKMA_BASE is monthly. For /historical lookups, the API returns the last day with data within that month. For /timeseries, expect entries on the effective dates within the range, not every calendar day.

Q3: How should I handle rate limits?
A: If you receive HTTP 429, check Retry-After and X-RateLimit-* headers and back off before retrying. Also consider caching stable historical responses and using incremental updates.

Q4: Can I compute loan payments directly from HKMA_BASE?
A: Yes. Convert the returned percent per annum to a monthly rate according to your compounding convention, then apply your payment formula. Keep the compounding assumption explicit in code reviews.

Q5: How do I ensure I’m using the right symbol?
A: Call /symbols with category=central_bank and base=HKD to verify HKMA_BASE exists and check its metadata (frequency and currency) before shipping to production.

Build, test, and ship your HKMA Base Rate integration now. Register for an API key, then start experimenting with the endpoints above. You can also Try Interest Rates API, Get started with Interest Rates API, and dive deeper in the MCP.

Ready to get started?

Get your API key and start validating bank data in minutes.

Get API Key