'Study 외/Python' 카테고리의 글 목록 :: Horizontal Grays S2

2022년 4월 4일 1,000,000원으로 시작 ~ 4월 18일까지 거래하다가 랜섬웨어로 PC들이 맛가서 Stop

2022년 6월 15일 다시 정비해서 재개 그리고 7월 22일까지 총 37 거래일

1,000,000원이 755,581원이 되었다. 약 -24.5% 손실

 

KOSPI가 4월 4일 2757.90 ~ 7월 22일 2393.14로 약 13.2% 빠졌으니 훨씬 안좋은 결과이다.

 

처음 알고리즘으로 운영을 하면서 하한가를 맞는 종목들에 대한 대처가 전혀 안되고 손실로 작동을 해서

Losscut을 그리고 수익률 또한 특정 수익률이 되면 매도처리 하는 함수를 6월 중순경부터 넣어 돌렸으나

손실은 크게 다르지 않았다.

 

7월 중순부터는 그동안 일자별로 매수종목 리스트를 파일로 저장해두었는데

이를 기반으로 시뮬레이션을 돌려 최적의 K값과 이익이 나는 수익률 Cut, 그리고 Loss cut 비율을 찾아보고 적용해보았으나 역시 별 효과는 없었다.

 

       A371160  A271050  A409820  A233740   A390950  
고가      6635.0   4605.0   4860.0   8390.0  100735.0  
저가      6485.0   4540.0   4810.0   8045.0  100715.0  
종가      6485.0   4575.0   4830.0   8240.0  100715.0  
변동폭      150.0     65.0     50.0    345.0      20.0  
09:00   6485.0   4525.0   5000.0   8485.0  100745.0  
09:01   6485.0   4530.0   5010.0   8480.0  100740.0  
09:02   6510.0   4540.0   5010.0   8515.0  100740.0  
09:03   6500.0   4540.0   5000.0   8485.0  100740.0  
09:04   6555.0   4530.0   5015.0   8515.0  100740.0  
09:05   6520.0   4540.0   5005.0   8480.0       0.0  
09:06   6520.0   4535.0   5005.0   8460.0       0.0  
09:07   6515.0   4545.0   5015.0   8455.0  100740.0  
09:08   6515.0   4545.0   5015.0   8445.0       0.0  
09:09   6515.0   4540.0   5015.0   8405.0       0.0  
09:10   6510.0   4545.0   5010.0   8385.0  100740.0  
09:11   6515.0   4545.0   5005.0   8395.0  100740.0  
09:12   6520.0   4550.0   5005.0   8355.0       0.0  
09:13   6520.0   4550.0   5000.0   8345.0       0.0  
09:14   6515.0   4555.0   5000.0   8355.0  100740.0  
09:15   6550.0   4550.0   5000.0   8345.0  100740.0  
09:16   6545.0   4550.0   5000.0   8340.0       0.0  
09:17   6535.0   4550.0   5005.0   8355.0       0.0  
09:18   6535.0   4550.0   5000.0   8375.0       0.0  
09:19   6535.0   4550.0   5000.0   8395.0       0.0  
09:20   6535.0   4550.0   5000.0   8430.0       0.0  
09:21   6535.0   4550.0   5000.0   8415.0       0.0  
09:22   6545.0   4555.0   5010.0   8420.0       0.0  
09:23   6540.0   4550.0   5010.0   8405.0       0.0  
09:24   6530.0   4550.0   5005.0   8410.0       0.0  
09:25   6540.0   4550.0   5010.0   8390.0       0.0  
09:26   6535.0   4550.0   5010.0   8405.0       0.0  
09:27   6530.0   4545.0   5005.0   8410.0       0.0  
09:28   6530.0   4545.0   5010.0   8400.0       0.0  
09:29   6530.0   4550.0   5010.0   8395.0       0.0  
09:30   6530.0   4550.0   5005.0   8360.0  100745.0  
09:31      0.0   4545.0   5010.0   8375.0       0.0  
09:32   6525.0   4555.0   5010.0   8350.0  100740.0  
09:33   6525.0   4570.0   5005.0   8325.0       0.0  
09:34   6520.0   4570.0   5000.0   8320.0       0.0  
09:35   6525.0   4565.0   5005.0   8320.0       0.0  
09:36   6525.0   4565.0   5010.0   8315.0       0.0  
09:37      0.0   4570.0   5005.0   8295.0  100740.0  
09:38   6520.0   4565.0   5005.0   8285.0  100740.0  
09:39      0.0   4575.0   5005.0   8285.0  100740.0  
09:40   6525.0   4575.0   4995.0   8275.0  100740.0  
09:41   6520.0   4570.0   4990.0   8295.0       0.0  
09:42   6530.0   4575.0   4995.0   8320.0  100740.0  
09:43   6520.0   4575.0   4995.0   8320.0  100740.0  
09:44   6520.0   4580.0   4995.0   8315.0  100740.0  
09:45   6520.0   4580.0   4995.0   8295.0  100740.0  
09:46      0.0   4590.0   4995.0   8310.0  100740.0  
09:47   6535.0   4595.0   4995.0   8315.0  100740.0  
09:48   6535.0   4595.0   4995.0   8300.0  100740.0  
09:49      0.0   4595.0   4990.0   8320.0  100740.0  
09:50   6535.0   4595.0   4995.0   8295.0  100740.0  
09:51   6535.0   4590.0   4995.0   8275.0  100740.0  
09:52   6535.0   4590.0   4990.0   8270.0  100740.0  
09:53   6535.0   4590.0   5000.0   8250.0  100740.0  
09:54      0.0   4590.0   4995.0   8255.0  100740.0  
09:55   6530.0   4590.0      0.0   8265.0  100740.0  
09:56   6525.0   4585.0   4995.0   8280.0  100740.0  
09:57   6515.0   4580.0   5000.0   8280.0  100740.0  
09:58      0.0   4580.0   4995.0   8275.0       0.0  
09:59   6520.0   4580.0   4995.0   8260.0       0.0

위와 같이 종목리스트를 기준으로 전날의 변동폭을 pykrx를 이용하여 만들고

당일의 분단위 거래가를 yfinance를 이용하여 구한뒤

dataframe으로 저장

그리고 K값, Profit cut ratio, Loss cut ratio를 for문으로 돌려 가장 이득이 최대, 손실이 최소 인 값을 시뮬레이션 해보았다.

 

여튼 실패. 

시장을 이기긴 힘들다 게다가 어설프면 크게 당한다.

slack으로 매수, 매도 할때 등 메시지를 보냈으므로 그동안 살펴보면

 

자동화 프로그램은 매수시점이 꼭 한발 늦는다. 그래서 비싸게 산다.

그리고 최근의 시장은 조금 올렸다가 금새 내리꽂아 버린다.

이게 느낌적인 느낌일수 있겠지만 여튼 전략을 바꿔서

 

매수종목리스트의 10종목을 9시가 되면 무조건 매수
그리고 수익 또는 손실에 매도 해버리는 더 전략으로 바꿔보려고 한다.

이렇게 또 당분간 돌려보면서 고민해봐야겠다.

수업료는 둘째치고 그만큼 공부는 하고 있나?
그렇지 못한것 같은것도

녹아버린 계좌만큼 씁쓸하다.

 

일단 오늘까지의 파일은 저장! ㅋ (그럴일은 없겠지만 이거 다운받아 쓰시면 계좌가 녹아요~ ㅋㅋ)

 

AutoTrade.py
0.02MB

 

사실 사건이 발생한지는 시간이 좀 지났다.

고쳐놓은 프로그램이 잘 동작하는지 여부등의 확인을 위해 공유기의 외부접속포트를 열어놓았다.
프로그램이 돌아가고 있는 상태에서 로그등을 봐야하니 아무래도 회사에서 일하고 있는 시간이라

회사에서 접속해서 볼 요량이었다.

 

그리고 그 주 목요일 4/14일은 외근이 있어 나갔다가 집에 와서 컴을 켜보니....

랜섬웨어 경고창이... ㅠㅠ

 

맘이 급해 캡춰나 사진을 찍을 생각은 당연히 못하고

랜선뽑고 물려있는 외장하드들 떼어내고, 다른 PC와 NAS의 모든 LAN 연결 뽑았다.

하필이면 주식 PC가 저녁에 유튜브도 보고 영상도 보는 PC라 내장하드, 외장하드 많이 연결되어 있는...

 

여튼 다음과 같은 랜섬웨어에 감염되었다.

Elbie 랜섬웨어를 제거하고 .Elbie 파일을 해독하는 방법 (free-uninstall.org)

 

위 이미지는 위 링크에서 가져왔고 위 링크에 잘 설명되어 있다.

(여기에 보면 원격접속프로토콜 RDP 로 타고들어오니 접속포트 변경하라 라고 나와있는데...  지금생각해보니 너무 당연한건데... 내가 너무 안일했다 ㅠㅜ)


증상은 파일들이 *.Elbie 로 바뀌어버렸고

윈도우디펜더는 사라져서 무용지물이 되었고

내장하드 2개, 외장하드 2개 중 1개 감염

네트워크드라이브로 연결해둔 NAS 감염

C드라이브에 있던 주식 자동투자 관련 소스도 감염...

방법이 없다. 모두 포맷하는것 외엔 ㅠㅜ
그나마 NAS와 같이 윈도우즈 시스템 밖에 있는 데이터는 .Elbie 파일들을 제거하는 것만으로 별문제 없이 해결이 되었지만 불안해서 NAS도 시놀로지 다시 깔고

PC와 HDD는 모두 포맷 


일단 그렇게 시스템을 재정비하고

백업 관련해서는 어떻게 하면 좋을지 구상하고 있다.

의욕이 많이 꺾여버렸다..

아~ 잔인한 4월이여~

지난번 포스팅에서

Creon Plus 연결할때 키보드 연결 어쩌구 오류가 나왔었다고 썼는데 이는 PC를 사용할때는 나오지 않는 문제점인데 

