Skip to content

Commit

Permalink
The portfolio report was extended with date since position was opened.
Browse files Browse the repository at this point in the history
  • Loading branch information
titov-vv committed Feb 9, 2024
1 parent 981a836 commit 947c01f
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 42 deletions.
3 changes: 3 additions & 0 deletions jal/db/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,9 @@ def open_trades_list(self, asset, timestamp=None) -> list:
trades.append({"operation": operation, "price": price, "remaining_qty": qty})
return trades

def asset_payments_amount(self, asset, start_ts, end_ts) -> Decimal:
return Decimal('0')

def _valid_data(self, data: dict, search: bool = False, create: bool = False) -> bool:
if data is None:
return False
Expand Down
57 changes: 43 additions & 14 deletions jal/db/holdings_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from jal.db.tree_model import AbstractTreeItem, ReportTreeModel
from jal.db.account import JalAccount
from jal.db.asset import JalAsset
from jal.db.operations import LedgerTransaction, Transfer, CorporateAction
from jal.widgets.delegates import GridLinesDelegate
from jal.widgets.helpers import ts2d

Expand All @@ -21,7 +22,7 @@ def __init__(self, data=None, parent=None, group=''):
self._data = {
'currency_id': 0, 'currency': '', 'account_id': 0, 'account': '', 'asset_id': 0, 'tag': '',
'asset_is_currency': False, 'asset': '', 'asset_name': '', 'country_id': 0, 'country': '', 'expiry': 0,
'qty': Decimal('0'), 'value_i': Decimal('0'),
'since': 0, 'qty': Decimal('0'), 'value_i': Decimal('0'),
'quote': Decimal('0'), 'quote_ts': Decimal('0'), 'quote_a': Decimal('0')
}
else:
Expand Down Expand Up @@ -88,6 +89,7 @@ def __init__(self, parent_view):
self._columns = [{'name': self.tr("Currency/Account/Asset")}, # 'field' key isn't used as model isn't query based
{'name': self.tr("Asset Name")},
{'name': self.tr("Qty")},
{'name': self.tr("Since")},
{'name': self.tr("Open")},
{'name': self.tr("Last")},
{'name': self.tr("Share, %")},
Expand All @@ -98,7 +100,7 @@ def __init__(self, parent_view):

def headerData(self, section, orientation, role=Qt.DisplayRole):
value = super().headerData(section, orientation, role)
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section == 9:
if orientation == Qt.Horizontal and role == Qt.DisplayRole and section == 10:
value += self._currency_name
return value

Expand Down Expand Up @@ -152,25 +154,30 @@ def data_text(self, item, column):
else:
return ''
if column == 3:
if data['since'] == 0:
return ''
else:
return ts2d(data['since'])
if column == 4:
if data['qty'] != Decimal('0') and data['value_i'] != Decimal('0'):
return localize_decimal(data['value_i'] / data['qty'], 4)
else:
return ''
if column == 4:
return localize_decimal(data['quote'], 4) if data['quote'] and float(data['qty']) != 0 else ''
if column == 5:
return localize_decimal(data['share'], 2) if data['share'] else Setup.NULL_VALUE
return localize_decimal(data['quote'], 4) if data['quote'] and float(data['qty']) != 0 else ''
if column == 6:
return localize_decimal(data['profit_rel'], 2)
return localize_decimal(data['share'], 2) if data['share'] else Setup.NULL_VALUE
if column == 7:
return localize_decimal(data['profit'], 2)
return localize_decimal(data['profit_rel'], 2)
if column == 8:
return localize_decimal(data['value'], 2)
return localize_decimal(data['profit'], 2)
if column == 9:
return localize_decimal(data['value'], 2)
if column == 10:
return localize_decimal(data['value_a'], 2) if data['value_a'] else Setup.NULL_VALUE

def data_tooltip(self, data, column):
if 4 <= column <= 8:
if 5 <= column <= 9:
quote_date = datetime.utcfromtimestamp(int(data['quote_ts']))
quote_age = int((datetime.utcnow() - quote_date).total_seconds() / 86400)
if quote_age > 7:
Expand All @@ -194,7 +201,7 @@ def data_font(self, item, column):
else:
font.setItalic(True)
return font
if column >= 4 and column <= 8:
if column >= 5 and column <= 9:
quote_date = datetime.utcfromtimestamp(int(data['quote_ts']))
quote_age = int((datetime.utcnow()- quote_date).total_seconds() / 86400)
if quote_age > 7:
Expand All @@ -211,12 +218,12 @@ def data_background(self, item, column, enabled=True):
return QBrush(CustomColor.LightPurple.lighter(factor))
if group == "account_id":
return QBrush(CustomColor.LightBlue.lighter(factor))
if column == 6 and data['profit_rel']:
if column == 7 and data['profit_rel']:
if data['profit_rel'] >= 0:
return QBrush(CustomColor.LightGreen.lighter(factor))
else:
return QBrush(CustomColor.LightRed.lighter(factor))
if column == 7 and data['profit']:
if column == 8 and data['profit']:
if data['profit'] >= 0:
return QBrush(CustomColor.LightGreen.lighter(factor))
else:
Expand Down Expand Up @@ -253,18 +260,38 @@ def get_data_for_tax(self, index):
data = index.internalPointer().details()
return data['account_id'], data['asset_id'], data['currency_id'], data['qty']

# Returns tuple of two values for open position in 'asset' for 'account' on given date 'end_ts':
# 1st (int) - the earliest timestamp of open position
# 2nd (Decimal) = 0 (not implemented - the amount of payments that were accumulated for given asset)
def get_asset_history_payments(self, account: JalAccount, asset: JalAsset, end_ts: int) -> (int, Decimal):
trades = account.open_trades_list(asset, end_ts)
since = min([x['operation'].timestamp() for x in trades])
amount = account.asset_payments_amount(asset, since, end_ts)
for trade in trades:
operation = trade['operation']
if operation.type() == LedgerTransaction.Transfer:
transfer_out = LedgerTransaction().get_operation(operation.type(), operation.id(), Transfer.Outgoing)
since_new, amount_new = self.get_asset_history_payments(transfer_out.account(), asset, transfer_out.timestamp()-1) # get position just before the transfer
elif operation.type() == LedgerTransaction.CorporateAction and operation.subtype() == CorporateAction.Split:
since_new, amount_new = self.get_asset_history_payments(account, asset, operation.timestamp()-1) # get position just before the split
else:
continue
since = min(since, since_new)
amount += amount_new
return since, amount

# Populate table 'holdings' with data calculated for given parameters of model: _currency, _date,
def prepareData(self):
holdings = []
accounts = JalAccount.get_all_accounts(account_type=PredefinedAccountType.Investment,
active_only=self._only_active_accounts)
accounts = JalAccount.get_all_accounts(account_type=PredefinedAccountType.Investment, active_only=self._only_active_accounts)
for account in accounts:
account_holdings = []
assets = account.assets_list(self._date)
rate = JalAsset(account.currency()).quote(self._date, self._currency)[1]
for asset_data in assets:
asset = asset_data['asset']
quote_ts, quote = asset.quote(self._date, account.currency())
since, payments_amount = self.get_asset_history_payments(account, asset, self._date)
record = {
"currency_id": account.currency(),
"currency": JalAsset(account.currency()).symbol(),
Expand All @@ -278,6 +305,7 @@ def prepareData(self):
"country": asset.country().name(),
"tag": asset.tag().name() if asset.tag().name() else self.tr("N/A"),
"expiry": asset.expiry(),
"since": since,
"qty": asset_data['amount'],
"value_i": asset_data['value'],
"quote": quote,
Expand All @@ -300,6 +328,7 @@ def prepareData(self):
"country": JalAsset(account.currency()).country().name(),
"tag": self.tr("Money"),
"expiry": 0,
"since": 0,
"qty": money,
"value_i": Decimal('0'),
"quote": Decimal('1'),
Expand Down
33 changes: 19 additions & 14 deletions jal/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1344,72 +1344,77 @@
<context>
<name>HoldingsModel</name>
<message>
<location filename="../db/holdings_model.py" line="90"/>
<location filename="../db/holdings_model.py" line="91"/>
<source>Qty</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="91"/>
<location filename="../db/holdings_model.py" line="92"/>
<source>Since</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="93"/>
<source>Open</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="92"/>
<location filename="../db/holdings_model.py" line="94"/>
<source>Last</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="93"/>
<location filename="../db/holdings_model.py" line="95"/>
<source>Share, %</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="94"/>
<location filename="../db/holdings_model.py" line="96"/>
<source>P/L, %</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="95"/>
<location filename="../db/holdings_model.py" line="97"/>
<source>P/L</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="96"/>
<location filename="../db/holdings_model.py" line="98"/>
<source>Value</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="99"/>
<location filename="../db/holdings_model.py" line="101"/>
<source>Value, </source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="177"/>
<location filename="../db/holdings_model.py" line="184"/>
<source>Last quote date: </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="279"/>
<location filename="../db/holdings_model.py" line="306"/>
<source>N/A</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="301"/>
<location filename="../db/holdings_model.py" line="329"/>
<source>Money</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="88"/>
<location filename="../db/holdings_model.py" line="89"/>
<source>Currency/Account/Asset</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="89"/>
<location filename="../db/holdings_model.py" line="90"/>
<source>Asset Name</source>
<translation></translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="142"/>
<location filename="../db/holdings_model.py" line="144"/>
<source>Exp:</source>
<translation></translation>
</message>
Expand Down
Binary file modified jal/languages/ru.qm
Binary file not shown.
33 changes: 19 additions & 14 deletions jal/languages/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1344,72 +1344,77 @@
<context>
<name>HoldingsModel</name>
<message>
<location filename="../db/holdings_model.py" line="90"/>
<location filename="../db/holdings_model.py" line="91"/>
<source>Qty</source>
<translation>Кол-во</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="91"/>
<location filename="../db/holdings_model.py" line="92"/>
<source>Since</source>
<translation>С</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="93"/>
<source>Open</source>
<translation>Цена откр.</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="92"/>
<location filename="../db/holdings_model.py" line="94"/>
<source>Last</source>
<translation>Цена закр.</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="93"/>
<location filename="../db/holdings_model.py" line="95"/>
<source>Share, %</source>
<translation>Доля, %</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="94"/>
<location filename="../db/holdings_model.py" line="96"/>
<source>P/L, %</source>
<translation>ПиУ, %</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="95"/>
<location filename="../db/holdings_model.py" line="97"/>
<source>P/L</source>
<translation>ПиУ</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="96"/>
<location filename="../db/holdings_model.py" line="98"/>
<source>Value</source>
<translation>Оценка</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="99"/>
<location filename="../db/holdings_model.py" line="101"/>
<source>Value, </source>
<translation>Оценка, </translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="177"/>
<location filename="../db/holdings_model.py" line="184"/>
<source>Last quote date: </source>
<translation>Дата последней котировки: </translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="279"/>
<location filename="../db/holdings_model.py" line="306"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="301"/>
<location filename="../db/holdings_model.py" line="329"/>
<source>Money</source>
<translation>Деньги</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="88"/>
<location filename="../db/holdings_model.py" line="89"/>
<source>Currency/Account/Asset</source>
<translation>Валюта/Счёт/ЦБ</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="89"/>
<location filename="../db/holdings_model.py" line="90"/>
<source>Asset Name</source>
<translation>Ценная бумага</translation>
</message>
<message>
<location filename="../db/holdings_model.py" line="142"/>
<location filename="../db/holdings_model.py" line="144"/>
<source>Exp:</source>
<translation>Эксп:</translation>
</message>
Expand Down

0 comments on commit 947c01f

Please sign in to comment.