TradingPosition#

API documentation for 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>, valuation_updates=<factory>, loan=None, liquidation_price=None)#
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_accrued_interest_quantity(asset)

Calculate the gained interest in tokens.

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()

There are no tied tokens in this position.

from_dict(kvs, *[, infer_missing])

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

get_accrued_interest()

Get the USD value of currently net accrued interest for this position so far.

get_accrued_interest_with_repayments()

Return the net from collateral and borrowed interest plus their interest payments.

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_base_token_balance_update_quantity()

Get quantity of all balance updates for this position.

get_borrowed()

Get the amount of outstanding loans we have.

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_claimed_interest()

How much interest we have claimed from this position and moved back to reserves.

get_closing_price()

Get the price when the position was closed.

get_collateral()

Get the amount of outstanding loans we have.

get_current_price()

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

get_debug_dump()

Return class contents for logging.

get_duration()

How long this position was held.

get_equity()

Get equity tied to this position.

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_held_assets()

Get all assets on-chain wallet should hold for this position.

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_last_updated_at()

When did we update this position last time.

get_loan_based_nav([include_interest, ...])

Calculate net asset value (NAV) for a loan based 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 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_original_planned_price()

Get the US-dollar price for a position that does not have any executed price.

get_orignal_stop_loss()

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

get_price_at_open()

Legacy.

get_profit_timeline_timestamp()

Where to place this position on a profit timeline.

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_old()

How many asset units this position tolds.

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([include_interest])

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

get_redeemed()

Get amount of position reduced via in-kind redemptions.

get_repaid_interest()

How much interest payments we have made in total.

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_profit_percent()

Calculated life-time profit over this position.

get_size_relative_realised_profit_percent()

Calculated life-time profit over this position.

get_size_relative_unrealised_or_realised_profit_percent()

Calculated life-time profit over this position, including unrealised PnL.

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_and_realised_profit_percent([...])

Calculated unrealised PnL for this position.

get_unrealised_profit_pct()

Get the current profit of this position, minus any netflow.

get_unrealised_profit_usd([...])

Calculate the position unrealised profit.

get_value([include_interest])

Get the current net asset value of this position.

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_credit_supply()

This is a trading position for gaining interest by lending out reserve currency.

is_frozen()

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

is_leverage()

Is this leveraged/loan backed position.

is_loan_based()

The profit for this trading pair is loan based..

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_properly_opened()

Did we manage to open this position correctly.

is_reduced()

Is any of the position closed.

is_repaired()

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

is_short()

Is this position short on the underlying base asset.

is_spot()

Is this a spot market position.

is_spot_market()

Alias for is_spot().

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_test()

The position was opened and closed by perform-test-trade command.

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.

revalue_base_asset(last_pricing_at, ...)

Update position token prices.

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

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

1.0 for stablecoins, unless out of peg, in which case can be 0.99

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.

valuation_updates

Trigger updates are stored oldest first.

loan

The loan underlying the position leverage or credit supply.

liquidation_price

What is the liquidation price for this position.

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.

last_reserve_price: float#

1.0 for stablecoins, unless out of peg, in which case can be 0.99

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

Execution time of the trade or wall-clock time if not available.

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.

Note

This should not be updated directly, but via tradeexecutor.strategy.pandas_trader.position_manager.update_stop_loss().

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

There is no record made if there are no trigger updates change. For example, for trailing stop loss, there is no record added, if the price did not move upwards, causing the stop loss level to move.

valuation_updates: List[ValuationUpdate]#

Trigger updates are stored oldest first.

See also last_token_price and last_pricing_at legacy attributes.

loan: Optional[Loan]#

The loan underlying the position leverage or credit supply.

Applicable for

  • short/long positions using lending protocols

  • credit supply (collateral without borrow)

This reflects the latest tradeexecutor.state.trade.TradeExecution.executed_loan of a successful trade. This object is updated with accrued interest information from on-chain data outside trades. If the position does not have successfully executed trades yet, this is None.

liquidation_price: float | None#

What is the liquidation price for this position. If the price goes below this, the position is liquidated.

Applicable for

  • short/long positions using lending protocols

TODO: When this is set and when this is updated.

get_human_readable_name()[source]#

How to refer this position in log output.

Return type:

str

get_debug_dump()[source]#

Return class contents for logging.

Returns:

Indented JSON-like content

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.

See also is_reduced():

Return type:

bool

is_test()[source]#

The position was opened and closed by perform-test-trade command.

The trade and the position should not be counted in the statistics.

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_spot()[source]#

Is this a spot market position.

Return type:

bool

is_long()[source]#

Is this position long on the underlying base asset.

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

This includes spot buy.

Return type:

bool

is_short()[source]#

Is this position short on the underlying base asset.

Return type:

bool

is_leverage()[source]#

Is this leveraged/loan backed position.

