Historical data for Thalex is available through our REST API. Documentation can be found here. Below you will find some simple Python sample script that show how to use this API to get historical data.
Available Data
The Index Price Historical Data endpoint contains the index price data (open, high, low, close) within a specified resolution.
The Mark Price Historical Data endpoint contains market data for each tradable instrument within a specified resolution. The following data is provided:
- Instrument Type (perpetual, future, combination, options)
- Mark Price (open, high, low, close)
- Implied Volatility for Options (open, high, low, close)
- Accumulated funding for Perpetuals in each interval. This is the PNL for a long position of 1 Perpetual since the last interval. Summing up the accumulated funding for each interval in a trading day will result in that day’s funding payout (for a long position of 1 Perpetual). Note that the sign here is the opposite of the funding rate sign, as a positive funding rate means long pays short, resulting in a negative PNL for those with a long position.
- Top of Book price and size at the start of each interval (top bid price, top bid size, top ask price, top ask size)
Code Snippets (Python)
- Print Index Prices
- Print Instrument Prices
- Print Funding Payment
- Print Option IVs
- Print Top of Book
- Error Handling & Pagination
Print Index Prices
The following code snippet prints the price of the specified index, in this case, BTCUSD.
import requests
from datetime import datetime, UTC
INDEX_NAME = "BTCUSD"
FROM_TIMESTAMP = int(datetime(2025, 6, 10, 8, 0, tzinfo=UTC).timestamp())
TO_TIMESTAMP = int(datetime(2025, 6, 24, 8, 0, tzinfo=UTC).timestamp())
RESOLUTION = "1m"
if __name__ == "__main__":
result = requests.get(
"https://thalex.com/api/v2/public/index_price_historical_data",
params={
"index_name": INDEX_NAME,
"from": FROM_TIMESTAMP,
"to": TO_TIMESTAMP,
"resolution": RESOLUTION,
},
).json()
for row in result["result"]["index"][-5:]:
dt = datetime.fromtimestamp(row[0], UTC)
open = row[1]
high = row[2]
low = row[3]
close = row[4]
print(f"{dt} O:{open:.2f}, H:{high:.2f}, L:{low:.2f}, C:{close:.2f}")
Print Instrument Prices
The following code snippet prints the mark price of the specified instrument, in this case, BTC perpetual.
import requests
from datetime import datetime, UTC
INSTRUMENT_NAME = "BTC-PERPETUAL"
FROM_TIMESTAMP = int(datetime(2025, 6, 10, 8, 0, tzinfo=UTC).timestamp())
TO_TIMESTAMP = int(datetime(2025, 6, 24, 8, 0, tzinfo=UTC).timestamp())
RESOLUTION = "1m"
if __name__ == "__main__":
result = requests.get(
"https://thalex.com/api/v2/public/mark_price_historical_data",
params={
"instrument_name": INSTRUMENT_NAME,
"from": FROM_TIMESTAMP,
"to": TO_TIMESTAMP,
"resolution": RESOLUTION,
},
).json()
for row in result["result"]["mark"][-5:]:
dt = datetime.fromtimestamp(row[0], UTC)
open = row[1]
high = row[2]
low = row[3]
close = row[4]
print(f"{dt} O:{open:.2f}, H:{high:.2f}, L:{low:.2f}, C:{close:.2f}")
Print Funding Payment
The following code snippet prints the funding payment of the specified instrument, in this case, BTC perpetual.
import requests
from datetime import datetime, UTC
INSTRUMENT_NAME = "BTC-PERPETUAL"
FROM_TIMESTAMP = int(datetime(2025, 6, 10, 8, 0, tzinfo=UTC).timestamp())
TO_TIMESTAMP = int(datetime(2025, 6, 24, 8, 0, tzinfo=UTC).timestamp())
RESOLUTION = "1m"
if __name__ == "__main__":
result = requests.get(
"https://thalex.com/api/v2/public/mark_price_historical_data",
params={
"instrument_name": INSTRUMENT_NAME,
"from": FROM_TIMESTAMP,
"to": TO_TIMESTAMP,
"resolution": RESOLUTION,
},
).json()
for row in result["result"]["mark"][-5:]:
dt = datetime.fromtimestamp(row[0], UTC)
funding_paid = row[5]
print(f"{dt} Funding Paid: {funding_paid:.2f}")
Print Option IVs
The following code snippet prints the option IVs of the specific option, in this case, BTC-27JUN25-105000-C. For efficiency, we recommend you use a list of instruments and loop through them to print the prices for each instrument.
import requests
from datetime import datetime, UTC
INSTRUMENT_NAME = "BTC-27JUN25-105000-C"
FROM_TIMESTAMP = int(datetime(2025, 6, 10, 8, 0, tzinfo=UTC).timestamp())
TO_TIMESTAMP = int(datetime(2025, 6, 24, 8, 0, tzinfo=UTC).timestamp())
RESOLUTION = "1m"
if __name__ == "__main__":
result = requests.get(
"https://thalex.com/api/v2/public/mark_price_historical_data",
params={
"instrument_name": INSTRUMENT_NAME,
"from": FROM_TIMESTAMP,
"to": TO_TIMESTAMP,
"resolution": RESOLUTION,
},
).json()
for row in result["result"]["mark"][-5:]:
dt = datetime.fromtimestamp(row[0], UTC)
iv_open = row[5]
iv_high = row[6]
iv_low = row[7]
iv_close = row[8]
print(f"{dt} IV_O:{iv_open:.2f}, IV_H:{iv_high:.2f}, IV_L:{iv_low:.2f}, IV_C:{iv_close:.2f}")
Print Top of Book
The following code snippet prints the top of book data for the specified instrument, in this case, BTC perpetual.
import requests
from datetime import datetime, UTC
INSTRUMENT_NAME = "BTC-PERPETUAL"
FROM_TIMESTAMP = int(datetime(2025, 6, 10, 8, 0, tzinfo=UTC).timestamp())
TO_TIMESTAMP = int(datetime(2025, 6, 24, 8, 0, tzinfo=UTC).timestamp())
RESOLUTION = "1m"
if __name__ == "__main__":
result = requests.get(
"https://thalex.com/api/v2/public/mark_price_historical_data",
params={
"instrument_name": INSTRUMENT_NAME,
"from": FROM_TIMESTAMP,
"to": TO_TIMESTAMP,
"resolution": RESOLUTION,
},
).json()
for row in result["result"]["mark"][-5:]:
dt = datetime.fromtimestamp(row[0], UTC)
top_bid_price = row[-1][0]
top_bid_size = row[-1][1]
top_ask_price = row[-1][2]
top_ask_size = row[-1][3]
print(
f"{dt} Top Bid: {top_bid_price}@{round(top_bid_size[0], 2) if top_bid_size and top_bid_size[0] is not None else 'N/A'}, Top Ask: {top_ask_price}@{round(top_ask_size[0], 2) if top_ask_size and top_ask_size[0] is not None else 'N/A'}"
)
Error Handling & Pagination
If you are fetching a large amount of data, you may need to paginate through the results. The following code snippet fetches the data in reverse chronological order until it reaches the from
timestamp.
import requests
import time
from datetime import datetime, UTC
INDEX_NAME = "BTCUSD"
FROM_TIMESTAMP = int(datetime(2025, 6, 14, 8, 0, tzinfo=UTC).timestamp())
TO_TIMESTAMP = int(datetime(2025, 7, 14, 8, 0, tzinfo=UTC).timestamp())
RESOLUTION = "1m"
def fetch_historical_data(from_time, to_time, resolution):
data = []
params = {
"index_name": INDEX_NAME,
"from": from_time,
"to": to_time,
"resolution": resolution,
}
while True:
response_json = requests.get(
"https://thalex.com/api/v2/public/index_price_historical_data",
params=params,
).json()
if "error" in response_json:
print(f"API Error: {response_json['error']}")
break
if response_json["result"].get("no_data", False):
print("No data available in or before the specified range.")
break
response = response_json["result"]["index"]
data = response + data
if response[0][0] <= params["from"]:
break
params["to"] = response[0][0] - 1
# Sleep for a moment to avoid getting throttled
time.sleep(0.1)
return data
if __name__ == "__main__":
result = fetch_historical_data(FROM_TIMESTAMP, TO_TIMESTAMP, RESOLUTION)
for row in result[-5:]:
dt = datetime.fromtimestamp(row[0], UTC)
open = row[1]
high = row[2]
low = row[3]
close = row[4]
print(f"{dt} O:{open:.2f}, H:{high:.2f}, L:{low:.2f}, C:{close:.2f}")