개발일지

10. 투자지표를 활용한 매매 시점 모니터링 - PDF Reporting

kirion 2022. 11. 19. 07:54
반응형

매매 시그널 발생 종목 PDF 보고서 작성

2022.11.01 - [개발일지] - 1. 투자지표를 활용한 매매 시점 모니터링 - 개요

2022.11.07 - [개발일지] - 2. 투자지표를 활용한 매매 시점 모니터링 - RSI, RMI

2022.11.07 - [개발일지] - 3. 투자지표를 활용한 매매 시점 모니터링 - 벡테스팅

2022.11.08 - [개발일지] - 4. 투자지표를 활용한 매매 시점 모니터링 - 시각화

2022.11.08 - [개발일지] - 5. 투자지표를 활용한 매매 시점 모니터링 - Kospi 종목 벡테스팅

2022.11.09 - [개발일지] - 6. 투자지표를 활용한 매매 시점 모니터링 - 손절선

2022.11.10 - [개발일지] - 7. 투자지표를 활용한 매매 시점 모니터링 - 다중 종목 벡테스팅

2022.11.15 - [개발일지] - 8. 투자지표를 활용한 매매 시점 모니터링 - 전략 설계 참고

2022.11.18 - [개발일지] - 9. 투자지표를 활용한 매매 시점 모니터링 - RSI 종목 추천

 

 

투자지표를 활용한 매매 시점 모니터링의 마지막 글이 될 것 같다.

대부분 조회, 검증, 보고서 작성 등 전략을 활용하기 위한 프로그래밍 위주의 내용들이고, 본격적인 전략 설계 및 테스트는 모니터링 시스템이 어느 정도 완성된 후에 새로운 시리즈로 진행할 예정이다. 

 

이번 글에서는 앞서 [9. 투자지표를 활용한 매매 시점 모니터링 - RSI 종목 추천] 글에서 매 일 별 매매 시그널이 뜬 종목을 이용해 보고서 형식으로 작성해보고자 한다.

 

앞서 저장되는 파일 목록을 보면

이런 식으로 매수, 매도 파일이 각각 나뉘어 있는 것을 볼 수 있다. 하나 씩 눌러보면

 

이렇게 보기 어려운 양식으로 저장이 되어있어서 종목 이름만 알지 추세나 현재 상태를 알기 어렵다. 따라서 이것을 보기 편하게 그리고 과거 추세도 알기 쉽게 보고서 형식을 만들어 저장해보자.

 

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime as dt
import copy
import pickle
from matplotlib.backends.backend_pdf import PdfPages

필요한 패키지 중 PdfPages가 새롭게 보인다.

x = dt.datetime.now()
buy_df = pd.read_csv('./RSI_monitoring_log/stock_rsi_buy'+str(x.month)+"월"+str(x.day)+"일"+'.csv',index_col = 0)
sell_df = pd.read_csv('./RSI_monitoring_log/stock_rsi_sell'+str(x.month)+"월"+str(x.day)+"일"+'.csv',index_col = 0)
rsi_df = pd.read_csv('./RSI_monitoring_log/stock_rsi_data.csv', index_col = 0)
rsi_df.index = pd.to_datetime(rsi_df.index)

sell_point = rsi_df.groupby(rsi_df.index).sum()["sell_tag"]
buy_point  = rsi_df.groupby(rsi_df.index).sum()["buy_tag"]

현재 날짜를 가져오기 위해 datetime함수로 가져오고, 당일 저장된 buy, sell 파일과 전체 종목이 저장되어있는 stock_rsi_data.csv를 불러온다.

저장했다가 불러올 때 날짜 형식의 index가 다르게 적용됨으로 타입을 날짜 형식으로 바꿔준다.

그리고 매매 시그널의 종합 정보를 알기 위해 groupby로 매매 시그널 수를 센다.

 

plot 함수는 두개이다.

첫 번째는 매매 시그널을 일 별로 종합해 보여주는 것이고 두 번째는 가격과 RSI 그리고 몇 가지 정보가 나타난다.

def summary_plot(point_df,plot_color,colname):
    fig, ax1 = plt.subplots(figsize = (14,7)) 
    ax1.set_ylabel('Price') 
    ax1.plot(price_data1["Close"],color = "tab:red",alpha = 1)
    ax2 = ax1.twinx() 
    ax2.set_ylabel('Count') 
    ax2.bar(point_df.index,point_df,alpha = 0.5,color = plot_color)
    plt.title("일 별 매매 시그널")
    plt.legend([colname])
    plt.show()
    return fig
def report_plot(i,c1):
    c1["lower_cut"] = 30
    c1["upper_cut"] = 70

    fig, ax1 = plt.subplots(figsize = (14,7)) 
    ax1.set_ylabel('Price') 
    
    ax1.plot(c1["Close"],color = "tab:red",alpha = 1)
    ax1.legend(["Price"],loc = "upper left")
#     ax1.plot(c1["High"],color = "tab:red",alpha = 0.2)
#     ax1.plot(c1["Low"],color = "tab:red",alpha = 0.2)

    ax2 = ax1.twinx() 
    ax2.set_ylabel('Index') 
    ax2.plot(c1["RSI"],color = "green",alpha = 0.5)
    ax2.plot(c1["RSI_signal"],color = "skyblue",alpha = 0.3)

    ax2.plot(c1["lower_cut"],color = "blue",alpha = 0.2)
    ax2.plot(c1["upper_cut"],color = "red",alpha = 0.2)
    ax2.set_ylim(0,100)
    plt.title(str(i+1)+" "+c1["stock_name"].values[0])
    plt.legend(["RSI","RSI_signal"],loc = 'upper right')
    tmp = c1.tail(1)
    rsi_v = tmp.RSI.values[0]
    rsi_s_v = tmp.RSI_signal.values[0]
    
    plt.text(c1.head(1).index, 10, 'RSI_signal      :  ' + str(rsi_s_v))
    plt.text(c1.head(1).index, 15, 'RSI               :  ' + str(rsi_v))
    plt.text(c1.head(1).index, 5, 'Volume_5day :  ' + str(c1.tail(5).Volume.to_list()))
    
    plt.show()
    return fig

 

