TradingPosition#

tradeexecutor.state.position.TradingPosition Python class in Trading Strategy framework.

class TradingPosition[source]#

Bases: GenericPosition

Represents a single trading position.

  • Each position trades a single asset

  • Position is opened when the first trade is made

  • Position is closed when the last remaining quantity is sold/closed

  • Position can have its target trigger levels for take_profit and stop_loss

  • Position can have multiple trades and increase or decrease the position exposure

  • Positions are revalued outside the trades

  • Trades for the position can have different triggers: rebalance, stop los, etc.

  • Position can be marked as frozen meaning the automatic system does not how to clean it up

__init__(position_id, pair, opened_at, last_pricing_at, last_token_price, last_reserve_price, reserve_currency, trades=<factory>, closed_at=None, frozen_at=None, unfrozen_at=None, last_trade_at=None, portfolio_value_at_open=None, stop_loss=None, take_profit=None, trailing_stop_loss_pct=None, notes=None, balance_updates=<factory>, trigger_updates=<factory>)#
Parameters:
Return type:

None

Methods

__init__(position_id, pair, opened_at, ...)

add_balance_update_event(event)

Include a new balance update event

add_notes_message(msg)

Add a new message to the notes field.

calculate_quantity_usd_value(quantity)

Calculate value of asset amount using the latest known price.

calculate_value_using_price(token_price, ...)

Calculate the value of this position using the given prices.

can_be_closed([epsilon])

There are no tied tokens in this position.

from_dict(kvs, *[, infer_missing])

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

get_available_trading_quantity()

Get token quantity still availble for the trades in this strategy cycle.

get_average_buy()

Calculate average buy price.

get_average_price()

The average price paid for all assets on the long or short side.

get_average_sell()

Calculate average buy price.

get_balance_update_events()

Iterate over all balance update events.

get_balance_update_quantity()

Get quantity of all balance udpdates for this position.

get_buy_quantity()

How many units we have bought total

get_buy_value()

Get the total value of the position when it was bought.

get_capital_tied_at_open_pct()

Calculate how much portfolio capital was risk when this position was opened.

get_closing_price()

Get the price when the position was closed.

get_current_price()

Get the price of the base asset based on the latest valuation.

get_duration()

How long this position was held.

get_equity_for_position()

How many asset units this position tolds.

get_executed_trades()

get_failed_trades()

Get all trades that have failed in the execution.

get_first_trade()

Get the first trade for this position.

get_freeze_reason()

Return the revert reason why this position is frozen.

get_human_readable_name()

How to refer this position in log output.

get_identifier()

One trading pair may have multiple open positions at the same time.

get_last_trade()

Get the the last trade for this position.

get_last_tx_hash()

Get the latest transaction performed for this position.

get_loss_risk_at_open()

What is the maximum risk of this position.

get_loss_risk_at_open_pct()

What is the maximum risk of this position.

get_max_size()

Get the largest size of this position over the time

get_name()

Get human readable name for this position

get_net_quantity()

The difference in the quantity of assets bought and sold to date.

get_opening_price()

Get the price when the position was opened.

get_orignal_stop_loss()

Get the original stop loss value when this position was opened.

get_price_at_open()

Get the price of the position at open.

get_quantity()

Get the tied up token quantity in all successfully executed trades.

get_quantity_at_open()

Get the quanaity of the asset the position at open.

get_quantity_unit_name()

Get the unit name we label the quantity in this position

get_realised_profit_percent()

Calculated life-time profit over this position.

get_realised_profit_usd()

Calculates the profit & loss (P&L) that has been 'realised' via two opposing asset transactions in the Position to date.

get_sell_quantity()

How many units we have sold total

get_sell_value()

Get the total value of the position when it was sold.

get_size_relative_realised_profit_percent()

Calculated life-time profit over this position.

get_successful_trades()

Get all trades that have been successfully executed and contribute to this position

get_total_bought_usd()

How much money we have used on buys

get_total_lp_fees_paid()

Get the total amount of swap fees paid in the position.

get_total_profit_at_timestamp(timestamp)

Get the profit of the position what it was at a certain point of time.

get_total_profit_percent()

How much % we have made profit so far.

get_total_profit_usd()

Realised + unrealised profit.

get_total_sold_usd()

How much money we have received on sells

get_trade_count()

Get the number of trades in this position.

get_trades_by_strategy_cycle(timestamp)

Get all trades made for this position at a specific time.

