dcfCalculator

  1import math
  2import requests
  3from bs4 import BeautifulSoup
  4
  5"""
  6Documentación de la clase FinanceAnalyzer
  7"""
  8
  9
 10class DcfCalculator:
 11    def __init__(self, ticker=None):
 12        """
 13        Inicializa el objeto FinanceAnalyzer con los datos financieros del ticker especificado.
 14
 15        Args:
 16            ticker (str): El símbolo de ticker de la acción.
 17        """
 18        self.balanceSheet = self.getBalanceSheet(ticker)
 19        """El balance de la acción."""
 20        self.info = self.getInfo(ticker)
 21        """La información básica de la acción."""
 22        self.financials = self.getFinancials(ticker)
 23        """Los estados financieros de la acción."""
 24        self.incomeStmt = self.getIncomeStmt(ticker)
 25        """El estado de ingresos de la acción."""
 26        self.cashFlow = self.getCashFlow(ticker)
 27        """El flujo de efectivo de la acción."""
 28
 29    def getAttribute(self, ticker, attribute, error_message):
 30        """
 31        Obtiene los datos de yahoo finance
 32
 33        Args:
 34            ticker (str): El símbolo de ticker de la acción.
 35            attribute (str): El nombre del atributo a obtener.
 36            error_message (str): El mensaje de error a mostrar si el atributo no se puede obtener.
 37
 38        Returns:
 39            obj: El valor del atributo.
 40        """
 41        try:
 42            return getattr(ticker, attribute)
 43        except:
 44            raise Exception(error_message)
 45
 46    def getFinancials(self, ticker):
 47        """
 48        Obtiene los estados financieros del ticker especificado.
 49
 50        Args:
 51            ticker (str): El símbolo de ticker de la acción.
 52
 53        Returns:
 54            obj: Los estados financieros del ticker.
 55        """
 56        return self.getAttribute(
 57            ticker,
 58            "financials",
 59            "No se pudo obtener los estados financieros de la acción",
 60        )
 61
 62    def getBalanceSheet(self, ticker):
 63        """
 64        Obtiene el balance de la acción del ticker especificado.
 65
 66        Args:
 67            ticker (str): El símbolo de ticker de la acción.
 68
 69        Returns:
 70            obj: El balance de la acción.
 71        """
 72        return self.getAttribute(
 73            ticker, "balance_sheet", "No se pudo obtener el balance de la acción"
 74        )
 75
 76    def getIncomeStmt(self, ticker):
 77        """
 78        Obtiene el estado de ingresos de la acción del ticker especificado.
 79
 80        Args:
 81            ticker (str): El símbolo de ticker de la acción.
 82
 83        Returns:
 84            obj: El estado de ingresos de la acción.
 85        """
 86        return self.getAttribute(
 87            ticker,
 88            "income_stmt",
 89            "No se pudo obtener el estado de los ingresos de la acción",
 90        )
 91
 92    def getInfo(self, ticker):
 93        """
 94        Obtiene la información básica de la acción del ticker especificado.
 95
 96        Args:
 97            ticker (str): El símbolo de ticker de la acción.
 98
 99        Returns:
100            obj: La información básica de la acción.
101        """
102        return self.getAttribute(
103            ticker, "info", "No se pudo obtener la información de la acción"
104        )
105
106    def getCashFlow(self, ticker):
107        """
108        Obtiene el flujo de efectivo de la acción del ticker especificado.
109
110        Args:
111            ticker (str): El símbolo de ticker de la acción.
112
113        Returns:
114            obj: El flujo de efectivo de la acción.
115        """
116        return self.getAttribute(
117            ticker, "cashflow", "No se pudo obtener el flujo de caja de la acción"
118        )
119
120    def getEbitda(self):
121        """
122        Calcula el EBITDA de la acción.
123
124        Returns:
125            float: El EBITDA de la acción.
126        """
127        try:
128            ebitda = self.getLastYearValue(self.incomeStmt, "EBITDA")
129        except Exception as e:
130            raise Exception("No se pudo obtener el EBITDA de la acción") from e
131        return ebitda
132
133    def getEarnings(self):
134        """
135        Calcula las ganancias de la acción.
136
137        Returns:
138            float: Las ganancias de la acción.
139        """
140        try:
141            grossProfit = self.getLastYearValue(self.incomeStmt, "Gross Profit")
142            totalRevenue = self.getLastYearValue(self.incomeStmt, "Total Revenue")
143            return (grossProfit / totalRevenue) * 100
144        except Exception as e:
145            raise Exception("No se pudo obtener las ganancias de la acción") from e
146
147    def getRoe(self):
148        """
149        Calcula el ROE (Return on Equity) de la acción.
150
151        Returns:
152            float: El ROE de la acción.
153        """
154        try:
155            last_year_net_income = self.getLastYearValue(self.incomeStmt, "Net Income")
156        except Exception as e:
157            raise Exception("No se pudo obtener el net income de la acción") from e
158
159        try:
160            last_year_equity = self.getLastYearValue(
161                self.balanceSheet, "Stockholders Equity"
162            )
163        except Exception as e:
164            raise Exception("No se pudo obtener el equity de la acción") from e
165
166        return (last_year_net_income / last_year_equity) * 100
167
168    def getPer(self):
169        """
170        Obtiene el PER (Price to Earnings Ratio) de la acción.
171
172        Returns:
173            float: El PER de la acción.
174        """
175        try:
176            return self.info["trailingPE"]
177        except:
178            raise Exception("No se pudo obtener el PER de la acción")
179
180    def getLastYearValue(self, data, label):
181        """
182        Obtiene el valor del año pasado para una etiqueta de datos específica.
183
184        Args:
185            data (DataFrame): Los datos financieros.
186            label (str): La etiqueta de datos específica.
187
188        Returns:
189            float: El valor del año pasado para la etiqueta de datos especificada.
190        """
191        try:
192            value = data.loc[label]
193            i = 0
194            last_year_value = value.iloc[i]
195            while math.isnan(value.iloc[i]):
196                i += 1
197                last_year_value = value.iloc[i]
198            return last_year_value
199        except:
200            try:
201                if label == "Current Debt And Capital Lease Obligation":
202                    return self.getLastYearValue(data, "Current Deferred Liabilities")
203            except:
204                raise Exception(f"No se pudo obtener {label} de la acción")
205            raise Exception(f"No se pudo obtener {label} de la acción")
206
207    def getTotalDebt(self, balanceSheet):
208        """
209        Calcula la deuda total de la acción.
210
211        Args:
212            balanceSheet (DataFrame): El balance de la acción.
213
214        Returns:
215            float: La deuda total de la acción.
216        """
217        try:
218            return self.getLastYearValue(balanceSheet, "Total Debt")
219        except Exception as e:
220            raise Exception("No se pudo obtener la deuda total de la acción") from e
221
222    def getGrowthEstimates(self, ticker, option):
223        """
224        Obtiene las estimaciones de crecimiento para la acción.
225
226        Args:
227            ticker (str): El símbolo de ticker de la acción.
228
229        Returns:
230            str: Las estimaciones de crecimiento.
231        """
232        try:
233            if option == "yahoo":
234                return self.getGrowthEstimatesYahoo(ticker)
235            elif option == "zacks":
236                return self.getGrowthEstimatesZacks(ticker)
237            elif option == "seeking":
238                return self.getGrowthEstimatesSeeking(ticker)
239
240        except Exception as e:
241            return str(e)
242
243    def getGrowthEstimatesYahoo(self, ticker):
244        """
245        Obtiene las estimaciones de crecimiento para la acción de la webd e Yahoo Finance.
246
247        Args:
248            ticker (str): El símbolo de ticker de la acción.
249
250        Returns:
251            str: Las estimaciones de crecimiento.
252        """
253        url = f"https://finance.yahoo.com/quote/{ticker}/analysis?ltr=1"
254        headers = {
255            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
256        }
257        try:
258            response = requests.get(url, headers=headers)
259            response.raise_for_status()
260            soup = BeautifulSoup(response.text, "html.parser")
261            desired_table = soup.find_all("table")[5]
262            target_value = (
263                desired_table.find_all("tr")[5].find_all("td")[1].text.strip()
264            )
265            return target_value
266        except IndexError:
267            raise Exception(
268                "No se encontraron suficientes tablas, filas o celdas en la página"
269            )
270        except requests.exceptions.RequestException as e:
271            raise Exception(f"Error en la solicitud: {e}")
272
273    def getGrowthEstimatesZacks(self, ticker):
274        """
275        Obtiene las estimaciones de crecimiento para la acción de la web de Zacks.
276
277        Args:
278            ticker (str): El símbolo de ticker de la acción.
279
280        Returns:
281            str: Las estimaciones de crecimiento.
282        """
283        url = f"https://www.zacks.com/stock/quote/{ticker}?q={ticker}"
284        headers = {
285            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
286        }
287        try:
288            response = requests.get(url, headers=headers)
289            response.raise_for_status()
290            soup = BeautifulSoup(response.text, "html.parser")
291            desired_table = soup.find_all("dl", class_="abut_bottom")
292            # print(desired_table)
293            target_value = desired_table[15].find_all("dd")[0].text.strip()
294            # print(target_value)
295            return target_value
296        except IndexError:
297            raise Exception(
298                "No se encontraron suficientes tablas, filas o celdas en la página"
299            )
300        except requests.exceptions.RequestException as e:
301            raise Exception(f"Error en la solicitud: {e}")
302
303    def getGrowthEstimatesSeeking(self, ticker):
304        """
305        Obtiene las estimaciones de crecimiento para la acción de la web de Seeking Alpha.
306
307        Args:
308            ticker (str): El símbolo de ticker de la acción.
309
310        Returns:
311            str: Las estimaciones de crecimiento.
312        """
313        url = f"https://seekingalpha.com/symbol/{ticker}/growth"
314        headers = {
315            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
316        }
317        try:
318            response = requests.get(url, headers=headers)
319            # print(response)
320            response.raise_for_status()
321            soup = BeautifulSoup(response.text, "html.parser")
322            desired_table = soup.find_all("table")[0]
323            target_value = (
324                desired_table.find_all("tr")[11].find_all("td")[1].text.strip()
325            )
326            # print(target_value, 'hi')
327            return target_value
328        except IndexError:
329            raise Exception(
330                "No se encontraron suficientes tablas, filas o celdas en la página"
331            )
332        except requests.exceptions.RequestException as e:
333            raise Exception(f"Error en la solicitud: {e}")
334
335    def waccCalculator(self, rf, rm):
336        """
337        Calcula el costo promedio ponderado del capital (WACC).
338
339        Args:
340            rf (float): Tasa libre de riesgo.
341            rm (float): Retorno del mercado.
342
343        Returns:
344            float: El WACC calculado.
345        """
346        last_year_total_debt = self.getTotalDebt(self.balanceSheet)
347
348        beta = self.info.get("beta", 1)
349
350        ke = rf + (beta * (rm - rf))
351
352        e = self.info.get("marketCap")
353        if e is None:
354            raise Exception(
355                "No se pudo obtener la capitalización bursátil de la acción"
356            )
357
358        total_debt_ED = e + last_year_total_debt
359
360        total_equity = ke * (e / total_debt_ED)
361
362        last_year_interest_expense = self.getLastYearValue(
363            self.financials, "Interest Expense"
364        )
365
366        last_year_current_debt = self.getLastYearValue(
367            self.balanceSheet, "Current Debt And Capital Lease Obligation"
368        )
369
370        last_year_long_term_debt = self.getLastYearValue(
371            self.balanceSheet, "Long Term Debt"
372        )
373
374        kd = last_year_interest_expense / (
375            last_year_current_debt + last_year_long_term_debt
376        )
377
378        last_year_tax_provision = self.getLastYearValue(
379            self.incomeStmt, "Tax Provision"
380        )
381
382        last_year_pretax_income = self.getLastYearValue(
383            self.incomeStmt, "Pretax Income"
384        )
385
386        t = last_year_tax_provision / last_year_pretax_income
387
388        total_debt_cost = kd * (1 - t) * (last_year_total_debt / total_debt_ED)
389
390        return total_equity + total_debt_cost
391
392    def dcf(self, tickerStr, g, rf, rm, option):
393        """
394        Calcula el valor intrínseco de una acción utilizando el modelo de descuento de flujos de efectivo (DCF).
395
396        Args:
397            tickerStr (str): El símbolo de ticker de la acción.
398            g (float): Tasa de crecimiento a perpetuidad.
399            rf (float): Tasa libre de riesgo.
400            rm (float): Retorno del mercado.
401
402        Returns:
403            list: Una lista que contiene varios valores calculados.
404        """
405        try:
406            last_year_total_debt = self.getTotalDebt(self.balanceSheet)
407            growthFCF = self.getGrowthEstimates(tickerStr, option)
408            print(option, growthFCF)
409            printGrowthFCF = growthFCF
410            try:
411                growthFCF = float(growthFCF.replace("%", "")) / 100
412            except:
413                FCFGrow = self.cashFlow.iloc[0]
414                growthFCF = (
415                    (FCFGrow.iloc[0] / FCFGrow.iloc[-1]) ** (1 / len(FCFGrow))
416                ) - 1
417                printGrowthFCF = "{:.2f}%".format(growthFCF * 100)
418
419            wacc = self.waccCalculator(rf, rm)
420            if type(wacc) != float:
421                raise Exception(wacc)
422
423            last_year_fcf = self.getLastYearValue(self.cashFlow, "Free Cash Flow")
424            printFCF = last_year_fcf
425
426            FCFn = [
427                int(format(last_year_fcf * (1 + growthFCF) ** i, ".0f"))
428                for i in range(1, 6)
429            ]
430
431            terminal_value = (FCFn[-1] * (1 + g)) / (wacc - g)
432            FNFnLast = FCFn[-1]
433            FCFn[-1] = int(format(FCFn[-1] + terminal_value, ".0f"))
434
435            enterprise_value = sum(
436                [FCFn[i] / ((1 + wacc) ** (i + 1)) for i in range(5)]
437            )
438
439            last_year_cash = self.getLastYearValue(
440                self.balanceSheet, "Cash Cash Equivalents And Short Term Investments"
441            )
442
443            equity_value = enterprise_value + last_year_cash - last_year_total_debt
444
445            shares_outstanding = self.info["sharesOutstanding"]
446
447            intrinsic_value = equity_value / shares_outstanding
448
449            price = self.info["regularMarketPreviousClose"]
450
451            difference = 100 + (((intrinsic_value - price) / price) * 100)
452
453            FCFn.pop()
454            FCFn.append(FNFnLast)
455
456            return [
457                (format((wacc * 100), ".2f") + " %"),
458                ("$ " + "{:,.0f}".format(printFCF).replace(",", ".")),
459                FCFn,
460                printGrowthFCF,
461                ("$ " + "{:,.0f}".format(equity_value, ".0f").replace(",", ".")),
462                ("$ " + str(price)),
463                ("$ " + format(intrinsic_value, ".2f")),
464                (format((difference), ".2f") + "%"),
465            ]
466        except Exception as e:
467            return str(e)
468
469
470# DcfCalculator("STX").getGrowthEstimates("AAPL")
471# DcfCalculator("STX").getGrowthEstimatesSeeking("AAPL")
class DcfCalculator:
 11class DcfCalculator:
 12    def __init__(self, ticker=None):
 13        """
 14        Inicializa el objeto FinanceAnalyzer con los datos financieros del ticker especificado.
 15
 16        Args:
 17            ticker (str): El símbolo de ticker de la acción.
 18        """
 19        self.balanceSheet = self.getBalanceSheet(ticker)
 20        """El balance de la acción."""
 21        self.info = self.getInfo(ticker)
 22        """La información básica de la acción."""
 23        self.financials = self.getFinancials(ticker)
 24        """Los estados financieros de la acción."""
 25        self.incomeStmt = self.getIncomeStmt(ticker)
 26        """El estado de ingresos de la acción."""
 27        self.cashFlow = self.getCashFlow(ticker)
 28        """El flujo de efectivo de la acción."""
 29
 30    def getAttribute(self, ticker, attribute, error_message):
 31        """
 32        Obtiene los datos de yahoo finance
 33
 34        Args:
 35            ticker (str): El símbolo de ticker de la acción.
 36            attribute (str): El nombre del atributo a obtener.
 37            error_message (str): El mensaje de error a mostrar si el atributo no se puede obtener.
 38
 39        Returns:
 40            obj: El valor del atributo.
 41        """
 42        try:
 43            return getattr(ticker, attribute)
 44        except:
 45            raise Exception(error_message)
 46
 47    def getFinancials(self, ticker):
 48        """
 49        Obtiene los estados financieros del ticker especificado.
 50
 51        Args:
 52            ticker (str): El símbolo de ticker de la acción.
 53
 54        Returns:
 55            obj: Los estados financieros del ticker.
 56        """
 57        return self.getAttribute(
 58            ticker,
 59            "financials",
 60            "No se pudo obtener los estados financieros de la acción",
 61        )
 62
 63    def getBalanceSheet(self, ticker):
 64        """
 65        Obtiene el balance de la acción del ticker especificado.
 66
 67        Args:
 68            ticker (str): El símbolo de ticker de la acción.
 69
 70        Returns:
 71            obj: El balance de la acción.
 72        """
 73        return self.getAttribute(
 74            ticker, "balance_sheet", "No se pudo obtener el balance de la acción"
 75        )
 76
 77    def getIncomeStmt(self, ticker):
 78        """
 79        Obtiene el estado de ingresos de la acción del ticker especificado.
 80
 81        Args:
 82            ticker (str): El símbolo de ticker de la acción.
 83
 84        Returns:
 85            obj: El estado de ingresos de la acción.
 86        """
 87        return self.getAttribute(
 88            ticker,
 89            "income_stmt",
 90            "No se pudo obtener el estado de los ingresos de la acción",
 91        )
 92
 93    def getInfo(self, ticker):
 94        """
 95        Obtiene la información básica de la acción del ticker especificado.
 96
 97        Args:
 98            ticker (str): El símbolo de ticker de la acción.
 99
100        Returns:
101            obj: La información básica de la acción.
102        """
103        return self.getAttribute(
104            ticker, "info", "No se pudo obtener la información de la acción"
105        )
106
107    def getCashFlow(self, ticker):
108        """
109        Obtiene el flujo de efectivo de la acción del ticker especificado.
110
111        Args:
112            ticker (str): El símbolo de ticker de la acción.
113
114        Returns:
115            obj: El flujo de efectivo de la acción.
116        """
117        return self.getAttribute(
118            ticker, "cashflow", "No se pudo obtener el flujo de caja de la acción"
119        )
120
121    def getEbitda(self):
122        """
123        Calcula el EBITDA de la acción.
124
125        Returns:
126            float: El EBITDA de la acción.
127        """
128        try:
129            ebitda = self.getLastYearValue(self.incomeStmt, "EBITDA")
130        except Exception as e:
131            raise Exception("No se pudo obtener el EBITDA de la acción") from e
132        return ebitda
133
134    def getEarnings(self):
135        """
136        Calcula las ganancias de la acción.
137
138        Returns:
139            float: Las ganancias de la acción.
140        """
141        try:
142            grossProfit = self.getLastYearValue(self.incomeStmt, "Gross Profit")
143            totalRevenue = self.getLastYearValue(self.incomeStmt, "Total Revenue")
144            return (grossProfit / totalRevenue) * 100
145        except Exception as e:
146            raise Exception("No se pudo obtener las ganancias de la acción") from e
147
148    def getRoe(self):
149        """
150        Calcula el ROE (Return on Equity) de la acción.
151
152        Returns:
153            float: El ROE de la acción.
154        """
155        try:
156            last_year_net_income = self.getLastYearValue(self.incomeStmt, "Net Income")
157        except Exception as e:
158            raise Exception("No se pudo obtener el net income de la acción") from e
159
160        try:
161            last_year_equity = self.getLastYearValue(
162                self.balanceSheet, "Stockholders Equity"
163            )
164        except Exception as e:
165            raise Exception("No se pudo obtener el equity de la acción") from e
166
167        return (last_year_net_income / last_year_equity) * 100
168
169    def getPer(self):
170        """
171        Obtiene el PER (Price to Earnings Ratio) de la acción.
172
173        Returns:
174            float: El PER de la acción.
175        """
176        try:
177            return self.info["trailingPE"]
178        except:
179            raise Exception("No se pudo obtener el PER de la acción")
180
181    def getLastYearValue(self, data, label):
182        """
183        Obtiene el valor del año pasado para una etiqueta de datos específica.
184
185        Args:
186            data (DataFrame): Los datos financieros.
187            label (str): La etiqueta de datos específica.
188
189        Returns:
190            float: El valor del año pasado para la etiqueta de datos especificada.
191        """
192        try:
193            value = data.loc[label]
194            i = 0
195            last_year_value = value.iloc[i]
196            while math.isnan(value.iloc[i]):
197                i += 1
198                last_year_value = value.iloc[i]
199            return last_year_value
200        except:
201            try:
202                if label == "Current Debt And Capital Lease Obligation":
203                    return self.getLastYearValue(data, "Current Deferred Liabilities")
204            except:
205                raise Exception(f"No se pudo obtener {label} de la acción")
206            raise Exception(f"No se pudo obtener {label} de la acción")
207
208    def getTotalDebt(self, balanceSheet):
209        """
210        Calcula la deuda total de la acción.
211
212        Args:
213            balanceSheet (DataFrame): El balance de la acción.
214
215        Returns:
216            float: La deuda total de la acción.
217        """
218        try:
219            return self.getLastYearValue(balanceSheet, "Total Debt")
220        except Exception as e:
221            raise Exception("No se pudo obtener la deuda total de la acción") from e
222
223    def getGrowthEstimates(self, ticker, option):
224        """
225        Obtiene las estimaciones de crecimiento para la acción.
226
227        Args:
228            ticker (str): El símbolo de ticker de la acción.
229
230        Returns:
231            str: Las estimaciones de crecimiento.
232        """
233        try:
234            if option == "yahoo":
235                return self.getGrowthEstimatesYahoo(ticker)
236            elif option == "zacks":
237                return self.getGrowthEstimatesZacks(ticker)
238            elif option == "seeking":
239                return self.getGrowthEstimatesSeeking(ticker)
240
241        except Exception as e:
242            return str(e)
243
244    def getGrowthEstimatesYahoo(self, ticker):
245        """
246        Obtiene las estimaciones de crecimiento para la acción de la webd e Yahoo Finance.
247
248        Args:
249            ticker (str): El símbolo de ticker de la acción.
250
251        Returns:
252            str: Las estimaciones de crecimiento.
253        """
254        url = f"https://finance.yahoo.com/quote/{ticker}/analysis?ltr=1"
255        headers = {
256            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
257        }
258        try:
259            response = requests.get(url, headers=headers)
260            response.raise_for_status()
261            soup = BeautifulSoup(response.text, "html.parser")
262            desired_table = soup.find_all("table")[5]
263            target_value = (
264                desired_table.find_all("tr")[5].find_all("td")[1].text.strip()
265            )
266            return target_value
267        except IndexError:
268            raise Exception(
269                "No se encontraron suficientes tablas, filas o celdas en la página"
270            )
271        except requests.exceptions.RequestException as e:
272            raise Exception(f"Error en la solicitud: {e}")
273
274    def getGrowthEstimatesZacks(self, ticker):
275        """
276        Obtiene las estimaciones de crecimiento para la acción de la web de Zacks.
277
278        Args:
279            ticker (str): El símbolo de ticker de la acción.
280
281        Returns:
282            str: Las estimaciones de crecimiento.
283        """
284        url = f"https://www.zacks.com/stock/quote/{ticker}?q={ticker}"
285        headers = {
286            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
287        }
288        try:
289            response = requests.get(url, headers=headers)
290            response.raise_for_status()
291            soup = BeautifulSoup(response.text, "html.parser")
292            desired_table = soup.find_all("dl", class_="abut_bottom")
293            # print(desired_table)
294            target_value = desired_table[15].find_all("dd")[0].text.strip()
295            # print(target_value)
296            return target_value
297        except IndexError:
298            raise Exception(
299                "No se encontraron suficientes tablas, filas o celdas en la página"
300            )
301        except requests.exceptions.RequestException as e:
302            raise Exception(f"Error en la solicitud: {e}")
303
304    def getGrowthEstimatesSeeking(self, ticker):
305        """
306        Obtiene las estimaciones de crecimiento para la acción de la web de Seeking Alpha.
307
308        Args:
309            ticker (str): El símbolo de ticker de la acción.
310
311        Returns:
312            str: Las estimaciones de crecimiento.
313        """
314        url = f"https://seekingalpha.com/symbol/{ticker}/growth"
315        headers = {
316            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
317        }
318        try:
319            response = requests.get(url, headers=headers)
320            # print(response)
321            response.raise_for_status()
322            soup = BeautifulSoup(response.text, "html.parser")
323            desired_table = soup.find_all("table")[0]
324            target_value = (
325                desired_table.find_all("tr")[11].find_all("td")[1].text.strip()
326            )
327            # print(target_value, 'hi')
328            return target_value
329        except IndexError:
330            raise Exception(
331                "No se encontraron suficientes tablas, filas o celdas en la página"
332            )
333        except requests.exceptions.RequestException as e:
334            raise Exception(f"Error en la solicitud: {e}")
335
336    def waccCalculator(self, rf, rm):
337        """
338        Calcula el costo promedio ponderado del capital (WACC).
339
340        Args:
341            rf (float): Tasa libre de riesgo.
342            rm (float): Retorno del mercado.
343
344        Returns:
345            float: El WACC calculado.
346        """
347        last_year_total_debt = self.getTotalDebt(self.balanceSheet)
348
349        beta = self.info.get("beta", 1)
350
351        ke = rf + (beta * (rm - rf))
352
353        e = self.info.get("marketCap")
354        if e is None:
355            raise Exception(
356                "No se pudo obtener la capitalización bursátil de la acción"
357            )
358
359        total_debt_ED = e + last_year_total_debt
360
361        total_equity = ke * (e / total_debt_ED)
362
363        last_year_interest_expense = self.getLastYearValue(
364            self.financials, "Interest Expense"
365        )
366
367        last_year_current_debt = self.getLastYearValue(
368            self.balanceSheet, "Current Debt And Capital Lease Obligation"
369        )
370
371        last_year_long_term_debt = self.getLastYearValue(
372            self.balanceSheet, "Long Term Debt"
373        )
374
375        kd = last_year_interest_expense / (
376            last_year_current_debt + last_year_long_term_debt
377        )
378
379        last_year_tax_provision = self.getLastYearValue(
380            self.incomeStmt, "Tax Provision"
381        )
382
383        last_year_pretax_income = self.getLastYearValue(
384            self.incomeStmt, "Pretax Income"
385        )
386
387        t = last_year_tax_provision / last_year_pretax_income
388
389        total_debt_cost = kd * (1 - t) * (last_year_total_debt / total_debt_ED)
390
391        return total_equity + total_debt_cost
392
393    def dcf(self, tickerStr, g, rf, rm, option):
394        """
395        Calcula el valor intrínseco de una acción utilizando el modelo de descuento de flujos de efectivo (DCF).
396
397        Args:
398            tickerStr (str): El símbolo de ticker de la acción.
399            g (float): Tasa de crecimiento a perpetuidad.
400            rf (float): Tasa libre de riesgo.
401            rm (float): Retorno del mercado.
402
403        Returns:
404            list: Una lista que contiene varios valores calculados.
405        """
406        try:
407            last_year_total_debt = self.getTotalDebt(self.balanceSheet)
408            growthFCF = self.getGrowthEstimates(tickerStr, option)
409            print(option, growthFCF)
410            printGrowthFCF = growthFCF
411            try:
412                growthFCF = float(growthFCF.replace("%", "")) / 100
413            except:
414                FCFGrow = self.cashFlow.iloc[0]
415                growthFCF = (
416                    (FCFGrow.iloc[0] / FCFGrow.iloc[-1]) ** (1 / len(FCFGrow))
417                ) - 1
418                printGrowthFCF = "{:.2f}%".format(growthFCF * 100)
419
420            wacc = self.waccCalculator(rf, rm)
421            if type(wacc) != float:
422                raise Exception(wacc)
423
424            last_year_fcf = self.getLastYearValue(self.cashFlow, "Free Cash Flow")
425            printFCF = last_year_fcf
426
427            FCFn = [
428                int(format(last_year_fcf * (1 + growthFCF) ** i, ".0f"))
429                for i in range(1, 6)
430            ]
431
432            terminal_value = (FCFn[-1] * (1 + g)) / (wacc - g)
433            FNFnLast = FCFn[-1]
434            FCFn[-1] = int(format(FCFn[-1] + terminal_value, ".0f"))
435
436            enterprise_value = sum(
437                [FCFn[i] / ((1 + wacc) ** (i + 1)) for i in range(5)]
438            )
439
440            last_year_cash = self.getLastYearValue(
441                self.balanceSheet, "Cash Cash Equivalents And Short Term Investments"
442            )
443
444            equity_value = enterprise_value + last_year_cash - last_year_total_debt
445
446            shares_outstanding = self.info["sharesOutstanding"]
447
448            intrinsic_value = equity_value / shares_outstanding
449
450            price = self.info["regularMarketPreviousClose"]
451
452            difference = 100 + (((intrinsic_value - price) / price) * 100)
453
454            FCFn.pop()
455            FCFn.append(FNFnLast)
456
457            return [
458                (format((wacc * 100), ".2f") + " %"),
459                ("$ " + "{:,.0f}".format(printFCF).replace(",", ".")),
460                FCFn,
461                printGrowthFCF,
462                ("$ " + "{:,.0f}".format(equity_value, ".0f").replace(",", ".")),
463                ("$ " + str(price)),
464                ("$ " + format(intrinsic_value, ".2f")),
465                (format((difference), ".2f") + "%"),
466            ]
467        except Exception as e:
468            return str(e)
DcfCalculator(ticker=None)
12    def __init__(self, ticker=None):
13        """
14        Inicializa el objeto FinanceAnalyzer con los datos financieros del ticker especificado.
15
16        Args:
17            ticker (str): El símbolo de ticker de la acción.
18        """
19        self.balanceSheet = self.getBalanceSheet(ticker)
20        """El balance de la acción."""
21        self.info = self.getInfo(ticker)
22        """La información básica de la acción."""
23        self.financials = self.getFinancials(ticker)
24        """Los estados financieros de la acción."""
25        self.incomeStmt = self.getIncomeStmt(ticker)
26        """El estado de ingresos de la acción."""
27        self.cashFlow = self.getCashFlow(ticker)
28        """El flujo de efectivo de la acción."""

