URI: 
       tCapital gains: * Show acquisition price in history. * Add summary to history command - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 0f16bcdc1ff5cda748f3079d7efd983b426277fb
   DIR parent b2c035024006f72efc711b37b39010067a5487cf
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 14 Feb 2018 10:42:09 +0100
       
       Capital gains:
       * Show acquisition price in history.
       * Add summary to history command
       
       Diffstat:
         M gui/qt/history_list.py              |      23 +++++++++++++----------
         M lib/exchange_rate.py                |      10 +++++++---
         M lib/wallet.py                       |      52 +++++++++++++++++++++++++++----
       
       3 files changed, 66 insertions(+), 19 deletions(-)
       ---
   DIR diff --git a/gui/qt/history_list.py b/gui/qt/history_list.py
       t@@ -61,7 +61,8 @@ class HistoryList(MyTreeWidget, AcceptFileDragDrop):
                headers = ['', '', _('Date'), _('Description') , _('Amount'), _('Balance')]
                fx = self.parent.fx
                if fx and fx.show_history():
       -            headers.extend(['%s '%fx.ccy + _('Amount'), '%s '%fx.ccy + _('Balance')])
       +            headers.extend(['%s '%fx.ccy + _('Value')])
       +            headers.extend(['%s '%fx.ccy + _('Acquisition price')])
                    headers.extend(['%s '%fx.ccy + _('Capital Gains')])
                    self.editable_columns.extend([6])
                self.update_headers(headers)
       t@@ -89,20 +90,22 @@ class HistoryList(MyTreeWidget, AcceptFileDragDrop):
                    label = self.wallet.get_label(tx_hash)
                    entry = ['', tx_hash, status_str, label, v_str, balance_str]
                    fiat_value = None
       -            if fx and fx.show_history():
       +            if value is not None and fx and fx.show_history():
                        date = timestamp_to_datetime(time.time() if conf <= 0 else timestamp)
                        fiat_value = self.wallet.get_fiat_value(tx_hash, fx.ccy)
                        if not fiat_value:
       -                    value_str = fx.historical_value_str(value, date)
       +                    fiat_value = fx.historical_value(value, date)
       +                    fiat_default = True
                        else:
       -                    value_str = str(fiat_value)
       +                    fiat_default = False
       +                value_str = fx.format_fiat(fiat_value)
                        entry.append(value_str)
       -                balance_str = fx.historical_value_str(balance, date)
       -                entry.append(balance_str)
                        # fixme: should use is_mine
       -                if value is not None and value < 0:
       -                    cg = self.wallet.capital_gain(tx_hash, fx.timestamp_rate, fx.ccy)
       -                    entry.append("%.2f"%cg if cg is not None else _('No data'))
       +                if value < 0:
       +                    ap, lp = self.wallet.capital_gain(tx_hash, fx.timestamp_rate, fx.ccy)
       +                    cg = None if lp is None or ap is None else lp - ap
       +                    entry.append(fx.format_fiat(ap))
       +                    entry.append(fx.format_fiat(cg))
                    item = QTreeWidgetItem(entry)
                    item.setIcon(0, icon)
                    item.setToolTip(0, str(conf) + " confirmation" + ("s" if conf != 1 else ""))
       t@@ -116,7 +119,7 @@ class HistoryList(MyTreeWidget, AcceptFileDragDrop):
                    if value and value < 0:
                        item.setForeground(3, QBrush(QColor("#BC1E1E")))
                        item.setForeground(4, QBrush(QColor("#BC1E1E")))
       -            if fiat_value:
       +            if not fiat_default:
                        item.setForeground(6, QBrush(QColor("#1E1EFF")))
                    if tx_hash:
                        item.setData(0, Qt.UserRole, tx_hash)
   DIR diff --git a/lib/exchange_rate.py b/lib/exchange_rate.py
       t@@ -506,10 +506,14 @@ class FxThread(ThreadJob):
                    self.value_str(COIN / (10**(8 - decimal_point)), rate), self.ccy)
        
            def value_str(self, satoshis, rate):
       -        if satoshis is None:  # Can happen with incomplete history
       -            return _("Unknown")
       -        if rate:
       +        if satoshis is not None and rate is not None:
                    value = Decimal(satoshis) / COIN * Decimal(rate)
       +        else:
       +            value = None
       +        return self.format_fiat(value)
       +
       +    def format_fiat(self, value):
       +        if value is not None:
                    return "%s" % (self.ccy_amount_str(value, True))
                return _("No data")
        
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -943,10 +943,21 @@ class Abstract_Wallet(PrintError):
        
                return h2
        
       +    def balance_at_timestamp(self, domain, target_timestamp):
       +        h = self.get_history(domain)
       +        for tx_hash, height, conf, timestamp, value, balance in h:
       +            if timestamp > target_timestamp:
       +                return balance - value
       +        # return last balance
       +        return balance
       +
            def export_history(self, domain=None, from_timestamp=None, to_timestamp=None, fx=None, show_addresses=False):
                from .util import format_time, format_satoshis, timestamp_to_datetime
                h = self.get_history(domain)
                out = []
       +        init_balance = None
       +        capital_gains = 0
       +        fiat_income = 0
                for tx_hash, height, conf, timestamp, value, balance in h:
                    if from_timestamp and timestamp < from_timestamp:
                        continue
       t@@ -960,6 +971,9 @@ class Abstract_Wallet(PrintError):
                        'value': format_satoshis(value, True) if value is not None else '--',
                        'balance': format_satoshis(balance)
                    }
       +            if init_balance is None:
       +                init_balance = balance - value
       +            end_balance = balance
                    if item['height']>0:
                        date_str = format_time(timestamp) if timestamp is not None else _("unverified")
                    else:
       t@@ -988,11 +1002,36 @@ class Abstract_Wallet(PrintError):
                        item['output_addresses'] = output_addresses
                    if fx is not None:
                        date = timestamp_to_datetime(time.time() if conf <= 0 else timestamp)
       -                item['fiat_value'] = fx.historical_value_str(value, date)
       -                item['fiat_balance'] = fx.historical_value_str(balance, date)
       +                fiat_value = self.get_fiat_value(tx_hash, fx.ccy)
       +                if fiat_value is None:
       +                    fiat_value = fx.historical_value(value, date)
       +                item['fiat_value'] = fx.format_fiat(fiat_value)
                        if value < 0:
       -                    item['capital_gain'] = self.capital_gain(tx_hash, fx.timestamp_rate, fx.ccy)
       +                    ap, lp = self.capital_gain(tx_hash, fx.timestamp_rate, fx.ccy)
       +                    cg = None if lp is None or ap is None else lp - ap
       +                    item['acquisition_price'] = fx.format_fiat(ap)
       +                    item['capital_gain'] = fx.format_fiat(cg)
       +                    capital_gains += cg
       +                else:
       +                    fiat_income += fiat_value
                    out.append(item)
       +
       +        if from_timestamp and to_timestamp:
       +            summary = {
       +                'start_date': format_time(from_timestamp),
       +                'end_date': format_time(to_timestamp),
       +                'initial_balance': format_satoshis(init_balance),
       +                'final_balance': format_satoshis(end_balance),
       +                'capital_gains': fx.format_fiat(capital_gains),
       +                'fiat_income': fx.format_fiat(fiat_income)
       +            }
       +            if fx:
       +                start_date = timestamp_to_datetime(from_timestamp)
       +                end_date = timestamp_to_datetime(to_timestamp)
       +                summary['initial_fiat_value'] = fx.format_fiat(fx.historical_value(init_balance, start_date))
       +                summary['final_fiat_value'] = fx.format_fiat(fx.historical_value(end_balance, end_date))
       +            out.append(summary)
       +
                return out
        
            def get_label(self, tx_hash):
       t@@ -1644,11 +1683,12 @@ class Abstract_Wallet(PrintError):
                    liquidation_price = None if p is None else out_value/Decimal(COIN) * p
                else:
                    liquidation_price = - fiat_value
       -
                try:
       -            return liquidation_price - out_value/Decimal(COIN) * self.average_price(tx, price_func, ccy)
       +            acquisition_price = out_value/Decimal(COIN) * self.average_price(tx, price_func, ccy)
                except:
       -            return None
       +            acquisition_price = None
       +        return acquisition_price, liquidation_price
       +
        
            def average_price(self, tx, price_func, ccy):
                """ average price of the inputs of a transaction """