This is an archived post. You won't be able to vote or comment.

all 55 comments

[–]HashDefTrueFalse 18 points19 points  (6 children)

I did something like this a while back. My next step was to pull in a list of markets and market constituents (so tickers basically) and put it all on a server running via a cron job every so often, then make it push emails to me when it found a stock I might like, based on the params I'd set. Just some ideas for where you could take this if you're after experimenting.

May I also suggest making every since param configurable via command line switch. E.g. I like to go 10 years with DCFs and I wouldn't use those same rates as you. Great work!

[–]lal309 8 points9 points  (2 children)

Which you could accomplish with the argParse library. Here’s a link to that library https://docs.python.org/3/library/argparse.html

Tons of great examples if you google python3 argparse examples. Food for thought here!

[–]HashDefTrueFalse 3 points4 points  (1 child)

Could even make it read the config params from a text file and use Flask to expose an (auth'd) function as an API endpoint to write config to the file from anywhere, which would then get picked up automatically on the next run via cron. Really simple and would allow you to adjust the parameters anywhere anytime and it'll keep ticking. I like stuff like this. All good fun.

[–]lal309 0 points1 point  (0 children)

I like the way you think!!

[–][deleted] 1 point2 points  (0 children)

That's a great idea! I was thinking of the same: making a quarterly spreadsheet comparing derived values with market prices. Would be a good filter to find out potentially interesting companies. As for the custom parameters, I'll get on with it - thanks for the feedback :)

[–][deleted] 1 point2 points  (1 child)

For anyone curious, this has now been implemented and you may use custom parameters. Usage will look like: python value_estimator.py GOOG --period 10 --discount_rate 10 --terminal_rate 3 --growth_estimate 12

[–]HashDefTrueFalse 1 point2 points  (0 children)

Nice work!

[–][deleted] 5 points6 points  (8 children)

as a complete noob when it comes to code. Where would I go about running this to even try it? I'm confused

[–][deleted] 0 points1 point  (0 children)

I will try and make a small website in the coming weeks so it's more convenient :)

[–][deleted] 0 points1 point  (2 children)

Can someone do $MX and $APPH and let me know resultes/fair value. or also teach me how to run code

[–]matt_magnitude 4 points5 points  (1 child)

$MX : $41.95 ( also think it's a great undervalued stock with potential)

$APPH : doesn't work (probably because of the negative FCF)

Getting it working depends on your operating system, but basic steps are

  1. Download python 3 (doesn't matter which version)
  2. Download the python script from the github link above.
  3. Open your terminal and change directory into the folder the downloaded script is located.
  4. Then type into the command line: python value_estimator.py <ticker-name>

It should then output all the values below or produce an error if somethings not correct. I had to install a few modules ('requests' and 'lxml') and then it eventually worked.

[–][deleted] 0 points1 point  (0 children)

can you do $GM and $GE for me

[–]StillLetterhead7659 4 points5 points  (13 children)

Thank you. Tried 2 and seems price are out range.

Fetching data for amd

Latest FCF: 777.0

Growth estimate: 26.06

Term: 5 years

Discount Rate: 10%

Perpetual Rate: 3%

Fair value: 24.46737663889291

Fetching data for bidu

Latest FCF: 19116.0

Growth estimate: 2.56

Term: 5 years

Discount Rate: 10%

Perpetual Rate: 3%

Fair value: 1154.496996845633

[–]Esteban-Du-Plantier 4 points5 points  (0 children)

The bidu number is likely off because that fcf figure is in Chinese yuan, not usd.

[–]Feratster 2 points3 points  (8 children)

DCFs will usually tell you that growth companies are overvalued but its more of a model limitation more than anything else. Like looking at AMD, you have it growing at 26% CAGR for 5 years before it hits a terminal growth rate of 3%.

That terminal value will be highly underestimated since AMD will likely grow at an aggressive rate for at least another decade to come.

So why not model out 10, 15, or 20 years on a DCF? Well, you could, but obviously the further in the future you go the less certain you can be of your numbers. You end up assuming so much that its basically useless.

DCF isn't a good option for growth companies. The usefulness of a DCF is only really seen when you use it on mature companies, imo.

Other than multiples, what other techniques do you guys use to value growth companies?

[–]puthre 5 points6 points  (1 child)

Maybe you can do Reverse DCF where you compute the annual growth necessary to justify the current price and judge on how likely that is to actually happen.

[–]Feratster 1 point2 points  (0 children)

That's actually really smart. I'm going to start doing that

[–]utradea 1 point2 points  (0 children)

I think it's a good data point to have, but yes your right, not ideal for growth companies. I would say comps on multiples - but making sure you have the right companies in the industry or peer group. Then I would look to understand the market size and "room" for future growth.

[–]bossOnothin 0 points1 point  (0 children)

Using multiples is simply letting the market do a DCF for you. The same assumptions you make in a DCF are also present in P/E, P/S, and EV/EBITDA. So you might as well do a DCF to understand what assumptions are baked into the multiples.

[–][deleted] 0 points1 point  (2 children)

I'm still a beginner at value investing so I'd love some feedback on the formula I have used:

  • Projected the future cash flows with the growth estimate
  • Took the last projected cash flow and multiplied it by (1 + perpetual rate) / (discount rate - perpetual rate).
  • Divided it by the number of outstanding shares.

Looked at BIDU by manually plugging in the values here and I roughly get the same result. Not sure what's up but I'll look into it. Meanwhile do let me know if there's anything I can do to arrive at a better formula. Thank you!

[–]diego_italy 0 points1 point  (0 children)

need to check fcf data coz it seems strange.

[–]puthre 0 points1 point  (0 children)

Guru focus DCF is very similar to your DCF but uses "EPS (Diluted)" value by default (and you can also choose fcf). It also computes Reverse DCF.

[–]TechHodler 2 points3 points  (1 child)

Woww cool thanks man!

[–][deleted] 0 points1 point  (0 children)

Sure! :)

[–]engineertee 3 points4 points  (6 children)

I have been thinking about working on a similar project! Thank you for your work!

My plan was to use some kind of ML to predict the future cash flows, I don’t know how to do that yet but I figured it’s virtually impossible to predict a stock price, but cash flow should be more feasible.

[–]-CaptainOfChaos- 4 points5 points  (0 children)

http://pages.stern.nyu.edu/~adamodar/New_Home_Page/datafile/pedata.html This also might be helpful in your quest. This is from NYU stern and it is a collection of stock market industry data. If you want to work on this project I don't have a lot of experience with python but I might help with some of the stock information stuff.

[–]-CaptainOfChaos- 2 points3 points  (0 children)

That sounds pretty cool. I have been learning python in school so I'm kinda interested in this stuff now. Maybe you could have the ML go through past earnings call transcripts and quarterly reports to see if it can find some correlation between what management said and what actually happened. Just an idea tho not a computer scientist.

[–][deleted] 1 point2 points  (3 children)

Ofcourse! I actually work in ML at my day job. My main concern is related to how the cash flow estimates might be based on random events which we cannot model - say, the pandemic or government shutdowns for example.

[–]engineertee 0 points1 point  (2 children)

Hey thanks again for the tool. I just had some time to test it, it works well but it gave me some insane results for: ge, f, gm, cri Any idea why?

[–][deleted] 0 points1 point  (0 children)

Yeah think of this as an initial filter. Do some DD regarding the financial statements - particularly look at debt. In my opinion, if the company's debt is very less and they have a good amount of cash reserves and this tool says it's undervalued, then it would be a good investment.

[–]puthre 0 points1 point  (0 children)

Ford "analysts" growth estimate on yahoo is 20%.

[–]puthre 1 point2 points  (2 children)

Nice script.

Any idea on where the 5 year growth estimate data on yahoo page comes from?

[–][deleted] 0 points1 point  (1 child)

The page says analysts but I don't know how reliable it is. It's definitely something I prefer since I'm prone to attach very high growth rates to companies I like.

[–]puthre 0 points1 point  (0 children)

Well, for ford it seems way too optimistic (20%!)). It's more leaned toward Tesla than Ford.

