State#

API documentation for tradeexecutor.state.state.State Python class in Trading Strategy framework.

class State[source]#

Bases: object

The current state of the trading strategy execution.

It tells the current and past state of a single trading strategy execution: positions, their trades and related valuations, metrics and such data.

This class is the root object of the serialisable state tree for a trading strategy.

  • Can be serialised as JSON

  • Contains one Portfolio object that contains all positions, trades and underlying blockchain transactions

  • Contains one Visualisation object that contains run-time calculated and stored visualisation about the portfolio

  • Contains one Statistics object that contains run-time calculated and stored metrics about the portfolio

Uses of this class include

  • Backtest fills in the state when simulating the trades

  • The live execution environment keeps its internal state on a disk as a serialised State object

  • Analysis and performance metrics read the state

  • The web frontend reads the state

__init__(created_at=<factory>, last_updated_at=None, cycle=1, name=None, portfolio=<factory>, stats=<factory>, asset_blacklist=<factory>, visualisation=<factory>, uptime=<factory>, sync=<factory>, backtest_data=None, other_data=<factory>)#
Parameters:
Return type:

None

Methods

__init__([created_at, last_updated_at, ...])

blacklist_asset(asset)

Add a asset to the blacklist.

check_if_clean()

Check that the state data is intact.

create_trade(strategy_cycle_at, pair, ...[, ...])

Creates a request for a new trade.

from_dict(kvs, *[, infer_missing])

from_json(s, *[, parse_float, parse_int, ...])

get_formatted_strategy_duration()

Get the age of the strategy execution in human-readable format.

get_strategy_duration()

Get the age of the strategy execution.

get_strategy_start_and_end()

Get the time range for which the strategy should have data.

get_strategy_time_range()

Get the time range for which the strategy should have data.

get_trading_time_range()

Get the time range when the strategy could have made trades.

is_empty()

This state has no open or past trades or reserves.

is_good_pair(pair)

Check if the trading pair is blacklisted.

mark_broadcasted(broadcasted_at, trade)

mark_ready(timestamp)

Mark that the strategy has enough (backtest) data to decide the first trade.

mark_trade_failed(failed_at, trade)

Unroll the allocated capital.

mark_trade_success(executed_at, trade, ...)

After trade has been successfully executed, update the state of our internal ledged to reflect this.

perform_integrity_check()

Check that we are not reusing any trade or position ids and counters are correct.

read_json_blob(text)

Parse state from JSON blob.

read_json_file(path)

Read state from the JSON file.

revalue_positions(ts, valuation_method)

Revalue all open positions in the portfolio.

schema(*[, infer_missing, only, exclude, ...])

start_execution(ts, trade[, txid, nonce, ...])

Update our balances and mark the trade execution as started.

start_execution_all(ts, trades[, ...])

Mark a bunch of trades ready to go.

supply_credit(strategy_cycle_at, pair, ...)

Create or adjust credit supply position.

to_dict([encode_json])

to_json(*[, skipkeys, ensure_ascii, ...])

to_json_safe()

Serialise to JSON format with helpful validation and error messages.

trade_short(strategy_cycle_at, pair, ...[, ...])

Creates a trade for a short position.

update_reserves(new_reserves)

write_json_file(path)

Write JSON to a file.

Attributes

created_at

When this state was created

last_updated_at

When this state was saved

cycle

The next cycle.

name

The name of this strategy.

portfolio

Portfolio of this strategy.

stats

Portfolio and position performance records over time.

asset_blacklist

Assets that the strategy is not allowed to touch, or have failed to trade in the past, resulting to a frozen position.

visualisation

Strategy visualisation and debug messages to show how the strategy is thinking.

uptime

Trade execution uptime and success statistcis]

sync

backtest_data

Backtest data related to this backtest result

other_data

Misc.

created_at: datetime#

When this state was created

Same as when the strategy was launched

last_updated_at: Optional[datetime]#

When this state was saved

UTC timestamp. Set by by tradeexecutor.state.store.StateStore.sync()

cycle: int#

The next cycle.