Inicializa el objeto FinanceAnalyzer con los datos financieros del ticker especificado.

Args: ticker (str): El símbolo de ticker de la acción.

balanceSheet

El balance de la acción.

info

La información básica de la acción.

financials

Los estados financieros de la acción.

incomeStmt

El estado de ingresos de la acción.

cashFlow

El flujo de efectivo de la acción.

def getAttribute(self, ticker, attribute, error_message):
30    def getAttribute(self, ticker, attribute, error_message):
31        """
32        Obtiene los datos de yahoo finance
33
34        Args:
35            ticker (str): El símbolo de ticker de la acción.
36            attribute (str): El nombre del atributo a obtener.
37            error_message (str): El mensaje de error a mostrar si el atributo no se puede obtener.
38
39        Returns:
40            obj: El valor del atributo.
41        """
42        try:
43            return getattr(ticker, attribute)
44        except:
45            raise Exception(error_message)

Obtiene los datos de yahoo finance

Args: ticker (str): El símbolo de ticker de la acción. attribute (str): El nombre del atributo a obtener. error_message (str): El mensaje de error a mostrar si el atributo no se puede obtener.

Returns: obj: El valor del atributo.

def getFinancials(self, ticker):
47    def getFinancials(self, ticker):
48        """
49        Obtiene los estados financieros del ticker especificado.
50
51        Args:
52            ticker (str): El símbolo de ticker de la acción.
53
54        Returns:
55            obj: Los estados financieros del ticker.
56        """
57        return self.getAttribute(
58            ticker,
59            "financials",
60            "No se pudo obtener los estados financieros de la acción",
61        )

