TradingStrategyUniverse#

API documentation for tradeexecutor.strategy.trading_strategy_universe.TradingStrategyUniverse Python class in Trading Strategy framework.

class TradingStrategyUniverse[source]#

Bases: StrategyExecutionUniverse

A trading strategy universe using our own data feeds.

  • Captures both the market data feeds and factors needed to make trading decisions, like the strategy reserve currency and backtesting tweaks

__init__(reserve_assets, data_universe=None, backtest_stop_loss_time_bucket=None, backtest_stop_loss_candles=None, required_history_period=None, options=None, price_data_delay_tolerance=None, pair_cache=<factory>)#
Parameters:
Return type:

None

Methods

__init__(reserve_assets[, data_universe, ...])

can_open_credit_supply(timestamp, pair[, ...])

Can we do a credit supply trade for a trading pair.

can_open_short(timestamp, pair[, ...])

Can we do a short trade for a trading pair.

can_open_spot(timestamp, pair[, ...])

Can we do a spot trade for a trading pair.

clone()

Create a copy of this universe.

create_from_dataset(dataset[, ...])

Create a universe from loaded dataset.

create_limited_pair_universe(dataset, ...[, ...])

Filters down the dataset for couple trading pair.

create_multichain_universe_by_pair_descriptions(...)

Create a trading universe based on list of (exchange, pair tuples)

create_multipair_universe(dataset, ...[, ...])

Create a trading universe where pairs match a filter conditions.

create_single_pair_universe([chain_id, ...])

Filters down the dataset for a single trading pair.

get_cache_key()

Get semi-human-readable filename id for this universe.

get_credit_supply_pair()

Get the credit supply trading pair.

get_latest_supply_apr([asset, timestamp, ...])

Get the latest supply APR for the lending asset.

get_pair_by_address(address)

Get a trading pair data by a smart contract address.

get_pair_by_human_description(desc)

Get pair by its human-readable description.

get_pair_by_id(internal_id)

Get a trading pair data by its internal id (pair_id).

get_pair_count()

get_reserve_asset()

Get the default reserve asset.

get_shorting_pair(pair)

Get the shorting pair from trading pair

get_single_chain()

Get the single trading pair in this universe.

get_single_pair()

Get the single trading pair in this universe.

get_trading_broken_reason(pair, ...[, ...])

Can we trade a pair.

get_trading_pair(pair)

Get a pair by id or by its data description.

has_any_lending_data()

Does this trading universe has any lending data loaded

has_lending_data()

Is any lending data available.

has_lending_market_available(timestamp, asset)

Did an asset have a lending market available at certain historic point of time.

has_liquidity_data()

Is any liquidty data available.

has_stop_loss_data()

Do we have data available to determine trade stop losses.

is_empty()

This is an empty universe

is_open_ended_universe()

Can new trading pairs to be added to this universe over time.

is_single_pair_universe()

Is this trading universe made for a single pair trading.

iterate_credit_for_reserve()

Iterate over all available credit supply pairs.

iterate_pairs()

Iterate over all available trading pairs.

read_pickle_dangerous(path)

Write a pickled ouput of this universe.

validate()

Check that the created universe looks good.

warm_up_data()

Make sure all data is properly

write_pickle(path)

Write a pickled ouput of this universe

Attributes

reserve_assets

The list of reserve assets used in this strategy.

data_universe

Trading universe datasets.

backtest_stop_loss_time_bucket

Are we using special take profit/stop loss trigger data.

backtest_stop_loss_candles

Special Pandas data feed for candles used only during the backtesting.

required_history_period

How much historic data is needed by the strategy to make its decision.

options

What options were applied to this universe

price_data_delay_tolerance

How much lag we allow in the price feed.

pair_cache

Translated asset and trading pair identifier cache.

end_at

End timestamp of the data.

start_at

Start timestamp of the data.

universe

Backwards compatibility method.

data_universe: Optional[Universe]#

Trading universe datasets.

This encapsulates more generic Universe class from tradingstrategy package.

backtest_stop_loss_time_bucket: Optional[TimeBucket]#

Are we using special take profit/stop loss trigger data.

If we are, what is the time granularity of this data.

backtest_stop_loss_candles: Optional[GroupedCandleUniverse]#

Special Pandas data feed for candles used only during the backtesting.

This allows us to simulate take profit and stop loss trigger orders that would be based on real-time market data in a live execution environment.

required_history_period: Optional[timedelta]#

How much historic data is needed by the strategy to make its decision.

This is the explicit time frame in days or hours for the historical data before today for the strategy to make a decision.

