도커는 환경 설정을 구성해주는 일종의 모듈이라 볼 수 있는데

보통 예제는 맥 (유닉스 기반), 우분투 (리눅스 기반)으로 예제가 구성 되어 있는데

윈도우에서 직접 해보는 방법에 대해서는 잘 안나와 있는거 같음.

 

물론 윈도우에서 우분투를 띄어서 그 안에서 돌릴 수 있으나, 

지금 집중하고 싶은것은 이더리움 네트워크이니, 윈도우 도커를 사용해서 구현하는 방법에 대해서 기술해 보겠습니다.

 

필요 설치. 

1. WSL2 설치

  WSL 는 윈도에서 리눅스 환경을 조성해 주는 프로그램입니다.

https://docs.microsoft.com/ko-kr/windows/wsl/install#step-4---download-the-linux-kernel-update-package

 

WSL 설치

wsl --install 명령을 사용하여 Linux용 Windows 하위 시스템을 설치합니다. Ubuntu, Debian, SUSE, Kali, Fedora, Pengwin, Alpine 등 원하는 Linux 배포판에서 실행되는 Windows 머신에서 Bash 터미널을 사용할 수 있습니

docs.microsoft.com

를 참고해서 설치해 봅시다.

(단순히 파워쉘에서 wsl --install 하면 되긴 하는데, 제대로 설치가 안될경우 이후 2번 윈도우 docker 설치시 문제가 발생할 수 있습니다.)

 

2. 윈도우 docker 설치

https://docs.docker.com/desktop/windows/install/

 

Install Docker Desktop on Windows

 

docs.docker.com

에서 윈도우 도커를 설치해 봅시다.

 

여기까지 제대로 됬으면 윈도우 도커를 실행시켜 봅니다.

이제 이더리움 네트워크 구성을 위해 환경 image를 받아 옵시다.

만약 go-ethereum 이 어떻게 생겼는지 소스를 보고 싶으시면

https://github.com/ethereum/go-ethereum 를 참고해서 소스를 받아 오시면 됩니다.

(Go 언어를 사용해서 기본적인 문법은 배워두는게 좋습니다. )

http://golang.site/go/article/1-Go-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%96%B8%EC%96%B4-%EC%86%8C%EA%B0%9C

 

예제로 배우는 Go 프로그래밍 - Go 프로그래밍 언어 소개

1. Go 개발자들 GO 프로그래밍 언어는 2007년 구글에서 개발을 시작하여 2012년 GO 버젼 1.0을 완성하였다. GO는 이후 계속 향상된 버젼을 내 놓았으며 2015년 말에는 1.5.2 버젼에 이르렀다. 흔히 golang 이

golang.site

소스 받는법

git clone https://github.com/ethereum/go-ethereum.git

 

3. docker 에 image 받기

파워쉘에서 아래와 같이 입력해 줍니다.

docker pull ethereum/client-go

제대로 받아 왔다면

이렇게 표시가 되어있을겁니다.

최근 비트코인 열풍으로 그래픽 카드가 아주 미쳐 돌아가고 있습니다.

불과 몇달전 적당히 맞출수 있는 PC가격으로 RTX 3060을 하나 겨우 살까 말까 해서

오히려 대기업 제품 PC가 가성비가 높아지는 아이러니한 상황이 나고 있습니다.

 

분명 85만원에도 부들부들하고 샀었는데, 3주도 안되서 115만원....

MSI 지포스 RTX 3060 게이밍 X D6 12GB 트윈프로져8

그와중에 브랜드 데스크탑 PC가격....

이 모든 원흉은 아시다 시피 가상화폐 체굴때문입니다.

 

세계 각국이 돈을 찍어대니까,

상대적으로 재화가 보장(?)되면서 소량으로 어떻게든되는(일확천금 노리는?) 

암호화폐로 돈이 쏠려 나가는거 같은데...

 

아래 동영상을 못보신 분들은 꼭 보시길 바랍니다.

암호화패 문제 뿐만아니라, 경제는 어려운데 주식이나 부동산은 왜 오르는지 잘 설명한 다큐멘터리입니다.

어쨋든 이걸 질러야 하나 말아야 하나 고민하다가 산 그래픽 카드

1,2달은 돌려야 본전은 뽑을꺼 같아서 집 PC로 채굴을 했습니다.

 

자료가 여기저기 파편화 되어있는걸 찾으면서 해봤습니다. 

처음 해보시는 분들에겐 좋은 가이드가 되길 바랍니다.

 

