본문 바로가기
무모한 도전-주식 인공지능 만들기

pytrader로 일봉차트(캔들차트) 가지고 오기-3-

by 인터넷떠돌이 인터넷떠돌이 2018. 12. 11.
반응형

안녕하세요?


지난번 포스팅에서는 계속해서 오류 투성이로 인해서 제대로 작업이 진행이 되지 않았는데, 이제서야 제대로 작업이 성공했고, 그 관련된 내용을 올리고자 합니다.



결국 하는 수 없이, 이렇게 답답하게 코드가 풀리지 않으면 하는 수 없이 위 스크린샷처럼 print()함수를 이용해서 일단 위스크린샷처럼 하나하나 입력해서 어느 줄에서 에러가 발생한 것인지 알아 보고자 합니다.



그런데 결과가 심각하다면 심각하다고 할 수 있는 것이, 일단 나왔는 결과는 첫줄만 겨우 통과했을 뿐이지, 아래로는 다 에러라는 결과를 알 수 있었습니다.



그래서 먼저 해보는 것은 변수 이름을 바꾸어 주도록 하는 것 입니다. 하지만 이것 역시 그다지 큰 차이가 없는 것을 확인할 수 있었을 뿐 이었습니다.



그래서 한번 reset_index()안의 내용물을 위 스크린샷처럼 아무것도 없는 것으로 바꾸어 주도록 합니다. 이렇게 해 보았습니다만........




일단 여기서는 한 단계 더 나아간 것을 확인할 수 있었습니다만, 문제는 date를 기준으로 해서 다시 배열하는 명령이 먹통이 된 것을 확인할 수 있었습니다.



그래서 어디가 문제인가 하다가 일단 index가 없는 상태로 DataFrame을 가져 오도록 하고, 그 다음으로는 set_index()함수를 써서 date항목을 인덱스로 지정하라는 식으로 만들어 주었습니다.



이렇게 하는 것으로 어떻게 제대로 프로그램이 돌아가는 것을 확인할 수 있었습니다. 그래서 이번 일은 이렇게 끝을 낼 수 있었습니다.



그리고 set_index()로 date를 지정해 둔 효과 때문인지, 제대로 다른 잡 항목이 없는 가운데, 위 스크린샷처럼 제대로 된 자료구조가 데이터 베이스 파일에 저장이 된 것을 확인할 수 있었습니다. 이제 다음 작업으로는 할 때 마다 일일히 저장할 경로를 코드를 수정해서 해야 했는데, 그러지 말고, 이번에는 간단하게 지정할 수 없는지를 알아 보고자 합니다.

반응형