This will limit the amount of data downloaded from the oracle and greatly optimise the strategy decision execution.

E.g. for 90 days you can use datetime.timedelta(days=90)

options: tradeexecutor.strategy.universe_model.UniverseOptions | None#

What options were applied to this universe

Could be e.g.

  • Loaded data range

  • Backtested data range

Not set in legacy code paths. Currently the life cycle of this variable is not well-defined, mostly used to pass the backtest data range around, and set before backtest run, not during the universe construction.

price_data_delay_tolerance: datetime.timedelta | None#

How much lag we allow in the price feed.

This can be set for a very high value when working with open ended universes where the liquidity pools are disappear when liquidity providers leave.

TODO: Use carefully - this is mostly a workaround variable and will have a more robust TVL/liquidity solution in the future.

pair_cache: dict#

Translated asset and trading pair identifier cache.

  • When called asset.set_tags() or setting asset.other_data() it is stored here.

  • See warm_up_data()

get_cache_key()[source]#

Get semi-human-readable filename id for this universe.

Note

Currently does not capture all the nuances of the data. Must be defined later to produce an accurate hash on Universe.

Return type:

str

property start_at: datetime#

Start timestamp of the data.

  • Valid for backtesting only

  • Based on OHLCV candles

property end_at: datetime#

End timestamp of the data.

  • Valid for backtesting only

  • Based on OHLCV candles

property universe#

Backwards compatibility method.

Deprecate in some point.

is_open_ended_universe()[source]#

Can new trading pairs to be added to this universe over time.

Returns:

True if the trading universe may contain hundreds or thousands of trading pairs.

Return type:

bool

has_lending_data()[source]#

Is any lending data available.

Note

For live trading, lending candles are not available, but any lending rates are directly updated from on-chain sources.

Return type:

bool

has_liquidity_data()[source]#

Is any liquidty data available.

Return type:

bool

get_pair_by_id(internal_id)[source]#

Get a trading pair data by its internal id (pair_id).

Parameters:

internal_id (int) –

Return type:

Optional[TradingPairIdentifier]

get_trading_pair(pair)[source]#

Get a pair by id or by its data description.

Parameters:

pair (int | tradingstrategy.pair.DEXPair) – Trading pair internal id or DEXPair object

Returns:

Tradind strategy pair definition.

Raises:

PairNotFoundError – If we have not loaded data for the given pair id.

Return type:

TradingPairIdentifier

can_open_spot(timestamp, pair, liquidity_threshold=None)[source]#

Can we do a spot trade for a trading pair.

To be used with backtesting. We will check a spot market exists at a certain historic point of time.

Parameters:
  • timestamp (Timestamp) – When

  • pair (TradingPairIdentifier) – The wanted trading pair

  • liquidity_threshold – Not implemented yet.

Returns:

True if we can open a spot position.

Return type:

bool

has_any_lending_data()[source]#

Does this trading universe has any lending data loaded

Return type:

bool

has_lending_market_available(timestamp, asset, liquidity_threshold=None, market_metric=LendingCandleType.variable_borrow_apr, data_lag_tolerance=Timedelta('7 days 00:00:00'))[source]#

Did an asset have a lending market available at certain historic point of time.

To be used with backtesting. We will check a lending market exists at a certain historic point of time.

Parameters:
  • timestamp (pandas._libs.tslibs.timestamps.Timestamp | datetime.datetime) – When

  • pair – The wanted trading pair

  • liquidity_threshold – Not implemented yet.

  • asset (AssetIdentifier) –

  • market_metric (LendingCandleType) –

Returns:

True if we can open a spot position.

Return type:

bool

warm_up_data()[source]#

Make sure all data is properly

  • Trading pair data must be preprocessed before we can call set_tags() or set other_data

  • See pair_cache for details

can_open_short(timestamp, pair, liquidity_threshold=None)[source]#

Can we do a short trade for a trading pair.

To be used with backtesting. We will check a lending market exists at a certain historic point of time for both base and quote asset.

Parameters:
Returns:

True if we can open a short position.

Return type:

bool

can_open_credit_supply(timestamp, pair, liquidity_threshold=None)[source]#

Can we do a credit supply trade for a trading pair.

To be used with backtesting. We will check a lending market exists at a certain historic point of time for both base and quote asset.

Parameters:
Returns:

True if we can open a credit supply position.

Return type:

bool

clone()[source]#

Create a copy of this universe.

Any dataframes are now copied, but set by reference, so do not mutate in place.

Return type:

TradingStrategyUniverse

write_pickle(path)[source]#

Write a pickled ouput of this universe

Parameters:

path (Path) –

