주식 매매 신호 감지 및 이메일 알림 시스템

주식 매매 시 참고해야 할 것들

주식 투자에서, 차트만 보고 투자하는 것은 위험한 투기에 가깝다. 예를 들어 어떤 종목의 차트가 아래와 같다면 당신은 어떻게 할 것인가?

실제 바로 다음의 상황은 아래와 같았다.

이 경우 차트 상의 주가의 움직임만 볼 게 아니라 모멘텀을 분석했다면 주가 하락을 미리 감지할 수 있었다. 모멘텀은 주가의 추세를 말하는 것으로, 모멘텀을 파악하는 방법에는 여러 가지가 있지만 차트 상에도 이를 알 수 있는 곡선이 있다. 첫번째 사진을 다시 보자.

오른쪽 끄트머리에서, 비록 주가는 올랐지만 단기이동평균선(분홍실선)이 중기이동평균선(하늘색 실선)을 가로질러 하향했음을 볼 수 있는데 이처럼 단기 이동평균선이 중기, 장기 이동평균선을 가로질러 세 이동평균선을 아래로 끌어내리는 것은 대표적인 매도 신호 중 하나이다. 그래서 주식 투자를 할 때는 이동평균선의 추이를 매일 살펴야 한다.

하지만 주가 차트는 주식 투자 때 살펴 보아야 여러가지 정보 중 극히 일부분에 불과하다. 나의 경우, 차트보다 오히려 해당 기업의 펀더멘털(수익성, 성장성 등)을 가리키는 각종 지표와 금리 변화, 해당 기업의 각종 이슈, 경제 지표(물가지수 등)를 살펴 보고 나면 차트를 들여다 볼 시간은 별로 없다.

그래서, 상대적으로 덜 중요한 차트 상의 매매신호를 컴퓨터에게 맡기고, 나는 더 중요한 작업에 몰두하는 방법이 없을까 고민하게 되었다. 그리고 이동평균선 매매신호를 자동으로 발견해주는 프로그램을 만들게 되었다.

이 글에서는, 이러한 이동평균선 매매신호를 투자자가 직접 일일이 하지 않고 자동으로 발견하고 나아가 이를 이메일로 알림받는 작업을 해 볼 것이다.

아이디어 개요

프로젝트 아이디어 개요는 아래와 같다.

주식 데이터를 수집하고 매매신호 함숫값을 매일 산출, 매매신호가 뜨면 이메일로 알림받는 단순한 구조다.

이에 필요한 패키지는 각각 아래와 같다.

다행히 파이썬에는 없는 게 없었다. 이미 이메일 전송, 주식 데이터 수집 관련해서는 ‘이쯤이야..’하고 파이썬 라이브러리를 찾을 수 있었다.

1단계: 주가 데이터 수집

yfinance 패키지를 이용해, 티커명과 기간 등을 입력하면 이를 전달받아 그에 상응하는 데이터를 표 형식으로 아래와 같이 받을 수 있다.

df = yf.download(ticker, period='60d', interval='1d', auto_adjust=True)

2단계. 이동평균선 데이터 산출

이제, 단기, 중기, 장기 추세선에 관한 데이터를 만들 차례다. 이러한 선을 이동평균선이라 한다. 예컨대, 5일 이동평균선이란, 최근 5일간의 종가 평균값을 차곡차곡 이어 만든 꺾응선그래프를 말하는데 주가의 단기 추세를 보여주는 선이다. 나는 단기(5일), 중기(20일) 이평선만 만들었다.

이동평균선을 제공하는 별도의 함수가 없기 때문에 말 그대로 수학적으로 사고한 과정을 코드로 옮겨서 직접 만들었다. 보다시피 close 즉 종가 칼럼의 가장 하단의 5개를 rolling하여 mean 즉 평균을 구하고 이를 MA5란 새로운 이름의 칼럼 값으로 추가하여 5일 이동평균선 데이터를 만들었다. 20일 이평선도 비슷하게 만들었다.

df['MA5'] = df['Close'].rolling(window=5).mean()
df['MA20'] = df['Close'].rolling(window=20).mean()

