본문 바로가기
주식 trading coding skill(기술지표, 자동매수, 퀀트)

주식 현황 알리미 - telegram bot

by 호빵님 2020. 7. 25.
반응형

주식투자의 퀀트분야에서는 퀀트알고리즘 별 주가 조건을 주기적으로 체크하면서, 리밸런싱을 해야한다.

여기서는 모멘텀과 공황횟수를 자동으로 확인해서, 텔레그램으로 알려주는 프로그램을 소개한다.

이외에도 사용자가 사용하고 싶은 퀀트알고리즘을 코딩해서, 주기적으로 나에게 주가 상황을 알려주면 매우 편하게 월별로 리밸런싱을 할 수 있을 것이다.

 

먼저 나에게 메시지를 보낼 텔레그램 봇을 만든다. 이 봇의 token은 생성할때 알 수 있고, 이를 이용해서 나에게 메시지를 보내도록 코딩한다.

 

텔레그램봇 생성

 

아래 예제 코드를 참고바란다.

네이버 stock 웹페이지를 크롤링해서 주식20일(실재 한달) 이내의 주가 데이터를 이용하여 알고리즘을 만들 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# -*- coding: utf-8 -*-
"""
Created on Sun Apr  5 00:02:49 2020
 
@author: kenro
"""
 
import time
import telepot
from _datetime import datetime
from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
from pandas import DataFrame
from selenium import webdriver

#발급된 bot의 토큰입력. 해당 토큰의 bot제어.
token = '1111086078:A**********************************'
#나의 telegram ID 입력. bot이 나에게 메시지를 보내게됨
mc = '9989*****'

stock = ['KOSPI''KOSDAQ','NAS@IXIC']
stock_name =['KOSPI''KOSDAQ','NASDAQ']
기간 = 20 # 기간은 임의 지정
기간2 = 10
 
panic_threshold = -3  #주가 변화율 퍼센트의 공황상태 기준값. '내일의 부' 책에서는 -3%가 떨어지면 공황시작으로 봄.
AvgDate_momentum_score=[]
MovingAvg_momentum_score=[]
Panic_check=[]
 
