diff --git a/hts/HTS.py b/hts/HTS.py index e77a9ae..b14a355 100644 --- a/hts/HTS.py +++ b/hts/HTS.py @@ -3,9 +3,29 @@ import time import os from datetime import datetime, timedelta import pandas as pd +from enum import Enum #import matplotlib.pyplot as plt #import plotly.graph_objects as go +# enum 주문 상태 세팅용 +class EorderBS(Enum): + buy = 1 # 매수 + sell= 2 # 매도 + none =3 + +class orderData: + def __init__(self): + self.dicEx = {EorderBS.buy: "매수", EorderBS.sell: "매도", EorderBS.none: "없음"} + self.orderNum = 0 + self.bs = EorderBS.none # 0 : buy 1: sell + self.code = "" + self.amount = 0 + self.price = 0 + + def debugPrint(self): + print(self.dicEx.get(self.bs), self.code, self.orderNum, self.amount, self.price) + + class HTS: objCpCybos = None @@ -140,7 +160,8 @@ class HTS: return # 주식 현금 매수주문 - def orderToBuy(self, stock_code, count, price): + def requestOrder(self, type, stock_code, count, price): + # type = 2: buy, type=1: sell # 주문 초기화 objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil") initCheck = objTrade.TradeInit(0) @@ -154,7 +175,7 @@ class HTS: # acc = "782446178" # accFlag[0] = "01" objStockOrder = win32com.client.Dispatch("CpTrade.CpTd0311") - objStockOrder.SetInputValue(0, "2") # 2: 매수 + objStockOrder.SetInputValue(0, type) # 1: 매도, 2: 매수 objStockOrder.SetInputValue(1, acc) # 계좌번호 objStockOrder.SetInputValue(2, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째 objStockOrder.SetInputValue(3, "A"+stock_code) # 종목코드 @@ -179,8 +200,83 @@ class HTS: return orderNum - # 주식 현금 매도주문 - def orderToSell(self, stock_code, count, price): + # 계좌 잔고 확인 + def requstJango(self): + jangoDic = {} + + objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil") + initCheck = objTrade.TradeInit(0) + if (initCheck != 0): + print("주문 초기화 실패") + exit() + + # 주식 매수 주문 + acc = objTrade.AccountNumber[0] # 계좌번호 + accFlag = objTrade.GoodsList(acc, 1) # 주식상품 구분 + + objRq = win32com.client.Dispatch("CpTrade.CpTd6033") + + objRq.SetInputValue(0, acc) # 계좌번호 + objRq.SetInputValue(1, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째 + objRq.SetInputValue(2, 50) # 요청 건수(최대 50) + dicflag1 = {ord(' '): '현금', + ord('Y'): '융자', + ord('D'): '대주', + ord('B'): '담보', + ord('M'): '매입담보', + ord('P'): '플러스론', + ord('I'): '자기융자', + } + while True: + objRq.BlockRequest() + # 통신 및 통신 에러 처리 + rqStatus = objRq.GetDibStatus() + rqRet = objRq.GetDibMsg1() + #print("통신상태", rqStatus, rqRet) + if rqStatus != 0: + return False + + cnt = objRq.GetHeaderValue(7) + #print(cnt) + + for i in range(cnt): + item = {} + code = objRq.GetDataValue(12, i) # 종목코드 + item['종목코드'] = code + item['종목명'] = objRq.GetDataValue(0, i) # 종목명 + item['현금신용'] = dicflag1[objRq.GetDataValue(1, i)] # 신용구분 + #print(code, '현금신용', item['현금신용']) + item['대출일'] = objRq.GetDataValue(2, i) # 대출일 + item['잔고수량'] = objRq.GetDataValue(7, i) # 체결잔고수량 + item['매도가능'] = objRq.GetDataValue(15, i) + item['장부가'] = objRq.GetDataValue(17, i) # 체결장부단가 + # item['평가금액'] = self.objRq.GetDataValue(9, i) # 평가금액(천원미만은 절사 됨) + # item['평가손익'] = self.objRq.GetDataValue(11, i) # 평가손익(천원미만은 절사 됨) + # 매입금액 = 장부가 * 잔고수량 + item['매입금액'] = item['장부가'] * item['잔고수량'] + item['현재가'] = 0 + item['대비'] = 0 + item['거래량'] = 0 + + # 잔고 추가 + # key = (code, item['현금신용'],item['대출일'] ) + key = code + jangoDic[key] = item + + if len(jangoDic) >= 200: # 최대 200 종목만, + break + + if len(jangoDic) >= 200: + break + + if (objRq.Continue == False): + break + return jangoList + + # 예약 주문 내역 조회 및 미체결 리스트 구하기 + def requestOrderList(self): + # type = 2: buy, type=1: sell + orderList = [] # 주문 초기화 objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil") initCheck = objTrade.TradeInit(0) @@ -188,61 +284,58 @@ class HTS: print("주문 초기화 실패") exit() - # 주식 매도 주문 - acc = objTrade.AccountNumber[0] # 계좌번호 - accFlag = objTrade.GoodsList(acc, 1) # 주식상품 구분 - # acc = "782446178" - # accFlag[0] = "01" - objStockOrder = win32com.client.Dispatch("CpTrade.CpTd0311") - objStockOrder.SetInputValue(0, "1") # 1: 매도 - objStockOrder.SetInputValue(1, acc) # 계좌번호 - objStockOrder.SetInputValue(2, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째 - objStockOrder.SetInputValue(3, "A"+stock_code) # 종목코드 - A003540 - 대신증권 종목 - objStockOrder.SetInputValue(4, count) # 매도수량 count 주 - objStockOrder.SetInputValue(5, price) # 주문단가 - price 원 - objStockOrder.SetInputValue(7, "0") # 주문 조건 구분 코드, 0: 기본 1: IOC 2:FOK - objStockOrder.SetInputValue(8, "01") # 주문호가 구분코드 - 01: 보통 - - # 매도 주문 요청 - objStockOrder.BlockRequest() - - rqStatus = objStockOrder.GetDibStatus() - rqRet = objStockOrder.GetDibMsg1() - print("통신상태", rqStatus, rqRet) - if rqStatus != 0: - exit() - - orderNum = objStockOrder.GetHeaderValue(0) - - return orderNum - - # 예약 취소 주문 - def cancelOrder(self, ordernum, code): - objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil") - initCheck = objTrade.TradeInit(0) - if (initCheck != 0): - print("주문 초기화 실패") - exit() - - # 주식 매도 주문 + # 주식 매수 주문 acc = objTrade.AccountNumber[0] # 계좌번호 accFlag = objTrade.GoodsList(acc, 1) # 주식상품 구분 - objCancel = win32com.client.Dispatch("CpTrade.CpTdNew9064") - objCancel.SetInputValue(0, ordernum) - objCancel.SetInputValue(1, acc) - objCancel.SetInputValue(2, accFlag[0]) - objCancel.SetInputValue(3, code) + objResult = win32com.client.Dispatch("CpTrade.CpTd9065") + objResult.SetInputValue(0, acc) # 계좌번호 + objResult.SetInputValue(1, accFlag[0]) # 상품구분 - 주식 상품 중 첫번째 + objResult.SetInputValue(2, 20) - # 예약 취소 주문 요청 - objCancel.BlockRequest() + while True: + objResult.BlockRequest() + if objResult.GetDibStatus() != 0: + print("통신상태", objResult.GetDibStatus(), objResult.GetDibMsg1()) + return False - if objCancel.GetDibStatus() != 0: - print("통신상태", objCancel.GetDibStatus(), objCancel.GetDibMsg1()) - return False + cnt = objResult.GetHeaderValue(4) + if cnt == 0: + break - print("예약주문 취소 ", ordernum, objCancel.GetDibMsg1()) - return True + for i in range(cnt): + i1 = objResult.GetDataValue(1, i) # 주문구분(매수 또는 매도) + i2 = objResult.GetDataValue(2, i) # 코드 + i3 = objResult.GetDataValue(3, i) # 주문 수량 + i4 = objResult.GetDataValue(4, i) # 주문호가구분 + i5 = objResult.GetDataValue(6, i) # 예약번호 + i6 = objResult.GetDataValue(12, i) # 처리구분내용 - 주문취소 또는 주문예정 + i7 = objResult.GetDataValue(9, i) # 주문단가 + i8 = objResult.GetDataValue(11, i) # 주문번호 + i9 = objResult.GetDataValue(12, i) # 처리구분코드 + i10 = objResult.GetDataValue(13, i) # 거부코드 + i11 = objResult.GetDataValue(14, i) # 거부내용 + print(i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11) + + # 미체결 + if (i6 == "주문예정"): + item = orderData() + item.orderNum = i5 + if (i1 == "매수"): + item.bs = EorderBS.buy + else: + item.bs = EorderBS.sell + item.code = i2 + item.amount = i3 + item.price = i7 + + orderList.append(item) + + # 연속 처리 체크 - 다음 데이터가 없으면 중지 + if objResult.Continue == False: + break + + return orderList # 주식 현재가 조회 def printStockData(self, stock_code, day): @@ -567,9 +660,11 @@ class HTS: logFp.flush() count = 3 - self.orderToBuy(stock_code, count, price) - time.sleep(60) - self.orderToSell(stock_code, count, price + 5) + # 매수 주문 + self.requestOrder("2", stock_code, count, price) + ## 매도 주문 (아래 잔고를 체킇서 매도를 호출하는 것으로 시도한다.) + ##time.sleep(60) + ##self.requestOrder("1", stock_code, count, price + 5) # 가져온 만큼 데이터를 누적해서 파일로 작성한다. self.write(given_day, result) @@ -580,6 +675,12 @@ class HTS: logFp.write("%s,%s,\n" % ("NONE", second)) logFp.flush() + # 만약 잔고가 있으면 장부가보다 5원 높게 매도한다. + jangoDic = self.requstJango() + if len(jangoDic) > 0: + for code in jangoDic: + self.requestOrder("1", stock_code, jangoDic[code]['잔고수량'], jangoDic[code]['장부가'] + 5) + time.sleep(1) logFp.close()