Portfolio#
tradeexecutor.state.portfolio.Portfolio Python class in Trading Strategy framework.
- class Portfolio[source]#
Bases:
object
Represents a trading portfolio on DEX markets.
Multiple trading pair issue: We do not identify the actual assets we have purchased, but the trading pairs that we used to purchase them. Thus, each position marks “openness” in a certain trading pair. For example open position of WBNB-BUSD means we have bought X BNB tokens through WBNB-BUSD trading pair. But because this is DEX market, we could enter and exit through WBNB-USDT, WBNB-ETH, etc. and our position is not really tied to a trading pair. However, because all TradFi trading view the world through trading pairs, we keep the tradition here.
- __init__(next_position_id=1, next_trade_id=1, open_positions=<factory>, reserves=<factory>, closed_positions=<factory>, frozen_positions=<factory>)#
- Parameters:
next_position_id (int) –
next_trade_id (int) –
open_positions (Dict[int, TradingPosition]) –
reserves (Dict[str, ReservePosition]) –
closed_positions (Dict[int, TradingPosition]) –
frozen_positions (Dict[int, TradingPosition]) –
- Return type:
None
Methods
__init__
([next_position_id, next_trade_id, ...])adjust_reserves
(asset, amount)Remove currency from reserved.
check_for_nonce_reuse
(nonce)A helper assert to see we are not generating invalid transactions somewhere.
create_trade
(strategy_cycle_at, pair, ...[, ...])Create a trade.
find_position_for_trade
(trade)Find a position tha trade belongs for.
from_dict
(kvs, *[, infer_missing])from_json
(s, *[, parse_float, parse_int, ...])Get open, closed and frozen, positions.
Get all pairs for which we have or had positions.
Iterate through all trades: completed, failed and in progress
Get the value of the portfolio based on the latest pricing.
Get how much reserve stablecoins we have.
Gets the default reserve currency associated with this state.
get_equity_for_pair
(pair)Return how much equity allocation we have in a certain trading pair.
Get all positions with already executed trades.
Get a position by a trading pair smart contract address identifier.
Get first and last trades overall.
Get the value of trading positions that are frozen currently.
How much we invested at the beginning of a backtest.
Get the value of current trading positions plus unexecuted trades.
Get the value of current trading positions.
get_open_position_for_pair
(pair)Get currently open positions.
Return the current holdings in different trading pairs.
Return the current ownerships.
get_position_by_id
(position_id)Get any position open/closed/frozen by id.
Get open position by a trading pair smart contract address identifier.
Get positions that were closed at a specific timestamp.
get_reserve_position
(asset)Get the value of the portfolio based on the latest pricing.
get_trade_by_id
(trade_id)Look up any trade in all positions.
Get positions that have been repaired.
Get the profit of currently open positions.
Do we have any trades that have capital allocated, but not executed yet.
is_empty
()This portfolio has no open or past trades or any reserves.
move_capital_from_reserves_to_trade
(trade[, ...])Allocate capital from reserves to trade instance.
open_new_position
(ts, pair, assumed_price, ...)Opens a new trading position.
return_capital_to_reserves
(trade[, ...])Return capital to reserves after a sell.
revalue_positions
(ts, valuation_method[, ...])Revalue all open positions in the portfolio.
schema
(*[, infer_missing, only, exclude, ...])to_dict
([encode_json])to_json
(*[, skipkeys, ensure_ascii, ...])update_reserves
(new_reserves)Update current reserves.
Attributes
Each position gets it unique running counter id.
Each trade gets it unique id as a running counter.
Currently open trading positions
Currently held reserve assets Token address -> reserve position mapping.
Trades completed in the past
Positions that have failed sells, or otherwise immovable and need manual clean up.
- next_trade_id: int = 1#
Each trade gets it unique id as a running counter. Trade ids are unique across different positions.
- open_positions: Dict[int, TradingPosition]#
Currently open trading positions
- reserves: Dict[str, ReservePosition]#
Currently held reserve assets Token address -> reserve position mapping.
- closed_positions: Dict[int, TradingPosition]#
Trades completed in the past
- frozen_positions: Dict[int, TradingPosition]#
Positions that have failed sells, or otherwise immovable and need manual clean up. Failure reasons could include - blockchain halted - ERC-20 token tax fees - rug pull token - transfer disabled
- get_position_by_id(position_id)[source]#
Get any position open/closed/frozen by id.
Always assume the position for a position_id exists.
- Parameters:
position_id (int) – Internal running counter id for the position inside this portfolio.
- Returns:
Always returns
- Throw:
Fails with py:class:AssertionError if there is no such position.
- Return type:
- get_trade_by_id(trade_id)[source]#
Look up any trade in all positions.
Note
Slow lookup. Only designed for testing.
- Returns:
Found trade or
- Parameters:
trade_id (int) –
- Return type:
- get_executed_positions()[source]#
Get all positions with already executed trades.
Ignore positions that are still pending - they have only planned trades.
- Return type:
- get_open_quantities_by_position_id()[source]#
Return the current ownerships.
Keyed by position id -> quantity.
- get_open_quantities_by_internal_id()[source]#
Return the current holdings in different trading pairs.
Keyed by trading pair internal id -> quantity.
- open_new_position(ts, pair, assumed_price, reserve_currency, reserve_currency_price)[source]#
Opens a new trading position.
Marks the position opened.
Does not add any trades yet
Marks the current value of the portfolio at the trade opening time, as we need to use this for the risk calculations
- Parameters:
ts (datetime) –
pair (TradingPairIdentifier) –
assumed_price (float) –
reserve_currency (AssetIdentifier) –
reserve_currency_price (float) –
- Return type:
- get_position_by_trading_pair(pair)[source]#
Get open position by a trading pair smart contract address identifier.
For Uniswap-likes we use the pool address as the persistent identifier for each trading pair.
- Parameters:
pair (TradingPairIdentifier) –
- Return type:
- get_existing_open_position_by_trading_pair(pair)[source]#
Get a position by a trading pair smart contract address identifier.
The position must have already executed trades (cannot be planned position(.
- Parameters:
pair (TradingPairIdentifier) –
- Return type:
- get_positions_closed_at(ts)[source]#
Get positions that were closed at a specific timestamp.
Useful to display closed positions after the rebalance.
- Parameters:
ts (datetime) –
- Return type:
- 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)[source]#
Create a trade.
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) – 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.
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.
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 repair trades.
pair (TradingPairIdentifier) –
reserve_currency_price (float) –
- Returns:
Tuple of entries
Trade position (old/new)
New trade
True if a a new position was opened
- Return type:
- get_frozen_position_equity()[source]#
Get the value of trading positions that are frozen currently.
- Return type:
- get_live_position_equity()[source]#
Get the value of current trading positions plus unexecuted trades.
- Return type:
- get_total_equity()[source]#
Get the value of the portfolio based on the latest pricing.
This is
Value of the positions
plus
Cash in the hand
- Return type:
- get_closed_profit_usd()[source]#
Get the value of the portfolio based on the latest pricing.
- Return type:
- get_equity_for_pair(pair)[source]#
Return how much equity allocation we have in a certain trading pair.
- Parameters:
pair (TradingPairIdentifier) –
- Return type:
- adjust_reserves(asset, amount)[source]#
Remove currency from reserved.
For internal accounting of the portfolio state.
- Parameters:
asset (AssetIdentifier) – Reserve asset
amount (Decimal) – Negative to reduce portfolio reserves, positive to increase
- move_capital_from_reserves_to_trade(trade, underflow_check=True)[source]#
Allocate capital from reserves to trade instance.
Total equity of the porfolio stays the same.
- Parameters:
trade (TradeExecution) –
- return_capital_to_reserves(trade, underflow_check=True)[source]#
Return capital to reserves after a sell.
- Parameters:
trade (TradeExecution) –
- has_unexecuted_trades()[source]#
Do we have any trades that have capital allocated, but not executed yet.
- Return type:
- update_reserves(new_reserves)[source]#
Update current reserves.
Overrides current amounts of reserves.
E.g. in the case users have deposited more capital.
- Parameters:
new_reserves (List[ReservePosition]) –
- check_for_nonce_reuse(nonce)[source]#
A helper assert to see we are not generating invalid transactions somewhere.
- Raise:
AssertionError
- Parameters:
nonce (int) –
- revalue_positions(ts, valuation_method, revalue_frozen=True)[source]#
Revalue all open positions in the portfolio.
Reserves are not revalued.
- get_default_reserve_currency()[source]#
Gets the default reserve currency associated with this state.
For strategies that use only one reserve currency. This is the first in the reserve currency list.
- Returns:
Tuple (Reserve currency asset, its latest US dollar exchanage rate)
- Return type:
- get_all_trades()[source]#
Iterate through all trades: completed, failed and in progress
- Return type:
- get_initial_deposit()[source]#
How much we invested at the beginning of a backtest.
Assumes we track the performance against the US dollar
Assume there has been only one deposit event
This deposit happened at the start of the backtest
- __init__(next_position_id=1, next_trade_id=1, open_positions=<factory>, reserves=<factory>, closed_positions=<factory>, frozen_positions=<factory>)#
- Parameters:
next_position_id (int) –
next_trade_id (int) –
open_positions (Dict[int, TradingPosition]) –
reserves (Dict[str, ReservePosition]) –
closed_positions (Dict[int, TradingPosition]) –
frozen_positions (Dict[int, TradingPosition]) –
- Return type:
None