파이썬으로 급등주 포착 알리미 만들기 : 전체 소스
토이 프로젝트/급등주 포착 알리미 만들기

파이썬으로 급등주 포착 알리미 만들기 : 전체 소스

by TechNyang 2024. 9. 22.
반응형

약속드린대로 전체소스를 공유드리겠습니다.

사실 지금까지 블로그를 통해 알려드린 내용은 과거 전자책으로 유료로 판매하던 내용입니다.

 

그리고 이것 말고도 암호화폐 거래소 API를 이용해서 여러 기술적 분석을 이용한 자동매매도 구현한 것이 있습니다.

이번 급등주 포착 알리미 포스팅이 조금이나마 여러분께 도움이 되셨다면 빠른 시일내에 업로드 하도록 하겠습니다.

 

참고로 그동안 파이썬 및 기타 라이브러리가 버전업이 되면서 아래 소스가 정상적으로 구현이 되지 않을 수도 있습니다.

그럴 경우 댓글을 달아주시면 확인하고 말씀드리도록 하겠습니다.

 

급등주 포착 알리미 전체소스

from urllib.request import urlopen
from bs4 import BeautifulSoup
import pandas as pd
import re
import time
import requests
from io import StringIO
import datetime
import telegram

goldenCrossStockList = []

telegramToken = '각자의 텔레그램 토큰을 입력해주세요.'
bot = telegram.Bot(token=telegramToken)

kosdaq200_list_dic = {}

stock_list = []

def get_stock_from_txt():
    file = open('stock_list.txt', 'r')
    while (1):
        line = file.readline()
        try:
            escape = line.index('\n')
        except:
            escape = len(line)

        if line:
            stock_list.append(line[0:escape])
        else:
            break
    file.close
    file = open('recommend_list.txt', 'r')
    while (1):
        line = file.readline()
        try:
            escape = line.index('\n')
        except:
            escape = len(line)

        if line:
            stock_list.append(line[0:escape])
        else:
            break
    file.close

def run():
    print('급등주 알리미 시작합니다.')
    isStockSend = {}
    isGetStock = False
    is_ready = False

    while True:
        now = datetime.datetime.now()
        open_market = now.replace(hour=9, minute=10, second=0, microsecond=0)
        close_market = now.replace(hour=15, minute=30, second=0, microsecond=0)
        get_stock_time = now.replace(hour=16, minute=00, second=0, microsecond=0)

        if now >= get_stock_time and not isGetStock:
            open('recommend_list.txt', 'w').close()  # 이전 파일내용 삭제.
            getStockData()
            send_golden_stock()
            isGetStock = True
            is_ready = False

        if now >= open_market and now < close_market:
            if not is_ready:
                get_stock_from_txt()
                for stockCd in stock_list:
                    isStockSend[stockCd] = False

                if isGetStock:
                    isGetStock = False

                is_ready = True

            for stockCd in stock_list:
                try: #국문 URL은 한국거래소에서 종목을 못가져올 때가 있다.
                    stockUrl = 'http://asp1.krx.co.kr/servlet/krx.asp.XMLSiseEng?code='+stockCd
                    reqStock = urlopen(stockUrl)

                    bsObjStock = BeautifulSoup(reqStock, 'lxml-xml')
                    currStockInfo = bsObjStock.find('TBL_StockInfo')
                    prevStockInfo = bsObjStock.find_all('DailyStock')

                    stockName = currStockInfo['JongName']
                    currPrice = float(currStockInfo['CurJuka'].replace(',',''))
                    prevHighPrice = float(prevStockInfo[1]['day_High'].replace(',',''))
                    prevLowPrice = float(prevStockInfo[1]['day_Low'].replace(',',''))
                    startPrice = float(currStockInfo['StartJuka'].replace(',',''))
                    prevRange = (prevHighPrice - prevLowPrice) * 0.5
                    tagetPrice = startPrice + prevRange

                    if currPrice > tagetPrice and not isStockSend[stockCd]:
                        bot.send_message(chat_id='각자의 chat id를 입력해주세요.', text=stockName+'('+stockCd+') : 변동성 돌파! 현재가 : '\
                                                                   + str(currPrice) + '타겟가 : ' + str(tagetPrice))
                        isStockSend[stockCd] = True
                    time.sleep(0.1)
                except:
                    continue
        time.sleep(1)

