Skip to content

Instantly share code, notes, and snippets.

@Lay4U
Created June 5, 2020 02:59
Show Gist options
  • Save Lay4U/2e0702b024c232c911356e06f0760abe to your computer and use it in GitHub Desktop.
Save Lay4U/2e0702b024c232c911356e06f0760abe to your computer and use it in GitHub Desktop.
# -*-coding: utf-8 -
import sys, os, re, datetime, copy, json
import logging
import xlwings as xw
import resource_rc
import util, kw_util
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, QUrl, QEvent
from PyQt5.QtCore import QStateMachine, QState, QTimer, QFinalState
from PyQt5.QtWidgets import QApplication
from PyQt5.QAxContainer import QAxWidget
from mainwindow_ui import Ui_MainWindow
###################################################################################################
# μ‚¬μš©μž μ •μ˜ νŒŒλΌλ―Έν„°
###################################################################################################
AUTO_TRADING_OPERATION_TIME = [ [ [8, 50], [15, 19] ] ] # 8μ‹œ 50뢄에 λ™μž‘ν•΄μ„œ 15μ‹œ 19뢄에 μžλ™ 맀수/맀도 정지/ λ§€λ„ν˜Έκ°€ μ •λ³΄μ˜ 경우 λ™μ‹œν˜Έκ°€ μ‹œκ°„μ—λ„ μ˜¬λΌμ˜€λ―€λ‘œ 주의
JANG_CHOBAN_TIME = [ AUTO_TRADING_OPERATION_TIME[0][0][0] + 1, 59 ] # 9μ‹œ 1λΆ„λΆ€ν„°
TOTAL_BUY_AMOUNT = 100000 # 맀도 ν˜Έκ°€ 1,2,3 총 μˆ˜λŸ‰μ΄ TOTAL_BUY_AMOUNT 이상 μ•ˆλ˜λ©΄ λ§€μˆ˜κΈˆμ§€ (μŠ¬λ¦¬ν”Όμ§€ μ΅œμ†Œν™”)
MAESU_UNIT = 1000000 # μΆ”κ°€ 맀수 κΈ°λ³Έ λ‹¨μœ„ 총 자본의 1/10 μˆ˜μ€€ μœ μ§€ 증거금 40% 적용(1/20)
BUNHAL_MAESU_LIMIT = 4 # λΆ„ν•  맀수 횟수 μ œν•œ
MAX_STOCK_POSSESION_COUNT = 8 # μ œμ™Έ μ’…λͺ© 리슀트 λΆˆν¬ν•¨ν•œ μ΅œλŒ€ μ’…λͺ© 보유 수맀수
BUNHAL_MAESU_PROHIBIT_DAYS = 1 # 졜근 ? λ‚΄μ—μ„œλŠ” λΆ„ν•  맀수 κΈˆμ§€
STOP_LOSS_CALCULATE_DAY = 1 # 졜근 ? 일간 νŠΉμ • 가격 κΈ°μ€€μœΌλ‘œ μ†μ ˆ 계산
REQUEST_MINUTE_CANDLE_TYPE = 3 # μš΄μ˜μ€‘ μš”μ²­ν•  뢄봉 μ’…λ₯˜ -1 의 경우 뢄봉 μš”μ²­ μ•ˆν•¨
MAX_SAVE_CANDLE_COUNT = (STOP_LOSS_CALCULATE_DAY +1) * 140 # 3뢄봉 κΈ°μ€€ μ €μž₯ 뢄봉 갯수
MAESU_TOTAL_PRICE = [ MAESU_UNIT * 1, MAESU_UNIT * 1, MAESU_UNIT * 1, MAESU_UNIT * 1, MAESU_UNIT * 1]
# μΆ”κ°€ 맀수 μ§„ν–‰μ‹œ stoploss 및 stopplus 퍼센티지 λ³€κ²½
# μΆ”κ°€ 맀수 μ–΄λŠ λ‹¨κ³„μ—μ„œλ“ μ§€ μ†μ ˆκΈˆμ•‘μ€ 확정적이여야 함
BASIC_STOP_LOSS_PERCENT = -80
STOP_PLUS_PER_MAESU_COUNT = [ 150, 150, 150, 150, 150 ]
STOP_LOSS_PER_MAESU_COUNT = [ int(BASIC_STOP_LOSS_PERCENT), int(BASIC_STOP_LOSS_PERCENT/2), int(BASIC_STOP_LOSS_PERCENT/3), int(BASIC_STOP_LOSS_PERCENT/4), int(BASIC_STOP_LOSS_PERCENT/3) ]
EXCEPTION_LIST = ['035480'] # μž₯κΈ° 보유 μ’…λͺ© 번호 리슀트 ex) EXCEPTION_LIST = ['034220']
###################################################################################################
###################################################################################################
TEST_MODE = False # 주의 TEST_MODE λ₯Ό True 둜 ν•˜λ©΄ 1μ£Ό λ‹¨μœ„λ‘œ μ‚Ό
TRADING_INFO_GETTING_TIME = [15, 55] # νŠΈλ ˆμ΄λ”© 정보λ₯Ό μ €μž₯ν•˜κΈ° μ‹œμž‘ν•˜λŠ” μ‹œκ°„
SLIPPAGE = 1.0 # μˆ˜μ΅μ‹œ 보톡가 μ†μ ˆμ‹œ μ‹œμž₯κ°€ 수수료 포함 3ν˜Έκ°€κΉŒμ§€ κ³„μ‚°ν•΄μ„œ 맀수 ν•˜λ―€λ‘œ 1% 적용
TR_TIME_LIMIT_MS = 7600 # 킀움 μ¦κΆŒμ—μ„œ μ •μ˜ν•œ 연속 TR μ‹œ ν•„μš” λ”œλ ˆμ΄
INTERESTED_STOCKS_FILE_PATH = "log" + os.path.sep + "interested_stocks.json"
CHEGYEOL_INFO_FILE_PATH = "log" + os.path.sep + "chegyeol.json"
JANGO_INFO_FILE_PATH = "log" + os.path.sep + "jango.json"
CHEGYEOL_INFO_EXCEL_FILE_PATH = "log" + os.path.sep + "chegyeol.xlsx"
###################################################################################################
###################################################################################################
class CloseEventEater(QObject):
def eventFilter(self, obj, event):
if( event.type() == QEvent.Close):
test_make_jangoInfo()
return True
else:
return super(CloseEventEater, self).eventFilter(obj, event)
class KiwoomConditon(QObject):
sigInitOk = pyqtSignal()
sigConnected = pyqtSignal()
sigDisconnected = pyqtSignal()
sigTryConnect = pyqtSignal()
sigGetConditionCplt = pyqtSignal()
sigSelectCondition = pyqtSignal()
sigReselectCondition = pyqtSignal()
sigStateStop = pyqtSignal()
sigStockComplete = pyqtSignal()
sigConditionOccur = pyqtSignal()
sigRequestMinuteCandleInfo = pyqtSignal()
sigRequestEtcInfo = pyqtSignal()
sigGetBasicInfo = pyqtSignal()
sigDetermineBuy = pyqtSignal()
sigGetHogaInfo = pyqtSignal()
sigTrWaitComplete = pyqtSignal()
sigWaitTr = pyqtSignal()
sigNoWaitTr = pyqtSignal()
sigRequestRealHogaComplete = pyqtSignal()
sigError = pyqtSignal()
sigRequestJangoComplete = pyqtSignal()
sigCalculateStoplossComplete = pyqtSignal()
sigStartProcessBuy = pyqtSignal()
sigStopProcessBuy = pyqtSignal()
sigTerminating = pyqtSignal()
def __init__(self):
super().__init__()
self.ocx = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
self.fsm = QStateMachine()
self.account_list = []
self.timerSystem = QTimer()
self.lineCmdText = ''
self.prohibitCodeList = [] # 졜근 ? μΌλ™μ•ˆ 거래 λ˜μ—ˆλ˜ μ’…λͺ© 거래 κΈˆμ§€ list
self.yupjongInfo = {'μ½”μŠ€ν”Ό': {}, 'μ½”μŠ€λ‹₯': {} } # { 'yupjong_code': { 'ν˜„μž¬κ°€': 222, ...} }
self.michegyeolInfo = {}
self.jangoInfo = {} # { 'jongmok_code': { 'μ΄μ΅μ‹€ν˜„κ°€': 222, ...}}
self.jangoInfoFromFile = {} # TR μž”κ³  정보 μš”μ²­ μ‘°νšŒλ‘œλŠ” 얻을 수 μ—†λŠ” 데이터λ₯Ό 파일둜 μ €μž₯ν•˜κ³  첫 μ‹€ν–‰μ‹œ λ‘œλ“œν•¨
self.chegyeolInfo = {} # { 'λ‚ μ§œ' : [ [ '주문ꡬ뢄', '맀도', 'λΆ„ν• λ§€μˆ˜μ΄λ ₯', '체결가' , 'μ²΄κ²°μˆ˜λŸ‰', 'λ―Έμ²΄κ²°μˆ˜λŸ‰'] ] }
self.conditionOccurList = [] # 쑰건 μ§„μž…μ΄ λ°œμƒν•œ λͺ¨λ“  리슀트 μ €μž₯ν•˜κ³  맀수 결정에 μ‚¬μš©λ˜λŠ” λͺ¨λ“  정보λ₯Ό μ €μž₯함 [ {'μ’…λͺ©μ½”λ“œ': code, ...}]
self.conditionRevemoList = [] # 쑰건 μ΄νƒˆμ΄ λ°œμƒν•œ λͺ¨λ“  리슀트 μ €μž₯
self.kospiCodeList = ()
self.kosdaqCodeList = ()
self.createState()
self.createConnection()
self.currentTime = datetime.datetime.now()
self.current_condition_name = '30a'
# μž”κ³  정보 μ €μž₯μ‹œ μ €μž₯ μ œμ™Έλ  ν‚€ κ°’λ“€
self.jango_remove_keys = [
'λ§€λ„ν˜Έκ°€1', 'λ§€λ„ν˜Έκ°€2', 'λ§€λ„ν˜Έκ°€3', 'λ§€λ„ν˜Έκ°€μˆ˜λŸ‰1', 'λ§€λ„ν˜Έκ°€μˆ˜λŸ‰2', 'λ§€λ„ν˜Έκ°€μˆ˜λŸ‰3','λ§€λ„ν˜Έκ°€μ΄μž”λŸ‰',
'λ§€μˆ˜ν˜Έκ°€1', 'λ§€μˆ˜ν˜Έκ°€2', 'λ§€μˆ˜ν˜Έκ°€3', 'λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰1', 'λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰2', 'λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰3', 'λ§€μˆ˜ν˜Έκ°€μ΄μž”λŸ‰',
'ν˜„μž¬κ°€', 'ν˜Έκ°€μ‹œκ°„', 'μ„ΈκΈˆ', '전일쒅가', 'ν˜„μž¬κ°€', 'μ’…λͺ©λ²ˆν˜Έ', '수읡율', '수읡', 'μž”κ³ ' , '맀도쀑', 'μ‹œκ°€', 'κ³ κ°€', 'μ €κ°€', 'μž₯ꡬ뢄',
'κ±°λž˜λŸ‰', 'λ“±λ½μœ¨', 'μ „μΌλŒ€λΉ„', 'κΈ°μ€€κ°€', 'μƒν•œκ°€', 'ν•˜ν•œκ°€',
'일{}봉'.format(MAX_SAVE_CANDLE_COUNT), '{}λΆ„{}봉'.format(REQUEST_MINUTE_CANDLE_TYPE, MAX_SAVE_CANDLE_COUNT) ]
def createState(self):
# state defintion
mainState = QState(self.fsm)
stockCompleteState = QState(self.fsm)
finalState = QFinalState(self.fsm)
self.fsm.setInitialState(mainState)
initState = QState(mainState)
disconnectedState = QState(mainState)
connectedState = QState(QtCore.QState.ParallelStates, mainState)
systemState = QState(connectedState)
initSystemState = QState(systemState)
waitingTradeSystemState = QState(systemState)
standbySystemState = QState(systemState)
requestingJangoSystemState = QState(systemState)
terminatingSystemState = QState(systemState)
#transition defition
mainState.setInitialState(initState)
mainState.addTransition(self.sigStateStop, finalState)
mainState.addTransition(self.sigStockComplete, stockCompleteState)
stockCompleteState.addTransition(self.sigStateStop, finalState)
initState.addTransition(self.sigInitOk, disconnectedState)
disconnectedState.addTransition(self.sigConnected, connectedState)
disconnectedState.addTransition(self.sigTryConnect, disconnectedState)
connectedState.addTransition(self.sigDisconnected, disconnectedState)
systemState.setInitialState(initSystemState)
initSystemState.addTransition(self.sigGetConditionCplt, requestingJangoSystemState)
requestingJangoSystemState.addTransition(self.sigRequestJangoComplete, waitingTradeSystemState)
waitingTradeSystemState.addTransition(self.sigSelectCondition, standbySystemState)
standbySystemState.addTransition(self.sigTerminating, terminatingSystemState )
standbySystemState.addTransition(self.sigReselectCondition, waitingTradeSystemState )
#state entered slot connect
mainState.entered.connect(self.mainStateEntered)
stockCompleteState.entered.connect(self.stockCompleteStateEntered)
initState.entered.connect(self.initStateEntered)
disconnectedState.entered.connect(self.disconnectedStateEntered)
connectedState.entered.connect(self.connectedStateEntered)
systemState.entered.connect(self.systemStateEntered)
initSystemState.entered.connect(self.initSystemStateEntered)
waitingTradeSystemState.entered.connect(self.waitingTradeSystemStateEntered)
requestingJangoSystemState.entered.connect(self.requestingJangoSystemStateEntered)
standbySystemState.entered.connect(self.standbySystemStateEntered)
terminatingSystemState.entered.connect(self.terminatingSystemStateEntered)
# processBuy definition
processBuyState = QState(connectedState)
initProcessBuyState = QState(processBuyState)
standbyProcessBuyState = QState(processBuyState)
requestEtcInfoProcessBuyState = QState(processBuyState)
# requestMinuteCandleInfoProcessBuyState = QState(processBuyState)
determineBuyProcessBuyState = QState(processBuyState)
waitingTRlimitProcessBuyState = QState(processBuyState)
processBuyState.setInitialState(initProcessBuyState)
initProcessBuyState.addTransition(self.sigStartProcessBuy, standbyProcessBuyState)
standbyProcessBuyState.addTransition(self.sigConditionOccur, standbyProcessBuyState)
standbyProcessBuyState.addTransition(self.sigRequestEtcInfo, requestEtcInfoProcessBuyState)
standbyProcessBuyState.addTransition(self.sigStopProcessBuy, initProcessBuyState)
requestEtcInfoProcessBuyState.addTransition(self.sigRequestEtcInfo, requestEtcInfoProcessBuyState)
requestEtcInfoProcessBuyState.addTransition(self.sigDetermineBuy, determineBuyProcessBuyState)
requestEtcInfoProcessBuyState.addTransition(self.sigError, standbyProcessBuyState )
# requestMinuteCandleInfoProcessBuyState.addTransition(self.sigDetermineBuy, determineBuyProcessBuyState)
# requestMinuteCandleInfoProcessBuyState.addTransition(self.sigError, standbyProcessBuyState )
determineBuyProcessBuyState.addTransition(self.sigNoWaitTr, standbyProcessBuyState)
determineBuyProcessBuyState.addTransition(self.sigWaitTr, waitingTRlimitProcessBuyState)
waitingTRlimitProcessBuyState.addTransition(self.sigTrWaitComplete, standbyProcessBuyState)
processBuyState.entered.connect(self.processBuyStateEntered)
initProcessBuyState.entered.connect(self.initProcessBuyStateEntered)
standbyProcessBuyState.entered.connect(self.standbyProcessBuyStateEntered)
requestEtcInfoProcessBuyState.entered.connect(self.requestEtcInfoProcessBuyStateEntered)
# requestMinuteCandleInfoProcessBuyState.entered.connect(self.requestMinuteCandleInfoProcessBuyStateEntered)
determineBuyProcessBuyState.entered.connect(self.determineBuyProcessBuyStateEntered)
waitingTRlimitProcessBuyState.entered.connect(self.waitingTRlimitProcessBuyStateEntered)
#fsm start
finalState.entered.connect(self.finalStateEntered)
self.fsm.start()
pass
def initQmlEngine(self):
self.qmlEngine.load(QUrl('qrc:///qml/main.qml'))
self.rootObject = self.qmlEngine.rootObjects()[0]
self.rootObject.startClicked.connect(self.onStartClicked)
self.rootObject.restartClicked.connect(self.onRestartClicked)
self.rootObject.requestJangoClicked.connect(self.onRequestJangoClicked)
self.rootObject.chegyeolClicked.connect(self.onChegyeolClicked)
self.rootObject.testClicked.connect(self.onTestClicked)
rootContext = self.qmlEngine.rootContext()
rootContext.setContextProperty("model", self)
pass
@pyqtSlot()
def onBtnMakeExcelClicked(self):
print(util.whoami())
self.make_excel(CHEGYEOL_INFO_EXCEL_FILE_PATH, self.chegyeolInfo)
pass
@pyqtSlot()
def onBtnStartClicked(self):
print(util.whoami())
self.sigInitOk.emit()
@pyqtSlot()
def onBtnJangoClicked(self):
self.printStockInfo()
@pyqtSlot()
def onBtnYupjongClicked(self):
self.printYupjongInfo()
pass
@pyqtSlot()
def onBtnChegyeolClicked(self):
self.printChegyeolInfo('all')
@pyqtSlot()
def onBtnRunClicked(self):
arg = self.lineCmdText
if( arg ):
eval(arg)
pass
@pyqtSlot()
def onBtnConditionClicked(self):
items = self.getCodeListConditionOccurList()
buffer = []
for item in items:
boyou = "보유" if item in self.jangoInfo else ""
log_string = "{} {} ({}-{})".format(
item,
self.getMasterCodeName(item),
self.getMasterStockInfo(item),
boyou)
if( boyou == "보유" ):
buffer.append(log_string)
else:
buffer.insert(0, log_string)
print( '\n'.join(buffer) )
pass
@pyqtSlot(str)
def onLineCmdTextChanged(self, str):
self.lineCmdText = str
pass
@pyqtSlot(str)
def onTestClicked(self, arg):
print(util.whoami() + ' ' + arg)
eval(arg)
pass
def createConnection(self):
self.ocx.OnEventConnect[int].connect(self._OnEventConnect)
self.ocx.OnReceiveMsg[str, str, str, str].connect(self._OnReceiveMsg)
self.ocx.OnReceiveTrData[str, str, str, str, str,
int, str, str, str].connect(self._OnReceiveTrData)
self.ocx.OnReceiveRealData[str, str, str].connect(
self._OnReceiveRealData)
self.ocx.OnReceiveChejanData[str, int, str].connect(
self._OnReceiveChejanData)
self.ocx.OnReceiveConditionVer[int, str].connect(
self._OnReceiveConditionVer)
self.ocx.OnReceiveTrCondition[str, str, str, int, int].connect(
self._OnReceiveTrCondition)
self.ocx.OnReceiveRealCondition[str, str, str, str].connect(
self._OnReceiveRealCondition)
self.timerSystem.setInterval(1000)
self.timerSystem.timeout.connect(self.onTimerSystemTimeout)
def isTradeAvailable(self):
# 맀수 κ°€λŠ₯ μ‹œκ°„ 체크
# κΈ°λ³Έ 정보λ₯Ό μ–»κΈ° μœ„ν•΄μ„œλŠ” μž₯ μ‹œμž‘μ „ 미리 λ™μž‘μ„ μ‹œμΌœμ•Ό ν•˜κ³  맀수λ₯Ό μœ„ν•œ μ‹œκ°„μ€ μ •ν™•νžˆ 9μ‹œλ₯Ό 맞좀 (λ™μ‹œν˜Έκ°€ μ‹œκ°„μ˜ 맀도 ν˜Έκ°€λ‘œ 인해 맀수 됨을 막기 μœ„ν•¨)
ret_vals= []
current_time = self.currentTime.time()
for start, stop in AUTO_TRADING_OPERATION_TIME:
start_time = datetime.time(
hour = 9,
minute = 0 )
stop_time = datetime.time(
hour = stop[0],
minute = stop[1])
if( current_time >= start_time and current_time <= stop_time ):
ret_vals.append(True)
else:
ret_vals.append(False)
pass
# ν•˜λ‚˜λΌλ„ True μ˜€μœΌλ©΄ 거래 κ°€λŠ₯μ‹œκ°„μž„
if( ret_vals.count(True) ):
return True
else:
return False
pass
@pyqtSlot()
def mainStateEntered(self):
pass
@pyqtSlot()
def stockCompleteStateEntered(self):
print(util.whoami())
self.sigStateStop.emit()
pass
@pyqtSlot()
def initStateEntered(self):
print(util.whoami())
self.sigInitOk.emit()
pass
@pyqtSlot()
def disconnectedStateEntered(self):
# print(util.whoami())
if( self.getConnectState() == 0 ):
self.commConnect()
QTimer.singleShot(90000, self.sigTryConnect)
pass
else:
self.sigConnected.emit()
@pyqtSlot()
def connectedStateEntered(self):
# get κ³„μ’Œ 정보
account_cnt = self.getLoginInfo("ACCOUNT_CNT")
acc_num = self.getLoginInfo("ACCNO")
user_id = self.getLoginInfo("USER_ID")
user_name = self.getLoginInfo("USER_NAME")
keyboard_boan = self.getLoginInfo("KEY_BSECGB")
firewall = self.getLoginInfo("FIREW_SECGB")
print("account count: {}, acc_num: {}, user id: {}, "
"user_name: {}, keyboard_boan: {}, firewall: {}"
.format(account_cnt, acc_num, user_id, user_name,
keyboard_boan, firewall))
self.account_list = (acc_num.split(';')[:-1])
print(util.whoami() + 'account list ' + str(self.account_list))
# μ½”μŠ€ν”Ό , μ½”μŠ€λ‹₯ μ’…λͺ© μ½”λ“œ 리슀트 μ–»κΈ°
result = self.getCodeListByMarket('0')
self.kospiCodeList = tuple(result.split(';'))
result = self.getCodeListByMarket('10')
self.kosdaqCodeList = tuple(result.split(';'))
pass
@pyqtSlot()
def systemStateEntered(self):
pass
@pyqtSlot()
def initSystemStateEntered(self):
# 체결정보 λ‘œλ“œ
if( os.path.isfile(CHEGYEOL_INFO_FILE_PATH) == True ):
with open(CHEGYEOL_INFO_FILE_PATH, 'r', encoding='utf8') as f:
file_contents = f.read()
self.chegyeolInfo = json.loads(file_contents)
if( os.path.isfile(JANGO_INFO_FILE_PATH) == True ):
with open(JANGO_INFO_FILE_PATH, 'r', encoding='utf8') as f:
file_contents = f.read()
self.jangoInfoFromFile = json.loads(file_contents)
# get 쑰건 검색 리슀트
self.getConditionLoad()
self.setRealReg(kw_util.sendRealRegUpjongScrNo, '1;101', kw_util.type_fidset['μ—…μ’…μ§€μˆ˜'], "0")
self.setRealReg(kw_util.sendRealRegTradeStartScrNo, '', kw_util.type_fidset['μž₯μ‹œμž‘μ‹œκ°„'], "0")
self.timerSystem.start()
pass
@pyqtSlot()
def requestingJangoSystemStateEntered(self):
# print(util.whoami() )
# κ³„μ’Œ 정보 쑰회
self.requestOpw00018(self.account_list[0], "0")
pass
@pyqtSlot()
def waitingTradeSystemStateEntered(self):
# μž₯μ‹œμž‘ 전에 쑰건이 μ‹œμž‘ν•˜λ„λ‘ 함
self.sigSelectCondition.emit()
# λ°˜ν™˜κ°’ : 쑰건인덱슀1^쑰건λͺ…1;쑰건인덱슀2^쑰건λͺ…2;…;
# result = '쑰건인덱슀1^쑰건λͺ…1;쑰건인덱슀2^쑰건λͺ…2;'
result = self.getConditionNameList()
searchPattern = r'(?P<index>[^\/:*?"<>|;]+)\^(?P<name>[^\/:*?"<>|;]+);'
fileSearchObj = re.compile(searchPattern, re.IGNORECASE)
findList = fileSearchObj.findall(result)
tempDict = dict(findList)
# print(tempDict)
condition_name_screenNo_dict = {}
for number, condition in tempDict.items():
condition_name_screenNo_dict[condition] = [kw_util.sendConditionScreenNo + '{}'.format(int (number)), number]
start_info = []
start_name = None
for name, info in condition_name_screenNo_dict.items():
if name == self.current_condition_name:
start_info = info
start_name = name
else:
# print("stop condition " + name + ", screen_no: " + info[0] + ", number " + info[1] )
self.sendConditionStop( info[0], name, info[1])
print("start condition " + start_name + ", screen_no: " + start_info[0] + ", number " + start_info[1] )
self.sendCondition( start_info[0], start_name, start_info[1], 1)
pass
@pyqtSlot()
def standbySystemStateEntered(self):
print(util.whoami() )
self.makeJangoInfoFile()
# μ—°μ†μœΌλ‘œ μ΅œλŒ€ 5개 κ°€λŠ₯ν•˜λ―€λ‘œ 5κ°œκΉŒμ§€ κΈ°λ‹€λ¦Ό
QTimer.singleShot( TR_TIME_LIMIT_MS * 5, self.sigStartProcessBuy)
pass
@pyqtSlot()
def terminatingSystemStateEntered(self):
print(util.whoami() )
pass
@pyqtSlot()
def processBuyStateEntered(self):
pass
@pyqtSlot()
def initProcessBuyStateEntered(self):
print(util.whoami())
pass
@pyqtSlot()
def standbyProcessBuyStateEntered(self):
# print(util.whoami() )
QTimer.singleShot(100, self.sigRequestEtcInfo)
@pyqtSlot()
def requestEtcInfoProcessBuyStateEntered(self):
#μž₯쀑에 ν•œλ²ˆλ§Œ 얻어도 λ˜λŠ” 정보λ₯Ό μš”μ²­ν•  λ•Œ
# print(util.whoami() )
# 쑰건 λ°œμƒ 리슀트 검색
for jongmok_code in self.conditionRevemoList:
self.removeConditionOccurList(jongmok_code)
self.conditionRevemoList.clear()
self.refreshRealRequest()
jongmok_info_dict = self.getConditionOccurList()
if( jongmok_info_dict == None ):
self.sigError.emit()
return
jongmok_code = jongmok_info_dict['μ’…λͺ©μ½”λ“œ']
jongmok_name = jongmok_info_dict['μ’…λͺ©λͺ…']
key_day_candle = '일{}봉'.format(MAX_SAVE_CANDLE_COUNT)
key_minute_candle = '{}λΆ„{}봉'.format(REQUEST_MINUTE_CANDLE_TYPE, MAX_SAVE_CANDLE_COUNT)
key_day_low_candle = '{}일봉쀑저가'.format(STOP_LOSS_CALCULATE_DAY)
# 일봉을 μš”μ²­ν•˜μ˜€κ³  μž”κ³  정보에 일봉 정보 μ—†λŠ” 경우 update
if( key_day_candle in jongmok_info_dict and jongmok_code in self.jangoInfo ):
if( key_day_candle not in self.jangoInfo[jongmok_code] ):
self.jangoInfo[jongmok_code][key_day_candle] = jongmok_info_dict[key_day_candle]
if( key_day_low_candle not in self.jangoInfo[jongmok_code] ):
self.jangoInfo[jongmok_code][key_day_low_candle] = jongmok_info_dict[key_day_low_candle]
##########################################################################################################
# 기본정보 μš”μ²­
# κΈ°μ€€κ°€μ˜ 경우 당일 상μž₯ μ’…λͺ©μ˜ 경우 곡백일 수 있음
# if ( 'κΈ°μ€€κ°€' not in jongmok_info_dict ):
# #κΈ°λ³Έ 정보 μ—¬λΆ€ 확인
# self.requestOpt10001(jongmok_code)
# print("request {}".format(jongmok_name) )
##########################################################################################################
# 일봉 정보 μš”μ²­
# if(key_day_candle not in jongmok_info_dict):
# #일봉 정보 μ—¬λΆ€ 확인
# self.requestOpt10081(jongmok_code)
# print("request {}".format(jongmok_name) )
##########################################################################################################
# 뢄봉 정보 μš”μ²­
if( True ):
#뢄봉 정보 확인
key_last_minute_candle_time = '졜근{}λΆ„λ΄‰μ²΄κ²°μ‹œκ°„'.format(REQUEST_MINUTE_CANDLE_TYPE)
last_request_time_str = jongmok_info_dict.get(key_last_minute_candle_time, '')
isRequestNeeded = False
if( last_request_time_str != ''):
last_request_time = datetime.datetime.strptime(last_request_time_str, "%Y%m%d%H%M%S")
# 초 정보 μ΄ˆκΈ°ν™”
last_request_time = last_request_time.replace(second = 0)
time_span = datetime.timedelta(minutes = REQUEST_MINUTE_CANDLE_TYPE)
expected_time = (last_request_time + time_span)
request_start_time = datetime.time(
hour = 9,
minute = REQUEST_MINUTE_CANDLE_TYPE
)
# 직전 λ΄‰μ‹œκ°„μ΄ μ΄ˆκ³Όν•œ κ²½μš°μ™€ μž₯ μ‹œμž‘ ν•˜κ³  λ°”λ‘œ 뢄봉 계속 μš”μ²­ν•˜λŠ” ν˜„μƒ λ§‰μŒ
if( expected_time <= self.currentTime and request_start_time <= self.currentTime.time() ):
isRequestNeeded = True
else:
#첫 μš”μ²­
isRequestNeeded = True
if( isRequestNeeded == True ):
if( self.requestOpt10080(jongmok_code) == False ):
self.sigError.emit()
else:
self.sigDetermineBuy.emit()
pass
pass
@pyqtSlot()
def determineBuyProcessBuyStateEntered(self):
jongmok_info_dict = self.getConditionOccurList()
key_day_candle = '일{}봉'.format(MAX_SAVE_CANDLE_COUNT)
key_minute_candle = '{}λΆ„{}봉'.format(REQUEST_MINUTE_CANDLE_TYPE, MAX_SAVE_CANDLE_COUNT)
# 쑰건 검색에 κ±Έλ¦° μ’…λͺ©λ„ 같이 λ¦¬μŠ€νŠΈμ—… λ˜λ―€λ‘œ
# μ’…λͺ© 기본정보, μ‹€μ‹œκ°„ 체결정보, μ‹€μ‹œκ°„ ν˜Έκ°€ μž”λŸ‰ 정보, 일봉 뢄봉 μžˆμ–΄μ•Ό 함
if( jongmok_info_dict != None ):
# κΈ°λ³Έ, 일봉, 뢄봉, μ‹€μ‹œκ°„ 정보가 μ—†λŠ” 경우 맀수 κΈˆμ§€
if(
jongmok_info_dict.get('λ“±λ½μœ¨', '') == '' or
jongmok_info_dict.get('λ§€λ„ν˜Έκ°€1', '') == ''
):
self.shuffleConditionOccurList()
self.sigNoWaitTr.emit()
print("1", end= '')
return
# 상μž₯ν•œμ§€ μ–Όλ§ˆ μ•ˆλ˜μ„œ 일봉 / 뢄봉 정보가 λΆ€μ‘±ν•œ 경우 μ œμ™Έ
if(
# len(jongmok_info_dict.get(key_day_candle, [])) != MAX_SAVE_CANDLE_COUNT or
len(jongmok_info_dict.get(key_minute_candle, [])) != MAX_SAVE_CANDLE_COUNT
):
self.shuffleConditionOccurList()
self.sigNoWaitTr.emit()
print("2", end= '')
return
else:
self.sigNoWaitTr.emit()
print("3", end= '')
return
if( self.isTradeAvailable() == False ):
print("4", end= '')
self.sigNoWaitTr.emit()
return
is_log_print_enable = False
return_vals = []
printLog = ''
jongmok_code = jongmok_info_dict['μ’…λͺ©μ½”λ“œ']
jongmok_name = jongmok_info_dict['μ’…λͺ©λͺ…']
# ν˜Έκ°€ μ •λ³΄λŠ” λ¬Έμžμ—΄λ‘œ κΈ°μ€€κ°€ λŒ€λΉ„ + , - 값이 λΆ™μ–΄ λ‚˜μ˜΄
maedoHoga1 = abs(int(jongmok_info_dict['λ§€λ„ν˜Έκ°€1']))
maedoHogaAmount1 = int(jongmok_info_dict['λ§€λ„ν˜Έκ°€μˆ˜λŸ‰1'])
maedoHoga2 = abs(int(jongmok_info_dict['λ§€λ„ν˜Έκ°€2']) )
maedoHogaAmount2 = int(jongmok_info_dict['λ§€λ„ν˜Έκ°€μˆ˜λŸ‰2'])
# print( util.whoami() + maedoHoga1 + " " + maedoHogaAmount1 + " " + maedoHoga2 + " " + maedoHogaAmount2 )
# print( util.whoami() + jongmok_name + " " + str(sum) + (" won") )
# util.save_log( '{0:^20} ν˜Έκ°€1:{1:>8}, μž”λŸ‰1:{2:>8} / ν˜Έκ°€2:{3:>8}, μž”λŸ‰2:{4:>8}'
# .format(jongmok_name, maedoHoga1, maedoHogaAmount1, maedoHoga2, maedoHogaAmount2), 'ν˜Έκ°€μž”λŸ‰' , folder= "log")
printLog += ' ' + jongmok_name + ' ' + jongmok_code + ' ' + str(maedoHoga1) + ' '
##########################################################################################################
# μ œμ™Έ μ’…λͺ©μΈμ§€ 확인
if( jongmok_code in EXCEPTION_LIST ):
printLog += "(μ œμ™Έμ’…λͺ©)"
return_vals.append(False)
##########################################################################################################
# μ΅œλŒ€ 보유 ν•  수 μžˆλŠ” μ’…λͺ© 보유수λ₯Ό λ„˜μ—ˆλŠ”μ§€ 확인
if( len(self.jangoInfo.keys()) < MAX_STOCK_POSSESION_COUNT + len(EXCEPTION_LIST) ):
pass
else:
if( jongmok_code not in self.jangoInfo):
printLog += "(μ’…λͺ©μ΅œλŒ€λ³΄μœ μ€‘)"
return_vals.append(False)
##########################################################################################################
# 졜근 λ§€μˆ˜κ°€/λΆ„ν•  맀수 횟수 정보 생성
bunhal_maesu_list = []
last_maeip_price = 99999999
maesu_count = 0
if( jongmok_code in self.jangoInfo):
bunhal_maesu_list = self.jangoInfo[jongmok_code].get('λΆ„ν• λ§€μˆ˜μ΄λ ₯', [])
chegyeol_info = bunhal_maesu_list[-1]
last_maeip_price = int(chegyeol_info.split(':')[1]) #λ‚ μ§œ:가격:μˆ˜λŸ‰
maesu_count = len(bunhal_maesu_list)
##########################################################################################################
# 전일 μ’…κ°€λ₯Ό μ–»κΈ° μœ„ν•œ κΈ°μ€€κ°€ 정보 생성
# κΈ°μ€€κ°€ 정보가 곡백 인 경우 있음
gijunga = int(float(jongmok_info_dict['ν˜„μž¬κ°€']) / ( 1 + float(jongmok_info_dict['λ“±λ½μœ¨']) / 100 ) )
# print( '{} κΈ°μ€€κ°€: {}'.format( jongmok_name, gijunga ))
# 0번의 경우 ν˜„μž¬λ΄‰μ„ λœ»ν•˜λ©°, TR μš”μ²­μ„ 계속 ν•˜κ²Œ λ˜λŠ” 경우 정확해짐 --> μ‹€μ‹œκ°„ μ²΄κ²°κ°€λ‘œ 확인
# ν˜„μž¬λ΄‰μ˜ 경우 맀번 μš”μ²­ν•˜μ§€ μ•ŠμœΌλ©΄ 데이터가 μ •ν™•ν•˜μ§€ μ•ŠμŒ
##########################################################################################################
# μΆ”κ°€ 맀수 횟수 μ œν•œ
if( maesu_count < BUNHAL_MAESU_LIMIT ):
pass
else:
printLog += '(λΆ„ν• λ§€μˆ˜ν•œκ³„)'
return_vals.append(False)
##########################################################################################################
# 당일 뢄봉 확인
# _today_min_list = []
# for item in jongmok_info_dict[key_minute_candle][1:]:
# # ν˜„μž¬λ΄‰ μ œμ™Έ
# # 20191104145500 ν˜•μ‹
# item_date = datetime.datetime.strptime(item[time_index], '%Y%m%d%H%M%S').date()
# # print(item_date)
# # 당일 λ΄‰λ§Œ 포함
# if( item_date >= self.currentTime.date()) :
# # print(item)
# _today_min_list.append(item)
##########################################################################################################
# 맀도 ν˜Έκ°€ μž”λŸ‰ 확인해 μ‚΄λ§ŒνΌ μžˆλŠ” 경우 맀수
# 맀도 2ν˜Έκ°€κΉŒμ§€ λ΄„
totalMaedoHogaAmount = maedoHoga1 * maedoHogaAmount1 + maedoHoga2 * maedoHogaAmount2
if( totalMaedoHogaAmount >= TOTAL_BUY_AMOUNT):
pass
else:
# print('{} (ν˜Έκ°€μˆ˜λŸ‰λΆ€μ‘±: λ§€λ„ν˜Έκ°€1 {} λ§€λ„ν˜Έκ°€μž”λŸ‰1 {} λ§€λ„ν˜Έκ°€2 {} λ§€λ„ν˜Έκ°€μž”λŸ‰2 {})'.format(jongmok_name, maedoHoga1, maedoHogaAmount1, maedoHoga2, maedoHogaAmount2))
printLog += '(ν˜Έκ°€μˆ˜λŸ‰λΆ€μ‘±: λ§€λ„ν˜Έκ°€1 {0} λ§€λ„ν˜Έκ°€μž”λŸ‰1 {1})'.format(maedoHoga1, maedoHogaAmount1)
# return_vals.append(False)
##########################################################################################################
# 기쑴에 이미 맀도 λ°œμƒν•˜κ±°λ‚˜,
# 졜근 ? 일내 맀수 μ’…λͺ©μ΄μ–΄μ„œ μΆ”κ°€ 맀수λ₯Ό 막기 μœ„ν•¨μΈ 경우
if( self.prohibitCodeList.count(jongmok_code) == 0 ):
pass
else:
printLog += '(κ±°λž˜κΈˆμ§€μ’…λͺ©)'
return_vals.append(False)
##########################################################################################################
# μ’…λͺ© λ“±λ½μœ¨μ„ 쑰건 적용
# +, - λΆ™λŠ” μ†Œμˆ˜μ΄λ―€λ‘œ float 으둜 λ¨Όμ € 처리
updown_percentage = float(jongmok_info_dict['λ“±λ½μœ¨'] )
if( updown_percentage < 23 and updown_percentage > 0):
pass
else:
printLog += '(μ’…λͺ©λ“±λ½μœ¨λ―ΈμΆ©μ‘±: λ“±λ½μœ¨ {0})'.format(updown_percentage)
return_vals.append(False)
pass
##########################################################################################################
# 첫 λ§€μˆ˜μ‹œλ§Œ μ μš©λ˜λŠ” 쑰건
if( jongmok_code not in self.jangoInfo ):
if( self.current_condition_name == 'μž₯초반'):
pass
else:
pass
##########################################################################################################
# μΆ”κ°€ λ§€μˆ˜μ‹œλ§Œ μ μš©λ˜λŠ” 쑰건
else:
##########################################################################################################
# 졜근 λ§€μž…κ°€ λŒ€λΉ„ λΉ„κ΅ν•˜μ—¬ 좔맀
if( maedoHoga1 > last_maeip_price
):
# print("{:<30}".format(jongmok_name) + "좔맀쑰건좩쑱" +" μ΅œκ·Όλ§€μˆ˜κ°€:" + str(last_maeip_price) + ' λ§€λ„ν˜Έκ°€1:' + str(maedoHoga1) )
pass
else:
printLog += '(좔맀쑰건미좩쑱)'
return_vals.append(False)
temp = '({} {})'\
.format( jongmok_name, maedoHoga1 )
# print( util.cur_time_msec() , temp)
printLog += temp
pass
##########################################################################################################
# 맀수
##########################################################################################################
# 맀도 ν˜Έκ°€κ°€ 0인경우 μƒν•œκ°€μž„
if( return_vals.count(False) == 0 and maedoHoga1 != 0 ):
util.save_log(jongmok_name, '맀수주문', folder= "log")
qty = 0
if( TEST_MODE == True ):
qty = 1
else:
# 맀수 μˆ˜λŸ‰μ„ μ‘°μ ˆν•˜κΈ° μœ„ν•¨
if( jongmok_code in self.jangoInfo):
first_chegyeol_time_str = ""
if( len(bunhal_maesu_list) ):
first_chegyeol_time_str = bunhal_maesu_list[0].split(':')[0] # λ‚ μ§œ:가격:μˆ˜λŸ‰
if( first_chegyeol_time_str != ''):
base_time = datetime.datetime.strptime("20180127010101", "%Y%m%d%H%M%S")
base2_time = datetime.datetime.strptime("20180319010101", "%Y%m%d%H%M%S")
first_maesu_time = datetime.datetime.strptime(first_chegyeol_time_str, "%Y%m%d%H%M%S")
total_price = MAESU_TOTAL_PRICE[maesu_count]
if( base2_time > first_maesu_time and base_time < first_maesu_time ):
# 500000
qty = int(total_price / maedoHoga1 ) / 3 + 1 # μ•½κ°„ μ˜€λ²„ν•˜κ²Œ μ‚Ό
pass
elif( base2_time < first_maesu_time ):
# 1500000
qty = int(total_price / maedoHoga1 ) + 1 # μ•½κ°„ μ˜€λ²„ν•˜κ²Œ μ‚Ό
pass
else:
qty = int(total_price / maedoHoga1 / 30 ) + 1
else:
pass
else:
# μ‹ κ·œ 맀수
total_price = MAESU_TOTAL_PRICE[maesu_count]
qty = int(total_price / maedoHoga1 ) + 1
result = ""
result = self.sendOrder("buy_" + jongmok_code, kw_util.sendOrderScreenNo,
objKiwoom.account_list[0], kw_util.dict_order["μ‹ κ·œλ§€μˆ˜"], jongmok_code,
qty, maedoHoga2 , kw_util.dict_order["지정가"], "")
print("B " + str(result) , sep="")
printLog = '**** [λ§€μˆ˜μˆ˜λŸ‰: {0}, λ§€μˆ˜κ°€: {1}, 맀수횟수: {2}] ****'.format(
qty,
maedoHoga1,
maesu_count
) + printLog
is_log_print_enable = True
pass
else:
self.sigNoWaitTr.emit()
pass
self.shuffleConditionOccurList()
if( is_log_print_enable ):
util.save_log(printLog, 'μ‘°κ±΄μ§„μž…', folder = "log")
pass
@pyqtSlot()
def waitingTRlimitProcessBuyStateEntered(self):
# print(util.whoami())
# TR 은 κ°œλ‹Ή 3.7 초 μ œν•œ
# 5연속 μ‘°νšŒμ‹œ 17초 λŒ€κΈ° 해야함
# print(util.whoami() )
QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigTrWaitComplete)
pass
@pyqtSlot()
def finalStateEntered(self):
print(util.whoami())
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
util.save_log('', subject= '', folder='log')
# import subprocess
# subprocess.call(["shutdown", "-s", "-t", "500"])
pass
def sendorder_multi(self, rQName, screenNo, accNo, orderType, code, qty, price, hogaGb, orgOrderNo):
def inner():
self.sendOrder(rQName, screenNo, accNo, orderType, code, qty, price, hogaGb, orgOrderNo)
return inner
def printStockInfo(self, jongmok_code = 'all'):
if( jongmok_code == 'all'):
print(json.dumps(self.jangoInfo, ensure_ascii= False, indent =2, sort_keys = True))
else:
print(json.dumps(self.jangoInfo[jongmok_code], ensure_ascii= False, indent =2, sort_keys = True))
pass
def printChegyeolInfo(self, current_date = 'all'):
if( current_date == 'all' ):
print(json.dumps(self.chegyeolInfo, ensure_ascii= False, indent = 2, sort_keys = True))
elif( current_date == ''):
current_date = self.currentTime.date().strftime("%y%m%d")
if( current_date in self.chegyeolInfo):
print(json.dumps(self.chegyeolInfo[current_date], ensure_ascii= False, indent = 2, sort_keys = True))
def printYupjongInfo(self):
print(json.dumps(self.yupjongInfo, ensure_ascii= False, indent =2, sort_keys = True))
# 주식 μž”κ³ μ •λ³΄ μš”μ²­
def requestOpw00018(self, account_num, sPrevNext):
self.setInputValue('κ³„μ’Œλ²ˆν˜Έ', account_num)
self.setInputValue('λΉ„λ°€λ²ˆν˜Έ', '') # μ‚¬μš©μ•ˆν•¨(곡백)
self.setInputValue('λΉ„λΉŒλ²ˆν˜Έμž…λ ₯맀체ꡬ뢄', '00')
self.setInputValue('μ‘°νšŒκ΅¬λΆ„', '1')
# 연속 데이터 μ‘°νšŒν•΄μ•Ό ν•˜λŠ” 경우
if( sPrevNext == "2" ):
ret = self.commRqData(account_num, "opw00018", 2, kw_util.sendAccountInfoScreenNo)
else:
ret = self.commRqData(account_num, "opw00018", 0, kw_util.sendAccountInfoScreenNo)
errorString = None
if( ret != 0 ):
errorString = account_num + " commRqData() " + kw_util.parseErrorCode(str(ret))
print(util.whoami() + errorString )
util.save_log(errorString, util.whoami(), folder = "log" )
return False
return True
# 주식 μž”κ³  정보 #rQName 의 경우 κ³„μ’Œ 번호둜 λ„˜κ²¨μ€Œ
def makeOpw00018Info(self, rQName):
data_cnt = self.getRepeatCnt('opw00018', rQName)
for cnt in range(data_cnt):
info_dict = {}
for item_name in kw_util.dict_jusik['TR:κ³„μ’Œν‰κ°€μž”κ³ λ‚΄μ—­μš”μ²­']:
result = self.getCommData("opw00018", rQName, cnt, item_name)
# μ—†λŠ” μ»¬λŸΌμ€ pass
if( len(result) == 0 ):
continue
if( item_name == 'μ’…λͺ©λͺ…'):
info_dict[item_name] = result.strip()
elif( item_name == 'μ’…λͺ©λ²ˆν˜Έ'):
info_dict[item_name] = result[1:-1].strip()
elif( item_name == '수읡λ₯ (%)'):
info_dict[item_name] = int(result) / 100
else:
info_dict[item_name] = int(result)
jongmok_code = info_dict['μ’…λͺ©λ²ˆν˜Έ']
info_dict['μ—…μ’…'] = self.getMasterStockInfo(jongmok_code)
if( jongmok_code not in self.jangoInfo.keys() ):
self.jangoInfo[jongmok_code] = info_dict
else:
# 기쑴에 가지고 μžˆλŠ” μ’…λͺ©μ΄λ©΄ update
self.jangoInfo[jongmok_code].update(info_dict)
# print(self.jangoInfo)
return True
# 주식 1일봉 μš”μ²­
def requestOpt10081(self, jongmok_code):
# print(util.cur_time_msec() )
datetime_str = datetime.datetime.now().strftime('%Y%m%d')
self.setInputValue("μ’…λͺ©μ½”λ“œ", jongmok_code)
self.setInputValue("κΈ°μ€€μΌμž", datetime_str)
self.setInputValue('μˆ˜μ •μ£Όκ°€κ΅¬λΆ„', '1')
ret = self.commRqData(jongmok_code, "opt10081", 0, kw_util.sendGibonScreenNo)
errorString = None
if( ret != 0 ):
errorString = jongmok_code + " commRqData() " + kw_util.parseErrorCode(str(ret))
print(util.whoami() + errorString )
util.save_log(errorString, util.whoami(), folder = "log" )
return False
return True
# 주식 일봉 데이터 생성
def makeOpt10081Info(self, rQName):
# 쑰건 λ°œμƒν•œ μ’…λͺ© μƒμœ„ 리슀트의 정보λ₯Ό μ–»κΈ° μœ„ν•¨
jongmok_info_dict = self.getConditionOccurList()
if( jongmok_info_dict == None ):
return False
# ν•œλ²ˆ 읽으면 900개 읽힘
repeatCnt = self.getRepeatCnt("opt10081", rQName)
jongmok_code = rQName
# κ±°λž˜λ˜μ§€ μ•ŠλŠ” μ’…λͺ©μ˜ 경우 μ €κ°€κ°€ '' 값이 였기 λ•Œλ¬Έμ— 1κ°œλŠ” μ±„μ›Œλ‘ 
low_price_list = [999999999]
total_current_price_list = []
# μΌλ΄‰μ˜ ν˜„μž¬ 봉도 포함
for i in range(min(repeatCnt, 200)):
for item_name in kw_util.dict_jusik['TR:일봉']:
if( item_name == "μ €κ°€"):
result = self.getCommData("opt10081", rQName, i, item_name)
if( i != 0 and result != '' and i <= STOP_LOSS_CALCULATE_DAY):
# μ²«λ²ˆμ§ΈλŠ” λ‹ΉμΌμ΄λ―€λ‘œ μ œμ™Έ
low_price_list.append( abs(int(result) ) )
if( item_name == "ν˜„μž¬κ°€"):
result = self.getCommData("opt10081", rQName, i, item_name)
if( i != 0 and result != '' ):
# μ²«λ²ˆμ§ΈλŠ” λ‹ΉμΌμ΄λ―€λ‘œ μ œμ™Έ
total_current_price_list.append( abs(int(result) ) )
jongmok_info_dict['{}일봉쀑저가'.format(STOP_LOSS_CALCULATE_DAY)] = min(low_price_list)
jongmok_info_dict['일{}봉'.format(MAX_SAVE_CANDLE_COUNT)] = total_current_price_list[0:MAX_SAVE_CANDLE_COUNT]
return True
# 주식 뢄봉 tr μš”μ²­
def requestOpt10080(self, jongmok_code):
# 뢄봉 tr μš”μ²­μ˜ 경우 λ„ˆλ¬΄ λ§Žμ€ 데이터λ₯Ό μš”μ²­ν•˜λ―€λ‘œ ν•œκ°œμ”© μˆ˜ν–‰
candle_type_str = "5:5λΆ„"
if( REQUEST_MINUTE_CANDLE_TYPE == 5):
candle_type_str = "5:5λΆ„"
elif( REQUEST_MINUTE_CANDLE_TYPE == 3 ):
candle_type_str = "3:3λΆ„"
self.setInputValue("μ’…λͺ©μ½”λ“œ", jongmok_code )
self.setInputValue("ν‹±λ²”μœ„", candle_type_str)
self.setInputValue("μˆ˜μ •μ£Όκ°€κ΅¬λΆ„","1")
# rQName 을 λ°μ΄ν„°λ‘œ μ™ΈλΆ€μ—μ„œ μ‚¬μš©
ret = self.commRqData(jongmok_code , "opt10080", 0, kw_util.send5minScreenNo)
errorString = None
if( ret != 0 ):
errorString = jongmok_code + " commRqData() " + kw_util.parseErrorCode(str(ret))
print(util.whoami() + errorString )
util.save_log(errorString, util.whoami(), folder = "log" )
return False
return True
# 뢄봉 데이터 생성
def makeOpt10080Info(self, rQName):
jongmok_code = rQName
jongmok_info_dict = self.getConditionOccurList()
if( jongmok_info_dict == None ):
return False
# ν•œλ²ˆ 읽으면 900개 읽힘
repeatCnt = self.getRepeatCnt("opt10080", rQName)
total_current_price_list = []
# 3뢄봉 κΈ°μ€€ 6.5 μ‹œκ°„ * 20 = 130
for i in range(min(repeatCnt, MAX_SAVE_CANDLE_COUNT)):
line = []
for item_name in kw_util.dict_jusik['TR:뢄봉']:
result = self.getCommData("opt10080", rQName, i, item_name)
if( item_name == "μ²΄κ²°μ‹œκ°„" ):
# 20191104145500 ν˜•μ‹
if( i == 0 ):
jongmok_info_dict['졜근{}λΆ„λ΄‰μ²΄κ²°μ‹œκ°„'.format(REQUEST_MINUTE_CANDLE_TYPE)] = result.strip()
line.append( result.strip() )
else:
line.append( abs(int(result.strip()) ))
pass
total_current_price_list.append( line )
key_minute_candle = '{}λΆ„{}봉'.format(REQUEST_MINUTE_CANDLE_TYPE, MAX_SAVE_CANDLE_COUNT)
jongmok_info_dict[key_minute_candle] = total_current_price_list
if( jongmok_code in self.jangoInfo ):
self.jangoInfo[jongmok_code][key_minute_candle] = jongmok_info_dict[key_minute_candle]
return True
# μ—…μ’… 뢄봉 tr μš”μ²­
def requestOpt20005(self, yupjong_code):
self.setInputValue("μ—…μ’…μ½”λ“œ", yupjong_code )
self.setInputValue("ν‹±λ²”μœ„","5:5λΆ„")
self.setInputValue("μˆ˜μ •μ£Όκ°€κ΅¬λΆ„","1")
ret = 0
if( yupjong_code == '001'):
ret = self.commRqData(yupjong_code , "opt20005", 0, kw_util.sendReqYupjongKospiScreenNo)
else:
ret = self.commRqData(yupjong_code , "opt20005", 0, kw_util.sendReqYupjongKosdaqScreenNo)
errorString = None
if( ret != 0 ):
errorString = yupjong_code + " commRqData() " + kw_util.parseErrorCode(str(ret))
print(util.whoami() + errorString )
util.save_log(errorString, util.whoami(), folder = "log" )
return False
return True
# μ—…μ’… 뢄봉 데이터 생성
def makeOpt20005Info(self, rQName):
if( rQName == '001'):
yupjong_info_dict = self.yupjongInfo['μ½”μŠ€ν”Ό']
elif( rQName == '101'):
yupjong_info_dict = self.yupjongInfo['μ½”μŠ€λ‹₯']
else:
return
repeatCnt = self.getRepeatCnt("opt20005", rQName)
fivebong_sum = 0
twentybong_sum = 0
for i in range(min(repeatCnt, 20)):
line = []
for item_name in kw_util.dict_jusik['TR:업쒅뢄봉']:
result = self.getCommData("opt20005", rQName, i, item_name)
if( item_name == "ν˜„μž¬κ°€" ):
current_price = abs(int(result)) / 100
if( i < 5 ):
fivebong_sum += current_price
twentybong_sum += current_price
line.append(str(current_price))
else:
line.append(result.strip())
key_value = '5λΆ„ {0}봉전'.format(i)
yupjong_info_dict[key_value] = line
yupjong_info_dict['20봉평균'] = str(round(twentybong_sum / 20, 2))
yupjong_info_dict['5봉평균'] = str(round(fivebong_sum / 5, 2))
return True
# 주식 κΈ°λ³Έ 정보 μš”μ²­
def requestOpt10001(self, jongmok_code):
# print(util.cur_time_msec() )
self.setInputValue("μ’…λͺ©μ½”λ“œ", jongmok_code)
ret = self.commRqData(jongmok_code, "opt10001", 0, kw_util.sendGibonScreenNo)
errorString = None
if( ret != 0 ):
errorString = jongmok_code + " commRqData() " + kw_util.parseErrorCode(str(ret))
print(util.whoami() + errorString )
util.save_log(errorString, util.whoami(), folder = "log" )
return False
return True
# 주식 κΈ°λ³Έ 데이터 ( multi data μ•„λ‹˜ )
def makeOpt10001Info(self, rQName):
jongmok_info_dict = self.getConditionOccurList()
if( jongmok_info_dict == None):
return False
jongmok_code = rQName
for item_name in kw_util.dict_jusik['TR:기본정보']:
result = self.getCommData("opt10001", rQName, 0, item_name)
if( jongmok_code in self.jangoInfo ):
self.jangoInfo[jongmok_code][item_name] = result.strip()
jongmok_info_dict[item_name] = result.strip()
return True
@pyqtSlot()
def onTimerSystemTimeout(self):
self.currentTime = datetime.datetime.now()
jang_choban_start_time = datetime.time( hour = 9, minute = 0, second = 30 )
jang_choban_end_time = datetime.time( hour = 9, minute = 30 )
jang_jungban_start_time = datetime.time( hour = 14, minute = 00 )
current_time = self.currentTime.time()
isConditionRefreshed = False
if( current_time > jang_choban_start_time and current_time < jang_choban_end_time ):
if( self.current_condition_name != 'μž₯초반' ):
isConditionRefreshed = True
self.current_condition_name = '30a'
elif( current_time > jang_jungban_start_time ):
if( self.current_condition_name != 'μž₯ν›„λ°˜' ):
isConditionRefreshed = True
self.current_condition_name = '30a'
else:
if( self.current_condition_name != 'νœ΄μ‹' ):
isConditionRefreshed = True
self.current_condition_name = '30a'
if(isConditionRefreshed == True):
self.sigReselectCondition.emit()
if( self.getConnectState() != 1 ):
util.save_log("Disconnected!", "μ‹œμŠ€ν…œ", folder = "log")
self.sigDisconnected.emit()
else:
if( datetime.time(*TRADING_INFO_GETTING_TIME) <= self.currentTime.time() ):
self.timerSystem.stop()
util.save_log("Stock Trade Terminate!\n\n\n\n\n", "μ‹œμŠ€ν…œ", folder = "log")
pass
else :
pass
pass
@pyqtSlot()
def quit(self):
print(util.whoami())
self.commTerminate()
QApplication.quit()
# μ—λŸ¬μ½”λ“œμ˜ λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•œλ‹€.
@pyqtSlot(int, result=str)
def parseErrorCode(self, errCode):
return kw_util.parseErrorCode(errCode)
# event
# 톡신 μ—°κ²° μƒνƒœ λ³€κ²½μ‹œ 이벀트
# nErrCodeκ°€ 0이면 둜그인 성곡, 음수면 μ‹€νŒ¨
def _OnEventConnect(self, errCode):
print(util.whoami() + '{}'.format(errCode))
if errCode == 0:
self.sigConnected.emit()
else:
self.sigDisconnected.emit()
# μˆ˜μ‹  λ©”μ‹œμ§€ 이벀트
def _OnReceiveMsg(self, scrNo, rQName, trCode, msg):
# print(util.whoami() + 'sScrNo: {}, sRQName: {}, sTrCode: {}, sMsg: {}'
# .format(scrNo, rQName, trCode, msg))
# [107066] 맀수주문이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.
# [107048] 맀도주문이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€
# [571489] μž₯이 μ—΄λ¦¬μ§€μ•ŠλŠ” λ‚ μž…λ‹ˆλ‹€
# [100000] μ‘°νšŒκ°€ μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€
printData = 'sScrNo: {}, sRQName: {}, sTrCode: {}, sMsg: {}'.format(scrNo, rQName, trCode, msg)
# buy ν•˜λ‹€κ°€ 였λ₯˜ λ‚œκ²½μš° κ°•μ œλ‘œ buy signal 생성
# buy 정상 λ©”μ‹œμ§€λŠ” 107066
if( 'buy' in rQName and '107066' not in msg ):
self.sigWaitTr.emit()
# sell ν•˜λ‹€κ°€ 였λ₯˜ λ‚œκ²½μš° κ°•μ œλ‘œ buy signal 생성
# sell 정상 λ©”μ‹œμ§€λŠ” 107066
if( 'sell' in rQName and '107048' not in msg ):
pass
# self.sigWaitTr.emit()
# sell ν•˜λ‹€κ°€ 였λ₯˜ λ‚œκ²½μš°
# if( 'sell' in rQName and '맀도가λŠ₯μˆ˜λŸ‰' in msg ):
# self.sigWaitTr.emit()
print(printData)
util.save_log(printData, "μ‹œμŠ€ν…œλ©”μ‹œμ§€", "log")
pass
# Tran μˆ˜μ‹ μ‹œ 이벀트
def _OnReceiveTrData( self, scrNo, rQName, trCode, recordName,
prevNext, dataLength, errorCode, message,
splmMsg):
# print(util.whoami() + 'sScrNo: {}, rQName: {}, trCode: {}, prevNext {}'
# .format(scrNo, rQName, trCode, prevNext))
if ( trCode == 'opw00018' ):
# 게쒌 정보 μš”μ²­ rQName 은 κ³„μ’Œλ²ˆν˜Έμž„
if( self.makeOpw00018Info(rQName) ):
# 연속 데이터 쑴재 ν•˜λŠ” 경우 재 쑰회
if( prevNext == "2" ) :
self.requestOpw00018(self.account_list[0], prevNext)
else:
QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigRequestJangoComplete)
else:
self.sigError.emit()
pass
#주식 κΈ°λ³Έ 정보 μš”μ²­ rQName 은 κ°œλ³„ μ’…λͺ© μ½”λ“œμž„
elif( trCode == "opt10001"):
if( self.makeOpt10001Info(rQName) ):
QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigRequestEtcInfo)
else:
self.sigError.emit()
pass
#주식 일봉 정보 μš”μ²­ rqName 은 κ°œλ³„ μ’…λͺ© μ½”λ“œμž„
elif( trCode =='opt10081'):
if( self.makeOpt10081Info(rQName) ):
QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigRequestEtcInfo)
self.makeJangoInfoFile()
pass
else:
self.sigError.emit()
# 주식 뢄봉 정보 μš”μ²­ rQName κ°œλ³„ μ’…λͺ© μ½”λ“œ
elif( trCode == "opt10080"):
if( self.makeOpt10080Info(rQName) ) :
QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigDetermineBuy )
else:
self.sigError.emit()
pass
# μ—…μ’… 뢄봉 rQName μ—…μ’… μ½”λ“œ
elif( trCode == "opt20005"):
if( self.makeOpt20005Info(rQName) ) :
QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigRequestEtcInfo)
pass
else:
self.sigError.emit()
pass
# μ‹€μ‹œκ°„ μ‹œμ„Έ 이벀트
def _OnReceiveRealData(self, jongmok_code, realType, realData):
# print(util.whoami() + 'jongmok_code: {}, {}, realType: {}'
# .format(jongmok_code, self.getMasterCodeName(jongmok_code), realType))
# μž₯전에도 주식 ν˜Έκ°€ μž”λŸ‰ 값이 올수 μžˆμœΌλ―€λ‘œ μœ μ˜ν•΄μ•Όν•¨
if( realType == "μ£Όμ‹ν˜Έκ°€μž”λŸ‰"):
# print(util.whoami() + 'jongmok_code: {}, realType: {}, realData: {}'
# .format(jongmok_code, realType, realData))
self.makeHogaJanRyangInfo(jongmok_code)
#주식 μ²΄κ²°λ‘œλŠ” 사고 νŒ”κΈ°μ—λŠ” λ°˜μ‘μ΄ λ„ˆλ¬΄ 느림
elif( realType == "주식체결"):
# print(util.whoami() + 'jongmok_code: {}, realType: {}, realData: {}'
# .format(jongmok_code, realType, realData))
self.makeBasicInfo(jongmok_code)
# WARNING: μž₯쀑에 κΈ‰λ“±μœΌλ‘œ 거래 정지 λ˜μ–΄ λ™μ‹œ ν˜Έκ°€μ§„ν–‰λ˜λŠ” κ²½μš°μ— λŒ€λΉ„ν•˜μ—¬ 체결가 정보 λ°œμƒν–ˆμ„λ•Œλ§Œ stoploss 진행함.
self.processStopLoss(jongmok_code)
pass
elif( realType == "μ£Όμ‹μ‹œμ„Έ"):
# μž₯μ’…λ£Œ 후에 λ‚˜μ˜΄
# print(util.whoami() + 'jongmok_code: {}, realType: {}, realData: {}'
# .format(jongmok_code, realType, realData))
pass
elif( realType == "μ—…μ’…μ§€μˆ˜" ):
# print(util.whoami() + 'jongmok_code: {}, realType: {}, realData: {}'
# .format(jongmok_code, realType, realData))
result = ''
for col_name in kw_util.dict_jusik['μ‹€μ‹œκ°„-μ—…μ’…μ§€μˆ˜']:
result = self.getCommRealData(jongmok_code, kw_util.name_fid[col_name] )
if( jongmok_code == '001'):
self.yupjongInfo['μ½”μŠ€ν”Ό'][col_name] = result.strip()
elif( jongmok_code == '100'):
self.yupjongInfo['μ½”μŠ€λ‹₯'][col_name] = result.strip()
pass
elif( realType == 'μž₯μ‹œμž‘μ‹œκ°„'):
# TODO: μž₯μ‹œμž‘ 30λΆ„μ „λΆ€ν„° μ‹€μ‹œκ°„ 정보가 μ˜¬λΌμ˜€λŠ”λ° 이λ₯Ό ν† λŒ€λ‘œ κ°€λ³€μ μœΌλ‘œ μž₯μ‹œμž‘μ‹œκ°„μ„ κ°€λŠ ν• μˆ˜ μžˆλ„λ‘ κΈ°λŠ₯ μΆ”κ°€ ν•„μš”
# μž₯μš΄μ˜κ΅¬λΆ„(0:μž₯μ‹œμž‘μ „, 2:μž₯μ’…λ£Œμ „, 3:μž₯μ‹œμž‘, 4,8:μž₯μ’…λ£Œ, 9:μž₯마감)
# λ™μ‹œν˜Έκ°€ μ‹œκ°„μ— 맀수 μ£Όλ¬Έ
result = self.getCommRealData(realType, kw_util.name_fid['μž₯μš΄μ˜κ΅¬λΆ„'] )
if( result == '2'):
self.sigTerminating.emit()
elif( result == '4' ): # μž₯μ’…λ£Œ ν›„ 5뢄뒀에 ν”„λ‘œκ·Έλž¨ μ’…λ£Œ ν•˜κ²Œ 함
QTimer.singleShot(300000, self.sigStockComplete)
# print(util.whoami() + 'jongmok_code: {}, realType: {}, realData: {}'
# .format(jongmok_code, realType, realData))
print(util.whoami() + 'jongmok_code: {}, realType: {}, realData: {}'
.format(jongmok_code, realType, realData))
pass
def calculateSuik(self, jongmok_code, current_price):
current_jango = self.jangoInfo[jongmok_code]
maeip_price = abs(int(current_jango['λ§€μž…κ°€']))
boyou_suryang = int(current_jango['λ³΄μœ μˆ˜λŸ‰'])
maeip_danga = maeip_price + maeip_price* 0.00015
maedo_danga = current_price - current_price * 0.00015 - current_price * 0.0025
suik_price = round( (maedo_danga - maeip_danga) * boyou_suryang , 2)
current_jango['수읡'] = suik_price
current_jango['수읡율'] = round( ( (maedo_danga - maeip_danga) / maeip_danga ) * 100 , 2)
pass
# μ‹€μ‹œκ°„ ν˜Έκ°€ μž”λŸ‰ 정보
def makeHogaJanRyangInfo(self, jongmok_code):
#주식 ν˜Έκ°€ μž”λŸ‰ 정보 μš”μ²­
result = None
for col_name in kw_util.dict_jusik['μ‹€μ‹œκ°„-μ£Όμ‹ν˜Έκ°€μž”λŸ‰']:
result = self.getCommRealData(jongmok_code, kw_util.name_fid[col_name] )
if( jongmok_code in self.jangoInfo ):
self.jangoInfo[jongmok_code][col_name] = result.strip()
if( jongmok_code in self.getCodeListConditionOccurList() ):
self.setHogaConditionOccurList(jongmok_code, col_name, result.strip() )
pass
# μ‹€μ‹œκ°„ 체결(κΈ°λ³Έ) 정보
def makeBasicInfo(self, jongmok_code):
#주식 ν˜Έκ°€ μž”λŸ‰ 정보 μš”μ²­
result = None
for col_name in kw_util.dict_jusik['μ‹€μ‹œκ°„-주식체결']:
result = self.getCommRealData(jongmok_code, kw_util.name_fid[col_name] )
if( jongmok_code in self.jangoInfo ):
self.jangoInfo[jongmok_code][col_name] = result.strip()
if( jongmok_code in self.getCodeListConditionOccurList() ):
self.setHogaConditionOccurList(jongmok_code, col_name, result.strip() )
pass
def isMinCandleExist(self, current_jango):
key_minute_candle = '{}λΆ„{}봉'.format(REQUEST_MINUTE_CANDLE_TYPE, MAX_SAVE_CANDLE_COUNT)
if( key_minute_candle in current_jango
and len( current_jango[key_minute_candle] ) == MAX_SAVE_CANDLE_COUNT ): # 뢄봉 정보 μ–»μ—ˆλŠ”μ§€ 확인
return True
else:
return False
def isDayCandleExist(self, current_jango):
key_day_candle = '일{}봉'.format(MAX_SAVE_CANDLE_COUNT )
if( key_day_candle in current_jango
# and len( current_jango[key_day_candle] ) == MAX_SAVE_CANDLE_COUNT
): # 뢄봉 정보 μ–»μ—ˆλŠ”μ§€ 확인
return True
else:
return False
def processStopLoss(self, jongmok_code):
jongmok_name = self.getMasterCodeName(jongmok_code)
if( self.isTradeAvailable() == False ):
print('-1', end = '')
return
# μ˜ˆμ™Έ 처리 리슀트이면 μ’…λ£Œ
if( jongmok_code in EXCEPTION_LIST ):
# print('-2', end = '')
return
# μž”κ³ μ— μ—†λŠ” μ’…λͺ©μ΄λ©΄ μ’…λ£Œ
if( jongmok_code not in self.jangoInfo ):
# print('-3', end = '')
return
current_jango = self.jangoInfo[jongmok_code]
key_day_candle = '일{}봉'.format(MAX_SAVE_CANDLE_COUNT )
key_minute_candle = '{}λΆ„{}봉'.format(REQUEST_MINUTE_CANDLE_TYPE, MAX_SAVE_CANDLE_COUNT)
first_bunhal_maesu_time_str = current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'][0].split(':')[0] #λ‚ μ§œ:가격:μˆ˜λŸ‰
first_maeip_price = int(current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'][0].split(':')[1]) #λ‚ μ§œ:가격:μˆ˜λŸ‰
last_maeip_date_time_str = current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'][-1].split(':')[0] #λ‚ μ§œ:가격:μˆ˜λŸ‰
last_maeip_price = int(current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'][-1].split(':')[1]) #λ‚ μ§œ:가격:μˆ˜λŸ‰
if(
'μ†μ ˆκ°€' not in current_jango or
'λ§€μˆ˜ν˜Έκ°€1' not in current_jango or
'맀맀가λŠ₯μˆ˜λŸ‰' not in current_jango
):
print('-4', end = '')
return
jangosuryang = int( current_jango['맀맀가λŠ₯μˆ˜λŸ‰'] )
# ν˜Έκ°€ μ •λ³΄λŠ” λ¬Έμžμ—΄λ‘œ κΈ°μ€€κ°€ λŒ€λΉ„ + , - 값이 λΆ™μ–΄ λ‚˜μ˜΄
maesuHoga1 = abs(int(current_jango['λ§€μˆ˜ν˜Έκ°€1']))
maesuHogaAmount1 = int(current_jango['λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰1'])
maesuHoga2 = abs(int(current_jango['λ§€μˆ˜ν˜Έκ°€2']))
maesuHogaAmount2 = int(current_jango['λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰2'])
maesuHoga3 = abs(int(current_jango['λ§€μˆ˜ν˜Έκ°€3']))
maesuHogaAmount3 = int(current_jango['λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰3'])
stop_plus = int(current_jango['μ΄μ΅μ‹€ν˜„κ°€'])
stop_loss = int(current_jango['μ†μ ˆκ°€'])
maeipga = int(current_jango['λ§€μž…κ°€'])
# print( util.whoami() + maeuoga1 + " " + maesuHogaAmount1 + " " + maesuHoga2 + " " + maesuHogaAmount2 )
totalAmount = maesuHoga1 * maesuHogaAmount1 + maesuHoga2 * maesuHogaAmount2 + maesuHoga3 * maesuHogaAmount3
# 체결 강도 계산
if( "μ΅œλŒ€μ²΄κ²°κ°•λ„" not in current_jango ):
current_jango['μ΅œλŒ€μ²΄κ²°κ°•λ„'] = 0
max_chegyeol_gangdo = int(current_jango['μ΅œλŒ€μ²΄κ²°κ°•λ„'])
current_chegyeol_gagndo = float(current_jango['체결강도'])
# if( max_chegyeol_gang > current_chegyeol_gagndo + 5 ):
# if( current_chegyeol_gagndo < 100 ):
# stop_loss = 99999999
if( max_chegyeol_gangdo < current_chegyeol_gagndo ):
current_jango['μ΅œλŒ€μ²΄κ²°κ°•λ„'] = current_chegyeol_gagndo
_today_open_price = current_jango.get('μ‹œκ°€', None)
_today_high_price = current_jango.get('κ³ κ°€', None)
_today_amount = current_jango.get('κ±°λž˜λŸ‰', None)
########################################################################################
# 일봉 μ—°μ‚°
# 1 봉이 직전 λ΄‰μ΄λ―€λ‘œ ν˜„μž¬κ°€λ₯Ό ν¬ν•¨ν•œ 평균가λ₯Ό ꡬ함
# if( self.isDayCandleExist(current_jango) == True ): # 일봉 정보 μ–»μ—ˆλŠ”μ§€ 확인
# current_price_index = kw_util.dict_jusik['TR:일봉'].index('ν˜„μž¬κ°€')
# low_price_index = kw_util.dict_jusik['TR:일봉'].index('μ €κ°€')
# _4day_list = current_jango[key_day_candle][1:5]
# _9day_list = current_jango[key_day_candle][1:10]
# _19day_list = current_jango[key_day_candle][1:20]
# _5day_avr = ( sum(_4day_list) + maesuHoga1) / 5
# _10day_avr = ( sum(_9day_list) + maesuHoga1) / 10
# _20day_avr = ( sum(_19day_list) + maesuHoga1) / 20
# pass
########################################################################################
# 뢄봉 μ—°μ‚°
# 1 봉이 직전 λ΄‰μ΄λ―€λ‘œ ν˜„μž¬κ°€λ₯Ό ν¬ν•¨ν•œ 평균가λ₯Ό ꡬ함
min_current_price_index = kw_util.dict_jusik['TR:뢄봉'].index('ν˜„μž¬κ°€')
min_close_price_index = kw_util.dict_jusik['TR:뢄봉'].index('ν˜„μž¬κ°€')
min_low_price_index = kw_util.dict_jusik['TR:뢄봉'].index('μ €κ°€')
min_high_price_index = kw_util.dict_jusik['TR:뢄봉'].index('κ³ κ°€')
min_open_price_index = kw_util.dict_jusik['TR:뢄봉'].index('μ‹œκ°€')
min_amout_index = kw_util.dict_jusik['TR:뢄봉'].index('κ±°λž˜λŸ‰')
time_index = kw_util.dict_jusik['TR:뢄봉'].index('μ²΄κ²°μ‹œκ°„')
updown_percentage = float(current_jango['λ“±λ½μœ¨'])
time_span = datetime.timedelta(days = 1)
expected_date = (self.currentTime - time_span).date()
_yesterday_open_price = 0
_yesterday_close_price = 0
_yesterday_low_price = 0
_yesterday_amount = 0
if( self.isMinCandleExist(current_jango) == True ): # 뢄봉 정보 μ–»μ—ˆλŠ”μ§€ 확인
_4min_list = current_jango[key_minute_candle][1:5]
_9min_list = current_jango[key_minute_candle][1:10]
_19min_list = current_jango[key_minute_candle][1:20]
_59min_list = current_jango[key_minute_candle][1:60]
_5min_avr = ( sum([ item[min_current_price_index] for item in _4min_list]) + maesuHoga1) / 5
_10min_avr = ( sum([ item[min_current_price_index] for item in _9min_list]) + maesuHoga1) / 10
_20min_avr = ( sum([ item[min_current_price_index] for item in _19min_list]) + maesuHoga1) / 20
_60min_avr = ( sum([ item[min_current_price_index] for item in _59min_list]) + maesuHoga1) / 60
##########################################################################################################
# 1일전 뢄봉 확인
_yesterday_min_list = []
for item in current_jango[key_minute_candle]:
# 20191104145500 ν˜•μ‹
item_date = datetime.datetime.strptime(item[time_index], '%Y%m%d%H%M%S').date()
# print(item_date)
# νŠΉμ • λ΄‰λ§Œ 포함
# 곡휴일 주말 λΌλŠ” 경우λ₯Ό λŒ€λΉ„ν•΄ 졜근 item_date κΈ°μ€€μœΌλ‘œ μ‚ΌμŒ
if( len( _yesterday_min_list) == 0 and item_date <= expected_date ):
expected_date = item_date
if( item_date == expected_date) :
_yesterday_min_list.append(item)
# 1일전 μ΅œκ³ κ°€ 계산
# _yesterday_high_price = max([ item[high_price_index] for item in _yesterday_min_list], default = 99999999 )
# 1일전 μ‹œμž‘κ°€ 계산
if( len(_yesterday_min_list) > 0 ):
_yesterday_open_price = _yesterday_min_list[-1][min_open_price_index]
_yesterday_close_price = _yesterday_min_list[0][min_close_price_index]
_yesterday_low_price = min( [item[min_low_price_index] for item in _yesterday_min_list] )
_yesterday_amount += sum( item[min_amout_index] for item in _yesterday_min_list)
first_bunhal_maesu_date_time = datetime.datetime.strptime( first_bunhal_maesu_time_str, '%Y%m%d%H%M%S').date()
if( expected_date >= first_bunhal_maesu_date_time):
# μŠ€μœ™ μ’…λͺ©
# 1일전 λ‚ μ§œκ°€ 첫 맀수 λ‚ μ§œλ³΄λ‹€ ν¬κ±°λ‚˜ 같은 경우 1일전 μ €κ°€λ‘œ
stop_loss = _yesterday_low_price
# μŠ€μœ™ μ’…λͺ©μœΌλ‘œ 당일 λ“±λ½μœ¨ λ„ˆλ¬΄ 높은 경우 맀도
# if( updown_percentage > 20 ):
# stop_loss = 99999999
# pass
# stop_plus = 99999999
# μŒλ΄‰μ— κ±°λž˜λŸ‰μ΄ λ§ˆμ΄λ„ˆμŠ€λ©΄ μ†μ ˆ
# if( _today_amount < _yesterday_amount
# and _today_open_price < maesuHoga1 ):
# stop_loss = 99999999
if( self.current_condition_name == "μž₯ν›„λ°˜"):
pass
else:
# 당일 맀수 μ’…λͺ©
##########################################################################################################
last_bunhal_maesu_date_time = datetime.datetime.strptime(last_maeip_date_time_str, "%Y%m%d%H%M%S")
time_span = datetime.timedelta( minutes = 6 )
stop_plus = 9999999
# 맀수 ν•œμ§€ ? 뢄이 μ§€λ‚˜κ³  수읡이 λ‚˜μ§€ μ•ŠμœΌλ©΄ μ†μ ˆ
# if(
# last_bunhal_maesu_date_time + time_span < self.currentTime
# and maesuHoga1 < maeipga
# ) :
# stop_loss = 999999999
# if( self.current_condition_name == 'μž₯초반'):
# if( maesuHoga1 > maeipga * 1.033 ):
# stop_plus = 0
# if( maesuHoga1 < maeipga * 0.97 ):
# stop_loss = 99999999
# if( self.current_condition_name == 'νœ΄μ‹'):
# stop_loss = 99999999
# pass
if( self.isMinCandleExist(current_jango) == True ): # 뢄봉 정보 μ–»μ—ˆλŠ”μ§€ 확인
last_min_open_price = current_jango[key_minute_candle][1][min_open_price_index]
last_min_low_price = current_jango[key_minute_candle][1][min_low_price_index]
last_min_high_price = current_jango[key_minute_candle][1][min_high_price_index]
last_min_close_price = current_jango[key_minute_candle][1][min_current_price_index]
# timecut μ‹œκ°„ 이후 직전 1봉 μ €κ°€ 트레일링 μŠ€νƒ‘
# if(
# last_bunhal_maesu_date_time + time_span < self.currentTime
# and maesuHoga1 < last_min_low_price ):
# if( maesuHoga1 < maeipga ):
# stop_loss = 99999999
# else:
# stop_plus = 0
########################################################################################
isSell = False
printData = jongmok_code + ' {0:20} '.format(jongmok_name)
# μ†μ ˆ / 읡절 계산
# μ •λ¦¬λ‚˜, μ†μ ˆμ˜ 경우 μ‹œμž₯κ°€λ‘œ νŒ”κ³  읡절의 경우 λ³΄ν†΅κ°€λ‘œ 팜
isSijanga = False
maedo_type = ''
sell_amount = 0
sell_amount = jangosuryang
if( stop_loss == 0 ):
maedo_type = "(μž”κ³ μ˜€λ₯˜)"
printData += maedo_type
isSijanga = False
isSell = False
elif ( stop_loss == 88888888 ):
maedo_type = "(뢄할맀도)"
printData += maedo_type
isSijanga = False
isSell = True
if( jangosuryang > 1 ):
sell_amount = jangosuryang / 2
chegyeol_info = util.cur_date_time('%Y%m%d%H%M%S') + ":" + str(maesuHoga2) + ":" + str(sell_amount)
current_jango['뢄할맀도이λ ₯'] = chegyeol_info
# 20180410150510 νŒœμŠ€μ›°λ°”μ΄μ˜€ μ‹€μ‹œκ°„ 맀수 ν˜Έκ°€κ°€ 0으둜 λ‚˜μ˜€λŠ” 경우 있음
elif( stop_loss >= maesuHoga1 and maesuHoga1 > 0 ) :
maedo_type = "(μ†μ ˆμ΄λ‹€)"
printData += maedo_type
isSijanga = True
isSell = True
elif( stop_plus < maesuHoga1 ) :
if( totalAmount >= TOTAL_BUY_AMOUNT):
maedo_type = "(μ΅μ ˆμ΄λ‹€)"
printData += maedo_type
isSell = True
else:
maedo_type = "(μ΅μ ˆλ―Έλ‹¬)"
printData += maedo_type
isSell = True
printData += ' μ†μ ˆκ°€: {0:7}/'.format(str(stop_loss)) + \
' μ΄μ΅μ‹€ν˜„κ°€: {0:7}/'.format(str(stop_plus)) + \
' λ§€μž…κ°€: {0:7}/'.format(str(maeipga)) + \
' μž”κ³ μˆ˜λŸ‰: {0:7}'.format(str(jangosuryang)) +\
' λ§€μˆ˜ν˜Έκ°€1 {0:7}/'.format(str(maesuHoga1)) + \
' λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰1 {0:7}/'.format(str(maesuHogaAmount1)) + \
' λ§€μˆ˜ν˜Έκ°€2 {0:7}/'.format(str(maesuHoga2)) + \
' λ§€μˆ˜ν˜Έκ°€μˆ˜λŸ‰2 {0:7}/'.format(str(maesuHogaAmount2))
# if( isSell == True ):
# # processStop 의 경우 μ²΄κ²°λ λ•Œλ§ˆλ‹€ ν˜ΈμΆœλ˜λ―€λ‘œ 쀑볡 주문이 λ‚˜κ°€μ§€ μ•Šκ²Œ 함
# if( '맀도쀑' not in current_jango):
# current_jango['맀도쀑'] = maedo_type
# if( isSijanga == True ):
# result = self.sendOrder("sell_" + jongmok_code, kw_util.sendOrderScreenNo, objKiwoom.account_list[0], kw_util.dict_order["μ‹ κ·œλ§€λ„"],
# jongmok_code, sell_amount, 0 , kw_util.dict_order["μ‹œμž₯κ°€"], "")
# else:
# result = self.sendOrder("sell_" + jongmok_code, kw_util.sendOrderScreenNo, objKiwoom.account_list[0], kw_util.dict_order["μ‹ κ·œλ§€λ„"],
# jongmok_code, sell_amount, maesuHoga2 , kw_util.dict_order["지정가"], "")
# util.save_log(printData, '맀도', 'log')
# print("S " + jongmok_code + ' ' + str(result), sep= "")
# pass
# pass
# 체결데이터λ₯Ό 받은 μ‹œμ μ„ μ•Œλ €μ€€λ‹€.
# sGubun – 0:주문체결톡보, 1:μž”κ³ ν†΅λ³΄, 3:νŠΉμ΄μ‹ ν˜Έ
# sFidList – 데이터 ꡬ뢄은 β€˜;’ 이닀.
'''
_OnReceiveChejanData gubun: 1, itemCnt: 27, fidList: 9201;9001;917;916;302;10;930;931;932;933;945;946;950;951;27;28;307;8019;957;958;918;990;991;992;993;959;924
{'μ’…λͺ©μ½”λ“œ': 'A010050', 'λ‹ΉμΌμ‹€ν˜„μ†μ΅λ₯ (μœ κ°€)': '0.00', 'λŒ€μΆœμΌ': '00000000', 'λ‹ΉμΌμ‹€ν˜„μ†μ΅λ₯ (μ‹ μš©)': '0.00', '(μ΅œμš°μ„ )λ§€μˆ˜ν˜Έκ°€': '+805', 'λ‹ΉμΌμˆœλ§€μˆ˜μˆ˜λŸ‰': '5', 'μ΄λ§€μž…κ°€': '4043',
'당일총맀도손일': '0', '만기일': '00000000', 'μ‹ μš©κΈˆμ•‘': '0', 'λ‹ΉμΌμ‹€ν˜„μ†μ΅(μ‹ μš©)': '0', 'ν˜„μž¬κ°€': '+806', 'κΈ°μ€€κ°€': '802', 'κ³„μ’Œλ²ˆν˜Έ': ', 'λ³΄μœ μˆ˜λŸ‰': '5',
'예수금': '0', 'μ£Όλ¬Έκ°€λŠ₯μˆ˜λŸ‰': '5', 'μ’…λͺ©λͺ…': 'μš°λ¦¬μ’…κΈˆ ', 'μ†μ΅μœ¨': '0.00', 'λ‹ΉμΌμ‹€ν˜„μ†μ΅(μœ κ°€)': '0', 'λ‹΄λ³΄λŒ€μΆœμˆ˜λŸ‰': '0', '924': '0',
'λ§€μž…λ‹¨κ°€': '809', 'μ‹ μš©κ΅¬λΆ„': '00', '맀도/λ§€μˆ˜κ΅¬λΆ„': '2', '(μ΅œμš°μ„ )λ§€λ„ν˜Έκ°€': '+806', 'μ‹ μš©μ΄μž': '0'}
'''
def _OnReceiveChejanData(self, gubun, itemCnt, fidList):
# print(util.whoami() + 'gubun: {}, itemCnt: {}, fidList: {}'
# .format(gubun, itemCnt, fidList))
if( gubun == "1"): # μž”κ³  정보
# μž”κ³  μ •λ³΄μ—μ„œλŠ” 맀도/맀수 ꡬ뢄이 λ˜μ§€ μ•ŠμŒ
jongmok_code = self.getChejanData(kw_util.name_fid['μ’…λͺ©μ½”λ“œ'])[1:]
boyou_suryang = int(self.getChejanData(kw_util.name_fid['λ³΄μœ μˆ˜λŸ‰']))
jumun_ganeung_suryang = int(self.getChejanData(kw_util.name_fid['μ£Όλ¬Έκ°€λŠ₯μˆ˜λŸ‰']))
maeip_danga = int(self.getChejanData(kw_util.name_fid['λ§€μž…λ‹¨κ°€']))
jongmok_name= self.getChejanData(kw_util.name_fid['μ’…λͺ©λͺ…']).strip()
current_price = abs(int(self.getChejanData(kw_util.name_fid['ν˜„μž¬κ°€'])))
current_amount = abs(int(self.getChejanData(kw_util.name_fid['λ‹ΉμΌμˆœλ§€μˆ˜μˆ˜λŸ‰'])))
#미체결 μˆ˜λŸ‰μ΄ μžˆλŠ” 경우 μž”κ³  정보 μ €μž₯ν•˜μ§€ μ•Šλ„λ‘ 함
if( jongmok_code in self.michegyeolInfo):
if( self.michegyeolInfo[jongmok_code]['λ―Έμ²΄κ²°μˆ˜λŸ‰'] ):
return
else:
# 미체결 μˆ˜λŸ‰μ΄ μ—†μœΌλ―€λ‘œ 정보 μ‚­μ œ
del ( self.michegyeolInfo[jongmok_code] )
if( boyou_suryang == 0 ):
# 보유 μˆ˜λŸ‰μ΄ 0 인 경우 맀도 μˆ˜ν–‰ν•œ κ²ƒμž„
self.jangoInfo.pop(jongmok_code)
self.removeConditionOccurList(jongmok_code)
else:
# 보유 μˆ˜λŸ‰μ΄ λŠ˜μ—ˆλ‹€λŠ” 것은 λ§€μˆ˜μˆ˜ν–‰ν–ˆμœΌλ©° 이에 TR μš”μ²­μ— λŒ€ν•œ λŒ€κΈ° μ‹œκ°„ ν•„μš”
self.sigWaitTr.emit()
# QTimer.singleShot(TR_TIME_LIMIT_MS, self.sigWaitTr)
# μ•„λž˜ μž”κ³  μ •λ³΄μ˜ 경우 TR:κ³„μ’Œν‰κ°€μž”κ³ λ‚΄μ—­μš”μ²­ ν•„λ“œμ™€ μΌμΉ˜ν•˜κ²Œ λ§Œλ“€μ–΄μ•Ό 함
current_jango = {}
current_jango['λ³΄μœ μˆ˜λŸ‰'] = boyou_suryang
current_jango['맀맀가λŠ₯μˆ˜λŸ‰'] = jumun_ganeung_suryang # TR μž”κ³ μ—μ„œ 맀맀가λŠ₯ μˆ˜λŸ‰ μ΄λž€ μ΄λ¦„μœΌλ‘œ μ‚¬μš©λ˜λ―€λ‘œ
current_jango['λ§€μž…κ°€'] = maeip_danga
current_jango['μ’…λͺ©λ²ˆν˜Έ'] = jongmok_code
current_jango['μ’…λͺ©λͺ…'] = jongmok_name.strip()
current_jango['μ—…μ’…'] = self.getMasterStockInfo(jongmok_code)
chegyeol_info = util.cur_date_time('%Y%m%d%H%M%S') + ":" + str(current_price) + ":" + str(current_amount)
if( jongmok_code not in self.jangoInfo):
current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'] = [chegyeol_info]
self.jangoInfo[jongmok_code] = current_jango
else:
# λ§€μˆ˜κ°€ λΆ„ν• λ‘œ λ˜λŠ” κ²½μš°μ—λŠ” λΆ„ν•  맀수 이λ ₯ μΆ”κ°€ μ•ˆν•¨
last_chegyeol_info = self.jangoInfo[jongmok_code]['λΆ„ν• λ§€μˆ˜μ΄λ ₯'][-1]
last_price = int(last_chegyeol_info.split(':')[1])
if( last_price != current_price ):
chegyeol_info_list = self.jangoInfo[jongmok_code]['λΆ„ν• λ§€μˆ˜μ΄λ ₯']
chegyeol_info_list.append( chegyeol_info )
current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'] = chegyeol_info_list
self.jangoInfo[jongmok_code].update(current_jango)
self.makeJangoInfoFile()
pass
elif ( gubun == "0"):
jumun_sangtae = self.getChejanData(kw_util.name_fid['μ£Όλ¬Έμƒνƒœ'])
jongmok_code = self.getChejanData(kw_util.name_fid['μ’…λͺ©μ½”λ“œ'])[1:]
michegyeol_suryang = int(self.getChejanData(kw_util.name_fid['λ―Έμ²΄κ²°μˆ˜λŸ‰']))
# μ£Όλ¬Έ μƒνƒœ
# 맀수 μ‹œ μ ‘μˆ˜(gubun-0) - 체결(gubun-0) - μž”κ³ (gubun-1)
# 맀도 μ‹œ μ ‘μˆ˜(gubun-0) - μž”κ³ (gubun-1) - 체결(gubun-0) - μž”κ³ (gubun-1) μˆœμž„
# 미체결 μˆ˜λŸ‰ 정보λ₯Ό μž…λ ₯ν•˜μ—¬ μž”κ³  정보 μ²˜λ¦¬μ‹œ 미체결 μˆ˜λŸ‰ μžˆλŠ” κ²½μš°μ— λŒ€ν•œ 처리λ₯Ό ν•˜λ„λ‘ 함
if( jongmok_code not in self.michegyeolInfo):
self.michegyeolInfo[jongmok_code] = {}
self.michegyeolInfo[jongmok_code]['λ―Έμ²΄κ²°μˆ˜λŸ‰'] = michegyeol_suryang
if( jumun_sangtae == "체결"):
self.makeChegyeolInfo(jongmok_code, fidList)
self.makeChegyeolInfoFile()
pass
pass
def makeChegyeolInfoFile(self):
# print(util.whoami())
with open(CHEGYEOL_INFO_FILE_PATH, 'w', encoding = 'utf8' ) as f:
f.write(json.dumps(self.chegyeolInfo, ensure_ascii= False, indent= 2, sort_keys = True ))
pass
# μ„œλ²„μ—μ„œ 얻을 수 μ—†λŠ” μΆ”κ°€ 정보 μ €μž₯
# 첫 μž”κ³  정보 μš”μ²­μ‹œ 호좜됨
# 맀수, 맀도후 체결 μ •λ³΄λ‘œ μž”κ³  정보 μ˜¬λ•Œ 호좜됨
def makeEtcJangoInfo(self, jongmok_code):
if( jongmok_code not in self.jangoInfo):
return
current_jango = self.jangoInfo[jongmok_code]
# λΆ„ν• λ§€μˆ˜ 이λ ₯ 데이터 νŒŒμΌλ‘œλΆ€ν„° μ½μ–΄μ˜€κ³  νŒŒμΌλ‘œλΆ€ν„°λ„ μ—†μœΌλ©΄ default κ°’ μž…λ ₯
if( 'λΆ„ν• λ§€μˆ˜μ΄λ ₯' not in current_jango ):
current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'] = ['29991212091234:2:1']
if( jongmok_code in self.jangoInfoFromFile):
if( 'λΆ„ν• λ§€μˆ˜μ΄λ ₯' in self.jangoInfoFromFile[jongmok_code] ):
current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯'] = self.jangoInfoFromFile[jongmok_code].get('λΆ„ν• λ§€μˆ˜μ΄λ ₯', [])
# 총 맀수 갯수 κ²Œμ‚°
bunhal_maesu_list = current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯']
maesu_count = len(bunhal_maesu_list)
# μ†μ ˆ/μ΅μ ˆκ°€ 퍼센티지 계산
stop_loss_percent = STOP_LOSS_PER_MAESU_COUNT[maesu_count -1]
stop_plus_percent = STOP_PLUS_PER_MAESU_COUNT[maesu_count -1]
maeip_price = current_jango['λ§€μž…κ°€']
last_chegyeol_info = bunhal_maesu_list[-1]
last_maeip_price = int(last_chegyeol_info.split(':')[1]) #λ‚ μ§œ:가격:μˆ˜λŸ‰
last_maeip_time = last_chegyeol_info.split(':')[0]
if( last_maeip_price == 0 ):
# λΆ„ν• λ§€μˆ˜ 정보 λˆ„λ½λ˜μ–΄ 기본으둜 μ„ΈνŒ…μ‹œλ₯Ό μœ„ν•œ λŒ€λΉ„
last_maeip_price = 99999999
# κΈ°λ³Έ μ†μ ˆκ°€ μΈ‘μ •
gibon_stoploss = round( maeip_price * (1 + (stop_loss_percent + SLIPPAGE) / 100) , 2 )
print("μ’…λͺ©μ΄λ¦„:{}, κΈ°λ³Έμ†μ ˆ:{}".format(self.getMasterCodeName(jongmok_code), gibon_stoploss))
###############################################################################################
current_jango['μ†μ ˆκ°€'] = gibon_stoploss
current_jango['μ΄μ΅μ‹€ν˜„κ°€'] = round( maeip_price * (1 + ((stop_plus_percent + SLIPPAGE)/100) ) , 2)
# ? 일 λ™μ•ˆ μΆ”κ°€ 맀수 κΈˆμ§€ 쑰치
base_time = datetime.datetime.strptime(last_maeip_time, '%Y%m%d%H%M%S')
# μΌκΈ°μ€€μœΌλ‘œλ§Œ ν•˜κΈ° μœ„ν•΄ μ‹œλΆ„μ΄ˆ 정보 제거
from_date = copy.deepcopy(base_time)
target_date = util.date_by_adding_business_days(from_date, BUNHAL_MAESU_PROHIBIT_DAYS )
saved_date = datetime.date(year = target_date.year,month = target_date.month, day = target_date.day)
current_date = datetime.date(year = self.currentTime.year, month = self.currentTime.month, day = self.currentTime.day )
if( saved_date > current_date):
if( jongmok_code not in self.prohibitCodeList):
self.prohibitCodeList.append(jongmok_code)
self.jangoInfo[jongmok_code].update(current_jango)
pass
@pyqtSlot()
def makeJangoInfoFile(self):
print(util.whoami())
# 기타 정보 μ—…λ°μ΄νŠΈ
for jongmok_code in self.jangoInfo.keys():
self.makeEtcJangoInfo(jongmok_code)
temp = copy.deepcopy(self.jangoInfo)
# λΆˆν•„μš” ν•„λ“œ 제거
for jongmok_code, contents in temp.items():
for key in self.jango_remove_keys:
if( key in contents):
del contents[key]
with open(JANGO_INFO_FILE_PATH, 'w', encoding = 'utf8' ) as f:
f.write(json.dumps(temp, ensure_ascii= False, indent= 2, sort_keys = True ))
pass
# self.makeInterestedStocksFile()
@pyqtSlot()
def makeInterestedStocksFile(self):
print(util.whoami())
temp = copy.deepcopy(self.conditionOccurList)
# λΆˆν•„μš” ν•„λ“œ 제거
# condition list
for item in temp:
for key in self.jango_remove_keys:
if( key in item):
del item[key]
with open(INTERESTED_STOCKS_FILE_PATH, 'w', encoding = 'utf8' ) as f:
f.write(json.dumps(temp, ensure_ascii= False, indent= 2, sort_keys = True ))
pass
def makeChegyeolInfo(self, jongmok_code, fidList):
fids = fidList.split(";")
printData = ""
info = []
# 미체결 μˆ˜λŸ‰μ΄ 0 이 μ•„λ‹Œ 경우 λ‹€μ‹œ 체결 정보가 올라 μ˜€λ―€λ‘œ 0인경우 처리 μ•ˆν•¨
michegyeol_suryung = int(self.getChejanData(kw_util.name_fid['λ―Έμ²΄κ²°μˆ˜λŸ‰']).strip())
if( michegyeol_suryung != 0 ):
return
nFid = kw_util.name_fid['λ§€λ„λ§€μˆ˜κ΅¬λΆ„']
result = self.getChejanData(nFid).strip()
maedo_maesu_gubun = '맀도' if result == '1' else '맀수'
# 첫 λ§€μˆ˜μ‹œλŠ” μž”κ³  정보가 없을 수 μžˆμœΌλ―€λ‘œ
current_jango = self.jangoInfo.get(jongmok_code, {})
bunhal_maesu_list = current_jango.get('λΆ„ν• λ§€μˆ˜μ΄λ ₯', [])
#################################################################################################
# μ‚¬μš©μž μ •μ˜ 컬럼 수읡과 수읡율 ν•„λ“œ 채움
if( maedo_maesu_gubun == '맀도'):
# 체결가λ₯Ό 톡해 수읡율 ν•„λ“œ μ—…λ°μ΄νŠΈ
current_price = int(self.getChejanData(kw_util.name_fid['체결가']).strip())
self.calculateSuik(jongmok_code, current_price)
# λ§€λ„μ‹œ μ²΄κ²°μ •λ³΄λŠ” 수읡율 ν•„λ“œκ°€ 쑴재
profit = current_jango.get('수읡', '0')
profit_percent = current_jango.get('수읡율', '0' )
maesu_count = len(bunhal_maesu_list)
maedo_type = current_jango.get('맀도쀑', '')
if( maedo_type == ''):
maedo_type = '(μˆ˜λ™λ§€λ„)'
info.append('{0:>10}'.format(profit_percent))
info.append('{0:>10}'.format(profit))
info.append(' 맀수횟수: {0:>1} '.format(maesu_count))
info.append(' {0} '.format(maedo_type))
pass
elif( maedo_maesu_gubun == '맀수') :
# λ§€μˆ˜μ‹œ μ²΄κ²°μ •λ³΄λŠ” 수읡율 / 수읡 ν•„λ“œκ°€
info.append('{0:>10}'.format('0'))
info.append('{0:>10}'.format('0'))
# μ²΄κ²°μ‹œλŠ” 맀수 횟수 정보가 μ—…λ°μ΄νŠΈ λ˜μ§€ μ•Šμ•˜κΈ° λ•Œλ¬Έμ— +1 ν•΄μ€Œ
# μ²«λ§€μˆ˜μ— λŒ€ν•œ μ²˜λ¦¬λ„ 함
maesu_count = len(bunhal_maesu_list)
info.append(' 맀수횟수: {0:>1} '.format(maesu_count + 1))
info.append(' {0} '.format('(λ‹¨μˆœλ§€μˆ˜)'))
#################################################################################################
# kiwoom api 체결 정보 ν•„λ“œ
for col_name in kw_util.dict_jusik["체결정보"]:
nFid = None
result = ""
if( col_name not in kw_util.name_fid ):
continue
nFid = kw_util.name_fid[col_name]
if( str(nFid) in fids):
result = self.getChejanData(nFid).strip()
if( col_name == 'μ’…λͺ©μ½”λ“œ'):
result = result[1:]
if( col_name == '체결가' ):
result = '{0:>10}'.format(result)
if( col_name == 'μ²΄κ²°λŸ‰' or col_name == 'λ―Έμ²΄κ²°μˆ˜λŸ‰'):
result = '{0:>7}'.format(result)
info.append(' {} '.format(result))
printData += col_name + ": " + result + ", "
current_date = self.currentTime.date().strftime('%y%m%d')
if( current_date not in self.chegyeolInfo) :
self.chegyeolInfo[current_date] = []
#################################################################################################
# λ§€λ„μ‹œ 맀수 이λ ₯ 정보 ν•„λ“œ
if( maedo_maesu_gubun == '맀도'):
info.append(' | '.join(current_jango['λΆ„ν• λ§€μˆ˜μ΄λ ₯']))
pass
self.chegyeolInfo[current_date].append('|'.join(info))
util.save_log(printData, "*체결정보", folder= "log")
pass
# λ‘œμ»¬μ— μ‚¬μš©μžμ‘°κ±΄μ‹ μ €μž₯ 성곡여뢀 응닡 이벀트
# 0:(μ‹€νŒ¨) 1:(성곡)
def _OnReceiveConditionVer(self, ret, msg):
print(util.whoami() + 'ret: {}, msg: {}'
.format(ret, msg))
if ret == 1:
self.sigGetConditionCplt.emit()
# 쑰건검색 μ‘°νšŒμ‘λ‹΅μœΌλ‘œ μ’…λͺ©λ¦¬μŠ€νŠΈλ₯Ό κ΅¬λΆ„μž(β€œ;”)둜 λΆ™μ–΄μ„œ λ°›λŠ” μ‹œμ .
# LPCTSTR sScrNo : μ’…λͺ©μ½”λ“œ
# LPCTSTR strCodeList : μ’…λͺ©λ¦¬μŠ€νŠΈ(β€œ;β€λ‘œ ꡬ뢄)
# LPCTSTR strConditionName : 쑰건λͺ…
# int nIndex : 쑰건λͺ… 인덱슀
# int nNext : μ—°μ†μ‘°νšŒ(2:μ—°μ†μ‘°νšŒ, 0:μ—°μ†μ‘°νšŒμ—†μŒ)
def _OnReceiveTrCondition(self, scrNo, codeList, conditionName, index, next):
# print(util.whoami() + 'scrNo: {}, codeList: {}, conditionName: {} '
# 'index: {}, next: {}'
# .format(scrNo, codeList, conditionName, index, next ))
codes = codeList.split(';')[:-1]
# λ§ˆμ§€λ§‰ split κ²°κ³Ό None μ΄λ―€λ‘œ μ‚­μ œ
for code in codes:
print('condition occur list add code: {} '.format(code) + self.getMasterCodeName(code))
self.addConditionOccurList(code)
# νŽΈμž…, μ΄νƒˆ μ’…λͺ©μ΄ μ‹€μ‹œκ°„μœΌλ‘œ λ“€μ–΄μ˜΅λ‹ˆλ‹€.
# strCode : μ’…λͺ©μ½”λ“œ
# strType : νŽΈμž…(β€œI”), μ΄νƒˆ(β€œD”)
# streonditionName : 쑰건λͺ…
# strConditionIndex : 쑰건λͺ… 인덱슀
def _OnReceiveRealCondition(self, code, type, conditionName, conditionIndex):
print(util.whoami() + 'code: {}, μ’…λͺ©μ΄λ¦„: {}, type: {}, conditionName: {}, conditionIndex: {}'
.format(code, self.getMasterCodeName(code), type, conditionName, conditionIndex ))
if type == 'I':
self.addConditionOccurList(code) # 쑰건 λ°œμƒν•œ 경우 ν•΄λ‹Ή λ‚΄μš© list 에 μΆ”κ°€
else:
self.conditionRevemoList.append(code)
pass
def addConditionOccurList(self, jongmok_code):
#λ°œμƒμ‹œκ°„, μ’…λͺ©μ½”λ“œ, μ’…λͺ©λͺ…
jongmok_name = self.getMasterCodeName(jongmok_code)
ret_vals = []
# 쀑볡 제거
for item_dict in self.conditionOccurList:
if( jongmok_code == item_dict['μ’…λͺ©μ½”λ“œ'] ):
ret_vals.append(True)
if( ret_vals.count(True) ):
pass
else:
self.conditionOccurList.append( {'μ’…λͺ©λͺ…': jongmok_name, 'μ’…λͺ©μ½”λ“œ': jongmok_code} )
self.sigConditionOccur.emit()
pass
def removeConditionOccurList(self, jongmok_code):
for item_dict in self.conditionOccurList:
if( item_dict['μ’…λͺ©μ½”λ“œ'] == jongmok_code ):
self.conditionOccurList.remove(item_dict)
break
pass
def getConditionOccurList(self):
if( len(self.conditionOccurList ) ):
return self.conditionOccurList[0]
else:
return None
pass
def getCodeListConditionOccurList(self):
items = []
for item_dict in self.conditionOccurList:
items.append(item_dict['μ’…λͺ©μ½”λ“œ'])
return items
def setHogaConditionOccurList(self, jongmok_code, col_name, value):
for index, item_dict in enumerate(self.conditionOccurList):
if( item_dict['μ’…λͺ©μ½”λ“œ'] == jongmok_code ):
item_dict[col_name] = value
# λ‹€μŒ codition list λ₯Ό κ°μ‹œ ν•˜κΈ° μœ„ν•΄ μ’…λͺ© μ„žκΈ°
def shuffleConditionOccurList(self):
jongmok_info_dict = self.getConditionOccurList()
jongmok_code = jongmok_info_dict['μ’…λͺ©μ½”λ“œ']
self.removeConditionOccurList(jongmok_code)
self.conditionOccurList.append(jongmok_info_dict)
# μ‹€μ‹œκ°„ 주식 정보 μš”μ²­ μš”μ²­λ¦¬μŠ€νŠΈ κ°±μ‹ 
# WARNING: μ‹€μ‹œκ°„ μš”μ²­λ„ TR 처럼 μ΄ˆλ‹Ή 횟수 μ œν•œμ΄ μžˆμœΌλ―€λ‘œ 잘 μ‚¬μš©ν•΄μ•Όν•¨
def refreshRealRequest(self):
# λ²„κ·Έλ‘œ λͺ¨λ‘ μ§€μš°κ³  μƒˆλ‘œ λ“±λ‘ν•˜κ²Œ 함
# print(util.whoami() )
self.setRealRemove("ALL", "ALL")
codeList = []
# 보유 μž”κ³  μ‹€μ‹œκ°„ 정보 μ–»κΈ° μœ„ν•΄ μΆ”κ°€
for code in self.jangoInfo.keys():
if( code not in codeList):
codeList.append(code)
condition_list = self.getCodeListConditionOccurList()
for code in condition_list:
if( code not in codeList):
codeList.append(code)
if( len(codeList) == 0 ):
# μ’…λͺ© 미보유둜 μ‹€μ‹œκ°„ 체결 μš”μ²­ ν• κ²Œ μ—†λŠ” 경우 μ½”μŠ€λ‹₯ μ½”μŠ€ν”Ό μ‹€μ‹œκ°„ 체결가가 μ˜¬λΌμ˜€μ§€ μ•ŠμœΌλ―€λ‘œ μž„μ‹œλ‘œ ν•˜λ‚˜ 등둝
codeList.append('044180')
else:
for code in codeList:
if ( code not in EXCEPTION_LIST):
self.addConditionOccurList(code)
# μ‹€μ‹œκ°„ ν˜Έκ°€ 정보 μš”μ²­ "0" 은 이전거 μ œμ™Έ ν•˜κ³  μƒˆλ‘œ μš”μ²­
if( len(codeList) ):
# WARNING: 주식 μ‹œμ„Έ μ‹€μ‹œκ°„μ€ λ¦¬ν„΄λ˜μ§€ μ•ŠμŒ!
# tmp = self.setRealReg(kw_util.sendRealRegSiseSrcNo, ';'.join(codeList), kw_util.type_fidset['μ£Όμ‹μ‹œμ„Έ'], "0")
tmp = self.setRealReg(kw_util.sendRealRegHogaScrNo, ';'.join(codeList), kw_util.type_fidset['μ£Όμ‹ν˜Έκ°€μž”λŸ‰'], "0")
tmp = self.setRealReg(kw_util.sendRealRegChegyeolScrNo, ';'.join(codeList), kw_util.type_fidset['주식체결'], "0")
tmp = self.setRealReg(kw_util.sendRealRegUpjongScrNo, '001;101', kw_util.type_fidset['μ—…μ’…μ§€μˆ˜'], "0")
def make_excel(self, file_path, data_dict):
result = False
result = os.path.isfile(file_path)
if( result == False):
with open( CHEGYEOL_INFO_EXCEL_FILE_PATH, 'w', encoding = 'utf8' ) as f:
f.write('')
# excel open
wb = xw.Book(file_path)
sheet_names = [sheet.name for sheet in wb.sheets]
insert_sheet_names = []
# print(sheet_names)
for key, value in data_dict.items():
# sheet name 이 쑴재 μ•ˆν•˜λ©΄ sheet add
sheet_name = key[0:4]
if( sheet_name not in sheet_names ):
if( sheet_name not in insert_sheet_names ):
insert_sheet_names.append(sheet_name)
for insert_sheet in insert_sheet_names:
wb.sheets.add(name = insert_sheet)
# sheet name 은 YYMM ν˜•μ‹
sheet_names = [sheet.name for sheet in wb.sheets]
for sheet_name in sheet_names:
# key 값이 match λ˜λŠ”κ²ƒμ„ 찾음
row_count = 1
excel_row_string = 'A{}'
for sorted_key in sorted(data_dict):
input_data_sheet_name = sorted_key[0:4]
if( input_data_sheet_name == sheet_name ):
wb.sheets[sheet_name].activate()
xw.Range(excel_row_string.format(row_count)).value = [ sorted_key, '-' * 156 ]
row_count += 1
for line in data_dict[sorted_key]:
items = [ item.strip() for item in line.split('|') ]
# 빈칸 λ‘κ°œ μΆ”κ°€
items.insert(0, '')
items.insert(0, '')
wb.sheets[sheet_name].activate()
xw.Range(excel_row_string.format(row_count)).value = items
row_count += 1
# save
wb.save()
wb.app.quit()
# method
# 둜그인
# 0 - 성곡, μŒμˆ˜κ°’μ€ μ‹€νŒ¨
# λ‹¨μˆœ API 호좜이 λ˜μ—ˆλŠλƒ μ•ˆλ˜μ—ˆλŠλƒλ§Œ 확인 κ°€λŠ₯
@pyqtSlot(result=int)
def commConnect(self):
return self.ocx.dynamicCall("CommConnect()")
# 둜그인 μƒνƒœ 확인
# 0:λ―Έμ—°κ²°, 1:μ—°κ²°μ™„λ£Œ, κ·Έμ™ΈλŠ” μ—λŸ¬
@pyqtSlot(result=int)
def getConnectState(self):
return self.ocx.dynamicCall("GetConnectState()")
# 둜그 아웃
@pyqtSlot()
def commTerminate(self):
self.ocx.dynamicCall("CommTerminate()")
# λ‘œκ·ΈμΈν•œ μ‚¬μš©μž 정보λ₯Ό λ°˜ν™˜ν•œλ‹€.
# β€œACCOUNT_CNT” – 전체 κ³„μ’Œ 개수λ₯Ό λ°˜ν™˜ν•œλ‹€.
# "ACCNO" – 전체 κ³„μ’Œλ₯Ό λ°˜ν™˜ν•œλ‹€. κ³„μ’Œλ³„ ꡬ뢄은 β€˜;’이닀.
# β€œUSER_ID” - μ‚¬μš©μž IDλ₯Ό λ°˜ν™˜ν•œλ‹€.
# β€œUSER_NAME” – μ‚¬μš©μžλͺ…을 λ°˜ν™˜ν•œλ‹€.
# β€œKEY_BSECGB” – ν‚€λ³΄λ“œλ³΄μ•ˆ 해지여뢀. 0:정상, 1:해지
# β€œFIREW_SECGB” – λ°©ν™”λ²½ μ„€μ • μ—¬λΆ€. 0:λ―Έμ„€μ •, 1:μ„€μ •, 2:해지
@pyqtSlot(str, result=str)
def getLoginInfo(self, tag):
return self.ocx.dynamicCall("GetLoginInfo(QString)", [tag])
# Tran μž…λ ₯ 값을 μ„œλ²„ν†΅μ‹  전에 μž…λ ₯값일 μ €μž₯ν•œλ‹€.
@pyqtSlot(str, str)
def setInputValue(self, id, value):
self.ocx.dynamicCall("SetInputValue(QString, QString)", id, value)
@pyqtSlot(str, result=str)
def getCodeListByMarket(self, sMarket):
return self.ocx.dynamicCall("GetCodeListByMarket(QString)", sMarket)
# 톡신 데이터λ₯Ό μ†‘μ‹ ν•œλ‹€.
# 0이면 정상
# OP_ERR_SISE_OVERFLOW – κ³Όλ„ν•œ μ‹œμ„Έμ‘°νšŒλ‘œ μΈν•œ ν†΅μ‹ λΆˆκ°€
# OP_ERR_RQ_STRUCT_FAIL – μž…λ ₯ ꡬ쑰체 생성 μ‹€νŒ¨
# OP_ERR_RQ_STRING_FAIL – μš”μ²­μ „λ¬Έ μž‘μ„± μ‹€νŒ¨
# OP_ERR_NONE – μ •μƒμ²˜λ¦¬
@pyqtSlot(str, str, int, str, result=int)
def commRqData(self, rQName, trCode, prevNext, screenNo):
return self.ocx.dynamicCall("CommRqData(QString, QString, int, QString)", rQName, trCode, prevNext, screenNo)
# μˆ˜μ‹  받은 λ°μ΄ν„°μ˜ 반볡 개수λ₯Ό λ°˜ν™˜ν•œλ‹€.
@pyqtSlot(str, str, result=int)
def getRepeatCnt(self, trCode, recordName):
return self.ocx.dynamicCall("GetRepeatCnt(QString, QString)", trCode, recordName)
# Tran 데이터, μ‹€μ‹œκ°„ 데이터, μ²΄κ²°μž”κ³  데이터λ₯Ό λ°˜ν™˜ν•œλ‹€.
# 1. Tran 데이터
# 2. μ‹€μ‹œκ°„ 데이터
# 3. 체결 데이터
# 1. Tran 데이터
# sJongmokCode : Tranλͺ…
# sRealType : μ‚¬μš©μ•ˆν•¨
# sFieldName : λ ˆμ½”λ“œλͺ…
# nIndex : 반볡인덱슀
# sInnerFieldName: μ•„μ΄ν…œλͺ…
# 2. μ‹€μ‹œκ°„ 데이터
# sJongmokCode : Key Code
# sRealType : Real Type
# sFieldName : Item Index (FID)
# nIndex : μ‚¬μš©μ•ˆν•¨
# sInnerFieldName:μ‚¬μš©μ•ˆν•¨
# 3. 체결 데이터
# sJongmokCode : 체결ꡬ뢄
# sRealType : β€œ-1”
# sFieldName : μ‚¬μš©μ•ˆν•¨
# nIndex : ItemIndex
# sInnerFieldName:μ‚¬μš©μ•ˆν•¨
@pyqtSlot(str, str, str, int, str, result=str)
def commGetData(self, jongmok_code, realType, fieldName, index, innerFieldName):
return self.ocx.dynamicCall("CommGetData(QString, QString, QString, int, QString)", jongmok_code, realType, fieldName, index, innerFieldName).strip()
# strRealType – μ‹€μ‹œκ°„ ꡬ뢄
# nFid – μ‹€μ‹œκ°„ μ•„μ΄ν…œ
# Ex) ν˜„μž¬κ°€μΆœλ ₯ - openApi.GetCommRealData(β€œμ£Όμ‹μ‹œμ„Έβ€, 10);
# μ°Έκ³ )μ‹€μ‹œκ°„ ν˜„μž¬κ°€λŠ” μ£Όμ‹μ‹œμ„Έ, 주식체결 λ“± λ‹€λ₯Έ μ‹€μ‹œκ°„νƒ€μž…(RealType)μœΌλ‘œλ„ μˆ˜μ‹ κ°€λŠ₯
@pyqtSlot(str, int, result=str)
def getCommRealData(self, realType, fid):
return self.ocx.dynamicCall("GetCommRealData(QString, int)", realType, fid).strip()
# 주식 주문을 μ„œλ²„λ‘œ μ „μ†‘ν•œλ‹€.
# sRQName - μ‚¬μš©μž ꡬ뢄 μš”μ²­ λͺ…
# sScreenNo - ν™”λ©΄λ²ˆν˜Έ[4]
# sAccNo - κ³„μ’Œλ²ˆν˜Έ[10]
# nOrderType - μ£Όλ¬Έμœ ν˜• (1:μ‹ κ·œλ§€μˆ˜, 2:μ‹ κ·œλ§€λ„, 3:λ§€μˆ˜μ·¨μ†Œ, 4:λ§€λ„μ·¨μ†Œ, 5:λ§€μˆ˜μ •μ •, 6:맀도정정)
# sCode, - 주식쒅λͺ©μ½”λ“œ
# nQty – μ£Όλ¬Έμˆ˜λŸ‰
# nPrice – 주문단가
# sHogaGb - κ±°λž˜κ΅¬λΆ„
# sHogaGb – 00:지정가, 03:μ‹œμž₯κ°€, 05:쑰건뢀지정가, 06:μ΅œμœ λ¦¬μ§€μ •κ°€, 07:μ΅œμš°μ„ μ§€μ •κ°€, 10:지정가IOC, 13:μ‹œμž₯κ°€IOC, 16:졜유리IOC, 20:지정가FOK, 23:μ‹œμž₯κ°€FOK, 26:졜유리FOK, 61:μž₯μ „μ‹œκ°„μ™Έμ’…κ°€, 62:μ‹œκ°„μ™Έλ‹¨μΌκ°€, 81:μž₯ν›„μ‹œκ°„μ™Έμ’…κ°€
# β€» μ‹œμž₯κ°€, μ΅œμœ λ¦¬μ§€μ •κ°€, μ΅œμš°μ„ μ§€μ •κ°€, μ‹œμž₯κ°€IOC, 졜유리IOC, μ‹œμž₯κ°€FOK, 졜유리FOK, μž₯μ „μ‹œκ°„μ™Έ, μž₯ν›„μ‹œκ°„μ™Έ μ£Όλ¬Έμ‹œ 주문가격을 μž…λ ₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
# ex)
# 지정가 맀수 - openApi.SendOrder(β€œRQ_1”, β€œ0101”, β€œ5015123410”, 1, β€œ000660”, 10, 48500, β€œ00”, β€œβ€);
# μ‹œμž₯κ°€ 맀수 - openApi.SendOrder(β€œRQ_1”, β€œ0101”, β€œ5015123410”, 1, β€œ000660”, 10, 0, β€œ03”, β€œβ€);
# 맀수 μ •μ • - openApi.SendOrder(β€œRQ_1”,β€œ0101”, β€œ5015123410”, 5, β€œ000660”, 10, 49500, β€œ00”, β€œ1”);
# 맀수 μ·¨μ†Œ - openApi.SendOrder(β€œRQ_1”, β€œ0101”, β€œ5015123410”, 3, β€œ000660”, 10, β€œ00”, β€œ2”);
# sOrgOrderNo – μ›μ£Όλ¬Έλ²ˆν˜Έ
@pyqtSlot(str, str, str, int, str, int, int, str, str, result=int)
def sendOrder(self, rQName, screenNo, accNo, orderType, code, qty, price, hogaGb, orgOrderNo):
return self.ocx.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)", [rQName, screenNo, accNo, orderType, code, qty, price, hogaGb, orgOrderNo])
# μ²΄κ²°μž”κ³  데이터λ₯Ό λ°˜ν™˜ν•œλ‹€.
@pyqtSlot(int, result=str)
def getChejanData(self, fid):
return self.ocx.dynamicCall("GetChejanData(int)", fid)
# μ„œλ²„μ— μ €μž₯된 μ‚¬μš©μž 쑰건식을 κ°€μ Έμ˜¨λ‹€.
@pyqtSlot(result=int)
def getConditionLoad(self):
return self.ocx.dynamicCall("GetConditionLoad()")
# 쑰건검색 쑰건λͺ… 리슀트λ₯Ό λ°›μ•„μ˜¨λ‹€.
# 쑰건λͺ… 리슀트(인덱슀^쑰건λͺ…)
# 쑰건λͺ… 리슀트λ₯Ό ꡬ뢄(β€œ;”)ν•˜μ—¬ λ°›μ•„μ˜¨λ‹€
@pyqtSlot(result=str)
def getConditionNameList(self):
return self.ocx.dynamicCall("GetConditionNameList()")
# 쑰건검색 μ’…λͺ©μ‘°νšŒTRμ†‘μ‹ ν•œλ‹€.
# LPCTSTR strScrNo : ν™”λ©΄λ²ˆν˜Έ
# LPCTSTR strConditionName : 쑰건λͺ…
# int nIndex : 쑰건λͺ…μΈλ±μŠ€
# int nSearch : μ‘°νšŒκ΅¬λΆ„(0:일반쑰회, 1:μ‹€μ‹œκ°„μ‘°νšŒ, 2:μ—°μ†μ‘°νšŒ)
# 1:μ‹€μ‹œκ°„μ‘°νšŒμ˜ ν™”λ©΄ 개수의 μ΅œλŒ€λŠ” 10개
@pyqtSlot(str, str, int, int)
def sendCondition(self, scrNo, conditionName, index, search):
self.ocx.dynamicCall("SendCondition(QString,QString, int, int)", scrNo, conditionName, index, search)
# μ‹€μ‹œκ°„ 쑰건검색을 μ€‘μ§€ν•©λ‹ˆλ‹€.
# β€» ν™”λ©΄λ‹Ή μ‹€μ‹œκ°„ 쑰건검색은 μ΅œλŒ€ 10개둜 μ œν•œλ˜μ–΄ μžˆμ–΄μ„œ 더 이상 μ‹€μ‹œκ°„ 쑰건검색을 μ›ν•˜μ§€ μ•ŠλŠ” 쑰건은 μ€‘μ§€ν•΄μ•Όλ§Œ 카운트 λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
@pyqtSlot(str, str, int)
def sendConditionStop(self, scrNo, conditionName, index):
self.ocx.dynamicCall("SendConditionStop(QString, QString, int)", scrNo, conditionName, index)
# λ³΅μˆ˜μ’…λͺ©μ‘°νšŒ Tran을 μ„œλ²„λ‘œ μ†‘μ‹ ν•œλ‹€.
# OP_ERR_RQ_STRING – μš”μ²­ μ „λ¬Έ μž‘μ„± μ‹€νŒ¨
# OP_ERR_NONE - μ •μƒμ²˜λ¦¬
#
# sArrCode – μ’…λͺ©κ°„ ꡬ뢄은 β€˜;’이닀.
# nTypeFlag – 0:주식관심쒅λͺ©μ •λ³΄, 3:μ„ λ¬Όμ˜΅μ…˜κ΄€μ‹¬μ’…λͺ©μ •λ³΄
@pyqtSlot(str, bool, int, int, str, str)
def commKwRqData(self, arrCode, next, codeCount, typeFlag, rQName, screenNo):
self.ocx.dynamicCall("CommKwRqData(QString, QBoolean, int, int, QString, QString)", arrCode, next, codeCount, typeFlag, rQName, screenNo)
# μ‹€μ‹œκ°„ 등둝을 ν•œλ‹€.
# strScreenNo : ν™”λ©΄λ²ˆν˜Έ
# strCodeList : μ’…λͺ©μ½”λ“œλ¦¬μŠ€νŠΈ(ex: 039490;005930;…)
# strFidList : FID번호(ex:9001;10;13;…)
# 9001 – μ’…λͺ©μ½”λ“œ
# 10 - ν˜„μž¬κ°€
# 13 - λˆ„μ κ±°λž˜λŸ‰
# strOptType : νƒ€μž…(β€œ0”, β€œ1”)
# νƒ€μž… β€œ0”은 항상 λ§ˆμ§€λ§‰μ— λ“±λ‘ν•œ μ’…λͺ©λ“€λ§Œ μ‹€μ‹œκ°„λ“±λ‘μ΄ λ©λ‹ˆλ‹€.
# νƒ€μž… β€œ1”은 이전에 μ‹€μ‹œκ°„ λ“±λ‘ν•œ μ’…λͺ©λ“€κ³Ό ν•¨κ»˜ μ‹€μ‹œκ°„μ„ λ°›κ³  싢은 μ’…λͺ©μ„ μΆ”κ°€λ‘œ 등둝할 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.
# β€» μ’…λͺ©, FIDλŠ” 각각 ν•œλ²ˆμ— μ‹€μ‹œκ°„ 등둝 ν•  수 μžˆλŠ” κ°œμˆ˜λŠ” 100개 μž…λ‹ˆλ‹€.
@pyqtSlot(str, str, str, str, result=int)
def setRealReg(self, screenNo, codeList, fidList, optType):
return self.ocx.dynamicCall("SetRealReg(QString, QString, QString, QString)", screenNo, codeList, fidList, optType)
# μ’…λͺ©λ³„ μ‹€μ‹œκ°„ ν•΄μ œ
# strScrNo : ν™”λ©΄λ²ˆν˜Έ
# strDelCode : μ‹€μ‹œκ°„ ν•΄μ œν•  μ’…λͺ©μ½”λ“œ
# -화면별 μ‹€μ‹œκ°„ν•΄μ œ
# μ—¬λŸ¬ ν™”λ©΄λ²ˆν˜Έλ‘œ κ±Έλ¦° μ‹€μ‹œκ°„μ„ ν•΄μ œν•˜λ €λ©΄ νŒŒλΌλ©”ν„°μ˜ ν™”λ©΄λ²ˆν˜Έμ™€ μ’…λͺ©μ½”λ“œμ— β€œALLβ€λ‘œ μž…λ ₯ν•˜μ—¬ ν˜ΈμΆœν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.
# SetRealRemove(β€œALL”, β€œALL”);
# κ°œλ³„ν™”λ©΄λ³„λ‘œ μ‹€μ‹œκ°„ ν•΄μ œ ν•˜μ‹œλ €λ©΄ νŒŒλΌλ©”ν„°μ—μ„œ ν™”λ©΄λ²ˆν˜ΈλŠ” μ‹€μ‹œκ°„ν•΄μ œν• 
# ν™”λ©΄λ²ˆν˜Έμ™€ μ’…λͺ©μ½”λ“œμ—λŠ” β€œALLβ€λ‘œ ν•΄μ£Όμ‹œλ©΄ λ©λ‹ˆλ‹€.
# SetRealRemove(β€œ0001”, β€œALL”);
# -ν™”λ©΄μ˜ μ’…λͺ©λ³„ μ‹€μ‹œκ°„ν•΄μ œ
# ν™”λ©΄μ˜ μ’…λͺ©λ³„λ‘œ μ‹€μ‹œκ°„ ν•΄μ œν•˜λ €λ©΄ νŒŒλΌλ©”ν„°μ— ν•΄λ‹Ήν™”λ©΄λ²ˆν˜Έμ™€ ν•΄μ œν• 
# μ’…λͺ©μ½”λ“œλ₯Ό μž…λ ₯ν•˜μ‹œλ©΄ λ©λ‹ˆλ‹€.
# SetRealRemove(β€œ0001”, β€œ039490”);
# λ¬Έμ„œμ™€λŠ” 달리 return μ—†μŒ
@pyqtSlot(str, str)
def setRealRemove(self, scrNo, delCode):
self.ocx.dynamicCall("SetRealRemove(QString, QString)", scrNo, delCode)
# μˆ˜μ‹  데이터λ₯Ό λ°˜ν™˜ν•œλ‹€.
# LPCTSTR strTrCode : μ‘°νšŒν•œTRμ½”λ“œ
# LPCTSTR strRecordName: μ‘°νšŒν•œ TRλͺ…
# nIndex : 볡수 데이터 인덱슀
# strItemName: μ•„μ΄ν…œ λͺ…
# λ°˜ν™˜κ°’: μˆ˜μ‹  데이터
@pyqtSlot(str, str, int, str, result=str)
def getCommData(self, trCode, recordName, index, itemName):
return self.ocx.dynamicCall("GetCommData(QString, QString, int, QString)",
trCode, recordName, index, itemName)
# 차트 μ‘°νšŒν•œ 데이터 μ „λΆ€λ₯Ό λ°°μ—΄λ‘œ λ°›μ•„μ˜¨λ‹€.
# LPCTSTR strTrCode : μ‘°νšŒν•œTRμ½”λ“œ
# LPCTSTR strRecordName: μ‘°νšŒν•œ TRλͺ…
# β€»ν•­λͺ©μ˜ μœ„μΉ˜λŠ” KOA Studio의 TRλͺ©λ‘ μˆœμ„œλ‘œ 데이터λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.
# 예둜 OPT10080을 μ‚΄νŽ΄λ³΄λ©΄ OUTPUT의 λ©€ν‹°λ°μ΄ν„°μ˜ ν•­λͺ©μ²˜λŸΌ ν˜„μž¬κ°€, κ±°λž˜λŸ‰, μ²΄κ²°μ‹œκ°„λ“± 순으둜 ν•­λͺ©μ˜ μœ„μΉ˜κ°€ 0λΆ€ν„° 1μ”©μ¦κ°€ν•©λ‹ˆλ‹€.
@pyqtSlot(str, str, result=str)
def getCommDataEx(self, trCode, recordName):
return self.ocx.dynamicCall("GetCommDataEx(QString, QString)", trCode, recordName)
# 리얼 μ‹œμ„Έλ₯Ό λŠλŠ”λ‹€.
# ν™”λ©΄ λ‚΄ λͺ¨λ“  리얼데이터 μš”μ²­μ„ μ œκ±°ν•œλ‹€.
# 화면을 μ’…λ£Œν•  λ•Œ λ°˜λ“œμ‹œ μœ„ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•΄μ•Ό ν•œλ‹€.
# Ex) openApi.DisconnectRealData(β€œ0101”);
@pyqtSlot(str)
def disconnectRealData(self, scnNo):
self.ocx.dynamicCall("DisconnectRealData(QString)", scnNo)
# μ’…λͺ©μ½”λ“œμ˜ ν•œκΈ€λͺ…을 λ°˜ν™˜ν•œλ‹€.
# strCode – μ’…λͺ©μ½”λ“œ
# μ’…λͺ©ν•œκΈ€λͺ…
# μ—†λŠ” μ½”λ“œ 일경우 empty λ₯Ό 리턴함
@pyqtSlot(str, result=str)
def getMasterCodeName(self, strCode):
return self.ocx.dynamicCall("GetMasterCodeName(QString)", strCode)
# μ’…λͺ©μ½”λ“œμ˜ ν•œλ‹€.
# strCode – μ’…λͺ©μ½”λ“œ
# μž…λ ₯ν•œ μ’…λͺ©μ— λŒ€ν•œ λŒ€λΆ„λ₯˜, 쀑뢄λ₯˜, 업쒅ꡬ뢄값을 κ΅¬λΆ„μžλ‘œ μ—°κ²°ν•œ λ¬Έμžμ—΄μ„ μ–»μ„μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.(μ—¬κΈ°μ„œ κ΅¬λΆ„μžλŠ” '|'와 ';'μž…λ‹ˆλ‹€.)
# KOA_Functions("GetMasterStockInfo", μ’…λͺ©μ½”λ“œ)
# μ‹œμž₯ꡬ뢄0|μ½”μŠ€λ‹₯|λ²€μ²˜κΈ°μ—…;μ‹œμž₯ꡬ뢄1|μ†Œν˜•μ£Ό;업쒅ꡬ뢄|제쑰|기계/μž₯λΉ„
# μ‹œμž₯ꡬ뢄0|κ±°λž˜μ†Œ;μ‹œμž₯ꡬ뢄1|μ€‘ν˜•μ£Ό;업쒅ꡬ뢄|μ„œλΉ„μŠ€μ—…;
@pyqtSlot(str, result=str)
def getMasterStockInfo(self, strCode):
stock_info = self.ocx.dynamicCall("KOA_Functions(QString, QString)", "GetMasterStockInfo", strCode)
# api return λ²„κ·Έλ‘œ μΆ”κ°€ ν•΄μ€Œ
kospi_kosdaq = ''
yupjong = ''
if( stock_info != ''):
if( stock_info[-1] == ';'):
stock_info = stock_info[0:-1]
kospi_kosdaq = stock_info.split(';')[0].split('|')[1]
yupjong = stock_info.split(';')[-1].split('|')[-1]
return kospi_kosdaq + ':' + yupjong
if __name__ == "__main__":
def test_buy():
# 비정상 맀수 (μ‹œμž₯가에 단가 λ„£κΈ° ) μš°λ¦¬μ’…κΈˆ 1μ£Ό
# objKiwoom.sendOrder("buy", kw_util.sendOrderScreenNo, objKiwoom.account_list[0], kw_util.dict_order["μ‹ κ·œλ§€μˆ˜"],
# "010050", 1, 900 , kw_util.dict_order["μ‹œμž₯κ°€"], "")
# 정상 맀수 - kd 건섀 1μ£Ό
objKiwoom.sendOrder("buy", kw_util.sendOrderScreenNo, objKiwoom.account_list[0], kw_util.dict_order["μ‹ κ·œλ§€μˆ˜"],
"044180", 1, 0 , kw_util.dict_order["μ‹œμž₯κ°€"], "")
pass
def test_sell():
#정상 맀도 - kd 건섀 1μ£Ό
objKiwoom.sendOrder("sell", kw_util.sendOrderScreenNo, objKiwoom.account_list[0], kw_util.dict_order["μ‹ κ·œλ§€λ„"],
"044180", 1, 0 , kw_util.dict_order["μ‹œμž₯κ°€"], "")
pass
def test_condition():
objKiwoom._OnReceiveRealCondition("044180", "I", "단타 μΆ”μ„Έ", 1)
pass
def test_getCodeList():
# μ½”μŠ€ν”Ό μ½”λ“œ 리슀트
result = objKiwoom.getCodeListByMarket('0')
print(result)
# μ½”μŠ€λ‹₯ μ½”λ“œ 리슀트
result = objKiwoom.getCodeListByMarket('10')
print(result)
pass
def test_jusikGibon():
objKiwoom.requestOpt10001("044180")
pass
def test_jusik_condition_occur():
objKiwoom.addConditionOccurList('044180')
pass
@pyqtSlot()
def test_make_jangoInfo():
objKiwoom.makeJangoInfoFile()
pass
def test_make_chegyeolInfo():
objKiwoom.makeChegyeolInfoFile()
def test_terminate():
objKiwoom.sigTerminating.emit()
pass
def test_make_excel():
file_path = r'd:\download\톡합 λ¬Έμ„œ2.xlsx'
test_data = {
"170822": [
" 8.56| 8750| 맀수횟수: 1 | (μ΅μ ˆμ΄λ‹€) | 210540 | -맀도 | 22200 | 5 | 141905 | λ””μ™€μ΄νŒŒμ›Œ ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 038870 | +맀수 | 10350 | 10 | 142205 | μ—μ½”λ°”μ΄μ˜€ "
],
"170824": [
" 8.81| 9180| 맀수횟수: 1 | (μ΅μ ˆμ΄λ‹€) | 033100 | -맀도 | 6300 | 18 | 090136 | μ œλ£‘μ „κΈ° ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 069540 | +맀수 | 6200 | 17 | 090349 | 라이트둠 ",
" 8.55| 9010| 맀수횟수: 1 | (μ΅μ ˆλ―Έλ‹¬) | 069540 | -맀도 | 6730 | 17 | 090557 | 라이트둠 ",
" 8.76| 8925| 맀수횟수: 1 | (μ΅μ ˆλ―Έλ‹¬) | 226350 | -맀도 | 3165 | 35 | 090842 | 아이엠텍 ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 180400 | +맀수 | 14250 | 8 | 091259 | μ— μ§€λ©”λ“œ ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 072470 | +맀수 | 8247 | 13 | 091845 | μš°λ¦¬μ‚°μ—…ν™€λ”©μŠ€ ",
" 0| 0| 맀수횟수: 4 | (λ‹¨μˆœλ§€μˆ˜) | 031860 | +맀수 | 5050 | 80 | 094752 | μ—”μ—μŠ€μ—” "
],
"170914": [
" 13.53| 14000| 맀수횟수: 1 | (μ΅μ ˆμ΄λ‹€) | 038870 | -맀도 | 11750 | 10 | 090102 | μ—μ½”λ°”μ΄μ˜€ ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 023800 | +맀수 | 6400 | 8 | 090105 | μΈμ§€μ»¨νŠΈλ‘€μŠ€ ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 042600 | +맀수 | 8420 | 6 | 090113 | μƒˆλ‘œλ‹‰μŠ€ ",
" 8.99| 4720| 맀수횟수: 1 | (μ΅μ ˆλ―Έλ‹¬) | 161570 | -맀도 | 7150 | 8 | 093611 | λ―Έλ™μ•€μ”¨λ„€λ§ˆ ",
" 0| 0| 맀수횟수: 1 | (λ‹¨μˆœλ§€μˆ˜) | 005420 | +맀수 | 19050 | 3 | 093933 | μ½”μŠ€λͺ¨ν™”ν•™ "
]
}
objKiwoom.make_excel(file_path, test_data)
def test_business_day():
base_time = datetime.datetime.strptime('20190920090011', '%Y%m%d%H%M%S')
target_day = util.date_by_adding_business_days(base_time, BUNHAL_MAESU_PROHIBIT_DAYS )
print(target_day)
# putenv λŠ” current process 에 영ν–₯을 λͺ»λΌμΉ˜λ―€λ‘œ environ μ—μ„œ 직접 μ„ΈνŒ…
# qml debugging λ₯Ό μœ„ν•΄ QML_IMPORT_TRACE ν™˜κ²½λ³€μˆ˜ 1둜 μ„ΈνŒ… ν›„ DebugView μ—μ„œ 디버깅 λ©”μ‹œμ§€ 확인 κ°€λŠ₯
os.environ['QML_IMPORT_TRACE'] = '1'
# print(os.environ['QML_IMPORT_TRACE'])
myApp = QtWidgets.QApplication(sys.argv)
objKiwoom = KiwoomConditon()
form = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(form)
event_filter = CloseEventEater()
form.installEventFilter( event_filter )
ui.btnMakeExcel.clicked.connect(objKiwoom.onBtnMakeExcelClicked )
ui.btnStart.clicked.connect(objKiwoom.onBtnStartClicked)
ui.btnYupjong.clicked.connect(objKiwoom.onBtnYupjongClicked)
ui.btnJango.clicked.connect(objKiwoom.onBtnJangoClicked)
ui.btnChegyeol.clicked.connect(objKiwoom.onBtnChegyeolClicked)
ui.btnCondition.clicked.connect(objKiwoom.onBtnConditionClicked)
ui.lineCmd.textChanged.connect(objKiwoom.onLineCmdTextChanged)
ui.btnRun.clicked.connect(objKiwoom.onBtnRunClicked)
form.show()
# test_business_day()
logging.basicConfig(filename='system_err.log', filemode='a',format='%(asctime)s - %(message)s', level=logging.INFO)
# try:
# 1/0
# except Exception as e:
# logging.exception("Error Occured")
sys.exit(myApp.exec_())
@fearhope
Copy link

fearhope commented Mar 6, 2023

μ•ˆλ…•ν•˜μ„Έμš”? μžλ™λ§€λ§€λ₯Ό μ‹œμž‘ν•˜κΈ°μ— μ•„μ£Ό 쒋은 μ˜ˆμ œλ„€μš”. 쒋은 자료 μ˜¬λ €μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€. 그런데 mainwindow_ui νŒŒμΌμ€ μ˜¬λΌμ™€ μžˆμ§€ μ•Šμ€λ°μš”. ν˜Ήμ‹œ 이 νŒŒμΌλ„ κ³΅μœ ν•΄ μ£Όμ‹€ 수 μžˆμœΌμ‹€κΉŒμš”? Qt와 open api μžλ™λ§€λ§€λŠ” 해본적이 μ—†μ–΄μ„œ μ˜¬λ €μ£Όμ‹œλ©΄ λ§Žμ€ 도움이 될 것 κ°™μŠ΅λ‹ˆλ‹€. κ°μ‚¬ν•©λ‹ˆλ‹€.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment