본문 바로가기
Trading/PythonForFinance

ALT - a tool for backtest; backtrader

by bents 2020. 12. 23.

목표
1. 주식 시뮬레이션 전략 (공매도 포함)
- 승률70%, MDD10%, 연평균 수익률10%
2. 300만원으로 실제 매매(주문은 수동으로)
- 승률70%, MDD10%, 연평균 수익률10%
(숏전략없음)
3.FX마진 시뮬레이션/데모 적용후 매매자동화
=======

zipline, backtesting 등 여러 패키지 중 backrader 의 장점

- 설치간편

- 전략 시뮬레이션 편리

## 자료정리

1. 간단한 사용법 : 공식문서

www.backtrader.com/docu/

2. 실전 활용예제 : 백테스트 루키

backtest-rookies.com

community.backtrader.com/

3. 참고 블로그 : jsp님 블로그
jsp-dev.tistory.com/104

4. 증권사 연결하는 법(*window만 사용가능)
wikidocs.net/4428

## 완료

1.  logging으로 매매내역 로그 파일로 저장하기

2. backtrader 설치 및 사용법 익히기 (+자료찾기)

3. colab 에서 시뮬레이션 결과 시각화 하기 (performance report  - not yet )

4. 나만의 longterm 매매 전략 만들기 ( 그래프, 지표 증권앱을 보면서..ㅜㅡㅜ)

 - 시사점; 시스템 트레이딩 매매전략을 연단위로 청산하면 수익률이 높게 나올 수도 있다. ( 삼성전자 기준 : 2010~2020 ; 130% < 180% )

## 미완료

시뮬레이션 복붙까지는 가능함. 

그러나 timeframe, multiple indicators, additional conditions 을 넣으니, 에러 발생.

내가 만든 전략을 정상적으로 시뮬레이션 돌리려면? 

 

 

지표를 생성하는 방식, 원&지표 데이터를 읽는 방식,  복잡한 매매 조건 입력하는 방식을 알아야 함.

1. 데이터 다루기 ( 시간샘플링,  주가/거래량,  기타 옵션) : "Data Feed"

1) 시간샘플링(timeframe)

  - 샘플링 세팅하기 

...Data(..., timeframe = bt.TimeFrame.Weeks,...)

  - 리샘플링하기

cerebro.resampledata( [dataObject], timeframe = bt.TimeFrame.Weeks, ... )

 

2) 주가/거래량 데이터

 

  - A member variable self.datas : array/list/iterable

  - automatic member variables : self.datas array (directly accessed)

  - omit self.data as a parameters in indicators

self.data == self.datas[0]
self.data0 == self.datas[0]

sma = btind.SimpleMovingAverage(self.data, period=self.params.period)
sma = btind.SimpleMovingAverage(period=self.params.period)

  -  Basically everything gets transformed into an object which can be used as a data feed once it has been operated upon. 모두 데이터 객체다.

 

***헷갈리지말자***

Data를 이곳저곳에서 가져와서 쓸 수 있다. 그래서 datas  리스트를 만들어 모든 수집데이터를 저장한다.

self.datas : # cerebro.adddata(data) 데이터 추가 가능
[<backtrader.feeds.yahoo.YahooFinanceData object at 0x7f147aaf8b00>]

self.data :  # self.datas[0]  or 원하는 데이터 위치에 따라 indexing! 
<backtrader.feeds.yahoo.YahooFinanceData object at 0x7f147aaf8b00>

self.data.close
<backtrader.linebuffer.LineBuffer object at 0x7f147aaf88d0>

self.data.close[0] :  # self.data[0] 동일 결과
56400.0 

 

3) 함수 파라미터

  - No *args or **kwargs are being received by the strategy’s __init__ method

  - parameters are declared as a class attribute (tuple, dictionary)

  - after scanning , remove them from **kwargs if matched and assign the value to the corresponding parameter

  - parameter accessing : self.params (shorthand: self.p)

params = (('period', 20),)
params = dict(period=20)
sma = btind.SimpleMovingAverage(period=self.p.period)

 

4) 속성 Lines

  - lines 이란? a set of points that conform a line when drawn together

  - lines은 tuple로만 declaration가능함.

  - 지표indicator와 데이터data, 전략strategy 모두 lines속성을 가지고 있다.

# 선언 - 내가 쓸 지표들은 이미 만들어져 있음. 맞춤형 지표만들 때, 필요한 내용임. 
class SimpleMovingAverage(Indicator):
    lines = ('sma',)
    ...

# 사용법은 datas와 동일함 (accessing)
self.line == self.lines[0]

# 지표만들기 
self.movav = btind.SimpleMovingAverage(self.data, period=self.p.period)

# 현재종가와 movav현재값 비교하기
self.movav.lines.sma[0] > self.data.lines.close[0]
# 다른 표현법
self.movav.l.sma[0] > self.data.l.close[0] # shorten : lines -> l
self.movav.sma[0] > self.data.close[0] # skip lines
self.movav.sma[0] > self.data0_close # data class 만의 특성
self.movav.sma[0] > self.data_close # 0은 생략가능

- Ex] the “period=25”: 함수마다 line 길이

 > prenext 24 times

 > nextstart 1 time (in turn calling next)

 > next n additional times until the data feed has been exhausted

 

5) 길이와 slicing

  - 지표, 데이터피드, 전략의 lines의 len은 `처리하는 bar 개수`다

  - indexing & slicing ; 

// 2 days ago = -2	
// previous = -1	
// current = 0
// no following 

# 오늘제외, 어제부터 10일치 데이터
myslice = self.my_sma.get(ago=-1, size=10)
myslice = self.my_sma[-11:-1]

 

2. 지표/신호 생성

1) 라이브러리 사용하기

# data0 is a daily data (=indicator)
sma0 = btind.SMA(self.data0, period=15)  # 15 days sma
# data1 is a weekly data
sma1 = btind.SMA(self.data1, period=5)  # 5 weeks sma
# a result of math operaton
self.buysig = sma0 > sma1()

2) 맞춤형 지표 만들기

?? - 클래스 만들기 / OBV만들기 예제 확인하시길 (난 완성!)

 

3) 연산자로 신호(또다른 지표) 만들기

self.buysig = bt.And(sma1 > self.data.close, sma1 > self.data.high)
high_or_low = bt.If(sma1 > self.data.close, self.data.low, self.data.high)

3. 매매전략 생성 

:   매매조건 ( Operator 생성 , 대소비교 ) 만들기

--> position 조건 제외하면 __init__ 와 next(self) 을 통해서 매매전략 완성가능함.

 

기억! 결국 모든 데이터는 linebuffer라는 사실!

 

 __init__에서 데이터 뿐만 아니라 매매전략에 필요한 지표, 매매신호를 모두 생성한다. 

1) data feed에서 필요한 컬럼(ex.종가,거래량) 가져오기

2) backtrader에서 제공되지 않는 지표는 indicator상속해서 로직넣어서 지표만들기

3) [선택사항1] 매수/매도 signal를 미리 만들 수 있음.

4) [선택사항2] next() 메소드 안에서 논리연산자와 조건문으로 매매조건 생성가능함.