get_unexeuted_reserve()

Get the reserve currency allocated for trades.

get_unrealised_profit_usd()

Calculate the position unrealised profit.

get_value()

Get the position value using the latest revaluation pricing.

get_value_at_close()

How much the position had value tied after its close.

get_value_at_open()

How much the position had value tied after its open.

has_automatic_close()

This position has stop loss/take profit set.

has_bad_data_issues()

Do we have legacy / incompatible data issues.

has_buys()

Does is position have any spot buys.

has_executed_trades()

This position represents actual holdings and has executed trades on it.

has_planned_trades()

has_sells()

Does is position have any spot sells.

has_trade(trade)

Check if a trade belongs to this position.

has_trigger_conditions()

Does this position need to check for stop loss/take profit.

has_unexecuted_trades()

is_closed()

This position has been closed and does not have any capital tied to it.

is_frozen()

This position has had a failed trade and can no longer be automatically moved around.

is_long()

Is this position long on the underlying base asset.

is_loss()

This position is currently having non-zero losses.

is_open()

This is an open trading position.

is_profitable()

This position is currently having non-zero profit.

is_repaired()

This position was frozen, but its trades were successfully repaired.

is_short()

Is this position short on the underlying base asset.

is_stop_loss()

Was this position ended with stop loss trade

is_stop_loss_closed()

Did this position close with stop loss.

is_take_profit()

Was this position ended with take profit trade

is_take_profit_closed()

Did this position close with trake profit.

is_trailing_stop_loss()

Was this position ended with a trailing stop loss trade.

is_unfrozen()

This position was frozen, but its trades were successfully repaired.

open_trade(strategy_cycle_at, trade_id, ...)

Open a new trade on position.

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

set_revaluation_data(last_pricing_at, ...)

to_dict([encode_json])

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

Attributes

position_id

Runnint int counter primary key for positions

pair

Trading pair this position is trading

opened_at

When this position was opened

last_pricing_at

When was the last time this position was (re)valued

last_token_price

Last valued price for the base token.

last_reserve_price

reserve_currency

Which reserve currency we are going to receive when we sell the asset

trades

List of trades taken for this position.

closed_at

When this position was closed

frozen_at

Timestamp when this position was moved to a frozen state.

unfrozen_at

Timestamp when this position was marked lively again

last_trade_at

When this position had a trade last time

portfolio_value_at_open

Record the portfolio value when the position was opened.

stop_loss

Trigger a stop loss if this price is reached,

take_profit

Trigger a take profit if this price is reached

trailing_stop_loss_pct

Trailing stop loss.

notes

Human readable notes about this trade

balance_updates

All balance updates that have touched this reserve position.

trigger_updates

Trigger updates are stored oldest first.

position_id: int#

Runnint int counter primary key for positions

pair: TradingPairIdentifier#

Trading pair this position is trading

opened_at: datetime#

When this position was opened

Strategy tick time.

last_pricing_at: datetime#

When was the last time this position was (re)valued

last_token_price: float#

Last valued price for the base token.

There are two ways to receive this

  • When the position is opened, set to the initial buy price

  • When the position is revalued, set to the sell price of the position

Note that this might be initially incorrect, if revaluation has not been done yet, because the buy price != sell price.

reserve_currency: AssetIdentifier#

Which reserve currency we are going to receive when we sell the asset

trades: Dict[int, TradeExecution]#

List of trades taken for this position. trade_id -> Trade map

closed_at: Optional[datetime]#

When this position was closed

frozen_at: Optional[datetime]#

Timestamp when this position was moved to a frozen state.

This can happen multiple times, so is is the last time when this happened.

See also unfrozen_at.

unfrozen_at: Optional[datetime]#

Timestamp when this position was marked lively again

Set by tradeexecutor.state.repair when the position trades are repaired and the position is moved to open or closed list.

last_trade_at: Optional[datetime]#

When this position had a trade last time

portfolio_value_at_open: Optional[float]#

Record the portfolio value when the position was opened.

This can be later used to analyse the risk of the trades. (“Max value at the risk”)

stop_loss: Optional[float]#

Trigger a stop loss if this price is reached,

We use mid-price as the trigger price.

take_profit: Optional[float]#

Trigger a take profit if this price is reached

We use mid-price as the trigger price.

trailing_stop_loss_pct: Optional[float]#

Trailing stop loss.

For details see Trailing stop loss.

