Historical OHLCV from REST: Build Candlestick Charts

This tutorial demonstrates how to fetch historical OHLCV (Open, High, Low, Close, Volume) data from the CoinAPI REST API and create professional candlestick charts. You'll learn how to retrieve historical price data for cryptocurrency pairs and visualize them using matplotlib and mplfinance.

  • How to authenticate with the CoinAPI REST API
  • How to fetch historical OHLCV data with specific parameters
  • How to process and clean the API response data
  • How to create professional candlestick charts
  • How to analyze price trends and patterns
  • Python 3.7+
  • Required packages: requests, pandas, numpy, matplotlib, mplfinance
  • CoinAPI API key (free tier available)
  1. Install required packages: pip install requests pandas numpy matplotlib mplfinance
  2. Get your free API key from CoinAPI
  3. Replace API_KEY placeholder in the code below

Set up your environment with necessary imports and configuration for working with the CoinAPI REST API.

1# Import required libraries
2import requests
3import pandas as pd
4import numpy as np
5import matplotlib.pyplot as plt
6import mplfinance as mpf
7from datetime import datetime, timedelta
8import json
9
10# Set up plotting style
11plt.style.use('default')
12plt.rcParams['figure.figsize'] = (14, 8)
13plt.rcParams['font.size'] = 10
14
15# API configuration
16API_KEY = "YOUR_API_KEY_HERE"  # Replace with your actual API key
17BASE_URL = "https://rest.coinapi.io/v1"
18
19# Editable parameters
20SYMBOL_ID = "BINANCE_SPOT_BTC_USDT"
21PERIOD_ID = "1HRS"
22TIME_START = "2025-07-07T00:00:00"
23TIME_END = "2025-07-14T00:00:00"
24LIMIT = 200
25
26print("Environment setup complete!")
27print(f"Using API base URL: {BASE_URL}")
28print(f"API Key configured: {'Yes' if API_KEY != 'YOUR_API_KEY_HERE' else 'No (Please update)'}")
29print(f"Target symbol: {SYMBOL_ID}")
30print(f"Time period: {TIME_START} to {TIME_END}")
31print(f"Data interval: {PERIOD_ID}")

Now we'll fetch historical OHLCV data from the CoinAPI REST API using the specified parameters. We'll make a request to the /ohlcv/:symbol_id/history endpoint with our query parameters.

1def fetch_ohlcv_data(symbol_id, period_id, time_start, time_end, limit):
2    """
3    Fetch historical OHLCV data from CoinAPI REST API
4    
5    Args:
6        symbol_id (str): Trading pair identifier (e.g., BINANCE_SPOT_BTC_USDT)
7        period_id (str): Time period for each candle (e.g., 1HRS, 1DAY)
8        time_start (str): Start time in ISO format
9        time_end (str): End time in ISO format
10        limit (int): Maximum number of candles to return
11    
12    Returns:
13        dict: API response with OHLCV data
14    """
15    endpoint = f"/ohlcv/{symbol_id}/history"
16    url = BASE_URL + endpoint
17    
18    # Query parameters
19    params = {
20        'period_id': period_id,
21        'time_start': time_start,
22        'time_end': time_end,
23        'limit': limit
24    }
25    
26    # Headers with API key
27    headers = {
28        'X-CoinAPI-Key': API_KEY
29    }
30    
31    try:
32        response = requests.get(url, params=params, headers=headers)
33        response.raise_for_status()
34        return response.json()
35    except requests.exceptions.RequestException as e:
36        print(f"Error fetching data: {e}")
37        return None
38
39# Fetch the data
40print("Fetching historical OHLCV data...")
41ohlcv_data = fetch_ohlcv_data(SYMBOL_ID, PERIOD_ID, TIME_START, TIME_END, LIMIT)
42
43if ohlcv_data:
44    print(f"Successfully fetched {len(ohlcv_data)} OHLCV records")
45    print("Sample data structure:")
46    if ohlcv_data:
47        print(f"First record: {ohlcv_data[0]}")
48else:
49    print("Failed to fetch data. Please check your API key and parameters.")

