PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 알고리즘 구축하기 (13) - 매수 예정 종목 데이터프레임 확인하기 ②

  • -

이전 게시글까지 알고리즘에 의해 매수 예정 가격 등을 포함한 결과 데이터가 정상적으로 전달되고 있음을 확인했으므로 main.py 파일 내에서 조건검색식에 의해 집계된 종목의 일봉 및 분봉 데이터를 algorithm_1.py 파일로 전달한 후 그 결과값을 반환받아보도록 하자. 근본적으로 삼성전자는 조건검색식에 의해 잘 집계되지 않으므로, 여태까지 살펴봤던 삼성전자는 이제 더 이상 등장하지 않을 것이다.

 

 

차트 데이터를 전달해보자.

이제 구현해야 할 기능은 바로 조건검색식에 의해 집계된 종목의 차트 데이터를 조회하는 버튼(  pushButton_7  )이 클릭된 순간 해당 종목의 차트 데이터를 조회함과 동시에 조회가 완료된 경우 algorithm_1.py 파일로 해당 차트 데이터를 전달하여 알고리즘에 의해 계산된 매수 예정 가격 데이터를 반환받는 것이다. 

현재 algorithm_1.py 파일 내에서   def __init__(self)  부분을 살펴보면 self 뒤에   min5_data  와   start_date  라는 두 개의 인자를 전달해줄 것을 요구하고 있음을 확인할 수 있다. 여기서 min5_data 자리에 들어갈 것이 바로 main.py 내에서 조회한 차트 데이터가 될 것이고,   start_date   자리에 들어갈 것은 바로 해당 종목의 5일 이동평균선과 20일 이동평균선이 골든 크로스된 일자가 된다. 하지만 이 일자 데이터에 크게 주의하지 않아도 되는 이유는 따로 있다. 왜냐하면 조건검색식은 5일 이동평균선이 20일 이동평균선을 상향 돌파한 종목만 집계하기 때문에,   start_date  는 곧 데이터를 조회하는 오늘의 날짜를 의미하기 때문이다. 그렇다면 이제 알고리즘 파일에 차트 데이터를 전달해보자.
※ Line : 1, 14
※ 일자 데이터는 추후에 자동적으로 전달하도록 구현할 예정입니다. 그러니 급한대로 일자를 수기로 전달해주면 됩니다.

from Algorithm import algorithm_1

class tradesystem(QMainWindow, form_class):
    def __init__(self):
        self.pushButton_7.clicked.connect(self._pushbtn_7)
        
        
    def _pushbtn_7(self):
        for item_code in self.code_list:
            if item_code != "":
                min5_chart_data = self.request_opt10080(item_code, 5)
                print(min5_chart_data)

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

일단   Line 1  에서는 Algorithm 폴더 내에 있는 algorithm_1.py 파일을 불러오는 코드이다. 그 후   Line 14  에서는 algorithm_1.py 파일 내에 있는   algo1   Class 내에   min5_chart_data  와 조회 시점의 일자 데이터를 전달해준 후,   run()   함수를 실행하도록 하여 그 결과값을   result  라는 변수 안에 입력하도록 한 것이다. 구조가 다소 어렵게 느껴질 수도 있겠지만, 하나하나 차근차근 이해해보면 어렵지 않다.

물론, 아래와 같은 방식으로도 얼마든지 사용할 수 있다. 아래는   Line 1  에서 필요한 파일들을 불러올 때, 파일에서 멈추지 않고 파일 내에 있는 Class인   algo1  을 불러온 후에 실제로 사용하는 지점인   Line 14  에서도 역시   algo1  에 곧바로 데이터를 전달하여 사용하는 방식이다.
※ Line : 1, 14

from Algorithm.algorithm_1 import algo1

class tradesystem(QMainWindow, form_class):
    def __init__(self):
        self.pushButton_7.clicked.connect(self._pushbtn_7)
        
        
    def _pushbtn_7(self):
        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").run()

 

 


728x90

 

 

계산된 결과값 확인해보기

이제 실제로 조건검색식에 의해 집계된 종목들의 매수 예정 가격을 확인해볼 차례이다. 이전 게시글에서 살펴봤으니 어느 정도 알고 있겠지만, 현재   result  라는 변수에 저장되어 있는 데이터는 첫 번째 자리에는 bool 형태의 True 또는 False가 입력되며 두 번째 자리에는 매수 예정 가격 데이터가 입력되고 있다. 따라서   result[0]  과   result[1]  로 나누어서 출력해보자.
※ Line : 10, 11

    def _pushbtn_7(self):

        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").run()

                print(result[0])
                print(result[1])
                
                
>>>
고가가 갱신되었습니다... 20220826, 20220826090500
저가가 갱신되었습니다... 20220826, 20220826090500
고가가 갱신되었습니다... 20220826, 20220826090000
저가가 갱신되었습니다... 20220826, 20220826090000
True
   item_code  first_buy_price  second_buy_price
