Warren E. Buffett’s Value Investing

Stock screening from Buffett’s investing principles.

Photo Creds: Flickr

Preface

Warren E. Buffett is the person who has made the most money from stocks in the history of the world. He returned to Omaha in 1956 and started with $100. As of August 1999, his total personal assets have reached $36 B, becoming the second richest person in U.S. in that time. Buffet’s investment principles are very simple. First, ignore the daily rise and fall of stock prices. Second, do not worry about changes in the overall economics situation. Third, invest with the mentality of buying a company instead of investing in stocks.

  • Company:
    a. Is this company simple and understandable?
    b. Is operating history of this company stable?
    c. Is the company’s long-term development prospects promising?
  • Operation:
    a. Whether the operator is rational?
    b. Whether the operator is honest and frank with his shareholders?
    c. Whether the operator will blindly follow the action of other legal entites ?
  • Finance:
    a. Focus on Return on Equity (ROE) rather than earnings per share (EPS).
    b. Calculate discounted free cash flow (DCF).
    c. Looking for high gross margin (GM).
    d. For each dollars of retained earnings make sure that the company has created at least on dollar of market value.
  • Market:
    a. What is the value of this company?
    b. Whether we can buy stocks at a significant value discount, that is, obtain a margin of safty.

The Editing Environment and Modules Required

We use Windows OS and Jupyter Notebook in this article.

import tejapi
import pandas as pd
import numpy as np
tejapi.ApiConfig.api_key = 'Your Key'
tejapi.ApiConfig.ignoretz = True

Note: Remember to replace ‘Your key’ with the one you applied for. The last line indicates that we ignore the time zone.

The highlights of the article

  • Quantify investment principles
  • Database search
  • Data filtering: loc , groupby , pivot_table

Quantitative Indicators

Due to part of principles cannot be quantified. Therefore, we choose only quantifiable principles. The basis of principles is to evaluate earning ability of company.

  1. Most recent year ROE > Industry average ROE:save to set_1
  2. Three-year average ROE > 15%:save to set_2
  3. Most recent year Gross margin > Industry average GM:save to set_3
  4. Increase in market value within 7 years / Increase in retained earnings within 7 years > 1:save to set_4
  5. (Most recent year FCF / FCF 7 year ago ) -1 > 1:save to set_5
  6. Current market value / The discounted value of FCF in next 10 years < 1 :save to set_6

Investing Strategy

We choose the stocks which are eligible, and buy on 2020/1/1, hold until 2020/12/31. Each condition will make a set to save eligible stocks. Finally, make the intersection to get portfolio.

When we comparing whether each dollar of retained earnings creates a dollar of market value, it involves whether the company has been listed for long enough. Therefore we selected the companies which are alive in 2020 and listed for more than 7 years. Due to the formula of ROE, we can improved by borrowing, so we exclude the industries with high debt ratio such as banking and finance holding.

Stock Pool

Step 1. Search listed company database

tejapi.search_table("上市日")
Results

Step 2. We use TWN/AIND database. Filter choose listed before 2013 and exclude industry (28 & 29).

comp_data = tejapi.get('TWN/AIND',
elist_day1 ={'lt':'2013-01-01'},
ind = {'ne':('28', '30')},
mkt = 'TSE',
opts = {'columns':['coid', 'elist_day1',
'ind']},
chinese_column_name=True,
paginate=True
)
comp_data

Obtain a list eligible companies and use it to create industry average data later.

comp_list = list(comp_data['公司簡稱'])

Step 3. Make industry dictionary

industry_list = comp_data["TEJ 產業別"].unique().tolist()

Create ROE dict of all companies in industry.

industry_data = tejapi.get('TWN/AIND',
ind = industry_list,
mkt = 'TSE',
opts = {'columns':['coid', 'ind']},
chinese_column_name=True,
paginate=True
).reset_index(drop=True)

The dict of key is industry and value is list of companies.

industry_dict = {}
for i in industry_list:
industry_dict[i] = industry_data[industry_data['TEJ 產業別'] ==
i]['公司簡稱'].tolist()

For example, search the companies in industry 13.

industry_dict["13"]

Most recent year ROE > Industry average ROE

  • Database TWN/AIM1A

The following stock selection methods are similar to this. This content will be more complicated. Readers can check the complete code if you do not understand.

Step 1. Obtain the ROE data.

ROE_data = tejapi.get('TWN/AIM1A',
coid = comp_list,
mdate= '2019-12-01',
opts={'pivot':True,
'columns':['coid', 'mdate', 'R103']},
chinese_column_name=True,
paginate=True)

Step 2. 迭 For loop to turn industry into dictionary. Create 2019 industry average dict.

industry_roe = {}
for i in industry_list:
data = tejapi.get('TWN/AIM1A',
coid = industry_dict[i],
mdate='2019-12-01',
opts={'pivot':True,
'columns':['coid', 'mdate', 'R103']},
chinese_column_name=True,
paginate=True).reset_index(drop=True)
industry_roe[i] = data.groupby('公司代碼').mean().mean()[0]

Step 3. 將 Mapping the industry average dict to get average ROE.

ROE_data['產業淨值報酬%'] = ROE_data['TEJ 產業別'].apply(lambda x: industry_roe[x])

Step 5. Save eligible companies to set_1 .

set_1 = set(ROE_data[ROE_data['ROE(A)-稅後'] > ROE_data['產業淨值報酬%']]['公司簡稱'])

