# Research Workflow (/scripting-v2/notebook/research)



## Cell 1: import packages [#cell-1-import-packages]

```python
import matplotlib.pyplot as plt
import pandas as pd
```

These imports come from the Python environment selected when `mlab notebook` started.

## Cell 2: choose a historical range [#cell-2-choose-a-historical-range]

```python
history = mlab.history(
    start="2026-08-01",
    end="2026-08-20",
)
```

`start` and `end` accept UTC dates or UTC date-times:

```python
history = mlab.history(
    start="2026-08-01 09:30:00",
    end="2026-08-01 16:00:00",
)
```

The range is validated immediately. No market data is fetched until a cell requests a source.

## Cell 3: fetch a source [#cell-3-fetch-a-source]

```python
CANDLES = "btc@candles@hyperliquidf:timeframe=3600"
candles = history.source(CANDLES)
```

Notebook history accepts the same exact selectors as Python V2. The first call fetches and normalizes the requested range. Repeated calls for the same selector use the history object's memory cache.

The result is a normal Python list of dictionaries ordered from oldest to newest.

Read individual records with the same indexing convention as Python V2:

```python
latest = history.source(CANDLES, 0)
previous = history.source(CANDLES, 1)
```

Index `0` is the newest record. An unavailable index returns `None`.

## Cell 4: analyze with pandas [#cell-4-analyze-with-pandas]

```python
df = pd.DataFrame(candles)
df["return"] = df["c"].pct_change()
df["sma_20"] = df["c"].rolling(20).mean()
df.tail()
```

Notebook history returns the complete requested range. It does not use the rolling `lookback` limit applied to Python strategy files.

## Cell 5: use Market Lab studies [#cell-5-use-market-lab-studies]

Notebook studies use `mlab.study`:

```python
sma = mlab.study.sma(candles, {"field": "c", "window": 20})
sma["latest"]
```

Available helpers:

* `sma`
* `ema`
* `cvd`
* `spread`
* `depth`
* `imbalance`
* `slippage`
* `vamp`

They run the same Rust calculations used by Python V2 and the Market Lab CLI. See [Built-In Functions](/scripting-v2/built-ins) for their input and return shapes; use `mlab.study` where those plain-file examples use `ctx.study`.

## Cell 6: plot the result [#cell-6-plot-the-result]

```python
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(df["t"], df["c"], label="BTC close")
ax.plot(df["t"], df["sma_20"], label="20-period SMA")
ax.legend()
plt.show()
```

## Refresh cached data [#refresh-cached-data]

Clear one selector and fetch it again:

```python
history.clear(CANDLES)
candles = history.source(CANDLES)
```

Clear every selector cached by the history object:

```python
history.clear()
```

Each new `mlab.history(...)` object has its own range and cache.

Read [How It Works](/scripting-v2/notebook/how-it-works) for the kernel bridge and current notebook boundaries.
