PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 일자 데이터 구현하기 ①

  • -

지난 게시글까지가 알고리즘을 이용해서 종목별 매수 예정 가격 데이터를 계산해내는 기능을 구현하는 방법에 대한 설명이었다. 이번 게시글에서는 일자 데이터를 구현할 예정인데, 일자 데이터를 구현하는 것은 생각보다 다양한 요소들을 고려해야 한다. 왜냐하면 주식 시장에는 장이 시작되고 종료되는 일정한 시간이 있기 때문이다.

 

 

일자 데이터를 어떻게 구현할까?

일단 방법론만 생각해보자면 상당히 간단한 모듈로 일자 데이터를 얻어올 수 있다. 가장 대표적인 것이   datetime  모듈인데, 예제로 간단하게 살펴보도록 하자.

>>> import datetime
>>> datetime.datetime.now()
>>> datetime.datetime(2022, 8, 28, 15, 17, 27, 453139)

일단   datetime  모듈을 import한 후에,   datetime.datetime.now()  를 사용하게 되면 지금 현재의 연도, 월, 일, 시간, 분, 초, 밀리초까지 모두 확인할 수 있다. 우리는 이 데이터를 우리가 원하는 형태로 형식을 지정하여 사용할 수 있는데, 이 때 사용되는 것이 바로   strftime()  메서드이다.

이   strftime()   메서드를 사용하게 되면 위의 Line 3과 같이 콤마로 구분되어 있는 여러 데이터들을 우리가 원하는 방식으로 수정할 수 있다. %Y는 연도고 %m는 월, %d는 일을 의미하는데, 자세한 건 아래의 코드를 살펴보도록 하자.

>>> date = datetime.datetime.now().strftime("%Y%m%d")
>>> date
>>> '20220828'

>>> time = datetime.datetime.now().strftime("%H%M%S")
>>> time
>>> '152213'

 

 

프로그램 시작 시 일자 데이터 얻어오기

위와 같은 내용을 기반으로 main.py 파일의 최상단에 아래와 같은 코드를 구현하면 된다. 이제는 프로그램을 실행할 때마다 date라는 변수 내에는 오늘 일자가 출력될 것이다.
※ Line : 16~18

import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5.QtCore import *
import pandas as pd
import time
import manage_db
from threading import Thread
import valuable._df as _df
import valuable.dummy_variable as dv
import datetime

from Algorithm.algorithm_1 import algo1

temp_date = datetime.datetime.now()
date = temp_date.strftime("%Y%m%d")
print(f"오늘 날짜는 {date}입니다.")

 

pydev 디버거에 연결되었습니다(빌드 221.5080.212)
오늘 날짜는 20220828입니다.

 

 


728x90

 

 

우리에게 필요한 건 거래일이다.

당장 당일의 일자 데이터를 얻어오기는 했으나, 정작 우리에게 있어 필요한 건 거래일 데이터이다. 왜냐하면 2022년 8월 28일은 거래일이 아닌 일요일이기 때문이다. 다시 말해, 조건검색식을 저장하는 데에 있어 굳이 일요일 데이터를 이름으로 하여 저장할 필요가 없다는 것이다. 그렇다면 오늘이 거래일인지 아닌지는 어떻게 판단할 수 있을까? 그리고 당일을 기준으로 하여 가장 최신의 거래일은 언제인지는 어떻게 찾을 수 있을까?

아쉽게도 키움증권 Open API 내에서는 거래일 정보를 전달해주는 tr을 제공하지 않고 있다. 따라서 이 기능은 우리가 직접 구현해줘야 한다는 번거로움이 있는 기능이므로 구현하기가 다소 복잡하고 손이 많이 가는 작업이다. 
※ 키움증권 Open API 담당자가 이 글을 볼리는 없겠지만, 만약 본다면 거래일 정보를 얻을 수 있는 tr을 제공해주길 바란다.

