def validate(left, right) -> Tuple['Quantity', 'Quantity']: if isinstance(left, Quantity) and isinstance(right, Quantity): if left.instrument != right.instrument: raise IncompatibleInstrumentOperation(left, right) if (left.path_id and right.path_id) and (left.path_id != right.path_id): raise QuantityOpPathMismatch(left.path_id, right.path_id) elif left.path_id and not right.path_id: right.path_id = left.path_id elif not left.path_id and right.path_id: left.path_id = right.path_id return left, right elif isinstance(left, Number) and isinstance(right, Quantity): left = Quantity(right.instrument, float(left), right.path_id) return left, right elif isinstance(left, Quantity) and isinstance(right, Number): right = Quantity(left.instrument, float(right), left.path_id) return left, right elif isinstance(left, Quantity): raise InvalidNonNumericQuantity(right) elif isinstance(right, Quantity): raise InvalidNonNumericQuantity(left) return left, right
def __rtruediv__(self, other: Union['Price', float, int]): """Divides two PriceType objects together. Arguments: other: Union[Price, float, int] The object that is the left argument of the addition operation. Raises: IncompatibleTradingPairException: If (other : Price) and the pairs do not equal each other. InvalidNonNumericQuantity: If not (other : Union[Price, Number]). """ price = None if isinstance(other, float) or isinstance(other, int): price = Price(other / self.rate, self.pair.quote / self.pair.base) elif isinstance(other, Quantity): raise IncompatiblePriceQuantityOperation(self, other) elif not isinstance(other, Number): raise InvalidNonNumericQuantity(other) return price
def __rsub__(self, other: Union['Price', float, int]): """Subtracts two PriceType objects together. Arguments: other: Union[Price, float, int] The object that is the left argument of the operation. Raises: IncompatibleTradingPairException: If (other : Price) and the pairs do not equal each other. InvalidNonNumericQuantity: If not (other : Union[Price, Number]). """ price = None if isinstance(other, Price): rate = other.rate - self.rate pair = self.pair or other.pair if self.pair != other.pair: raise IncompatibleTradingPairOperation(self.pair, other.pair) price = Price(rate, pair) elif isinstance(other, float) or isinstance(other, int): price = Price(other - self.rate, self.pair) elif not isinstance(other, Number): raise InvalidNonNumericQuantity(other) return price
def __iadd__(self, other: Union['Price', float, int]): """Iteratively add to a Price object. Arguments: other: Union[Price, float, int] The object that is the left argument of the operation. Raises: IncompatibleTradingPairException: If (other : Price) and the pairs do not equal each other. InvalidNonNumericQuantity: If not (other : Union[Price, Number]). """ if isinstance(other, Price): if self.pair != other.pair: raise IncompatibleTradingPairOperation(self.pair, other.pair) self.rate += other.rate elif isinstance(other, float) or isinstance(other, int): self.rate += other elif not isinstance(other, Number): raise InvalidNonNumericQuantity(other) return self
def __mul__(self, other: Union['Price', 'Quantity', float, int]): """Multiplies two PriceType objects together. Arguments: other: Union[Price, float, int] The object that is the right argument of the operation. Raises: IncompatibleTradingPairException: If (other : Price) and the pairs do not equal each other. InvalidNonNumericQuantity: If not (other : Union[Price, Number]). """ price = None if isinstance(other, Price): rate = self.rate * other.rate pair = self.pair or other.pair if self.pair != other.pair: raise IncompatibleTradingPairOperation(self.pair, other.pair) price = Price(rate, pair) elif isinstance(other, float) or isinstance(other, int): price = Price(self.rate * other, self.pair) elif isinstance(other, Quantity): if other.instrument != self.pair.quote: raise IncompatiblePriceQuantityOperation( self.pair.quote, other.instrument) return Quantity(self.pair.base, self.rate * other.size, other.path_id) elif not isinstance(other, Number): raise InvalidNonNumericQuantity(other) return price
def _bool_operation(left: Union['Quantity', float, int], right: Union['Quantity', float, int], bool_op: operator) -> bool: right_size = right if isinstance(right, Quantity): if left.instrument != right.instrument: raise IncompatibleInstrumentOperation(left, right) right_size = right.size if not isinstance(right_size, Number): raise InvalidNonNumericQuantity(right_size) boolean = bool_op(left.size, right_size) if not isinstance(boolean, bool): raise Exception( "`bool_op` cannot return a non-bool type ({}).".format( boolean)) return boolean
def _math_operation(left: Union['Quantity', float, int], right: Union['Quantity', float, int], op: operator) -> 'Quantity': right_size = right if isinstance(right, Quantity): if left.instrument != right.instrument: raise IncompatibleInstrumentOperation(left, right) if left.path_id and right.path_id: if left._path_id != right._path_id: raise QuantityOpPathMismatch(left.path_id, right.path_id) right_size = right.size if not isinstance(right_size, Number): raise InvalidNonNumericQuantity(right_size) size = op(left.size, right_size) return Quantity(instrument=left.instrument, size=size, path_id=left.path_id)