이하영

open_api 함수 추가

......@@ -237,8 +237,7 @@ class Simulator_Func:
columns=['id', 'order_num', 'code', 'code_name', 'rate', 'purchase_rate',
'purchase_price','present_price', 'valuation_price','valuation_profit',
'holding_amount', 'buy_date', 'item_total_purchase','chegyul_check',
'invest_unit','sell_date', 'sell_price', 'sell_rate', 'rate_std',
'rate_std_mod_val','rate_std_htr', 'rate_htr','rate_std_mod_val_htr',
'invest_unit','sell_date', 'sell_price', 'sell_rate',
'yes_close', 'close', 'd1_diff_rate', 'd1_diff',
'open', 'high','low','volume',
'clo5', 'clo10', 'clo20', 'clo60','clo120',
......@@ -1192,3 +1191,30 @@ class Simulator_Func:
else:
if self.check_balance():
self.auto_trade_buy_stock(str(date_rows_today) + "0900", date_rows_today, date_rows_yesterday)
# daily_buy_list 데이터베이스에서 가장 최근의 날짜 테이블을 가져오는 함수
def get_recent_daily_buy_list_date(self):
query="select TABLE_NAME from information_schema.tables " \
"where table_schema = 'daily_buy_list' and TABLE_NAME like '%s' order by table_name desc limit 1"
row = self.engine_daily_buy_list.execute(query % ("20%%")).fetchall()
if len(row) == 0:
return False
return row[0][0]
# 최근 daily_buy_list의 날짜 테이블에서 code에 해당하는 데이터만 가져오는 함수
def get_daily_buy_list_by_code(self,code,date):
query = f"select * from `{date}` where code = '{code}' group by code"
daily_buy_list = self.engine_daily_buy_list.execute(query).fetchall()
df_daily_buy_list = DataFrame(daily_buy_list,
columns=['index', 'index2', 'date', 'check_item',
'code', 'code_name', 'd1_diff', 'd1_diff_rate',
'close', 'open','high', 'low', 'volume',
'clo5', 'clo10', 'clo20', 'clo60', 'clo120',
"clo5_diff_rate", "clo10_diff_rate", "clo20_diff_rate",
"clo60_diff_rate", "clo120_diff_rate",
'yes_clo5', 'yes_clo10', 'yes_clo20', 'yes_clo60','yes_clo120',
'vol5', 'vol10', 'vol20', 'vol60', 'vol120'])
return df_daily_buy_list
......
from Open_Api import *
from collections import OrderedDict
from pandas import DataFrame
import time
from Daily_Info import *
from Stock_Info import *
import config
class Collector_Api():
def __init__(self):
self.open_api=Open_Api()
self.engine_bot=self.open_api.engine_bot
self.set_variable()
# 변수 설정
def set_variable(self):
self.open_api.use="collector"
self.stock_info=Stock_Info(config.real_bot_name,config.real_dailyInfo_name,config.real_stockInfo_name)
self.daily_info=Daily_Info()
def code_update_check(self):
query="select code_update,balance_to_db,posses_stocks,today_profit,contract_check,db_to_daily_info," \
"today_buy_list,stock_info,min_info,daily_info from setting_data"
result=self.engine_bot.execute(query).fetchall()
today=self.open_api.today
# 오늘 날짜에 종목리스트가 업데이트 되지 않았다면 업데이트를 실행
if result[0][0]!=today:
self.open_api.get_balance()
self.get_code_list()
# 계좌정보 업데이트
if result[0][1]!=today or result[0][2]!=today:
self.check_balance()
self.open_api.set_per_invest()
# 현재 보유종목 테이블 업데이트
if result[0][2]!=today:
self.open_api.get_posses_item()
self.open_api.setting_data_posses_stock()
# 수익률 테이블 업데이트
if result[0][3]!=today:
self.update_today_profit_list()
# stock_info 테이블 업데이트
if result[0][7]!=today:
self.check_stock_info()
if result[0][9]!=today:
self.check_daily_info()
if result[0][4]!=today:
self.open_api.check_contract()
self.open_api.final_check_contract()
if result[0][6]!=today:
self.realtime_daily_info_check()
# 코스피, 코스닥 리스트 확인 및 데이터베이스 업데이트
def get_code_list(self):
self.stock_info.get_item_kospi()
self.stock_info.get_item_kosdaq()
stock_data=OrderedDict(
kospi=self.stock_info.kospi_list,
kosdaq=self.stock_info.kosdaq_list
)
for s_type,data in stock_data.items():
stock_data[s_type]=self.create_stock_table(data,s_type)
stock_all=stock_data['kospi'].append(stock_data['kosdaq'],ignore_index=True)
self.create_stock_table(stock_all,"all")
query="update setting_data set code_update='%s'"
self.engine_bot.execute(query%(self.open_api.today))
# kospi, kosdaq 주식 종목을 저장하는 테이블 생성
def create_stock_table(self,data,type):
checking=['kospi','kosdaq']
stock_df=DataFrame()
stock_df['code']=data['code']
stock_list=list()
# 주식 code를 이용하여 실제 kiwoom 증권에서 사용하는 주식이름으로 변경
for kind in data.itertuples():
kiwoom_name=self.open_api.dynamicCall("GetMasterCodeName(QString)",kind.code).strip()
stock_list.append(kiwoom_name)
stock_df['code_name']=stock_list
stock_df['check_item']=0
if type in checking:
stock_df=stock_df[stock_df['code_name'].map(len)>0]
if type=="all":
stock_df['check_stock']="0"
stock_df['check_min']="0"
# 데이터 타입을 설정
# code, code_name 칼럼은 Text. check_item 칼럼은 Integer
dtypes=dict(zip(list(stock_df.columns),[Text]*len(stock_df.columns)))
dtypes['check_item']=Integer
table_name='stock_'+str(type)
stock_df.to_sql(table_name,self.open_api.engine_daily,if_exists='replace',dtype=dtypes)
return stock_df
def check_balance(self):
self.open_api.reset_opw00018_output()
# 예수금 상세현황 요청
self.open_api.set_input_value("계좌번호",self.open_api.account_no)
self.open_api.set_input_value("비밀번호입력매체구분",00)
self.open_api.set_input_value("조회구분",1)
self.open_api.comm_rq_data("opw00001_req","opw00001",0,"2000")
# 계좌평가 잔고내역 요청
self.open_api.set_input_value("계좌번호",self.open_api.account_no)
self.open_api.comm_rq_data("opw00018_req","opw00018",0,"2000")
while self.open_api.remained_data:
self.open_api.set_input_value("계좌번호",self.open_api.account_no)
self.open_api.comm_rq_data("opw00018_req","opw00018",2,"2000")
# 일자별 실현손익 요청
self.open_api.set_input_value("계좌번호",self.open_api.account_no)
self.open_api.set_input_value("시작일자","20170101")
self.open_api.set_input_value("종료일자",self.open_api.today)
self.open_api.comm_rq_data("opt10074_req","opt10074",0,"0329")
while self.open_api.remained_data:
self.open_api.set_input_value("계좌번호", self.open_api.account_no)
self.open_api.set_input_value("시작일자", "20170101")
self.open_api.set_input_value("종료일자", self.open_api.today)
self.open_api.set_input_value("구분","0")
self.open_api.comm_rq_data("opt10074_req", "opt10074", 2, "0329")
self.create_balance_table()
# balance_data 테이블 생성
def create_balance_table(self):
self.total_invest=int(self.open_api.deposit)+int(self.open_api.total_purchase)
balance_data={'id':[],'date':[],'total_asset':[],'today_profit':[],"total_profit":[],
'total_invest':[],'deposit':[],'total_purchase':[],'total_evaluation':[],'today_invest':[],
'today_rate':[],'estimated_asset':[]}
balance_cols=['date','today_earning_rate','total_asset','deposit',
'today_profit','total_profit','today_invest','total_invest',
'total_purchase','today_evaluation','today_sell_count',
'today_rate','estimated_asset','sell_point','per_invest','limit_money',
'today_buy_count','today_sell_count','total_posses_count','today_buy_price','today_sell_price'
]
balance=DataFrame(balance_data,columns=balance_cols,index=balance_data['id'])
balance.loc[0,'date']=self.open_api.today
balance.loc[0,'today_profit']=self.open_api.today_profit
balance.loc[0,'total_profit']=self.open_api.total_profit
balance.loc[0,'total_invest']=self.open_api.total_invest
balance.loc[0,'deposit']=self.open_api.deposit
balance.loc[0,'total_purchase']=self.open_api.total_purchase
balance.loc[0,'total_evaluation']=self.open_api.total_evaluated_price
balance.loc[0,'today_invest']=self.open_api.total_valuation
balance.loc[0,'today_rate']=float(self.open_api.earning_rate/self.open_api.mod_classify)
balance.loc[0,'estimate_asset']=self.open_api.estimated_deposit
balance.loc[0,'sell_point']=self.open_api.simul_api.sell_point
balance.loc[0,'per_invest']=self.open_api.per_invest
balance.loc[0,'limit_money']=self.open_api.simul_api.limit_money
# balance_data 테이블 생성
balance.to_sql('balance_data', self.engine_bot, if_exists='append')
query = "select date from balance_data"
rows = self.engine_bot.execute(query).fetchall()
for i in range(len(rows)):
# today_earning_rate
query = "update balance_data " \
"set " \
"today_earning_rate =round(today_profit / total_invest * '%s',2) WHERE date='%s'"
self.engine_bot.execute(query % (100, rows[i][0]))
# today_buy_count
query = "UPDATE balance_data " \
"SET " \
"today_buy_count=" \
"(select count(*) " \
"from " \
"(select code from transaction_history where buy_date like '%s' group by code )) " \
"WHERE date='%s'"
self.engine_bot.execute(query % (rows[i][0] + "%%", rows[i][0]))
# today_sell_count
query="UPDATE balance_data " \
"SET " \
"today_sell_count=" \
"(select count(*) " \
"from " \
"(select code from transaction_history" \
"where buy_date like '%s' and sell_date is not null group by code) temp) " \
"WHERE date='%s'"
self.engine_bot.execute(query % (rows[i][0] + "%%", rows[i][0]))
# today_sell_price
query="UPDATE balance_data " \
"SET" \
"today_sell_price=" \
"(select sum(*) " \
"from " \
"(select sell_price from transaction_history " \
"where sell_date like '%s')" \
"where date='%s'"
self.engine_bot.execute(query%(rows[i][0])+"%%",rows[i][0])
# today_buy_price
query="UPDATE balance_data " \
"SET" \
"today_sell_price=" \
"(select sum(*) " \
"from " \
"(select purchase_price from transaction_history " \
"where sell_date like '%s')" \
"where date='%s'"
self.engine_bot.execute(query%(rows[i][0])+"%%",rows[i][0])
# total_posses_count
query="UPDATE balance_data " \
"SET" \
"total_posses_count=" \
"(select count(*) " \
"from" \
"transaction_history where sell_date is Null)" \
"where date='%s'"
self.engine_bot.execute(query%(rows[i][0]))
sql = "UPDATE setting_data SET balance_to_db='%s' limit 1"
self.engine_bot.execute(sql % (self.open_api.today))
def is_table_exist(self,db_name,table_name):
query="select 1 from information_schema.tables where table_schema='{}' and table_name='{}'"
result=self.open_api.engine_minute.execute(query.format(db_name,table_name)).fetchall()
if len(result)==1:
return True
else:
return False
def update_today_profit_list(self):
self.open_api.reset_opt10073_output()
self.open_api.set_input_value("계좌번호",self.open_api.account_no)
self.open_api.set_input_value("시작일자",self.open_api.today)
self.open_api.set_input_value("종료일자",self.open_api.today)
self.open_api.comm_rq_data("opt10073_req","opt10073",0,"0328")
while self.open_api.remained_data:
self.open_api.set_input_value("계좌번호",self.open_api.account_no)
self.open_api.comm_rq_data("opt10073_req","opt10073",2,"0328")
today_profit_item_temp = {'date': [], 'code': [], 'code_name': [], 'amount': [], 'today_profit': [],
'earning_rate': []}
today_profit_item = DataFrame(today_profit_item_temp,
columns=['date', 'code', 'code_name', 'amount', 'today_profit',
'earning_rate'])
item_count = len(self.open_api.opt10073_output['multi'])
for i in range(item_count):
row = self.open_api.opt10073_output['multi'][i]
today_profit_item.loc[i, 'date'] = row[0]
today_profit_item.loc[i, 'code'] = row[1]
today_profit_item.loc[i, 'code_name'] = row[2]
today_profit_item.loc[i, 'amount'] = int(row[3])
today_profit_item.loc[i, 'today_profit'] = float(row[4])
today_profit_item.loc[i, 'earning_rate'] = float(row[5])
if len(today_profit_item) > 0:
today_profit_item.to_sql('today_profit_list', self.engine_bot, if_exists='append')
query = "UPDATE setting_data SET today_profit='%s' limit 1"
self.engine_bot.execute(query % (self.open_api.today))
def check_stock_info(self):
self.update_daily_info()
query="update setting_data set daily_info='%s'"
self.engine_bot.execute(query%(self.open_api.today))
def update_daily_info(self):
query="select code,code_name,check_stock from stock_all"
code_list=self.open_api.engine_daily.execute(query).fetchall()
num=len(code_list)
query="update stock_all set check_stock='%s' where code='%s'"
for i in range(num):
if int(code_list[i][2] in (1,3)):
continue
code=code_list[i][0]
code_name=code_list[i][1]
check_item_sort=self.set_stock_info_table(code,code_name)
self.open_api.engine_daily.execute(query%(check_item_sort,code))
# stock_info 데이터베이스에 테이블 생성 및 추가
def set_stock_info_table(self,code,code_name):
df=self.open_api.get_date_data(code,code_name,self.open_api.today)
df=DataFrame(df,
columns=['date', 'check_item', 'code', 'code_name', 'd1_diff_rate',
'close', 'open', 'high','low','volume',
'clo5', 'clo10', 'clo20', 'clo60','clo120',
'pre_clo5', 'pre_clo10', 'pre_clo20', 'pre_clo60','pre_clo120',
'vol5', 'vol10', 'vol20', 'vol60','vol120'])
df=df.sort_values(by=['date'],ascending=True)
df['code']=code
df['code_name']=code_name
df['d1_diff_rate']=float((df['close']-df['close'].shift(1))/df['close'].shift(1)*100)
df['clo5']=df['close'].rolling(window=5).mean()
df['clo10']=df['close'].rolling(window=10).mean()
df['clo20']=df['close'].rolling(window=20).mean()
df['clo60']=df['close'].rolling(window=60).mean()
df['clo120']=df['close'].rolling(window=120).mean()
df['pre_col5']=df['clo5'].shift(1)
df['pre_col10']=df['clo10'].shift(1)
df['pre_col20']=df['clo20'].shift(1)
df['pre_col60']=df['clo60'].shift(1)
df['pre_col120']=df['clo120'].shift(1)
df['vlo5']=df['volume'].rolling(window=5).mean()
df['vlo10']=df['volume'].rolling(window=10).mean()
df['vlo20']=df['volume'].rolling(window=20).mean()
df['vlo60']=df['volume'].rolling(window=60).mean()
df['vlo120']=df['volume'].rolling(window=120).mean()
# 이미 테이블이 존재한다면 저장된 가장 최신의 날짜 이후의 데이터만 저장
if self.engine_bot.dialect.has_table(self.open_api.engine_stock,code_name):
df=df[df.date>self.open_api.get_latest_date_from_stock_info(code_name)]
df[['date', 'check_item', 'code', 'code_name', 'd1_diff_rate',
'close', 'open', 'high','low','volume',
'clo5', 'clo10', 'clo20', 'clo60','clo120',
'pre_clo5', 'pre_clo10', 'pre_clo20', 'pre_clo60','yes_clo120',
'vol5', 'vol10', 'vol20', 'vol60','vol120']]=\
df[['date', 'check_item', 'code', 'code_name', 'd1_diff_rate',
'close', 'open', 'high','low','volume',
'clo5', 'clo10', 'clo20', 'clo60','clo120',
'pre_clo5', 'pre_clo10', 'pre_clo20', 'pre_clo60','yes_clo120',
'vol5', 'vol10', 'vol20', 'vol60','vol120']].fillna(0).astype(int)
df.to_sql(name=code_name,con=self.open_api.engine_stock,if_exists='append')
check_item_sort = 1
return check_item_sort
def check_daily_info(self):
self.daily_info.create_daily_table()
query="update setting_data set daily_info='%s'"
self.engine_bot.execute(query%(self.open_api.today))
def realtime_daily_info_check(self):
if self.open_api.simul_api.is_date_exist(self.open_api.today):
self.open_api.simul_api.get_date_for_simul()
self.open_api.simul_api.choose_to_buy_list(self.open_api.today,self.open_api.today,len(self.open_api.simul_api.date_rows))
if self.open_api.sf.is_date_exist(self.open_api.today):
logger.debug("daily_buy_list DB에 {} 테이블이 있습니다. jackbot DB에 realtime_daily_buy_list 테이블을 생성합니다".format(self.open_api.today))
self.open_api.sf.get_date_for_simul()
# 첫 번째 파라미터는 여기서는 의미가 없다.
# 두 번째 파라미터에 오늘 일자를 넣는 이유는 매수를 하는 시점인 내일 기준으로 date_rows_yesterday가 오늘 이기 때문
self.open_api.sf.db_to_realtime_daily_buy_list(self.open_api.today, self.open_api.today, len(self.open_api.sf.date_rows))
# all_item_db에서 open, clo5~120, volume 등을 오늘 일자 데이터로 업데이트 한다.
self.open_api.sf.update_all_db_by_date(self.open_api.today)
self.open_api.rate_check()
# realtime_daily_buy_list(매수 리스트) 테이블 세팅을 완료 했으면 아래 쿼리를 통해 setting_data의 today_buy_list에 오늘 날짜를 찍는다.
sql = "UPDATE setting_data SET today_buy_list='%s' limit 1"
self.engine_JB.execute(sql % (self.open_api.today))
else:
logger.debug(
"""daily_buy_list DB에 {} 테이블이 없습니다. jackbot DB에 realtime_daily_buy_list 테이블을 생성 할 수 없습니다.
realtime_daily_buy_list는 daily_buy_list DB 안에 오늘 날짜 테이블이 만들어져야 생성이 됩니다.
realtime_daily_buy_list 테이블을 생성할 수 없는 이유는 아래와 같습니다.
1. 장이 열리지 않은 날 혹은 15시 30분 ~ 23시 59분 사이에 콜렉터를 돌리지 않은 경우
2. 콜렉터를 오늘 날짜 까지 돌리지 않아 daily_buy_list의 오늘 날짜 테이블이 없는 경우
""".format(self.open_api.today))
app=QApplication(sys.argv)
c=Collector_Api()
c.get_code_list()
\ No newline at end of file
from sqlalchemy import *
from open_api import *
from daily_info import *
from stock_info import *
import config
class CollectorApi():
def __init__(self):
self.open_api=OpenApi()
self.engine_bot=self.open_api.engine_bot
def set_variable(self):
self.open_api.sort="collector"
self.stock_info=StockInfo(config.real_bot,config.real_stockInfo,config.real_dailyInofo)
self.daily_info=DailyInfo()
def update_code(self):
print("update code")
query = "select code_update,jango_data_db_check, possessed_item, today_profit, final_chegyul_check, " \
"db_to_buy_list,today_buy_list, daily_crawler , min_crawler, daily_buy_list " \
"from setting_data limit 1"
result=self.engine_bot.execute(query).fetchall()
print(result)
if result[0][0]!=self.open_api.today():
self.open_api.check_balance()
self.get_code_list()
def set_db_minute_info(self):
print("Make Minute Info Database")
query="select code,code_name from stock_all"
target=self.open_api.engine_dInfo.execute(query).fetchall()
print(target)
app = QApplication(sys.argv)
c=CollectorApi()
c.update_code()
\ No newline at end of file
......@@ -6,9 +6,10 @@ import datetime
from sqlalchemy import *
from collections import defaultdict
from pandas import DataFrame
import re
from Logger import *
import config
import cf
from Simulator_Api import *
pymysql.install_as_MySQLdb()
......@@ -21,7 +22,7 @@ class Open_Api(QAxWidget):
self.login_event_loop=QEventLoop()
self.tr_event_loop=QEventLoop()
# open_api 호출 횟수를 저장f
# open_api 호출 횟수를 저장
self.rq_count=0
self.set_date()
self.tr_loop_count=0
......@@ -38,13 +39,14 @@ class Open_Api(QAxWidget):
# 변수 설정
self.set_variable()
self.simul_api=Simulator_Api(self.simul_num,"real",self.db_name)
self.sf=Simulator_Func(self.simul_num,"real",self.db_name)
logger.debug("알고리즘 번호 : %s",self.simul_api.simul_num)
logger.debug("매수 알고리즘 번호 : %s",self.simul_api.buy_algorithm)
logger.debug("매도 알고리즘 번호 : %s",self.simul_api.sell_algorithm)
# 시뮬레이션 데이터베이스에 setting_data 테이블이 존재하지 않는다면 생성
if not self.simul_api.is_table_exist(self.db_name,"setting_data"):
self.create_setting_data()
self.init_setting_data()
self.set_simul_variable()
self.ohlcv=defaultdict(list)
......@@ -88,6 +90,28 @@ class Open_Api(QAxWidget):
except Exception as e:
logger.critical(e)
# 사용자의 계좌정보 저장 및 출력
def get_account_info(self):
account_no=self.get_login_info("ACCNO")
self.account_no=account_no.split(";")[0]
logger.debug(self.account_no)
# 원하는 사용자 정보 반환
# param : tag - ACCNO - 보유계좌리스트
# ACCOUNT_CNT - 보유계좌 수
# USER_ID - 사용자 ID
# USER_NAME - 사용자 이름
# KEY_BSECGB - 키보드 보안 해제 여부 (0 : 정상, 1: 해지)
# FIREW_SECGB - 방화벽 설정여부 (0 : 미설정, 1: 설정, 2 : 해지)
# GetServerGubun - 접속서버 구분 (1 : 모의투자, 나머지 : 실서버)
# return : tag를 통해 요청한 정보(ret) 반환
def get_login_info(self,tag):
try:
ret=self.dynamicCall("GetLoginInfo(QString)",tag)
return ret
except Exception as e:
logger.critical(e)
# 수동 로그인설정인 경우 로그인창을 출력해서 로그인을 시도
# 자동로그인 설정인 경우 로그인창 출력없이 로그인을 시도
def comm_connect(self):
......@@ -105,7 +129,7 @@ class Open_Api(QAxWidget):
# sPrevNext : 다음 페이지가 있는지 여부. "2" : 다음페이지 존재, "0" or "" : 다음페이지 없음
def _receive_tr_data(self,sScrNo,sRQName,sTrCode,sRecordName,sPrevNext):
if sPrevNext=='2':
self.remained_data=True
self.remained_data=True # 다음 페이지가 존재하는지 확인하는 변수
else:
self.remained_data=False
......@@ -161,14 +185,133 @@ class Open_Api(QAxWidget):
# GetChejanData()함수를 이용해서 상세한 정보를 얻을 수 있다
# param : sGubun - 체결구분. 접수와 체결시 '0'값, 국내주식 잔고전달은 '1'값, 파생잔고 전달은 '4'
def _receive_chejan_data(self,sGubun,nItemCnt,sFIdList):
# 현재 체결 진행 중인 코드
print("주분번호 : ",self.get_chejan_data(9023))
print("종목명 : ",self.get_chejan_data(302))
print("주문수량 : ",self.get_chejan_data(900))
print("주문가격 : ",self.get_chejan_data(901))
# 체결구분. 접수와 체결
if sGubun=="0":
code=self.get_chejan_data(9001) # 현재 체결 진행 중인 코드
code=re.compile(r'\d{6}') # 종목코드는 연속된 숫자 6자리
order_num=self.get_chejan_data(9203) # 주문번호
# 주문번호가 존재하지 않는다면 주문실패
if not order_num:
logger.debug(code,"주문 실패")
return
chegyul_fail_amount=self.get_chejan_data(902) # 미체결 수량
order_gubun=self.get_chejan_data(905) # 주문구분
purchase_price=self.get_chejan_data(10) # 체결가
# 종목코드가 존재한다면
if code:
if chegyul_fail_amount!="":
# 해당 종목을 보유하고 있지 않은 경우
if not self.is_exist_possess_item_in_transaction(code):
# 해당 종목의 체결 실패 내역이 없다면
# transaction 테이블에 업데이트. 정상 체결 시 chegyul_check=0
if chegyul_fail_amount=="0":
logger.debug(code, "체결 완료")
self.db_to_transaction(order_num,code,0,purchase_price,0)
# 체결 실패 내역이 존재한다면
# transaction 테이블에 업데이트. 미체결 시 chegyul_check=1
else:
logger.debug(code,"미체결")
self.db_to_transaction(order_num,code,1,purchase_price,0)
# 매수하는 경우
elif order_gubun=="+매수":
if chegyul_fail_amount!="0" and self.check_stock_chegyul(code):
logger.debug("미체결. 매수 진행중!")
pass
elif chegyul_fail_amount=="0" and self.check_stock_chegyul(code):
logger.debug("매수 완료")
self.check_end_invest(code)
else:
pass
# 매도하는 경우
elif order_gubun=="-매도":
if chegyul_fail_amount=="0":
logger.debug("전량 매도")
self.check_end_sell(code)
else:
logger.debug("부분 매도")
self.check_sell_chegyul_fail(code)
else:
logger.debug("Invalid order_gubun")
else:
logger.debug("Invalid chegyul_fail_amount value")
else:
logger.debug("can't receive code value")
# 국내주식 잔고전달
elif sGubun=="1":
chegyul_fail_amount=self.get_chejan_data(902)
logger.debug("미체결 수량",chegyul_fail_amount)
else:
logger.debug("Invlid _receive_chejan_data")
# 특정 종목을 보유하고 있는지 확인하는 함수
def is_exist_possess_item_in_transaction(self,code):
query = "select code from transaction " \
"where code='%s' and (sell_date ='%s' or sell_date='%s') ORDER BY buy_date desc LIMIT 1"
result = self.engine_bot.execute(query % (code, 0, "")).fetchall()
if len(result) != 0:
return True
else:
return False
# 해당 종목이 체결되었는지 확인하는 함수
def check_stock_chegyul(self,code):
query = "SELECT chegyul_check FROM transaction " \
"where code='%s' and sell_date = '%s' ORDER BY buy_date desc LIMIT 1"
result = self.engine_bot.execute(query % (code, 0)).fetchall()
if result[0][0] == 1:
return True
else:
return False
# 체결 완료 시 transaction 테이블의 chegyul_check항목을 업데이트
def check_end_invest(self,code):
query = "UPDATE transaction " \
"SET " \
"chegyul_check='%s' WHERE code='%s' and sell_date = '%s' ORDER BY buy_date desc LIMIT 1"
self.engine_bot.execute(query % (0, code, 0))
# 매도 완료 후 DB 업데이트트
def check_sell_end(self,code):
query="select valuation_profit,rate,item_total_urchase,present_price" \
"from possessed_item" \
"where code={} limit 1"
get_list=self.engine_bot.execute(query.format(code)).fetchall()
# 매도 완료 종목에 대해 DB 업데이트
if get_list:
item = get_list[0]
query = f"""UPDATE transaction
SET
item_total_purchase = {item.item_total_purchase}, chegyul_check = 0,
sell_date = '{self.today_detail}', valuation_profit = {item.valuation_profit},
sell_rate = {item.rate}, sell_price = {item.present_price}
WHERE code = '{code}' and sell_date = '0' ORDER BY buy_date desc LIMIT 1"""
self.engine_bot.execute(query)
# 매도 완료 후 possessd_item 테이블에서 해당 종목 삭제
self.engine_bot.execute(f"DELETE FROM possessed_item WHERE code = '{code}'")
else:
logger.debug("보유 종목이 없습니다.")
# 매도 체결 실패시 DB 업데이트
def check_sell_chegyul_fail(self,code):
query = "UPDATE transaction SET chegyul_check='%s' " \
"WHERE code='%s' and sell_date = '%s' ORDER BY buy_date desc LIMIT 1"
self.engine_bot.execute(query % (1, code, 0))
# OnReceiveChejan()이벤트가 호출될때 체결정보나 잔고정보를 얻어오는 함수
# param : nFid - 실시간 타입에 포함된 FID
# FID List
# (FID, 설명) : (9023, 주문번호), (302, 종목명), (900, 주문수량), (901,주문가격), (902,미체결수량), (904,원주문번호),
# (905, 주문구분), (908, 주문/체결시간), (909, 체결번호), (910, 체결가), (911, 체결량), (10, 현재가/체결가/실시간종가)
def get_chejan_data(self,nFid):
try:
ret=self.dynamicCall("GetChejanData(int)",nFid)
......@@ -176,27 +319,15 @@ class Open_Api(QAxWidget):
except Exception as e:
logger.critical(e)
# 사용자의 계좌정보 저장 및 출력
def get_account_info(self):
account_no=self.get_login_info("ACCNO")
self.account_no=account_no.split(";")[0]
logger.debug(self.account_no)
# 원하는 사용자 정보 반환
# param : tag - ACCNO - 보유계좌리스트
# ACCOUNT_CNT - 보유계좌 수
# USER_ID - 사용자 ID
# USER_NAME - 사용자 이름
# KEY_BSECGB - 키보드 보안 해제 여부 (0 : 정상, 1: 해지)
# FIREW_SECGB - 방화벽 설정여부 (0 : 미설정, 1: 설정, 2 : 해지)
# GetServerGubun - 접속서버 구분 (1 : 모의투자, 나머지 : 실서버)
# return : tag를 통해 요청한 정보(ret) 반환
def get_login_info(self,tag):
try:
ret=self.dynamicCall("GetLoginInfo(QString)",tag)
return ret
except Exception as e:
logger.critical(e)
# 거래이력(transaction)테이블에 현재 보유중인 종목이 있는지 확인하는 함수
def is_transaction_check(self,code):
query = "select code from transaction " \
"where code='%s' and (sell_date ='%s' or sell_date='%s') ORDER BY buy_date desc LIMIT 1"
rows = self.engine_bot.execute(query % (code, 0, "")).fetchall()
if len(rows) != 0:
return True
else:
return False
# 조회요청시 TR의 Input값을 지정하는 함수
# param : sId - TR에 명시된 Input이름
......@@ -240,55 +371,56 @@ class Open_Api(QAxWidget):
# 변수 설정
# 실전투자인지 모의투자인지 여부를 확인하고 그에 해당하는 데이터베이스를 생성하는 함수
def set_variable(self):
self.config=config
self.cf=cf
self.get_today_buy_list_code=0
self.reset_opw00018_output()
if self.account_no==self.config.real_account_no:
if self.account_no==self.cf.real_account_no:
logger.debug("실전투자")
self.simul_num=self.config.real_num
self.set_database(self.config.real_bot_name)
self.mod_classify=100
self.simul_num=self.cf.real_num
self.set_database(cf.real_bot_name)
self.mod_gubun=100 # 실전투자와 모의투자를 구분하는 변수
elif self.account_no==self.config.test_account_no:
elif self.account_no==self.cf.test_account_no:
logger.debug("모의투자")
self.simul_num=self.config.test_num
self.set_database(self.config.test_bot_name)
self.mod_classify=1
self.simul_num=self.cf.test_num
self.set_database(cf.test_bot_name)
self.mod_gubun=1
else:
logger.debug("Invalid Account Number. Check the Config.py")
exit(1)
self.is_balance_null=True
self.use=False
self.py_gubun=False
# 데이터베이스 생성 및 엔진 설정
def set_database(self,db_name):
self.db_name=db_name
conn=pymysql.connect(
host=config.db_ip,
port=int(config.db_port),
user=config.db_id,
password=config.db_pw,
charset='utf8'
host=cf.db_ip,
port=int(cf.db_port),
user=cf.db_id,
password=cf.db_pw,
charset='utf8mb4'
)
cursor=conn.cursor()
if not self.is_database_exist(cursor):
self.create_database(cursor)
self.engine_bot=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+
self.config.db_ip + ":" + self.config.db_port+"/"+db_name,encoding='utf-8')
self.create_info_database(cursor)
self.engine_bot=create_engine("mysql+pymysql://"+self.cf.db_id+":"+self.cf.db_pw+"@"+
self.cf.db_ip + ":" + self.cf.db_port+"/"+db_name,encoding='utf-8')
self.create_basic_database(cursor)
conn.commit()
cursor.close()
conn.close()
self.engine_daily=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+
self.config.db_ip + ":" + self.config.db_port+"/daily_info",encoding='utf-8')
self.engine_stock=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+
self.config.db_ip + ":" + self.config.db_port+"/stock_info",encoding='utf-8')
self.engine_minute=create_engine("mysql+pymysql://"+self.config.db_id+":"+self.config.db_pw+"@"+
self.config.db_ip + ":" + self.config.db_port+"/minute_info",encoding='utf-8')
self.engine_craw = create_engine("mysql+pymysql://" + cf.db_id + ":" + cf.db_pw + "@" + cf.db_ip + ":" +
cf.db_port + "/min_craw",encoding='utf-8')
self.engine_daily_craw = create_engine("mysql+pymysql://" + cf.db_id + ":" + cf.db_pw + "@" + cf.db_ip + ":" +
cf.db_port + "/daily_craw",encoding='utf-8')
self.engine_daily_buy_list = create_engine("mysql+pymysql://" + cf.db_id + ":" + cf.db_pw + "@" + cf.db_ip + ":"
+ cf.db_port + "/daily_buy_list",encoding='utf-8')
# Bot Database가 존재하는지 확인하는 함수
def is_database_exist(self,cursor):
......@@ -304,123 +436,183 @@ class Open_Api(QAxWidget):
query="create database {}"
cursor.execute(query.format(self.db_name))
# information 데이터베이스가 존재하는지 확인
# daily_craw(종목의 날짜별 데이터), daily_buy_list(날짜별 종목 데이터), min_craw(종목의 분별 데이터) 가 존재하는지 확인하는 함수
# 존재하지 않는다면 새로 생성
def create_info_database(self,cursor):
info_list=['daily_info','stock_info','minute_info']
query="select schema_name from information_schema.schemata"
def create_basic_database(self,cursor):
check_list = ['daily_craw', 'daily_buy_list', 'min_craw']
query = "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA"
cursor.execute(query)
result=cursor.fetchall()
print(result)
exist_list=[item[0].lower() for item in result]
create_query="create database {}"
has_created=False
for db in info_list:
if db not in exist_list:
has_created=True
logger.debug(db,"Database not exist. Create the Database.")
cursor.execute(create_query.format(db))
logger.debug(db,"Creation Completed!")
result = cursor.fetchall()
db_list = [n['SCHEMA_NAME'].lower() for n in result]
create_db_query = "CREATE DATABASE {}"
has_created = False
for check_name in check_list:
if check_name not in db_list:
has_created = True
logger.debug(check_name,"데이터베이스 생성...")
create_db_sql = create_db_query.format(check_name)
cursor.execute(create_db_sql)
if has_created and self.engine_bot.has_table('setting_data'):
print("exist")
self.engine_bot.execute("update setting_data set code_update='0")
def create_setting_data(self):
df_data={"limit_money":[],"per_invest":[],"max_per_invest":[],"min_per_invest":[],"set_per_invest":[],
"code_update":[],"today_finish":[],"balance_to_db":[],"posses_stocks":[],"today_profit":[],
"contract_check":[],"final_contract_check":[],"db_to_daily_info":[],"today_buy_list":[],
"stock_info":[],"min_info":[],"daily_info":[]}
df_setting_data=DataFrame(df_data,
columns=['limit_money','per_invest','max_per_invest','min_per_invest','set_per_invest',
'code_update','today_finish','balance_to_db','posses_stocks','today_profit',
'contract_check','final_contract_check','db_to_daily_info','today_buy_list',
'stock_info','min_info','daily_info'])
df_setting_data.loc[0,'limit_money']=int(0)
df_setting_data.loc[0,'per_invest']=int(0)
df_setting_data.loc[0,'max_per_invest']=int(0)
df_setting_data.loc[0,'min_per_invest']=int(0)
df_setting_data.loc[0,'set_per_invest']=str(0)
df_setting_data.loc[0,'code_update']=str(0)
df_setting_data.loc[0,'today_finish']=str(0)
df_setting_data.loc[0,'balance_to_db']=str(0)
df_setting_data.loc[0,'posses_stocks']=str(0)
df_setting_data.loc[0,'today_profit']=float(0)
df_setting_data.loc[0,'contract_check']=str(0)
df_setting_data.loc[0,'final_contract_check']=str(0)
df_setting_data.loc[0,'db_to_daily_info']=str(0)
df_setting_data.loc[0,'today_buy_list']=str(0)
df_setting_data.loc[0,'stock_info']=str(0)
df_setting_data.loc[0,'min_info']=str(0)
df_setting_data.loc[0,'daily_info']=str(0)
df_setting_data.to_sql("setting_data",self.engine_bot,if_exists="replace")
# 시뮬레이터에서 사용할 변수들을 설정
self.engine_bot.execute("UPDATE setting_data SET code_update = '0';")
# setting_data 테이블 생성 및 초기화하는 함수
def init_setting_data(self):
df_setting_data_temp = {'limit_money': [], 'invest_unit': [], 'max_invest_unit': [],
'min_invest_unit': [],'set_invest_unit': [], 'code_update': [],
'today_buy_stop': [],'account_balance_db_check': [], 'possessed_item': [],
'today_profit': [],'final_chegyul_check': [],'db_to_buy_list': [], 'today_buy_list': [],
'daily_crawler': [],'daily_buy_list': []}
df_setting_data = DataFrame(df_setting_data_temp,
columns=['limit_money', 'invest_unit', 'max_invest_unit','min_invest_unit',
'set_invest_unit', 'code_update', 'today_buy_stop',
'account_balance_db_check', 'possessed_item', 'today_profit',
'final_chegyul_check','db_to_buy_list', 'today_buy_list', 'daily_crawler',
'daily_buy_list'])
# 칼럼 자료형 설정
df_setting_data.loc[0, 'limit_money'] = int(0) # 잔고에 최소한으로 남겨놓을 금액
df_setting_data.loc[0, 'invest_unit'] = int(0) # 기준 투자금액
df_setting_data.loc[0, 'max_invest_unit'] = int(0) # 최대 투자금액
df_setting_data.loc[0, 'min_invest_unit'] = int(0) # 최소 투자금액
df_setting_data.loc[0, 'set_invest_unit'] = str(0) # 기준 투자금액 설정 날짜
df_setting_data.loc[0, 'code_update'] = str(0) # setting_data의 데이터를 업데이트 한 날짜
df_setting_data.loc[0, 'today_buy_stop'] = str(0) # 당일 구매 종료 설정 시간
df_setting_data.loc[0, 'account_balance_db_check'] = str(0) # 잔고데이터 DB 업데이트 날짜
df_setting_data.loc[0, 'possessed_item'] = str(0) # 보유종목 DB 업데이트 날짜
df_setting_data.loc[0, 'today_profit'] = str(0) # 당일 수익
df_setting_data.loc[0, 'final_chegyul_check'] = str(0) # 마지막 체결 확인
df_setting_data.loc[0, 'db_to_buy_list'] = str(0) # 구매 리스트 DB 업데이트 날짜
df_setting_data.loc[0, 'today_buy_list'] = str(0) # 당일 구매 리스트 DB 업데이트 날짜
df_setting_data.loc[0, 'daily_crawler'] = str(0) # daily_crawler(종목의 일별 데이터) 업데이트 날짜
df_setting_data.loc[0, 'min_crawler'] = str(0) # min_crawler(종목의 분별 데이터) 업데이트 날자
df_setting_data.loc[0, 'daily_buy_list'] = str(0) # daily_buy_list(일별 종목 데이터) 업데이트 날짜
df_setting_data.to_sql('setting_data', self.engine_JB, if_exists='replace')
# simulator_fun 에서 설정한 변수를 가져오는 함수
def set_simul_variable(self):
self.latest_date=self.simul_api.get_latest_date()
if not self.simul_api.is_table_exist(self.db_name,"transaction_history"):
logger.debug("create transaction_history table")
self.per_invest=0
self.create_transaction_history(0,0,0,0,0)
self.delete_item_by_code(0)
if not self.check_per_invest():
self.set_per_invest()
# daily_buy_list에 저장된 가장 최신 날짜
self.date_rows_yesterday=self.sf.get_recent_daily_buy_list_date()
# AutoBot 데이터베이스에 transaction 테이블이 존재하지 않을 경우
# 테이블 생성 및 초기화
if not self.sf.is_simul_table_exist(self.db_name,"transaction"):
logger.debug("transaction 테이블을 생성합니다")
self.invest_unit=0
self.db_to_transaction(0,0,0,0,0)
# 테이블 생성 후 초기화
self.delete_transaction_item("0")
# setting_data에 invest_unit값이 없다면 설정
if not self.check_set_invest_unit():
self.set_invest_unit()
# 존재한다면 해당 값을 simulator_func에 저장
else:
self.per_invest=self.get_per_invest()
self.simul_api.per_invest=self.per_invest
# transaction_history 테이블 생성 및 column 설정
def create_transaction_history(self,order_num,code,contract_check,purchase_price,rate):
logger.debug("creating transaction_history table")
self.set_date()
self.simul_api.df_transaction_history()
self.simul_api.df_th.loc[0,'order_num']=order_num
self.simul_api.df_th.loc[0,'code']=str(code)
self.simul_api.df_th.loc[0,'reate']=float(rate)
self.simul_api.df_th.loc[0,'buy_date']=self.today_time
self.simul_api.df_th.loc[0,'contract_check']=contract_check
self.simul_api.df_th.loc[0,'per_invest']=self.per_invest
self.simul_api.df_th.loc[0,'purchase_price']=purchase_price
self.simul_api.df_th=self.simul_api.df_th.fillna(0)
self.simul_api.df_th.to_sql('transaction_history',self.engine_bot,if_exists='append')
def delete_item_by_code(self,code):
query="delete from transaction_history where code='%s'"
self.engine_bot.execute(query%code)
# setting_data에 per_invest항목이 설정되어 있는지 확인하는 함수
def check_per_invest(self):
query="select per_invest, set_per_invest from setting_data"
self.invest_unit=self.get_invest_unit()
self.sf.invest_unit=self.invest_unit
# transaction(거래 내역) 테이블 생성
def db_to_transaction(self,order_num,code,chegyul_check,purchase_price,rate):
self.date_setting()
# 거래내역 DataFrame 생성
self.sf.init_df_transaction()
# dataframe에 값 할당
self.sf.df_transaction.loc[0, 'order_num'] = order_num # 주문번호
self.sf.df_transaction.loc[0, 'code'] = str(code) # 종목코드
self.sf.df_transaction.loc[0, 'rate'] = float(rate) # 수익률
self.sf.df_transaction.loc[0, 'buy_date'] = self.today_detail # 구매날짜
self.sf.df_all_item.loc[0, 'chegyul_check'] = chegyul_check # 체결확인
self.sf.df_all_item.loc[0, 'invest_unit'] = self.invest_unit # 투자기준금액
self.sf.df_all_item.loc[0, 'purchase_price'] = purchase_price # 구매금액
if order_num != 0:
recent_daily_buy_list_date=self.sf.get_recent_daily_buy_list_date()
if recent_daily_buy_list_date:
# 특정 날짜, 특정 종목의 주가 데이터
df=self.sf.get_daily_buy_list_by_code(code,recent_daily_buy_list_date)
if not df.empty:
self.sf.df_transaction.loc[0, 'code_name'] = df.loc[0, 'code_name'] # 종목명
self.sf.df_transaction.loc[0, 'close'] = df.loc[0, 'close'] # 종가
self.sf.df_transaction.loc[0, 'open'] = df.loc[0, 'open'] # 시가
self.sf.df_transaction.loc[0, 'high'] = df.loc[0, 'high'] # 고가
self.sf.df_transaction.loc[0, 'low'] = df.loc[0, 'low'] # 저가
self.sf.df_transaction.loc[0, 'volume'] = df.loc[0, 'volume'] # 거래량
self.sf.df_transaction.loc[0,'d1_diff']=float(df.loc[0,'d1_diff']) # 전날대비 가격변동
self.sf.df_transaction.loc[0, 'd1_diff_rate'] = float(df.loc[0, 'd1_diff_rate']) # 전날대비 가격변동률
self.sf.df_transaction.loc[0, 'clo5'] = df.loc[0, 'clo5'] # 5일 이동평균선
self.sf.df_transaction.loc[0, 'clo10'] = df.loc[0, 'clo10'] # 10일 이동평균선
self.sf.df_transaction.loc[0, 'clo20'] = df.loc[0, 'clo20'] # 20일 이동평균선
self.sf.df_transaction.loc[0, 'clo60'] = df.loc[0, 'clo60'] # 60일 이동평균선
self.sf.df_transaction.loc[0, 'clo120'] = df.loc[0, 'clo120'] # 120일 이동평균선
if df.loc[0, 'clo5_diff_rate'] is not None:
self.sf.df_transaction.loc[0, 'clo5_diff_rate'] = float(df.loc[0, 'clo5_diff_rate']) # 5일 이동평균선 변동률
if df.loc[0, 'clo10_diff_rate'] is not None:
self.sf.df_transaction.loc[0, 'clo10_diff_rate'] = float(df.loc[0, 'clo10_diff_rate'])
if df.loc[0, 'clo20_diff_rate'] is not None:
self.sf.df_transaction.loc[0, 'clo20_diff_rate'] = float(df.loc[0, 'clo20_diff_rate'])
if df.loc[0, 'clo60_diff_rate'] is not None:
self.sf.df_transaction.loc[0, 'clo60_diff_rate'] = float(df.loc[0, 'clo60_diff_rate'])
if df.loc[0, 'clo120_diff_rate'] is not None:
self.sf.df_transaction.loc[0, 'clo120_diff_rate'] = float(df.loc[0, 'clo120_diff_rate'])
# null값을 0으로 변환
self.sf.df_all_item = self.sf.df_all_item.fillna(0)
self.sf.df_all_item.to_sql('transaction', self.engine_bot, if_exists='append', dtype={
'code_name': Text,
'rate': Float,
'sell_rate': Float,
'purchase_rate': Float,
'sell_date': Text,
'd1_diff': Integer,
'd1_diff_rate': Float,
'clo5_diff_rate': Float,
'clo10_diff_rate': Float,
'clo20_diff_rate': Float,
'clo60_diff_rate': Float,
'clo120_diff_rate': Float,
})
# 거래내역(transaction) 테이블에서 특정 종목을 삭제하는 함수
def delete_transaction_item(self,code):
query=f"delete from transaction where code={code}"
self.engine_bot.execute(query)
# setting_data 테이블에 invest_unit이 오늘 업데이트 되었는지 확인
def check_set_invest_unit(self):
query="select invest_unit, set_invest_unit from setting_data"
result=self.engine_bot.execute(query).fetchall()
if result[0][1]==self.today:
self.per_invest=result[0][0]
self.invest_unit=result[0][0]
return True
else:
return False
# 데이터베이스에서 per_invest항목을 반환
def get_per_invest(self):
query="select per_invest from setting_data"
# 데이터베이스에서 invest_unit값을 가져오는 함수
def get_invest_unit(self):
query="select invest_unit from setting_data"
result=self.engine_bot.execute(query).fetchall()
return result[0][0]
# per_invest 항목 설정
# per_ invest : 한 종목 당 투자할 금액
def set_per_invest(self):
# invest_unit 항목 업데이트
# 업데이트 완료 후 set_invest_unit에 업데이트 날짜 저장
def set_invest_unit(self):
self.get_deposit()
self.get_balance()
self.total_invest=self.deposit+self.total_purchase
self.total_invest=self.deposit+self.total_purchase_price
self.per_invest=self.simul_api.per_invest
query="update setting_data set per_invest='%s', set_per_invest='%s'"
self.engine_bot.execute(query%(self.per_invest,self.today))
self.invest_unit=self.sf.invest_unit
query=f"update setting_data set invest_unit='{self.invest_unit}', set_invest_unit='{self.today}'"
self.engine_bot.execute(query)
# 예수금 조회 및 저장
def get_deposit(self):
......@@ -429,11 +621,6 @@ class Open_Api(QAxWidget):
self.set_input_value("조회구분",1)
self.comm_rq_data("opw00001_req","opw00001",0,"2000")
# 예수금 상세현황요청 함수
def _opw00001(self,sRQName,sTrCode):
self.deposit=self._get_comm_data(sTrCode,sRQName,0,"d+2출금가능금액")
self.deposit=int(self.deposit)
# 잔고 조회 및 저장
def get_balance(self):
self.reset_opw00018_output()
......@@ -444,64 +631,6 @@ class Open_Api(QAxWidget):
self.set_input_value("계좌번호",self.account_no)
self.comm_rq_data("opw00018_req","opw00018",2,"2000")
# 계좌평가 잔고내역을 저장하는 변수 초기화
def reset_opw00018_output(self):
self.opw00018_output={'single':[],'multi':[]}
# 계좌평가 잔고내역 요청
# 싱글데이터를 통해 계좌에 대한 평가 잔고 데이터를 제공
# 멀티데이터를 통해 보유 종목별 평가 잔고 데이터를 제공
def _opw00018(self,sRQName,sTrCode):
# 계좌평가 잔고 데이터 - 싱글데이터 저장
self.total_purchase=self._get_comm_data(sTrCode,sRQName,0,"총매입금액")
self.total_evaluated_price=self._get_comm_data(sTrCode,sRQName,0,"총평가금액")
self.total_valuation=self._get_comm_data(sTrCode,sRQName,0,"총평가손익금액")
self.earning_rate=self._get_comm_data(sTrCode,sRQName,0,"총수익률(%)")
self.estimated_deposit=self._get_comm_data(sTrCode,sRQName,0,"추정예탁자산")
self.total_purchase=int(self.total_purchase)
self.total_evaluated_price=int(self.total_evaluated_price)
self.total_valuation=int(self.total_valuation)
self.earning_rate=float(self.earning_rate)
self.estimated_deposit=int(self.estimated_deposit)
self.opw00018_output['single'].append(self.total_purchase)
self.opw00018_output['single'].append(self.total_evaluated_price)
self.opw00018_output['single'].append(self.total_valuation)
self.opw00018_output['single'].append(self.earning_rate)
self.opw00018_output['single'].append(self.estimated_deposit)
# 종목별 평가 잔고 데이터 - 멀티데이터 저장
rows=self._get_repeat_cnt(sTrCode,sRQName)
for i in range(rows):
code=self._get_comm_data(sTrCode,sRQName,i,"종목번호")
name=self._get_comm_data(sTrCode,sRQName,i,"종목명")
quantity=self._get_comm_data(sTrCode,sRQName,i,"보유수량")
purchase_price=self._get_comm_data(sTrCode,sRQName,i,"매입가")
current_price=self._get_comm_data(sTrCode,sRQName,i,"현재가")
total_valuation=self._get_comm_data(sTrCode,sRQName,i,"평가손익")
earning_rate=self._get_comm_data(sTrCode,sRQName,i,"수익률(%)")
total_purchase=self._get_comm_data(sTrCode,sRQName,i,"매입금액")
code=code[1:]
quantity=int(quantity)
purchase_price=int(purchase_price)
current_price=int(current_price)
total_valuation=int(total_valuation)
earning_rate=float(earning_rate)
total_purchase=int(total_purchase)
self.opw00018_output['multi'].append(
[name,quantity,purchase_price,current_price,total_valuation,earning_rate,total_purchase,code]
)
# 일자별 실현 손익 요청
def _opt10074(self,sRQName,sTrCode):
self.total_profit=self._get_comm_data(sTrCode,sRQName,0,"실현손익")
self.today_profit=self._get_comm_data(sTrCode,sRQName,0,"당일매도손익")
# open_api를 통해 보유한 종목을 가져오는 함수
# 가져온 정보를 posses_item이라는 테이블에 저장
def get_posses_item(self):
......@@ -556,39 +685,11 @@ class Open_Api(QAxWidget):
self.create_transaction_history(self.not_contract['주문번호'],item.code,contract_check,self.not_contract['체결가'],item.rate)
def _opt10076(self,sRQName,sTrCode):
outputs=['주문번호','종목명','주문구분','주문가격','주문수량','체결가','체결량','미체결수량',
'당일매매수수료','당일매매세금','주문상태','매매구분','원주문번호','주문시간','종목코드']
self.not_contract={}
for key in outputs:
if key not in ['주문번호','원주문번호','주문시간','종목코드']:
self.not_contract[key]=int(self._get_comm_data(sTrCode,sRQName,0,key))
self.not_contract[key]=self._get_comm_data(sTrCode,sRQName,0,key)
# posses_item 테이블을 업데이트 했을 경우 setting data 테이블에 업데이트 한 날짜를 표시
def setting_data_posses_stock(self):
query="update setting_data set posses_stocks='%s'"
self.engine_bot.execute(query%self.today)
def reset_opt10073_output(self):
self.opt10073_output={'single':[],'multi':[]}
def _opt10073(self,sRQName,sTrCode):
rows=self._get_repeat_cnt(sTrCode,sRQName)
for i in range(rows):
date=self._get_comm_data(sTrCode,sRQName,i,"일자")
code=self._get_comm_data(sTrCode,sRQName,i,"종목코드")
code_name=self._get_comm_data(sTrCode,sRQName,i,"종목명")
amount=self._get_comm_data(sTrCode,sRQName,i,"체결량")
today_profit=self._get_comm_data(sTrCode,sRQName,i,"당일매도손익")
earning_rate=self._get_comm_data(sTrCode,sRQName,i,"손익율")
code=code.lstrip('A')
self.opt10073_output['multi'].append([date,code,code_name,amount,today_profit,earning_rate])
# 특정 종목의 일자별 거래 데이터 조회 함수
def get_date_data(self,code,code_name,date):
self.ohlcv=defaultdict(list)
......@@ -625,26 +726,6 @@ class Open_Api(QAxWidget):
else:
return False
# 주식 일봉차트 조회 요청
# 주식의 날짜별 데이터를 저장하는 함수
def collector_opt10081(self,sRQName,sTrCode):
ohlcv_cnt=self._get_repeat_cnt(sTrCode,sRQName)
for i in range(ohlcv_cnt):
date=self._get_comm_data(sTrCode,sRQName,i,"일자")
open=self._get_comm_data(sTrCode,sRQName,i,"시가")
high=self._get_comm_data(sTrCode,sRQName,i,"고가")
low=self._get_comm_data(sTrCode,sRQName,i,"저가")
close=self._get_comm_data(sTrCode,sRQName,i,"현재가")
volume=self._get_comm_data(sTrCode,sRQName,i,"거래량")
self.ohlcv['date'].append(date)
self.ohlcv['open'].append(int(open))
self.ohlcv['high'].append(int(high))
self.ohlcv['low'].append(int(low))
self.ohlcv['close'].append(int(close))
self.ohlcv['volume'].append(int(volume))
# stock_info의 특정 종목 테이블에서 마지막으로 저장된 날짜를 가져오는 함수
# 저장된 데이터가 없다면 '0'문자를 반환
def get_latest_date_from_stock_info(self,code_name):
......@@ -697,6 +778,167 @@ class Open_Api(QAxWidget):
"where code='%s' and sell_date='%s'"
self.engine_bot.execute(query%(0,self.today_time,code,0))
# 주식일봉차트조회 요청 함수 - 하나의 데이터만 저장
def _opt10081(self, sRQName, sTrCode):
code = self._get_comm_data(sTrCode, sRQName, 0, "종목코드")
# 조회하는 종목이 매수하려는 종목이 아니라면 에러메세지 출력
if code != self.get_today_buy_list_code:
logger.critical(f"_opt10081:({code},{self.get_today_buy_list_code})")
date = self._get_comm_data(sTrCode, sRQName, 0, "일자")
open = self._get_comm_data(sTrCode, sRQName, 0, "시가")
high = self._get_comm_data(sTrCode, sRQName, 0, "고가")
low = self._get_comm_data(sTrCode, sRQName, 0, "저가")
close = self._get_comm_data(sTrCode, sRQName, 0, "현재가")
volume = self._get_comm_data(sTrCode, sRQName, 0, "거래량")
self.ohlcv['date'].append(date)
self.ohlcv['open'].append(int(open))
self.ohlcv['high'].append(int(high))
self.ohlcv['low'].append(int(low))
self.ohlcv['close'].append(int(close))
self.ohlcv['volume'].append(int(volume))
# 주식일봉차트조회 요청 함수 - 모든 행의 데이터를 저장
def collector_opt10081(self, sRQName, sTrCode):
# 몇개의 행을 읽어야 하는지 담는 변수
ohlcv_cnt = self._get_repeat_cnt(sTrCode, sRQName)
for i in range(ohlcv_cnt):
date = self._get_comm_data(sTrCode, sRQName, i, "일자")
open = self._get_comm_data(sTrCode, sRQName, i, "시가")
high = self._get_comm_data(sTrCode, sRQName, i, "고가")
low = self._get_comm_data(sTrCode, sRQName, i, "저가")
close = self._get_comm_data(sTrCode, sRQName, i, "현재가")
volume = self._get_comm_data(sTrCode, sRQName, i, "거래량")
self.ohlcv['date'].append(date)
self.ohlcv['open'].append(int(open))
self.ohlcv['high'].append(int(high))
self.ohlcv['low'].append(int(low))
self.ohlcv['close'].append(int(close))
self.ohlcv['volume'].append(int(volume))
# 예수금 상세현황요청 함수
def _opw00001(self,sRQName,sTrCode):
self.deposit=self._get_comm_data(sTrCode,sRQName,0,"d+2출금가능금액")
self.deposit=int(self.deposit)
# 계좌평가 잔고내역을 저장하는 변수 초기화
def reset_opw00018_output(self):
# single data : 계좌에 대한 평가 잔고 데이터 제공
# multi data : 보유 종목별 평가 잔고 데이터 제공
self.opw00018_output={'single':[],'multi':[]}
# 계좌평가 잔고내역 요청 함수
def _opw00018(self,sRQName,sTrCode):
# 계좌평가 잔고 데이터 - 싱글데이터 저장
self.total_purchase_price=self._get_comm_data(sTrCode,sRQName,0,"총매입금액")
self.total_eval_price=self._get_comm_data(sTrCode,sRQName,0,"총평가금액")
self.total_eval_profit_loss_price=self._get_comm_data(sTrCode,sRQName,0,"총평가손익금액")
self.total_earning_rate=self._get_comm_data(sTrCode,sRQName,0,"총수익률(%)")
self.estimated_deposit=self._get_comm_data(sTrCode,sRQName,0,"추정예탁자산")
self.total_purchase_price=int(self.total_purchase_price)
self.total_eval_price=int(self.total_eval_price)
self.total_eval_profit_loss_price=int(self.total_eval_profit_loss_price)
self.total_earning_rate=float(self.total_earning_rate)
self.estimated_deposit=int(self.estimated_deposit)
self.opw00018_output['single'].append(self.total_purchase_price)
self.opw00018_output['single'].append(self.total_eval_price)
self.opw00018_output['single'].append(self.total_eval_profit_loss_price)
self.opw00018_output['single'].append(self.total_earning_rate)
self.opw00018_output['single'].append(self.estimated_deposit)
# 종목별 평가 잔고 데이터 - 멀티데이터 저장
rows=self._get_repeat_cnt(sTrCode,sRQName)
for i in range(rows):
code=self._get_comm_data(sTrCode,sRQName,i,"종목번호")
name=self._get_comm_data(sTrCode,sRQName,i,"종목명")
quantity=self._get_comm_data(sTrCode,sRQName,i,"보유수량")
purchase_price=self._get_comm_data(sTrCode,sRQName,i,"매입가")
current_price=self._get_comm_data(sTrCode,sRQName,i,"현재가")
eval_profit_loss_price=self._get_comm_data(sTrCode,sRQName,i,"평가손익")
earning_rate=self._get_comm_data(sTrCode,sRQName,i,"수익률(%)")
item_total_purchase=self._get_comm_data(sTrCode,sRQName,i,"매입금액")
code=code[1:]
quantity=int(quantity)
purchase_price=int(purchase_price)
current_price=int(current_price)
eval_profit_loss_price=int(eval_profit_loss_price)
earning_rate=float(earning_rate)
item_total_purchase=int(item_total_purchase)
self.opw00018_output['multi'].append(
[name,quantity,purchase_price,current_price,eval_profit_loss_price,earning_rate,item_total_purchase,code]
)
# 일자별 실현 손익 요청
def _opt10074(self,sRQName,sTrCode):
self.total_profit=self._get_comm_data(sTrCode,sRQName,0,"실현손익")
self.today_profit=self._get_comm_data(sTrCode,sRQName,0,"당일매도손익")
# 위탁종합거래내역 요청 함수
def _opw00015(self,sRQName,sTrCode):
rows = self._get_repeat_cnt(sTrCode, sRQName)
acc_no = self._get_comm_data(sTrCode, sRQName, 1, "계좌번호")
for i in range(rows):
date = self._get_comm_data(sTrCode, sRQName, i, "거래일자")
# 실시간체결요청 함수
def _opt10076(self,sRQName,sTrCode):
outputs=['주문번호','종목명','주문구분','주문가격','주문수량','체결가','체결량','미체결수량',
'당일매매수수료','당일매매세금','주문상태','매매구분','원주문번호','주문시간','종목코드']
self._data={}
for key in outputs:
if key not in ['주문번호','원주문번호','주문시간','종목코드']:
self._data[key]=int(self._get_comm_data(sTrCode,sRQName,0,key))
continue
self._data[key]=self._get_comm_data(sTrCode,sRQName,0,key)
# _opt10073 결과를 담는 변수를 초기화하는 함수
def reset_opt10073_output(self):
self.opt10073_output={'single':[],'multi':[]}
# 일자별종목별실현손익요청 함수
def _opt10073(self,sRQName,sTrCode):
rows=self._get_repeat_cnt(sTrCode,sRQName)
for i in range(rows):
date=self._get_comm_data(sTrCode,sRQName,i,"일자")
code=self._get_comm_data(sTrCode,sRQName,i,"종목코드")
code_name=self._get_comm_data(sTrCode,sRQName,i,"종목명")
amount=self._get_comm_data(sTrCode,sRQName,i,"체결량")
today_profit=self._get_comm_data(sTrCode,sRQName,i,"당일매도손익")
earning_rate=self._get_comm_data(sTrCode,sRQName,i,"손익율")
code=code.lstrip('A')
self.opt10073_output['multi'].append([date,code,code_name,amount,today_profit,earning_rate])
# 주식분봉차트조회요청 함수
def _opt10080(self,sRQName,sTrCode):
data_cnt = self._get_repeat_cnt(sTrCode, sRQName)
for i in range(data_cnt):
date = self._get_comm_data(sTrCode, sRQName, i, "체결시간")
open = self._get_comm_data(sTrCode, sRQName, i, "시가")
high = self._get_comm_data(sTrCode, sRQName, i, "고가")
low = self._get_comm_data(sTrCode, sRQName, i, "저가")
close = self._get_comm_data(sTrCode, sRQName, i, "현재가")
volume = self._get_comm_data(sTrCode, sRQName, i, "거래량")
self.ohlcv['date'].append(date[:-2])
self.ohlcv['open'].append(abs(int(open)))
self.ohlcv['high'].append(abs(int(high)))
self.ohlcv['low'].append(abs(int(low)))
self.ohlcv['close'].append(abs(int(close)))
self.ohlcv['volume'].append(int(volume))
self.ohlcv['sum_volume'].append(int(0))
if __name__=="__main__":
app=QApplication(sys.argv)
......