@run-out Oh...Okay I got it!
import backtrader as bt
import backtrader.feeds as feeds
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import selenium
from selenium import webdriver
from pandas_datareader import data as pdr
from pandas import DataFrame as DF
from datetime import datetime as dt
from yahoofinance import IncomeStatement
from bs4 import BeautifulSoup
### Global ###
driver=webdriver.Chrome(executable_path=r'C:\chromedriver\chromedriver.exe')
#path='C:\Users\USER\Desktop\Stock\Backtest\Data\'
def stock_data(start, end, instrument):
start_time = dt(*start) #* : 튜플 -> dt.datetime 형태로 만듬
end_time = dt(*end)
df = pdr.get_data_yahoo(instrument, start_time, end_time)
df.columns=['high', 'low','open','close','volume','adj_close']
return df
def BS_data(symbol):
headers=[]
contents=[]
temp=[]
# ex: https://finance.yahoo.com/quote/NXPI/balance-sheet?p=NXPI
url= 'https://finance.yahoo.com/quote/' + symbol + '/balance-sheet?p=' + symbol
driver.get(url)
table_html=driver.execute_script('return document.body.innerHTML;')
soup=BeautifulSoup(table_html, 'lxml')
table_list=soup.find_all('div', class_='D(tbr)') #all of the rows
for num, row in enumerate(table_list):
if num==0:
for item in row.find_all('div', class_='D(ib)'):
headers.append(item.text)
else:
x=row.find_all('div', class_='D(tbc)') # 숫자가 적힌 부분이 생소한 형태이긴 한데 tbc가 맞음 (주의사항)
for line in x:
temp.append(line.text)
contents.append(temp)
temp=[]
# print(headers)
# print(contents)
df=pd.DataFrame(contents)
df.columns=headers
return df
def IS_data(instrument):
headers=[]
temp=[]
contents=[]
url="https://finance.yahoo.com/q/is?s="+instrument+"&annual"
driver.get(url)
table_html=driver.execute_script('return document.body.innerHTML;')
soup=BeautifulSoup(table_html, 'lxml')
row_list=soup.find_all('div', class_='D(tbr)')
for num, row in enumerate(row_list):
if (num==0):
for item in row.find_all('div', class_='D(ib)'):
headers.append(item.text)
else:
for item in row.find_all('div', class_='D(tbc)'):
temp.append(item.text)
contents.append(temp)
temp=[]
# print(headers)
# print(contents)
df=pd.DataFrame(contents)
df.columns=headers
return df
def CF_data(symbol):
url="https://finance.yahoo.com/quote/"+symbol+"/cash-flow?p="+symbol+"NXPI"
driver.get(url)
table_html=driver.execute_script("return document.body.innerHTML;")
soup=BeautifulSoup(table_html, 'html.parser')
row_list=soup.find_all('div', class_='D(tbr)')
headers=[]
temp=[]
contents=[]
for num, row in enumerate(row_list):
if num==0:
for item in row.find_all('div', class_="D(ib)"):
headers.append(item.text)
else:
for item in row.find_all('div', class_='D(tbc)'):
temp.append(item.text)
contents.append(temp)
temp=[]
print(contents)
df=pd.DataFrame(contents)
df.columns=headers
return df
class Stock_Data(bt.feeds.PandasData):
linesoveride=True
lines=(
('datetime', None),
('open', -1),
('high', -1),
('low', -1),
('close',-1),
('volume',-1),
('adj_close',-1)
)
class Financial_Data(bt.feeds.PandasData):
linesoverride=True
recent_year=int(dt.today().year-1)
first="12/30/"+str(recent_year)
second="12/30/"+str(recent_year-1)
third="12/30/"+str(recent_year-2)
lines=(
('Breakdown', None),
(first, -1),
(second, -1),
(third, -1)
)
start = (2018, 1, 1) # 2000-01-01
end = (2020, 12, 31) # 2020-12-31
symbol='103140.KS'
ST=stock_data(start, end, symbol)
BS=BS_data(symbol)
IS=IS_data(symbol)
CF=CF_data(symbol)
# BS_path=path+symbol+"_BS.csv" #C:\Users\USER\Desktop\Stock\Backtest\Data\숫자.KS_BS.csv
# BS.to_csv(BS_path, mode="w")
ST=bt.feeds.PandasData(dataname=ST, timeframe=1, openinterest=None)
BS=bt.feeds.PandasData(dataname=BS)
IS=bt.feeds.Financial_Data(dataname=IS)
CF=bt.feeds.Financial_Data(dataname=CF)
class (bt.Strategy):
params=dict(
short=20,
mid=60,
long=120
)
def __init__(self):
"""
self.datas : st, bs, is_data, cf
"""
for num, data in enumerate(self.datas):
print('{}th data: {}'.format(num,data._name))
name=data._name
self.name=data
def anal_cash(self):
#1. 대놓고 있는 현금 흐름
cf=self.cf
final_cf=cf.loc[['Free Cash Flow'],['TTM']]
#2. 은밀한 현금 흐름
#아;; 이 전략 폐기. 생각해보니 크롤링으론 파일 다운이 안돼서 공시 자료 못 받음;;
def next(self):
curr_stock_price=self.data.close[0]
if not self.position: #not in market
self.cross0=curr_stock_price-self.sma_short
#print(self.cross0)
if ((self.cross0>0)and(self.cross1>0)):
size=int((self.broker.getcash())*0.1/self.data.close[0])#how many stocks?
self.buy(size=size) #살 때는 size가 있는 게 나음.
print("Buy")
elif ((self.cross1<0)):#already in market
#size=int((self.broker.getcash())*0.1/self.data.close[0])#how many stocks?
self.sell() #팔 때는 사이즈 없는 게 수익률 나음.
print("Sell")
cerebro=bt.Cerebro()
cerebro.adddata(ST, name=st)
cerebro.adddata(BS, name=bs)
cerebro.adddata(IS, name=is_data)
cerebro.adddata(CF, name=cf)
investment=1000000000
cerebro.broker.setcash(investment) #10억으로 초기 자본 설정
cerebro.broker.setcommission(commission=0.0025) #세금을 수수료로 간주, 0.25%
cerebro.addstrategy(Array_analysis)
cerebro.run()
Here!