URI: 
       tcompute capital gains using wallet.txi and txo - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 51f04d4e7bdb1021c5535c47b676c3d2d084eebf
   DIR parent e7c3712181e304b8661d52391c5ca4ab3c49f575
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 21 Feb 2018 14:29:39 +0100
       
       compute capital gains using wallet.txi and txo
       
       Diffstat:
         M lib/wallet.py                       |      61 +++++++++++++++++--------------
       
       1 file changed, 33 insertions(+), 28 deletions(-)
       ---
   DIR diff --git a/lib/wallet.py b/lib/wallet.py
       t@@ -503,6 +503,17 @@ class Abstract_Wallet(PrintError):
                    delta += v
                return delta
        
       +    def get_tx_value(self, txid):
       +        " effect of tx on the entire domain"
       +        delta = 0
       +        for addr, d in self.txi.get(txid, {}).items():
       +            for n, v in d:
       +                delta -= v
       +        for addr, d in self.txo.get(txid, {}).items():
       +            for n, v, cb in d:
       +                delta += v
       +        return delta
       +
            def get_wallet_delta(self, tx):
                """ effect of tx on wallet """
                addresses = self.get_addresses()
       t@@ -1694,7 +1705,7 @@ class Abstract_Wallet(PrintError):
                coins = self.get_utxos(domain)
                now = time.time()
                p = price_func(now)
       -        ap = sum(self.coin_price(coin, price_func, ccy, self.txin_value(coin)) for coin in coins)
       +        ap = sum(self.coin_price(coin['prevout_hash'], price_func, ccy, self.txin_value(coin)) for coin in coins)
                lp = sum([coin['value'] for coin in coins]) * p / Decimal(COIN)
                return lp - ap
        
       t@@ -1704,42 +1715,36 @@ class Abstract_Wallet(PrintError):
                and the price of these coins when they entered the wallet.
                price_func: function that returns the fiat price given a timestamp
                """
       -        tx = self.transactions[txid]
       -        ir, im, v, fee = self.get_wallet_delta(tx)
       -        out_value = -v
       +        out_value = - self.get_tx_value(txid)/Decimal(COIN)
                fiat_value = self.get_fiat_value(txid, ccy)
       -        if fiat_value is None:
       -            p = self.price_at_timestamp(txid, price_func)
       -            liquidation_price = out_value/Decimal(COIN) * p
       -        else:
       -            liquidation_price = - fiat_value
       -
       -        acquisition_price = out_value/Decimal(COIN) * self.average_price(tx, price_func, ccy)
       +        liquidation_price = - fiat_value if fiat_value else out_value * self.price_at_timestamp(txid, price_func)
       +        acquisition_price = out_value * self.average_price(txid, price_func, ccy)
                return acquisition_price, liquidation_price
        
       -    def average_price(self, tx, price_func, ccy):
       -        """ average price of the inputs of a transaction """
       -        input_value = sum(self.txin_value(txin) for txin in tx.inputs()) / Decimal(COIN)
       -        total_price = sum(self.coin_price(txin, price_func, ccy, self.txin_value(txin)) for txin in tx.inputs())
       -        return total_price / input_value
       -
       -    def coin_price(self, coin, price_func, ccy, txin_value):
       -        """ fiat price of acquisition of coin """
       -        txid = coin['prevout_hash']
       -        tx = self.transactions[txid]
       -        if all([self.is_mine(txin['address']) for txin in tx.inputs()]):
       -            return self.average_price(tx, price_func, ccy) * txin_value/Decimal(COIN)
       -        elif all([ not self.is_mine(txin['address']) for txin in tx.inputs()]):
       +    def average_price(self, txid, price_func, ccy):
       +        """ Average acquisition price of the inputs of a transaction """
       +        input_value = 0
       +        total_price = 0
       +        for addr, d in self.txi.get(txid, {}).items():
       +            for ser, v in d:
       +                input_value += v
       +                total_price += self.coin_price(ser.split(':')[0], price_func, ccy, v)
       +        return total_price / (input_value/Decimal(COIN))
       +
       +    def coin_price(self, txid, price_func, ccy, txin_value):
       +        """
       +        Acquisition price of a coin.
       +        This assumes that either all inputs are mine, or no input is mine.
       +        """
       +        if self.txi.get(txid, {}) != {}:
       +            return self.average_price(txid, price_func, ccy) * txin_value/Decimal(COIN)
       +        else:
                    fiat_value = self.get_fiat_value(txid, ccy)
                    if fiat_value is not None:
                        return fiat_value
                    else:
                        p = self.price_at_timestamp(txid, price_func)
                        return p * txin_value/Decimal(COIN)
       -        else:
       -            # could be some coinjoin transaction..
       -            return Decimal('NaN')
       -
        
        class Simple_Wallet(Abstract_Wallet):
            # wallet with a single keystore