How many strategy thinking and execution cycles we have completed successfully.

Starts with 1 (no cycles completed)

name: Optional[str]#

The name of this strategy. Can be unset. Set when the state is created.

portfolio: Portfolio#

Portfolio of this strategy. Currently only one portfolio per strategy.

stats: Statistics#

Portfolio and position performance records over time.

asset_blacklist: Set[str]#

Assets that the strategy is not allowed to touch, or have failed to trade in the past, resulting to a frozen position. Besides this internal black list, the executor can have other blacklists based on the trading universe and these are not part of the state. The main motivation of this list is to avoid assets that caused a freeze in the future. Key is Ethereum address, lowercased.

visualisation: Visualisation#

Strategy visualisation and debug messages to show how the strategy is thinking.

uptime: Uptime#

Trade execution uptime and success statistcis]

Contains statistics about trade execution having to manage to run its internal functions.

backtest_data: tradeexecutor.state.state.BacktestData | None#

Backtest data related to this backtest result

Data that is relevant only for backtest results, not live trading.

other_data: Optional[OtherData]#

Misc. backtesting variables settable by users

is_empty()[source]#

This state has no open or past trades or reserves.

Return type:

bool

is_good_pair(pair)[source]#

Check if the trading pair is blacklisted.

Parameters:

pair (TradingPairIdentifier) –

Return type:

bool

mark_ready(timestamp)[source]#

Mark that the strategy has enough (backtest) data to decide the first trade.

This marks the difference between the backtesting data availability period, and actual tradeable period when all indicators have enough data.

  • See BacktestData.ready_at for more information

  • Can be called multiple times, only the first time counts

  • See get_trading_time_range() for reading

  • If you do not call this method in decide_trades(), nothing bad happens, but backtest benchmark indices (buy and hold BTC, etc.) might have biases results to a direction or another

Parameters:

timestamp (datetime.datetime | pandas._libs.tslibs.timestamps.Timestamp) –

get_strategy_time_range()[source]#

Get the time range for which the strategy should have data.

  • If this is a backtest, return backtesting range

  • If this is a live execution, return created - last updated

  • See also get_trading_time_range()

Return type:

Tuple[datetime, datetime]

get_trading_time_range()[source]#

Get the time range when the strategy could have made trades.

Return type:

Tuple[datetime, datetime]

get_strategy_duration()[source]#

Get the age of the strategy execution. If backtest, return backtest range, if live, return created - last updated

See get_strategy_time_range() for details.

Returns:

Age of the strategy execution, or None if the age cannot be calculated.

Return type:

datetime.timedelta | None

get_formatted_strategy_duration()[source]#

Get the age of the strategy execution in human-readable format.

See get_strategy_duration() for details.

Returns:

Age of the strategy execution in human-readable format.

Return type:

str

create_trade(strategy_cycle_at, pair, quantity, reserve, assumed_price, trade_type, reserve_currency, reserve_currency_price, notes=None, pair_fee=None, lp_fees_estimated=None, planned_mid_price=None, price_structure=None, position=None, slippage_tolerance=None, leverage=None, closing=False, planned_collateral_consumption=None, planned_collateral_allocation=None, flags=None, pending=False)[source]#

Creates a request for a new trade.

If there is no open position, marks a position open.

Trade can be opened by knowing how much you want to buy (quantity) or how much cash you have to buy (reserve).

  • To open a spot buy, fill in reseve amount you wish to use for the buy

  • To open a spot sell, fill in quoantity amount you wish to use for the buy, as a negative number