일단 가장 먼저, 우리는 거래일 여부를 판단하기 위해 조회된 일자가 평일인지 주말인지를 판단하여 평일이 아니라면 오늘은 무조건 거래일이 아니라는 결론에 도달할 수 있다. 그 다음으로 시간적인 기준에 있어서, 만약 현재 시간이 3시 30분이 지나지 않았다면 현재 시점에서 최신 거래일은 오늘이 아닌 어제가 된다. 이 부분이 무엇을 의미하는지는 직접 제작하다보면 어렵지 않게 이해할 수 있다. 일단은 평일과 주말을 판단해주는   weekday()  메서드를 사용해서 평일 일자를 찾아보도록 하자.

  weekday()  메서드는 월요일은 0, 화요일은 1과 같은 식으로 결과값을 반환하기 때문에 5는 토요일을, 6은 일요일을 의미한다. 그렇기 때문에 weekday() 메서드의 결과값이 5보다 작다면(또는 4보다 작거나 같다면) 평일을 의미하고 4보다 크다면(또는 5보다 크거나 같다면) 주말을 의미하게 된다. 아래의 코드는 6이 출력되었는데, 실제로 2022년 8월 28일은 일요일이 맞다.

>>> a = datetime.datetime.now()
>>> a.weekday()
>>> 6

 

그렇다면 우리는   if a.weekday() > 4:  라는 조건이 충족된다면 당일은 주말이므로 현재 일자로부터 하루를 빼서 전일의 데이터를 얻어온 후, 그 데이터는 주말인지 평일인지를 확인하면 된다. 여기서 특정 일자의 데이터에서 하루 또는 이틀과 같은 데이터를 더하고 빼는 등의 기능은   timedelta()  메서드를 통해 사용할 수 있다.
※ Line : 5, 9

>>> a = datetime.datetime.now()
>>> a
>>> datetime.datetime(2022, 8, 28, 15, 38, 21, 955604)

>>> b = a- datetime.timedelta(days=1)
>>> b
>>> datetime.datetime(2022, 8, 27, 15, 38, 21, 955604)

>>> c = b - datetime.timedelta(days=1)
>>> c
>>> datetime.datetime(2022, 8, 26, 15, 38, 21, 955604)

>>> c.weekday()
>>> 4

 

이렇게 이 작업을   weekday()  메서드를 사용한 결과값이 4 밑으로 내려온다면 그 날이 곧 평일이므로, 해당 데이터를 반환해주면 되는 것이다. 이와 같은 작업은   while 조건:  을 통해 해당 조건이 충족될 때(True일 때) while 아래의 코드를 실행하도록 함으로써 계속해서 반복이 이루어지게 구현한다면 어렵지 않게 그 결과 데이터를 얻을 수 있다.
※ Line : 2~7, 10

temp_date = datetime.datetime.now()
latest_date = temp_date

while latest_date.weekday() > 4:
    latest_date = latest_date - datetime.timedelta(days=1)

latest_date = latest_date.strftime("%Y%m%d")
date = temp_date.strftime("%Y%m%d")

print(f"오늘 날짜는 {date}입니다.. 최신 거래일은 {latest_date}입니다.")

>>>
pydev 디버거에 연결되었습니다(빌드 221.5080.212)
오늘 날짜는 20220828입니다.. 최신 거래일은 20220826입니다.

 

그럼 이제 이전 게시글에서 만들었던   total_df.to_sql()  부분에서 name이라는 파라미터의 인자로   latest_date  라는 변수를 전달해주면 해당 거래일의 데이터가 데이터베이스 테이블의 이름으로 설정되어 저장되는 것이다.
※ Line : 17
※ f"s{latest_date}"를 사용하는 이유는 바로 테이블의 이름은 숫자로 시작할 수 없기 때문이다. 따라서 s가 아닌 다른 문자열을 넣어도 된다.

def _pushbtn_7(self):
    total_df = _df.algo1_df()

    for item_code in self.code_list:
        if item_code != "":
            min5_chart_data = self.request_opt10080(item_code, 5)
            print(min5_chart_data)

            result = algo1(min5_chart_data, "20220826", item_code).run()

            if result[0]:
                total_df = pd.concat([total_df, result[1]], ignore_index=True).reset_index(drop=True)

    print("total_df")
    print(total_df)

    total_df.to_sql(name=f"s{latest_date}", con=manage_db.engine_condition, index=False, if_exists='replace')

 

이제 프로그램을 다시 실행해서 조건검색식에 의한 데이터를 조회해보면, 아래와 같은 테이블이 생성된 모습을 확인할 수 있다.

'condition' 내 's20220826'의 이름으로 저장되었다.

 

 


728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.