1. driver 준비

   암호화폐난으로 NVIDIA에선 드라이버에 채굴 lock 을 걸었습니다.
   채굴 프로그램이 돈다고 감지되는 순간, 채굴 효율을 절반으로 떨어트립니다. 
   (원래 0.0001 btc 캔다면, 이걸 의도적으로 0.00005 btc 캐도록 합니다)

 

   그런데, 실수인거 같은데(지금 공식 홈페이지엔 없습니다), 이 lock이 해제된 드라이버가 잠깐 나왔습니다.

   470.05 버젼인데 이 드라이버를 설치 하셔야 100% 성능이 나옵니다.

   구글에서 rtx 3060 mining driver 470.05 download 라고 검색하는걸로 설치 하시기 바랍니다.

 

   그리고 참고로 그래픽 카드 hdmi 가 꼽혀 있어야 100% 성능 나옵니다.
   펌웨어 설정인지 몰라도, gpu 100% 쓰고 있는데 모니터 출력이 없으면 무족건 해시를 반으로 다운 시키더군요.
   굳이 끼고 싶지 않으면 시중에 판매되는 hdmi 더미를 구입해서 끼는것도 방법입니다.
   

HDMI 더미플러그/더미 어댑터/4K 60hz/DUMMY PLUG/디스플레이 에뮬레이터/원격 가상 모니터

 

2. gpu 오버 클럭 프로그램 (msi 의 경우 애프터 버너 프로그램)

   gpu 를 100%, 120% 쓸 필요 없습니다. 어차피 아래와 같이 프로그램은 GPU를 100% 씁니다.

   대신 전성비라고 해서 전기쓰는 효율 대비 gpu 효율을 잘 뽑아야 합니다.

   

    무슨 말이냐면 파워를 65%만 공급해도 채굴량이 비슷하다는 것입니다 !!!

    24시간 내내 일하는거 100%로 돌리면 전기세도 많이 나오고,
    gpu도 금방 망가질테니 적절한 전압을 조절해야 하는게 좋습니다


    제 그래픽카드는 MSI라 애프터 버너 프로그램 썻는데,
    각 제조사마다 오버클럭 관련 프로그램 검색해서 설정하는게 좋습니다.

 

3-a. 안정적인 비트코인 채굴하기.

    비트코인은 솔직히 망할거 같진 않습니다.

    허상이네 아니네 그런 논쟁을 하려면 이미 2017,18년에 망했어야 했다고 봅니다.

    가장 사람들에게 인식이 각인된 비트코인
    그리고 모든 알트코인과도 환전이 가능하기 때문에 많이들 비트코인을 채굴합니다.

 

    문제는 비트코인은 전용 채굴 장비로 해야 어느정도 나오는데, 
    일반 사람들이 그럴 수 없으므로 일종의 mining pool 에 여러 pc들이 node 연결하여 hash power를 갖고 옵니다.

    그리고 나온 비트코인 갯수만큼 나눠갖죠.

 

    가장 편한 채굴 프로그램이 nicehash 프로그램입니다.

    www.nicehash.com/에 들어가서 가입하고 로그인 하면 아래와 같이 나옵니다

    dashboad는 현재 채굴 PC들 상태를 나타내 주고, 옆에 my wallets에는 그동안 채굴로 쌓인 비트코인이 보이네요

    최소 출금은 0.001 btc 이며 그전까진 출금이 안되니 주의 하시기 바랍니다.

 

    여기서 위 메뉴의 mining 으로 들어가서 오른쪽의 download minner or add asic 를 눌러 줍니다. 

그럼 채굴 프로그램을 설치하는 페이지가 나오는데

위에가 nvidia 최적화 마이너고, 아래가 범용입니다.

범용이 사용하기 쉬어서 어느정도 감 잡으면 위에걸로 교체 하시는게 좋습니다.

 

프로그램 설치시 입력하라고 채굴용 주소가 페이지에 나오는데 이거 copy 했다가 
채굴 프로그램 설치 후 수동으로 입력해 주셔야 합니다. 

참고로 여기서 채굴되서 들어온 비트코인은
아래 처럼 0.001 BTC가 되어야 출금이 가능합니다.
RTX 3060으로는 약 24시간 x 3주 넘게 돌려야 합니다.

 

3-b 그밖의 코인 캐기

  최근 도지코인에 대해서 말이 많고, 일론 머스크가 많이 언급하고 해서 

  그냥 라즈베리pi 4 같은거 사서 거기서 채굴할까 했는데,

  구글링 하던중 pc에서 채굴 하는 방법을 발견 했습니다.

  www.unmineable.com/coins

 게다가 이사이트는 위의 nicehash 처럼 가입을 하지 않아도 됩니다.

 