pdfsave = PdfPages("./RSI_monitoring_log/report_buy_"+str(x.month)+"월"+str(x.day)+"일"+".pdf")
pdfsave.savefig(summary_plot(buy_point,"tab:blue","buy"))
for i,nm in enumerate(buy_df.stock_name):
    c1 = rsi_df[rsi_df["stock_name"]==nm].copy()
    pdfsave.savefig(report_plot(i,c1))
pdfsave.close()

PdfPages 함수를 통해 그래프를 pdf로 저장한다. 하나의 파일 안에 저장하기 위해 반복문을 사용한다.

일 별로 시그널이 나오는 종목 개수가 다르기 때문에 유동적으로 하기 위해서도 반복문을 사용했다. 위의 코드를 실행시키면 buy 시그널 종합 정보와 buy 시그널이 발생한 종목 별로 그래프를 그리면서 pdf에 하나씩 저장한다. pdf로 확인하기 전에 jupyter notebook 상에서도 출력할 수 있도록 해놓았다.

buy 시그널이 한 종목이었기 때문에 한 개의 그래프가 생성되는데 아래와 같다.

최근 200 거래일의 주가, RSI, RSI_signal, 30, 70 선이 그래프에 나타나고 조회일 기준의 값이 왼쪽 하단에 쓰여있다.

그래프만으로는 정확한 값을 알기 어렵기 때문에 text로도 나타내었다. 그리고 거래량도 중요하기 때문에 최근 5일의 거래량을 마지막 줄에 적었다. 거래량이 너무 없는 종목은 매수에 신중해야 하기 때문이다.

 

pdfsave = PdfPages("./RSI_monitoring_log/report_sell_"+str(x.month)+"월"+str(x.day)+"일"+".pdf")
pdfsave.savefig(summary_plot(sell_point,"tab:red","sell"))
for i,nm in enumerate(sell_df.stock_name):
    c1 = rsi_df[rsi_df["stock_name"]==nm].copy()
    pdfsave.savefig(report_plot(i,c1))
pdfsave.close()

매도 시그널이 발생한 종목도 동일하게 실행시켜 pdf로 저장한다.

 

 

여기서 한 가지, 보유 종목에 대한 보고서도 필요하다. 내가 가지고 있는 종목이 현재 괜찮은 흐름인지, 매수 혹은 매도에 가깝지 않은지, 가격은 얼마인지 과거의 정보와 한 번에 보기 위해 동일한 방식으로 보고서를 만든다.

 

stock_name = ["삼성전자","KT&G","NAVER"]

with open('holding_stock_name.pickle', 'wb') as f:
    pickle.dump(stock_name, f)

보유 종목을 수기로 적은 리스트를 pickle 패키지를 이용해 저장한다. 현재 글에서는 저장하고 바로 불러오지만, 보고서도 이전 글의 실시간 모니터링 시스템에 심을 예정이기 때문에 다른 스크립트에서 종목이 바뀌면 저장하는 방식으로 운용하면 될 것이다.(증권사 api와 연결은 아직 못했기 때문에..)

 

with open('holding_stock_name.pickle', 'rb') as f:
    holding_stock_name = pickle.load(f)

pdfsave = PdfPages("./RSI_monitoring_log/report_hold_"+str(x.month)+"월"+str(x.day)+"일"+".pdf")
pdfsave.savefig(summary_plot(buy_point,"tab:blue","buy"))
pdfsave.savefig(summary_plot(sell_point,"tab:red","sell"))
for i,nm in enumerate(holding_stock_name):
    c1 = rsi_df[rsi_df["stock_name"]==nm].copy()
    pdfsave.savefig(report_plot(i,c1))
pdfsave.close()

보유 종목을 불러온 후 똑같이 보고서를 만드는 코드에 실행시킨다.

 

 

위의 코드가 모두 실행되면 pdf 파일이 아래처럼 저장된다.

저장된 보고서 목록

pdf 형식으로 각 그래프가 다른 페이지에 할당되어 만들어졌다. 

 

앞으로 장이 마감되고 RSI 모니터링이 완료되면 이런 보고서가 매일 올라올 것이다. 올라오는 보고서를 검토하고 매매 종목을 결정하는데 참고 자료로 사용하면 편리할 것 같다.

 

 

보고서 양식은 간단하게 구현한 것임으로 참고만 바란다. 아직 전략이 구체적으로 구현된 것도 아니고, 보고서에 들어갈 만한 정보도 많을 것이다. 일 별 매수, 매도 시그널과 kospi 대표지수와의 관계 등 그럴 듯 한 보고서를 만드는 과정이 조금 더 필요할 것이다. 지금은 보고서로 저장 방식을 소개하고, 앞으로 주식 종목 모니터링 시스템에 통합할 때 사용할 기초 코드로 활용하기 위함이다.

 

또한, 파일을 내가 해당 위치에 들어가서 눌러보는 것이 아닌 카카오톡 혹은 메일로 첨부해 보내는 것까지 구현되면 좋을 것 같다. 카카오톡은 api로 파일보내기는 안 된다고 해서 다른 방법을 고민해봐야겠다.

 

반응형