Parameters:
  • strategy_cycle_at (datetime) – The strategy cycle timestamp for which this trade was executed.

  • trade_id – Trade id allocated by the portfolio

  • quantity (Optional[Decimal]) –

    How many units this trade does.

    Positive for buys, negative for sells in the spot market.

    For short positions, negative quantity means increase the position of this much, positive quantity means decrease the position.

    Any fees have been already reduced away from this quantity, as PriceModel gives the planned price that includes fees.

  • assumed_price (float) –

    The planned execution price.

    This is the price we expect to pay per quantity unit after the execution. This is the mid price + any LP fees included.

  • trade_type (TradeType) – What kind of a trade is this.

  • reserve_currency (AssetIdentifier) –

    Which portfolio reserve we use for this trade.

    param reserve_currency_price:

    If the quote token is not USD, then the exchange rate between USD and quote token we assume we have.

    Actual exchange rate may depend on the execution.

  • notes (Optional[str]) – Any human-readable remarks we want to tell about this trade.

  • pair_fee (Optional[float]) – The fee tier from the trading pair / overriden fee.

  • lp_fees_estimated (Optional[float]) – HOw much we estimate to pay in LP fees (dollar)

  • planned_mid_price (Optional[float]) – What was the mid-price of the trading pair when we started to plan this trade.

  • reserve (Optional[Decimal]) –

    How many reserve units this trade produces/consumes.

    I.e. dollar amount for buys/sells.

  • price_structure (Optional[TradePricing]) –

    The full planned price structure for this trade.

    The state of the market at the time of planning the trade, and what fees we assumed we are going to get.

  • position (Optional[TradingPosition]) –

    Override the position for the trade.

    • Use for close trades (you need to explicitly tell which position to close as there might be two positions with the same pair)

    • Use for repair trades.

  • notes – Human-readable string to show on the trade.

  • slippage_tolerance (Optional[float]) –

    Slippage tolerance for this trade.

    See tradeexecutor.state.trade.TradeExecution.slippage_tolerance for details.

  • closing (Optional[bool]) –

    This trade should close the position entirely.

    A flag used with leveraged positions.

  • pending

    Do not generate a new open position.

    Used when adding take profit triggers to market limit position.

  • pair (TradingPairIdentifier) –

  • reserve_currency_price (float) –

  • leverage (Optional[float]) –

  • planned_collateral_consumption (Optional[Decimal]) –

  • planned_collateral_allocation (Optional[Decimal]) –

  • flags (Optional[Set[TradeFlag]]) –

Returns:

Tuple of entries

  • Trade position (old/new)

  • New trade

  • True if a a new position was opened

Return type:

Tuple[TradingPosition, TradeExecution, bool]

trade_short(strategy_cycle_at, pair, borrowed_asset_price, trade_type, reserve_currency, collateral_asset_price, borrowed_quantity=None, collateral_quantity=None, notes=None, pair_fee=None, lp_fees_estimated=None, planned_mid_price=None, price_structure=None, position=None, slippage_tolerance=None, closing=False, planned_collateral_consumption=None, planned_collateral_allocation=None, flags=None)[source]#

Creates a trade for a short position.

  • Opens, increases or decreases short position size.

For argument and return value documentation see create_trade().

See also supply_credit().

Parameters:
Returns:

Trading position, trade execution and created flag.

TradeExecution.planned_loan is set.

After the trade succeeds, TradingPosition.loan is set.

If the trade does not succeed loan data remains unchanged.

Return type:

Tuple[TradingPosition, TradeExecution, bool]

supply_credit(strategy_cycle_at, pair, trade_type, reserve_currency, collateral_asset_price, collateral_quantity=None, notes=None, pair_fee=None, lp_fees_estimated=None, planned_mid_price=None, price_structure=None, position=None, slippage_tolerance=None, closing=False, flags=None)[source]#

Create or adjust credit supply position.

Credit supply position trades are modelled as following

  • You BUY aToken using the reserve. Like buying aUSDC with USDC.

  • You SELL aToken and get back reserve + interest, with the trade size reserve + interest

  • Reserve is USDC, always positive

  • The modelling is different from trade_short/trade_long

  • See also trade_short()

Parameters:
Return type:

Tuple[TradingPosition, TradeExecution, bool]

start_execution(ts, trade, txid=None, nonce=None, underflow_check=False, triggered=False)[source]#

Update our balances and mark the trade execution as started.

  • Called before a transaction is broadcasted.

  • Updates internal accounting and moves capital from the reserve account locked on a trade

See also start_execution_all().