Set the trailing stop as the percentage of the market price. This will update stop_loss price if the new resulting stop_loss will be higher as the previous one.

Percents as the relative to the the market price, e.g. for 10% trailing stop loss set this value for 0.9.

Calculated as stop_loss = mid_price trailing_stop_loss_pct.

Updated by tradeexecutor.strategy.stop_loss.check_position_triggers(). For any updates you can read trigger_updates.

notes: Optional[str]#

Human readable notes about this trade

Special case; not worth to display unless the field is filled in.

  • May contain multiple newline separated messages

  • Used to mark test trades from command line.

  • Used to add log information abotu frozen and unfrozen positions

balance_updates: Dict[int, BalanceUpdate]#

All balance updates that have touched this reserve position.

Generated by tradeexecutor.strategy.sync_model.SyncModel.

BalanceUpdate.id -> BalanceUpdate mapping

trigger_updates: List[TriggerPriceUpdate]#

Trigger updates are stored oldest first.

get_human_readable_name()[source]#

How to refer this position in log output.

Return type:

str

is_open()[source]#

This is an open trading position.

Return type:

bool

is_closed()[source]#

This position has been closed and does not have any capital tied to it.

Return type:

bool

is_frozen()[source]#

This position has had a failed trade and can no longer be automatically moved around.

After the position is unfrozen the flag goes away.

Return type:

bool

is_unfrozen()[source]#

This position was frozen, but its trades were successfully repaired.

Return type:

bool

is_repaired()[source]#

This position was frozen, but its trades were successfully repaired.

Alias for is_unfrozen().

Return type:

bool

has_automatic_close()[source]#

This position has stop loss/take profit set.

Return type:

bool

get_first_trade()[source]#

Get the first trade for this position.

Considers unexecuted trades.

Return type:

TradeExecution

get_last_trade()[source]#

Get the the last trade for this position.

Considers unexecuted and failed trades.

Return type:

TradeExecution

is_long()[source]#

Is this position long on the underlying base asset.

We consider the position long if the first trade is buy.

Return type:

bool

is_short()[source]#

Is this position short on the underlying base asset.

Return type:

bool

is_stop_loss()[source]#

Was this position ended with stop loss trade

Return type:

bool

is_trailing_stop_loss()[source]#

Was this position ended with a trailing stop loss trade.

  • Position was terminated with a stop loss

  • Trailing stop loss was set

  • Trailing stop loss was updated at least once

Return type:

bool

is_take_profit()[source]#

Was this position ended with take profit trade

Return type:

bool

is_profitable()[source]#

This position is currently having non-zero profit.

is_loss()[source]#

This position is currently having non-zero losses.

has_executed_trades()[source]#

This position represents actual holdings and has executed trades on it.

This will return false for positions that are still planned or have zero successful trades.

Return type:

bool

has_trigger_conditions()[source]#

Does this position need to check for stop loss/take profit.

Return type:

bool

get_name()[source]#

Get human readable name for this position

Return type:

str

get_quantity_unit_name()[source]#

Get the unit name we label the quantity in this position

Return type:

str

get_balance_update_events()[source]#

Iterate over all balance update events.

Balance updates describe external events affecting the balance of this position: the update was not triggered by the trade executor itself.

  • Deposits

  • Redemptions

  • Account corrections

  • Trades are not included here

Return type:

Iterable[BalanceUpdate]

get_balance_update_quantity()[source]#

Get quantity of all balance udpdates for this position.

Returns:

How much in-kind redemption events have affected this position.

Decimal zero epsilon noted.

Return type:

Decimal

get_quantity()[source]#

Get the tied up token quantity in all successfully executed trades.

  • Does not account for trades that are currently being executed.

  • Does some fixing for rounding errors in the form of epsilon checks

  • Accounts for any balance update events (redemptions, interest, accounting corrections)

Returns:

Number of asset units held by this position.

Rounded down to zero if the sum of

Return type:

Decimal

get_available_trading_quantity()[source]#

Get token quantity still availble for the trades in this strategy cycle.

This includes

  • All executed trades

  • All planned trades for this cycle that have already reduced/increased amounts for this position

This gives you remaining token balance, even if there are some earlier sell orders that have not been executed yet.

Return type:

Decimal

get_current_price()[source]#

Get the price of the base asset based on the latest valuation.

Return type:

float

get_opening_price()[source]#

Get the price when the position was opened.

Return type:

float

get_closing_price()[source]#