Return type:

bool

is_loan_based()[source]#

The profit for this trading pair is loan based..

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_credit_supply()[source]#

This is a trading position for gaining interest by lending out reserve currency.

is_spot_market()[source]#

Alias for is_spot().

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_base_token_balance_update_quantity()[source]#

Get quantity of all balance updates for this position.

  • How much non-trade events have changed our base token balance

  • This includes interest events and accounting corrections

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 (in started, or planned state).

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

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

For interest positions

  • The underlying principle is calculated as sum of trades e.g. how many deposit or redemption trades we did for Aave reserves

  • The accrued interest can be read from balance update events

Returns:

Number of asset units held by this position.

Rounded down to zero if the sum of

Return type:

Decimal

get_redeemed()[source]#

Get amount of position reduced via in-kind redemptions.

  • Also include any other account corrections

Alias for get_base_token_balance_update_quantity()

Returns:

A negative number, the amount of quantiy redeemed from this position

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.

Returns:

Get the executed opening price of the position.

If the first trade was not success, return 0.0.

Return type:

float

get_closing_price()[source]#

Get the price when the position was closed.

Return type:

float

get_quantity_old()[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, include_interest=True)[source]#

Calculate the value of this position using the given prices.

Parameters:
  • token_price (float) –

  • reserve_price (float) –

Return type:

float

get_equity()[source]#

Get equity tied to this position.

TODO: Use TradingPosition.loan.get_net_asset_value() for collateral based positions.

Returns:

How much equity we have tied in this position.

TODO: Does not work for collateral positions.

Return type:

float

get_value(include_interest=True)[source]#

Get the current net asset value of this position.

If the position is closed, the value should be zero

Note

This is the planned value, so may be different fr om the executed value.

Parameters:

include_interest

Include accrued interest in the valuation.

This will add any interest earned/lost in loans, plus their repayments.

Returns:

The value of the position if any remaining open amount would be completely closed/unwind.

Return type:

float

get_loan_based_nav(include_interest=True, include_fees=True)[source]#

Calculate net asset value (NAV) for a loan based position.

Parameters:
  • include_interest – Should interest should be included in the NAV

  • include_fees – TODO

Returns:

Zero if this position is not yet opened.

When the first trade of position is executed, loan attribute becomes available.

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

is_properly_opened()[source]#

Did we manage to open this position correctly.

Returns:

True if the opening trade was correctly executed.

Might also return False for legacy data

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, portfolio_value_at_creation=None, leverage=None, closing=False, planned_collateral_consumption=None, planned_collateral_allocation=None, exchange_name=None, flags=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.

  • portfolio_value_at_creation (Optional[float]) –

    Record the portfolio’s value when this posistion was opened.

    Will be later used for risk metrics calculations and such.

  • flags (Optional[Set[TradeFlag]]) – Flags set on the trade.

  • reserve_currency_price (float) –

  • leverage (Optional[float]) –

  • closing (Optional[bool]) –

  • planned_collateral_consumption (Optional[Decimal]) –

  • planned_collateral_allocation (Optional[Decimal]) –

  • exchange_name (Optional[str]) –

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()[source]#

There are no tied tokens in this position.

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

Return type:

bool

get_last_updated_at()[source]#

When did we update this position last time.

  • What was the last timestamp when this position data was mutated

Returns:

UTC time

Return type:

datetime

get_profit_timeline_timestamp()[source]#

Where to place this position on a profit timeline.

  • If the position is closed, place it at its closing data

Returns:

UTC time

Return type:

datetime

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.

Note

To be deprecated. Please use :py:method:`get_quantity` instead.

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 sell trades that would have completed successfully

Return type:

Optional[float]

get_price_at_open()[source]#

Legacy.

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]

is_reduced()[source]#

Is any of the position closed.

The position is reduced towards close if it contains opposite trades.

See also is_closed().

Return type:

bool

get_realised_profit_usd(include_interest=True)[source]#

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

  • Profit is calculated as the diff of avg buy and sell price times quantity

  • Any avg buy and sell contains all fees we have paid in included in the price, so we do not need to add them to profit here

  • See also get_realised_profit_percent().

  • Always returns zero for frozen positions

Note

This function does not account for in-kind redemptions or any other account corrections. Please use get_realised_profit_percent() if possible.

Parameters:

include_interest – Include any accrued interest in PnL.

Returns:

Profit in dollar.

None if the position lacks any realised profit (contains only unrealised).

Return type:

Optional[float]

get_unrealised_profit_usd(include_interest=True, account_redemptions=True)[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.

Parameters:
  • include_interest – The interest accrued on this position is includedin the result

  • account_redemptions – Any in-kind redemptions are reduced from the net euqantity.

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.

TODO: Legacy method. Use get_unrealised_and_realised_profit_percent() instead.

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]

