오늘 시가가 어제 시가보다 낮으면 매수하고, 매수가격을 저장했다가 오늘시가가 매수가격보다 높으면 매도하는 매매법을 자동매매로 구현하고자 코드를 짜본다. FinanceDataReader로 가격정보를 가져와 백테스트 하기 위해 코드를 만들어 봤다.
import pandas as pd
import FinanceDataReader as fdr
tiers = 6 # 분할값
holddays = 20 # 손절일
total_cash = 2000000 # 설정값
# 거래기록 리스트 생성
trades = []
sell_list =[]
df=fdr.DataReader(ticker)
df.index = df.index.strftime('%Y-%m-%d') # 날짜 형식 변경
df.reset_index(inplace=True)
df['Pre_open'] = df['Open'].shift(1) # 전일시가 칼럼 만들기
df = df.dropna() # 결측치 삭제
print(df)
라이브러리는 Pandas와 FinanceDataReader를 사용했다. 분할값과 손절일 시드금액을 설정하고, 보유기록 (trades)과 거래기록 (sell_list)을 저장할 빈 리스트를 만들었다. 가격정보를 불러와서 인덱스에 있는 날짜 정보의 형식을 변경하고, 인덱스를 칼럼으로 변경하고, 전일시가 (Pre_open)칼럼을 만든후 결측치를 삭제하여 백테스트에 사용할 데이터프레임을 정리하였다.
Date Open High Low Close Volume Change Pre_open
1 2015-12-18 10400 10815 10305 10815 1026044 0.033939 10345.0
2 2015-12-21 10755 10910 10755 10835 1012556 0.001849 10400.0
3 2015-12-22 10900 10970 10565 10660 996448 -0.016151 10755.0
4 2015-12-23 10705 10755 10520 10535 1497183 -0.011726 10900.0
5 2015-12-24 10575 10595 10360 10360 1304007 -0.016611 10705.0
for index, row in df.iterrows():
if row['Open'] < row['Pre_open'] and len(trades) < tiers:
trades.append({'Date': row['Date'], 'Buy_price': row['Open']})
else:
for trade in trades[:]:
if row['Open'] > trade['Buy_price']:
sell_list.append({'Buy_Date': trade['Date'], 'Buy_price': trade['Buy_price'], 'Sell_date':row['Date'],'Sell_price': row['Open']})
trades.remove(trade)
df_trades = pd.DataFrame(trades)
print(df_trades)
df_sell = pd.DataFrame(sell_list)
print(df_sell)
데이터프레임을 반복해가면서 전일시가와 금일시가를 비교하여, 매수를 진행하였다. 매수조건문에 보유기록 리스트의 길이가 분할값보다 적어야지 매수가 되도록 조건을 추가하였고, 잘 작동되었다. 매수가 진행되면 보유기록리스트에 매수날짜와 매수가격을 저장한다. 추후에는 매수주수도 기록할 계획이다. 매수가 진행되지 않은 경우 매도를 진행한다. 매수가격보다 금일시가가 높으면 매도를 진행한다. 거래기록리스트에 매수일, 매수가격, 매도일, 매도가격을 저장하고, 매도된 기록은 보유기록에서 삭제한다.
Date Buy_price
0 2018-02-02 27020
1 2018-03-22 25555
2 2018-04-19 23710
3 2018-04-20 23000
4 2018-04-23 22885
5 2018-06-14 20880
Buy_Date Buy_price Sell_date Sell_price
0 2015-12-28 10330 2015-12-29 10475
1 2015-12-23 10705 2015-12-30 11520
2 2015-12-24 10575 2015-12-30 11520
3 2016-01-05 11155 2016-01-06 11740
4 2016-01-08 11230 2016-01-11 11830
.. ... ... ... ...
161 2018-05-02 21390 2018-05-03 21500
162 2018-05-04 21065 2018-05-28 21280
163 2018-05-30 21070 2018-05-31 21305
164 2018-06-05 21105 2018-06-08 21505
165 2018-06-11 20845 2018-06-12 20950
6개의 보유기록 날짜가 오래전 것으로 남고, 최종거래일도 오래전인걸로 봐서 손절로직이 필요하다.보유일을 계산하는 로직이 필요한데 아이디어가 없다. 다음편에서 다루어보겠다. 또한, 시드를 분할값으로 나누어 매수개수를 계산하는 로직도 필요하다.
매수가 먼저인지 매도가 먼저인지는 고민해볼 문제이다. 아니면 아예 별도로 만드는 방법도 고민해야할 것이다. 일반적인 자동매매로직에서는 매도가 우선이라는 느낌이다.