Three-year average ROE > 15%

Choose 3-year data and operate like point 1method groupby. Then get averaged numbermean and save toset_2 .

ROE_data_3Y = tejapi.get('TWN/AIM1A',
coid=comp_list,
mdate=['2017-12-01','2018-12-01','2019-12-
01'],
opts={'pivot':True,
'columns':['coid', 'mdate', 'R103']},
paginate=True,
chinese_column_name=True,
)

Most recent year Gross margin > Industry average GM

The operation method is similar to point 1. We save eligible companies into set_3 .

Increase in market value within 7 years / Increase in retained earnings within 7 years > 1

Step 1. Obtain market value and retained earnings data.

MV_RE_data = tejapi.get('TWN/AIM1A',
coid = comp_list,
mdate= ['2019/12/01','2013/03/01'],
opts={'pivot':True,
'columns':['coid', 'mdate','MV','2341']},
chinese_column_name=True,
paginate=True
).reset_index(drop=True)

Step 2. pivot_table

MV_RE_data.pivot_table(index='公司代碼', columns='財報年月').reset_index()

Step 3. Subtract the two columns to get the added value.

MV_RE_data['保留盈餘增加值'] = MV_RE_data.iloc[:,2] - MV_RE_data.iloc[:,1]MV_RE_data['市值增加值'] = MV_RE_data.iloc[:,4] - MV_RE_data.iloc[:,3]

Step 4. Calculate the signal.

MV_RE_data['指標'] = MV_RE_data['市值增加值'] / MV_RE_data['保留盈餘增加值']

Step 5. Save eligible companies into set_4 .

set_4 = set(MV_RE_data[MV_RE_data['指標']>1]['公司代碼'])

(Most recent year FCF / FCF 7 year ago ) -1 > 1

Step 1. Obtain FCF data.

cash_data = tejapi.get('TWN/AIM1A',
coid= comp_list,
mdate=['2013-12-01', '2019-12-01'],
opts={'pivot':True,
'columns':['coid', 'mdate', 'R69B']},
paginate=True,
chinese_column_name=True,
)

Step 2. The operation method is similar to point 4. Use pivot_table and Subtract the two columns.

Step 3. Save toset_5

set_5 = set(cash_data[cash_data['指標'] > 1].index)

Current market value / The discounted value of FCF in next 10 years. Database: TWN/AIM1A, code: R69B

  • Calculate present and future value. We can import useful module numpy_financial . Its documentation is here. Type pip install numpy_financial in terminal.
import numpy_financial as npf

For instance, a company 4-year FCF are 100 / -150 / -200 / 400. We can use NPV method to calculate its present value by setting discount rate 10%.

cash_flows = np.array([100, -150, -200, 400])
npf.npv(0.1, cash_flows)
example NPV
  • We use two-stage discount model. The growth rate of the first stage is 15% ( first 3 years) and 5% in stage two. Assuming that the discount rate remains unchanged which is 9%. The following defines the cash flow for the next 10 years, and y0 is the 2019 cash flow.
def Cashflows(y0):
y1 = y0 * 1.15
y2 = y1 * 1.15
y3 = y2 * 1.15
y4 = y3 * 1.05
y5 = y4 * 1.05
y6 = y5 * 1.05
y7 = y6 * 1.05
y8 = y7 * 1.05
y9 = y8 * 1.05
y10 = y9 * 1.05

cashflows = np.array([y1,y2,y3,y4,y5,y6,y7,y8,y9,y10])

return cashflows

Step 1. Obtain 2019 FCF and market value.

MV_cash_data = tejapi.get('TWN/AIM1A',
coid= comp_list,
mdate='2019-12-01',
opts={'pivot':True,
'columns':['coid', 'mdate', 'R69B',
'MV']},
paginate=True,
chinese_column_name=True,
).reset_index(drop=True)

Step 2. Present value of 10-year FCF

MV_cash_data['自由現金流量(D)'].apply(lambda x: npf.npv(0.09, Cashflows(x)))

Step 3. Calculate the signal.

MV_cash_data['指標'] = MV_cash_data['季底普通股市值'] / MV_cash_data['自由現金流量(D)'].apply(lambda x: npf.npv(0.09, Cashflows(x)))

Step 3. Save to set_6

set_6 = set(MV_cash_data[(MV_cash_data['指標']<1) & (MV_cash_data['指標']>0)]['公司代碼'])

Review portfolio performane

Coming to the final stage we are most looking forward to, take the intersection of each set to get our portfolio.

set_1 & set_2 & set_3 & set_4 & set_5 & set_6

Refer to 【Application(5)】Modular Backtesting System. We put this list into the system. Because the price gap of the stock is too large, we use equal weight to buy and hold. Obtain the return rate is

ROI on Portfolio

Conclusion

More proficient in operating database, more able to design personalized stock selection. You can also test various stock selection stratigies. The content of this article is more complicated and requires more effort to study. If you have interest on this topic, you can go to our official website. It provides various financial data to help you make better strategy.

The content of this webpage is not an investment device and does not constitute any offer or solicitation to offer or recommendation of any investment product. It is for learning purposes only and does not take into account your individual needs, investment objectives and specific financial circumstances. Investment involves risk. Past performance is not indicative of future performance. Readers are requested to use their personal independent thinking skills to make investment decisions on their own. If losses are incurred due to relevant suggestions, it will not be involved with author.

Related Link

Back
Procesing