[주식자동매매 프로그램 특강 2편] 정해진 시간에 계좌에 있는 모든 종목 매도하기(코딩편)
본문 바로가기

주식 자동매매 강의/중급반(시황 및 차트 구현)

[주식자동매매 프로그램 특강 2편] 정해진 시간에 계좌에 있는 모든 종목 매도하기(코딩편)

반응형

 이전 강의에서 GUI를 만들었고 관련 시간 정보를 GUI에 입력 및 출력하는 법을 알아보았습니다. 이번 강의에서는 시간 관련 정보를 이용해 특정 시간이 되면 모든 종목을 하도하는 코딩을 해 보겠습니다.

 

 1. 이전강의 복습

 - QT Designer를 이용해 GUI를 만들었습니다.

 - GUI는 Time Edit를 이용해 만듭니다.

 - Time Edit에 값을 입력하기 위해서는 setDisplyFormat과 setTime 함수를 이용합니다.

 - Time Edit에 값을 불러오기 위해서는 time(). toString("HHmmss")

 

  링크 : 이전강의

 

2. 특정 시간에 모든 종목 매도하기 코딩

 우선 우리가 자동매매를 하는 스레드에 코딩을 실시해야 합니다.

 

반응형

 

자동매매를 하는 스레드
자동매매를 하는 스레드

 저 같은 경우는 Qthread_7.py에서 하기 때문에 시 GUI에 있는 시간 관련 정보를 이 스크립트 처음에 가져옵니다.

 

GUI에 있는 시간관련 정보 가져오기
GUI에 있는 시간관련 정보 가져오기

 위의 코드를 보시면 저번에 말씀드린 time(). toString() 함수를 이용해 부모 GUI의 Time Edit인 stop_time에서 관련 정보를 가져오고 a에 저장한 후 그 값을 정수(int)로 변환합니다. 그리고 최종 값을 self.stop_meme에 저장합니다.

 이렇게 self에 저장하게 되면 Qthread_7.py 스크립트 어디에 [서든 시간 관련 정보를 확인할 수 있습니다.

 

 중급반 12강에서 말씀드렸지만 한 번 더 비슷한 코딩을 해 보겠습니다. 정해진 시간에 원하는 코딩을 실행하기 위해서는 별도의 스레드를 통해 현재 시간을 확인해야 합니다. 현재시간을 확인하는 함수로는 self.printhelloWorld2()라고 하겠습니다. 

 

 

 

현재 시간 확인하는 함수
현재 시간 확인하는 함수

  위의 현재 시간 확인하는 함수로 인해 printhelloWorld2 함수를 호출하였죠? 호출한 함수를 이제 만들어 보겠습니다.

 

printhelloWorld2
printhelloWorld2

 위의 코드를 확인해 보시면 datetime.today(). strftime(% H% M% S)를 통해 현재 시간을 받아옵니다. 이때, 현재 시간은 서버의 시간이 아니라 본인의 컴퓨터 시간입니다. 따라서, 본인의 컴퓨터 시간이 이상할 경우 올바르지 못한 연산이 될 수 있으니 반드시 조심하시기 바랍니다. 그리고 받아온 현재 시간 값은 정수로 만들어 주기 위해 int를 취하게 됩니다. 그러면 date_today에 정수 값이 최종적으로 들어가게 됩니다.

 이때,  시간이 14:00:30이면 출력되는 값은 140030입니다.

 그다음 threading.Timer 함수를 이용해 600초마다 self.printhelloWorld2를 수행하는 스레드 함수 t를 만듭니다. 그리고 t.start()를 통해 이 함수가 계속 실행되도록 구성합니다. 이렇게 되면 printhelloWorld2는 600초마다 무조건 1번 실행하게 되어 있습니다. 이제 600초마다 한번씩 현재시간을 확인하는 스레드 함수도 구성하였으니 특정 시간이 되시면 모든 종목을 매도하셔야겠죠?

 

 

코딩
코딩

 

  위의 코딩을 보시면 항상 보시던 거죠? 이미 기초반 또는 중급반에서 매도/매수할 때 항상 사용했던 구조입니다. 단, 처음과 달라진 부분은 1번이겠네요.

 1번을 보시면 만약 지금 시간 date_today이 self.stop_meme 보다 크면 아래 코드가 실행되게 해 두었습니다. 600초마다 date_time은 업데이트되고 self.stop_meme 시간은 여러분들이 이미 정해 둔 것이기 때문에 원하는 시간 이상이 되면 아래 코드가 실행됩니다.

 코드가 실행되면, 현재 계좌잔고 또는 금일 매수한 종목이 들어있는 방의 모든 코드들을 가져와야겠죠. self.k.acc_portfolio.keys()를 하시면 self.k.acc_portfolio에 들어 있는 모든 종목의 코드들을 total_sCode에 저장하게 됩니다. 그리고 total_sCode의 길이가 1개 이상이면 또 아래 코드를 실행합니다.

 for sCode in total_sCode를 하시면 total_sCode에 들어있는 코드들이 하나씩 sCode로 들어가 sCode에 대응하는 종목을 전체 매도하게 됩니다.

 2번 코드 중 order_success20을 보시면 항상 설명드렸던 부분이죠. 관련 코드에 대응하는 주식의 매매 가능 수량만큼 매도 주문을 넣습니다. 

 그리고 데이터 베이스를 확인하게 되죠. 

 

 

 

 위의 코드 중 조심해야 할 부분인 키움에서는 1초에 5번 이상 주문을 못 넣게 되어 있습니다. 만약 본인의 매매 종목이 5개 이상이라면 조심하셔야 합니다. 따라서, 강제로 qwait함수 등을 이용하여 약간의 지연을 넣어 줄 필요도 있습니다.

 

QTest.qWait(10000)

 

관련 코드는 아래와 같이 한번 공유드리겠습니다. 혹시 어려운 부분이 있으면 언제든 질문 주시면 답글 달아 드리겠습니다. 감사합니다.

 

    def printhelloWorld2(self):
        print("특정 시간 후 계좌 전체 매도 합니다. 10분마다 확인")
        date_today = int(datetime.today().strftime("%H%M%S"))
        print(date_today)
        t = threading.Timer(600, self.printhelloWorld2)
        t.start()

        if date_today >= self.stop_meme:
            print("금일 매수한 종목 전체 매도")

            total_sCode = self.k.acc_portfolio.keys()               # self.k.acc_portfolio,   self.k.jango_dict.keys()

            if len(total_sCode) >= 1:  # 틱 데이터가 1개 이상인지 확인한다.

                for sCode in total_sCode:

                    jd = self.k.acc_portfolio[sCode]

                    order_success20 = self.k.kiwoom.dynamicCall(
                        "SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
                        ["전체 매도", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 2, sCode, jd['매매가능수량'],
                         0, self.realType.SENDTYPE['거래구분']['시장가'], ""])

                    wf2 = open("dist/medo_database.txt", "a",
                               encoding="utf8")  # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
                    wf2.write("%s\t%s\t%s\t%s\n" % ("시장가 전체 매도", self.k.portfolio_stock_dict[sCode]["종목명"], 0,
                                                    date_today))  # t는 tap을 의미한다.
                    wf2.close()

                    if order_success20 == 0:
                        print("계좌평가잔고 내역에 절대 손절")
                        # if asd['매매가능수량'] == 0:
                        #    del self.account_stock_dict[sCode]  # 지우기 전에 수량, 등등을 다 확인해야 한다.
                    else:
                        print("계좌평가잔고 내역에 절대 손절")
반응형

.link_tit