Obtiene los estados financieros del ticker especificado.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: obj: Los estados financieros del ticker.

def getBalanceSheet(self, ticker):
63    def getBalanceSheet(self, ticker):
64        """
65        Obtiene el balance de la acción del ticker especificado.
66
67        Args:
68            ticker (str): El símbolo de ticker de la acción.
69
70        Returns:
71            obj: El balance de la acción.
72        """
73        return self.getAttribute(
74            ticker, "balance_sheet", "No se pudo obtener el balance de la acción"
75        )

Obtiene el balance de la acción del ticker especificado.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: obj: El balance de la acción.

def getIncomeStmt(self, ticker):
77    def getIncomeStmt(self, ticker):
78        """
79        Obtiene el estado de ingresos de la acción del ticker especificado.
80
81        Args:
82            ticker (str): El símbolo de ticker de la acción.
83
84        Returns:
85            obj: El estado de ingresos de la acción.
86        """
87        return self.getAttribute(
88            ticker,
89            "income_stmt",
90            "No se pudo obtener el estado de los ingresos de la acción",
91        )

Obtiene el estado de ingresos de la acción del ticker especificado.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: obj: El estado de ingresos de la acción.

def getInfo(self, ticker):
 93    def getInfo(self, ticker):
 94        """
 95        Obtiene la información básica de la acción del ticker especificado.
 96
 97        Args:
 98            ticker (str): El símbolo de ticker de la acción.
 99
100        Returns:
101            obj: La información básica de la acción.
102        """
103        return self.getAttribute(
104            ticker, "info", "No se pudo obtener la información de la acción"
105        )

