API Call Returning Null Value/Blank Array

Hello,

I’m getting started with the Alpaca API and have run into some issues returning historical data from the Market Data API.

Here is my code:

headers = {
“APCA-API-KEY-ID”: “Key ID”,
“APCA-API-SECRET-KEY”: “Secret Key”,
}

 params = {
    "symbols": "TSLA",
    "limit": "20",
    "start": "2020-09-01T0:00:00Z",
    "end": "2020-09-02T0:00:00Z",
    "timeframe": "12M"
    }
teslabars = requests.get("https://data.alpaca.markets/v2/stocks/bars", headers=headers, params=params)

return teslabars.content

This is the response from the API:

{“bars”:{},“next_page_token”:null}

Can someone please help? It would be much appreciated.

Thank you,
Al

@axg5068 What timeframe (ie the length of each bar) are you expecting. Specifying ‘12M’ means you are requesting bars which are 12 months long. Is that what was intended? The allowable values are in the docs and are:

  • [1-59]Min / T
  • [1-23]Hour / H
  • 1Day / D
  • 1Week / W
  • [1,2,3,4,6,12]Month / M

Also note how each bar is labeled. The day, week, and month bars are all labeled with a time of midnight market time (America/New_York). The week bars always begin on Monday and the month bars always begin on the first of the month. For example here are some example bar labels (ie timestamps)

Daily bars

timestamp
2023-08-24 00:00:00-04:00 4.788 4.8500 4.175 4.325 762940 36505 4.409000 IDEX
2023-08-25 00:00:00-04:00 3.800 4.3800 3.250 4.300 2044336 15996 3.852685 IDEX
2023-08-28 00:00:00-04:00 3.960 4.0985 3.350 3.480 1070353 9753 3.582292 IDEX

Weekly bars

timestamp
2023-08-28 00:00:00-04:00 3.96 4.0985 2.95 2.97 4406089 36147 3.232392 IDEX
2023-09-04 00:00:00-04:00 2.97 2.9700 2.04 2.07 2541074 26358 2.476772 IDEX

Monthly bars

timestamp
2023-07-01 00:00:00-04:00 9.775 13.36 9.55 11.61 4731765 345316 11.368918 IDEX
2023-08-01 00:00:00-04:00 11.460 12.25 2.95 3.02 14257496 539822 5.499967 IDEX
2023-09-01 00:00:00-04:00 3.100 3.24 2.04 2.07 3461414 32728 2.634436 IDEX

Another convention to note is when the ‘multiple’ numbering starts. For months this is always January. For example, a 12Month timeframe will always start on January 01.

Why is this important? When fetching bars, both the date and time are considered. For example, fetching 1Month bars after 2023-07-01 09:030:00-04:00 won’t return the 2023-07-01 00:00:00-04:00 bar. Be aware of this when specifying the start and end times.

In this specific case, using the parameters

 params = {
    "symbols": "TSLA",
    "limit": "20",
    "start": "2020-09-01T0:00:00Z",
    "end": "2020-09-02T0:00:00Z",
    "timeframe": "12M"
    }

specifies “fetch up to 20 12month bars with labels/timestamps between 2020-09-01T0:00:00Z thru 2020-09-02T0:00:00Z”. This won’t return any bars. A 12Month bar is always labeled with January 1. The following are valid labels/timestamps for 12Month bars

timestamp
2019-01-01 00:00:00-05:00 153.75 355.00 71.25 106.96 1163889 466216 206.575391 IDEX
2020-01-01 00:00:00-05:00 106.79 593.75 34.50 248.75 36963391 10196817 255.440216 IDEX
2021-01-01 00:00:00-05:00 250.00 691.25 138.75 150.00 41660442 12447064 378.825054 IDEX

Notice there are no bars with timestamps 2020-09-01T0:00:00Z thru 2020-09-02T0:00:00Z". That is why no bars are returned.

Thanks Dan. That’s helpful and that fixed it - I used the “T” instead of “M” for minute timestamp and then I was able to get an API response.

I have a few follow-up questions:

  1. I can’t tell what all the symbols that are part of the bar mean and they aren’t listed in the Alpaca documentation. For instance, I know Open, High, Low, Close. I believe “v” is for volume. What is “vw”? Also, what does “n” stand for?

  2. The other issue I came across is data accuracy. The API states that Tesla’s opening price on 09-01-2020 was $530.04 and the volume was 126,594. However, when I checked the Nasdaq site for historical price data, the actual opening price that day was closer to $167. Can you help me understand why there is such a large discrepancy here?

  3. Is there any way to run an API call that looks at every publicly traded stock (e.g. including NYSE, Nasdaq, and other exchanges).

  4. If #3 is not possible, is it possible to run an API call that returns stocks for a given period that open each day X% above their close price the previous trading day?

Thank you!
Al

@axg5068 I’ll try to answer your questions.

…What is “vw”? Also, what does “n” stand for?