revalue_base_asset(last_pricing_at, last_token_price)[source]#

Update position token prices.

TODO: Legacy. See valuation_updates.

Parameters:
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 also

See Profitability calculations for more details.

Returns:

If the position made 1% profit returns 0.01.

Return 0 if the position profitability cannot be calculated, e.g. due to broken trades.

Return type:

float

get_unrealised_and_realised_profit_percent(valuation_price=None, include_unrealised=True)[source]#

Calculated unrealised PnL for this position.

This is an estimation of the profit % assuming the position would be completely closed with the current price.

  • This function accounts for in-kind redemptions affecting the position

  • Currently only long positions supportd

See also

Parameters:
  • valuation_price – Valuate the unrealised portion of tokens at this price

  • include_unrealised – Include the unrealised PnL as the part of the result

Returns:

The profitability of this position currently.

Return 0.05 for a position that is 5% in profit.

Return 0 if you ask for realised profit and none of the position is yet closed.

Return type:

float

get_unrealised_profit_pct()[source]#

Get the current profit of this position, minus any netflow.

  • Calculate based on avg buy and sell

  • For the unrealised portion, calculate the expected close

See also

Returns:

Estimated position profit in percet, based on avg trade prices

Return type:

float

get_size_relative_realised_profit_percent()[source]#

Calculated life-time profit over this position.

The profit is scaled to the % of the position size relative to the portfolio to account for max capital allocation for the position.

  • TODO: This does not work for positions that have capital added over time

See Profitability calculations for more details.

Returns:

If the 50% aloocation position made 1% profit returns 1.005.

Return type:

float

get_size_relative_unrealised_or_realised_profit_percent()[source]#

Calculated life-time profit over this position, including unrealised PnL.

The profit is scaled to the % of the position size relative to the portfolio to account for max capital allocation for the position.

  • TODO: This does not work for positions that have capital added over time

  • TODO: Only correctly support unrealised PnL for spot

Returns:

If the 50% aloocation position made 1% profit returns 1.005.

Return type:

float

get_size_relative_profit_percent()[source]#

Calculated life-time profit over this position.

Both realised and unrealised profit.

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 time

NOTE: This metric doesn’t work for positions with more than 2 trades i.e: positions which have been increased and reduced in size

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]

get_original_planned_price()[source]#

Get the US-dollar price for a position that does not have any executed price.

  • The position was left in a broken state after the first trade failed to execute

  • We will still have the price from the first trade we thought we were going to get

  • Always use TradingPosition.last_token_price if available.

  • Applies to spot positions only

Returns:

PlannedUS dollar spot price of the first trade

Return type:

float

calculate_quantity_usd_value(quantity)[source]#

Calculate value of asset amount using the latest known price.

  • If we do not have price data, use the first planned trade

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) –

calculate_accrued_interest_quantity(asset)[source]#

Calculate the gained interest in tokens.

This is done as the sum of all interest events.

This is also denormalised as position.interest.accrued_interest.

Parameters:

asset (AssetIdentifier) – aToken/vToken for which we calculate the interest for

Returns:

Number of quote tokens this position has gained interest.

Return type:

Decimal

get_accrued_interest()[source]#

Get the USD value of currently net accrued interest for this position so far.

Get any unclaimed interest on this position. After position is closed, all remaining accrued interest is claimed.

See get_accrued_interest_with_repayments() to account any interest payments.

  • The accrued interest is included as the position accounting item until the position is completely closed

  • When the position is completed closed, the accured interest tokens are traded and moved to reserves

  • After position is closed calling get_accrued_interest() should return zero

TODO: This might not work correctly for partially closed positions.

Returns:

Net interest PnL in USD.

Positive if we have earned interest, negative if we have paid it.

Return type:

float

get_accrued_interest_with_repayments()[source]#

Return the net from collateral and borrowed interest plus their interest payments.

Return type:

float

get_claimed_interest()[source]#

How much interest we have claimed from this position and moved back to reserves.

See also

  • get_accrued_interest() for the life-time interest accumulation.

  • Loan.get_net_asset_value() for notes about loan interest tracking

Return type:

float

get_repaid_interest()[source]#

How much interest payments we have made in total.

See also

Return type:

float

get_borrowed()[source]#

Get the amount of outstanding loans we have.

Return type:

float

get_collateral()[source]#

Get the amount of outstanding loans we have.

Return type:

float

get_held_assets()[source]#

Get all assets on-chain wallet should hold for this position.

  • A position may hold multiple on-chain assets

  • Multiple positions can share the same on-chain asset

  • Any on-chain accrued interest is included in quantity

Returns:

Iterable (asset, quantity) tuples

Return type:

Iterable[Tuple[AssetIdentifier, Decimal]]

__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>, valuation_updates=<factory>, loan=None, liquidation_price=None)#
Parameters:
Return type:

None