Tradind OHLCV candle data and manipulation.


  • Candle for information about OHLCV data presentation

  • tradingstrategy.client.Client.fetch_candle_universe() how to load OHLCV dataset

You are likely to working with candle datasets that are presented by

For more information about candles see candle in glossary.

exception tradingstrategy.candle.PriceUnavailable

We tried to look up price for a trading pair, but count not find a candle close to the timestamp.

class tradingstrategy.candle.Candle

Data structure presenting one OHLCV trading candle.

Based on the open-high-low-close-volume concept.

Trading Strategy candles come with additional information available on the top of core OHLCV, as chain analysis has deeper visibility than one would get on traditional exchanges. For example for enhanced attributes see Candle.buys (buy count) or Candle.start_block (blockchain starting block number of the candle).

We also separate “buys” and “sells”. Although this separation might not be meaningful on order-book based exchanges, we define “buy” as a DEX swap where quote token (USD, ETH) was swapped into more exotic token (AAVE, SUSHI, etc.)

pair_id: tradingstrategy.types.PrimaryKey

Primary key to identity the trading pair Use pair universe to map this to chain id and a smart contract address

timestamp: tradingstrategy.types.UNIXTimestamp

Open timestamp for this candle. Note that the close timestamp you need to supply yourself based on the context.

exchange_rate: float

USD exchange rate of the quote token used to convert to dollar amounts in this candle.

Note that currently any USD stablecoin (USDC, DAI) is assumed to be 1:1 and the candle server cannot handle exchange rate difference among stablecoins.

The rate is taken at the beginning of the 1 minute time bucket. For other time buckets, the exchange rate is the simple average for the duration of the bucket.

open: tradingstrategy.types.USDollarAmount

OHLC core data

close: tradingstrategy.types.USDollarAmount

OHLC core data

high: tradingstrategy.types.USDollarAmount

OHLC core data

low: tradingstrategy.types.USDollarAmount

OHLC core data

buys: int

Number of buys happened during the candle period

sells: int

Number of sells happened during the candle period

buy_volume: tradingstrategy.types.USDollarAmount

Volume data

sell_volume: tradingstrategy.types.USDollarAmount

Volume data

avg: tradingstrategy.types.USDollarAmount

Average trade size

start_block: tradingstrategy.types.BlockNumber

The first blockchain block that includes trades that went into this candle.

end_block: tradingstrategy.types.BlockNumber

The last blockchain block that includes trades that went into this candle.

property trades: int

Amount of all trades during the candle period.

property volume: tradingstrategy.types.USDollarAmount

Total volume during the candle period.

Unline in traditional CEX trading, we can separate buy volume and sell volume from each other, becauase liquidity provider is a special role.

classmethod to_dataframe() pandas.core.frame.DataFrame

Return emptry Pandas dataframe presenting candle data.

classmethod to_qstrader_dataframe() pandas.core.frame.DataFrame

Return emptry Pandas dataframe presenting candle data for QStrader.

TODO: Fix QSTrader to use “standard” column names.

classmethod to_pyarrow_schema(small_candles=False) pyarrow.lib.Schema

Construct schema for writing Parquet filess for these candles.


small_candles – Use even smaller word sizes for frequent (1m) candles.

__init__(pair_id: tradingstrategy.types.PrimaryKey, timestamp: tradingstrategy.types.UNIXTimestamp, exchange_rate: float, open: tradingstrategy.types.USDollarAmount, close: tradingstrategy.types.USDollarAmount, high: tradingstrategy.types.USDollarAmount, low: tradingstrategy.types.USDollarAmount, buys: int, sells: int, buy_volume: tradingstrategy.types.USDollarAmount, sell_volume: tradingstrategy.types.USDollarAmount, avg: tradingstrategy.types.USDollarAmount, start_block: tradingstrategy.types.BlockNumber, end_block: tradingstrategy.types.BlockNumber) None
class tradingstrategy.candle.CandleResult

Server-reply for live queried candle data.

Uses dataclasses-json module for JSON serialisation.

candles: List[tradingstrategy.candle.Candle]

A bunch of candles. Candles are unordered and subject to client side sorting. Multiple pairs and chains may be present in candles.


In-place sorting of candles by their timestamp.

__init__(candles: List[tradingstrategy.candle.Candle]) None
class tradingstrategy.candle.GroupedCandleUniverse

A candle universe where each trading pair has its own candles.

This is helper class to create foundation for multi pair strategies.

For the data logistics purposes, all candles are lumped together in single columnar data blobs. However, it rarely makes sense to execute operations over different trading pairs. :py:class`GroupedCandleUniverse` creates trading pair id -> candle data grouping out from raw candle data.


# Get candles for SUSHI-USDT

exchange_universe = client.fetch_exchange_universe()
raw_pairs = client.fetch_pair_universe().to_pandas()
raw_candles = client.fetch_all_candles(TimeBucket.d7).to_pandas()

pair_universe = PandasPairUniverse(raw_pairs)
candle_universe = GroupedCandleUniverse(raw_candles)

# Do some test calculations for a single pair
sushi_swap = exchange_universe.get_by_chain_and_name(ChainId.ethereum, "sushi")
sushi_usdt = pair_universe.get_one_pair_from_pandas_universe(sushi_swap.exchange_id, "SUSHI", "USDT")

raw_candles = client.fetch_all_candles(TimeBucket.d7).to_pandas()
candle_universe = GroupedCandleUniverse(raw_candles)
sushi_usdth_candles = candle_universe.get_candles_by_pair(sushi_usdt.pair_id)
get_candle_count() int

Return the dataset size - how many candles total

get_candles_by_pair(pair_id: tradingstrategy.types.PrimaryKey) Optional[pandas.core.frame.DataFrame]

Get candles for a single pair.

get_closest_price(pair_id: tradingstrategy.types.PrimaryKey, when: pandas._libs.tslibs.timestamps.Timestamp, kind='close', look_back_time_frames=5) tradingstrategy.types.USDollarAmount

Get the available liuqidity for a trading pair at a specific timepoint or some candles before the timepoint.

The liquidity is defined as one-sided as in XY liquidity model.

  • pair_id – Traing pair id

  • when – Timestamp to query

  • kind – One of OHLC data points: “open”, “close”, “low”, “high”

  • look_back_timeframes – If there is no liquidity sample available at the exact timepoint, look to the past to the get the nearest sample


We always return


LiquidityDataUnavailable – There was no liquidity sample available

static create_empty() tradingstrategy.candle.GroupedCandleUniverse

Return an empty GroupedCandleUniverse

static create_empty_qstrader() tradingstrategy.candle.GroupedCandleUniverse

Return an empty GroupedCandleUniverse.

TODO: Fix QSTrader to use “standard” column names.