Historical VWAP data very wrong

Bellow is the stock data pulled by using the Alpaca API.

request_params = StockBarsRequest(
                      symbol_or_symbols='DECK',
                      timeframe=TimeFrame.Day,
                      adjustment='all',
                      start= datetime.datetime.now() - datetime.timedelta(days = 1)
                )

Capture

As you can see, vwap is higher than the day’s highest price which doesn’t make sense. I can see a lot of vwap of other tickers also having similar problem. Can anyone help me bugcheck this issue

@Steve_Kim One thing to appreciate about the calculations for the Open, High, Low, Close, Volume, and VWAP bar values is they don’t typically 1) look at all the trades within the bar and 2) the different calculations look at different trades. There is more detail on this in this post .

The simple reason why the VWAP can be higher than the High is that each considers different trades in their calculation. The VWAP calculation considers all trades included in the Volume calculation which is effectively all trades. The High and Low calculations exclude a number of trades (most notably any ‘odd lot’ trades less than 100).

There was another forum post with a similar question here

Does that make sense?

@Dan_Whitnable_Alpaca I read the documents you shared but I have some concerns regarding the VWAP calculation for the ticker DECK as provided by your API. I noticed significant discrepancies when comparing your data with other sources like TradingView, which lists today’s VWAP for DECK at 902.27, aligning with the day’s high and low range. However, I observed the ticker DECK experienced substantial trading activity and an approximate 8% price increase after regular trading hours. the VWAP from Alpaca’s API is saying 910.23 which seems to include post-market trades.

It appears that when using the timeframe=TimeFrame.Day parameter, the open, high, low, and close values correspond to the regular trading hours, but the VWAP calculation seems to include post-market trades. Could you please clarify if this is the case? Understanding this would help in ensuring the accuracy of the data used for trading decisions.

Thank you for your assistance.

@Steve_Kim You asked if “the VWAP calculation seems to include post-market trades”. That is correct. The VWAP calculations include extended hour trades. This is because Alpaca uses all trades included in the volume calculations when calculating VWAP. Daily volume calculations include extended hour trades (you may not have realized that?).

Take a look at the guidance on page 64 of the Consolidated Tape System (CTS) Specification and page 43 of the UTP Specification. The only trades excluded from the volume calculation are those with conditions M, Q, or 9. Extended hour trades (ie having a T condition) are not excluded.

One can calculate the VWAP from trades something like this

trades = client.get_stock_trades(StockTradesRequest(
                    symbol_or_symbols='DECK',
                    start=pd.to_datetime('2024-05-23T00:00:00').tz_localize('America/New_York'),
                    end=pd.to_datetime('2024-05-23T23:00:00').tz_localize('America/New_York'),
                    feed='sip',)
                    ).df.tz_convert('America/New_York', level='timestamp')

# list of conditions which exclude a trade from the volume calc
excluded_conditions = ['M', 'Q', '9']

trades['excluded'] = [any(condition in excluded_conditions for condition in conditions) for conditions in trades.conditions]

included_trades = trades.query('not excluded')

vwap = (included_trades['price'] * included_trades['size']).sum() / included_trades['size'].sum()

Using the above calculation vwap=910.3039512569943.

Below is the daily bar for DECK. Note the volume, trade_count and VWAP are slightly different from the screenshot above. The screenshot above was taken while extended hour trading was still active so therefore didn’t capture the entire day. Notice the VWAP is the same as our calculated number above.

@Dan_Whitnable_Alpaca Thank you for your clear explanations. I learned a lot. I just have one more point I’d like to confirm: When using the timeframe=TimeFrame.Hour (instead of Day), is the VWAP calculated exclusively within that one-hour period? For instance, if we are considering the 1 PM to 2 PM timeframe, does the VWAP only include transactions that occurred within that specific hour, without considering data outside of this range?

Thank you for clarifying this for me.

@Steve_Kim VWAP, like the other bar calculations (eg High, Low, Trade_Count, and volume), only include those trades within the bar timeframe. For example, if one is looking at a 1Hour bar with a label 13:00, the bar will only include trades made between 13:00-14:00 (technically 13:00 <= t < 14:00).

Bar calculations involve 3 steps

  1. filter for trades executed within the bar timeframe
  2. exclude any trades with ‘excluding’ trade conditions which varies by specific calculation (eg High/Low, Close, VWAP etc)
  3. perform specific calculation

The bar calculations do not consider any data outside of the bar timeframe.