Alpaca has different daily open price compared to other providers

Hi, I noticed that Alpaca has different logic for determining the open price of a day compared to every other provider that I checked. For example, let’s consider AAPL on Sep 8, 2022.

Alpaca’s APIs report the open price to be 154.49. All the financial websites that I checked (e.g. Nasdaq) report the open price to be 154.64. Why is Alpaca different?

I did some digging into the raw trade events. Here are the interesting ones:

{
   "t": "2022-09-08T13:30:00.19411456Z",
   "x": "P",
   "p": 154.64,
   "s": 75,
   "c": [
       "@",
       "Q"
   ],
   "i": 6994,
   "z": "C"
},
{
   "t": "2022-09-08T13:30:01.381157959Z",
   "x": "Q",
   "p": 154.49,
   "s": 550148,
   "c": [
       "@",
       "O",
       "X"
   ],
   "i": 4436,
   "z": "C"
},
{
   "t": "2022-09-08T13:30:01.382083822Z",
   "x": "Q",
   "p": 154.49,
   "s": 550148,
   "c": [
       "@",
       "Q"
   ],
   "i": 4438,
   "z": "C"
}

According to the UTP specification, condition Q means “Market Center Official Open” and condition O means “Opening Prints” (AKA opening trade, if I understood correctly). So, the above events show that

  1. A market open event came in with price 154.64.
  2. The opening trade event came in with price 154.49.
  3. Another market open event came in with price 154.49.

Why are there two market open events and why does Alpaca use the second one while other providers use the first one?

2 Likes

My backtesting software (backtrader) uses open prices for filling orders. If this is different and/or errant, I would love to know.

We see frequent inconsistencies in open / close / high / low historical data. For example, an Open which is higher than the High. We switched all inputs to Polygon.

Example for AAAA:
Close=25.04
Date=4/1/2021
High=25.04
Low=25.04
Open=25.05 ← higher than High!
Volume=105

1 Like

Hey :wave: @08.fortes.waxen

Your question is excellent and I love that you almost answered it yourself.

Why are there two market open events and why does Alpaca use the second one while other providers use the first one?

I don’t know why the other providers use the first one, but here’s why Alpaca uses the second one. As you figured out the daily bar’s opening price is populated by the trade price with the opening print condition. As you also figured out, there are 2 of these: O and Q. The difference between the two is that O is reported by the primary market center of the particular symbol, while Q can be reported by any exchange. This means of course that there can be multiple of them, while there should only ever be one O. Alpaca decided to use O, while it seems like other providers tend to just “pick the first one”.

@dominicp Yes, it can happen that Open is higher than High. It’s because there are certain trade conditions that update the opening price of the bar, but doesn’t update the high value. If you give me the exact symbol and timestamp of your example bar I can give a more exact explanation.

1 Like

Thanks for the reply, @Gergely_Alpaca! Good to know that there can be multiple market open events and that Alpaca uses the opening trade event itself.

I’m curious where the price of the first market open event came from though. How can there be a market open event without an opening trade event?

Hi @Gergely_Alpaca,

Polygon data does not exhibit the same behavior. I have tested this across their entire universe of symbols. We always have this consistency:
Errors.Assert(this.Open > 0);
Errors.Assert(this.Close > 0);
Errors.Assert(this.High > 0);
Errors.Assert(this.Low > 0);
Errors.Assert(this.Open <= this.High);
Errors.Assert(this.Open >= this.Low);
Errors.Assert(this.Close <= this.High);
Errors.Assert(this.Close >= this.Low);

I have previously provided the sample symbol and timestamp you requested:
Example for AAAA:
Close=25.04
Date=4/1/2021
High=25.04
Low=25.04
Open=25.05 ← higher than High!
Volume=105

Using HistoricalBarsRequest with ListHistoricalBarsAsync() and BarTimeFrame.Day will yield this. This is using C# but I am sure can be translated into another programming language.
DateTime date = new DateTime(2021, 4, 1);
HistoricalBarsRequest historicalBarsRequest = new HistoricalBarsRequest(“AAAA”, date.AddDays(-1), date.AddDays(1), BarTimeFrame.Day);
IPage page = this.dataClient.ListHistoricalBarsAsync(historicalBarsRequest).Result;
foreach (IBar bar in page.Items)
{
// run validation above
}

Appreciate any explanation.