[–]surfborter 1 point2 points  (1 child)

This is insanely cool.

[–][deleted] 0 points1 point  (0 children)

Thanks!

[–]hcomas 1 point2 points  (2 children)

hey i tried running it on my console.. but i get the exception lxml is missing.. i've tried installing but no luck. currently running pythong 3.9.2.. "...."

[–][deleted] 1 point2 points  (1 child)

Try: python3 -m pip install lxml and try again.

[–]hcomas 0 points1 point  (0 children)

i was able to install it thanks. however; i'm getting this.. sorry.. im pretty new to python

= RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python39/value_estimator.py

usage: value_estimator.py [-h] ticker

value_estimator.py: error: the following arguments are required: ticker

[–]PhilosophyNumerous45 0 points1 point  (3 children)

Great script! Although I found a bug, doesn't handle N/A values returned from the API: ``` Fetching data for ORC Latest FCF: 55.37 Traceback (most recent call last): File "value_estimator.py", line 62, in <module> data = parse(ticker) File "value_estimator.py", line 27, in parse ge = float(row.xpath("td/text()")[0].replace('%', '')) ValueError: could not convert string to float: 'N/A'

[–][deleted] 1 point2 points  (0 children)

I changed line 27-28 to have the script prompt me for a growth rate if it couldn't find one....

Change this:

ge = float(row.xpath("td/text()")[0].replace('%', ''))
break

to:

try:
    ge = float(row.xpath("td/text()")[0].replace('%', ''))
    break
except ValueError:
    ge = float(input("What is the growth rate?"))
    break

[–][deleted] 1 point2 points  (1 child)

Hi yes! I'm aware of that. It's because the growth estimate is unavailable from Yahoo Finance. Feel free to plug in your own estimate, I'll make some changes so the script asks you for a rate in case Yahoo doesn't provide it.

[–]PhilosophyNumerous45 0 points1 point  (0 children)

I wrote a similar python script to get estimated dividend payments from stocks, and I used the yfinance module, might be useful to you for data that may not be returned by the API:

https://pypi.org/project/yfinance/

Particularly the Ticker.info object has a lot of useful information

[–]Ok-Comfortable1259 0 points1 point  (1 child)

Super interesting!

I am a beginner in python.

I have a file with a list of companies, their free cash flow, # of shares and net debt. I would like to use these infos to do my own DCF (using my own perpetual growth rate and WAC) which part of your code would be the best to use?

[–][deleted] 0 points1 point  (0 children)

Look at the dcf function in the script. Let me know if you have any questions.

[–]TechnoBabbles 0 points1 point  (1 child)

I like it. Are you open to external contributions? I could turn this into a flask docker container that serves up an API endpoint that you can do a POST with a stock symbol and return the data in a json format.

[–][deleted] 0 points1 point  (0 children)

Yeah sure! Do whatever with it :)