How to Get Historical Crypto Prices from Surge API for Backtesting

Backtesting trading strategies is a fundamental step for any quantitative analyst or algorithmic trader. To do it effectively, you need reliable, consistent historical price data. While many sources exist, acquiring clean, aggregated crypto data across various assets and timeframes can be challenging. This article will guide you through using the Surge API to access historical cryptocurrency prices, specifically tailored for backtesting purposes.

We'll cover the essentials: understanding the data, making API requests, interpreting the responses, and navigating common pitfalls. Our goal is to equip you with the practical knowledge to integrate Surge's data into your backtesting infrastructure.

Understanding Surge's Historical Data Offering

Surge provides aggregated historical OHLCV (Open, High, Low, Close, Volume) data for a wide range of cryptocurrencies against major fiat currencies (like USD) and other cryptocurrencies. This data is standardized and cleaned, sourced from multiple exchanges to give you a robust, representative market price.

Key characteristics of Surge's historical data:

  • Granularity: Primarily daily OHLCV, suitable for most medium to long-term backtesting strategies. Depending on your subscription tier, finer granularities (e.g., hourly) may be available for specific symbols.
  • Symbol Naming: Assets are identified using a standardized BASE-QUOTE format, for example, BTC-USD, ETH-USD, SOL-USDT. Always use this format to ensure you're querying the correct asset pair.
  • Timezone: All timestamps for historical data are in UTC, which simplifies cross-exchange and international data synchronization.
  • Depth: Historical data availability varies by asset, with major pairs like BTC-USD having extensive history, often going back several years.

Accessing this data requires an API key, which you can generate from your Surge dashboard after signing up. The free tier offers generous rate limits and data access, making it excellent for initial exploration and smaller-scale backtesting.

API Basics: Authentication and Endpoints

To interact with the Surge API, you'll need an API key. This key should be passed as an X-Api-Key HTTP header with every request.

The primary endpoint for historical crypto OHLCV data is: https://surge.91-99-176-101.nip.io/api/v1/crypto/ohlcv

This endpoint accepts several query parameters to specify the data you need:

  • symbol (required): The trading pair, e.g., BTC-USD.
  • start_date (required): The start date for the data, in YYYY-MM-DD format.
  • end_date (required): The end date for the data, in YYYY-MM-DD format.
  • interval (optional, default: 1d): The aggregation interval. For daily data, use 1d. Other intervals like 1h (hourly) might be available based on your subscription.

Responses are typically paginated for larger requests. However, for daily OHLCV over reasonable date ranges, you'll often receive all data in a single response. Always check the response structure for next_page_token or similar pagination indicators if you're fetching very large datasets.

Example 1: Fetching Daily OHLCV for Bitcoin with curl

Let's say you want to retrieve daily OHLCV data for Bitcoin against the US Dollar (BTC-USD) for the month of January 2023. You can achieve this using curl directly from your terminal.

First, ensure you have your Surge API key. Replace YOUR_SURGE_API_KEY with your actual key.

curl -X GET \
  'https://surge.91-99-176-101.nip.io/api/v1/crypto/ohlcv?symbol=BTC-USD&start_date=2023-01-01&end_date=2023-01-31&interval=1d' \
  -H 'X-Api-Key: YOUR_SURGE_API_KEY' \
  -H 'Content-Type: application/json'

The response will be a JSON object containing a list of OHLCV data points. Each data point typically includes:

{
  "data": [
    {
      "symbol": "BTC-USD",
      "timestamp": "2023-01-01T00:00:00Z",
      "open": 16547.01,
      "high": 16578.49,
      "low": 16520.12,
      "close": 16540.33,
      "volume": 1234567.89
    },
    {
      "symbol": "BTC-USD",
      "timestamp": "2023-01-02T00:00:00Z",
      "open": 16540.33,
      "high": 16789.00,
      "low": 16500.00,
      "close": 16670.50,
      "volume": 1500000.00
    }
    // ... more data points
  ],
  "meta": {
    "symbol": "BTC-USD",
    "start_date": "2023-01-01",
    "end_date": "2023-01-31",
    "interval": "1d",
    "count": 31
  }
}

Notice the timestamp field. For daily data, it represents the start of the UTC day (00:00:00Z). This consistent timestamping is crucial for aligning data points across different assets and timeframes during backtesting.

Example 2: Programmatic Access with Python

For more complex backtesting scenarios, you'll likely want to fetch data programmatically, perhaps for multiple assets, longer periods, or to integrate directly into a data processing pipeline. Python is a common choice for this.

Here's a Python script using the requests library to fetch daily OHLCV data for ETH-USD and ADA-USD for a specific period and then store it in a Pandas DataFrame.

```python import requests import pandas as pd from datetime import datetime, timedelta

--- Configuration ---

API_KEY = "YOUR_SURGE_API_KEY" # Replace with your actual Surge API key BASE_URL = "https://surge.91-99-176-101.nip.io/api/v1/crypto/ohlcv" SYMBOLS = ["ETH-USD", "ADA-USD"] START_DATE = "2023-06-01" END_DATE = "2023-06-30" INTERVAL = "1d"

def fetch_ohlcv_data(symbol, start_date, end_date, interval="1d"): """Fetches historical OHLCV data for a given symbol and date range.""" headers = { "X-Api-Key": API_KEY, "Content-Type": "application/json" } params = { "symbol": symbol, "start_date": start_date, "end_date": end_date, "interval": interval }

print(f"Fetching data for {symbol} from {start_date} to {end_date}...")
response = requests.get(BASE_URL, headers=headers, params=params)

if response.status_code == 200:
    data = response.json().get("data", [])
    print(f"Successfully fetched {len(data)} data points for {symbol}.")
    return data
else:
    print(f"Error fetching data for {symbol}: {response.status_code} - {response.text}")
    return []

def process_data_to_dataframe(all_data): """Converts fetched data into a Pandas DataFrame.""" if not all_data: return pd.DataFrame()

df = pd.DataFrame(all_data)
df["timestamp"] = pd.to_datetime(df["timestamp"])
df = df.set_index("timestamp")
return df

if name == "main": all_crypto_data = [] for symbol in SYMBOLS: symbol_data = fetch_ohl