댓글4

  • 2020.05.18 18:24

    비밀댓글입니다
    답글

  • 안녕하세요?

    혹시 프로그램을 실행시키다가 에러가 발생한 것인가요? 그렇다면 에러 메세지를 보여주세요.
    답글

  • 심재군 2021.04.01 21:14

    # kiwoom.py
    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QAxContainer import *
    from PyQt5.QtCore import *
    import time
    import pandas as pd # data 저장용
    import sqlite3 # data 저장용

    TR_REQ_TIME_INTERVAL = 0.2 # 키움의 요청제한 옵션


    class Kiwoom(QAxWidget):
    # org 3줄
    def __init__(self):
    super().__init__() #com obj를 생성하는 작업
    # 키움 login
    self._create_kiwoom_instance()
    self._set_signal_slots()

    #org 1줄 키움 api login 사용 명령
    def _create_kiwoom_instance(self):
    self.setControl("KHOPENAPI.KHOpenAPICtrl.1")
    #self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
    #self.kiwoom.dynamicCall("CommConnect()")
    # org -1줄 pytr-06 일부 추가 키움OpenApi + Event 연결이 되면 다음
    def _set_signal_slots(self): #연결이 되면
    self.OnEventConnect.connect(self._event_connect) # org
    #self.OnReceiveTrData.connect(self._receive_tr_data)
    #self.OnReceiveChejanData.connect(self._receive_chejan_data) #pytr-06추가

    #self.setWindowTitle("PyStock") # test용 화면
    #self.setGeometry(300, 300, 300, 150) # test용 화면

    #label = QLineEdit(self) # test용 화면
    #label = move(20, 20) # test용 화면

    #self.code_edit = QlineEdit(self) # test용 화면
    #self.code_edit.move(80, 20) # test용 화면
    #self.code_edit.setText("039490") # test용 화면

    #org-3줄 이벤트를 일일이 설정해주어야 함.
    def comm_connect(self):
    self.dynamicCall("CommConnect()")
    self.login_event_loop = QEventLoop()
    self.login_event_loop.exec_()

    #org-6줄 연결이 성공되면 출력 메시지
    def _event_connect(self, err_code): # 에러코드가 연결에 성공이면 0을 반환하고 루프를 탈출하라
    if err_code == 0:
    print("connected")
    else:
    print("disconnected")

    self.login_event_loop.exit() #comm_connect메서드에서 설정한 로그인event_loop를 로그인했으므로 정지할 필요가 있다

    # org-3줄
    def get_code_list_by_market(self, market):
    code_list = self.dynamicCall("GetCodeListByMarket(QString)", market) #키움제공분
    code_list = code_list.split(';')
    return code_list[:-1]

    # 1421에서 추가
    def get_master_code_name(self, code): #아래의 code는 입력되는 값에 유의 if__main__에서 code값이 입력
    code_name = self.dynamicCall("GetMasterCodeName(QString)", code) # code는 입력
    return code_name

    #pytr-06 이전
    def get_connect_state(self):
    ret = self.dynamicCall("GetConnectState()")
    return ret

    #pytr-06에서 추가
    def get_login_info(self, tag): # pytr-06 open Api의 고유한 메소드를 사용하게 함
    ret = self.dynamicCall("GetLoginInfo(QString)", tag) # pytr-06
    return ret

    def set_input_value(self, id, value): # 요청할 형식
    self.dynamicCall("SetInputValue(QString, QString)", id, value)
    print(id)
    print(value)

    ''' # TR을 요청하면 데이터가 바로 반환되는 것이 아닙 # 키움증권이 이벤트를 줄 때까지 대기
    따라서 CommRqData를 호출한 후에 이벤트 루프를 만들어주는 코드가 반드시 '''

    def comm_rq_data(self, rqname, trcode, next, screen_no): # 서버로 보내는 것
    self.dynamicCall("CommRqData(QString, QString, int, QString)", rqname, trcode, next, screen_no)
    self.tr_event_loop = QEventLoop()
    self.tr_event_loop.exec_()

    ''' 키움증권 서버로부터 TR 처리에 대한 이벤트가 발생했을 때 실제로 데이터를 가져오려면 CommGetData 메서드를 사용해야 합니다.
    역시 OpenAPI+의 개발 가이드를 참조해서 다음과 같이 _comm_get_data 메서드를 Kiwoom 클래스에 구현합니다.
    OpenAPI+의 CommGetData 메서드의 반환값은 문자열 타입 로 양쪽에 공백이 있습니다.
    따라서 공백을 제거하기 위해 반환받은 문자열에 strip 메서드를 사용했습니다. '''
    def _comm_get_data(self, code, real_type, field_name, index, item_name):
    print("fit6")
    ret = self.dynamicCall("CommGetData(QString, QString, QString, int, QString)",\
    code, real_type, field_name, index, item_name)
    print("fit6")
    return ret.strip()

    ''' opt10081을 통해 일봉 데이터를 요청하는 경우 약 900개의 데이터(거래일 기준)가 반환됩니다.
    데이터를 받는 입장에서는 총 몇 개의 데이터가 왔는지 알고 있어야 for나 while과 같은 반복문을 통해 데이터를 읽을 수 있습니다.
    이러한 용도로 사용하는 메서드가 _get_repeat_cnt입니다. 역시 OpenAPI+의 개발 가이드를 참조해서 다음과 같이 Kiwoom 클래스에 구현 '''
    # pytr-06 이전
    def _get_repeat_cnt(self, trcode, rqname): # opt10081을 통해 일봉 데이터를 요청하는 경우 - data량 파악
    ret = self.dynamicCall("GetRepeatCnt(QString, QString)", trcode, rqname)
    return ret

    # pytr-06 추가(kiwm)
    def send_order(self, rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no):
    self.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
    [rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no])

    # pytr-06 추가(kiwm)
    def get_chejan_data(self, fid):
    ret = self.dynamicCall("GetChejanData(int)", fid)
    return ret

    # pytr-06 추가(kiwm) org-5 print()
    def _receive_chejan_data(self, gubun, Item_cnt, fid_list):
    print(gubun)
    print(self.get_chejan_data(9203))
    print(self.get_chejan_data(302))
    print(self.get_chejan_data(900))
    print(self.get_chejan_data(901))

    # 12에서 임시주석 처리
    ''' #pyt11에서 추가
    def get_server_gubun(self):
    ret = self.dynamicCall("KOA_Functions(QString, QString)", "GetServerGubun", "")
    return ret '''

    # org+ 11추가, data 수신후 OnReceiveTrData이벤트가 발생한후 data가 남은 data가 존재함을 의미
    def _receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
    print("fit7")
    print(rqname)
    if next == '2':
    self.remained_data = True
    else:
    self.remained_data = False

    if rqname == "opt10081_req": # 일봉 차트data 요청분이 맞는지 확인
    self._opt10081(rqname, trcode)
    elif rqname == "opw00001_req": # pytr-11
    self._opw00001(rqname, trcode) # pytr-11
    elif rqname == "opw00018_req": # pytr-11
    self._opw00018(rqname, trcode) # pytr-11

    try: # 싱행중 예외처리상황이면 그냥넘어갈것
    self.tr_event_loop.exit()
    except AttributeError:
    pass

    @staticmethod # pytr-11에서 데이터정리를 위한 메소드
    def change_format(data):
    print("bom1")
    strip_data = data.lstrip('-0')
    print("bom2")
    if strip_data == '' or strip_data == '.00':
    print("bom4")
    strip_data = '0'

    #try:
    format_data = format(int(float(strip_data)), ',d') #14 float() 추가
    print("bom5")
    #except:
    # format_data = format(int(float(strip_data)))

    if data.startswith('-'):
    print("bom6")
    format_data = '-' + format_data
    print("bom7")

    return format_data

    # pytr-11에서 org설명추가, 포멧을 변경하기위한 메소드
    @staticmethod
    def change_format2(data):
    strip_data = data.lstrip('-0')

    if strip_data == '':
    strip_data = '0'

    if strip_data.startswith('.'):
    strip_data = '0' + strip_data

    if data.startswith('-'):
    strip_data = '-' + strip_data

    return strip_data

    # pyt-11 org, 계좌의 예금된 돈을 tr 이 도착했을 때 _comm_get_DATA()를 이용 항목수신후 change_format()을 통해 정리작업함.
    def _opw00001(self, rqname, trcode):
    d2_deposit = self._comm_get_data(trcode, "", rqname, 0, "d+2추정예수금")
    self.d2_deposit = Kiwoom.change_format(d2_deposit)

    def _opt10081(self, rqname, trcode): # pandas와 sqlite가 사용
    data_cnt = self._get_repeat_cnt(trcode, rqname)

    ''' 데이터의 총 개수를 얻었다면 반복문을 통해 데이터를 하나씩 얻어오면 됩니다. 일봉 데이터는 거래일 단위로
    ‘종목코드’, ‘현재가’, ‘거래량’, ‘거래대금’, ‘일자’, ‘시가’, ‘고가’, ‘저가’, ‘수정주가구분’, ‘수정비율’, ‘대업종구분’, ‘소업종구분’,
    ‘종목정보’, ‘수정주가이벤트’, ‘전일종가’를 한 번에 제공합니다. 여기서는
    ‘일자’, ‘시가’, ‘고가’, ‘저가’, ‘현재가’, ‘거래량’만 필요 '''
    for i in range(data_cnt):
    date = self._comm_get_data(trcode, "", rqname, i, "일자")
    open = self._comm_get_data(trcode, "", rqname, i, "시가")
    high = self._comm_get_data(trcode, "", rqname, i, "고가")
    low = self._comm_get_data(trcode, "", rqname, i, "저가")
    close = self._comm_get_data(trcode, "", rqname, i, "현재가")
    volume = self._comm_get_data(trcode, "", rqname, i, "거래량")
    # print(date, open, high, low, close, volume)

    self.ohlcv['date'].append(date) # 가져온 데이터를 각각의 key와 매치되는 ohlcv형 딕셔너리로 만드는 작업
    self.ohlcv['open'].append(int(open))
    self.ohlcv['high'].append(int(high))
    self.ohlcv['low'].append(int(low))
    self.ohlcv['close'].append(int(close))
    self.ohlcv['volume'].append(int(volume))

    # pyt-11 opw00018 tr수신후 []딕셔너리를 만드는 작업임.
    def reset_opw00018_output(self):
    self.opw00018_output = {'single': [], 'multi': []}

    # pytr-11에서 대부분의 계좌정보를 보여줌 추가메서드(single, multy)
    def _opw00018(self, rqname, trcode):
    # ### 총괄적인 데이터를 받을 딕셔너리 구축 (single data)
    total_purchase_price = self._comm_get_data(trcode, "", rqname, 0, "총매입금액")
    print("test1")
    total_eval_price = self._comm_get_data(trcode, "", rqname, 0, "총평가금액")
    print("test2")
    total_eval_profit_loss_price = self._comm_get_data(trcode, "", rqname, 0, "총평가손익금액")
    print("test3")
    total_earning_rate = self._comm_get_data(trcode, "", rqname, 0, "총수익률(%)")
    print("test4")
    estimated_deposit = self._comm_get_data(trcode, "", rqname, 0, "추정예탁자산")
    print("test5")

    self.opw00018_output['single'].append(Kiwoom.change_format(total_purchase_price))
    self.opw00018_output['single'].append(Kiwoom.change_format(total_eval_price))
    self.opw00018_output['single'].append(Kiwoom.change_format(total_eval_profit_loss_price))
    # self.opw00018_output['single'].append(Kiwoom.change_format(total_earning_rate))
    # self.opw00018_output['single'].append(Kiwoom.change_format(total_estimated_deposit))

    total_earning_rate = Kiwoom.change_format(total_earning_rate)
    print("test9")

    # 12에서 임시로 주석 처리
    ''' if self.get_server_gubun(): #임시로 주석
    total_earning_rate = float(total_earning_rate) / 100
    total_earning_rate = str(total_earning_rate) '''

    self.opw00018_output['single'].append(total_earning_rate)
    self.opw00018_output['single'].append(Kiwoom.change_format(estimated_deposit))

    # multi data 03=04 02보다 추가함수
    rows = self._get_repeat_cnt(trcode, rqname)
    for i in range(rows):
    name = self._comm_get_data(trcode, "", rqname, i, "종목명")
    quantity = self._comm_get_data(trcode, "", rqname, i, "보유수량")
    purchase_price = self._comm_get_data(trcode, "", rqname, i, "매입가")
    current_price = self._comm_get_data(trcode, "", rqname, i, "현재가")
    eval_profit_loss_price = self._comm_get_data(trcode, "", rqname, i, "평가손익")
    earning_rate = self._comm_get_data(trcode, "", rqname, i, "수익률(%)")

    quantity = Kiwoom.change_format(quantity)
    purchase_price = Kiwoom.change_format(purchase_price)
    current_price = Kiwoom.change_format(current_price)
    eval_profit_loss_price = Kiwoom.change_format(eval_profit_loss_price)
    earning_rate = Kiwoom.change_format2(earning_rate)

    self.opw00018_output['multi'].append([name, quantity, purchase_price, current_price, eval_profit_loss_price,
    earning_rate])

    if __name__ == "__main__": #여기서 본격적인 prg를 시작함
    app = QApplication(sys.argv) #org1 인스턴스생성
    kiwoom = Kiwoom() # org2 class에서정의된 이름인 Kiwoom()으로 인스턴스(kiwoom)생성
    kiwoom.comm_connect() # org3 login메서드 실행
    code_list = kiwoom.get_code_list_by_market('10') # org4 10은 코스닥
    print(kiwoom.get_master_code_name("000660")) #1421에서 임시연습 get_master_code_name과 함께 변경 종목으로 가져올것을 추가
    #for code in code_list: #org5 1421애서 삭제변경
    # print(code, end=" ") #org6 입력되는 값을 지칭함. 1421에서 삭제변경

    #kiwoom.reset_opw00018_output()
    #account_number = kiwoom.get_login_info("ACCNO")
    #account_number = account_number.split(';')[0]

    #kiwoom.set_input_value("계좌번호", account_number) # 위로 2번째줄의 "ACCNO"가있는 변수를 지정 함
    #kiwoom.comm_rq_data("opw00018_req", "opw00018", 0, "2000")
    #print(kiwoom.opw00018_output['single'])
    #print(kiwoom.opw00018_output['multi'])


    # QtDesigner로 만든 UI와 해당 UI의 위젯에서 발생하는 이벤트를 컨트롤하는 클래스
    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5 import uic
    from PyQt5 import QtGui
    from PyQt5.QtWidgets import QFileDialog
    from kiwoom import *
    import kiwoom
    import time
    import codecs
    from datetime import datetime
    import pandas as pd
    import sqlite3
    import os
    import matplotlib


    form_class = uic.loadUiType("pytrader.ui")[0]

    class MyWindow(QMainWindow, form_class):
    def __init__(self):
    super().__init__() #pyt04
    self.setupUi(self) #pyt04

    self.trade_stocks_done = False #15

    self.K = Kiwoom() # pyt04 06에서 kiwoom.추가11에서 다시 지움, 키움py의 class전체를 가져옴
    self.K.comm_connect(self) #pyt04 rev06

    self.timer = QTimer(self) #pyt04 06 메인timer
    self.timer.start(1000) #py04 06
    self.timer.timeout.connect(self.timeout) #pyt04 06 self.변수.신호.connect(self.timeout메소드실행)

    self.timer2 = QTimer(self) # pytr-11추가
    self.timer2.start(1000 * 10) # pytr-11추가
    self.timer2.timeout.connect(self.timeout2) # pytr-11추가, self.변수.신호.connect(self.timeout2메소드실행)

    accouns_num = int(self.K.get_login_info("ACCOUNT_CNT")) # pytr-06 추가
    accounts = self.K.get_login_info("ACCNO") # pytr-06 추가

    accounts_list = accounts.split(';')[0:accouns_num] # pytr-06 추가
    self.accountComboBox.addItems(accounts_list) # pytr-06 추가
    #self.ComboBox.addItems(accounts_list) # pytr-06 추가

    self.lineEdit.textChanged.connect(self.code_changed) # pytr-06 추가
    self.pushButton.clicked.connect(self.send_order) # pytr-06 추가

    self.pushButton_2.clicked.connect(self.check_balance) # pytr-11에서 추가
    self.pushButton_3.clicked.connect(self.candle_data_acquire) #pytr-일봉01

    self.load_buy_sell_list() #15

    #15
    def trade_stocks(self):
    hoga_lookup = {'지정가': "00", '시장가': "03"}

    f = open("buy_list.txt", 'rt') # binary가 아니고 text-type
    buy_list = f.readlines()
    f.close()

    f = open("sell_list.txt", 'rt') # binary가 아니고 text-type
    sell_list = f.readlines()
    f.close()

    # 계좌정보를 QcomboBox위젯으로부터 얻어옴
    account = self.comboBox.currentText()

    # buy_list.txt로부터 하나씩 얻어진 후 문자열을 문리하여 주문에 필요한 정보를 준비함
    for row_data in buy_list:
    split_row_data = row_data.split(';')
    hoga = split_row_data[2] #호가
    code = split_row_data[1] #종목코드
    num = split_row_data[3] #수량
    price = split_row_data[4] #가격

    # 매수주문 실행
    if split_row_data[-1].rstrip() == '매수전':
    self.K.send_order("send_order_req", "0101", account, 1, code, num, price, hoga_lookup[hoga], "")
    time.sleep(0.3)

    # sell_list.txt에서도 동일하게 문자열 분리
    for row_data in sell_list:
    split_row_data = row_data.split(';')
    hoga = split_row_data[2] #호가
    code = split_row_data[1] #종목코드
    num = split_row_data[3] #수량
    price = split_row_data[4] #가격

    # 매도주문 실행
    if split_row_data[-1].rstrip() == '매도전':
    self.K.send_order("send_order_req", "0101", account, 2, code, num, price, hoga_lookup[hoga], "")
    time.sleep(0.3)

    # 주문완료후 buy_list를 매수 화일 처리
    for i, row_data in enumerate(buy_list):
    buy_list[i] = buy_list[i].replace("매수전", "주문완료")

    # 매수된 화일 file update
    f = open("buy_list.txt", 'wt')
    for row_data in buy_list:
    f.write(row_data)
    f.close()

    # 주문완료후 sell list 매도 화일 처리
    for i, row_data in enumerate(sell_list):
    sell_list[i] = sell_list[i].replace("매도전", "주문완료")

    # 매도된 화일 file update
    f = open("sell_list.txt", 'wt')
    for row_data in sell_list:
    f.write(row_data)
    f.close()

    # 15 화일을 로드시켜서 읽어 들임
    def load_buy_sell_list(self):
    f = open("buy_list.txt", 'rt')
    buy_list = f.readlines()
    f.close()

    f = open("sell_list.txt", 'rt')
    sell_list = f.readlines()
    f.close()

    # DATA의 크기를 확인하고
    row_count = len(buy_list) + len(sell_list) # DATA의 크기를 COUNT
    self.tableWidget_3.setRowCount(row_count) # qtable Widget객체의 setRowCount메서드로 설정,호출

    # buy list
    # 읽은 데이터를 QTableWidget객체에 추가하는 과정
    # 종목코드로부터 종목명을 구하려면 kiwoom클래스의 kiwoom.get_master_code_name메서드를 이용함
    for j in range(len(buy_list)):
    row_data = buy_list[j]
    split_row_data = row_data.split(';')
    split_row_data[1] = self.K.get_master_code_name(split_row_data[1].rsplit())

    for i in range(len(split_row_data)):
    item = QTableWidgetItem(split_row_data[i].rstrip())
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignCenter)
    self.tableWidget_3.setItem(j, i, item) # 크기조절용 값

    # sell list
    for j in range(len(sell_list)):
    row_data = sell_list[j]
    split_row_data = row_data.split(';')
    split_row_data[1] = self.K.get_master_code_name(split_row_data[1].rstrip())

    for i in range(len(split_row_data)):
    item = QTableWidgetItem(split_row_data[i].rstrip())
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignCenter)
    self.tableWidget_3.setItem(len(buy_list) + j, i, item) # 크기조절용 값

    self.tableWidget_3.resizeRowsToContents() # 크기조절

    # pytr-06에서 추가
    def code_changed(self):
    code = self.lineEdit.text() #06기본
    name = self.K.get_master_code_name(code) #06기본
    self.lineEdit_2.setText(name) #06기본

    # 자동 주문
    self.timer_stock = QTimer(self)
    self.timer_stock.start(1000*21)
    self.timer_stock.timeout.connect(self.timeout)

    # 잔고 및 보유종목 조회 타이머
    self.inquiryTimer = QTimer(self)
    self.inquiryTimer.start(1000*10)
    self.inquiryTimer.timeout.connect(self.timeout)

    self.setAccountComboBox()
    self.codeLineEdit.textChanged.connect(self.set_code_name)
    self.orderBtn.clicked.connect(self.send_order)
    self.inquiryBtn.clicked.connect(self.inquiry_balance)

    # 자동 주문
    # 자동 주문을 활성화 하려면 True로 설정
    self.is_automatic_order = True
    self.in_processing = False

    # 자동 선정 종목 리스트 테이블 설정
    self.set_automated_stocks()
    self.inquiry_balance()

    def send_order(self):
    """ 키움서버로 주문정보를 전송한다. """
    order_type_table = {'신규매수': 1, '신규매도': 2, '매수취소': 3, '매도취소': 4}
    hoga_type_table = {'지정가': "00", '시장가': "03"}

    account = self.accountComboBox.currentText()
    order_type = order_type_table[self.orderTypeComboBox.currentText()]
    code = self.codeLineEdit.text()
    hoga_type = hoga_type_table[self.hogaTypeComboBox.currentText()]
    qty = self.qtySpinBox.value()
    price = self.priceSpinBox.value()

    try:
    self.K.send_order("수동주문", "0101", account, order_type, code, qty, price, hoga_type, "")
    except (ParameterTypeError, KiwoomProcessingError) as e:
    self.show_dialog('Critical', e)

    #pyt05 + 15
    def timeout(self): # 어떤 타이머에 의해서 호출되었는지 확인
    market_start_time = QTime(9, 0, 0) # 03보다 추가
    current_time = QTime.currentTime() #pyt05

    # 03보다 아래 3줄 if문 추가
    if current_time > market_start_time and self.trade_stocks_done is False: #15
    self.trade_stocks()
    self.trade_stocks_done = True

    text_time = current_time.toString("hh:mm:ss") #pyt05
    time_msg = "현재시간: " + text_time #pyt05

    state = self.K.get_connect_state() #pyt05
    if state == 1: #pyt05
    state_msg = "서버 연결중" #pyt05
    else: #pyt05
    state_msg = "서버 미 연결중" #pyt05

    self.stbar = QStatusBar(self) # pytr08에서 stbar 문장추가, 09(self) 삽입
    self.setStatusBar(self.stbar) # 09에서 stbar 문장추가
    self.stbar.showMessage(state_msg + " : " + time_msg) #pyt05

    # pytr-11에서 일부 추가가
    def timeout2(self): # 어떤 타이머에 의해서 호출되었는지 확인
    if self.checkBox.IsChecked(): # pyt-11
    self.check_balance() # pyt-11

    #pyt11 Timeout2가 작동후에 check_balance가 작동함
    def check_balance(self):
    print("part1") # pyt-12
    self.K.reset_opw00018_output()
    print("part2") # pyt-12
    account_number = self.K.get_login_info("ACCNO")
    print("part3") # pyt-12
    account_number == account_number.split('11;')[0] # 13에서 ; 로 된것을 11;로 수정
    print("part4") # pyt-12

    self.K.set_input_value("계좌번호", account_number) #pytr-14 한글이 맞음
    #self.K.set_input_value("ACCNO", account_number) #pytr13 ACCNO영문화 안됨
    print("part5") # pyt-12
    self.K.comm_rq_data("opw00018_req", "opw00018", 0, "2000")
    print("part6") # pyt-12

    while self.K.remained_data: #pyt11
    time.sleep(0.2)
    self.K.set_input_value("계좌번호", account_number) #pytr-11
    self.K.comm_rq_data("opw00018_req", "opw00018", 2, "2000")

    # opw00001 pyt11
    self.K.set_input_value("계좌번호", account_number) #pytr-11
    self.K.comm_rq_data("opw00001_req", "opw00001", 0, "2000")

    # balance pyt11
    item = QTableWidgetItem(self.K.d2_deposit)
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.tableWidget.setItem(0, 0, item)

    for i in range(1, 6): #pyt11
    item = QTableWidgetItem(self.K.opw00018_output['single'][i - 1])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.tableWidget.setItem(0, i, item)

    self.tableWidget.resizeRowsToContents() #pyt11

    # Item list pyt11
    item_count = len(self.K.opw00018_output['multi'])
    self.tableWidget_2.setRowCount(item_count)

    for j in range(item_count): #pyt11
    row = self.K.opw00018_output['multi'][j]
    for i in range(len(row)):
    item = QTableWidgetItem(row[i])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.tableWidget_2.setItem(j, i, item)

    self.tableWidget_2.resizeRowsToContents() #pyt11

    def set_code_name(self):
    """ 종목코드에 해당하는 한글명을 codeNameLineEdit에 설정한다. """
    code = self.codeLineEdit.text()

    if code in self.code_list:
    code_name = self.K.get_master_code_name(code)
    self.codeNameLineEdit.setText(code_name)

    def folderSelectSignal(self):
    folderPath = QFileDialog.getExistingDirectory()
    folderPath = os.path.realpath()
    self.folderPath2 = folderPath
    return self.folderPath2

    def candle_date_acquire(self): # 캔들가져오기-1392 의 227+49
    self.K.ohlcv = {'date': [], 'open': [], 'high':[], 'low':[], 'close':[], 'volume':[]}
    # opt10081요청
    if self.folderPath2:
    folderPath3 = self.folderPath2
    folderPath3 = str(folderPath3)
    else:
    QMessageBox.about(self, "Error", "database폴더 경로를 지정하세요")
    return

    #if self.lineEdit.text():
    if self.lineEdit_2.text():
    stockCode = self.lineEdit.text()
    else:
    QMessageBox.about(self, "Error", "종목코드를 입력하세요")
    return

    stockCode = self.lineEdit.text()
    self.K.set_input_value("종목코드", stockCode)
    daynow = datetime.now()
    daynow1 = daynow.yeqr
    daynow2 = daynow.month
    if daynow2 < 10:
    daynow2 = "0%s" % daynow2
    daynow3 = daynow.day
    if daynow3 < 10:
    daynow3 = "0%s" % daynow3
    daynow4 = "%s%s%s" % (daynow1, daynow2, daynow3)
    self.K.set_input_value("기준일자", "20181201")
    self.K.set_input_value("수정주가구분", 1)
    self.K.comm_rq_data("opt10081_req", "opt10081", 0, "0101")

    while self.K.remained_data == True:
    time.sleep(0.2)
    self.K.set_input_value("종목코드", stockCode)
    self.K.set_input_value("기준일자", daynow4)
    self.K.set_input_value("수정주가구분", 1)
    self.K.comm_rq_data("opt10081_req", "opt10081", 2, "0101")

    # 여기서는 df가 dataframe객체로 바꾸어 준다
    df = pd.DataFrame(self.K.ohlcv, columns=['open', 'high', 'low', 'close', 'volume']) #챠트3
    print("001")
    df2 = df.set_index('date') #챠트3
    print("002")
    #df = pd.DataFrame(self.K.ohlcv,
    # columns=['open', 'high', 'low', 'close', 'volume'], index=self.K.ohlcv['date'])
    df3 = df2.sort_values(by=['date'], axis=0, ascending=True) #챠트3
    print("003")
    #df4 = df3.set_index('date')
    #print("004")
    # con = sqlite3.connect("c:/Users/shim/stock.db")
    con = sqlite3.connect(folderPath3+"/$s.db" % daynow4)
    df4.to_sql('068400', con, if_exists='replace')

    def setAccountComboBox(self):
    """ accountComboBox에 계좌번호를 설정한다. """
    try:
    cnt = int(self.K.get_login_info("ACCOUNT_CNT"))
    accountList = self.K.get_login_info("계좌번호").split(';')
    self.accountComboBox.addItems(accountList[0:cnt])
    except (KiwoomConnectError, ParameterTypeError, ParameterValueError) as e:
    self.show_dialog('Critical', e)

    def inquiry_balance(self):
    """ 예수금상세현황과 계좌평가잔고내역을 요청후 테이블에 출력한다. """
    self.in_processing = True
    self.inquiryTimer.stop()
    self.timer_stock.stop()

    try:
    # 예수금상세현황요청
    self.K.set_input_value("계좌번호", self.accountComboBox.currentText())
    self.K.set_input_value("비밀번호", "1775")
    self.K.comm_rq_data("예수금상세현황요청", "opw00001", 0, "2000")

    # 계좌평가잔고내역요청 - opw00018 은 한번에 20개의 종목정보를 반환
    self.K.set_input_value("계좌번호", self.accountComboBox.currentText())
    self.K.set_input_value("비밀번호", "0000")
    self.K.comm_rq_data("계좌평가잔고내역요청", "opw00018", 0, "2000")
    while self.K.inquiry == '2':
    time.sleep(0.3)
    self.K.set_input_value("계좌번호", self.accountComboBox.currentText())
    self.K.set_input_value("비밀번호", "1775")
    self.K.comm_rq_data("계좌평가잔고내역요청", "opw00018", 2, "2")
    except (ParameterTypeError, ParameterValueError, KiwoomProcessingError) as e:
    self.show_dialog('Critical', e)

    # accountEvaluationTable 테이블에 정보 출력

    item = QTableWidgetItem(self.K.data_opw00001)
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.accountEvaluationTable.setItem(0, 0, item)

    for i in range(1, 6):
    item = QTableWidgetItem(self.K.data_opw00018['account_evaluation'][i-1])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.accountEvaluationTable.setItem(0, i, item)

    self.accountEvaluationTable.resizeRowsToContents()

    # Item list
    item_count = len(self.K.data_opw00018['stocks'])
    self.stocksTable.setRowCount(item_count)

    #with open('data/stocks_in_account.txt', 'wt', encoding='utf-8') as f_stock:
    with open('data/account.txt', 'wt', encoding='utf-8') as f_stock:
    f_stock.write('%d\n'%self.K.data_opw00001)
    for i in range(item_count):
    row = self.K.data_opw00018['stocks'][i]
    for j in range(len(row)-1):
    f_stock.write('%s,'%row[j].replace(',', ''))
    if j == len(row)-2:
    f_stock.write('%s,'%row[-1])
    item = QTableWidgetItem(row[j])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.stocksTable.setItem(i, j, item)
    f_stock.write('\n')

    self.stocksTable.resizeRowsToContents()

    # 데이터 초기화
    self.K.opw_data_reset()

    self.in_processing = False
    # inquiryTimer 재시작
    #self.inquiryTimer.start(1000*10)
    #self.timer_stock.start(1000*100)

    # 경고창
    def show_dialog(self, grade, error):
    grade_table = {'Information': 1, 'Warning': 2, 'Critical': 3, 'Question': 4}

    dialog = QMessageBox()
    dialog.setIcon(grade_table[grade])
    dialog.setText(error.msg)
    dialog.setWindowTitle(grade)
    dialog.setStandardButtons(QMessageBox.Ok)
    dialog.exec_()

    def set_automated_stocks(self):
    file_list = ["sell_list.txt", "buy_list.txt"]
    automated_stocks = []

    try:
    for file in file_list:
    # utf-8로 작성된 파일을
    # cp949 환경에서 읽기위해서 encoding 지정
    with open(file, 'rt', encoding='utf-8') as f:
    stocks_list = f.readlines()
    automated_stocks += stocks_list
    except Exception as e:
    print(e)
    e.msg = "set_automated_stocks() 에러"
    self.show_dialog('Critical', e)
    return

    # 테이블 행수 설정
    cnt = len(automated_stocks)
    self.automatedStocksTable.setRowCount(cnt)

    # 테이블에 출력
    for i in range(cnt):
    stocks = automated_stocks[i].split(';')
    for j in range(len(stocks)):
    if j == 1:
    name = self.K.get_master_code_name(stocks[j].rstrip())
    item = QTableWidgetItem(name)
    else:
    item = QTableWidgetItem(stocks[j].rstrip())
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignCenter)
    self.automatedStocksTable.setItem(i, j, item)
    self.automatedStocksTable.resizeRowsToContents()

    def automatic_order(self):
    file_list = ["sell_list.txt", "buy_list.txt"]
    hoga_type_table = {'지정가': "00", '시장가': "03"}
    account = self.accountComboBox.currentText()
    automated_stocks = []
    self.in_processing = True
    # 파일읽기
    try:
    for file in file_list:
    # utf-8로 작성된 파일을
    # cp949 환경에서 읽기위해서 encoding 지정
    with open(file, 'rt', encoding='utf-8') as f:
    stocks_list = f.readlines()
    automated_stocks += stocks_list
    except Exception as e:
    print(e)
    #e.msg = "automatic_order() 에러"
    #self.show_dialog('Critical', e)
    return

    cnt = len(automated_stocks)

    # 주문하기
    buy_result = []
    sell_result = []

    for i in range(cnt):
    time.sleep(0.3)
    stocks = automated_stocks[i].split(';')

    code = stocks[1]
    hoga = stocks[2]
    qty = stocks[3]
    price = stocks[4]

    try:
    if stocks[5].rstrip() == '매수전':
    self.K.send_order("자동매수주문", "0101", account, 1, code, int(qty), int(price), hoga_type_table[hoga], "")
    print("order_no: ", self.K.order_no)

    # 주문 접수시
    if self.K.order_no:
    buy_result += automated_stocks[i].replace("매수전", "매수완료")
    self.K.order_no = ""
    # 주문 미접수시
    else:
    buy_result += automated_stocks[i]

    # 참고: 해당 종목을 현재도 보유하고 있다고 가정함.
    elif stocks[5].rstrip() == '매도전':
    self.K.send_order("자동매도주문", "0101", account, 2, code, int(qty), 0, hoga_type_table[hoga], "")
    print("order_no: ", self.K.order_no)

    # 주문 접수시
    if self.K.order_no:
    sell_result += automated_stocks[i].replace("매도전", "매도완료")
    self.K.order_no = ""
    # 주문 미접수시
    else:
    sell_result += automated_stocks[i]
    elif stocks[5].rstrip() == '매수완료':
    buy_result += automated_stocks[i]
    elif stocks[5].rstrip() == '매도완료':
    sell_result += automated_stocks[i]

    except (ParameterTypeError, KiwoomProcessingError) as e:
    #self.show_dialog('Critical', e)
    print(e)

    # 잔고및 보유종목 디스플레이 갱신
    self.inquiry_balance()

    # 결과저장하기
    for file, result in zip(file_list, [sell_result, buy_result]):
    with open(file, 'wt', encoding='utf-8') as f:
    for data in result:
    f.write(data)
    self.in_processing = False

    if __name__ == "__main__":
    '''
    app = QApplication(sys.argv) #pytr05
    myWindow = QMainWindow() #pytr05
    myWindow.show() #pytr05-1414
    app.exec_() #pytr05-1414 '''

    app = QApplication(sys.argv) #pytr05-1414
    K = Kiwoom() #pytr05-1414
    #SH = MyWindow() # 08에서 변경
    # 08에서 주석처리
    # K.comm_connect() #pytr07-1412
    '''
    myWindow = form_class() #pytr05-1414
    myWindow2 = QMainWindow() #pytr05-1414
    myWindow.setupUi(myWindow2) #pytr05-1414
    myWindow2.show() #pytr05-1414 '''
    K.show() # 09에서 추가변경-임시 SH
    app.exec_() #pytr05-1414



    답글

  • 심재군 2021.04.01 21:14

    # kiwoom.py
    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QAxContainer import *
    from PyQt5.QtCore import *
    import time
    import pandas as pd # data 저장용
    import sqlite3 # data 저장용

    TR_REQ_TIME_INTERVAL = 0.2 # 키움의 요청제한 옵션


    class Kiwoom(QAxWidget):
    # org 3줄
    def __init__(self):
    super().__init__() #com obj를 생성하는 작업
    # 키움 login
    self._create_kiwoom_instance()
    self._set_signal_slots()

    #org 1줄 키움 api login 사용 명령
    def _create_kiwoom_instance(self):
    self.setControl("KHOPENAPI.KHOpenAPICtrl.1")
    #self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
    #self.kiwoom.dynamicCall("CommConnect()")
    # org -1줄 pytr-06 일부 추가 키움OpenApi + Event 연결이 되면 다음
    def _set_signal_slots(self): #연결이 되면
    self.OnEventConnect.connect(self._event_connect) # org
    #self.OnReceiveTrData.connect(self._receive_tr_data)
    #self.OnReceiveChejanData.connect(self._receive_chejan_data) #pytr-06추가

    #self.setWindowTitle("PyStock") # test용 화면
    #self.setGeometry(300, 300, 300, 150) # test용 화면

    #label = QLineEdit(self) # test용 화면
    #label = move(20, 20) # test용 화면

    #self.code_edit = QlineEdit(self) # test용 화면
    #self.code_edit.move(80, 20) # test용 화면
    #self.code_edit.setText("039490") # test용 화면

    #org-3줄 이벤트를 일일이 설정해주어야 함.
    def comm_connect(self):
    self.dynamicCall("CommConnect()")
    self.login_event_loop = QEventLoop()
    self.login_event_loop.exec_()

    #org-6줄 연결이 성공되면 출력 메시지
    def _event_connect(self, err_code): # 에러코드가 연결에 성공이면 0을 반환하고 루프를 탈출하라
    if err_code == 0:
    print("connected")
    else:
    print("disconnected")

    self.login_event_loop.exit() #comm_connect메서드에서 설정한 로그인event_loop를 로그인했으므로 정지할 필요가 있다

    # org-3줄
    def get_code_list_by_market(self, market):
    code_list = self.dynamicCall("GetCodeListByMarket(QString)", market) #키움제공분
    code_list = code_list.split(';')
    return code_list[:-1]

    # 1421에서 추가
    def get_master_code_name(self, code): #아래의 code는 입력되는 값에 유의 if__main__에서 code값이 입력
    code_name = self.dynamicCall("GetMasterCodeName(QString)", code) # code는 입력
    return code_name

    #pytr-06 이전
    def get_connect_state(self):
    ret = self.dynamicCall("GetConnectState()")
    return ret

    #pytr-06에서 추가
    def get_login_info(self, tag): # pytr-06 open Api의 고유한 메소드를 사용하게 함
    ret = self.dynamicCall("GetLoginInfo(QString)", tag) # pytr-06
    return ret

    def set_input_value(self, id, value): # 요청할 형식
    self.dynamicCall("SetInputValue(QString, QString)", id, value)
    print(id)
    print(value)

    ''' # TR을 요청하면 데이터가 바로 반환되는 것이 아닙 # 키움증권이 이벤트를 줄 때까지 대기
    따라서 CommRqData를 호출한 후에 이벤트 루프를 만들어주는 코드가 반드시 '''

    def comm_rq_data(self, rqname, trcode, next, screen_no): # 서버로 보내는 것
    self.dynamicCall("CommRqData(QString, QString, int, QString)", rqname, trcode, next, screen_no)
    self.tr_event_loop = QEventLoop()
    self.tr_event_loop.exec_()

    ''' 키움증권 서버로부터 TR 처리에 대한 이벤트가 발생했을 때 실제로 데이터를 가져오려면 CommGetData 메서드를 사용해야 합니다.
    역시 OpenAPI+의 개발 가이드를 참조해서 다음과 같이 _comm_get_data 메서드를 Kiwoom 클래스에 구현합니다.
    OpenAPI+의 CommGetData 메서드의 반환값은 문자열 타입 로 양쪽에 공백이 있습니다.
    따라서 공백을 제거하기 위해 반환받은 문자열에 strip 메서드를 사용했습니다. '''
    def _comm_get_data(self, code, real_type, field_name, index, item_name):
    print("fit6")
    ret = self.dynamicCall("CommGetData(QString, QString, QString, int, QString)",\
    code, real_type, field_name, index, item_name)
    print("fit6")
    return ret.strip()

    ''' opt10081을 통해 일봉 데이터를 요청하는 경우 약 900개의 데이터(거래일 기준)가 반환됩니다.
    데이터를 받는 입장에서는 총 몇 개의 데이터가 왔는지 알고 있어야 for나 while과 같은 반복문을 통해 데이터를 읽을 수 있습니다.
    이러한 용도로 사용하는 메서드가 _get_repeat_cnt입니다. 역시 OpenAPI+의 개발 가이드를 참조해서 다음과 같이 Kiwoom 클래스에 구현 '''
    # pytr-06 이전
    def _get_repeat_cnt(self, trcode, rqname): # opt10081을 통해 일봉 데이터를 요청하는 경우 - data량 파악
    ret = self.dynamicCall("GetRepeatCnt(QString, QString)", trcode, rqname)
    return ret

    # pytr-06 추가(kiwm)
    def send_order(self, rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no):
    self.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
    [rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no])

    # pytr-06 추가(kiwm)
    def get_chejan_data(self, fid):
    ret = self.dynamicCall("GetChejanData(int)", fid)
    return ret

    # pytr-06 추가(kiwm) org-5 print()
    def _receive_chejan_data(self, gubun, Item_cnt, fid_list):
    print(gubun)
    print(self.get_chejan_data(9203))
    print(self.get_chejan_data(302))
    print(self.get_chejan_data(900))
    print(self.get_chejan_data(901))

    # 12에서 임시주석 처리
    ''' #pyt11에서 추가
    def get_server_gubun(self):
    ret = self.dynamicCall("KOA_Functions(QString, QString)", "GetServerGubun", "")
    return ret '''

    # org+ 11추가, data 수신후 OnReceiveTrData이벤트가 발생한후 data가 남은 data가 존재함을 의미
    def _receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
    print("fit7")
    print(rqname)
    if next == '2':
    self.remained_data = True
    else:
    self.remained_data = False

    if rqname == "opt10081_req": # 일봉 차트data 요청분이 맞는지 확인
    self._opt10081(rqname, trcode)
    elif rqname == "opw00001_req": # pytr-11
    self._opw00001(rqname, trcode) # pytr-11
    elif rqname == "opw00018_req": # pytr-11
    self._opw00018(rqname, trcode) # pytr-11

    try: # 싱행중 예외처리상황이면 그냥넘어갈것
    self.tr_event_loop.exit()
    except AttributeError:
    pass

    @staticmethod # pytr-11에서 데이터정리를 위한 메소드
    def change_format(data):
    print("bom1")
    strip_data = data.lstrip('-0')
    print("bom2")
    if strip_data == '' or strip_data == '.00':
    print("bom4")
    strip_data = '0'

    #try:
    format_data = format(int(float(strip_data)), ',d') #14 float() 추가
    print("bom5")
    #except:
    # format_data = format(int(float(strip_data)))

    if data.startswith('-'):
    print("bom6")
    format_data = '-' + format_data
    print("bom7")

    return format_data

    # pytr-11에서 org설명추가, 포멧을 변경하기위한 메소드
    @staticmethod
    def change_format2(data):
    strip_data = data.lstrip('-0')

    if strip_data == '':
    strip_data = '0'

    if strip_data.startswith('.'):
    strip_data = '0' + strip_data

    if data.startswith('-'):
    strip_data = '-' + strip_data

    return strip_data

    # pyt-11 org, 계좌의 예금된 돈을 tr 이 도착했을 때 _comm_get_DATA()를 이용 항목수신후 change_format()을 통해 정리작업함.
    def _opw00001(self, rqname, trcode):
    d2_deposit = self._comm_get_data(trcode, "", rqname, 0, "d+2추정예수금")
    self.d2_deposit = Kiwoom.change_format(d2_deposit)

    def _opt10081(self, rqname, trcode): # pandas와 sqlite가 사용
    data_cnt = self._get_repeat_cnt(trcode, rqname)

    ''' 데이터의 총 개수를 얻었다면 반복문을 통해 데이터를 하나씩 얻어오면 됩니다. 일봉 데이터는 거래일 단위로
    ‘종목코드’, ‘현재가’, ‘거래량’, ‘거래대금’, ‘일자’, ‘시가’, ‘고가’, ‘저가’, ‘수정주가구분’, ‘수정비율’, ‘대업종구분’, ‘소업종구분’,
    ‘종목정보’, ‘수정주가이벤트’, ‘전일종가’를 한 번에 제공합니다. 여기서는
    ‘일자’, ‘시가’, ‘고가’, ‘저가’, ‘현재가’, ‘거래량’만 필요 '''
    for i in range(data_cnt):
    date = self._comm_get_data(trcode, "", rqname, i, "일자")
    open = self._comm_get_data(trcode, "", rqname, i, "시가")
    high = self._comm_get_data(trcode, "", rqname, i, "고가")
    low = self._comm_get_data(trcode, "", rqname, i, "저가")
    close = self._comm_get_data(trcode, "", rqname, i, "현재가")
    volume = self._comm_get_data(trcode, "", rqname, i, "거래량")
    # print(date, open, high, low, close, volume)

    self.ohlcv['date'].append(date) # 가져온 데이터를 각각의 key와 매치되는 ohlcv형 딕셔너리로 만드는 작업
    self.ohlcv['open'].append(int(open))
    self.ohlcv['high'].append(int(high))
    self.ohlcv['low'].append(int(low))
    self.ohlcv['close'].append(int(close))
    self.ohlcv['volume'].append(int(volume))

    # pyt-11 opw00018 tr수신후 []딕셔너리를 만드는 작업임.
    def reset_opw00018_output(self):
    self.opw00018_output = {'single': [], 'multi': []}

    # pytr-11에서 대부분의 계좌정보를 보여줌 추가메서드(single, multy)
    def _opw00018(self, rqname, trcode):
    # ### 총괄적인 데이터를 받을 딕셔너리 구축 (single data)
    total_purchase_price = self._comm_get_data(trcode, "", rqname, 0, "총매입금액")
    print("test1")
    total_eval_price = self._comm_get_data(trcode, "", rqname, 0, "총평가금액")
    print("test2")
    total_eval_profit_loss_price = self._comm_get_data(trcode, "", rqname, 0, "총평가손익금액")
    print("test3")
    total_earning_rate = self._comm_get_data(trcode, "", rqname, 0, "총수익률(%)")
    print("test4")
    estimated_deposit = self._comm_get_data(trcode, "", rqname, 0, "추정예탁자산")
    print("test5")

    self.opw00018_output['single'].append(Kiwoom.change_format(total_purchase_price))
    self.opw00018_output['single'].append(Kiwoom.change_format(total_eval_price))
    self.opw00018_output['single'].append(Kiwoom.change_format(total_eval_profit_loss_price))
    # self.opw00018_output['single'].append(Kiwoom.change_format(total_earning_rate))
    # self.opw00018_output['single'].append(Kiwoom.change_format(total_estimated_deposit))

    total_earning_rate = Kiwoom.change_format(total_earning_rate)
    print("test9")

    # 12에서 임시로 주석 처리
    ''' if self.get_server_gubun(): #임시로 주석
    total_earning_rate = float(total_earning_rate) / 100
    total_earning_rate = str(total_earning_rate) '''

    self.opw00018_output['single'].append(total_earning_rate)
    self.opw00018_output['single'].append(Kiwoom.change_format(estimated_deposit))

    # multi data 03=04 02보다 추가함수
    rows = self._get_repeat_cnt(trcode, rqname)
    for i in range(rows):
    name = self._comm_get_data(trcode, "", rqname, i, "종목명")
    quantity = self._comm_get_data(trcode, "", rqname, i, "보유수량")
    purchase_price = self._comm_get_data(trcode, "", rqname, i, "매입가")
    current_price = self._comm_get_data(trcode, "", rqname, i, "현재가")
    eval_profit_loss_price = self._comm_get_data(trcode, "", rqname, i, "평가손익")
    earning_rate = self._comm_get_data(trcode, "", rqname, i, "수익률(%)")

    quantity = Kiwoom.change_format(quantity)
    purchase_price = Kiwoom.change_format(purchase_price)
    current_price = Kiwoom.change_format(current_price)
    eval_profit_loss_price = Kiwoom.change_format(eval_profit_loss_price)
    earning_rate = Kiwoom.change_format2(earning_rate)

    self.opw00018_output['multi'].append([name, quantity, purchase_price, current_price, eval_profit_loss_price,
    earning_rate])

    if __name__ == "__main__": #여기서 본격적인 prg를 시작함
    app = QApplication(sys.argv) #org1 인스턴스생성
    kiwoom = Kiwoom() # org2 class에서정의된 이름인 Kiwoom()으로 인스턴스(kiwoom)생성
    kiwoom.comm_connect() # org3 login메서드 실행
    code_list = kiwoom.get_code_list_by_market('10') # org4 10은 코스닥
    print(kiwoom.get_master_code_name("000660")) #1421에서 임시연습 get_master_code_name과 함께 변경 종목으로 가져올것을 추가
    #for code in code_list: #org5 1421애서 삭제변경
    # print(code, end=" ") #org6 입력되는 값을 지칭함. 1421에서 삭제변경

    #kiwoom.reset_opw00018_output()
    #account_number = kiwoom.get_login_info("ACCNO")
    #account_number = account_number.split(';')[0]

    #kiwoom.set_input_value("계좌번호", account_number) # 위로 2번째줄의 "ACCNO"가있는 변수를 지정 함
    #kiwoom.comm_rq_data("opw00018_req", "opw00018", 0, "2000")
    #print(kiwoom.opw00018_output['single'])
    #print(kiwoom.opw00018_output['multi'])


    # QtDesigner로 만든 UI와 해당 UI의 위젯에서 발생하는 이벤트를 컨트롤하는 클래스
    import sys
    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5 import uic
    from PyQt5 import QtGui
    from PyQt5.QtWidgets import QFileDialog
    from kiwoom import *
    import kiwoom
    import time
    import codecs
    from datetime import datetime
    import pandas as pd
    import sqlite3
    import os
    import matplotlib


    form_class = uic.loadUiType("pytrader.ui")[0]

    class MyWindow(QMainWindow, form_class):
    def __init__(self):
    super().__init__() #pyt04
    self.setupUi(self) #pyt04

    self.trade_stocks_done = False #15

    self.K = Kiwoom() # pyt04 06에서 kiwoom.추가11에서 다시 지움, 키움py의 class전체를 가져옴
    self.K.comm_connect(self) #pyt04 rev06

    self.timer = QTimer(self) #pyt04 06 메인timer
    self.timer.start(1000) #py04 06
    self.timer.timeout.connect(self.timeout) #pyt04 06 self.변수.신호.connect(self.timeout메소드실행)

    self.timer2 = QTimer(self) # pytr-11추가
    self.timer2.start(1000 * 10) # pytr-11추가
    self.timer2.timeout.connect(self.timeout2) # pytr-11추가, self.변수.신호.connect(self.timeout2메소드실행)

    accouns_num = int(self.K.get_login_info("ACCOUNT_CNT")) # pytr-06 추가
    accounts = self.K.get_login_info("ACCNO") # pytr-06 추가

    accounts_list = accounts.split(';')[0:accouns_num] # pytr-06 추가
    self.accountComboBox.addItems(accounts_list) # pytr-06 추가
    #self.ComboBox.addItems(accounts_list) # pytr-06 추가

    self.lineEdit.textChanged.connect(self.code_changed) # pytr-06 추가
    self.pushButton.clicked.connect(self.send_order) # pytr-06 추가

    self.pushButton_2.clicked.connect(self.check_balance) # pytr-11에서 추가
    self.pushButton_3.clicked.connect(self.candle_data_acquire) #pytr-일봉01

    self.load_buy_sell_list() #15

    #15
    def trade_stocks(self):
    hoga_lookup = {'지정가': "00", '시장가': "03"}

    f = open("buy_list.txt", 'rt') # binary가 아니고 text-type
    buy_list = f.readlines()
    f.close()

    f = open("sell_list.txt", 'rt') # binary가 아니고 text-type
    sell_list = f.readlines()
    f.close()

    # 계좌정보를 QcomboBox위젯으로부터 얻어옴
    account = self.comboBox.currentText()

    # buy_list.txt로부터 하나씩 얻어진 후 문자열을 문리하여 주문에 필요한 정보를 준비함
    for row_data in buy_list:
    split_row_data = row_data.split(';')
    hoga = split_row_data[2] #호가
    code = split_row_data[1] #종목코드
    num = split_row_data[3] #수량
    price = split_row_data[4] #가격

    # 매수주문 실행
    if split_row_data[-1].rstrip() == '매수전':
    self.K.send_order("send_order_req", "0101", account, 1, code, num, price, hoga_lookup[hoga], "")
    time.sleep(0.3)

    # sell_list.txt에서도 동일하게 문자열 분리
    for row_data in sell_list:
    split_row_data = row_data.split(';')
    hoga = split_row_data[2] #호가
    code = split_row_data[1] #종목코드
    num = split_row_data[3] #수량
    price = split_row_data[4] #가격

    # 매도주문 실행
    if split_row_data[-1].rstrip() == '매도전':
    self.K.send_order("send_order_req", "0101", account, 2, code, num, price, hoga_lookup[hoga], "")
    time.sleep(0.3)

    # 주문완료후 buy_list를 매수 화일 처리
    for i, row_data in enumerate(buy_list):
    buy_list[i] = buy_list[i].replace("매수전", "주문완료")

    # 매수된 화일 file update
    f = open("buy_list.txt", 'wt')
    for row_data in buy_list:
    f.write(row_data)
    f.close()

    # 주문완료후 sell list 매도 화일 처리
    for i, row_data in enumerate(sell_list):
    sell_list[i] = sell_list[i].replace("매도전", "주문완료")

    # 매도된 화일 file update
    f = open("sell_list.txt", 'wt')
    for row_data in sell_list:
    f.write(row_data)
    f.close()

    # 15 화일을 로드시켜서 읽어 들임
    def load_buy_sell_list(self):
    f = open("buy_list.txt", 'rt')
    buy_list = f.readlines()
    f.close()

    f = open("sell_list.txt", 'rt')
    sell_list = f.readlines()
    f.close()

    # DATA의 크기를 확인하고
    row_count = len(buy_list) + len(sell_list) # DATA의 크기를 COUNT
    self.tableWidget_3.setRowCount(row_count) # qtable Widget객체의 setRowCount메서드로 설정,호출

    # buy list
    # 읽은 데이터를 QTableWidget객체에 추가하는 과정
    # 종목코드로부터 종목명을 구하려면 kiwoom클래스의 kiwoom.get_master_code_name메서드를 이용함
    for j in range(len(buy_list)):
    row_data = buy_list[j]
    split_row_data = row_data.split(';')
    split_row_data[1] = self.K.get_master_code_name(split_row_data[1].rsplit())

    for i in range(len(split_row_data)):
    item = QTableWidgetItem(split_row_data[i].rstrip())
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignCenter)
    self.tableWidget_3.setItem(j, i, item) # 크기조절용 값

    # sell list
    for j in range(len(sell_list)):
    row_data = sell_list[j]
    split_row_data = row_data.split(';')
    split_row_data[1] = self.K.get_master_code_name(split_row_data[1].rstrip())

    for i in range(len(split_row_data)):
    item = QTableWidgetItem(split_row_data[i].rstrip())
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignCenter)
    self.tableWidget_3.setItem(len(buy_list) + j, i, item) # 크기조절용 값

    self.tableWidget_3.resizeRowsToContents() # 크기조절

    # pytr-06에서 추가
    def code_changed(self):
    code = self.lineEdit.text() #06기본
    name = self.K.get_master_code_name(code) #06기본
    self.lineEdit_2.setText(name) #06기본

    # 자동 주문
    self.timer_stock = QTimer(self)
    self.timer_stock.start(1000*21)
    self.timer_stock.timeout.connect(self.timeout)

    # 잔고 및 보유종목 조회 타이머
    self.inquiryTimer = QTimer(self)
    self.inquiryTimer.start(1000*10)
    self.inquiryTimer.timeout.connect(self.timeout)

    self.setAccountComboBox()
    self.codeLineEdit.textChanged.connect(self.set_code_name)
    self.orderBtn.clicked.connect(self.send_order)
    self.inquiryBtn.clicked.connect(self.inquiry_balance)

    # 자동 주문
    # 자동 주문을 활성화 하려면 True로 설정
    self.is_automatic_order = True
    self.in_processing = False

    # 자동 선정 종목 리스트 테이블 설정
    self.set_automated_stocks()
    self.inquiry_balance()

    def send_order(self):
    """ 키움서버로 주문정보를 전송한다. """
    order_type_table = {'신규매수': 1, '신규매도': 2, '매수취소': 3, '매도취소': 4}
    hoga_type_table = {'지정가': "00", '시장가': "03"}

    account = self.accountComboBox.currentText()
    order_type = order_type_table[self.orderTypeComboBox.currentText()]
    code = self.codeLineEdit.text()
    hoga_type = hoga_type_table[self.hogaTypeComboBox.currentText()]
    qty = self.qtySpinBox.value()
    price = self.priceSpinBox.value()

    try:
    self.K.send_order("수동주문", "0101", account, order_type, code, qty, price, hoga_type, "")
    except (ParameterTypeError, KiwoomProcessingError) as e:
    self.show_dialog('Critical', e)

    #pyt05 + 15
    def timeout(self): # 어떤 타이머에 의해서 호출되었는지 확인
    market_start_time = QTime(9, 0, 0) # 03보다 추가
    current_time = QTime.currentTime() #pyt05

    # 03보다 아래 3줄 if문 추가
    if current_time > market_start_time and self.trade_stocks_done is False: #15
    self.trade_stocks()
    self.trade_stocks_done = True

    text_time = current_time.toString("hh:mm:ss") #pyt05
    time_msg = "현재시간: " + text_time #pyt05

    state = self.K.get_connect_state() #pyt05
    if state == 1: #pyt05
    state_msg = "서버 연결중" #pyt05
    else: #pyt05
    state_msg = "서버 미 연결중" #pyt05

    self.stbar = QStatusBar(self) # pytr08에서 stbar 문장추가, 09(self) 삽입
    self.setStatusBar(self.stbar) # 09에서 stbar 문장추가
    self.stbar.showMessage(state_msg + " : " + time_msg) #pyt05

    # pytr-11에서 일부 추가가
    def timeout2(self): # 어떤 타이머에 의해서 호출되었는지 확인
    if self.checkBox.IsChecked(): # pyt-11
    self.check_balance() # pyt-11

    #pyt11 Timeout2가 작동후에 check_balance가 작동함
    def check_balance(self):
    print("part1") # pyt-12
    self.K.reset_opw00018_output()
    print("part2") # pyt-12
    account_number = self.K.get_login_info("ACCNO")
    print("part3") # pyt-12
    account_number == account_number.split('11;')[0] # 13에서 ; 로 된것을 11;로 수정
    print("part4") # pyt-12

    self.K.set_input_value("계좌번호", account_number) #pytr-14 한글이 맞음
    #self.K.set_input_value("ACCNO", account_number) #pytr13 ACCNO영문화 안됨
    print("part5") # pyt-12
    self.K.comm_rq_data("opw00018_req", "opw00018", 0, "2000")
    print("part6") # pyt-12

    while self.K.remained_data: #pyt11
    time.sleep(0.2)
    self.K.set_input_value("계좌번호", account_number) #pytr-11
    self.K.comm_rq_data("opw00018_req", "opw00018", 2, "2000")

    # opw00001 pyt11
    self.K.set_input_value("계좌번호", account_number) #pytr-11
    self.K.comm_rq_data("opw00001_req", "opw00001", 0, "2000")

    # balance pyt11
    item = QTableWidgetItem(self.K.d2_deposit)
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.tableWidget.setItem(0, 0, item)

    for i in range(1, 6): #pyt11
    item = QTableWidgetItem(self.K.opw00018_output['single'][i - 1])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.tableWidget.setItem(0, i, item)

    self.tableWidget.resizeRowsToContents() #pyt11

    # Item list pyt11
    item_count = len(self.K.opw00018_output['multi'])
    self.tableWidget_2.setRowCount(item_count)

    for j in range(item_count): #pyt11
    row = self.K.opw00018_output['multi'][j]
    for i in range(len(row)):
    item = QTableWidgetItem(row[i])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.tableWidget_2.setItem(j, i, item)

    self.tableWidget_2.resizeRowsToContents() #pyt11

    def set_code_name(self):
    """ 종목코드에 해당하는 한글명을 codeNameLineEdit에 설정한다. """
    code = self.codeLineEdit.text()

    if code in self.code_list:
    code_name = self.K.get_master_code_name(code)
    self.codeNameLineEdit.setText(code_name)

    def folderSelectSignal(self):
    folderPath = QFileDialog.getExistingDirectory()
    folderPath = os.path.realpath()
    self.folderPath2 = folderPath
    return self.folderPath2

    def candle_date_acquire(self): # 캔들가져오기-1392 의 227+49
    self.K.ohlcv = {'date': [], 'open': [], 'high':[], 'low':[], 'close':[], 'volume':[]}
    # opt10081요청
    if self.folderPath2:
    folderPath3 = self.folderPath2
    folderPath3 = str(folderPath3)
    else:
    QMessageBox.about(self, "Error", "database폴더 경로를 지정하세요")
    return

    #if self.lineEdit.text():
    if self.lineEdit_2.text():
    stockCode = self.lineEdit.text()
    else:
    QMessageBox.about(self, "Error", "종목코드를 입력하세요")
    return

    stockCode = self.lineEdit.text()
    self.K.set_input_value("종목코드", stockCode)
    daynow = datetime.now()
    daynow1 = daynow.yeqr
    daynow2 = daynow.month
    if daynow2 < 10:
    daynow2 = "0%s" % daynow2
    daynow3 = daynow.day
    if daynow3 < 10:
    daynow3 = "0%s" % daynow3
    daynow4 = "%s%s%s" % (daynow1, daynow2, daynow3)
    self.K.set_input_value("기준일자", "20181201")
    self.K.set_input_value("수정주가구분", 1)
    self.K.comm_rq_data("opt10081_req", "opt10081", 0, "0101")

    while self.K.remained_data == True:
    time.sleep(0.2)
    self.K.set_input_value("종목코드", stockCode)
    self.K.set_input_value("기준일자", daynow4)
    self.K.set_input_value("수정주가구분", 1)
    self.K.comm_rq_data("opt10081_req", "opt10081", 2, "0101")

    # 여기서는 df가 dataframe객체로 바꾸어 준다
    df = pd.DataFrame(self.K.ohlcv, columns=['open', 'high', 'low', 'close', 'volume']) #챠트3
    print("001")
    df2 = df.set_index('date') #챠트3
    print("002")
    #df = pd.DataFrame(self.K.ohlcv,
    # columns=['open', 'high', 'low', 'close', 'volume'], index=self.K.ohlcv['date'])
    df3 = df2.sort_values(by=['date'], axis=0, ascending=True) #챠트3
    print("003")
    #df4 = df3.set_index('date')
    #print("004")
    # con = sqlite3.connect("c:/Users/shim/stock.db")
    con = sqlite3.connect(folderPath3+"/$s.db" % daynow4)
    df4.to_sql('068400', con, if_exists='replace')

    def setAccountComboBox(self):
    """ accountComboBox에 계좌번호를 설정한다. """
    try:
    cnt = int(self.K.get_login_info("ACCOUNT_CNT"))
    accountList = self.K.get_login_info("계좌번호").split(';')
    self.accountComboBox.addItems(accountList[0:cnt])
    except (KiwoomConnectError, ParameterTypeError, ParameterValueError) as e:
    self.show_dialog('Critical', e)

    def inquiry_balance(self):
    """ 예수금상세현황과 계좌평가잔고내역을 요청후 테이블에 출력한다. """
    self.in_processing = True
    self.inquiryTimer.stop()
    self.timer_stock.stop()

    try:
    # 예수금상세현황요청
    self.K.set_input_value("계좌번호", self.accountComboBox.currentText())
    self.K.set_input_value("비밀번호", "1775")
    self.K.comm_rq_data("예수금상세현황요청", "opw00001", 0, "2000")

    # 계좌평가잔고내역요청 - opw00018 은 한번에 20개의 종목정보를 반환
    self.K.set_input_value("계좌번호", self.accountComboBox.currentText())
    self.K.set_input_value("비밀번호", "0000")
    self.K.comm_rq_data("계좌평가잔고내역요청", "opw00018", 0, "2000")
    while self.K.inquiry == '2':
    time.sleep(0.3)
    self.K.set_input_value("계좌번호", self.accountComboBox.currentText())
    self.K.set_input_value("비밀번호", "1775")
    self.K.comm_rq_data("계좌평가잔고내역요청", "opw00018", 2, "2")
    except (ParameterTypeError, ParameterValueError, KiwoomProcessingError) as e:
    self.show_dialog('Critical', e)

    # accountEvaluationTable 테이블에 정보 출력

    item = QTableWidgetItem(self.K.data_opw00001)
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.accountEvaluationTable.setItem(0, 0, item)

    for i in range(1, 6):
    item = QTableWidgetItem(self.K.data_opw00018['account_evaluation'][i-1])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.accountEvaluationTable.setItem(0, i, item)

    self.accountEvaluationTable.resizeRowsToContents()

    # Item list
    item_count = len(self.K.data_opw00018['stocks'])
    self.stocksTable.setRowCount(item_count)

    #with open('data/stocks_in_account.txt', 'wt', encoding='utf-8') as f_stock:
    with open('data/account.txt', 'wt', encoding='utf-8') as f_stock:
    f_stock.write('%d\n'%self.K.data_opw00001)
    for i in range(item_count):
    row = self.K.data_opw00018['stocks'][i]
    for j in range(len(row)-1):
    f_stock.write('%s,'%row[j].replace(',', ''))
    if j == len(row)-2:
    f_stock.write('%s,'%row[-1])
    item = QTableWidgetItem(row[j])
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignRight)
    self.stocksTable.setItem(i, j, item)
    f_stock.write('\n')

    self.stocksTable.resizeRowsToContents()

    # 데이터 초기화
    self.K.opw_data_reset()

    self.in_processing = False
    # inquiryTimer 재시작
    #self.inquiryTimer.start(1000*10)
    #self.timer_stock.start(1000*100)

    # 경고창
    def show_dialog(self, grade, error):
    grade_table = {'Information': 1, 'Warning': 2, 'Critical': 3, 'Question': 4}

    dialog = QMessageBox()
    dialog.setIcon(grade_table[grade])
    dialog.setText(error.msg)
    dialog.setWindowTitle(grade)
    dialog.setStandardButtons(QMessageBox.Ok)
    dialog.exec_()

    def set_automated_stocks(self):
    file_list = ["sell_list.txt", "buy_list.txt"]
    automated_stocks = []

    try:
    for file in file_list:
    # utf-8로 작성된 파일을
    # cp949 환경에서 읽기위해서 encoding 지정
    with open(file, 'rt', encoding='utf-8') as f:
    stocks_list = f.readlines()
    automated_stocks += stocks_list
    except Exception as e:
    print(e)
    e.msg = "set_automated_stocks() 에러"
    self.show_dialog('Critical', e)
    return

    # 테이블 행수 설정
    cnt = len(automated_stocks)
    self.automatedStocksTable.setRowCount(cnt)

    # 테이블에 출력
    for i in range(cnt):
    stocks = automated_stocks[i].split(';')
    for j in range(len(stocks)):
    if j == 1:
    name = self.K.get_master_code_name(stocks[j].rstrip())
    item = QTableWidgetItem(name)
    else:
    item = QTableWidgetItem(stocks[j].rstrip())
    item.setTextAlignment(Qt.AlignVCenter | Qt.AlignCenter)
    self.automatedStocksTable.setItem(i, j, item)
    self.automatedStocksTable.resizeRowsToContents()

    def automatic_order(self):
    file_list = ["sell_list.txt", "buy_list.txt"]
    hoga_type_table = {'지정가': "00", '시장가': "03"}
    account = self.accountComboBox.currentText()
    automated_stocks = []
    self.in_processing = True
    # 파일읽기
    try:
    for file in file_list:
    # utf-8로 작성된 파일을
    # cp949 환경에서 읽기위해서 encoding 지정
    with open(file, 'rt', encoding='utf-8') as f:
    stocks_list = f.readlines()
    automated_stocks += stocks_list
    except Exception as e:
    print(e)
    #e.msg = "automatic_order() 에러"
    #self.show_dialog('Critical', e)
    return

    cnt = len(automated_stocks)

    # 주문하기
    buy_result = []
    sell_result = []

    for i in range(cnt):
    time.sleep(0.3)
    stocks = automated_stocks[i].split(';')

    code = stocks[1]
    hoga = stocks[2]
    qty = stocks[3]
    price = stocks[4]

    try:
    if stocks[5].rstrip() == '매수전':
    self.K.send_order("자동매수주문", "0101", account, 1, code, int(qty), int(price), hoga_type_table[hoga], "")
    print("order_no: ", self.K.order_no)

    # 주문 접수시
    if self.K.order_no:
    buy_result += automated_stocks[i].replace("매수전", "매수완료")
    self.K.order_no = ""
    # 주문 미접수시
    else:
    buy_result += automated_stocks[i]

    # 참고: 해당 종목을 현재도 보유하고 있다고 가정함.
    elif stocks[5].rstrip() == '매도전':
    self.K.send_order("자동매도주문", "0101", account, 2, code, int(qty), 0, hoga_type_table[hoga], "")
    print("order_no: ", self.K.order_no)

    # 주문 접수시
    if self.K.order_no:
    sell_result += automated_stocks[i].replace("매도전", "매도완료")
    self.K.order_no = ""
    # 주문 미접수시
    else:
    sell_result += automated_stocks[i]
    elif stocks[5].rstrip() == '매수완료':
    buy_result += automated_stocks[i]
    elif stocks[5].rstrip() == '매도완료':
    sell_result += automated_stocks[i]

    except (ParameterTypeError, KiwoomProcessingError) as e:
    #self.show_dialog('Critical', e)
    print(e)

    # 잔고및 보유종목 디스플레이 갱신
    self.inquiry_balance()

    # 결과저장하기
    for file, result in zip(file_list, [sell_result, buy_result]):
    with open(file, 'wt', encoding='utf-8') as f:
    for data in result:
    f.write(data)
    self.in_processing = False

    if __name__ == "__main__":
    '''
    app = QApplication(sys.argv) #pytr05
    myWindow = QMainWindow() #pytr05
    myWindow.show() #pytr05-1414
    app.exec_() #pytr05-1414 '''

    app = QApplication(sys.argv) #pytr05-1414
    K = Kiwoom() #pytr05-1414
    #SH = MyWindow() # 08에서 변경
    # 08에서 주석처리
    # K.comm_connect() #pytr07-1412
    '''
    myWindow = form_class() #pytr05-1414
    myWindow2 = QMainWindow() #pytr05-1414
    myWindow.setupUi(myWindow2) #pytr05-1414
    myWindow2.show() #pytr05-1414 '''
    K.show() # 09에서 추가변경-임시 SH
    app.exec_() #pytr05-1414



    답글