Obtiene la información básica de la acción del ticker especificado.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: obj: La información básica de la acción.

def getCashFlow(self, ticker):
107    def getCashFlow(self, ticker):
108        """
109        Obtiene el flujo de efectivo de la acción del ticker especificado.
110
111        Args:
112            ticker (str): El símbolo de ticker de la acción.
113
114        Returns:
115            obj: El flujo de efectivo de la acción.
116        """
117        return self.getAttribute(
118            ticker, "cashflow", "No se pudo obtener el flujo de caja de la acción"
119        )

Obtiene el flujo de efectivo de la acción del ticker especificado.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: obj: El flujo de efectivo de la acción.

def getEbitda(self):
121    def getEbitda(self):
122        """
123        Calcula el EBITDA de la acción.
124
125        Returns:
126            float: El EBITDA de la acción.
127        """
128        try:
129            ebitda = self.getLastYearValue(self.incomeStmt, "EBITDA")
130        except Exception as e:
131            raise Exception("No se pudo obtener el EBITDA de la acción") from e
132        return ebitda

Calcula el EBITDA de la acción.

Returns: float: El EBITDA de la acción.

def getEarnings(self):
134    def getEarnings(self):
135        """
136        Calcula las ganancias de la acción.
137
138        Returns:
139            float: Las ganancias de la acción.
140        """
141        try:
142            grossProfit = self.getLastYearValue(self.incomeStmt, "Gross Profit")
143            totalRevenue = self.getLastYearValue(self.incomeStmt, "Total Revenue")
144            return (grossProfit / totalRevenue) * 100
145        except Exception as e:
146            raise Exception("No se pudo obtener las ganancias de la acción") from e

