def buy(self, security: Security, num_shares: int, online: bool) -> str: """ Adds num_shares of the given security to the holdings of this asset class. Returns the state of the buy transaction. """ price: Optional[float] = security.get_price() if price is None: raise Exception("Can't buy security with undefined price") security_id: str = security.get_id() if self.contains_holding(security_id): hol: Holding = self.get_holding(security_id) old_num_shares: int = hol.get_num_shares() old_abp: float = hol.get_average_buy_price() old_div: float = hol.get_dividends() new_num_shares: int = old_num_shares + num_shares new_abp: float = (old_abp * old_num_shares + price * num_shares) / (old_num_shares + num_shares) self.update_holding(security_id, new_num_shares, new_abp, old_div) else: self.update_holding(security_id, num_shares, price, 0.0) log.info("Buy {n} {s} of {c} at {p} for a total of {t}? (Y/n) ".format( n=num_shares, s="shares" if num_shares > 1 else "share", c=security.get_symbol(), p=dollar_str(price), t=dollar_str(price * num_shares), )) order_state: str = "confirmed" if online: # Actually buy the ETFs user_choice: str = input("").lower() if user_choice in ["", "y"]: resp: Dict[str, Any] = r.order_buy_limit(security.get_symbol(), num_shares, security.get_price()) if resp is None: order_state = "failed" else: order_state = resp["state"] return order_state
def __init__(self, security: Security, num_shares: int) -> None: sec_price = security.get_price() if sec_price is None: raise Exception( "Purchase must be instantiated with a Security " "that has a non-None price" ) if num_shares <= 0: raise Exception( "Purchase must be instantiated with num_shares >= 0" ) self.__security: Security = security self.__num_shares: int = num_shares self.__cost: float = sec_price * self.__num_shares