Source code for tensortrade.wallets.wallet

# Copyright 2019 The TensorTrade Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License

from typing import Dict, Tuple

from tensortrade.base import Identifiable
from tensortrade.base.exceptions import InsufficientFunds
from tensortrade.instruments import Quantity


[docs]class Wallet(Identifiable): """A wallet stores the balance of a specific instrument on a specific exchange.""" def __init__(self, exchange: 'Exchange', quantity: 'Quantity'): self._exchange = exchange self._instrument = quantity.instrument self._balance = quantity self._locked = {}
[docs] @classmethod def from_tuple(cls, wallet_tuple: Tuple['Exchange', 'Instrument', float]): exchange, instrument, balance = wallet_tuple return cls(exchange, Quantity(instrument, balance))
@property def exchange(self) -> 'Exchange': return self._exchange @exchange.setter def exchange(self, exchange: 'Exchange'): raise ValueError("You cannot change a Wallet's Exchange after initialization.") @property def instrument(self) -> 'Instrument': return self._instrument @instrument.setter def instrument(self, instrument: 'Exchange'): raise ValueError("You cannot change a Wallet's Instrument after initialization.") @property def balance(self) -> 'Quantity': """The total balance of the wallet available for use.""" return self._balance @balance.setter def balance(self, balance: 'Quantity'): self._balance = balance @property def locked_balance(self) -> 'Quantity': """The total balance of the wallet locked in orders.""" locked_balance = Quantity(self.instrument, 0) for quantity in self.locked.values(): locked_balance += quantity.size return locked_balance @property def total_balance(self) -> 'Quantity': """The total balance of the wallet, both available for use and locked in orders.""" total_balance = self._balance for quantity in self.locked.values(): total_balance += quantity.size return total_balance @property def locked(self) -> Dict[str, 'Quantity']: return self._locked
[docs] def deallocate(self, path_id: str): if path_id in self.locked.keys(): quantity = self.locked.pop(path_id, None) if quantity is not None: self += quantity.size * self.instrument
def __iadd__(self, quantity: 'Quantity') -> 'Wallet': if quantity.is_locked: if quantity.path_id not in self.locked.keys(): self._locked[quantity.path_id] = quantity else: self._locked[quantity.path_id] += quantity else: self._balance += quantity return self def __isub__(self, quantity: 'Quantity') -> 'Wallet': if quantity.is_locked and self.locked[quantity.path_id]: if quantity > self.locked[quantity.path_id]: raise InsufficientFunds(self.locked[quantity.path_id], quantity.size) self._locked[quantity.path_id] -= quantity elif not quantity.is_locked: if quantity > self._balance: raise InsufficientFunds(self.balance, quantity.size) self._balance -= quantity return self def __str__(self): return '<Wallet: balance={}, locked={}>'.format(self.balance, self.locked_balance) def __repr__(self): return str(self)