def Search_stock_logic(stock):
    web = webdriver.Chrome('chromedriver.exe'# 크롬 웹 드라이버(본 py파일과 동일위치에 파일이 있을 경우는 별도 경로 불필요)
    
    if stock == 'KOSPI' or stock =='KOSDAQ' :
        url = 'https://m.stock.naver.com/sise/siseIndex.nhn?code=%s'%(stock)
    elif stock == 'NAS@IXIC' :
        url = 'https://m.stock.naver.com/world/item.nhn?symbol=%s'%(stock)
    
    web.get(url)
    time.sleep(3# 데이터가 화면에 완전히 뜰 수 있도록 기다림
    html_source = web.page_source
    web.close() # 크롬 웹드라이버 닫음
 
    soup = BeautifulSoup(html_source, 'html.parser')
 
    table = soup.find_all('td', class_= '_child_wrapper')
    
    cnt=0 # 받은 데이터 자리 확인용(날짜, 종가)
    date=[]
    global close
    close=[]
    UpDownRate=[]
    
    global df
    df = DataFrame()
    dt = datetime.now() # 날짜 오류 방지를 위해 현재 날짜받아옴
    
    for i in table:
        
        if cnt == 0 or cnt % 7 == 0# 날짜 저장(0번과 7의 배수자리이므로 7을 나눠서 나머지가 0인 자리)
            if dt.month < 5# 오늘이 5월 이전일 경우
                if i.text[:2== '01'# 1월 데이터면 올해 데이터
                    date.append(str(dt.year) + '-' + (i.text).replace('.''-'))
                elif i.text[:2== '02'# 2월 데이터면 올해 데이터
                    date.append(str(dt.year) + '-' + (i.text).replace('.''-'))
                elif i.text[:2== '03'# 3월 데이터면 올해 데이터
                    date.append(str(dt.year) + '-' + (i.text).replace('.''-'))
                elif i.text[:2== '04'# 4월 데이터면 올해 데이터
                    date.append(str(dt.year) + '-' + (i.text).replace('.''-'))
                else# 모두 아닐 경우는 작년데이터로 처리
                    date.append(str(dt.year-1+ '-' + (i.text).replace('.''-'))
            else:
                date.append(str(dt.year) + '-' + (i.text).replace('.''-'))
                
        elif cnt == 1 or (cnt - 1) % 7 == 0# 종가 저장(1번과 6의 배수자리)
            close.append((i.text).replace(','''))
            
        elif cnt == 3 or (cnt - 3) % 7 == 0# 종가 저장(1번과 3의 배수자리)
            UpDownRate.append((i.text).replace(',''').replace('%',''))
             
        cnt += 1
    
    df['DATE'= date
    df['CLOSE'= close
    df['RATE'= UpDownRate
    
    df['CLOSE'= pd.to_numeric(df['CLOSE']) # 계산을 위해서 숫자형으로 변환
    df['RATE'= pd.to_numeric(df['RATE']) # 계산을 위해서 숫자형으로 변환
    
    df = df[['DATE''CLOSE''RATE']]
    df = df.sort_values(by='DATE')
    df = df.set_index('DATE', inplace=False)
    
    df['MA3'= df['CLOSE'].rolling(window=3).mean() # 종가 3일 평균 열 생성
    df['MA5'= df['CLOSE'].rolling(window=5).mean() # 종가 5일 평균 열 생성
    df['MA10'= df['CLOSE'].rolling(window=10).mean() # 종가 10일 평균 열 생성
    df['MA20'= df['CLOSE'].rolling(window=20).mean() # 종가 20일 평균 열 생성
    df['SUM1'= np.where(df['CLOSE'- df['MA3'> 010# 종가 > 3일 평균이면 1점, 아니면 0점 부여
    df['SUM2'= np.where(df['CLOSE'- df['MA5'> 010# 종가 > 5일 평균이면 1점, 아니면 0점 부여
    df['SUM3'= np.where(df['CLOSE'- df['MA10'> 010# 종가 > 10일 평균이면 1점, 아니면 0점 부여
    df['SUM4'= np.where(df['CLOSE'- df['MA20'> 010# 종가 > 20일 평균이면 1점, 아니면 0점 부여
    df['SUM'= df['SUM1'+ df['SUM2'+ df['SUM3'+ df['SUM4'# 부여 점수 합 계산
    
    score=0
    for i in range(1,기간+1):
        score = np.where(df['CLOSE'/ df['CLOSE'].shift(i) > 110+ score # 마지막 날 기준으로 1일전 ~ 20일전까지 일별 비교하여 높으면 1, 낮으면 0으로 스코어 매겨서 더함
    score = str(score[len(score)-1]/기간*100# 기간으로 나눠서 평균모멘텀 게산함
    
    result = str(df['SUM'][len(df)-1])
    
    #공황 발생 횟수 계산
    df = df.sort_index(ascending=False)
    panic_score=0
    for i in range(0,기간):
        # 마지막 날 기준으로 거래일 1일전 ~ 20일전(날짜로 한달전)까지 일별 비교하여 높으면 1, 낮으면 0으로 스코어 매겨서 더함
        # 이전 한달이내에 공황으로 판단되는 주가 감소율이 발생한 횟수 임
        panic_score = np.where(df.iloc[i,1<= panic_threshold, 10+ panic_score 
    panic_score = str(panic_score)
    
    panic_score2=0
    for i in range(0,기간2):
        # 마지막 날 기준으로 거래일 1일전 ~ 10일전(날짜로 2주전)까지 일별 비교하여 높으면 1, 낮으면 0으로 스코어 매겨서 더함
        # 이전 한달이내에 공황으로 판단되는 주가 감소율이 발생한 횟수 임
        panic_score2 = np.where(df.iloc[i,1<= panic_threshold, 10+ panic_score2 
    panic_score2 = str(panic_score2)
    
    
    return score, result, panic_score, panic_score2
 
if __name__ == '__main__':
 
 
    for i in stock:
        score, result, panic_score, panic_score2 = Search_stock_logic(i)
        AvgDate_momentum_score.append(score)
        MovingAvg_momentum_score.append(result)
        Panic_check.append([panic_score,panic_score2])
        
    time1 = str(기간)
    tiem2 = str(기간2)
    # 결과 텔레그램 전송
    bot = telepot.Bot(token)
    bot.sendMessage(mc, '<주가지수모멘텀>' + '\n' + '1. 20일 평균 모멘텀' + '\n\t\t\t\t' + stock_name[0+ ' : ' 
                    + AvgDate_momentum_score[0+ '%' + '\n\t\t\t\t' + stock_name[1+ ' : ' 
                    + AvgDate_momentum_score[1]+ '%'+ '\n' + '\t\t\t\t' + stock_name[2+ ' : ' 
                    + AvgDate_momentum_score[2]+ '%'+ '\n\n'  + '2. 이동평균 모멘텀(4점만점)' 
                    + '\n\t\t\t\t' + stock_name[0+ ' : ' + MovingAvg_momentum_score[0+ '\n\t\t\t\t' 
                    + stock_name[1+ ' : ' + MovingAvg_momentum_score[1+ '\n\t\t\t\t' + stock_name[2+ ' : ' 
                    + MovingAvg_momentum_score[2+ '\n\n' + '<직전 한달간 공황 발생 횟수(일일주가하락율기준)>' 
                    + '\n\t\t\t\t' + stock_name[0+ ' : ' + time1 + '일 동안 ' + Panic_check[0][0+',  '+ tiem2 + '일 동안 '+ Panic_check[0][1
                    + '\n\t\t\t\t' + stock_name[1+ ' : ' + time1 + '일 동안 '+ Panic_check[1][0+',  '+ tiem2 + '일 동안 '+ Panic_check[1][1+ '\n' 
                    + '\t\t\t\t' + stock_name[2+ ' : ' + time1 + '일 동안 '+ Panic_check[2][0+',  '+ tiem2 + '일 동안 '+ Panic_check[2][1+ '\n' )
 
 
 
 
 
cs

 

위 코드를 실행하면, 텔레그램에서 나에게 현재 주가상태에 대해서 분석하여 메시지를 보내준다.

 

텔레그램봇이 주가 분석 메시지 보냄

 

이제 위 코드를 어떤 PC나 서버에서 자동으로 주기적으로 수행하도록 하면 된다. 텔레그램은 별로 안쓰니, 카카오톡으로 메시지를 보내도록 할 수도 있을 것 같다.

향후 연구를 해봐야겠다.

반응형