The vw attribute is the ‘volume weighted price’ for that bar. The price and volume for each trade is multiplied then these are summed and finally divided by the total volume. It’s an ‘average price’ for the bar. The n attribute is the number of trades during the bar. There is a bit more description in the docs here.

The API states that Tesla’s opening price on 09-01-2020 was $530.04 and the volume was 126,594 … However, when I checked the Nasdaq for historical price data, the actual opening price that day was closer to $167

I wasn’t able to reproduce the API data you posted. When I fetch the daily open for TSLA on 09-01-2020 I get $502.14 with no adjustment (ie adjustment='raw') and $167.38 adjusted for splits (ie adjustment='split') which matches the NASDAQ open price. Typically any discrepancy is whether the data is adjusted for splits or not.

Is there any way to run an API call that looks at every publicly traded stock (e.g. including NYSE, Nasdaq, and other exchanges).

All market data calls accept multiple symbols, so in theory one can request all tradable symbols in a single call. However, as a practical matter the number is limited to about 3500 symbols/call. The reason is the symbols are a ‘query parameter’ and become part of the URL. With a lot of symbols the URL becomes very long and some/most networks cannot handle such long URLs.

So, fetching all data for all symbols is a 2 step process. 1) fetch a list of all tradable assets. Use the assets endpoint to get that list, and 2) fetch the data for those assets by dividing the list into chunks of 3500 symbols.

…is it possible to run an API call that returns stocks for a given period that open each day X% above their close price the previous trading day?

There is an endpoint for the top and bottom gainers for the day which may be what you are looking for. Check out the movers endpoint.

Hello Dan,

Thanks so much for the response!

The API is working and I’m able to pull data. However, I’m only seeing the first 25 records of the request accompanied by a “next page” token.

I read in a different forum that to get the subsequent pages, I could use a while loop or get the Alpaca.Markets.Extension. Is such an extension available for Python?

What is the easiest/most straightforward way to obtain subsequent pages of data?

Thank you,
Al

@axg5068 The trades, quotes, and bars endpoints can each return up to 10,000 items in a single call. If more than that are requested, a page_token is returned allowing one to make a subsequent call starting where the previous one stopped. So, if you know you won’t be fetching more than 10,000 items (eg bars) the simplest may be to simply specify limit=10000. No paging necessary.

However, a more generalized approach is to use one of the Alpaca SDKs such as alpaca_trade_api or alpaca-py. Both of those packages do the paging for you behind the scenes. Just enter the start and end dates.

Here is an example, using the alpaca_trade_api SDK, for getting a month of minute bars for 10 stocks (over 100,000 bars).

#First install and import the Alpaca python API SDK 'wrapper'
!pip install -q alpaca_trade_api

import alpaca_trade_api as alpacaapi

#set the desired symbols and dates
symbols = ['A', 'CAT', 'IBM', 'SPY', 'F', 'BHP', 'BTU', 'SPY', 'TSLA', 'META']

start_time = pd.to_datetime("2023-03-01 00:00:00").tz_localize('America/New_York')
end_time = pd.to_datetime("2023-04-01 00:00:00").tz_localize('America/New_York')

#fetch the minute bars
#convert to a dataframe indexed by the bar time with market timezone
minute_bars = api_data.get_bars(symbols,
                             '1Min',
                             start=start_time.isoformat(),
                             end=end_time.isoformat(),
                             ).df.tz_convert('America/New_York')

The result is the following dataframe

Thanks again for the response Dan.

I’ve been tinkering with the API this evening but have run into some roadblocks. Specifically, I can’t load in the environmental variable that stores the secret Alpaca keys. It returns “None” when I try to print the keys after loading them from the .env file. More detail below.

I began building my Python project based on the following example on Github:

The only difference is that I used the Python dotenv package (instead of os.environ) to load the APCA_API_KEY_ID and APCA_API_SECRET_KEY.

Here is the code from the top of my base.py file:

from dynaconf import FlaskDynaconf
from flask import render_template
from flask import request
from flask import Flask, redirect, url_for, request, jsonify, make_response
import requests
from alpaca.data.historical import CryptoHistoricalDataClient
from alpaca.data.requests import CryptoBarsRequest
from alpaca.data.timeframe import TimeFrame
import datetime
import pandas as pd
import json
import socket
import os
from dotenv import load_dotenv
import alpaca_trade_api as tradeapi
from alpaca_trade_api.rest import TimeFrame, URL, REST
from alpaca_trade_api.rest_async import gather_with_concurrency, AsyncRest


load_dotenv()

app = Flask(__name__)

Here is the code for starting the program on localhost and pulling in the env variables:

if __name__ == "__main__":
   api_key_id = os.getenv('APCA_API_KEY_ID')
   api_secret = os.getenv('APCA_API_SECRET_KEY')
   base_url = "https://paper-api.alpaca.markets"
   app.run(host="127.0.0.1", port=8080, debug=True)

Screenshot of my directory is attached. Notice that .env file is in the same folder as the base.py file (my main python file).

image