unMineable - Mine your favorite non-mineable crypto coin or token!

 

www.unmineable.com

코인 검색에 DOGE 검색해서 코인을 누릅시다

 

저 부분이 핵심입니다. 
필요한게 doge 코인 지갑 주소, 채굴 프로그램입니다. 

위에선 like lolMiner 라고 해서 여러 마이너 써도 된다는 뜻이니 적절한거 찾아서 돌리면 됩니다.

 

a 도지코인 입금 주소

  이건 업비트나 바이낸스, 주 거래소에 가서 지갑을 생성하면 주소값이 나옵니다
  암호화된 문자열이므로 손수 입력하단 오타 날수 있으니,
  업비트나 바이낸스 홈페이지에 가서 복사 버튼을 눌러 복사해야 합니다.

 

b. 채굴 프로그램

   일단 저는 피닉스 마이너를 다운 로드 하려고 합니다.

github.com/PhoenixMinerDevTeam/PhoenixMiner/releases/

 

Releases · PhoenixMinerDevTeam/PhoenixMiner

Official repository of the fastest Ethereum/Ethash miner with lowest devfee - PhoenixMinerDevTeam/PhoenixMiner

github.com

위에 링크 들어가서 맨위의 제목 같은거 누르면 

요렇게 다운 받을 수 있습니다.

다운을 받고 압축을 푼뒤 보면 아래처럼 코인별, 마이닝풀별 설정해놓은 배치파일이 있습니다.

다 필요 없고 하나 잡아서 ctrl + c, ctrl + v 를 한뒤에 0_doge.bat 라고 파일명 바꿔 줍시다
(확장자가 안보여도 그냥 복사했으면 확장자는 따라오니 이름만 0_doge로 바꿉니다)

 

그리고 오른쪽 버튼 눌러서 나오는 팝업메뉴에 편집으로 들어가 아래와 같이 수정합니다.

아까 a에서 갖고온 주소를 아래와 같이 입력합니다.

PhoenixMiner.exe -pool ethash.unmineable.com:3333 -wal DOGE:[도지코인주소].[워커이름 아무거나]#[추천인 코드 없어도됨] -pass x
pause

/* 예시
PhoenixMiner.exe -pool ethash.unmineable.com:3333 -wal DOGE:D7EcSgxgjekriB1ZwkrR6bnxU6X34KMXQG.Work3#r641-3w9h -pass x
*/

워커 (worker) 이름 뒤에 추천인 코드입니다.

괜찮으시면 제 코드 r641-3w9h 넣어 주셨으면 합니다. (이거 정리하는데 힘들었어요 ㅠㅠ)

 

그럼 이제 얘가 일하는건 어디서 볼 수 있냐?

저기에 doge 코인 지갑 주소를 넣어서 검색합니다.

 

그럼 아래와 같이 현재 채굴 현황이 나옵니다.

1시간에 1개정도 나오는거 같네요.

여긴 또 보니 30 doge 전까진 출금이 안되네요 

하지만 비트코인의 0.0001 몇에 비하면....

 

일단 1주일 정도 돌려본 상태입니다.
대충 92.8 도지코인이 채굴 되었고

 

업비트 입금 주소로 보니까 제대로 들어오고 있습니다

1주 = 3만원 => 1달 12만원 (만약 도지코인 단가 350원선에 왔다 갔다 한다면) 계산되니

비트코인 채굴보다는 조금 더 낳은거 같기도 합니다.

 

여튼 가상화폐도 좋지만

직접 사서 거래하는것 보단 천천히 적금하는거 처럼 이렇게 마이닝 하면서 몇년 모으는것도 하나의 답인거 같습니다.

 

가상화폐 시장 변동성은 해외 선물과 비등비등하다고 생각되니 투자하실땐 조심 하시고

부디 메이저 (비트코인, 이더리움, ... 시총 top 10이내) 코인만 투자하시는게 비교적 안전하니 유념하시기 바랍니다.

최근 미국 주식장 릴레이에 맞춰서

자녀에게도 선물을 주는 트렌드 입니다.

 

저도 자녀에게 테슬라랑 애플 주식 몇주 사주던 도중 

지난주 GameStop 사건이 조명 받으면서 미국에선 자녀에게 주식을 사주고

증서 (주권)을 실물로 발급받아서 액자에 기념선물로 준다는걸 알았습니다.

 