Get the price when the position was closed.

Return type:

float

get_equity_for_position()[source]#

How many asset units this position tolds.

TODO: Remove this

Alias for get_quantity()

Return type:

Decimal

get_identifier()[source]#

One trading pair may have multiple open positions at the same time.

Return type:

str

get_successful_trades()[source]#

Get all trades that have been successfully executed and contribute to this position

Return type:

List[TradeExecution]

get_failed_trades()[source]#

Get all trades that have failed in the execution.

Return type:

List[TradeExecution]

calculate_value_using_price(token_price, reserve_price)[source]#

Calculate the value of this position using the given prices.

Parameters:
  • token_price (float) –

  • reserve_price (float) –

Return type:

float

get_value()[source]#

Get the position value using the latest revaluation pricing.

If the position is closed, the value should be zero.

Return type:

float

get_trades_by_strategy_cycle(timestamp)[source]#

Get all trades made for this position at a specific time.

Returns:

Iterable of 0….N trades

Parameters:

timestamp (datetime) –

Return type:

Iterable[TradeExecution]

get_unexeuted_reserve()[source]#

Get the reserve currency allocated for trades.

Assumes position can only have one reserve currency.

Only spot buys can have unexecuted reserve.

Returns:

Amount of capital we have allocated in trades that did not correctly execute

Return type:

Decimal

is_stop_loss_closed()[source]#

Did this position close with stop loss.

Return type:

bool

is_take_profit_closed()[source]#

Did this position close with trake profit.

Return type:

bool

open_trade(strategy_cycle_at, trade_id, quantity, reserve, assumed_price, trade_type, reserve_currency, reserve_currency_price, pair_fee=None, lp_fees_estimated=None, planned_mid_price=None, price_structure=None, slippage_tolerance=None)[source]#

Open a new trade on position.

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

Parameters:
  • strategy_cycle_at (datetime.datetime | None) –

    The strategy cycle timestamp for which this trade was executed.

    Might not be available for the accounting corrections done offline.

  • trade_id (int) – 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.

  • 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.

  • 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.

  • slippage_tolerance (Optional[float]) –

    Slippage tolerance for this trade.

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

  • reserve_currency_price (float) –

Return type:

TradeExecution

has_trade(trade)[source]#

Check if a trade belongs to this position.

Parameters:

trade (TradeExecution) –

has_buys()[source]#

Does is position have any spot buys.

Return type:

bool

has_sells()[source]#

Does is position have any spot sells.

Return type:

bool

can_be_closed(epsilon=0.0001)[source]#

There are no tied tokens in this position.

Perform additional check for token amount dust caused by rounding errors.

Return type:

bool

get_total_bought_usd()[source]#

How much money we have used on buys

Return type:

float

get_total_sold_usd()[source]#

How much money we have received on sells

Return type:

float

get_buy_quantity()[source]#

How many units we have bought total

Return type:

Decimal

get_sell_quantity()[source]#

How many units we have sold total

Return type:

Decimal

get_net_quantity()[source]#

The difference in the quantity of assets bought and sold to date.

Return type:

Decimal

get_average_buy()[source]#

Calculate average buy price.

Returns:

None if no buys

Return type:

Optional[float]

get_average_sell()[source]#

Calculate average buy price.

Returns:

None if no sells

Return type:

Optional[float]

get_price_at_open()[source]#

Get the price of the position at open.

Include only the first trade that opened the position. Calculate based on the executed price.

Return type:

float

get_quantity_at_open()[source]#

Get the quanaity of the asset the position at open.

Include only the first trade that opened the position. Calculate based on the executed price.

Return type:

Decimal

get_average_price()[source]#

The average price paid for all assets on the long or short side.

Returns:

None if no executed trades

Return type:

Optional[float]

get_realised_profit_usd()[source]#

Calculates the profit & loss (P&L) that has been ‘realised’ via two opposing asset transactions in the Position to date.

Returns:

profit in dollar or None if no opposite trade made

Return type:

Optional[float]

get_unrealised_profit_usd()[source]#

Calculate the position unrealised profit.

Calculates the profit & loss (P&L) that has yet to be ‘realised’ in the remaining non-zero quantity of assets, due to the current market price.

Returns:

profit in dollar

Return type:

float

get_total_profit_usd()[source]#

Realised + unrealised profit.

Return type:

float

get_total_profit_percent()[source]#

How much % we have made profit so far.

Returns:

0 if profit calculation cannot be made yet