밤새 사용하지 않다가 아침에 Creon Plus 자동실행하면 Ahnlab Online Security 에서 띄우는 문제점인가 보다.
여튼 아래와 같은 메시지가 뜨는데 파이썬으로 자동으로 Enter가 입력되게 해보려했으나 실패했다.

일단 출근전에 수동으로 Enter 한번 눌러주면 되긴 하니까 당분간은 그렇게.. T.T

 

 

4월 4일 월요일 첫날 성적은 좋았다. 수익률은 3.66% 문제점이라고 하긴 뭐하고 개선점으로 생각되는 부분이 보였다.

전 영업일에 자동으로 리스트업 해둔 리스트 중 3종목을 자동으로 매매를 했는데 그중 한 종목이 오전중 상한가를 쳤다.

알고리즘으로는 5종목까지 매수할수 있도록 예수금의 19%만 매수되게 했기에 상한을 쳐도 전체수익률이 상한은 아니다.

여튼 오전에 상한을 쳤으나 장종료 직전 매도까지 그상태 그대로 있다가 매도를 하게 된다.

이를 대비해서 상한에 근접 또는 상한가를 치면 바로 매도를 하도록 그리고 유리한 가격에 매도를 하도록 하는게 좋겠다.

 

 

4월 5일 둘째날은 안좋다. -1.22%

4개의 종목이 자동투자 되었는데 1개의 종목이 하한가에 근접했다. 이는 확실히 문제점이 맞다.

이부분 역시 대비해서 매수후 일정 % 이하로 떨어지면 손절을 하도록 프로그램을 수정하도록 해야겠다.

 

첫번째 문제건 두번째 문제건 팔아야한다.

 

주기적으로 체크해서 특정 이상 손실이면 팔고, 특정 이상 수익이면 팔아버리자

def check_losscut(code):
    try:
        global bought_list      # 함수 내에서 값 변경을 하기 위해 global로 지정
        time_now = datetime.now()
        cur_price, ask_price, bid_price = get_current_price(code) 
        bought_price_index = bought_list.index(code)
        bought_price = bought_list_price(bought_price_index)
        price_ratio = ((cur_price - bought_price)/cur_price)*100.0
        if price_ratio < -5.0:      #losscut -5%
            dbgout("-5% 이하로 떨어져서 손절 절차에 들어갑니다." + str(code))
            sell_stock(code)

        if price_ratio > 28.0:     #상한가
            dbgout("상한으로 판단하여 매도 절차에 들어갑니다." + str(code))
            sell_stock(code)

    except Exception as ex:
        dbgout("check_losscus() -> exception! " + str(ex))

뭐 이름을 losscut으로 했지만 수익이 나도 파는 것으로 했다.

기본적인 알고리즘은 샀을때 가격을 list에 넣어두었고 이를 현재가와 비교해서 

-5% 손실이면 손절

+28% 수익이면 상한으로 간주하고 익절하도록 했다.

 

돌아갈지는 아직 모르겠다 ㅎ

 

 

일단 실제 거래가 되는 루틴은 막고 돌려보았다.

 

3월 31일

오전 8시 Creon Plus 자동연결은 알아서 실행되었으나

Creon Plus 연결할때 키보드 연결 어쩌구 오류가 나왔는데 확인 누르니 넘어가고 

 

자동거래프로그램도 자동으로 실행되었는데... 퇴근하고 보니

아... 아무런 기록도 남아있지 않았다.

 

그리고 매수종목 리스트 프로그램도 실행결과가 남아있질 않았다.

 

자 하나씩 해결해보자.

1. 일단 Print 로그를 파일로 저장해버리기 위해 기존의 .py 를 실행하는 방식이 아닌 .bat 파일 실행 방식으로 바꾸었다.

 

AutoTrade.bat 파일을 만들고 파일의 내용은

python AutoTrade.py > AutoTradeResult.txt

이런식으로 저장해두고 작업 스케줄러를 다음과 같이 수정해서 bat파일을 실행하게 해주었다.

매수종목 list 만드는 프로그램도 마찬가지로 작업해서 txt파일로 기록을 남겨두도록 하였다.

 

2. Slack으로 메시지를 보내도록 수정했다.

프로그램의 시작/종료, 매수를 알리는 일 등을 Slack으로 메시지를 보내도록 수정하였다.

 

3. 매수종목 list 만드는 프로그램의 오류 수정

매수종목 list 만드는 프로그램이 결과를 내지 못하는 이유를 디버깅 하다보니 중간에 어제날짜의 데이터가 없으면 Error가 나는 것이었다. 그래서 DataFrame의 행의 수를 살펴 어제와 오늘 날짜의 Data가 있는 경우만 진행하도록 수정했다.

df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=etf_ticker)
    if(len(df) == 2):

수정한 source

from pykrx import stock
import time,sys
import pandas as pd
from datetime import datetime,timedelta
import requests

def post_message(token, channel, text):
    response = requests.post("https://slack.com/api/chat.postMessage",
        headers={"Authorization": "Bearer "+token},
        data={"channel": channel,"text": text}
    )
    print(response)

myToken = "xoxb-2241580444021-2948023303025-K4NHATNUlfFIJzl6KIpkhd9u"
def dbgout(message):
    """인자로 받은 문자열을 파이썬 셸과 슬랙으로 동시에 출력한다."""
    print(datetime.now().strftime('[%m/%d %H:%M:%S]'), message)
    strbuf = datetime.now().strftime('[%m/%d %H:%M:%S] ') + message
    #slack.chat.post_message('#etf-algo-trading', strbuf)
    post_message(myToken,"#stock",strbuf) 

dbgout('매수종목 List 작성을 시작합니다.')
#DataFrame define
kospi_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
kosdaq_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
etf_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])

today = datetime.today()- timedelta(0)      #오늘날짜 구하기 timedelta(1)을 빼면 어제날짜
yesterday = datetime.today()- timedelta(1)
str_today = today.strftime("%Y%m%d")        #구한 날짜를 String type으로
str_yesterday = yesterday.strftime("%Y%m%d")        #구한 날짜를 String type으로

print(str_today)
print(str_yesterday)
bt_day = stock.get_nearest_business_day_in_a_week(date=str_today)   #오늘 날짜 집어넣고 장을 여는 가장 가까운 날을 구함 오늘 장을 열면 오늘 날짜 반환
by_day = stock.get_nearest_business_day_in_a_week(date=str_yesterday)
print("btday=",bt_day)
print("byday=",by_day)
if bt_day != str_today: #오늘 날짜와 구한 날짜가 같지 않다는건 오늘 장을 열지 않는다는 것
    print("오늘은 장을 열지 않으므로 프로그램 종료")
    sys.exit(0)

kospilist = stock.get_market_ticker_list(date=bt_day, market="KOSPI")   #KOSPI 종목코드를 list로 반환
kosdaqlist = stock.get_market_ticker_list(date=bt_day, market="KOSDAQ") #KOSDAQ 종목코드를 list로 반환
etflist = stock.get_etf_ticker_list(date=bt_day)                        #ETF 종목코드를 list로 반환

kospi_stock_list_count = 0      #나중에 Dataframe에 count로 사용할 변수 초기화
kosdaq_stock_list_count = 0
etf_stock_list_count = 0