Calcula las ganancias de la acción.

Returns: float: Las ganancias de la acción.

def getRoe(self):
148    def getRoe(self):
149        """
150        Calcula el ROE (Return on Equity) de la acción.
151
152        Returns:
153            float: El ROE de la acción.
154        """
155        try:
156            last_year_net_income = self.getLastYearValue(self.incomeStmt, "Net Income")
157        except Exception as e:
158            raise Exception("No se pudo obtener el net income de la acción") from e
159
160        try:
161            last_year_equity = self.getLastYearValue(
162                self.balanceSheet, "Stockholders Equity"
163            )
164        except Exception as e:
165            raise Exception("No se pudo obtener el equity de la acción") from e
166
167        return (last_year_net_income / last_year_equity) * 100

Calcula el ROE (Return on Equity) de la acción.

Returns: float: El ROE de la acción.

def getPer(self):
169    def getPer(self):
170        """
171        Obtiene el PER (Price to Earnings Ratio) de la acción.
172
173        Returns:
174            float: El PER de la acción.
175        """
176        try:
177            return self.info["trailingPE"]
178        except:
179            raise Exception("No se pudo obtener el PER de la acción")

Obtiene el PER (Price to Earnings Ratio) de la acción.

Returns: float: El PER de la acción.

def getLastYearValue(self, data, label):
181    def getLastYearValue(self, data, label):
182        """
183        Obtiene el valor del año pasado para una etiqueta de datos específica.
184
185        Args:
186            data (DataFrame): Los datos financieros.
187            label (str): La etiqueta de datos específica.
188
189        Returns:
190            float: El valor del año pasado para la etiqueta de datos especificada.
191        """
192        try:
193            value = data.loc[label]
194            i = 0
195            last_year_value = value.iloc[i]
196            while math.isnan(value.iloc[i]):
197                i += 1
198                last_year_value = value.iloc[i]
199            return last_year_value
200        except:
201            try:
202                if label == "Current Debt And Capital Lease Obligation":
203                    return self.getLastYearValue(data, "Current Deferred Liabilities")
204            except:
205                raise Exception(f"No se pudo obtener {label} de la acción")
206            raise Exception(f"No se pudo obtener {label} de la acción")