곧 설날이고 아이 세뱃돈으로 테슬라 주식 주권을 주면 좋아 하지 않을까 생각해서 

증권회사에 문의해 보았습니다만, 

이건 현지 미국인이 아니면 안되는거 같더군요

 

하지만 이대로 포기 할수 없어서 검색을 해봤는데,

아래와 같이 실제 주식을 사서 그걸 증서로 받은뒤 보내주는 서비스가 있더군요.

www.giveashare.com/eshop/10expand.asp?productcode=tsla-103

 

Gift Tesla Inc Stock | Real Ownership + Stock Certificate in our Paper Frame

"This was a gift and needless to say they loved it" by RAFAEL N. LOS ANGELES, CA 12/30/1899 131852 --> Honda stock --> "My experience with GiveAShare has been awesome! The customer service team was able to quickly assist me when I needed additional guidan

www.giveashare.com

하지만, 이거 일단 1주 사서 그것에 대한 증서를 뽑는건데,

지금 테슬라 1주는 대략 850달러선 거의 100만원에 육박 합니다. 

 

그래서 어쩔수 없이 주권을 프린트 해서 적당히 고친뒤, 

이걸 액자로 만들어 주는게 해주는게 좋을거 같아서 구글에 검색을 해봤습니다.

(어차피 실물은 계좌 통장에 찍혀 있으니까요)

이중 gov 아무리 봐도 정부 기간인데, 역시 미국 증권 거래위원회 홈페이지네요.

www.sec.gov/

 

SEC.gov | HOME

We Enforce Federal Securities Laws

www.sec.gov

www.sec.gov/Archives/edgar/data/1318605/000156459017003118/tsla-ex41_1279.htm

 

tsla-ex41_1279.htm

tsla-ex41_1279.htm Exhibit 4.1 ZQ|CERT#|COY|CLS|RGSTRY|ACCT#|TRANSTYPE|RUN|TRANS# COMMON STOCK NO PAR VALUE COMMON STOCK THIS CERTIFICATE IS TRANSFERABLE IN CANTON, MA AND NEW YORK, NY Certificate Number ZA00000000 Shares **00 00 00 ****************** ***0

www.sec.gov

여기서 테슬라 주권 사진 파일이 있으니 이걸 다운로드 합니다.

아마 실물의 경우 이것 저것 법적 문제가 있어서 그런건지

이미지 해상도가 썩 좋지 않네요 ㅠㅠ

다운 받은후 예제 글자 (이름, 갯수)를 적당히 지우고

이제 아래의 포토샵 같은 사이트에서 적당히 이름과 갯수를 적어줍시다.

pixlr.com/kr/x/#editor

 

사진 에디터 : Pixlr.com - 온라인 무료 사진 편집 툴

Pixlr X를 통해 브라우저에서 고급 사진 편집 툴을 바로 실행할 수 있어요. 별도의 설치 또는 회원가입이 불필요! 컴퓨터, 태블릿, 스마트폰에서 언제 어디서나 무료로 이용하세요.

pixlr.com

아래와 같이 위에는 이름, 밑에는 갯수를 적어주고 프린트를 한다음

이미지를 저장한 다음

프린트를 A4용지 전체에 맞춰야 하는데, 워드에서 이미지 로딩한후 이미지 크기를 A4용지에 맞추고 인쇄하면 됩니다.

 

마지막으로 인터넷에서 깔끔해 보이는 A4용지 액자를 주문해서 끼워주면 완성입니다.

 

소스파일은 github.com/galaxywiz/StockCrawler_py 에서 확인 가능합니다.

 

이제 봇까지 만들었으니 이 봇을 실행시켜 주는 시작점을 만들어 주도록 합시다.

Main 은 말 그대로 시작점이니, 봇을 셋팅 해서 만들어 준 다음 이 봇을 어떻게 굴리는지에 대해 보시면 좋을 거 같습니다.

 

main.py

### 라이브러리 설치
# python -m pip install --upgrade pip

### 필요 라이브러리들
# pip install pandas pandas-datareader dataframe
# pip install psutil requests schedule telepot yfinance beautifulsoup4 plotly  

### 딥러닝에 필요한 것들
# pip install tensorflow keras matplotlib astroid==2.2.5 pylint==2.3.1

### 윈도우에서 talib 설치시 아래 링크에서 파이썬 버젼에 맞는 (cpXX-amd64)로 다운 받아서 해줘야 한다.
# https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib
# pip install .\TA_Lib-0.4.19-cp38-cp38-win_amd64.whl

