어설픈 0458 – 1편

civimanwp

Updated on:

오늘 시가가 어제 시가보다 낮으면 매수하고, 매수가격을 저장했다가 오늘시가가 매수가격보다 높으면 매도하는 매매법을 자동매매로 구현하고자 코드를 짜본다. 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개의 보유기록 날짜가 오래전 것으로 남고, 최종거래일도 오래전인걸로 봐서 손절로직이 필요하다.보유일을 계산하는 로직이 필요한데 아이디어가 없다. 다음편에서 다루어보겠다. 또한, 시드를 분할값으로 나누어 매수개수를 계산하는 로직도 필요하다.

매수가 먼저인지 매도가 먼저인지는 고민해볼 문제이다. 아니면 아예 별도로 만드는 방법도 고민해야할 것이다. 일반적인 자동매매로직에서는 매도가 우선이라는 느낌이다.