PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 알고리즘 구축하기 (8) - 알고리즘 구현하기 ③

  • -

지난 게시글에서는 매수 가격의 기준이 되는 시가(self.start_price) 변수 값을 구했으니, 이번 게시글에서는 5분봉 차트 데이터가 담긴 변수인 self.min5_data 변수를 대상으로 for문을 사용하여 예정 매수 가격 데이터를 구해보자.

 

 

매수 예정 가격 계산하기

일단 기본적으로 이동평균선 간 골든 크로스가 발생한 시점의 봉의 시가 값인 self.start_price를 기준으로 해서 고가가 갱신될 때마다 해당 고가와 self.start_price 의 중간 가격을 매수 예정 가격으로 할 것이다. 그러기 위해서는 for문을 통해 특정 고가 데이터가 이전의 고가 데이터보다 높은지를 지속적으로 확인해줘야 한다. 이러한 기능은 어떻게 구현할 수 있을까?

기본적으로 데이터프레임을 대상으로 for문을 돌릴 때에는, 뒤에 itertuples()를 넣어줘야 한다. DataFrame을 대상으로 할 때에는 DataFrame.itertuples():와 같이 사용해야 한다는 것이다. 그리고 for data in ~~~: 부분에서, i는 단순하게 데이터프레임 내에 있는 데이터 한 줄 한 줄을 의미한다. 만약 DataFrame 내에 A, B, C라는 세 개의 칼럼이 있을 때, i.A는 A 칼럼의 데이터를, i.B는 B 칼럼의 데이터를, i.C는 C 칼럼의 데이터를 나타내는 것이다. 마찬가지로 아래 LIne 20에서 사용된   data.high  는 for문을 돌면서 잡힌 'high' 칼럼의 데이터를 의미하는 것이다. 아래의 도식과 같이 사용할 수 있다.

 

이제 이 내용을 바탕으로 코드를 구현해보면, Line 18에서와 같이 for문을 작성한 후에 Line 20에서와 같이 data.high와 기존 self.highest_price 간 비교를 통해 고가가 갱신되었는지 아닌지 그 여부를 판단해낼 수 있다. 여기서 self.highest_price 변수는 고가가 갱신될 때마다 값을 계속해서 새롭게 입력해줄 변수가 되는데, 시작 시점에서는 시가(self.start_price) 데이터를 입력해주면 된다. 그래야 약간의 갱신이 일어났을 경우에 고가 데이터를 계속해서 업데이트해줄 수 있기 때문이다. (물론 0을 입력해줘도 된다.)
※ Line : 16~21

"""algorithm_1.py"""
import pandas as pd
import manage_db

class algo1:

    def __init__(self, min5_data, start_date):
        self.min5_data = min5_data
        self.start_date = start_date
        self.min5_data['date'] = self.min5_data['time'].str.slice(start=0, stop=8)
        data_of_start_date = self.min5_data[self.min5_data['date'] == self.start_date].reset_index(drop=True)
        self.start_price = int(data_of_start_date.loc[0, 'open'])


    def run(self):
        self.highest_price = self.start_price

        for data in self.min5_data.itertuples():

            if data.high > self.highest_price:
                print("고가가 갱신되었습니다.")

 

그렇다면 이제 고가가 갱신되었다면 어떤 작업을 수행해줘야 할까? 단순하다. 매수 예정 가격을 계산해주면 된다. 매수 예정 가격이란 시가와 고가의 중심값이다. 다시 말해, self.start_price와 self.highest_price의 중심값이다.

Line 8에서는 고가 데이터를 재입력하는 기능을 갖고 있다. 즉, 여태까지의 고가 데이터인 self.highest_price보다 현재 고가인 data.high가 더 높은 것으로 판별됐으므로, 현재까지의 고가 데이터가 입력돼있는 self.highest_price의 값을 data.high로 변경해주는 것이다. 그 다음으로 self.buy_price 변수 내에는 self.start_price와 self.highest_price의 중간값을 계산해서 입력해준다. 이제 코드를 돌려보도록 하자.
※ Line : 7~11

    def run(self):
        self.highest_price = self.start_price

        for data in self.min5_data.itertuples():

            if data.high > self.highest_price:
                print("고가가 갱신되었습니다.")
                self.highest_price = data.high  ## 고가 데이터 재입력
                self.buy_price = (self.start_price + self.highest_price) / 2
                
        print(self.buy_price)

 

 


728x90

 

 

오류가 또 생기는데요?

Traceback (most recent call last):
  File "Algorithm/algorithm_1.py", line 40, in <module>
    algo1(min5_data, start_date).run()
  File "Algorithm/algorithm_1.py", line 27, in run
    if data.high > self.highest_price:
TypeError: '>' not supported between instances of 'str' and 'int'

str 형태의 자료형과 int 형태의 자료형 간에는 부등호를 통한 대소 비교가 불가능하다는 TypeError 오류이다. 즉, 앞서 self.start_price에 대해서는 int() 메서드를 통해 자료형을 숫자형으로 저장해주었지만 data.high 데이터는 아직 str(), 즉 문자열 자료이기 때문에 대소 비교가 안 되는 것이다. 예를 들어 문자형 데이터인 "30,000"과 숫자형 데이터인 20,000이 있다고 할 때, 이 둘 간에는 대소 비교가 불가능하다는 것이다. 왜냐하면 문자형 데이터인 "30,000"은 우리의 눈으로 보이는 30,000이 아닌 단순한 문자 그 자체이기 때문이다. 다시 말해, "30,000"은 "3만"이나 "300백"이나 다를 바 없는 하나의 문자열이므로 대소비교가 불가능한 것이다. 이 오류의 해결은 간단하다. data.high의 데이터 타입을 숫자형으로 지정해주면 된다.
※ Line : 5, 7, 9(5는 추가, 7과 9는 data.high 부분에서 data. 부분을 제거함)

    def run(self):
        self.highest_price = self.start_price

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

            if high > self.highest_price:
                print("고가가 갱신되었습니다.")
                self.highest_price = high  ## 고가 데이터 재입력
                self.buy_price = (self.start_price + self.highest_price) / 2
                
        print(self.buy_price)

 

저 반복문이 모두 돌아간 후에는 우리는 self.buy_price 데이터를 얻을 수 있다.

고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
70850.0

 

 

이제 이 데이터가 실제 데이터와 맞는지만 살펴보면 된다. 삼성전자의 주가 데이터를 확인해보도록 하자. 삼성전자의 2022년 7월 21일까지의 차트 모습이다.

우리가 사전에 계산했던 self.start_price의 값은58,400원이고 아래의 사진 상 그 이후에 형성된 고가 데이터는 62,100원이다. 그렇다면 58,400원과 62,100원 사이의 중간 값을 직접 계산해보면 60,250원이라는 값이 나와야 한다.

 

하지만 직접 결과 데이터를 확인해보니 60,250원이라는 값이 출력되지 않고 70,850원이 출력됐다. 골든 크로스가 발생한 이후의 최고가가 62,100원인데 어떻게 70,850원이 어떤 값의 중심값이 될 수가 있었을까?

이 오류는 가장 흔히 발생하는 오류이기도 하고, 이러한 오류가 발생했을 때 해결할 수 있는 가장 좋은 방법이 있다. 바로 현재 조회하고 있는 데이터의 시간 데이터를 함께 출력해주는 것이다. 그러면 언제 고가가 갱신되었으며 언제의 고가를 기준으로 계산된 데이터가 70,850원인지 확인할 수 있다.

고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
고가가 갱신되었습니다.
70850.0

 

 

 


728x90
반응형
Contents

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

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