def get_stocks_data(stocks: list, finance_key: str, sa_dict: dict, stocks_data: dict, period: str): """Get stocks data based on a list of stocks and the finance key. The function searches for the correct financial statement automatically. [Source: StockAnalysis] Parameters ---------- stocks: list A list of tickers that will be used to collect data for. finance_key: str The finance key used to search within the sa_dict for the correct name of item on the financial statement sa_dict: dict A dictionary that includes BS, IS and CF, the abbreviations and names of items on the financial statements. I.e: {"BS": {"ce": "Cash & Equivalents"}} stocks_data : dict A dictionary that is empty on initialisation but filled once data is collected for the first time. period : str Whether you want annually, quarterly or trailing financial statements. Returns ------- dict Dictionary of filtered stocks data separated by financial statement """ no_data = [] for symbol in tqdm(stocks): for statement in sa_dict.keys(): if finance_key in sa_dict[statement]: if statement not in stocks_data: stocks_data[statement] = {} used_statement = statement symbol_statement = create_dataframe(symbol, statement, period.lower()) if symbol_statement[0].empty: no_data.append(symbol) continue stocks_data[statement][symbol] = ( change_type_dataframes(symbol_statement[0]) * symbol_statement[1]) if period in ["Quarterly", "Trailing"]: for symbol in stocks_data[used_statement]: stocks_data[used_statement][symbol].columns = ( stocks_data[used_statement][symbol].columns.map( lambda x: pd.Period(x, "Q")).astype(str)) stocks_data[used_statement] = match_length_dataframes( stocks_data[used_statement]) if no_data: console.print( f"No data available for {', '.join(str(symbol) for symbol in no_data)}" ) return stocks_data
def get_data(self, statement: str, row: int, header: bool) -> pd.DataFrame: df, rounding, _ = dcf_model.create_dataframe(self.info["ticker"], statement) if df.empty: raise ValueError("Could generate a dataframe for the ticker") self.info["rounding"] = rounding if not self.info["len_data"]: self.info["len_data"] = len(df.columns) self.ws[1][f"A{row}"] = dcf_static.statement_titles[statement] self.ws[1][f"A{row}"].font = dcf_static.bold_font rowI = row + 1 names = df.index.values.tolist() for name in names: self.ws[1][f"A{rowI}"] = name if name in dcf_static.sum_rows: length = self.info["len_data"] + (self.info["len_pred"] if statement != "CF" else 0) for i in range(length): if statement == "CF" and name == "Net Income": pass else: self.ws[1][ f"{dcf_static.letters[i+1]}{rowI}"].font = dcf_static.bold_font self.ws[1][ f"{dcf_static.letters[i+1]}{rowI}"].border = dcf_static.thin_border_top rowI += 1 column = 1 for key, value in df.iteritems(): rowI = row if header: dcf_model.set_cell( self.ws[1], f"{dcf_static.letters[column]}{rowI}", float(key), font=dcf_static.bold_font, ) for item in value: rowI += 1 m = 0 if item is None else float(item.replace(",", "")) dcf_model.set_cell( self.ws[1], f"{dcf_static.letters[column]}{rowI}", m, num_form="[$$-409]#,##0.00;[RED]-[$$-409]#,##0.00", ) column += 1 return df
def get_stocks_data( stocks: list, finance_key: str, sa_dict: dict, stocks_data: dict, period: str, convert_currency: str = "USD", ): """Get stocks data based on a list of stocks and the finance key. The function searches for the correct financial statement automatically. [Source: StockAnalysis] Parameters ---------- stocks: list A list of tickers that will be used to collect data for. finance_key: str The finance key used to search within the sa_dict for the correct name of item on the financial statement sa_dict: dict A dictionary that includes BS, IS and CF, the abbreviations and names of items on the financial statements. I.e: {"BS": {"ce": "Cash & Equivalents"}} stocks_data : dict A dictionary that is empty on initialisation but filled once data is collected for the first time. period : str Whether you want annually, quarterly or trailing financial statements. convert_currency : str Choose in what currency you wish to convert each company's financial statement. Default is USD (US Dollars). Returns ------- dict Dictionary of filtered stocks data separated by financial statement """ no_data = [] for symbol in tqdm(stocks): for statement in sa_dict.keys(): if finance_key in sa_dict[statement]: if statement not in stocks_data: stocks_data[statement] = {} used_statement = statement symbol_statement, rounding, currency = create_dataframe( symbol, statement, period.lower()) if symbol_statement.empty: no_data.append(symbol) continue symbol_statement_rounded = ( change_type_dataframes(symbol_statement) * rounding) if convert_currency and convert_currency != currency: currency_data = yf.download( f"{currency}{convert_currency}=X", start=f"{symbol_statement_rounded.columns[0]}-01-01", end=f"{symbol_statement_rounded.columns[-1]}-12-31", progress=False, )["Adj Close"] for year in symbol_statement_rounded: # Since fiscal year can differ, I take the median of the currency and not the last value # of the year symbol_statement_rounded[year] = ( symbol_statement_rounded[year] * currency_data.loc[year].median()) stocks_data[statement][symbol] = symbol_statement_rounded if period in ["Quarterly", "Trailing"]: for symbol in stocks_data[used_statement]: stocks_data[used_statement][symbol].columns = ( stocks_data[used_statement][symbol].columns.map( lambda x: pd.Period(x, "Q")).astype(str)) stocks_data[used_statement] = match_length_dataframes( stocks_data[used_statement]) if no_data: console.print( f"No data available for {', '.join(str(symbol) for symbol in no_data)}" ) return stocks_data