Obtiene el valor del año pasado para una etiqueta de datos específica.

Args: data (DataFrame): Los datos financieros. label (str): La etiqueta de datos específica.

Returns: float: El valor del año pasado para la etiqueta de datos especificada.

def getTotalDebt(self, balanceSheet):
208    def getTotalDebt(self, balanceSheet):
209        """
210        Calcula la deuda total de la acción.
211
212        Args:
213            balanceSheet (DataFrame): El balance de la acción.
214
215        Returns:
216            float: La deuda total de la acción.
217        """
218        try:
219            return self.getLastYearValue(balanceSheet, "Total Debt")
220        except Exception as e:
221            raise Exception("No se pudo obtener la deuda total de la acción") from e

Calcula la deuda total de la acción.

Args: balanceSheet (DataFrame): El balance de la acción.

Returns: float: La deuda total de la acción.

def getGrowthEstimates(self, ticker, option):
223    def getGrowthEstimates(self, ticker, option):
224        """
225        Obtiene las estimaciones de crecimiento para la acción.
226
227        Args:
228            ticker (str): El símbolo de ticker de la acción.
229
230        Returns:
231            str: Las estimaciones de crecimiento.
232        """
233        try:
234            if option == "yahoo":
235                return self.getGrowthEstimatesYahoo(ticker)
236            elif option == "zacks":
237                return self.getGrowthEstimatesZacks(ticker)
238            elif option == "seeking":
239                return self.getGrowthEstimatesSeeking(ticker)
240
241        except Exception as e:
242            return str(e)