def getStockData():
    kosdaq200List = []
    for page in range(1, 5):
        kosdaqUrl = 'https://finance.naver.com/sise/sise_market_sum.nhn?sosok=1&page=' + str(page)  # 1페이지당 50종목
        reqKosdaq = urlopen(kosdaqUrl)
        bsObjKosdaq = BeautifulSoup(reqKosdaq, 'html.parser')
        kosdaqList = bsObjKosdaq.find_all('a', {'class': 'tltle'})
        for codeKosdaq in kosdaqList:
            try:
                kosdaqCmpNm = codeKosdaq.get_text()
                kosdaqHrefTxt = codeKosdaq.get('href')
                kosdaqPattern = re.compile(r'\d+')
                codeKosdaqTxt = re.search(kosdaqPattern, kosdaqHrefTxt)
                if codeKosdaqTxt != None:
                    kosdaqCd = str(codeKosdaqTxt.group())
                    kosdaq200_list_dic[kosdaqCd] = kosdaqCmpNm
                    kosdaq200List.append(kosdaqCd)
            except:
                continue
        time.sleep(0.1)

    makeDataFrame(kosdaq200List)

def getGoldenCrossStock(df):
    goldenDf = df.sort_values(by=['날짜'], axis=0)  # 날짜를 기준으로 오름차순으로 정렬
    goldenDf.reset_index(drop=True, inplace=True)
    ma60 = goldenDf['종가'].rolling(60).mean()
    ma20 = goldenDf['종가'].rolling(20).mean()  # 단순 20일선 20일평균이기 때문에 처음 19개는 결측값이 생김
    ma5 = goldenDf['종가'].rolling(5).mean()  # 단순 5일선 5일평균이기 때문에 처음 4개는 결측값이 생김
    ma20.dropna(axis=0, inplace=True)
    ma5.dropna(axis=0, inplace=True)
    if ma20.iloc[-1] >= ma20.iloc[-2] >= ma20.iloc[-3]:  # 20일선 우상향 or 횡보
        if ma5.iloc[-1] > ma5.iloc[-2] > ma5.iloc[-3]: # 5일선 우상향
            if ma5.iloc[-2] < ma20.iloc[-2] and ma5.iloc[-1] >= ma20.iloc[-1]: # 5일선이 막 20일선을 돌파
                return True

    if ma20.iloc[-1] > ma20.iloc[-2] > ma20.iloc[-3]: # 20일선 우상향
        if ma20.iloc[-2] < ma60.iloc[-2] and ma20.iloc[-1] >= ma60.iloc[-1]: # 20일선이 막 60일선을 돌파
            return True
        else:
            return False
    else:
        return False

def makeDataFrame(codeList):
    for code in codeList:
        stockDf = pd.DataFrame()
        for page in range(1, 21): #200일 데이터 가져옴(21) (1페이지당 10거래일 DATA)
            try:
               headers = {'User-Agent' : 'Mozilla/5.0'}
               priceUrl = 'https://finance.naver.com/item/sise_day.naver?code='+str(code)+'&page='+str(page)
               response = requests.get(priceUrl, headers = headers)
               html = BeautifulSoup(response.text, 'html.parser')
               table = html.select('table')

               if table:
                   # stockDf가 초기화되지 않았다면 빈 DataFrame으로 초기화
                   if 'stockDf' not in locals():
                       stockDf = pd.DataFrame()

                   # 테이블을 DataFrame에 추가
                   html_string = str(table[0])
                   new_df = pd.read_html(StringIO(html_string))[0]
                   stockDf = pd.concat([stockDf, new_df], ignore_index=True)

               time.sleep(0.1)
            except Exception as e:
                print(e)
                continue
        stockDf = stockDf.dropna()

        if getGoldenCrossStock(stockDf):
            goldenCrossStockList.append(code)
        # if getVolumeStock(stockDf):
        #    volumneStock.append(code)

def send_golden_stock():
    if len(goldenCrossStockList) > 0:
        with open('recommend_list.txt', 'at') as f:
            for goldenItem in goldenCrossStockList:
                f.write(goldenItem)
                f.write("\n")

        recomStockStr = ''
        bot.send_message(chat_id='각자의 chat id를 입력해주세요.', text='추천주가 생성되었습니다.')
        for goldenCd in goldenCrossStockList:
            stockName = getStockName(goldenCd)
            recomStockStr += stockName+'('+goldenCd+')' + ' ,'

        bot.send_message(chat_id='각자의 chat id를 입력해주세요.', text=recomStockStr)
        print("금일의 추천주" + recomStockStr)
    else:
        bot.send_message(chat_id='각자의 chat id를 입력해주세요.', text='금일은 추천주가 없습니다.')
        print("금일은 추천주가 없습니다.")

def getStockName(stockCd):
    url = 'https://finance.naver.com/item/main.nhn?code=' + stockCd
    reqStockName = urlopen(url)
    bsStockName = BeautifulSoup(reqStockName, 'html.parser')
    findList = bsStockName.find_all('dl', {'class': 'blind'})
    for item in findList:
        stockName = item.find('strong')
    return stockName.get_text()

if __name__ == '__main__':
    getStockData()
반응형

TOP

Designed by 티스토리

loading