Skip to content

Commit

Permalink
[PortfolioValue] Migrate to PortfolioValueHolder
Browse files Browse the repository at this point in the history
  • Loading branch information
Herklos committed Sep 15, 2020
1 parent 9e44c4f commit ec4c514
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 83 deletions.
2 changes: 1 addition & 1 deletion octobot_trading/api/portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def get_portfolio_currency(exchange_manager, currency, portfolio_type=PORTFOLIO_


def get_origin_portfolio(exchange_manager) -> dict:
return exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.origin_portfolio.portfolio
return exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.origin_portfolio.portfolio


async def refresh_real_trader_portfolio(exchange_manager) -> bool:
Expand Down
4 changes: 2 additions & 2 deletions octobot_trading/api/profitability.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ def get_profitability_stats(exchange_manager) -> tuple:


def get_origin_portfolio_value(exchange_manager) -> float:
return exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.portfolio_origin_value
return exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.portfolio_origin_value


def get_current_portfolio_value(exchange_manager) -> float:
return exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.portfolio_current_value
return exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.portfolio_current_value


def get_current_holdings_values(exchange_manager) -> float:
Expand Down
4 changes: 2 additions & 2 deletions octobot_trading/consumers/abstract_mode_consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ async def can_create_order(self, symbol, state):
return False

async def get_holdings_ratio(self, currency):
return self.exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager \
return self.exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder \
.get_currency_holding_ratio(currency)

def get_number_of_traded_assets(self):
return len(self.exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager
return len(self.exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder
.origin_crypto_currencies_values)


Expand Down
4 changes: 2 additions & 2 deletions octobot_trading/portfolios/portfolio_manager.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from octobot_trading.portfolios.portfolio cimport Portfolio
from octobot_trading.portfolios.portfolio_profitability cimport PortfolioProfitability
from octobot_trading.exchanges.exchange_manager cimport ExchangeManager
from octobot_trading.portfolios.portfolio_value_manager cimport PortfolioValueManager
from octobot_trading.portfolios.portfolio_value_holder cimport PortfolioValueHolder
from octobot_trading.traders.trader cimport Trader
from octobot_trading.util.initializable cimport Initializable

Expand All @@ -33,7 +33,7 @@ cdef class PortfolioManager(Initializable):
cdef public Trader trader

cdef public PortfolioProfitability portfolio_profitability
cdef public PortfolioValueManager portfolio_value_manager
cdef public PortfolioValueHolder portfolio_value_holder
cdef public Portfolio portfolio

cpdef bint handle_balance_update(self, dict balance)
Expand Down
12 changes: 6 additions & 6 deletions octobot_trading/portfolios/portfolio_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
CONFIG_STARTING_PORTFOLIO, CURRENT_PORTFOLIO_STRING, BALANCE_CHANNEL
from octobot_trading.portfolios.portfolio_factory import create_portfolio_from_exchange_manager
from octobot_trading.portfolios.portfolio_profitability import PortfolioProfitability
from octobot_trading.portfolios.portfolio_value_manager import PortfolioValueManager
from octobot_trading.portfolios.portfolio_value_holder import PortfolioValueHolder
from octobot_trading.util import get_reference_market
from octobot_trading.util.initializable import Initializable

Expand All @@ -38,7 +38,7 @@ def __init__(self, config, trader, exchange_manager):

self.portfolio = None
self.portfolio_profitability = None
self.portfolio_value_manager = None
self.portfolio_value_holder = None
self.reference_market = None

async def initialize_impl(self):
Expand Down Expand Up @@ -83,7 +83,7 @@ async def handle_profitability_recalculation(self, force_recompute_origin_portfo
to ensure portfolio values are available
:param force_recompute_origin_portfolio: when True, force origin portfolio computation
"""
await self.portfolio_value_manager.handle_profitability_recalculation(force_recompute_origin_portfolio)
await self.portfolio_value_holder.handle_profitability_recalculation(force_recompute_origin_portfolio)

async def handle_mark_price_update(self, symbol, mark_price):
"""
Expand All @@ -93,7 +93,7 @@ async def handle_mark_price_update(self, symbol, mark_price):
:return: True if profitability changed
"""
return await self.portfolio_profitability. \
update_profitability(force_recompute_origin_portfolio=self.portfolio_value_manager.
update_profitability(force_recompute_origin_portfolio=self.portfolio_value_holder.
update_origin_crypto_currencies_values(symbol, mark_price))

async def _refresh_real_trader_portfolio(self) -> bool:
Expand All @@ -113,7 +113,7 @@ async def _reset_portfolio(self):
self._load_portfolio()

self.reference_market = get_reference_market(self.config)
self.portfolio_value_manager = PortfolioValueManager(self)
self.portfolio_value_holder = PortfolioValueHolder(self)
self.portfolio_profitability = PortfolioProfitability(self)

def _refresh_simulated_trader_portfolio_from_order(self, order):
Expand Down Expand Up @@ -156,4 +156,4 @@ def clear(self):
Clear portfolio manager objects
"""
self.portfolio_profitability = None
self.portfolio_value = None
self.portfolio_value_holder = None
4 changes: 2 additions & 2 deletions octobot_trading/portfolios/portfolio_profitability.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
In simulation it will also define rules to be filled / canceled
It is also use to store creation & fill values of the order """
from octobot_trading.portfolios.portfolio_manager cimport PortfolioManager
from octobot_trading.portfolios.portfolio_value_manager cimport PortfolioValueManager
from octobot_trading.portfolios.portfolio_value_holder cimport PortfolioValueHolder

cdef class PortfolioProfitability:
cdef object logger

cdef PortfolioManager portfolio_manager
cdef PortfolioValueManager value_manager
cdef PortfolioValueHolder value_manager

cdef public double profitability
cdef public double profitability_percent
Expand Down
4 changes: 2 additions & 2 deletions octobot_trading/portfolios/portfolio_profitability.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class PortfolioProfitability:

def __init__(self, portfolio_manager):
self.portfolio_manager = portfolio_manager
self.value_manager = portfolio_manager.portfolio_value_manager
self.value_manager = portfolio_manager.portfolio_value_holder
self.logger = get_logger(f"{self.__class__.__name__}[{self.portfolio_manager.exchange_manager.exchange_name}]")

# profitability attributes
Expand All @@ -52,7 +52,7 @@ def get_average_market_profitability(self):
Returns the % move average of all the watched cryptocurrencies between bot's start time and now
:return: the average market profitability
"""
self.portfolio_manager.portfolio_value_manager.get_current_crypto_currencies_values()
self.portfolio_manager.portfolio_value_holder.get_current_crypto_currencies_values()
return self._calculate_average_market_profitability()

async def update_profitability(self, force_recompute_origin_portfolio=False) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ It is also use to store creation & fill values of the order """
from octobot_trading.portfolios.portfolio cimport Portfolio
from octobot_trading.portfolios.portfolio_manager cimport PortfolioManager

cdef class PortfolioValueManager:
cdef class PortfolioValueHolder:
cdef object logger
cdef object config

Expand All @@ -49,7 +49,10 @@ cdef class PortfolioValueManager:
cdef double _update_portfolio_current_value(self, dict portfolio, dict currencies_values=*, bint fill_currencies_values=*)
cdef void _fill_currencies_values(self, dict currencies_values)
cdef dict _update_portfolio_and_currencies_current_value(self)
cdef double _evaluate_value(self, str currency, double quantity, bint raise_error=*)

# don't cythonize it to forward KeyError
# cdef double _evaluate_value(self, str currency, double quantity, bint raise_error=*)

cdef double _check_currency_initialization(self, str currency, double currency_value)
cdef void _recompute_origin_portfolio_initial_value(self)
cdef double _try_get_value_of_currency(self, str currency, double quantity, bint raise_error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
from octobot_trading.constants import TICKER_CHANNEL


class PortfolioValueManager:
class PortfolioValueHolder:
"""
PortfolioValueManager calculates the current and the origin portfolio value in reference market for each updates
PortfolioValueHolder calculates the current and the origin portfolio value in reference market for each updates
"""

def __init__(self, portfolio_manager):
Expand Down Expand Up @@ -223,9 +223,10 @@ def _try_get_value_of_currency(self, currency, quantity, raise_error):
self.missing_currency_data_in_exchange.add(currency)
return 0
except KeyError as missing_data_exception:
self._try_to_ask_ticker_missing_symbol_data(currency, symbol, reversed_symbol)
if raise_error:
raise missing_data_exception
if not self.portfolio_manager.exchange_manager.is_backtesting:
self._try_to_ask_ticker_missing_symbol_data(currency, symbol, reversed_symbol)
if raise_error:
raise missing_data_exception
return 0

def _try_to_ask_ticker_missing_symbol_data(self, currency, symbol, reversed_symbol):
Expand Down Expand Up @@ -350,12 +351,12 @@ def _evaluate_portfolio_value(self, portfolio, currencies_values=None):

def _get_currency_value(self, portfolio, currency, currencies_values=None, raise_error=False):
"""
:param portfolio:
:param currency:
:param currencies_values:
:param raise_error:
:return:
Return the currency value
:param portfolio: the specified portfolio
:param currency: the currency to evaluate
:param currencies_values: currencies values dict
:param raise_error: When True, forward exceptions
:return: the currency value
"""
if currency in portfolio and portfolio[currency][CONFIG_PORTFOLIO_TOTAL] != 0:
if currencies_values and currency in currencies_values:
Expand All @@ -365,11 +366,12 @@ def _get_currency_value(self, portfolio, currency, currencies_values=None, raise

def _should_currency_be_considered(self, currency, portfolio, ignore_missing_currency_data):
"""
:param currency:
:param portfolio:
:param ignore_missing_currency_data:
:return:
Return True if enough data is available to evaluate currency value
:param currency: the currency to evaluate
:param portfolio: the specified portfolio
:param ignore_missing_currency_data: When True, ignore check of currency presence
in missing_currency_data_in_exchange
:return: True if enough data is available to evaluate currency value
"""
return (currency not in self.missing_currency_data_in_exchange or ignore_missing_currency_data) and \
(portfolio[currency][PORTFOLIO_TOTAL] > 0 or currency in
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def build_ext(*args, **kwargs):
"octobot_trading.orders.types.unknown_order",
"octobot_trading.portfolios.portfolio",
"octobot_trading.portfolios.portfolio_manager",
"octobot_trading.portfolios.portfolio_value_manager",
"octobot_trading.portfolios.portfolio_value_holder",
"octobot_trading.portfolios.portfolio_profitability",
"octobot_trading.portfolios.portfolio_factory",
"octobot_trading.portfolios.sub_portfolio",
Expand Down
8 changes: 4 additions & 4 deletions tests/modes/test_abstract_mode_consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ async def test_valid_create_new_order():
async def test_get_holdings_ratio():
exchange_manager, symbol, consumer = await _get_tools()
exchange_manager.client_symbols = [symbol]
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.currencies_last_prices[symbol] = \
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.currencies_last_prices[symbol] = \
1000
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.portfolio_current_value = 11
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.portfolio_current_value = 11
exchange_manager.exchange_personal_data.portfolio_manager.portfolio.portfolio = {
"BTC": {
PORTFOLIO_TOTAL: 10
Expand All @@ -145,7 +145,7 @@ async def test_get_holdings_ratio():
assert round(ratio, 8) == 0.09090909

exchange_manager.exchange_personal_data.portfolio_manager.portfolio.portfolio.pop("USDT")
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.portfolio_current_value = 10
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.portfolio_current_value = 10
ratio = await consumer.get_holdings_ratio("BTC")
assert round(ratio, 8) == 1
# add ETH and try to get ratio without symbol price
Expand All @@ -167,7 +167,7 @@ async def test_get_holdings_ratio():

async def test_get_number_of_traded_assets():
exchange_manager, symbol, consumer = await _get_tools()
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_manager.\
exchange_manager.exchange_personal_data.portfolio_manager.portfolio_value_holder.\
origin_crypto_currencies_values = {
symbol: 1,
"xyz": 2,
Expand Down
40 changes: 20 additions & 20 deletions tests/portfolios/test_portfolio_profitability.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,75 +28,75 @@ async def test_init_profitability(backtesting_trader):
config, exchange_manager, trader = backtesting_trader
portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
portfolio_profitability = portfolio_manager.portfolio_profitability
portfolio_value_manager = portfolio_manager.portfolio_value_manager
portfolio_value_holder = portfolio_manager.portfolio_value_holder
assert portfolio_profitability.profitability == 0
assert portfolio_profitability.profitability_percent == 0
assert portfolio_profitability.profitability_diff == 0
assert portfolio_profitability.market_profitability_percent == 0
assert portfolio_profitability.initial_portfolio_current_profitability == 0
assert portfolio_value_manager.portfolio_origin_value == 0
assert portfolio_value_manager.portfolio_current_value == 0
assert portfolio_value_holder.portfolio_origin_value == 0
assert portfolio_value_holder.portfolio_current_value == 0


async def test_simple_handle_balance_update(backtesting_trader):
config, exchange_manager, trader = backtesting_trader
portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
portfolio_profitability = portfolio_manager.portfolio_profitability
portfolio_value_manager = portfolio_manager.portfolio_value_manager
portfolio_value_holder = portfolio_manager.portfolio_value_holder

# set the original values
await portfolio_profitability.portfolio_manager.handle_balance_updated()
await portfolio_manager.handle_balance_updated()
assert portfolio_profitability.profitability == 0
assert portfolio_profitability.profitability_percent == 0
assert portfolio_profitability.profitability_diff == 0
assert portfolio_value_manager.portfolio_origin_value == 10
assert portfolio_value_manager.portfolio_current_value == 10
assert portfolio_value_holder.portfolio_origin_value == 10
assert portfolio_value_holder.portfolio_current_value == 10

update_portfolio_balance({
'BTC': {'available': 20, 'total': 20},
'USDT': {'available': 1000, 'total': 1000}
}, exchange_manager)
await portfolio_profitability.portfolio_manager.handle_balance_updated()
await portfolio_manager.handle_balance_updated()
assert portfolio_profitability.profitability == 10
assert portfolio_profitability.profitability_percent == 100
assert portfolio_profitability.profitability_diff == 100
assert portfolio_value_manager.portfolio_origin_value == 10
assert portfolio_value_manager.portfolio_current_value == 20
assert portfolio_value_holder.portfolio_origin_value == 10
assert portfolio_value_holder.portfolio_current_value == 20


async def test_random_quantity_handle_balance_update(backtesting_trader):
config, exchange_manager, trader = backtesting_trader
portfolio_manager = exchange_manager.exchange_personal_data.portfolio_manager
portfolio_profitability = portfolio_manager.portfolio_profitability
portfolio_value_manager = portfolio_manager.portfolio_value_manager
portfolio_value_holder = portfolio_manager.portfolio_value_holder
original_symbol_quantity = 10

# set the original values
await portfolio_profitability.portfolio_manager.handle_balance_updated()
await portfolio_manager.handle_balance_updated()
assert portfolio_profitability.profitability == 0
assert portfolio_profitability.profitability_percent == 0
assert portfolio_profitability.profitability_diff == 0
assert portfolio_value_manager.portfolio_origin_value == original_symbol_quantity
assert portfolio_value_manager.portfolio_current_value == original_symbol_quantity
assert portfolio_value_holder.portfolio_origin_value == original_symbol_quantity
assert portfolio_value_holder.portfolio_current_value == original_symbol_quantity

new_btc_available = random_quantity(max_value=15) # shouldn't impact profitability
new_btc_total = random_quantity(min_value=new_btc_available, max_value=15)
new_prof_percent = (100 * new_btc_total / original_symbol_quantity) - 100
update_portfolio_balance({'BTC': {'available': new_btc_available, 'total': new_btc_total}},
exchange_manager)
await portfolio_profitability.portfolio_manager.handle_balance_updated()
await portfolio_manager.handle_balance_updated()
assert portfolio_profitability.profitability == new_btc_total - original_symbol_quantity
assert portfolio_profitability.profitability_percent == new_prof_percent
assert portfolio_profitability.profitability_diff == new_prof_percent - 0
assert portfolio_value_manager.portfolio_origin_value == original_symbol_quantity
assert portfolio_value_manager.portfolio_current_value == new_btc_total
assert portfolio_value_holder.portfolio_origin_value == original_symbol_quantity
assert portfolio_value_holder.portfolio_current_value == new_btc_total

new_btc_total_2 = random_quantity(min_value=new_btc_available, max_value=12)
new_prof_percent_2 = (100 * new_btc_total_2 / original_symbol_quantity) - 100
update_portfolio_balance({'BTC': {'total': new_btc_total_2}}, exchange_manager)
await portfolio_profitability.portfolio_manager.handle_balance_updated()
await portfolio_manager.handle_balance_updated()
assert portfolio_profitability.profitability == new_btc_total_2 - original_symbol_quantity
assert portfolio_profitability.profitability_percent == new_prof_percent_2
assert portfolio_profitability.profitability_diff == new_prof_percent_2 - new_prof_percent
assert portfolio_value_manager.portfolio_origin_value == original_symbol_quantity
assert portfolio_value_manager.portfolio_current_value == new_btc_total_2
assert portfolio_value_holder.portfolio_origin_value == original_symbol_quantity
assert portfolio_value_holder.portfolio_current_value == new_btc_total_2

0 comments on commit ec4c514

Please sign in to comment.