Source: https://databento.com/docs/examples/basics-historical/midprice


# Best bid, best offer, and midprice

In this example we will use the [Historical client](https://databento.com/docs/api-historical/client.md) to retrieve the best bid and offer (BBO) and use these data to calculate the midprice.
To do this we will request a subset of the entire order book data and then average the bid and ask prices to calculate the midprice.

Note that _ask_ and _offer_ are synonyms referring to the sell price.

## TBBO Schema

We'll use the [TBBO schema](https://databento.com/docs/schemas/tbbo.md) to demonstrate this.
This schema contains every trade execution event together with the best bid and offer immediately before the trade.

## Example

```cpp
#include <databento/constants.hpp>  // kUndefPrice
#include <databento/historical.hpp>
#include <databento/pretty.hpp>  // Px
#include <iomanip>
#include <iostream>

namespace db = databento;

int main() {
  auto client = db::Historical::Builder().SetKey("$YOUR_API_KEY").Build();
  auto store = client.TimeseriesGetRange(
      "GLBX.MDP3", {"2022-10-28T20:30:00", "2022-10-28T21:00:00"}, {"ESH3"},
      db::Schema::Tbbo);

  std::cout << std::setprecision(3);
  while (const auto* record = store.NextRecord()) {
    auto bbo = record->Get<db::TbboMsg>();
    auto ask_px = bbo.levels[0].ask_px;
    auto bid_px = bbo.levels[0].bid_px;
    // Skip records where either side of the book is empty
    if (ask_px == db::kUndefPrice || bid_px == db::kUndefPrice) {
      continue;
    }
    auto mid_px = (ask_px + bid_px) / 2;
    std::cout << bbo.hd.instrument_id << '\t' << db::pretty::Px{ask_px} << '\t'
              << db::pretty::Px{mid_px} << '\t' << db::pretty::Px{bid_px}
              << '\n';
  }
  return 0;
}
```
## Result

```plaintext
206299	3955.250	3955.000	3954.750
206299	3955.750	3955.375	3955.000
206299	3955.750	3955.375	3955.000
206299	3955.500	3955.125	3954.750
206299	3956.250	3956.125	3956.000
206299	3955.000	3954.750	3954.500
206299	3956.250	3955.500	3954.750
206299	3956.000	3954.875	3953.750
206299	3956.000	3955.250	3954.500
```


# Best bid, best offer, and midprice

## Overview

In this example we will use the [Historical client](https://databento.com/docs/api-historical/client.md) to retrieve the best bid and offer (BBO) and use these data to calculate the midprice. To do this we will request a subset of the entire order book data and then average the bid and ask prices to calculate the midprice.

Note that _ask_ and _offer_ are synonyms referring to the sell price.

## TBBO schema

We'll use the [TBBO schema](https://databento.com/docs/schemas/tbbo.md) to
demonstrate this. This schema contains every trade execution event together with the
best bid and offer immediately before the trade.

## Example

```python
import databento as db

# Create a historical client
client = db.Historical("$YOUR_API_KEY")

# Request TBBO data
data = client.timeseries.get_range(
    dataset="GLBX.MDP3",
    start="2022-10-28T20:30:00",
    end="2022-10-28T21:00:00",
    symbols="ESH3",
    stype_in="raw_symbol",
    schema="tbbo",
)

# Convert to DataFrame
tbbo_data = data.to_df()

# Calculate the midprice for each row
tbbo_data["mid_px"] = tbbo_data[["ask_px_00", "bid_px_00"]].mean(axis=1)

# We now have a DataFrame that contains execution price, BBO, and midprice
print(tbbo_data[["symbol", "side", "price", "ask_px_00", "mid_px", "bid_px_00"]])
```
## Result

```plaintext
                                    symbol side    price  ask_px_00    mid_px  bid_px_00
ts_recv
2022-10-28 20:30:59.047138053+00:00   ESH3    B  3955.25    3955.25  3955.000    3954.75
2022-10-28 20:37:53.112494436+00:00   ESH3    A  3955.00    3955.75  3955.375    3955.00
2022-10-28 20:39:05.152071481+00:00   ESH3    A  3955.00    3955.75  3955.375    3955.00
2022-10-28 20:51:37.650473254+00:00   ESH3    B  3955.50    3955.50  3955.125    3954.75
2022-10-28 20:52:36.842346377+00:00   ESH3    A  3956.00    3956.25  3956.125    3956.00
2022-10-28 20:52:57.780797186+00:00   ESH3    B  3955.00    3955.00  3954.750    3954.50
2022-10-28 20:57:28.474236098+00:00   ESH3    A  3954.75    3956.25  3955.500    3954.75
2022-10-28 20:59:15.075191111+00:00   ESH3    A  3953.75    3956.00  3954.875    3953.75
2022-10-28 20:59:34.607239899+00:00   ESH3    A  3954.50    3956.00  3955.250    3954.50
```


# Best bid, best offer, and midprice
In this example we will use the [Historical client](https://databento.com/docs/api-historical/client.md) to retrieve the best bid and offer (BBO) and use these data to calculate the midprice.
To do this we will request a subset of the entire order book data and then average the bid and ask prices to calculate the midprice.

Note that _ask_ and _offer_ are synonyms referring to the sell price.

## TBBO Schema
We'll use the [TBBO schema](https://databento.com/docs/schemas/tbbo.md?) to demonstrate this.
This schema contains every trade execution event together with the best bid and offer immediately before the trade.

## Example
```rust
use databento::{
    HistoricalClient,
    dbn::{
        Dataset::GlbxMdp3,
        Schema, TbboMsg, UNDEF_PRICE,
        decode::DbnMetadata,
        pretty::{Px, Ts},
    },
    historical::timeseries::GetRangeParams,
};
use time::macros::datetime;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let mut client = HistoricalClient::builder().key_from_env()?.build()?;
    // First, we request the TBBO data
    let mut decoder = client
        .timeseries()
        .get_range(
            &GetRangeParams::builder()
                .dataset(GlbxMdp3)
                .date_time_range(datetime!(2022-10-28 20:30 UTC)..datetime!(2022-10-28 21:00 UTC))
                .symbols("ESH3")
                .schema(Schema::Tbbo)
                .build(),
        )
        .await?;
    // Next, we extract the symbol mappings for date we queried
    let symbol_mappings = decoder
        .metadata()
        .symbol_map_for_date(decoder.metadata().start().date())?;
    println!(
        "{:<32}{:<8}{:<4}{:>9}{:>9}{:>9}{:>9}",
        "ts_recv", "symbol", "side", "price", "ask", "mid", "bid"
    );
    // Finally, we calculate the midprice for each record
    while let Some(tbbo) = decoder.decode_record::<TbboMsg>().await? {
        let (bid_px, ask_px) = (tbbo.levels[0].bid_px, tbbo.levels[0].ask_px);
        let mid_px = if bid_px == UNDEF_PRICE || ask_px == UNDEF_PRICE {
            UNDEF_PRICE
        } else {
            bid_px + (ask_px - bid_px) / 2
        };
        println!(
            "{:<32}{:<8}{:?} {:>9.2}{:>9.2}{:>9.2}{:>9.2}",
            Ts(tbbo.ts_recv),
            symbol_mappings[tbbo],
            tbbo.side()?,
            Px(tbbo.price),
            Px(tbbo.levels[0].ask_px),
            Px(mid_px),
            Px(tbbo.levels[0].bid_px),
        );
    }
    Ok(())
}
```
## Result
```plaintext
ts_recv                         symbol  side    price      ask      mid      bid
2022-10-28T20:30:59.047138053Z  ESH3    Bid   3955.25  3955.25  3955.00  3954.75
2022-10-28T20:37:53.112494436Z  ESH3    Ask   3955.00  3955.75  3955.37  3955.00
2022-10-28T20:39:05.152071481Z  ESH3    Ask   3955.00  3955.75  3955.37  3955.00
2022-10-28T20:51:37.650473254Z  ESH3    Bid   3955.50  3955.50  3955.12  3954.75
2022-10-28T20:52:36.842346377Z  ESH3    Ask   3956.00  3956.25  3956.12  3956.00
2022-10-28T20:52:57.780797186Z  ESH3    Bid   3955.00  3955.00  3954.75  3954.50
2022-10-28T20:57:28.474236098Z  ESH3    Ask   3954.75  3956.25  3955.50  3954.75
2022-10-28T20:59:15.075191111Z  ESH3    Ask   3953.75  3956.00  3954.87  3953.75
2022-10-28T20:59:34.607239899Z  ESH3    Ask   3954.50  3956.00  3955.25  3954.50
```