Parameters:
  • trade (TradeExecution) – Trade to

  • underflow_check

    Raise exception if we have not enough cash to allocate.

    The check disabled by default. Might be legit for portfolio strats that need to sell old assets before buying new assets.

  • txid (str | None) – Legacy. Do not use.

  • nonce (int | None) – Legacy. Do not use.

  • triggered – True if this execution is from stop loss trigger checks, otherwise from decision trades cycle.

  • ts (datetime) –

mark_trade_success(executed_at, trade, executed_price, executed_amount, executed_reserve, lp_fees, native_token_price, cost_of_gas=None, executed_collateral_consumption=None, executed_collateral_allocation=None, force=False)[source]#

After trade has been successfully executed, update the state of our internal ledged to reflect this.

  • Trade is marked as successfully complete

  • All position sizes are updated to match executed values (instead of planned values)

  • Mark any LP and gas fees from the trade

  • If this was the final trade of the position, mark the position closed

Parameters:
mark_trade_failed(failed_at, trade)[source]#

Unroll the allocated capital.

Parameters:
revalue_positions(ts, valuation_method)[source]#

Revalue all open positions in the portfolio.

Reserves are not revalued.

Parameters:
blacklist_asset(asset)[source]#

Add a asset to the blacklist.

Parameters:

asset (AssetIdentifier) –

perform_integrity_check()[source]#

Check that we are not reusing any trade or position ids and counters are correct.

Raise:

Assertion error in the case internal data structures are damaged

start_execution_all(ts, trades, max_slippage=None, underflow_check=False, rebroadcast=False, triggered=False)[source]#

Mark a bunch of trades ready to go.

Update any internal accounting of capital allocation from reseves to trades.

Sets the execution model specific parameters like max_slippage on the trades.

See also start_execution()

Parameters:
  • ts (datetime) – Strategy cycle timestamp

  • trades (List[TradeExecution]) – List of trades to prepare

  • max_slippage (float) –

    Legacy. Do not use.

    The slippage allowed for this trade before it fails in execution. 0.01 is 1%.

  • underflow_check

    Legacy. Do not use.

    If true warn us if we do not have enough reserves to perform the trades. This does not consider new reserves released from the closed positions in this cycle.

check_if_clean()[source]#

Check that the state data is intact.

Check for the issues that could be caused e.g. trade-executor unclean shutdown or a blockchain node crash.

One of a typical issue would be

  • A trade that failed to execute

  • A trade that was broadcasted, but we did not get a confirmation back in time, causing the trade executor to crash

Call this when you restart a trade execution to ensure the old state is intact. For any unfinished trades, run a repair command or manually repair the database.

Raises:

UncleanState – In the case we detect unclean stuff

to_json_safe()[source]#

Serialise to JSON format with helpful validation and error messages.

Extra validation adds performance overhead.

Returns:

The full strategy execution state as JSON string.

The strategy can be saved on a disk, resumed, or server to the web frontend using this JSON blob.

Return type:

str

write_json_file(path)[source]#

Write JSON to a file.

  • Validates state before writing it out

  • Work around any serialisation quirks

Parameters:

path (pathlib.Path | str) –

get_strategy_start_and_end()[source]#

Get the time range for which the strategy should have data.

TODO: Clean up this. In the future, each strategy must record its start (launched at) and end (last run) dates on the state itself.

Return type:

tuple[pandas._libs.tslibs.timestamps.Timestamp | None, pandas._libs.tslibs.timestamps.Timestamp | None]

static read_json_file(path)[source]#

Read state from the JSON file.

  • Deal with all serialisation quirks

Parameters:

path (pathlib.Path | str) –

Return type:

State

static read_json_blob(text)[source]#

Parse state from JSON blob.

  • Deal with all serialisation quirks

Parameters:

text (str) –

Return type:

State

__init__(created_at=<factory>, last_updated_at=None, cycle=1, name=None, portfolio=<factory>, stats=<factory>, asset_blacklist=<factory>, visualisation=<factory>, uptime=<factory>, sync=<factory>, backtest_data=None, other_data=<factory>)#
Parameters:
Return type:

None