Now we'll process the raw API response data into a pandas DataFrame and perform some basic analysis. We'll convert timestamps, calculate additional metrics, and prepare the data for visualization.

1def process_ohlcv_data(raw_data):
2    """
3    Process raw OHLCV data into a pandas DataFrame
4    
5    Args:
6        raw_data (list): Raw API response data
7    
8    Returns:
9        pd.DataFrame: Processed OHLCV data
10    """
11    if not raw_data:
12        return None
13    
14    # Convert to DataFrame
15    df = pd.DataFrame(raw_data)
16    
17    # Convert timestamp to datetime
18    df['time_period_start'] = pd.to_datetime(df['time_period_start'])
19    df['time_period_end'] = pd.to_datetime(df['time_period_end'])
20    
21    # Set time_period_start as index
22    df.set_index('time_period_start', inplace=True)
23    
24    # Sort by time
25    df.sort_index(inplace=True)
26    
27    # Calculate additional metrics
28    df['price_change'] = df['price_close'] - df['price_open']
29    df['price_change_pct'] = (df['price_change'] / df['price_open']) * 100
30    df['body_size'] = abs(df['price_close'] - df['price_open'])
31    df['upper_shadow'] = df['price_high'] - df[['price_open', 'price_close']].max(axis=1)
32    df['lower_shadow'] = df[['price_open', 'price_close']].min(axis=1) - df['price_low']
33    
34    return df
35
36# Process the data
37if ohlcv_data:
38    df = process_ohlcv_data(ohlcv_data)
39    
40    if df is not None:
41        print("Data processing complete!")
42        print(f"DataFrame shape: {df.shape}")
43        print("\nFirst few rows:")
44        print(df.head())
45        
46        print("\nData summary:")
47        print(df.describe())
48        
49        print("\nPrice statistics:")
50        print(f"Price range: ${df['price_low'].min():.2f} - ${df['price_high'].max():.2f}")
51        print(f"Average volume: {df['volume_traded'].mean():.2f}")
52        print(f"Total price change: {df['price_change'].sum():.2f} USDT")
53        print(f"Average price change: {df['price_change_pct'].mean():.2f}%")
54    else:
55        print("Failed to process data.")
56else:
57    print("No data to process.")

Now we'll create professional candlestick charts using mplfinance, which is specifically designed for financial data visualization. We'll create multiple chart types to analyze different aspects of the price data.