# 리눅스에선 그냥 
# pip install ta-lib
# 안될경우 리눅스에서 설치법
# $ wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
# $ tar -xvf ta-lib-0.4.0-src.tar.gz 
# $ cd ta-lib
# $ ./configure --prefix=/usr
# $ make

# 이 프로그램 설계
# 1. 웹에서 인기 있는 종목 수집 (거래량 순)
# 2. 웹에서 데이터 수집 (한국 주식 / 미국 주식)
# 3. 전략 테스팅 매수 / 매도 시스널 포착
# 4. 3에서 포착된 주식 차트 그리고 텔레그램으로 전송

import os
import time
import signal
import sys

import botConfig
from bot import Bot

def test(bot):
    bot.getStocksList()
    bot.checkStrategy()

def signalHandler(sig, frame):
    print('You pressed Ctrl+C!')
    sys.exit(0)
#-----------------------------------------
# 메인 함수 시작
if __name__ == '__main__':
    signal.signal(signal.SIGINT, signalHandler)
    
    usaBot = Bot(botConfig.USABotConfig())
    koreaBot = Bot(botConfig.KoreaBotConfig())

    test(usaBot)
    test(koreaBot)

    botList = []
    botList.append(usaBot)
    botList.append(koreaBot)

    while(True):
        now = time.localtime()
        if now.tm_wday < 6:  ## 일요일은 안함
            for bot in botList:
                bot.do()

        current = "%04d-%02d-%02d %02d:%02d:%02d" % (now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)
        print("지금시간 : [%s]" % current)
        time.sleep(60)

    

28라인까지는 이 프로그램 돌리기 위한 셋팅이나 아이디어에 대해서 적어 놨습니다.

실제 함수는 47라인에서 시작합니다.

 

48라인 보시면 시그널SIGINT 이런 거 받아오는데 저게 뭐냐 면 이 프로그램이 돌다가 Ctrl + C 입력이 들어오면 어떻게 처리할 것인지를 정의한 코드 입니다. 42라인 함수를 실행하는데 보면 exit로 프로그램을 강제로 꺼주게 하죠.

50라인에서 봇을 세팅해서 만들어 주고, 56 list안에 봇들을 넣어줍니다.

 

이후 while(true)로 무한 루프를 돌면서 1분마다 한 번씩 bot 들을 실행시켜 줍니다.

실행하면 아래 화면처럼 나올 겁니다.

 

'재테크 > 주식 알람 시스템 만들기' 카테고리의 다른 글

11. 조립 제작  (0) 2020.11.08
10. Bot  (0) 2020.11.08
9. 머신 러닝에 대해서  (0) 2020.11.08
8-3. 단기 변동성 돌파 전략  (0) 2020.11.08
8-2. MACD 전략  (0) 2020.11.08
8-1. 골든 크로스 전략  (0) 2020.11.08

소스파일은 github.com/galaxywiz/StockCrawler_py 에서 확인 가능합니다.

 

그동안 코드 읽으시느라 고생 많으셨습니다.
이제 지금까지 만들어 놓은 파츠를 조립하여 움직이는 몸통을 만들어 봅시다.

우선 파트가 2부분으로 되어 있습니다.
봇의 환경설정을 해주는 botConfig.py 라는 것과 이 botConfig라는 걸 이용해서 실제 돌아가는 bot.py 입니다.

먼저 환경 설정에 대해서 생각해 봅시다.

 

botConfig.py

import dataframe
from datetime import datetime
from datetime import timedelta
import time
import util

from stockCrawler import USAStockCrawler, KoreaStockCrawler
from sqliteStockDB import DayPriceDB, DayPriceFloatDB
from stockData import StockData, BuyState
from tradeStrategy import MaTradeStrategy, LarryRTradeStrategy, MACDTradeStrategy

# 봇 설정
class BotConfig:
    def crawlingTime(self):
        pass

#---------------------------------------------------------#
class KoreaBotConfig(BotConfig):
    def __init__(self):
        self.telegramToken_ = "1080369141:AAFfXa9y70x-wqR2nJBKCVMNLmNFpm8kwA0"
        self.telegramId_ = "108036914" 
        
        self.isFileLoad_ = False
        #self.listFileName_ = "Kr_watchList.txt"
        self.crawler_ = KoreaStockCrawler()
        self.dayPriceDB_ = DayPriceDB("KoreaStockData.db", "day_price")
        self.chartDir_ = "chart_Korea/"
        self.baseWebSite_ = "http://finance.daum.net/quotes/A%s"
        self.strategy_ = MACDTradeStrategy()
        self.isStock_ = True
        self.limitSize_ = 250
        
    def crawlingTime(self):
        now = time.localtime()
        startHour = 16
        startMin = 30
        if now.tm_wday < 5:
            if now.tm_hour == startHour and now.tm_min >= startMin: 
                return True
        return False