Return type:

float

get_total_profit_at_timestamp(timestamp)[source]#

Get the profit of the position what it was at a certain point of time.

Include realised and unrealised profit.

Parameters:

timestamp (datetime) – Include all traeds before and including at this timestamp.

Return type:

float

get_freeze_reason()[source]#

Return the revert reason why this position is frozen.

Get the revert reason of the last blockchain transaction, assumed to be swap, for this trade.

If this position has been unfrozen, then return the last freeze reason.

Returns:

Revert message (cleaned) or None

Return type:

Optional[str]

get_last_tx_hash()[source]#

Get the latest transaction performed for this position.

It’s the tx of the trade that was made for this position.

TODO: Deprecate

Return type:

Optional[str]

get_value_at_open()[source]#

How much the position had value tied after its open.

Calculate the value after the first trade.

Return type:

float

get_value_at_close()[source]#

How much the position had value tied after its close.

Calculate the value after the last trade

Return type:

float

get_capital_tied_at_open_pct()[source]#

Calculate how much portfolio capital was risk when this position was opened.

  • This is based on the opening values, any position adjustment after open is ignored

  • Assume capital is tied to the position and we can never release it.

  • Assume no stop loss is used, or it cannto be trigged

See also get_loss_risk_at_open_pct().

Returns:

Percent of the portfolio value

Return type:

float

get_loss_risk_at_open()[source]#

What is the maximum risk of this position.

The maximum risk is the amount of portfolio we can lose at one position. It is calculated as position stop loss / position total size. We assume stop losses always trigged perfectly and we do not lose (too much) on the stop loss trigger.

Returns:

Dollar value of the risked capital

Return type:

float

get_loss_risk_at_open_pct()[source]#

What is the maximum risk of this position.

Risk relative to the portfolio size.

See also get_loss_risk_at_open_pct().

Returns:

Percent of total portfolio value

Return type:

float

get_realised_profit_percent()[source]#

Calculated life-time profit over this position.

Calculate how many percent profit this position made, relative to all trades taken over the life time of the position.

See Profitability calculations for more details.

Returns:

If the position made 1% profit returns 1.01.

Return type:

float

get_size_relative_realised_profit_percent()[source]#

Calculated life-time profit over this position.

Calculate how many percent this profit made profit, adjusted to the position size compared to the available strategy equity at the opening of the position.

This is mostly useful to calculate the strategy performance independent of funding deposits and redemptions.

See Profitability calculations for more details.

Returns:

If the position made 1% profit returns 1.01.

Return type:

float

get_duration()[source]#

How long this position was held. :return: None if the position is still open

Return type:

datetime.timedelta | None

get_total_lp_fees_paid()[source]#

Get the total amount of swap fees paid in the position. Includes all trades.

Return type:

float

get_buy_value()[source]#

Get the total value of the position when it was bought.

Return type:

float

get_sell_value()[source]#

Get the total value of the position when it was sold.

Return type:

float

has_bad_data_issues()[source]#

Do we have legacy / incompatible data issues.

Return type:

bool

get_max_size()[source]#

Get the largest size of this position over the time

Return type:

float

get_trade_count()[source]#

Get the number of trades in this position.

Return type:

int

get_orignal_stop_loss()[source]#

Get the original stop loss value when this position was opened.

Setting trailing_stop_loss will cause stop_loss to be updated. We can still fetch the original stop loss from trigger_updates.

Returns:

The original dollar price of the stop loss

Return type:

Optional[float]

calculate_quantity_usd_value(quantity)[source]#

Calculate value of asset amount using the latest known price.

Parameters:

quantity (Decimal) –

Return type:

float

add_notes_message(msg)[source]#

Add a new message to the notes field.

Messages are newline separated.

Parameters:

msg (str) –

add_balance_update_event(event)[source]#

Include a new balance update event

Raises:

BalanceUpdateEventAlreadyAdded – In the case of a duplicate and event id is already used.

Parameters:

event (BalanceUpdate) –

__init__(position_id, pair, opened_at, last_pricing_at, last_token_price, last_reserve_price, reserve_currency, trades=<factory>, closed_at=None, frozen_at=None, unfrozen_at=None, last_trade_at=None, portfolio_value_at_open=None, stop_loss=None, take_profit=None, trailing_stop_loss_pct=None, notes=None, balance_updates=<factory>, trigger_updates=<factory>)#
Parameters:
Return type:

None