def withdraw(self, quantity: 'Quantity', reason: str) -> 'Quantity': """Withdraws funds from the wallet. Parameters ---------- quantity : `Quantity` The amount to withdraw from this wallet. reason : str The reason for withdrawing the amount. Returns ------- `Quantity` The withdrawn amount. """ if quantity.is_locked and self._locked.get(quantity.path_id, False): locked_quantity = self._locked[quantity.path_id] if quantity > locked_quantity: if (quantity-locked_quantity)>Decimal(10)**(-self.instrument.precision+2): raise InsufficientFunds(locked_quantity, quantity) else: quantity = locked_quantity self._locked[quantity.path_id] -= quantity elif not quantity.is_locked: if quantity > self.balance: if (quantity-self.balance)>Decimal(10)**(-self.instrument.precision+2): raise InsufficientFunds(self.balance, quantity) else: quantity = self.balance self.balance -= quantity self.balance = self.balance.quantize() self.ledger.commit(wallet=self, quantity=quantity, source="{}:{}/locked".format(self.exchange.name, self.instrument), target=self.exchange.name, memo="WITHDRAWAL ({})".format(reason)) return quantity
def lock(self, quantity, order: 'Order', reason: str) -> 'Quantity': """Locks funds for specified order. Parameters ---------- quantity : `Quantity` The amount of funds to lock for the order. order : `Order` The order funds will be locked for. reason : str The reason for locking funds. Returns ------- `Quantity` The locked quantity for `order`. Raises ------ DoubleLockedQuantity Raised if the given amount is already a locked quantity. InsufficientFunds Raised if amount is greater the current balance. """ if quantity.is_locked: raise DoubleLockedQuantity(quantity) if quantity > self.balance: raise InsufficientFunds(self.balance, quantity) self.balance -= quantity quantity = quantity.lock_for(order.path_id) if quantity.path_id not in self._locked: self._locked[quantity.path_id] = quantity else: self._locked[quantity.path_id] += quantity self._locked[quantity.path_id] = self._locked[ quantity.path_id].quantize() self.balance = self.balance.quantize() self.ledger.commit(wallet=self, quantity=quantity, source="{}:{}/free".format(self.exchange.name, self.instrument), target="{}:{}/locked".format( self.exchange.name, self.instrument), memo="LOCK ({})".format(reason)) return quantity
def unlock(self, quantity: 'Quantity', reason: str) -> 'Quantity': """Unlocks a certain amount from the locked funds of the wallet that are associated with the given `quantity` path id. Parameters ---------- quantity : `Quantity` The quantity to unlock from the funds. reason : str The reason for unlocking funds. Returns ------- `Quantity` The free quantity. Raises ------ DoubleUnlockedFunds Raised if `quantity` is not a locked quantity. QuantityNotLocked Raised if `quantity` has a path id that is not currently allocated in this wallet. InsufficientFunds Raised if `quantity` is greater than the amount currently allocated for the associated path id. """ if not quantity.is_locked: raise DoubleUnlockedQuantity(quantity) if quantity.path_id not in self._locked: raise QuantityNotLocked(quantity) if quantity > self._locked[quantity.path_id]: raise InsufficientFunds(self._locked[quantity.path_id], quantity) self._locked[quantity.path_id] -= quantity self.balance += quantity.free() self._locked[quantity.path_id] = self._locked[ quantity.path_id].quantize() self.balance = self.balance.quantize() self.ledger.commit( wallet=self, quantity=quantity, source="{}:{}/locked".format(self.exchange.name, self.instrument), target="{}:{}/free".format(self.exchange.name, self.instrument), memo="UNLOCK {} ({})".format(self.instrument, reason)) return quantity