#---------------------------------------------------------#
class USABotConfig(BotConfig):
    def __init__(self):
        self.telegramToken_ = "1080369141:AAFfXa9y70x-wqR2nJBKCVMNLmNFpm8kwA0"
        self.telegramId_ = "108036914" 

        self.isFileLoad_ = False
        #self.listFileName_ = "USA_watchList.txt"
        self.crawler_ = USAStockCrawler()
        self.dayPriceDB_ = DayPriceFloatDB("USAStockData.db","day_price")
        self.chartDir_ = "chart_USA/"
        self.baseWebSite_ = "https://finance.yahoo.com/quote/%s"
        self.strategy_ = MACDTradeStrategy()
        self.isStock_ = True
        self.limitSize_ = 200

    def crawlingTime(self):
        now = time.localtime()
        startHour = 7
        startMin = 0
        if 0 < now.tm_wday and now.tm_wday < 6:
            if now.tm_hour == startHour and now.tm_min >= startMin: 
                return True
        return False

간략하게 한국 주식시장과, 미국 주식 시장 감시하는 설정입니다.
모두 생성자에서 변수 설정하고 이것은 어떤 크롤러 쓰고, 어떤 유를 쓰며, 어떤 전략을 채택하고, 텔레그램에서 url을 열 떄 사용하는 웹사이트는 무엇이며 등

나중에 일본 / 홍콩 / 상하이 같은 거 만드실 때 적절히 수정만 하면 다른 나라 주식 감시에도 큰 도움이 되실 겁니다.

 

다음은 봇에 대한 소스입니다.

기본적으로 __ 로 내부에서 사용하는 함수와, 외부에서 호출 가능한 함수를 구분하면서 코드를 읽으시면 한결 보기 편하실 겁니다.

 

bot.py

# 주식 데이터 수집해서 매매 신호 찾고 처리하는
# 주식 봇을 기술
from enum import Enum
import pandas as pd 
from pandas import Series, DataFrame
import numpy as np
import dataframe
from datetime import datetime
from datetime import timedelta
import time
import os
import shutil
import glob
import locale
import util

import botConfig
from stockCrawler import USAStockCrawler, KoreaStockCrawler
from sqliteStockDB import DayPriceDB, DayPriceFloatDB
from stockData import StockData, BuyState
from telegram import TelegramBot
from stockPredic import StockPredic
from printChart import PrintChart
from telegram import TelegramBot
from tradeStrategy import MaTradeStrategy, LarryRTradeStrategy, MACDTradeStrategy