0        NaN           2187.5               NaN
RQNAME:분봉차트조회요청, TRCODE:opt10080, RECORDNAME:, PRENEXT:2
[13:57:55] 정상 동작 중입니다.
RQNAME:분봉차트조회요청, TRCODE:opt10080, RECORDNAME:, PRENEXT:2
                     :
                     :
저가가 갱신되었습니다... 20220826, 20220826091000
저가가 갱신되었습니다... 20220826, 20220826090500
저가가 갱신되었습니다... 20220826, 20220826090000
True
   item_code  first_buy_price  second_buy_price
0        NaN          32700.0               NaN
RQNAME:분봉차트조회요청, TRCODE:opt10080, RECORDNAME:, PRENEXT:2
[13:58:11] 정상 동작 중입니다.
RQNAME:분봉차트조회요청, TRCODE:opt10080, RECORDNAME:, PRENEXT:2
                     :
                     :
저가가 갱신되었습니다... 20220826, 20220826091500
저가가 갱신되었습니다... 20220826, 20220826091000
True
   item_code  first_buy_price  second_buy_price
0        NaN           6460.0               NaN
[13:58:28] 정상 동작 중입니다.
                     :

 

 

얼레? 데이터가 이러면 어떻게 쓰나?

한 가지 문제가 있다면, 계산된 매수 예정 가격 데이터가 정확히 어떤 종목의 매수 예정 가격 데이터인지 확인하는 것이 어렵다는 것이다. 그렇다면 우리는 이 문제를 어떻게 해결하는 것이 바람직할까?

  • algorithm_1.py 파일 내에서 종목코드를 전달받아 데이터프레임(  self.df  )에 입력해서 main.py에 전달
  • main.py 파일 내에서 전달받은 데이터프레임(  result  )에 종목코드를 입력

어떤 방법을 사용하든 간에 문제는 없지만 본인의 경우에는 첫 번째 방법을 사용하고 있다. 그렇다면 algorithm_1.py 파일 내에   def __init__(self, min5_data, start_date):   부분에서 5분봉 차트 데이터와 일자 데이터 외에도 종목코드 데이터를 함께 전달받도록 수정해보자.
※ Line : 12

"""algorithm_1.py"""
import pandas as pd
import manage_db
from valuable import _df

class algo1:

    def __init__(self, min5_data, start_date, item_code):
        self.df = _df.algo1_df()
        self.min5_data = min5_data
        self.start_date = start_date
        self.item_code = item_code

 

이제 다시 main.py 파일 내에서는 for문에 의해 저장되어 있는   item_code  라는 변수를 함께 전달해주면 된다.
※ Line : 8

    def _pushbtn_7(self):

        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()

                print(result[0])
                print(result[1])

 

이제 다시 algorithm_1.py 파일로 돌아와서   self.df  의   ['first_buy_price'칼럼에 데이터를 입력하는 구간에서   ['item_code']  칼럼에도 동일하게   self.item_code  를 입력함으로써   self.df  데이터를 보다 완벽하게 만들 수 있다.
※ Line : 16

def run(self):
    self.highest_price = self.start_price
    self.lowest_price = 0
    self.pos_buy = False
    idx_of_df = len(self.df['item_code'])

    for data in self.tem_min5_data.itertuples():
        high = int(data.high)
        low = int(data.low)

        if high > self.highest_price:
            print(f"고가가 갱신되었습니다... {data.date}, {data.time}")
            self.highest_price = high  ## 고가 데이터 재입력
            self.buy_price = (self.start_price + self.highest_price) / 2
            self.df.loc[idx_of_df, 'first_buy_price'] = self.buy_price
            self.df.loc[idx_of_df, 'item_code'] = self.item_code
            self.lowest_price = high

            if high == self.standard_high:
                self.pos_buy = True

        if low <= self.lowest_price:
            print(f"저가가 갱신되었습니다... {data.date}, {data.time}")
            self.lowest_price = low

            if self.pos_buy:
                if low < self.buy_price:
                    print(f"매수 예정 가격에 닿았습니다... [{data.time}] {low}/{self.buy_price}")
                    return False, '0'

    return True, self.df

 

이제 프로그램을 다시 실행한 후 결과 데이터를 확인해보면, 아래와 같이 깔끔한 데이터가 전달되고 있음을 확인할 수 있다.

>>>
True
  item_code  first_buy_price  second_buy_price
0    042670           6695.0               NaN

True
  item_code  first_buy_price  second_buy_price
0    044060           2187.5               NaN

True
  item_code  first_buy_price  second_buy_price
0    048410          32700.0               NaN

True
  item_code  first_buy_price  second_buy_price
0    095910           6460.0               NaN

 

이제 다음 게시글에서는 이 데이터프레임 형태로 전달받은 데이터들을 모두 합쳐서 거래일 날짜를 기준으로 하여 데이터베이스에 저장하는 방법에 대해 알아보도록 하자.

 

 


728x90
반응형
Contents

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

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