Obtiene las estimaciones de crecimiento para la acción.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: str: Las estimaciones de crecimiento.

def getGrowthEstimatesYahoo(self, ticker):
244    def getGrowthEstimatesYahoo(self, ticker):
245        """
246        Obtiene las estimaciones de crecimiento para la acción de la webd e Yahoo Finance.
247
248        Args:
249            ticker (str): El símbolo de ticker de la acción.
250
251        Returns:
252            str: Las estimaciones de crecimiento.
253        """
254        url = f"https://finance.yahoo.com/quote/{ticker}/analysis?ltr=1"
255        headers = {
256            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
257        }
258        try:
259            response = requests.get(url, headers=headers)
260            response.raise_for_status()
261            soup = BeautifulSoup(response.text, "html.parser")
262            desired_table = soup.find_all("table")[5]
263            target_value = (
264                desired_table.find_all("tr")[5].find_all("td")[1].text.strip()
265            )
266            return target_value
267        except IndexError:
268            raise Exception(
269                "No se encontraron suficientes tablas, filas o celdas en la página"
270            )
271        except requests.exceptions.RequestException as e:
272            raise Exception(f"Error en la solicitud: {e}")

Obtiene las estimaciones de crecimiento para la acción de la webd e Yahoo Finance.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: str: Las estimaciones de crecimiento.

def getGrowthEstimatesZacks(self, ticker):
274    def getGrowthEstimatesZacks(self, ticker):
275        """
276        Obtiene las estimaciones de crecimiento para la acción de la web de Zacks.
277
278        Args:
279            ticker (str): El símbolo de ticker de la acción.
280
281        Returns:
282            str: Las estimaciones de crecimiento.
283        """
284        url = f"https://www.zacks.com/stock/quote/{ticker}?q={ticker}"
285        headers = {
286            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
287        }
288        try:
289            response = requests.get(url, headers=headers)
290            response.raise_for_status()
291            soup = BeautifulSoup(response.text, "html.parser")
292            desired_table = soup.find_all("dl", class_="abut_bottom")
293            # print(desired_table)
294            target_value = desired_table[15].find_all("dd")[0].text.strip()
295            # print(target_value)
296            return target_value
297        except IndexError:
298            raise Exception(
299                "No se encontraron suficientes tablas, filas o celdas en la página"
300            )
301        except requests.exceptions.RequestException as e:
302            raise Exception(f"Error en la solicitud: {e}")

Obtiene las estimaciones de crecimiento para la acción de la web de Zacks.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: str: Las estimaciones de crecimiento.