class Bot:
    REFRESH_DAY = 1

    def __init__(self, botConfig):
        self.stockPool_ = {}
        self.config_ = botConfig
        self.telegram_ = TelegramBot(token = botConfig.telegramToken_, id = botConfig.telegramId_)

        locale.setlocale(locale.LC_ALL, '')
        now = datetime.now() - timedelta(days=1)  
        self.lastCrawlingTime_ = now

    def __process(self):
        self.getStocksList()
        self.checkStrategy()
        
        now = time.localtime()
        current = "%04d-%02d-%02d %02d:%02d:%02d" % (now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)
        print("[%s] 갱신 완료" % current)

    def __doScheduler(self):
        now = datetime.now()
        print("[%s] run" % self.config_.__class__.__name__)

        if self.config_.crawlingTime():
            elpe = now - self.lastCrawlingTime_
            if elpe.total_seconds() < (60*60*24 - 600):
                return
            
            self.lastCrawlingTime_ = datetime.now()
            self.__process()

    #----------------------------------------------------------#
    def sendMessage(self, log):
        TelegramBot.sendMessage(self, log)
  
    #----------------------------------------------------------#
    # db 에 데이터 저장 하고 로딩!
    def __getStockInfoFromWeb2DB(self, name, code):
        loadDays = 10
        # DB에 데이터가 없으면 테이블을 만듬
        sel = self.config_.dayPriceDB_.getTable(code)
        if sel == 0:
            return None
        elif sel == 1:  # 신규 생성 했으면
            loadDays = 365*5  #5 년치

        # 크롤러에게 code 넘기고 넷 데이터 긁어오기
        df = self.config_.crawler_.getStockData(code, loadDays)
        if df is None:
            print("! 주식 [%s] 의 크롤링 실패" % (name))
            return None

        # 데이터 저장      
        self.config_.dayPriceDB_.save(code, df)
        print("====== 주식 일봉 데이터 [%s] 저장 완료 =====" % (name))

    def __loadFromDB(self, code):
        ret, df = self.config_.dayPriceDB_.load(code)
        if ret == False:
            return False, None

        return True, df

    ## db 에서 데이터 봐서 있으면 말고 없으면 로딩
    def __loadStockData(self, name, code, marketCapRanking):  
        now = datetime.now()
        ret, df = self.__loadFromDB(code)
            
        if ret == False:
            self.__getStockInfoFromWeb2DB(name, code)
            ret, df = self.__loadFromDB(code)
            if ret == False:
                return None
        else:
            dateStr = df.iloc[-1]['candleTime']
            candleDate = datetime.strptime(dateStr, "%Y-%m-%d")
            elpe = (now - candleDate).days
            if elpe > self.REFRESH_DAY:
                self.__getStockInfoFromWeb2DB(name, code)
                ret, df = self.__loadFromDB(code)
                if ret == False:
                    return None

        #30일전 데이터가 있는지 체크
        if len(df) < 35:
            return None

        prevDateStr = df.iloc[-15]['candleTime']
        candleDate = datetime.strptime(prevDateStr, "%Y-%m-%d")
        elpe = (now - candleDate).days
        if elpe > 30:
            print("%s 데이터 로딩 실패" % name)
            return None

        sd = StockData(code, name, df)
        self.stockPool_[name] = sd
        sd.calcIndicator()
        sd.marketCapRanking_ = marketCapRanking

        print("*%s, %s load 완료" % (name, code))

    def getStocksList(self, limit = -1):
        self.stockPool_.clear()
        isFileLoad = self.config_.isFileLoad_
        if isFileLoad:
            fileName = self.config_.listFileName_
            stockDf = self.config_.crawler_.getStocksListFromFile(fileName)
        else: 
            tableLimit = self.config_.limitSize_
            stockDf = self.config_.crawler_.getStocksList(tableLimit)    # 웹에 있는 종목을 긁어온다.
            
        # 주식의 일자데이터 크롤링 / db 에서 갖고 오기
        for idxi, rowCode in stockDf.iterrows():
            name = rowCode['name']
            code = rowCode['code']
            marketCapRanking = rowCode['ranking']
            if type(name) != str:
                continue
            self.__loadStockData(name, code, marketCapRanking)
            if limit > 0:
                if idxi > limit:
                    break
    #----------------------------------------------------------#
    def __checkNowTime(self, sd):
        now = datetime.now()
        nowCandle = sd.candle0()
        dateStr = nowCandle["candleTime"]
        candleDate = datetime.strptime(dateStr, "%Y-%m-%d")
        elpe = (now - candleDate).days
        
        temp = self.REFRESH_DAY
        if now.weekday() == 6:
            temp += 2

        if elpe <= temp:
            return True
        return False

    def __doPredic(self, sd):
        vm = StockPredic(sd)
        predicPrice = vm.predic()
        sd.predicPrice_ = predicPrice[0]
        del vm

    def __drawChart(self, sd):
        # 시그널 차트화를 위한 
        chartMaker = PrintChart() 
        dir = self.config_.chartDir_
        chartPath = chartMaker.saveFigure(dir, sd)
        del chartMaker

        return chartPath

    def checkStrategy(self):
        now = datetime.now()
        time = now.strftime("%Y-%m-%d")
                
        for name, sd in self.stockPool_.items():
            if self.__checkNowTime(sd) == False:
                continue

            nowCandle = sd.candle0()
            nowPrice = nowCandle["close"]

            strategy = self.config_.strategy_
            strategy.setStockData(sd)
            action = BuyState.STAY
            timeIdx = len(sd.chartData_) - 1
            
            # 고전 전략 (EMA 골든 크로스로 판단)
            if strategy.buy(timeIdx):
                self.__doPredic(sd)
                action = BuyState.BUY
                sd.teleLog_ = "[%s][%s] 시총 순위[%d]\n" % (time, sd.name_, sd.marketCapRanking_)
                sd.teleLog_ +=" * [%s] long(매수) 신호\n" % (strategy.__class__.__name__)

            elif strategy.sell(timeIdx):
                self.__doPredic(sd)
                action = BuyState.SELL
                sd.teleLog_ = "[%s][%s] 시총 순위[%d]\n" % (time, sd.name_, sd.marketCapRanking_)
                sd.teleLog_ +=" * [%s] short(매도) 신호\n" % (strategy.__class__.__name__)
             
            sd.strategyAction_ = action

            if sd.strategyAction_ != BuyState.STAY:
                # if self.config_.isStock_:
                #     if sd.strategyAction_ == BuyState.BUY:
                #         if nowPrice > sd.predicPrice_:
                #             continue
                
                # sd.teleLog_ +=" * 금일 종가[%f] -> 예측[%f]\n" % (nowPrice, sd.predicPrice_)
                webSite = self.config_.baseWebSite_ % (sd.code_)
                sd.teleLog_ += webSite

                # 시그널 차트화를 위한 
                chartData = sd.chartData_
                chartData["BuySignal"] = strategy.buyList()
                chartData["SellSignal"] = strategy.sellList()
                chartPath = self.__drawChart(sd)
                if chartPath != None:
                    self.telegram_.sendPhoto(chartPath, sd.teleLog_) 

        self.config_.dayPreDB_.saveStockData(self.stockPool_)

    #----------------------------------------------------------#
    def do(self):
        self.__doScheduler()

