1. 목표
벤저민 그레이엄의 방어 투자자를 위한 투자 전략에 이어 공격 투자자를 위한 투자 전략을 사용해 종목 선정하는 것을 목표로 한다.
방어 투자자를 위한 투자 전략에 대한 정보가 궁금하다면 아래 두 개의 글을 참조하면 된다.
2. 공격 투자자를 위한 6가지 투자 전략
(1) 적정 PER:
- PER이 9 이하인 종목
(2) 재무 상태:
- 유동자산이 유동부채의 150% 이상인 종목
("유동자산 / 유동부채 = 유동비율(current ratio) >= 1.5"인 종목)
- 부채(total debt)가 순 유동자산의 110% 이하인 종목
(순 유동자산 = 총 유동자산(total current assets) - 총 유동부채(total current liabilities))
(3) 이익의 안정성:
- 지난 5년 동안 적자를 기록한 적 없는 종목
(즉, 5년간 당기순이익(net income)이 마이너스가 없는 종목)
(4) 배당 실적:
- 당기에 조금이라도 배당을 지급한 종목
(5) 이익 증가:
- 작년 이익이 4년 전 이익보다 많은 종목
(6) 주가:
- 주가가 순유형자산의 120% 미만
(순유형자산(net tangible assets) = 총 자산(total assets) - 총 부채(total liabilities) - 무형자산(intangible assets) - 영업권(goodwill))
첫 번째, PER이 9 이하이며, 유동자산이 유동부채의 150% 이상인 종목 선정 (투자 전략 (1), (2) - 1)
먼저 investing.com에서 제공하는 stock screener를 통해 위 조건을 만족하는 종목을 필터링한다.
이때 유동자산이 유동부채의 150% 이상이라는 것은 유동비율(current ratio)가 1.5 이상이라는 것을 의미한다.
다음으로 selenium을 이용한 웹 스크래핑으로 필터링 된 종목들의 ticker를 추출해 csv 파일에 dataframe의 형태로 저장한다.
코드는 다음과 같다.
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pandas as pd
import time
driver = webdriver.Chrome('C:/Program Files/chromedriver_win32/chromedriver.exe')
driver.implicitly_wait(5)
tickers = []
for i in range(1, 34):
driver.get(f'https://www.investing.com/stock-screener/?sp=country::5|sector::a|industry::a|equityType::a|peexclxor_us::9,250000|qcurratio_us::1.5,3921.01%3Ceq_market_cap;{i}')
try:
driver.find_element_by_link_text('Overview').send_keys(Keys.ENTER)
except:
continue
time.sleep(5)
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
select = soup.select('.symbol.left.bold.elp')
for s in select:
text = s.find_next(class_='left').text
tickers.append(text)
tickers_df = pd.DataFrame({'Symbol' : tickers})
tickers_df.to_csv('tickers_result_1.csv')
두 번째, 부채가 순유동자산의 110% 이하인 종목 선정 (투자 전략 (2) - 2)
먼저 finviz.com에서 위에서 추출한 ticker들의 총 부채(total debt), 총 유동자산(total current assets)과 총 유동부채(total current liabilities)을 웹 스크래핑으로 추출한다.
코드는 다음과 같다.
from bs4 import BeautifulSoup
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
tickers = pd.read_csv('tickers_result_1.csv')
tickers = tickers['Symbol'].tolist()
columns = ['Total Current Assets', 'Total Current Liabilities', 'Total Debt']
df_filter = pd.DataFrame(index=tickers, columns=columns)
driver = webdriver.Chrome('C:/Program Files/chromedriver_win32/chromedriver.exe')
driver.implicitly_wait(3)
for ticker in tickers:
driver.get(f'https://finviz.com/quote.ashx?t={ticker}')
try:
driver.find_element_by_link_text('balance sheet').send_keys(Keys.ENTER)
except:
continue
time.sleep(5)
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
for column in columns:
r = soup.find(text=column).find_next(class_='snapshot-td2').find_next(class_='snapshot-td2').text
try:
df_filter.loc[ticker, column] = float(r.replace(',', ''))
except:
df_filter.loc[ticker, column] = None
df_filter.to_csv('df_filter_2.csv')
다음으로 위에서 추출한 정보로 부채가 순유동자산의 110% 이하인 종목들을 필터링해 dataframe의 형태로 csv 파일에 저장한다.
이때 부채는 총 부채(total debt) 값을 사용하고, 순유동자산은 "총 유동자산(total current assets) - 총 유동부채(total current liabilities)"로 계산한다.
코드는 다음과 같다.
import pandas as pd
df = pd.read_csv('df_filter_2.csv', index_col = 0)
df = df.dropna()
list = []
for i in range(len(df)):
comp = df.iloc[i, 0] - df.iloc[i, 1]
if (1.1 * comp) >= df.iloc[i, 2]:
list.append(df.index[i])
df_result = pd.DataFrame({'Symbol' : list})
df_result.to_csv('tickers_result_2.csv')
세 번째, 지난 5년 동안 적자를 기록한 적이 없고, 작년 이익이 4년 전의 이익보다 많은 종목 선정 (투자 전략 (2), (4))
(두 투자 전략에 대한 정보가 같으므로 한 번에 필터링해서 분석했다.)
먼저 위에서 필터링 한 종목들의 5년 치 당기순이익(net income) 정보를 macrotrends.net에서 웹 스크래핑을 통해서 추출해 csv 파일에 저장한다.
코드는 다음과 같다.
from bs4 import BeautifulSoup
import pandas as pd
from selenium import webdriver
def column(num):
column = []
for i in range(1, num+1):
column.append(f'{i}년 전')
return column
df = pd.read_csv('tickers_result_2.csv')
tickers = df['Symbol'].tolist()
df_net_income = pd.DataFrame(index=tickers, columns=column(5))
driver = webdriver.Chrome('C:/Program Files/chromedriver_win32/chromedriver.exe')
for ticker in tickers:
driver.get(f'https://www.macrotrends.net/stocks/charts/{ticker}/apple/financial-statements')
driver.implicitly_wait(10)
#net income 크롤링
html = driver.page_source
soup = BeautifulSoup(html, 'lxml')
s1 = soup.select('#row15jqxgrid > div > div')
for i in range(1, 6):
try:
df_net_income.loc[ticker, f'{i}년 전'] = float(s1[i + 1].get_text().replace(',', '')[1:])
except:
df_net_income.loc[ticker, f'{i}년 전'] = None
df_net_income.to_csv('df_net_income_3.csv')
다음으로 위에서 구한 5년간의 net income 정보를 통해 5년간 net income 값이 마이너스가 아니고, 1년 전의 net income 값이 4년 전의 net income 값에 비해 큰 종목들을 필터링한다.
코드는 다음과 같다.
import pandas as pd
df_net_income = pd.read_csv('df_net_income_3.csv', index_col=0)
df_net_income = df_net_income.dropna()
list = []
for i in range(len(df_net_income)):
for j in range(5):
if (df_net_income.iloc[i, j]) >= 0:
pass
else:
break
if j == 4:
list.append(df_net_income.index[i])
list1 = []
for i in list:
if df_net_income.loc[i, '1년 전'] > df_net_income.loc[i, '4년 전']:
list1.append(i)
df_result = pd.DataFrame({'Symbol' : list1})
df_result.to_csv('tickers_result_3.csv')
3. 요약
이 글에서는 벤저민 그레이엄의 공격 투자자를 위한 6가지 투자 전략 중 4가지의 투자 전략을 통해 필터링해보았다.
다음 글에서는 나머지 2가지 전략과 결과적으로 필터링 된 종목에 대해서 알아볼 것이다.
'코딩 > 퀀트 투자' 카테고리의 다른 글
[파이썬/ 웹 스크래핑] 기업 가치(EV, enterprise value)를 통한 종목 선정 (0) | 2021.09.12 |
---|---|
[파이썬/ 웹 스크래핑] 벤저민 그레이엄의 투자 전략에 따른 종목 선정 - 공격 투자자(2) (0) | 2021.09.11 |
[파이썬/ 웹 스크래핑] 벤저민 그레이엄의 투자 전략에 따른 종목 선정 - 방어 투자자(2) (0) | 2021.09.04 |
[파이썬/ 웹 스크래핑] 벤저민 그레이엄의 투자 전략에 따른 종목 선정 - 방어 투자자(1) (0) | 2021.09.04 |
파이썬으로 S&P 500 지수 투자 분석하기(TIGER ETF 편) (0) | 2021.08.28 |