static read_pickle_dangerous(path)[source]#

Write a pickled ouput of this universe.

Warning

Only use for trusted input. Python pickle issue.

Parameters:

path (Path) –

Return type:

TradingStrategyUniverse

is_empty()[source]#

This is an empty universe

  • without trading pairs

  • …or without candles

Return type:

bool

is_single_pair_universe()[source]#

Is this trading universe made for a single pair trading.

Note that even a single pair universe may contain two trading pairs, if we need intermediate routing pairs. E.g. AAVE -> BNB -> BUSD/

Return type:

bool

has_stop_loss_data()[source]#

Do we have data available to determine trade stop losses.

Note that this applies for backtesting only - when doing production trade execution, stop loss data is not part of the universe but real time pricing comes directly from the exchange using real-time side channels.

Return type:

bool

validate()[source]#

Check that the created universe looks good.

Raises:

TradingUniverseIssue – In the case of detected issues

get_pair_by_human_description(desc)[source]#

Get pair by its human-readable description.

See tradingstrategy.pair.PandasPairUniverse.get_pair_by_human_description()

The trading pair must be loaded in the exchange universe.

Returns:

The trading pair on the exchange.

Highest volume trading pair if multiple matches.

Raises:

NoPairFound – In the case input data cannot be resolved.

Parameters:

desc (Union[Tuple[ChainId, str | None, str, str, float], Tuple[ChainId, str | None, str, str]]) –

Return type:

TradingPairIdentifier

iterate_pairs()[source]#

Iterate over all available trading pairs.

Return type:

Iterable[TradingPairIdentifier]

iterate_credit_for_reserve()[source]#

Iterate over all available credit supply pairs.

  • We can deposit our reserve and get aToken for interest

Return type:

Iterable[TradingPairIdentifier]

create_single_pair_universe(chain_id=None, exchange_slug=None, base_token=None, quote_token=None, pair=None)[source]#

Filters down the dataset for a single trading pair.

This is ideal for strategies that only want to trade a single pair.

Parameters:
Return type:

TradingStrategyUniverse

static create_limited_pair_universe(dataset, chain_id, exchange_slug, pairs, reserve_asset_pair_ticker=None, forward_fill=False)[source]#

Filters down the dataset for couple trading pair.

This is ideal for strategies that only want to trade few pairs, or a single pair using three-way trading on a single exchange.

The university reserve currency is set to the quote token of the first pair.

Parameters:
  • dataset (Dataset) – Datasets downloaded from the server

  • pairs (Set[Tuple[str, str]]) – List of trading pairs as ticket tuples. E.g. [ (“WBNB, “BUSD”), (“Cake”, “WBNB”) ]

  • reserve_asset_pair_ticker (Optional[Tuple[str, str]]) – Choose the quote token of this trading pair as a reserve asset. This must be given if there are several pairs (Python set order is unstable).

  • forward_fill

    Forward-fill the data.

    When working with sparse data (gaps in candles), many strategies need these gaps to be filled. Setting this parameter True will automatically forward-fill any data we are loading from the dataset.

    See forward fill for more information.

  • chain_id (ChainId) –

  • exchange_slug (str) –

Return type:

TradingStrategyUniverse

get_pair_by_address(address)[source]#

Get a trading pair data by a smart contract address.

Parameters:

address (str) –

Return type:

Optional[TradingPairIdentifier]

get_single_pair()[source]#

Get the single trading pair in this universe.

Raises:

Exception – If we have more than one trading pair

Return type:

TradingPairIdentifier

get_single_chain()[source]#

Get the single trading pair in this universe.

Raises:

Exception – If we have more than one chain

Return type:

ChainId

static create_multipair_universe(dataset, chain_ids, exchange_slugs, quote_tokens, reserve_token, factory_router_map, liquidity_resample_frequency=None)[source]#

Create a trading universe where pairs match a filter conditions.

These universe may contain thousands of trading pairs. This is for strategies that trade across multiple pairs, like momentum strategies.

Parameters:
  • dataset (Dataset) – Datasets downloaded from the oracle

  • chain_ids (Iterable[ChainId]) – Allowed blockchains

  • exchange_slugs (Iterable[str]) – Allowed exchanges

  • quote_tokens (Iterable[str]) – Allowed quote tokens as smart contract addresses

  • reserve_token (str) – The token addresses that are used as reserve assets.

  • factory_router_map (Dict[str, tuple]) – Ensure we have a router address for every exchange we are going to use. TODO: In the future this information is not needed.

  • liquidity_resample_frequency (Optional[str]) –

    Create a resampled liquidity universe instead of accurate one.

    If given, this will set Universe.resampled_liquidity attribute.

    Using ResampledLiquidityUniverse will greatly speed up backtests that estimate trading pair liquidity, by trading off sample accuracy for code execution speed.

    Must be a Pandas frequency string value, like 1d.

    Note that resamping itself takes a lot of time upfront, so you want to use this only if the backtest takes lont time.