제일 마지막, 234 라인의 do 라는 함수가 메인입니다.
이건 단순히 doScheduler 라는 걸 호출 하는데, 이렇게 만든 이유는 밖에서 보기엔 XXX_bot.do 라고 하면 봇에게 뭐 시키라고 하는 것 처럼 보이기 때문에 코드 읽으면서 의미 파악이 쉽기 때문에 저렇게 작성 했습니다.

 

내부에선 스케쥴을 돌게 하는데, 스케쥴이 정의된 48라인 보시면, 아까 botConfig crawlingTime 함수를 호출해서, 지금 이걸 실행해도 되는 시간인지 체크합니다.


물론 하루에 한 번씩 돌아야 하니 돌았을 때 실행되는 시간을 저장해서 연달아 돌지 않도록 장치를 해줍니다.

스케쥴 끝자락58라인에 보면 __process 라고 실제 진행에 대한 함수를 호출합니다.


그럼 40라인 정의를 보면, 주식 데이터 갖고 오고, 주식 전략을 체크해 보고 있죠.

그럼 주식을 갖고 오는 130라인 getStockList를 살펴봅시다.

아까 설정한 botConfig에 의해서 파일리스트로 종목을 얻을지, 웹에서 긁어올지 선택을 합니다. 그렇게 해서 나온 리스트는 147라인의 __loadStockData로 일봉 데이터를 긁어오게 됩니다.

 

__loadStockData는 보시면 살짝 복잡해 보이는 if문 코드들이 앞에 있는데, 이게 처음에 db에서 데이터를 로딩해서 없으면 데이터 크게 긁어 오는 것이고, 있다면, 최근 날짜를 조회해서 지금 시간과 1일이 지났는지 봐서 최대한 웹에서 긁어오지 않도록 하고 있습니다. (느리니까요)

다 로딩되면 124라인처럼 bot내부 pool에 등록을 시켜주고, 기술지표를 계산해 줍니다.

 

여기까지가 getStockList 내용이고요. 그 다음에 실행되는 것은 checkStrategy 함수를 살펴보죠

182라인인데, 각 주식 리스트에 대해서 botConfig에서 지정한 tradeStrategy.py에서 기술된 전략을 기반으로 매수 / 매도를 판단합니다.

 

추가로 매수 매도 판단되면 다음날 주식 종가를 예측하기 위해 __doPredic 이란 함수를 사용하고, 이것은 위의 stockPredic.py에서 작성한 머신 러닝 예측을 통해 값을 받아옵니다.

 

그리고 매수, 매도를 판단 받았다면 214라인주석 처리를 했는데, 이는 머신 러닝 값을 믿는다면, 사용하는 것이고, 전 아직은 아닌 거 같아 주석 처리를 해 놓았습니다.

 

이후 224라인에서 이 주식의 추세 판단을 위해 시각화, 즉 차트를 그려주고, 차트 이미지가 제대로 생성되었으면 229라인처럼 텔레그램으로 이 데이터를 전송합니다.

'재테크 > 주식 알람 시스템 만들기' 카테고리의 다른 글

11. 조립 제작  (0) 2020.11.08
10. Bot  (0) 2020.11.08
9. 머신 러닝에 대해서  (0) 2020.11.08
8-3. 단기 변동성 돌파 전략  (0) 2020.11.08
8-2. MACD 전략  (0) 2020.11.08
8-1. 골든 크로스 전략  (0) 2020.11.08

+ Recent posts