실행하면 아래와 같이 아까는 없던 MA5, MA20 칼럼이 생긴 것을 볼 수 있다.

3단계. 매매신호 함수 정의

이제 매매신호 함수를 만들 차례다.

이평선에서 매수 신호란? 단기(중기) 추세선이 중기(장기) 추세선을 뚫고 올라가는 것을 말한다. 이를 골든 크로스라고 한다. (그 반대를 데쓰크로스라고 한다.) 골든크로스가 발생했다 해서 무조건 매수하라고 해석하는 것은 곤란하지만, 적어도 매수를 고민하기 시작해야 할 단계로 해석할 필요는 충분하다.

여기서는 골든 크로스 발생 여부를 반환해 주는 매수신호 함수를 만들어 볼 것이다. 어제는 5일 이평선이 20일 이평선보다 낮은 위치에 있었는데 오늘은 그 대소관계가 바뀌었다면 이는 어젯밤 사이 골든 크로스가 일어난 것이므로 실수 1을, 반대의 경우에는 실수 -1을, 이도 저도 아닌 경우는 실수 0을 반환하도록 짰다.

df['Signal'] = np.where(
    (df['MA5'] > df['MA20']) & (df['MA5'].shift(1) <= df['MA20'].shift(1)), 1, np.where(
        (df['MA5'] < df['MA20']) & (df['MA5'].shift(1) >= df['MA20'].shift(1)), -1, 0
    )
)

실행했더니 아래와 같이 오른쪽 끝에서, 4/15일에 매수신호가, 4/21에 매도신호가 뜸을 볼 수 있다.

이 코드는 오로지 파이썬 기본 문법과 약간의 수학 연산자만을 활용하였다. 수학적, 논리적 사고력만 충분하다면 특별한 것 없이도 충분히 쓸모있는 프로젝트를 완성할 수 있다.

4단계. 이메일 송신

이제 이메일 송신 부분이 남았다. 할 수만 있다면 클라우드 서버를 이용해 일을 키우고 싶었지만, 다음에 도전하기로 하고 전통적인 이메일 송신 과정을 이용하였다. 지메일의 기능을 이용했는데 패스워드는 보안상 지웠다. 이 기능을 이용하기 위해서는 구글 2차 인증 앱 비밀번호설정이 필요하다. 이렇게 메일 제목, 본문, 송수신자를 파라미터로 받아 송신함수를 정의할 수 있다.

def send_email(subject, body, to_email, from_email, app_password) :
    msg = MIMEMultipart()
    msg['From'] = from_email
    msg['To'] = to_email
    msg['Subject'] = subject 

아래는 결과이다.

나머지 과정은 예상대로다. 아까 매수신호는 1, 매도신호는 -1, 둘 다 아닌 경우 0을 반환하도록 정의하였다. 그래서 매수신호가 안 뜨면, 즉, 신호가 0인 경우는 신호가 없다는 내용의 이메일을, 그렇지 않은 날은 매매신호가 떴다는 알람 성격의 이메일을 보내도록 조건문을 작성하였다.

if len(cross_signals) == 0 :
    subject = "No signal today"
    body = "No signal today"
elif len(cross_signals) > 0 :
    subject = "ALARM : Buy/Sell signal triggerd!"
    body = "\n".join(cross_signals)
send_email(subject, body, TO_EMAIL, FROM_EMAIL, APP_PASSWORD)

아래는 결과창이고,

아래는 실제 첫 3일간의 메일함에 도착한 메일이다.

마무리

현재 내 포트폴리오에 종목이 15개 가량 있는데 이 종목들의 매매신호를 매일 일일이 확인하는 것은 여간 번거로운 일이 아니다. 매매신호 알림 시스템 덕분에 매일 모든 종목의 차트를 확인하는 번거로움은 줄이고, 남는 시간을 더 중요한 일에 집중할 수 있게 되었다.


코멘트

댓글 남기기

Cha's Record에서 더 알아보기

지금 구독하여 계속 읽고 전체 아카이브에 액세스하세요.

계속 읽기