def getGrowthEstimatesSeeking(self, ticker):
304    def getGrowthEstimatesSeeking(self, ticker):
305        """
306        Obtiene las estimaciones de crecimiento para la acción de la web de Seeking Alpha.
307
308        Args:
309            ticker (str): El símbolo de ticker de la acción.
310
311        Returns:
312            str: Las estimaciones de crecimiento.
313        """
314        url = f"https://seekingalpha.com/symbol/{ticker}/growth"
315        headers = {
316            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
317        }
318        try:
319            response = requests.get(url, headers=headers)
320            # print(response)
321            response.raise_for_status()
322            soup = BeautifulSoup(response.text, "html.parser")
323            desired_table = soup.find_all("table")[0]
324            target_value = (
325                desired_table.find_all("tr")[11].find_all("td")[1].text.strip()
326            )
327            # print(target_value, 'hi')
328            return target_value
329        except IndexError:
330            raise Exception(
331                "No se encontraron suficientes tablas, filas o celdas en la página"
332            )
333        except requests.exceptions.RequestException as e:
334            raise Exception(f"Error en la solicitud: {e}")

Obtiene las estimaciones de crecimiento para la acción de la web de Seeking Alpha.

Args: ticker (str): El símbolo de ticker de la acción.

Returns: str: Las estimaciones de crecimiento.

def waccCalculator(self, rf, rm):
336    def waccCalculator(self, rf, rm):
337        """
338        Calcula el costo promedio ponderado del capital (WACC).
339
340        Args:
341            rf (float): Tasa libre de riesgo.
342            rm (float): Retorno del mercado.
343
344        Returns:
345            float: El WACC calculado.
346        """
347        last_year_total_debt = self.getTotalDebt(self.balanceSheet)
348
349        beta = self.info.get("beta", 1)
350
351        ke = rf + (beta * (rm - rf))
352
353        e = self.info.get("marketCap")
354        if e is None:
355            raise Exception(
356                "No se pudo obtener la capitalización bursátil de la acción"
357            )
358
359        total_debt_ED = e + last_year_total_debt
360
361        total_equity = ke * (e / total_debt_ED)
362
363        last_year_interest_expense = self.getLastYearValue(
364            self.financials, "Interest Expense"
365        )
366
367        last_year_current_debt = self.getLastYearValue(
368            self.balanceSheet, "Current Debt And Capital Lease Obligation"
369        )
370
371        last_year_long_term_debt = self.getLastYearValue(
372            self.balanceSheet, "Long Term Debt"
373        )
374
375        kd = last_year_interest_expense / (
376            last_year_current_debt + last_year_long_term_debt
377        )
378
379        last_year_tax_provision = self.getLastYearValue(
380            self.incomeStmt, "Tax Provision"
381        )
382
383        last_year_pretax_income = self.getLastYearValue(
384            self.incomeStmt, "Pretax Income"
385        )
386
387        t = last_year_tax_provision / last_year_pretax_income
388
389        total_debt_cost = kd * (1 - t) * (last_year_total_debt / total_debt_ED)
390
391        return total_equity + total_debt_cost

Calcula el costo promedio ponderado del capital (WACC).

Args: rf (float): Tasa libre de riesgo. rm (float): Retorno del mercado.

Returns: float: El WACC calculado.

def dcf(self, tickerStr, g, rf, rm, option):
393    def dcf(self, tickerStr, g, rf, rm, option):
394        """
395        Calcula el valor intrínseco de una acción utilizando el modelo de descuento de flujos de efectivo (DCF).
396
397        Args:
398            tickerStr (str): El símbolo de ticker de la acción.
399            g (float): Tasa de crecimiento a perpetuidad.
400            rf (float): Tasa libre de riesgo.
401            rm (float): Retorno del mercado.
402
403        Returns:
404            list: Una lista que contiene varios valores calculados.
405        """
406        try:
407            last_year_total_debt = self.getTotalDebt(self.balanceSheet)
408            growthFCF = self.getGrowthEstimates(tickerStr, option)
409            print(option, growthFCF)
410            printGrowthFCF = growthFCF
411            try:
412                growthFCF = float(growthFCF.replace("%", "")) / 100
413            except:
414                FCFGrow = self.cashFlow.iloc[0]
415                growthFCF = (
416                    (FCFGrow.iloc[0] / FCFGrow.iloc[-1]) ** (1 / len(FCFGrow))
417                ) - 1
418                printGrowthFCF = "{:.2f}%".format(growthFCF * 100)
419
420            wacc = self.waccCalculator(rf, rm)
421            if type(wacc) != float:
422                raise Exception(wacc)
423
424            last_year_fcf = self.getLastYearValue(self.cashFlow, "Free Cash Flow")
425            printFCF = last_year_fcf
426
427            FCFn = [
428                int(format(last_year_fcf * (1 + growthFCF) ** i, ".0f"))
429                for i in range(1, 6)
430            ]
431
432            terminal_value = (FCFn[-1] * (1 + g)) / (wacc - g)
433            FNFnLast = FCFn[-1]
434            FCFn[-1] = int(format(FCFn[-1] + terminal_value, ".0f"))
435
436            enterprise_value = sum(
437                [FCFn[i] / ((1 + wacc) ** (i + 1)) for i in range(5)]
438            )
439
440            last_year_cash = self.getLastYearValue(
441                self.balanceSheet, "Cash Cash Equivalents And Short Term Investments"
442            )
443
444            equity_value = enterprise_value + last_year_cash - last_year_total_debt
445
446            shares_outstanding = self.info["sharesOutstanding"]
447
448            intrinsic_value = equity_value / shares_outstanding
449
450            price = self.info["regularMarketPreviousClose"]
451
452            difference = 100 + (((intrinsic_value - price) / price) * 100)
453
454            FCFn.pop()
455            FCFn.append(FNFnLast)
456
457            return [
458                (format((wacc * 100), ".2f") + " %"),
459                ("$ " + "{:,.0f}".format(printFCF).replace(",", ".")),
460                FCFn,
461                printGrowthFCF,
462                ("$ " + "{:,.0f}".format(equity_value, ".0f").replace(",", ".")),
463                ("$ " + str(price)),
464                ("$ " + format(intrinsic_value, ".2f")),
465                (format((difference), ".2f") + "%"),
466            ]
467        except Exception as e:
468            return str(e)

Calcula el valor intrínseco de una acción utilizando el modelo de descuento de flujos de efectivo (DCF).

Args: tickerStr (str): El símbolo de ticker de la acción. g (float): Tasa de crecimiento a perpetuidad. rf (float): Tasa libre de riesgo. rm (float): Retorno del mercado.

Returns: list: Una lista que contiene varios valores calculados.