%matplotlib inline
%config InlineBackend.figure_format = 'retina'
import warnings
import matplotlib.pyplot as plt
from matplotlib.font_manager import fontManager as fm
plt.style.use('seaborn') # 'seaborn-colorblind'
plt.rc('axes', unicode_minus=False)
warnings.simplefilter(action='ignore', category=FutureWarning)
font_list_check = ['D2Coding', 'NanumGothicCoding', 'NanumGothic']
for font in font_list_check:
font_counts = [ f for f in font_list_check
if font in [_.name for _ in fm.ttflist]]
if len(font_counts) > 1:
print(f"found : {font}"); break
plt.rc('font', family=font) # 폰트 적용하기
found : D2Coding
DATA_FILENAME = 'data/stock-twitter.pkl'
import pandas as pd
import yfinance as yf
try:
df_twiter = pd.read_pickle(DATA_FILENAME)
except FileNotFoundError:
df_twiter = yf.download('TWTR', start='2020-01-01', end='2022-12-31', progress=False)
df_twiter.to_pickle(DATA_FILENAME)
df_twiter.head(3)
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2019-12-31 | 31.860001 | 32.320000 | 31.770000 | 32.049999 | 32.049999 | 11050600 |
2020-01-02 | 32.310001 | 32.500000 | 31.959999 | 32.299999 | 32.299999 | 10721100 |
2020-01-03 | 31.709999 | 32.099998 | 31.260000 | 31.520000 | 31.520000 | 14429500 |
# plotly 활성화 하기
import cufflinks as cf
from plotly.offline import iplot, init_notebook_mode
cf.set_config_file(world_readable=True, theme='pearl', offline=True) # set up settings (run it once)
init_notebook_mode()
# 수집한 데이터를 활용하여 그림 그리기 (1.캔들차트, 2.거래량, 3,4.이동평균 곡선)
# SMA : 단순 이동 평균 (Simple Moving Average)
# EMA : 지수 이동 평균 (Exponential Moving Average)
qf = cf.QuantFig(df_twiter, title='Twitter Stock Price', legend='top', name='twitter')
qf.add_sma(periods=20, column='Close', color='red')
qf.add_ema(periods=20, color='green')
qf.add_volume()
qf.iplot()
DATA_FILENAME = 'data/stock-apple.pkl'
import pandas as pd
import yfinance as yf
try:
data_csv = pd.read_pickle(DATA_FILENAME)
except FileNotFoundError:
data_csv = yf.download('TWTR', start='2020-01-01', end='2022-12-31', progress=False)
data_csv.to_pickle(DATA_FILENAME)
data_csv.head(3)
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2019-12-31 | 31.860001 | 32.320000 | 31.770000 | 32.049999 | 32.049999 | 11050600 |
2020-01-02 | 32.310001 | 32.500000 | 31.959999 | 32.299999 | 32.299999 | 10721100 |
2020-01-03 | 31.709999 | 32.099998 | 31.260000 | 31.520000 | 31.520000 | 14429500 |
loading from CSV to Pandas DataFrame of the BackTrader DataSet.
# Back Trading 전략에 DataFrame 데이터로 Simulation 합니다.
import backtrader as bt
data_stock = bt.feeds.PandasData(dataname = data_csv)
type(data_stock)
backtrader.feeds.pandafeed.PandasData
# Signal Class 를 정의합니다.
# => 20일 이동평균선 전략을 정의 합니다.
class SmaSignal(bt.Signal):
params = (('period', 20), )
def __init__(self):
self.lines.signal = self.data - bt.ind.SMA(period=self.p.period)
# Back Testing 을 설정에 추가합니다
cerebro = bt.Cerebro(stdstats=False)
cerebro.adddata(data_stock) # Add the data feed
cerebro.broker.setcash(1000.0)
cerebro.add_signal(bt.SIGNAL_LONG, SmaSignal)
cerebro.addobserver(bt.observers.BuySell)
cerebro.addobserver(bt.observers.Value)
# Back Testing 실행 결과를 계산 합니다.
print(f'Starting Portfolio Value : {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'Final Portfolio Value: {cerebro.broker.getvalue():.2f}')
Starting Portfolio Value : 1000.00 Final Portfolio Value: 1035.30
plt.rcParams['figure.dpi'] = 80
plt.rcParams['figure.figsize'] = [20, 6]
cerebro.plot(iplot=False, volume=False)
plt.show()
import backtrader as bt
# 이동평균선 전략을 정의 합니다.
class SmaCross(bt.Strategy):
params = dict(
pfast=10, # fast moving average
pslow=30) # slow moving average
def __init__(self):
sma1 = bt.ind.SMA(period=self.p.pfast)
sma2 = bt.ind.SMA(period=self.p.pslow)
self.crossover = bt.ind.CrossOver(sma1, sma2) # crossover signal
def next(self):
if not self.position: # not in the market
if self.crossover > 0: # if fast crosses slow to the upside
self.buy() # enter long (매수 진행한다)
elif self.crossover < 0: # in the market & cross to the downside
self.close() # close long position (보유시 매도를 진행한다)
# 위 Back Trading 전략에 DataFrame 데이터로 Simulation 합니다.
cerebro = bt.Cerebro() # create a "Cerebro" engine instance
cerebro.adddata(data_stock) # Add the data feed
cerebro.addstrategy(SmaCross) # Add the trading strategy
# backtest 를 실행한다.
print(f'Starting Portfolio Value : {cerebro.broker.getvalue():.2f}')
cerebro.run() # run it all
print(f'Final Portfolio Value: {cerebro.broker.getvalue():.2f}')
Starting Portfolio Value : 10000.00 Final Portfolio Value: 10010.79
plt.rcParams['figure.dpi'] = 300
plt.rcParams['figure.figsize'] = [20, 6]
cerebro.plot(iplot=False, volume=False)
plt.show()
class SmaStrategy(bt.Strategy):
params = (('ma_period', 20), )
def __init__(self):
# keep track of pending orders/buy price/buy commission
self.data_close = self.datas[0].close # Series 에서 close 추출
self.order = None
self.price = None
self.comm = None
self.sma = bt.ind.SMA( # add a simple moving average indicator
self.datas[0], period=self.params.ma_period)
def log(self, txt):
dt = self.datas[0].datetime.date(0).isoformat()
print(f'{dt}, {txt}')
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# order already submitted/accepted - no action required
return
# report executed order
if order.status in [order.Completed]:
if order.isbuy():
self.log(f'BUY EXECUTED --- Price: {order.executed.price:.2f}, Cost: {order.executed.value:.2f}, Commission: {order.executed.comm:.2f}')
self.price = order.executed.price
self.comm = order.executed.comm
else:
self.log(f'SELL EXECUTED --- Price: {order.executed.price:.2f}, Cost: {order.executed.value:.2f}, Commission: {order.executed.comm:.2f}')
# report failed order
elif order.status in [
order.Canceled, order.Margin, order.Rejected]:
self.log('Order Failed')
# set no pending order
self.order = None
def notify_trade(self, trade):
if not trade.isclosed:
return
self.log(f'OPERATION RESULT --- Gross: {trade.pnl:.2f}, Net: {trade.pnlcomm:.2f}')
def next(self):
# do nothing if an order is pending
if self.order:
return
# check if there is already a position
if not self.position:
# buy condition
if self.data_close[0] > self.sma[0]:
self.log(f'BUY CREATED --- Price: {self.data_close[0]:.2f}')
self.order = self.buy()
else:
# sell condition
if self.data_close[0] < self.sma[0]:
self.log(f'SELL CREATED --- Price: {self.data_close[0]:.2f}')
self.order = self.sell()
cerebro = bt.Cerebro(stdstats = False)
cerebro.adddata(data_stock) # Add the data feed
cerebro.broker.setcash(1000.0)
cerebro.addstrategy(SmaStrategy)
cerebro.addobserver(bt.observers.BuySell)
cerebro.addobserver(bt.observers.Value)
print(f'Starting Portfolio Value: {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'Final Portfolio Value: {cerebro.broker.getvalue():.2f}')
Starting Portfolio Value: 1000.00 2020-01-29, BUY CREATED --- Price: 33.63 2020-01-30, BUY EXECUTED --- Price: 32.86, Cost: 32.86, Commission: 0.00 2020-01-31, SELL CREATED --- Price: 32.48 2020-02-03, SELL EXECUTED --- Price: 32.56, Cost: 32.86, Commission: 0.00 2020-02-03, OPERATION RESULT --- Gross: -0.30, Net: -0.30 2020-02-04, BUY CREATED --- Price: 33.96 2020-02-05, BUY EXECUTED --- Price: 34.00, Cost: 34.00, Commission: 0.00 2020-02-25, SELL CREATED --- Price: 35.21 2020-02-26, SELL EXECUTED --- Price: 35.28, Cost: 34.00, Commission: 0.00 2020-02-26, OPERATION RESULT --- Gross: 1.28, Net: 1.28 2020-04-07, BUY CREATED --- Price: 25.61 2020-04-08, BUY EXECUTED --- Price: 26.79, Cost: 26.79, Commission: 0.00 2020-04-21, SELL CREATED --- Price: 25.75 2020-04-22, SELL EXECUTED --- Price: 27.00, Cost: 26.79, Commission: 0.00 2020-04-22, OPERATION RESULT --- Gross: 0.21, Net: 0.21 2020-04-22, BUY CREATED --- Price: 28.44 2020-04-23, BUY EXECUTED --- Price: 28.43, Cost: 28.43, Commission: 0.00 2020-05-06, SELL CREATED --- Price: 27.68 2020-05-07, SELL EXECUTED --- Price: 28.08, Cost: 28.43, Commission: 0.00 2020-05-07, OPERATION RESULT --- Gross: -0.35, Net: -0.35 2020-05-07, BUY CREATED --- Price: 28.77 2020-05-08, BUY EXECUTED --- Price: 29.09, Cost: 29.09, Commission: 0.00 2020-05-13, SELL CREATED --- Price: 28.13 2020-05-14, SELL EXECUTED --- Price: 27.83, Cost: 29.09, Commission: 0.00 2020-05-14, OPERATION RESULT --- Gross: -1.26, Net: -1.26 2020-05-14, BUY CREATED --- Price: 28.56 2020-05-15, BUY EXECUTED --- Price: 28.30, Cost: 28.30, Commission: 0.00 2020-06-19, SELL CREATED --- Price: 33.41 2020-06-22, SELL EXECUTED --- Price: 33.57, Cost: 28.30, Commission: 0.00 2020-06-22, OPERATION RESULT --- Gross: 5.27, Net: 5.27 2020-07-07, BUY CREATED --- Price: 32.99 2020-07-08, BUY EXECUTED --- Price: 33.20, Cost: 33.20, Commission: 0.00 2020-09-08, SELL CREATED --- Price: 38.19 2020-09-09, SELL EXECUTED --- Price: 38.85, Cost: 33.20, Commission: 0.00 2020-09-09, OPERATION RESULT --- Gross: 5.65, Net: 5.65 2020-09-18, BUY CREATED --- Price: 40.15 2020-09-21, BUY EXECUTED --- Price: 39.43, Cost: 39.43, Commission: 0.00 2020-09-21, SELL CREATED --- Price: 39.90 2020-09-22, SELL EXECUTED --- Price: 40.37, Cost: 39.43, Commission: 0.00 2020-09-22, OPERATION RESULT --- Gross: 0.94, Net: 0.94 2020-09-22, BUY CREATED --- Price: 42.73 2020-09-23, BUY EXECUTED --- Price: 43.88, Cost: 43.88, Commission: 0.00 2020-10-30, SELL CREATED --- Price: 41.36 2020-11-02, SELL EXECUTED --- Price: 41.15, Cost: 43.88, Commission: 0.00 2020-11-02, OPERATION RESULT --- Gross: -2.73, Net: -2.73 2020-11-20, BUY CREATED --- Price: 44.68 2020-11-23, BUY EXECUTED --- Price: 44.90, Cost: 44.90, Commission: 0.00 2021-01-07, SELL CREATED --- Price: 52.33 2021-01-08, SELL EXECUTED --- Price: 52.50, Cost: 44.90, Commission: 0.00 2021-01-08, OPERATION RESULT --- Gross: 7.60, Net: 7.60 2021-01-28, BUY CREATED --- Price: 51.57 2021-01-29, BUY EXECUTED --- Price: 51.02, Cost: 51.02, Commission: 0.00 2021-03-04, SELL CREATED --- Price: 66.75 2021-03-05, SELL EXECUTED --- Price: 67.67, Cost: 51.02, Commission: 0.00 2021-03-05, OPERATION RESULT --- Gross: 16.65, Net: 16.65 2021-04-06, BUY CREATED --- Price: 67.00 2021-04-07, BUY EXECUTED --- Price: 66.64, Cost: 66.64, Commission: 0.00 2021-04-20, SELL CREATED --- Price: 65.70 2021-04-21, SELL EXECUTED --- Price: 65.73, Cost: 66.64, Commission: 0.00 2021-04-21, OPERATION RESULT --- Gross: -0.91, Net: -0.91 2021-04-21, BUY CREATED --- Price: 67.33 2021-04-22, BUY EXECUTED --- Price: 67.42, Cost: 67.42, Commission: 0.00 2021-04-22, SELL CREATED --- Price: 64.31 2021-04-23, SELL EXECUTED --- Price: 65.72, Cost: 67.42, Commission: 0.00 2021-04-23, OPERATION RESULT --- Gross: -1.70, Net: -1.70 2021-05-24, BUY CREATED --- Price: 57.06 2021-05-25, BUY EXECUTED --- Price: 57.35, Cost: 57.35, Commission: 0.00 2021-07-16, SELL CREATED --- Price: 66.41 2021-07-19, SELL EXECUTED --- Price: 65.24, Cost: 57.35, Commission: 0.00 2021-07-19, OPERATION RESULT --- Gross: 7.89, Net: 7.89 2021-07-21, BUY CREATED --- Price: 69.54 2021-07-22, BUY EXECUTED --- Price: 68.64, Cost: 68.64, Commission: 0.00 2021-07-26, SELL CREATED --- Price: 68.69 2021-07-27, SELL EXECUTED --- Price: 68.32, Cost: 68.64, Commission: 0.00 2021-07-27, OPERATION RESULT --- Gross: -0.32, Net: -0.32 2021-07-28, BUY CREATED --- Price: 69.96 2021-07-29, BUY EXECUTED --- Price: 69.50, Cost: 69.50, Commission: 0.00 2021-08-03, SELL CREATED --- Price: 68.63 2021-08-04, SELL EXECUTED --- Price: 68.68, Cost: 69.50, Commission: 0.00 2021-08-04, OPERATION RESULT --- Gross: -0.82, Net: -0.82 2021-08-05, BUY CREATED --- Price: 69.28 2021-08-06, BUY EXECUTED --- Price: 69.30, Cost: 69.30, Commission: 0.00 2021-08-06, SELL CREATED --- Price: 67.37 2021-08-09, SELL EXECUTED --- Price: 67.50, Cost: 69.30, Commission: 0.00 2021-08-09, OPERATION RESULT --- Gross: -1.80, Net: -1.80 Final Portfolio Value: 1035.30
cerebro.plot(iplot=False)
plt.show()