Return type:

TradingStrategyUniverse

static create_from_dataset(dataset, reserve_asset=None, forward_fill=False)[source]#

Create a universe from loaded dataset.

For code example see load_trading_and_lending_data().

Parameters:
  • reserve_asset (str) –

    Which reserve asset to use.

    As the token address or symbol.

    If not given try to guess from the dataset.

    • Assume all trading pairs have the same quote token and that is our reserve asset

    • If dataset has trading pairs with different quote tokens, aborts

    Examples:

    • 0x2791bca1f2de4661ed88a30c99a7a9449aa84174 (USDC.e bridged address on Polygon)

    • 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 (USDC native)

  • forward_fill

    Forward-fill the data.

    When working with sparse data (gaps in candles), many strategies need these gaps to be filled. Setting this parameter True will automatically forward-fill any data we are loading from the dataset.

    See forward fill for more information.

  • dataset (Dataset) –

static create_multichain_universe_by_pair_descriptions(dataset, pairs, reserve_token_symbol)[source]#

Create a trading universe based on list of (exchange, pair tuples)

This is designed for backtesting multipe pairs across different chains. The created universe do not have any routing options and thus cannot make any trades.

Parameters:
  • dataset (Dataset) – Datasets downloaded from the oracle

  • pairs (Collection[Union[Tuple[ChainId, str | None, str, str, float], Tuple[ChainId, str | None, str, str]]]) –

    List of trading pairs to filter down.

    The pair set is desigend to be small, couple of dozens of pairs max.

    See HumanReadableTradingPairDescription.

  • reserve_token_symbol (str) –

    The token symbol of the reverse asset.

    Because we do not support routing, we just pick the first matching token.

Return type:

TradingStrategyUniverse

get_credit_supply_pair()[source]#

Get the credit supply trading pair.

This trading pair identifies the trades where we move our strategy reserve currency to Aave lending pool to gain interest.

Assume we move our single reserve currency to a single lending reserve we know for it.

Returns:

Credit supply trading pair with ticket (aToken for reserve asset, reserve asset)

Return type:

TradingPairIdentifier

get_shorting_pair(pair)[source]#

Get the shorting pair from trading pair

This trading pair identifies the trades where we borrow asset from Aave against collateral.

Parameters:

pair (TradingPairIdentifier) – Trading pair of the asset to be shorted

Returns:

Short pair with ticker (vToken for borrowed asseet, aToken for reserve asset)

Return type:

TradingPairIdentifier

get_trading_broken_reason(pair, min_candles_required, min_price=1e-08, max_price=1000000)[source]#

Can we trade a pair.

Check if we can trade a particular trading pair.

  • Work around spotty low cap coins

  • Check that we have minimum amout of bars of data

  • Check that price data does not look weird

Parameters:
  • pair (TradingPairIdentifier) – Trading pair

  • min_candles_required (int) – How many bars of adta we need

  • min_price – Avoid low cap tokens with float64 breaking prices

  • max_pric – Avoid low cap tokens with float64 breaking prices

Returns:

A string why the trading pair is broken.

None if good.

Return type:

str | None

get_latest_supply_apr(asset=None, timestamp=None, tolerance=datetime.timedelta(days=1))[source]#

Get the latest supply APR for the lending asset.

Parameters:
  • asset (tradeexecutor.state.identifier.AssetIdentifier | None) –

    Specify the asset to get the rate for If none, use the reserve asset.

    Must be non-wrapped, not aToken.

  • timestamp (datetime.datetime | None) – Specify timestamp to get the rate for If none, return the latest rate

  • tolerance (timedelta) –

    Lookback tolerance with stale data.

    Default to 1 days if not given.

Returns:

Latest supply APR rate

Return type:

float

reserve_assets: Collection[AssetIdentifier]#

The list of reserve assets used in this strategy.

Currently we support only one reserve asset per strategy, though in the future there can be several.

Usually return the list of a BUSD/USDC/similar stablecoin.

TODO: Migrate to Set[] in all the code

__init__(reserve_assets, data_universe=None, backtest_stop_loss_time_bucket=None, backtest_stop_loss_candles=None, required_history_period=None, options=None, price_data_delay_tolerance=None, pair_cache=<factory>)#
Parameters:
Return type:

None