print("KOSPI 확인 - 종목수 : ",len(kospilist))
for kospi_ticker in kospilist:  #KOSPI 종목
#for i in range(100):   #for test
    #kospi_ticker = kospilist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kospi_ticker)    #KOSPI 종목코드 어제,오늘 관련정보 DataFrame

    if(len(df) == 2):
        yesterday_volume = df.iloc[0]['거래량']     #DataFrame에서 어제 거래량 변수로 입력
        today_volume = df.iloc[1]['거래량']         #DataFrame에서 오늘 거래량 변수로 입력
        today_price = df.iloc[1]['종가']            #DataFrame에서 오늘 종가 변수로 입력
        
        print("종목코드",kospi_ticker)
        print("종가",today_price) 
        print("어제 거래량",yesterday_volume)
        print("오늘 거래량", today_volume)
        if yesterday_volume == 0:                   #어제거래량이 없으면 거래량변화 -100
            volume_ratio = -100
        else:
            volume_ratio = (today_volume-yesterday_volume)/yesterday_volume     #거래량변화율 

        
        new_data = [kospi_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
        kospi_stock_list.loc[kospi_stock_list_count] = new_data     #관련 정보 DataFrame의 행에 추가
        kospi_stock_list_count = kospi_stock_list_count + 1
        time.sleep(1) 

print("KOSDAQ 확인 - 종목수 : ",len(kosdaqlist))
for kosdaq_ticker in kosdaqlist:
#for i in range(100):       #for test
    #kosdaq_ticker = kosdaqlist[i]  #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kosdaq_ticker)
    if(len(df) == 2):
        yesterday_volume = df.iloc[0]['거래량']
        today_volume = df.iloc[1]['거래량']
        today_price = df.iloc[1]['종가']
    
        print("종목코드",kosdaq_ticker)
        print("종가",today_price) 
        print("어제 거래량",yesterday_volume)
        print("오늘 거래량", today_volume)
        if yesterday_volume == 0:
            volume_ratio = -100
        else:
            volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

        
        new_data = [kosdaq_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
        kosdaq_stock_list.loc[kosdaq_stock_list_count] = new_data
        kosdaq_stock_list_count = kosdaq_stock_list_count + 1
    time.sleep(1) 



print("ETF 확인 - 종목수 : ",len(etflist))
for etf_ticker in etflist:
#for i in range(100):   #for test
    #etf_ticker = etflist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=etf_ticker)
    if(len(df) == 2):
        yesterday_volume = df.iloc[0]['거래량']
        today_volume = df.iloc[1]['거래량']
        today_price = df.iloc[1]['종가']
        
        print("종목코드",etf_ticker)
        print("종가",today_price) 
        print("어제 거래량",yesterday_volume)
        print("오늘 거래량", today_volume)
        if yesterday_volume == 0:
            volume_ratio = -100
        else:
            volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

        
        new_data = [etf_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
        etf_stock_list.loc[etf_stock_list_count] = new_data
        etf_stock_list_count = etf_stock_list_count + 1
        time.sleep(1) 

all_stock_list = pd.concat([kospi_stock_list,kosdaq_stock_list])    #KOSPI와 KOSDAQ은 합쳐서 하나의 DataFrame으로

print("KOSPI")
print(kospi_stock_list)
print("KOSDAQ")
print(kosdaq_stock_list)
print("KOSPI+KOSDAQ")
print(all_stock_list)
print("ETF")
print(etf_stock_list)


all_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #거래량 우선으로 정렬
sort_volume_list = all_stock_list.head(12)                                          #그중 12개만 추출해서 저장
print("all stock sort by volume")
print(sort_volume_list)
sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)  #12개를 거래량 변화율로 정렬
sort_ratio_list = sort_volume_list.head(6)                                          #그 중 6개만 추출해서 저장
print("all stock sort by volume")
print(sort_ratio_list)

etf_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #ETF도 같은 과정 
etf_sort_volume_list = etf_stock_list.head(28)
print("ETF stock sort by volume")
print(etf_sort_volume_list)
etf_sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)
etf_sort_ratio_list = etf_sort_volume_list.head(14)             
print("ETF stock sort by volume")
print(etf_sort_ratio_list)

total_stock_list = pd.concat([sort_ratio_list,etf_sort_ratio_list])     #최종 KOSPI,KOSDAQ에서 6개, ETF에서 14개 총 20개 를 하나의 DataFrame으로 합치고
print("Total stock sort by volume")
print(total_stock_list)

final_stock_list = list(total_stock_list['stock_code'])     #DataFrame에서 종목코드만 List로 뽑고
print("final Stock List")
print(final_stock_list)

for i in range(len(final_stock_list)):
    final_stock_list[i] = 'A'+ str(final_stock_list[i])     #List에 'A' 추가해서
print(final_stock_list)

f = open('codelist.txt','w')
f.write(','.join(final_stock_list))     #파일로 저장
f.close()

dbgout('매수종목 List 작성을 종료합니다.')
#symbol_list = open('codelist.txt','r').read().split(',')       #for verify
#print(symbol_list)                                             #for verify

 

4월 1일

오전 8시 Creon Plus 자동연결은 알아서 실행되었으나

Creon Plus 연결할때 키보드 연결 어쩌구 오류가 또 나왔는데 역시 확인 누르니 넘어갔다.

나중에 다시 실행해보아도 이부분은 문제가 없이 잘 실행되는데 물리적키보드가 연결이 안되어있는게 문제인건가?

 

그리고 나머지는 잘 실행되긴 했다.

하지만 결과는...

 

일단 실제 프로그래그램에서 매수할 종목의 수는 5종목이지만 실제 매수는 하지 않았으므로 조건에 해당하면 메시지를 보냈다.

그 결과 오늘은 총 7종목이 조건에 해당한다고 메시지를 보냈다.

 

KODEX 인버스(A114800) 0.0EA : 4310 meets the buy condition!`
[04/01 09:10:07] but_etf 매수 종목 : KODEX 인버스종목코드 : A114800현재가 : 4310 => 4300

[04/01 09:10:41] KODEX 200선물인버스2X(A252670) 0.0EA : 2480 meets the buy condition!`
[04/01 09:10:41] but_etf 매수 종목 : KODEX 200선물인버스2X종목코드 : A252670현재가 : 2480 =>2465

[04/01 09:11:38] TIGER 200선물인버스2X(A252710) 0.0EA : 2590 meets the buy condition!`
[04/01 09:11:38] but_etf 매수 종목 : TIGER 200선물인버스2X종목코드 : A252710현재가 : 2590 => 2575

[04/01 09:12:32] TIGER 단기통안채(A157450) 0.0EA : 100740 meets the buy condition!`
[04/01 09:12:32] but_etf 매수 종목 : TIGER 단기통안채종목코드 : A157450현재가 : 100740 => 100730

[04/01 09:23:58] 켐온(A217600) 0.0EA : 3180 meets the buy condition!`
[04/01 09:23:58] but_etf 매수 종목 : 켐온종목코드 : A217600현재가 : 3180 => 2985

[04/01 09:30:06] TJ미디어(A032540) 0.0EA : 9700 meets the buy condition!`
[04/01 09:30:06] but_etf 매수 종목 : TJ미디어종목코드 : A032540현재가 : 9700 => 9400

[04/01 11:20:10] TIGER 차이나전기차SOLACTIVE(A371460) 0.0EA : 14750 meets the buy condition!`
[04/01 11:20:10] but_etf 매수 종목 : TIGER 차이나전기차SOLACTIVE종목코드 : A371460현재가 : 14750 => 14670

 

파란색 글자는 실제 오늘 종가이다.  모두 마이너스 ...

계산해보면 실제 공식보다 비싼 현재가에서 구매를 하는걸로 되는데 이부분 감안해서 K값을 조금 줄여야 할것 같다.

현재 K값은 0.5

여튼 실제 투자는 다음주부터 일단 해보는 걸로!

 

 

책을 아직도 다 읽진 않았지만 - 앞으로도 다 읽진 않겠지만 - 

매수종목 선정 방법 관련해서는 자세히 나온것이 없다. 

그래서 임의로 내가 방법을 세우고 프로그래밍해려고 한다.

 

검색해보면 이러한 종목이 오를 것이다라는 여러 이야기 들이 있지만 복잡한것까지는 잘 모르겠다.

내 경험상으로도 그렇고 검색 결과로도 그렇고 일단 거래량이 가장 중요한 것 같다.

그래서 일단 단순하게

 

1. 이틀전 거래량 - 하루전 거래량 으로 거래량 증가폭이 높은 순으로 정렬해서 최상단 20종목 추리고

2. 그중 하루전 거래량 기준으로 절대 거래량 높은 순으로 10종목 추려서 매수종목 리스트에 넣는다.

 

이런 단순한 방법을 우선 취해보기로 했다. 

이렇게 한 근거는 일단 없다. 이렇게 해보고 결과가 안좋으면 수정해야겠다.

 

크레온 플러스 API 예제를 이용하면 더 편할것 같기도 한데 이게 제한이 있다.

   조회 제한  실시간 제한
시세
오브젝트
15초에 최대 60건으로제한
초과 요청시 첫 요청으로부터 15초가
지날 때까지 내부적으로기다림
최대 400건의요청으로제한
초과요청시오류
주문관련오브젝트 15초에 최대 20건으로제한
초과 요청시 첫 요청으로부터 15초가
지날 때까지 요청함수(Request, BlockRequest, BlockRequest2)에서
4를 반환
제한 없음

그래서 일단 네이버 스크래핑을 위주로 이용해보기로 한다.

 

먼저 처음 예제였던 종목정보 구하기 예제를 차후에 파일로 가공할 것을 감안하여 조금 수정하고

실행해서 전체종목의 코드를 구해봤다. (이건 크레온 플러스 API 이용)

 

import win32com.client

# 연결 여부 체크
objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
bConnect = objCpCybos.IsConnect
if (bConnect == 0):
    print("PLUS가 정상적으로 연결되지 않음. ")
    exit()
 
# 종목코드 리스트 구하기
objCpCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
codeList = objCpCodeMgr.GetStockListByMarket(1) #거래소
codeList2 = objCpCodeMgr.GetStockListByMarket(2) #코스닥
 
 
print("번호",",","종목코드",",","종목명",",","구분코드",",","금액")
for i, code in enumerate(codeList):
    secondCode = objCpCodeMgr.GetStockSectionKind(code)
    name = objCpCodeMgr.CodeToName(code)
    stdPrice = objCpCodeMgr.GetStockStdPrice(code)
    print(i,",",code,",", name,",", secondCode,",", stdPrice)
    
for i, code in enumerate(codeList2):
    secondCode = objCpCodeMgr.GetStockSectionKind(code)
    name = objCpCodeMgr.CodeToName(code)
    stdPrice = objCpCodeMgr.GetStockStdPrice(code)
    print(i+len(codeList),",",code,",", name,",", secondCode,",", stdPrice)
 
#print("거래소 + 코스닥 종목코드 ",len(codeList) + len(codeList2))

실행할 때 단지 아래와 같이 하면 print 결과값을 파일로 저장한다.

python test1.py > codelist.txt

 

이로써 codelist.txt라는 종목정보파일이 만들어졌다.

이 파일의 끝을 보면 "거래소 + 코스닥 종목코드  3306" 으로 총 3306 종목이 있슴을 알 수 있고

위 그림과 같이 ETF도 포함되어 있슴을 알 수 있다. 

 

이 txt파일을 엑셀에서 읽어서 금일거래량, 전일거래량, 거래량증가비 열을 추가하고 codelist.xlsx 로 저장했다.

 

우선 파이썬에서 엑셀 데이터를 다루기 위해서 openpyxl을 설치해주도록 한다.

pip install openpyxl을 cmd 창에서 실행

 

 

-----------------------------------------------------------------------------------------------------------------------------------

이렇게 하다가 문제가 발생했다.

여튼 엑셀데이터의 종목코드를 읽고 거래량을 구하는 과정에서 현재 거래정지된 종목의 경우 에러가 발생하는 것이었다.

여기서 예외처리를 할까 하다가 전면 수정을 하기로 하고 다시 프로그램을 작성했다.

종목코드 자체를 매일 실시간으로 읽어서 진행하기로...

 

검색해보니 pykrx 라고 주식관련 라이브러리가 아주 잘되어 있었고 어차피  엑셀을 이용해도 이 라이브러리를 이용했어야 했다. ("GitHub - sharebook-kr/pykrx: KRX 주식 정보 스크래핑" 참고)

 

기본적인 구상은 다음과 같다.

매일 장을 종료하면 이 프로그램을 실행하여

1. 종목코드를 get_market_ticker_list() 로 읽어와서

2. get_market_ohlcv_by_date() 로 거래량 정보를 읽고 가공 후 DataFrame에 집어넣고

3. 각 DataFrame을 거래량 별로 정렬 후 상위 추출, 거래량 변화율 별로 정렬 후 상위 추출

4. ETF는 70%, KOSPI/KOSDAQ에서는 30%로 구성해서 20개 종목을 최종 List 만들어서

5. 파일로 저장

6. 다음날 자동거래 프로그램에서 매수대상 리스트는 이 파일을 읽어서 20개의 후보군으로 실행

 

파이썬을 잘 모르기도 하고 혼자서 단순하게 막 짜다보니 좀 비효율적인 프로그램이 된것 같긴 하지만 일단 테스트로 돌려본 결과 잘 돌아가긴 한다.

 

내일 자동거래 프로그램을 백테스팅용으로 수정을 좀 하고 목,금 백테스팅을 좀 하고 4월부터는 실제거래를 해봐야겠다.

 

 

from pykrx import stock
import time,sys
import pandas as pd
from datetime import datetime,timedelta

#DataFrame define
kospi_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
kosdaq_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])
etf_stock_list = pd.DataFrame(columns=['stock_code','price','yesterday_volume','today_volume','volume_ratio'])

today = datetime.today()- timedelta(0)      #오늘날짜 구하기 timedelta(1)을 빼면 어제날짜
yesterday = datetime.today()- timedelta(1)
str_today = today.strftime("%Y%m%d")        #구한 날짜를 String type으로
str_yesterday = yesterday.strftime("%Y%m%d")        #구한 날짜를 String type으로

print(str_today)
print(str_yesterday)
bt_day = stock.get_nearest_business_day_in_a_week(date=str_today)   #오늘 날짜 집어넣고 장을 여는 가장 가까운 날을 구함 오늘 장을 열면 오늘 날짜 반환
by_day = stock.get_nearest_business_day_in_a_week(date=str_yesterday)
print("btday=",bt_day)
print("byday=",by_day)
if bt_day != str_today: #오늘 날짜와 구한 날짜가 같지 않다는건 오늘 장을 열지 않는다는 것
    print("오늘은 장을 열지 않으므로 프로그램 종료")
    sys.exit(0)

kospilist = stock.get_market_ticker_list(date=bt_day, market="KOSPI")   #KOSPI 종목코드를 list로 반환
kosdaqlist = stock.get_market_ticker_list(date=bt_day, market="KOSDAQ") #KOSDAQ 종목코드를 list로 반환
etflist = stock.get_etf_ticker_list(date=bt_day)                        #ETF 종목코드를 list로 반환

kospi_stock_list_count = 0      #나중에 Dataframe에 count로 사용할 변수 초기화
kosdaq_stock_list_count = 0
etf_stock_list_count = 0

print("KOSPI 확인 - 종목수 : ",len(kospilist))
for kospi_ticker in kospilist:  #KOSPI 종목
#for i in range(100):   #for test
#    kospi_ticker = kospilist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kospi_ticker)    #KOSPI 종목코드 어제,오늘 관련정보 DataFrame

    yesterday_volume = df.iloc[0]['거래량']     #DataFrame에서 어제 거래량 변수로 입력
    today_volume = df.iloc[1]['거래량']         #DataFrame에서 오늘 거래량 변수로 입력
    today_price = df.iloc[1]['종가']            #DataFrame에서 오늘 종가 변수로 입력
    
    print("종목코드",kospi_ticker)
    print("종가",today_price) 
    print("어제 거래량",yesterday_volume)
    print("오늘 거래량", today_volume)
    if yesterday_volume == 0:                   #어제거래량이 없으면 거래량변화 -100
        volume_ratio = -100
    else:
        volume_ratio = (today_volume-yesterday_volume)/yesterday_volume     #거래량변화율 

    
    new_data = [kospi_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
    kospi_stock_list.loc[kospi_stock_list_count] = new_data     #관련 정보 DataFrame의 행에 추가
    kospi_stock_list_count = kospi_stock_list_count + 1
    time.sleep(1) 

print("KOSDAQ 확인 - 종목수 : ",len(kosdaqlist))
for kosdaq_ticker in kosdaqlist:
#for i in range(100):       #for test
    #kosdaq_ticker = kosdaqlist[i]  #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=kosdaq_ticker)
    
    yesterday_volume = df.iloc[0]['거래량']
    today_volume = df.iloc[1]['거래량']
    today_price = df.iloc[1]['종가']
    
    print("종목코드",kosdaq_ticker)
    print("종가",today_price) 
    print("어제 거래량",yesterday_volume)
    print("오늘 거래량", today_volume)
    if yesterday_volume == 0:
        volume_ratio = -100
    else:
        volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

    
    new_data = [kosdaq_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
    kosdaq_stock_list.loc[kosdaq_stock_list_count] = new_data
    kosdaq_stock_list_count = kosdaq_stock_list_count + 1
    time.sleep(1) 



print("ETF 확인 - 종목수 : ",len(etflist))
for etf_ticker in etflist:
#for i in range(100):   #for test
    #etf_ticker = etflist[i]    #for test
    df = stock.get_market_ohlcv_by_date(fromdate=by_day, todate=bt_day, ticker=etf_ticker)
    
    yesterday_volume = df.iloc[0]['거래량']
    today_volume = df.iloc[1]['거래량']
    today_price = df.iloc[1]['종가']
    
    print("종목코드",etf_ticker)
    print("종가",today_price) 
    print("어제 거래량",yesterday_volume)
    print("오늘 거래량", today_volume)
    if yesterday_volume == 0:
        volume_ratio = -100
    else:
        volume_ratio = (today_volume-yesterday_volume)/yesterday_volume

    
    new_data = [etf_ticker,today_price,yesterday_volume,today_volume,volume_ratio]
    etf_stock_list.loc[etf_stock_list_count] = new_data
    etf_stock_list_count = etf_stock_list_count + 1
    time.sleep(1) 

all_stock_list = pd.concat([kospi_stock_list,kosdaq_stock_list])    #KOSPI와 KOSDAQ은 합쳐서 하나의 DataFrame으로

print("KOSPI")
print(kospi_stock_list)
print("KOSDAQ")
print(kosdaq_stock_list)
print("KOSPI+KOSDAQ")
print(all_stock_list)
print("ETF")
print(etf_stock_list)


all_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #거래량 우선으로 정렬
sort_volume_list = all_stock_list.head(12)                                          #그중 12개만 추출해서 저장
print("all stock sort by volume")
print(sort_volume_list)
sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)  #12개를 거래량 변화율로 정렬
sort_ratio_list = sort_volume_list.head(6)                                          #그 중 6개만 추출해서 저장
print("all stock sort by volume")
print(sort_ratio_list)

etf_stock_list.sort_values(['today_volume'],axis=0,ascending=False,inplace=True)    #ETF도 같은 과정 
etf_sort_volume_list = etf_stock_list.head(28)
print("ETF stock sort by volume")
print(etf_sort_volume_list)
etf_sort_volume_list.sort_values(['volume_ratio'],axis=0,ascending=False,inplace=True)
etf_sort_ratio_list = etf_sort_volume_list.head(14)             
print("ETF stock sort by volume")
print(etf_sort_ratio_list)

total_stock_list = pd.concat([sort_ratio_list,etf_sort_ratio_list])     #최종 KOSPI,KOSDAQ에서 6개, ETF에서 14개 총 20개 를 하나의 DataFrame으로 합치고
print("Total stock sort by volume")
print(total_stock_list)

final_stock_list = list(total_stock_list['stock_code'])     #DataFrame에서 종목코드만 List로 뽑고
print("final Stock List")
print(final_stock_list)

for i in range(len(final_stock_list)):
    final_stock_list[i] = 'A'+ str(final_stock_list[i])     #List에 'A' 추가해서
print(final_stock_list)

f = open('codelist.txt','w')
f.write(','.join(final_stock_list))     #파일로 저장
f.close()

#symbol_list = open('codelist.txt','r').read().split(',')       #for verify
#print(symbol_list)                                             #for verify

지난 포스팅에서 무엇을 살것인가에서 ETF를, 그리고 ETF 종목의 조회를 어떻게 하는가 봤다

 

그리고 얼마에 살 것인가는 변동성 돌파 전략에서 K값의 결정에 따라 산다 정도로 설명했다.

 

일단 프로그램 전체를 가져와보자.

 

역시 기본적으로 책인 [파이썬 증권 데이터 분석] 에서 제공하는 github의 소스를 이용한다.

StockAnalysisInPython/ch08_03_EtfAlgoTrader.py at master · INVESTAR/StockAnalysisInPython · GitHub

 

GitHub - INVESTAR/StockAnalysisInPython

Contribute to INVESTAR/StockAnalysisInPython development by creating an account on GitHub.

github.com

다만 slack으로 메시지 보내는 방법은 수정되어야 해서 전에 slack 관련 포스팅과 같은 방식으로 수정하였다.

아래와 같이 post_message 함수 정의해서 사용했다.

def post_message(token, channel, text):
    response = requests.post("https://slack.com/api/chat.postMessage",
        headers={"Authorization": "Bearer "+token},
        data={"channel": channel,"text": text}
    )
    print(response)

내가 직접 짠 소스가 아니므로 여기에 모두 포스팅 하지는 못하겠고 이정도 수정은 필요하신 분이시라면 어렵지 않게 하실수 있을것이라 생각한다.

 

같은 과정으로 vscode 실행하고 새 파이썬 파일 만들어서 소스 복붙하고 위의 post_message 부분으로 수정하면 된다.

 

일단 나의 경우 AutoTrade.py라고 저장하였고. 이 AutoTrade를 실행하기전에 이전포스팅에서 설명했던 AutoConnect.py를 먼저 실행해서 CREON Plus와 연결을 한다. 그리고 이 AutoTrade.py를 실행하는 것이다.

 

우선 main 부분만 훑어 보자.

if __name__ == '__main__':
    try:
        symbol_list = ['A122630', 'A252670', 'A233740', 'A250780', 'A225130',
             'A280940', 'A261220', 'A217770', 'A295000', 'A176950'] #매수 대상 종목 리스트
        bought_list = []     # 매수 완료된 종목 리스트
        target_buy_count = 5 # 매수할 종목 수
        buy_percent = 0.19   #종목별 매수 비율 5 종목 * 19%씩 매수 = 95% 매수하고 5% 금액 남게 된다.
        printlog('check_creon_system() :', check_creon_system())  # 크레온 접속 점검
        stocks = get_stock_balance('ALL')      # 보유한 모든 종목 조회
        total_cash = int(get_current_cash())   # 100% 증거금 주문 가능 금액 조회
        buy_amount = total_cash * buy_percent  # 종목별 주문 금액 계산
        printlog('100% 증거금 주문 가능 금액 :', total_cash)
        printlog('종목별 주문 비율 :', buy_percent)
        printlog('종목별 주문 금액 :', buy_amount)
        printlog('시작 시간 :', datetime.now().strftime('%m/%d %H:%M:%S'))
        soldout = False

        while True:
            t_now = datetime.now() #현재시간
            t_9 = t_now.replace(hour=9, minute=0, second=0, microsecond=0)  # 9:00
            t_start = t_now.replace(hour=9, minute=5, second=0, microsecond=0) # 9:05 시작 시간
                                                                                      참고로 유동성 공급자 활동시간 9:05 ~ 15:20
            t_sell = t_now.replace(hour=15, minute=15, second=0, microsecond=0) # 15:15 매도 시간
            t_exit = t_now.replace(hour=15, minute=20, second=0,microsecond=0) # 15:20 종료 시간
            today = datetime.today().weekday() #금일 요일
            if today == 5 or today == 6:  # 토요일이나 일요일이면 자동 종료
                printlog('Today is', 'Saturday.' if today == 5 else 'Sunday.')
                sys.exit(0)
            if t_9 < t_now < t_start and soldout == False:
                                            #9:00~9:05 사이에 시작하기전 혹시나 남은 주식이 있으면 다 매도
                soldout = True
                sell_all()
            if t_start < t_now < t_sell :  # AM 09:05 ~ PM 03:15 : 매수
                for sym in symbol_list: # 매수대상 종목리스트에서
                    if len(bought_list) < target_buy_count: #매수 완료한 종목이 목표수보다 작으면
                        buy_etf(sym)    #매수
                        time.sleep(1)
                if t_now.minute == 30 and 0 <= t_now.second <= 5:   #30분마다 잔고 등의 정보를 알림
                    get_stock_balance('ALL')
                    time.sleep(5)
            if t_sell < t_now < t_exit:  # PM 03:15 ~ PM 03:20 : 일괄 매도
                if sell_all() == True:
                    dbgout('`sell_all() returned True -> self-destructed!`')
                    sys.exit(0)
            if t_exit < t_now:  # PM 03:20 ~ :프로그램 종료
                dbgout('`self-destructed!`')
                sys.exit(0)
            time.sleep(3)
    except Exception as ex:
        dbgout('`main -> exception! ' + str(ex) + '`')

일단 설명할 부분은 주석으로 달아놨고

여기서 매수할 종목 대상 리스트는 ETF든 KOSPI든 KOSDAQ이든 미리 알아서 집어넣어두면 된다.

그리고 얼마에 매수할것인지에 대한 결정은 buy_etf()함수에서 불러오는

아래의 get_target_price()에 함수에서 설정되는 K값 0.5로 결정된다.

def get_target_price(code):
    """매수 목표가를 반환한다."""
    try:
        time_now = datetime.now()
        str_today = time_now.strftime('%Y%m%d')
        ohlc = get_ohlc(code, 10)
        if str_today == str(ohlc.iloc[0].name):
            today_open = ohlc.iloc[0].open
            lastday = ohlc.iloc[1]
        else:
            lastday = ohlc.iloc[0]                                      
            today_open = lastday[3]
        lastday_high = lastday[1]
        lastday_low = lastday[2]
        target_price = today_open + (lastday_high - lastday_low) * 0.5
        return target_price
    except Exception as ex:
        dbgout("`get_target_price() -> exception! " + str(ex) + "`")
        return None

현재 K값을 0.5 상수로 두고 있는데 이를 변수로 두던 상수로 두던 값 역시 수정하면 된다.
다만 K값이 낮으면 매수가 쉽고 높으면 어렵다..... 당연하군 ^^;

실제로 이 프로그램으로 매수/매도를 해보질 않았다.
일단 함수단위 테스트를 먼저 해보자.

바로 위 get_target_price()에 KODEX 200(069500) 을 한번 테스트 해보자. 

일단 test2.py 라는 임의로 파이썬 파일을 만들고 AutoTrade.py에서 일부분만 테스트를 위해 좀 잘라서

다음과 같이 테스트프로그램을 작성해서 실행해본다.

import os, sys, ctypes
import win32com.client
import pandas as pd
from datetime import datetime
import requests
import time, calendar

# 크레온 플러스 공통 OBJECT
cpCodeMgr = win32com.client.Dispatch('CpUtil.CpStockCode')
cpStatus = win32com.client.Dispatch('CpUtil.CpCybos')
cpTradeUtil = win32com.client.Dispatch('CpTrade.CpTdUtil')
cpStock = win32com.client.Dispatch('DsCbo1.StockMst')
cpOhlc = win32com.client.Dispatch('CpSysDib.StockChart')
cpBalance = win32com.client.Dispatch('CpTrade.CpTd6033')
cpCash = win32com.client.Dispatch('CpTrade.CpTdNew5331A')
cpOrder = win32com.client.Dispatch('CpTrade.CpTd0311')  

def get_ohlc(code, qty):
    """인자로 받은 종목의 OHLC 가격 정보를 qty 개수만큼 반환한다."""
    cpOhlc.SetInputValue(0, code)           # 종목코드
    cpOhlc.SetInputValue(1, ord('2'))        # 1:기간, 2:개수
    cpOhlc.SetInputValue(4, qty)             # 요청개수
    cpOhlc.SetInputValue(5, [0, 2, 3, 4, 5]) # 0:날짜, 2~5:OHLC
    cpOhlc.SetInputValue(6, ord('D'))        # D:일단위
    cpOhlc.SetInputValue(9, ord('1'))        # 0:무수정주가, 1:수정주가
    cpOhlc.BlockRequest()
    count = cpOhlc.GetHeaderValue(3)   # 3:수신개수
    columns = ['open', 'high', 'low', 'close']
    index = []
    rows = []
    for i in range(count):
        index.append(cpOhlc.GetDataValue(0, i))
        rows.append([cpOhlc.GetDataValue(1, i), cpOhlc.GetDataValue(2, i),
            cpOhlc.GetDataValue(3, i), cpOhlc.GetDataValue(4, i)])
    df = pd.DataFrame(rows, columns=columns, index=index)
    return df

def get_target_price(code):
    """매수 목표가를 반환한다."""
    try:
        time_now = datetime.now()
        str_today = time_now.strftime('%Y%m%d')
        ohlc = get_ohlc(code, 10)
        print(ohlc)
        if str_today == str(ohlc.iloc[0].name):
            today_open = ohlc.iloc[0].open
            lastday = ohlc.iloc[1]
        else:
            lastday = ohlc.iloc[0]                                      
            today_open = lastday[3]
        lastday_high = lastday[1]
        lastday_low = lastday[2]
        target_price = today_open + (lastday_high - lastday_low) * 0.5
        return target_price
    except Exception as ex:
        print("`get_target_price() -> exception! " + str(ex) + "`")
        return None

target_price = get_target_price('A069500')
print("목표가 = " + str(target_price))

2022년 2월 24일 현재 실행결과 아래와 같이 나온다.

즉 KODEX200 의 열흘간 시작가, 최고가, 최저가, 종가 가 출력되고 이를 토대로

K값이 0.5일때 목표가는 \36642.5 원이라는 것이다.

그럼 이제 K값을 변화해서 살펴보자.

K = 0.3 일 때
K = 0.7 일 때

자 각각 K가 0.3, 0.7로 바꿔서 놓고 실행해보면 목표가가 0.3일 때 36561.5원, 0.7일 때 36723.5원 으로 바뀌는 것을 볼 수 있다.

K = 0.3 K = 0.5 K = 0.7
\36561.5 \36642.5 \36723.5

이 매수조건에 현재가가 5일 이동평균선과 10일 이동평균선 위에 있어야 한다는 조건이 추가되어 있는데

이 부분이 buy_etf() 함수에서 get_movingaverage() 함수를 불러 이동평균을 구하고 조건을 추가하는식이다.

...
        ma5_price = get_movingaverage(code, 5)   # 5일 이동평균가
        ma10_price = get_movingaverage(code, 10) # 10일 이동평균가
...
        if current_price > target_price and current_price > ma5_price and current_price > ma10_price:  
         


자 그렇다면 이제

1. 무엇을 살 것인가는 ETF 중에서 또는 관심가는 종목 중 골라서 종목코드를 매수대상 종목리스트 symbol_list에 넣어두면 되고

2. 얼마에 살 것인가는 위에 조건처럼 K값과 이동평균선 조건에 따라서 매수하고 장마감에 매도

이런 아주 기초적인 조건으로 매매는 시작할 수 있게 되겠다.

 

그러고보니 매수대상을 종목리스트에 넣어두는 것은 자동은 아니네 --a 

그리고 추가로 설명할 부분이 주문조건과 주문호가가 있는데 프로그램에서는 ETF를 기본으로 하고 있다보니

거래량이 다른 주식대비 많지 않아 비싼 가격을 지불하지 않도록 [최유리 FOK 매수 주문] 방법으로 매수하고

매도는 [최유리 IOC 매도] 방법으로 매도하도록 되어있다.


비록 아직은 매수대상 종목리스트는 수작업으로 하지만 프로그램의 실행은 윈도우가 알아서 실행하도록 해보자.

 

우선 PC가 켜지는 것은

 1) 켜두거나

 2) BIOS가 지원한다면 BIOS에서 해야하는데 각 회사마다 다르겠지만

   기본적으로 BIOS진입 - Advanced - ACPI Configuration - RTC Alarm Power On 에서 예약 부팅 을 해두면 된다.

 

그리고 PC가 켜지면 윈도우키 + S 를 누른뒤 "작업 스케줄러"로 검색/실행을 하면 아래와 같이 작업스케줄러가 실행이된다.

그리고 좌측 창의 [작업 스케줄러 라이브러리] 클릭하면 가운데 창이 아래 그림처럼 나오는데 그 창에서

우측 클릭 - 새 작업 만들기

그러면 나타나는 창에서

이름과 설명은 원하는 대로 작성하고 형광펜의 '가장 높은 수준의 권한으로 실행' 에 체크

그리고 트리거 탭으로 가서 '새로만들기' 누른뒤 나타나는 창에서 '매일' '오전 8:20' 그리고 아래에 '사용'에 체크

그럼 트리거가 하나 만들어진다.

그리고 동작탭으로 넘어가서 역시 '새로만들기'

설정의 프로그램/스크립트 에서는 찾아보기 버튼을 누른뒤 python.exe가 있는 폴더에 들어가서 선택해주고

인수추가에는 실행할 python 파일 이름 위 그림엔 AutoConnect.py 시작위치는 AutoConnect.py가 있는 폴더의 경로
그리고 확인을 누르면 된다.

 

그리고 같은 방법으로 8:30 정도에 AutoTrade.py도 등록해주면 윈도우즈의 작업스케줄러가 알아서 실행한다.

 


- 지금까지 대부분의 정보는 "파이썬 증권 데이터 분석" 이라는 책의 내용을 보고 정리한 내용이며 일부 현재 동작하지 않는 Slack의 requests 같은 부분은 내가 검색해서 수정하였음을 미리 밝힌다. 그래서 세세한 소스는 직접 책에서 제공하는 github로 링크하였다.

 

- 현재 나도 아직 이 방식으로 주식거래를 시작하지 않았다.  '주식투자자동화' 관련 포스팅은 여기서 끝나는게 아니고

일단 서둘러 해보고 싶은 분들을 위해 1부? 여튼 일단 시작할 수 있는 정도까지 서둘러 포스팅한다.

나는 여기서 종목을 골라서 리스트에 넣는 부분과 K값을 조금씩 조절하고 그에 따른 결과를 자동으로 기록하는 부분까지는 조금 더 프로그램하고 작은 금액이라도 실제 투자해볼 생각이다.

그 부분은 차근차근 여기다 포스팅하고 수익이 나던 손해가 나던 일정 기간 후 역시 결과도 포스팅 해 볼 예정이다.

 

일단은 여기까지!!

이전 포스팅을 보면 늘 실행하기전에 CREON Plus를 실행해야 한다는 말을 쓰곤 했는데

내가 항상 깜빡하고 CREON Plus도 실행하지 않고 실행해서 Error가 발생하곤 했기 때문이다.

추가로 CREON Plus 실행하고 비번 치고, 비번 또 치고 이러는것도 귀찮기도 하고 ㅎ

여튼 그래서 우선 할것은 CREON Plus 자동 실행 프로그램이다.

이 소스는 구매한 책인 [파이썬 증권 데이터 분석] 이 유용하게도 github에 소스도 제공해주는데 여기에 자동 실행 예제가 있다.

 

아래의 링크에 들어가보자.

StockAnalysisInPython/08_Volatility_Breakout at master · INVESTAR/StockAnalysisInPython · GitHub

 

GitHub - INVESTAR/StockAnalysisInPython

Contribute to INVESTAR/StockAnalysisInPython development by creating an account on GitHub.

github.com

위 링크의 8장 말고도 다른 장도 다양한 소스가 있으니 공부에 참고하면 좋을듯하다.

물론 책을 사서 보면서 해야겠지만 ㅎ 나도 책은 아직 보는 중

여기에 보면 ch08_01_AutoConnect.py 이라는 파이썬 파일이 있다.

-------------------------------------------------------------------------------------------------------
from pywinauto import application
import time
import os

os.system('taskkill /IM coStarter* /F /T')
os.system('taskkill /IM CpStart* /F /T')
os.system('taskkill /IM DibServer* /F /T')
os.system('wmic process where "name like \'%coStarter%\'" call terminate')
os.system('wmic process where "name like \'%CpStart%\'" call terminate')
os.system('wmic process where "name like \'%DibServer%\'" call terminate')
time.sleep(5)        

app = application.Application()
app.start('C:\CREON\STARTER\coStarter.exe /prj:cp /id:userid /pwd:pa$$word /pwdcert:certPa$$word /autostart')
time.sleep(60)

-------------------------------------------------------------------------------------------------------

14번째줄 (끝에서 두번째줄) userid 에 ID 넣고, pwd에 password 넣고 pwdcert에 인증서암호 넣고

그리고 Autoconnect.py 로 저장하고 실행하면 끝

소스의 설명은 딱히 할게 없다. 

11번째 줄까지는 혹시 CREON Plus가 실행하고 있으면 끝내고

5초 대기

CREON Plus 를 실행하고 60초 대기 

그리고 이 소스에서 
-------------------------------------------------------------------------------------------------------
from pywinauto import application
import time
import os

os.system('taskkill /IM coStarter* /F /T')
os.system('taskkill /IM CpStart* /F /T')
os.system('taskkill /IM DibServer* /F /T')
os.system('wmic process where "name like \'%coStarter%\'" call terminate')
os.system('wmic process where "name like \'%CpStart%\'" call terminate')
os.system('wmic process where "name like \'%DibServer%\'" call terminate')
time.sleep(5)    

-------------------------------------------------------------------------------------------------------

이 부분만 Disconnect.py로 저장하고 끝낼때 종종 쓰곤 한다. ㅋ

 

자 그럼 이제 주식투자 자동화 프로그램을 해보도록 하자.

 

책에서 설명하는 주식 자동프로그램의 기본전략은 변동성 돌파전략이다. 

그럼 변동성 돌파전략이란 무엇인가?

 

변동성 돌파전략(volatility breakout strategy)이란 선물 트레이더의 대가라고 하는 래리 윌리엄스라는 사람이 개발한 투자전략으로 가격이 전일 가격범위의 K% 이상이 될 때 매수하고 장마감시 매도해서 수익을 실현하는 전략이라고 

책에 설명되어 있다.

 

여기서 중요한건 그럼 무엇을 (어느종목을) 과 언제 (K% 이상이 될 때) 의 결정이 가장 중요하지 싶다.

이건 책을 다 봐야 알것 같은데 책을 아직 다 보지 않았... (다 보면 나오긴 할까?)

여튼 나같은 초보에게 가장 쉽게 이해되는 그림을 첨부해보고자 구글링 해봤지만

그래도 책에 나온 그림이 가장 쉽게 이해되는 그림이었다.

변동성 돌파 전략 (책 파이썬 증권 데이터 분석 371페이지 그림)

그렇다면 수많은 종목 중에서 저렇게 스윙하는 종목들을 매수하게 된다고 가정하고

내 자금을 그 종목 1개만 몰빵해서 사기는 위험하고 그런 종목들 중 몇종목을 살것인지도 결정하기도 해야하겠다.

그리고 하루에 한번은 매수/매도도 해야겠고

그럼 그 수수료도 만만치 않을것이다. 

그래서 수수료를 생각해보면 이전에 대신증권은 0.015% 또는 월정액 15000원 + 0.0088% 라고 했는데....

"세금" 이 있다!!

 

CREON 트레이딩 - 제휴은행 계좌개설 - 크레온 (creontrade.com)

 

크레온

대신증권 온라인 주식 거래 서비스. 비대면계좌개설, 수수료 혜택, 주식시세, 종목추천, 투자정보 제공

www.creontrade.com

 

위 링크를 보면 수수료가 나와있는데 "매매관련세금" 탭이 있는 것을 볼 수 있다. 여기를 보면

KOSPI는 거래세 0.08% + 농특세 0.15% = 0.23%

KOSDAQ은 거래세 0.23%

ETF는 0%


정리하면

  매수 매도 합계
KOSPI 0.015% 0.015% + 0.23% 0.26%
KOSDAQ 0.015% 0.015% + 0.23% 0.26%
ETF 0.015% 0.015% 0.03%

하루에 한번꼴로 매수/매도를 하는데 KOSPI 또는 KOSDAQ과 ETF는 약 10배 가량 차이가 난다!
즉 거래를 자주하는데는 ETF가 유리하다!!

물론 KOSPI나 KOSDAQ이 훨씬 수수료 이상의 수익을 내준다면 상관이 없겠다 ㅎ

일단은 ETF 위주로 진행해보는 걸로 계속 진행해보자

 

그 ETF 중에도 당연히 시가총액이 크고 거래량이 많은 종목 중에서 선택을 하는것이 좋겠다.
그래서 ETF 종목 정보를 구해보도록 하자.

 

1. pip install beautifulsoap4 설치

2. pip install pandas 설치

3. pip install selenium으로 selenium 설치

4. Chrome 브라우저 실행하고 주소창에 chrome://version 입력해서 버전 확인  (나의 경우 98.0.4758.102)

5. https://chromedriver.chromium.org/downloads

 에서 버전에 맞는 chromedriver를 다운받고 압축을 푼다음에 chromedriver.exe 파일을 c:\myPackage 폴더 만든후 이 폴더로 복사

6. c:\myPackage의 chromedriver.exe를 관리자권한으로 실행하도록 설정

7. 아래의 파이썬 증권데이터 분석 책에서 제공하는 github 에서 소스

 StockAnalysisInPython/ch08_02_DynamicPageScraping_NaverETF.py at master · INVESTAR/StockAnalysisInPython · GitHub

 

GitHub - INVESTAR/StockAnalysisInPython

Contribute to INVESTAR/StockAnalysisInPython development by creating an account on GitHub.

github.com

 

8. vscode 실행시켜서 새파일(파이썬파일) 만들기 후 복붙  (나의경우 ScrapingETF.py)

9. 저장 후 터미널에서 python ScrapingETF.py를 실행하였더니!

아.. 이건 또 무슨 에러냐... 구글 검색해본 결과 lxml 이 없는게 이유

그럼 터미널에서 pip install lxml 하면 설치하는게 보인다.

 

10. 그리고 다시 실행하면

위와같이 naver에서 518개의 ETF종목의 정보를 가져온것을 확인할수 있다. 순서는 시가총액 순이다.
pandas로 읽은 이정보를 잘 추려서 이 중에서 어떤 종목을 선택할 것인지 이것도 매우 중요한 요소일것이다.

 

오늘은 일단 여기까지!

 

이 주식자동화를 프로그램을 돌려놓고 수익이 알아서 막 나면 얼마나 좋을까?

하지만 수익은 커녕 손실만 계속 발생한다면 그것도 큰 문제다.

수익이 나던 손실이 나던 적어도 이 프로그램이 현재 뭘하고 있는지 내가 어디에 있던 나에게 알려는 줘야 한다. 

무슨 종목을 얼마에 체결하는지 같은 정보 등등

여튼 최악의 상황에서 원격데스크탑으로든 무슨 수를 써서든 주식용 컴퓨터에 접속을 해서 프로그램을 멈추든 하지 않겠는가.

 

 

이런 정보를 가장 많이들 사용하는 카카오톡으로 그때 그때 보내주면 좋겠는데 뭐 그건 아직 모르겠다.

카카오톡도 api가 있는걸로 아는데 그건 나중에 공부해보는걸로 하고

일단 이것 역시 시키는대로 ^^;;

 

Slack은 업무용 메신저로 엄청 많이 사용되는 것으로 알고 있다. 미국회사던가 여튼 이번에 코로나 사태에 '줌'과 함께 꽤나 좋은 실적을 낸 회사로 알고 있다.

잡설은 그만하고 슬랙에 접속해서 가입을 한다.

GOOLGE로 가입을 해도 되고, 로그인 버튼을 누르고 우측 상단 계정생성을 눌러 계정을 만들면 된다.

 

https://slack.com/

 

Slack은 미래의 업무가 이루어지는 곳입니다

Slack은 여러분의 팀과 소통할 새로운 방법입니다. 이메일보다 빠르고, 더 조직적이며, 훨씬 안전합니다.

slack.com

 

이메일을 입력하면 6자리 인증코드를 확인하는 과정이 나오고

입력했던 본인의 이메일 slack에서 보낸 6자리 인증코드를 입력해서 다음으로 넘어가면  workspace 생성 화면이 나온다.

여기서 workspace 이름을 적당히 지어둔다. 위에선 jslee-stock이라고 지어줬다. 다음을 눌러 다음단계로 넘어가면

채널이름을 설정하는데 위에선 stock이라고 지어줬다. 그리고 다음

여럿이서 같이하는 작업이 아니고 혼자 쓸것이므로 팀원추가가 필요없다 형광펜으로 칠한 이단계 건너뛰기를 하면 기본설정이 끝이난다.

PC에서는 위와같은 초기화면이 뜨고

핸드폰 IOS, Android 모두 Slack 앱이 있는데 다운로드하여 접속하면 아래와 같은 화면이 뜬다.

위의 가입-설정의 워크스페이스와 이름이 jslee-stock과 jslee 로 다른데 가입-설정 과정을 사진으로 남기려고

새로 가입하여 만든 워크스페이스인 jslee-stock과 기존에 쓰던 워크스페이스인 jslee와 이름이 다르게 되었다.

 

다음은 이렇게 만든 slack 워크스페이스에 알람을 보내준 슬랙알람봇을 만들어준기 위해 아래의 링크에 접속한다.

api.slack.com

 

Create an App을 눌러 app을 만든다.

App Name 을 적당히 적고 (위의 예에선 jslee-stock-bot)

App Name 아래의 workspace에서 본인의 워크스페이스를 선택한다.(jslee-stock)

 

그러면 위와같이 App이 만들어지고 기본 정보들이 표시된다.

이제 이 알리봇에 권한을 줘야하는데 

왼쪽 메뉴에서 형광펜으로 칠한  OAuth & Permissions 을 클릭 하고 우측 메인화면을 스크롤 다운하면

Scope / Bot Token Scopes 가 나오는데 여기서 Add an OAuth Scope를 누르면 다음과 같이 여러 권한이 나온다.

이 여러권한 중 우리는 알림봇이 우리의 채팅창에 메시지를 보내는 것이므로

형광펜으로 칠한 chat:write 권한을 선택한다.

그리고 스크롤 업해서 위로 올라가다 보면 위 그림처럼 OAuth Tokens for Your Workspace의 Install to Workspace가 나오는다. 클릭해주자.

그러면 위 그림과 같이 허용할꺼냐고 묻는데 허용!

자 여기서 중요한게 뭐냐면 앞으로 우리가 작성하는 파이썬 프로그램은 이 알림봇에게 메시지를 보낼때

이 알림봇을 구분하는 구분자 같은게 있는데 그게 아래 그림의 Bot User OAuth Token 이다.

이 부분이 나중에 소스에 사용됨을 기억하자.

즉 파이썬을 작성한 코드에서 메시지는 이 Token을 가진 알림봇에 메시지를 전달하고

이 알림봇은 내 채팅창에 메시지를 전달하는 것이다.

 

이를 위해 한가지 더 작업해둘 사항이 있다.

다시 slack 채팅창으로 가서

형광펜 부분을 누른다. 그러면 아래와 같은 창이 뜨는데

통합 탭에서 앱/앱추가 를 눌러 만들어둔 앱을 추가해준다.

 

그러면 아래와 같이 jslee-stock-bot님과 함께 참여했다고 뜬다.

 

자 그럼 이제 이 slack 채팅으로 메시지를 보내보도록 하자.

지난번에 작업했던 대로 vs code 를 실행하여 임의로 파이썬 파일을 만들고 테스트를 해보도록 하자.

일단 msgtest.py 로 작업한다.

 

그 전에 해야할게 있는데 slack으로 메시지를 보내기 위해 파이썬은 requests 라는 것을 사용한다.

그래서 request를 깔아야하는데 역시 pip install requests 로 설치하도록 한다.

역시 이미 설치되어 있어서 위와 같은 메시지가 나온다만 설치되어 있지 않을 경우 설치되는 과정이 표시될 것이다.

 

설치가 되었다면 아래의 소스와 같이 타이핑 해보자

 

import requests
import win32com.client

def post_message(token, channel, text):
    response = requests.post("https://slack.com/api/chat.postMessage",
        headers={"Authorization": "Bearer "+token},
        data={"channel": channel,"text": text}
    )
    print(response)
 
myToken = "여기는 본인이 사용하는 고유의 Bot User OAuth Token 값을 넣어야 함!!"

# 연결 여부 체크
objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
bConnect = objCpCybos.IsConnect
if (bConnect == 0):
    print("PLUS가 정상적으로 연결되지 않음. ")
    exit()
 
# 현재가 객체 구하기
objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
objStockMst.SetInputValue(0, 'A005930')   #종목 코드 - 삼성전자
objStockMst.BlockRequest()
 
# 현재가 통신 및 통신 에러 처리
rqStatus = objStockMst.GetDibStatus()
rqRet = objStockMst.GetDibMsg1()
print("통신상태", rqStatus, rqRet)
if rqStatus != 0:
    exit()
 
# 현재가 정보 조회

offer = objStockMst.GetHeaderValue(16)  #매도호가
post_message(myToken,"#stock","삼성전자 현재가:" + str(offer))

(위 소스는 CREON Plus 자료실의 주식현재가 조회 소스에 Slack 메시지 전송을 덧붙인 예제임)

 

위 코드를 작성할때  11행의 반드시 myToken 값은 위의 api.slack.com 에서 표시되는 본인의 Bot User OAuth Token 값을 넣어줘야만 한다.

 

그리고 이 소스를 실행하기전에 CREON Plus 를 반드시 실행하고 위 소스를 실행한다.

실행은 터미널에서 python msgtest.py

그러면 터미널의 결과에서도 아래와 같이 조회가 완료되었고 Response [200] -이게 잘 되었다는 것- 으로 표시되고

다음과 같이 브라우저의 slack 채팅창에서도 메시지가 표시되고

핸드폰에 (slack에 미리 로그인한) 알림이 뜨는 것을 확인할 수 있다.

앞으로 이 파이썬의 requests를 이용해서 여러 정보를 slack의 메시지로 보내고 내가 어디에 있던 핸드폰 또는 브라우저 등으로 확인 할 수 있겠다.

 

오늘은 여기까지!

사실 파이썬이야 command prompt 에서도 할수 있겠지만 불편하고

많이 쓰이는 파이참을 써도 되겠다만
책과 조코딩 유튜브에서 시키는대로 할란다.. ㅋ 이 부분은 정말 다르게 한다고 별 문제가 발생할것 같지는 않다.

여튼 아래의 링크에서 VS Code를 다운받아 설치한다.

Download Visual Studio Code - Mac, Linux, Windows

 

여기서 보면 user installer가 있고 system installer 가 있는데 두개의 차이점은

user 는 현재 설치하고 있는 계정만 사용가능

system은 모든 사용자 사용가능
개인 pc에다 설치하니까 system으로 설치하는게 속편할듯!

VS Code는 그냥 다운받고 설치
그리고
Creon의 파이썬 예제 테스트 먼저 한번 해보기위한 사전작업

본인이 원하는 폴더를 하나 만든다. (나는 유튜브에 나오는대로 c:\stockauto\ 그대로 만듬)

앞으로 이 폴더에 파이썬 소스들을 하나씩 만들 예정이다.

 

VS Code 실행한다.

메뉴바에서 파일/폴더열기 에서 위에서 만든 폴더를 선택한다.

 

위 사진은 임의로 temp 라는 폴더를 만들었을 뿐...

그리고 이 과정에서였는지 언제였는지 vs code에서 파이썬 확장 설치를 묻는데

설치 안해도 된다. 설치 하면서부터 뭔가 복잡하게 꼬인다.. 이건 내가 vs code를 잘 몰라서 그럴수 있음

 

그리고 파이썬을 실행하는 터미널을 표시하려면 역시 메뉴바에서 보기/터미널 을 누르면 터미널을 볼수 있다.

위 그림의 우측 상단을 보면 powershell로 실행된것을 볼 수 있는데 유튜브에서는 cmd로 하도록 한다.

그런데 해보면 powershell도 별 상관없었다 

어쨌든 cmd로 하려면 저 powershell이라고 쓰인 옆에 + 버튼을 누르면 Command Prompt를 볼수 있는데 이를 추가하면 cmd도 사용할수 있다.

이제 CREON Plus API를 실행할수 있는 파이썬 라이브러리를 설치해야하는데

명령 프롬프트에 다음과 같은 명령어를 실행한다.

pip install pywinauto

나는 이미 설치되어 있어서 위와 같이 뜨는데 여튼 별문제 없으면 설치하는 표시등이 나타난다.

그런데 보통은 여기서 그냥 넘어가지 않는다.

위 그림처럼 Fatal Error 가 발생하는데...

 python -m pip install pywinauto 

이렇게 실행하면 된다고 하는데 이에 앞서

기본적으로 vscode도 관리자 권한으로 실행되도록 되어야 함을 잊지 말자.

(파이썬 실행파일 관리자권한 실행하도록 했던것과 동일)

파이썬, vscode 모두 관리자권한 실행이면 문제없이 설치되는것이 정상이다.

 

pywinauto까지 정상적으로 설치되었다면 기본 예제를 실행해보자.

vscode의 좌측 탐색기? 에서 아래 그림의 표시부를 눌러 새파일을 추가하고 이름을 test.py 로 만든다.

물론 이름은 맘대로 만들고 확장자는 파이썬의 확장자인 .py로 해야한다.

그리고 크레온 플러스 API 사이트에서 예제를 복사해서 테스트 해보도록 한다.

아래의 링크에 들어가서 CREON Plus(API) / 자료실 

크레온플러스자료실 - 크레온 (creontrade.com)

그리고 언어에서 파이썬을 클릭, Page 3을 클릭하면 처음에 종목정보 구하는 예제가 나온다.

소스 복사해서 test.py에 붙여넣기

그리고 파일을 저장하고

터미널에서 python test.py 를 타이핑하여 실행해보도록 한다.

자 그럼 위와같이 잘 실행되는것을 볼 수 있다. 

 

혹시 이런 실수를 할지도 몰라 적어두자면 실행이 정상적으로 안된다면

이건 당연히 CREON Plus를 접속을 안했기 때문이다. 이 모든것은 CREON Plus를 접속을 해야 CREON Plus API 서비스를 사용할 수 있다. 접속여부는 아래그림처름 작업표시줄 아이콘으로 확인해보면 된다.

 

우선 당연히 주식거래이니 만큼 증권계좌가 필요하다
다행히 그동안 사용하던 계좌가 대신증권이었... 다고 해도 원래 내 거래계좌를 가지고 할순 없고 ㅋ
여튼 대신증권에서 제공하는 API가 가장 사용성이 좋은가보다.

책에서 아래와 같이 비교하고 있다 (현재 어떤지 내가 정확히 비교한게 아니므로 다를수 있음에 주의)

  키움증권 Open API+ 대신증권 CREON 플러스 API 이베스트증권 xingAPI
제공방식 OCX COM COM, DLL
파이썬지원 보통 좋음 보통
API 사용성 보통 좋음 좋음
API거래수수료 0.015%(HTS수준) 0.015%(HTS수준) 또는
월정액 15000원 + 0.0088%
0.015%(HTS수준)

여튼 원래 사용하던 대신증권에 계좌를 하나 추가하였다.

 

그리고 아래 페이지에 크레온 HTS 프로그램을 다운로드 한다.
다운로드 센터 - 크레온 (creontrade.com)

 

크레온

대신증권 온라인 주식 거래 서비스. 비대면계좌개설, 수수료 혜택, 주식시세, 종목추천, 투자정보 제공

www.creontrade.com

다운로드 후 설치 

그리고 바탕화면에 있는 CREON 아이콘을 실행하면 아래와 같은그림이 뜨는데 위쪽에 형광펜으로 칠해놓은것 같이 creon plus 탭 이것으로 앞으로 모든것을 동작 시킬 것이다. (별도로 CREON PLUS 아이콘도 생기는데 그걸로 해도 된다)

 

그리고 작업표시줄 CREON PLUS 아이콘에서 마우스 우측버튼을 누르면 "주문 오브젝트 사용동의" 이걸 눌러서 API 사용을 할수 있게 해줘야 한다.

 

그리고 "주문내역 확인 설정" 을 누르면 아래의 그림과 같은 창이 뜨는데 형광펜으로 칠한것과 같이 체크박스를 "해제" 해주어야 자동으로 주문할때 확인을 안해도 알아서 할수 있게 될 것이다.


일단 이걸로 계좌 관련된건 설치가 되었고.... 그러고 보니 먼저 나와야 할건 파이썬 설치였는데 ...
뭐 나중에 설치한다고 어찌 되는건 아니니 ㅋ

책과 유튜브에서는 파이썬 3.8 버전의 설치를 권장한다. 최신의 버전을 설치해서 실험해보고자 하였지만 괜히 시스템 꼬일까 싶어 그냥 시키는대로 따라하기로.. ㅎ

내가 설치한건 파이썬 3.8.6 32비트 버전 (32비트 버전으로 하란다)

아래 링크에서 바로 다운 받을수 있고
https://www.python.org/ftp/python/3.8.6/python-3.8.6.exe

아니면 Python Releases for Windows | Python.org 여기 가서 3.8.6 x86 다운받으면 된다.

 

설치과정에서 반드시 "Add Python 3.8 to PATH" 를 체크해주고 

"Customize Install" - 모두 체크



또 모두체크

 

그리고 설치 경로에서 본인이 원하는 설치경로 지정 (난 C:\python38-32 폴더 만들어서 설치)

하고 설치한다.



설치 후 시스템 - 고급 시스템 설정 - 환경변수 - 시스템변수 - path 에 위의 설치경로의 path 지정해준다.

아래 그림과 같이

 

확인 - 확인 - 확인

 

그리고 python 설치한 경로로 가서 관리자 권한으로 실행할수 있도록 하여야 한다.

 

python.exe 와 pythonw.exe 파일에 마우스 우측버튼 - 호환성 - 관리자 권한으로 실행 클릭 으로 항상 관리자 권한으로 실행할 수 있도록 한다.

 



일단 오늘은 여기까지

 

그러고보니 주식투자 - 투자라고 하니 뭔가 거창해보인다만 적은 금액임 - 를 한지

어느새 5년차에 접어든것 같다.

초기에는 이래저래 시행착오도 많았고 나름 공부도 많이 해보고 나름 나만의 기준을 만들어
그동안 연평균 약 10% 이상의 꾸준한 수익을 내고 있다는 것은 매우 만족스럽다.

내가 직접 투자를 하는 원칙은
나만의 우량종목에 많이 분산투자하고 겁나 오래 기다린다. 라는 매우 단순한 방법이다.
보통 2,3년씩 투자하는 방식이긴 하다.

뭐 그래서인지 프로그램이 자동매매하게 하는것에 더 관심을 가지게 되었는지도 모르겠다. 

나의 투자방식과 반대이니 ㅎ

여튼 이제부터 블로그에 작성할 모든것은 다음의 책 "파이썬 증권 데이터 분석"
과 유튜브 "조코딩" 다음의 링크를 기본으로 한다.

https://youtu.be/Y01D2J_7894
https://youtu.be/xqlG-aEEa3Q
https://youtu.be/D2nZnmECTo8

https://youtu.be/5bTxyBeOVkA?list=PLU9-uwewPMe0fB60VIMuKFV7gPDXmyOzp 

 

책 당연히 내돈내산! 아직 읽진 않음 ㅋ

 

자 이제 정보는 대충 알아뒀고

 

실행할 PC는 내가 출근하기 전부터 켜지기 시작해서 최소 3시에서 퇴근전까지는 켜져있어야 하니 저전력 PC가 필요하다.
이거 하는데 고성능 사양의 PC가 필요할까 싶어서 전에 가지고 있던

J1900 CPU에 RAM 4G의 타오나스 에 셋팅해보았다.

동작은 하는데 너무 느리다 ㅠㅜ
그래서 집에서 나름 저전력 홈시어터 용으로 사용하는 J5040 CPU에 RAM 8G에 셋팅해 보았는데 나름 만족스럽게 돌아갔다.

 

왼쪽 J1900 RAM4G 타오나스 (PASSMARK 1131, TDP 10W) , 오른쪽 J5040 RAM 8G 타오나스 케이스 (PASSMARK 3578, TDP 10W)

 

뉴에그에서 직구한 J5040보드는 케이스를 타오나스케이스를 사용하기에 두 PC의 생긴건 똑같다 ㅋㅋㅋ
여튼 J5040 PC를 사용하기로 결정하고 J1900 PC는 뭐에 쓸지는 다시 생각해보자 ㅎ


그리고 기본적인 알고리즘의 원칙은

1. 단순하게 작성한다.

2. 매수/매도는 최소화

 

1번의 단순하게 작성한다는게 코딩을 단순하게 쓴다는 의미보다는 매도/매수의 원칙을 최대한 단순하게 세운다 라는 것임 괜히 이것이 복잡해진다고 크게 달라질것 같진 않다.

다만 이 기준값 두어가지를 결정하는 것과 종목의 선정을 딥러닝이던 머신러닝이던 배워가며 진행해보려고 한다.

그럼 다음 포스팅은 셋팅!

+ Recent posts