1def create_candlestick_chart(df, title="BTC/USDT Candlestick Chart"):
2    """
3    Create a professional candlestick chart using mplfinance
4    
5    Args:
6        df (pd.DataFrame): OHLCV data with datetime index
7        title (str): Chart title
8    """
9    # Create a clean DataFrame with only the required OHLCV columns
10    # The actual column names from the API are: price_open, price_high, price_low, price_close, volume_traded
11    ohlcv_df = df[['price_open', 'price_high', 'price_low', 'price_close', 'volume_traded']].copy()
12    
13    # Rename columns to the standard OHLCV format expected by mplfinance
14    ohlcv_df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
15    
16    print("OHLCV DataFrame shape:", ohlcv_df.shape)
17    print("OHLCV DataFrame columns:", ohlcv_df.columns.tolist())
18    print("\nFirst few rows of OHLCV data:")
19    print(ohlcv_df.head())
20    
21    # Create the candlestick chart
22    mpf.plot(ohlcv_df, 
23             type='candle', 
24             title=title,
25             ylabel='Price (USDT)',
26             volume=True,
27             style='charles',
28             figsize=(14, 8),
29             panel_ratios=(3, 1),
30             savefig='candlestick_chart.png')
31    
32    print("Candlestick chart created and saved as 'candlestick_chart.png'")
33
34def create_price_analysis_charts(df):
35    """
36    Create additional analysis charts
37    """
38    fig, axes = plt.subplots(2, 2, figsize=(16, 12))
39    fig.suptitle('BTC/USDT Price Analysis', fontsize=16, fontweight='bold')
40    
41    # Price trend over time
42    axes[0, 0].plot(df.index, df['price_close'], linewidth=2, color='blue')
43    axes[0, 0].set_title('Price Trend Over Time')
44    axes[0, 0].set_ylabel('Price (USDT)')
45    axes[0, 0].grid(True, alpha=0.3)
46    
47    # Volume analysis
48    axes[0, 1].bar(df.index, df['volume_traded'], alpha=0.7, color='green')
49    axes[0, 1].set_title('Trading Volume')
50    axes[0, 1].set_ylabel('Volume')
51    axes[0, 1].grid(True, alpha=0.3)
52    
53    # Price change distribution
54    axes[1, 0].hist(df['price_change_pct'], bins=20, alpha=0.7, color='orange', edgecolor='black')
55    axes[1, 0].set_title('Price Change Distribution')
56    axes[1, 0].set_xlabel('Price Change (%)')
57    axes[1, 0].set_ylabel('Frequency')
58    axes[1, 0].grid(True, alpha=0.3)
59    
60    # Body size vs volume scatter
61    axes[1, 1].scatter(df['body_size'], df['volume_traded'], alpha=0.6, color='purple')
62    axes[1, 1].set_title('Body Size vs Volume')
63    axes[1, 1].set_xlabel('Candle Body Size (USDT)')
64    axes[1, 1].set_ylabel('Volume')
65    axes[1, 1].grid(True, alpha=0.3)
66    
67    plt.tight_layout()
68    plt.savefig('price_analysis_charts.png', dpi=300, bbox_inches='tight')
69    plt.show()
70    
71    print("Price analysis charts created and saved as 'price_analysis_charts.png'")
72
73# Create the charts
74if 'df' in locals() and df is not None:
75    print("Creating candlestick chart...")
76    create_candlestick_chart(df)
77    
78    print("\nCreating price analysis charts...")
79    create_price_analysis_charts(df)
80    
81    print("\nAll visualizations complete!")
82else:
83    print("No data available for visualization. Please run the data processing cell first.")

Creating candlestick chart...
OHLCV DataFrame shape: (168, 5)
OHLCV DataFrame columns: ['Open', 'High', 'Low', 'Close', 'Volume']

First few rows of OHLCV data:
Open High Low Close \
time_period_start
2025-07-07 00:00:00+00:00 109203.85 109288.02 108800.01 108823.07
2025-07-07 01:00:00+00:00 108823.07 109089.00 108679.75 109019.12
2025-07-07 02:00:00+00:00 109019.12 109499.99 109019.12 109364.52
2025-07-07 03:00:00+00:00 109364.53 109700.00 109364.52 109389.47
2025-07-07 04:00:00+00:00 109389.46 109447.54 109128.72 109128.73

Volume
time_period_start
2025-07-07 00:00:00+00:00 253.53776
2025-07-07 01:00:00+00:00 299.50777
2025-07-07 02:00:00+00:00 433.77607
2025-07-07 03:00:00+00:00 326.47933
2025-07-07 04:00:00+00:00 184.06878
Candlestick chart created and saved as 'candlestick_chart.png'

Creating price analysis charts...

Congratulations! You've successfully fetched historical OHLCV data from the CoinAPI REST API and built professional candlestick charts.

  • Successfully connected to the CoinAPI REST API using proper authentication
  • Fetched historical OHLCV data for BTC/USDT with specific parameters
  • Processed and analyzed the raw API response data
  • Created professional candlestick charts using mplfinance
  • Generated additional analysis charts for deeper insights
  • Saved all visualizations as high-quality image files
  • The CoinAPI REST API provides clean, structured OHLCV data
  • Proper data processing is essential for financial analysis
  • Volume analysis provides valuable insights into market activity
  • Historical data analysis helps identify patterns and trends

Happy analyzing!