이하영

주간보고서

......@@ -6,7 +6,7 @@ from pandas import *
from Logger import *
import cf
class Simulator_Func:
class Simulator_Api:
def __init__(self,simul_num,op,db_name):
self.simul_num=int(simul_num)
......@@ -231,18 +231,18 @@ class Simulator_Func:
index=a_balance['id'])
# transaction table 생성
def init_df_transaction(self):
trs={'id':[]}
self.df_transaction=DataFrame(trs,
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',
'yes_close', 'close', 'd1_diff_rate', 'd1_diff',
'open', 'high','low','volume',
'clo5', 'clo10', 'clo20', 'clo60','clo120',
"clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate",
"clo60_diff_rate", "clo120_diff_rate"])
def init_df_all_stocks(self):
all_stocks={'id':[]}
self.df_all_stocks=DataFrame(all_stocks,
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',
'yes_close','d1_diff_rate', 'd1_diff',
'open', 'close','high','low','volume',
'clo5', 'clo10', 'clo20', 'clo60','clo120',
"clo5_diff_rate", "clo10_diff_rate","clo20_diff_rate",
"clo60_diff_rate", "clo120_diff_rate"])
# account_balance(잔고 데이터)에 저장된 가장 최근의 날짜를 가져오는 함수
def get_last_date_account_balance(self):
......@@ -1217,4 +1217,4 @@ class Simulator_Func:
"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
return df_daily_buy_list
\ No newline at end of file
......
......@@ -39,24 +39,27 @@ class Open_Api(QAxWidget):
# 변수 설정
self.set_variable()
self.sf=Simulator_Func(self.simul_num,"real",self.db_name)
self.sf=Simulator_Api(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"):
if not self.sf.is_simul_table_exist(self.db_name,"setting_data"):
self.init_setting_data()
# invest unit 설정
self.set_simul_variable()
self.ohlcv=defaultdict(list)
# 날짜 설정
# -* date_setting
def set_date(self):
self.today=datetime.datetime.today().strftime("%Y%m%d")
self.today_time=datetime.datetime.today().strftime("%Y%m%d%H%M")
# 키움 open_api 를 사용하기 위한 ocx controller 생성
# -* create_open_api_instance
def _create_instance(self):
try:
self.setControl("KHOPENAPI.KHOpenAPICtrl.1")
......@@ -92,9 +95,10 @@ class Open_Api(QAxWidget):
# 사용자의 계좌정보 저장 및 출력
def get_account_info(self):
logger.debug("-* get_account_info 함수 *-")
account_no=self.get_login_info("ACCNO")
self.account_no=account_no.split(";")[0]
logger.debug(self.account_no)
logger.debug("계좌번호 : ", self.account_no)
# 원하는 사용자 정보 반환
# param : tag - ACCNO - 보유계좌리스트
......@@ -371,18 +375,19 @@ class Open_Api(QAxWidget):
# 변수 설정
# 실전투자인지 모의투자인지 여부를 확인하고 그에 해당하는 데이터베이스를 생성하는 함수
def set_variable(self):
logger.debug("-* set variable 함수 *-")
self.cf=cf
self.get_today_buy_list_code=0
self.reset_opw00018_output()
if self.account_no==self.cf.real_account_no:
logger.debug("실전투자")
logger.debug("실전투자 - 계좌번호 : ",self.account_no)
self.simul_num=self.cf.real_num
self.set_database(cf.real_bot_name)
self.mod_gubun=100 # 실전투자와 모의투자를 구분하는 변수
elif self.account_no==self.cf.test_account_no:
logger.debug("모의투자")
logger.debug("모의투자 - 계좌번호 : ",self.account_no)
self.simul_num=self.cf.test_num
self.set_database(cf.test_bot_name)
self.mod_gubun=1
......@@ -395,6 +400,7 @@ class Open_Api(QAxWidget):
self.py_gubun=False
# 데이터베이스 생성 및 엔진 설정
# -* db_name_setting
def set_database(self,db_name):
self.db_name=db_name
conn=pymysql.connect(
......@@ -402,8 +408,10 @@ class Open_Api(QAxWidget):
port=int(cf.db_port),
user=cf.db_id,
password=cf.db_pw,
charset='utf8mb4'
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
cursor=conn.cursor()
if not self.is_database_exist(cursor):
self.create_database(cursor)
......@@ -422,22 +430,23 @@ class Open_Api(QAxWidget):
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가 존재하는지 확인하는 함수
# bot database가 존재하는지 확인하는 함수
def is_database_exist(self,cursor):
query="select 1 from information_schema.schemata where schema_name='{}'"
result=cursor.execute(query.format(self.db_name))
query=f"select 1 from information_schema.schemata where schema_name='{self.db_name}'"
result=cursor.execute(query)
if result:
return True
else:
return False
# Bot Database를 생성하는 함수
# bot database를 생성하는 함수
def create_database(self,cursor):
query="create database {}"
cursor.execute(query.format(self.db_name))
query=f"create database {self.db_name}"
cursor.execute(query)
# daily_craw(종목의 날짜별 데이터), daily_buy_list(날짜별 종목 데이터), min_craw(종목의 분별 데이터) 가 존재하는지 확인하는 함수
# 존재하지 않는다면 새로 생성
# -* basic_db_check
def create_basic_database(self,cursor):
check_list = ['daily_craw', 'daily_buy_list', 'min_craw']
query = "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA"
......@@ -449,25 +458,26 @@ class Open_Api(QAxWidget):
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)
logger.debug(f"{check_name} 데이터베이스 생성...")
cursor.execute(create_db_query.format(check_name))
if has_created and self.engine_bot.has_table('setting_data'):
self.engine_bot.execute("UPDATE setting_data SET code_update = '0';")
# setting_data 테이블 생성 및 초기화하는 함수
def init_setting_data(self):
logger.debug("-* init_setting_data 함수 *-")
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_buy_stop': [],'jango_data_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',
'jango_data_db_check', 'possessed_item', 'today_profit',
'final_chegyul_check','db_to_buy_list', 'today_buy_list', 'daily_crawler',
'daily_buy_list'])
......@@ -480,7 +490,7 @@ class Open_Api(QAxWidget):
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, 'jango_data_db_check'] = str(0) # 잔고데이터 DB 업데이트 날짜
df_setting_data.loc[0, 'possessed_item'] = str(0) # 보유종목 DB 업데이트 날짜
df_setting_data.loc[0, 'today_profit'] = str(0) # 당일 수익
......@@ -495,16 +505,17 @@ class Open_Api(QAxWidget):
# simulator_fun 에서 설정한 변수를 가져오는 함수
def set_simul_variable(self):
logger.debug("-* set simul variable 함수 *-")
# 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 테이블을 생성합니다")
# AutoBot 데이터베이스에 all_stock 테이블이 존재하지 않을 경우 테이블 생성 및 초기화
# all_stock : 모든 주식 거래 내역을 저장하는 테이블
if not self.sf.is_simul_table_exist(self.db_name,"all_stocks"):
logger.debug("all_stocks 테이블을 생성합니다")
# 테이블 생성 후 초기화
self.invest_unit=0
self.db_to_transaction(0,0,0,0,0)
# 테이블 생성 후 초기화
self.delete_transaction_item("0")
# setting_data에 invest_unit값이 없다면 설정
......@@ -515,11 +526,11 @@ class Open_Api(QAxWidget):
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):
# all_stock(거래 내역) 테이블 생성
def db_to_all_stocks(self,order_num,code,chegyul_check,purchase_price,rate):
logger.debug("-* db_to_all_stocks function *-")
self.date_setting()
# 거래내역 DataFrame 생성
self.sf.init_df_transaction()
self.sf.init_df_all_stocks() # all_stocks 테이블 데이터프레임 생성
# dataframe에 값 할당
self.sf.df_transaction.loc[0, 'order_num'] = order_num # 주문번호
......@@ -632,38 +643,36 @@ class Open_Api(QAxWidget):
self.comm_rq_data("opw00018_req","opw00018",2,"2000")
# open_api를 통해 보유한 종목을 가져오는 함수
# 가져온 정보를 posses_item이라는 테이블에 저장
def get_posses_item(self):
# 가져온 정보를 possesd_item이라는 테이블에 저장
def db_to_possessd_item(self):
item_count=len(self.opw00018_output['multi'])
posses_item_data={'date':[],'code':[],'code_name':[],'holding_amount':[],'purchase_price':[],
possesd_item_data={'date':[],'code':[],'code_name':[],'holding_amount':[],'purchase_price':[],
'present_price':[],'valuation_profit':[],'rate':[],'item_total_purchase':[]}
posses_item=DataFrame(posses_item_data,
possesd_item=DataFrame(possesd_item_data,
columns=['date','code','code_name','holding_amount','purchase_price',
'present_price','valuation_profit','rate','item_total_purchase'])
for i in range(item_count):
item=self.opw00018_output['multi'][i]
posses_item.loc[i,'date']=self.today
posses_item.loc[i,'code']=item[7]
posses_item.loc[i,'code_name']=item[0]
posses_item.loc[i,'holding_amount']=int(item[1])
posses_item.loc[i,'purchase_price']=int(item[2])
posses_item.loc[i,'present_price']=int(item[3])
posses_item.loc[i,'valuation_profit']=int(item[4])
posses_item.loc[i,'rate']=float(item[5])
posses_item.loc[i,'item_total_purchase']=int(item[6])
posses_item.to_sql("posses_item",self.engine_bot,if_exists='replace')
possesd_item.loc[i,'date']=self.today
possesd_item.loc[i,'code']=item[7]
possesd_item.loc[i,'code_name']=item[0]
possesd_item.loc[i,'holding_amount']=int(item[1])
possesd_item.loc[i,'purchase_price']=int(item[2])
possesd_item.loc[i,'present_price']=int(item[3])
possesd_item.loc[i,'valuation_profit']=int(item[4])
possesd_item.loc[i,'rate']=float(item[5])
possesd_item.loc[i,'item_total_purchase']=int(item[6])
possesd_item.to_sql("possesd_item",self.engine_bot,if_exists='replace')
self.contract_sync()
# 현재 소유하고 있는 종목에 대해 transaction_history 테이블을 업데이트
def contract_sync(self):
query="select code,code_name,rate from posses_item p" \
"where p.code not in (select a.code from transaction_history a" \
"where a.sell_date='0' group by a.code)" \
"group by p.code"
# 현재 소유하고 있는 종목에 대해 transaction 테이블을 업데이트
def chegyul_sync(self):
query="select code,code_name,rate from possessed_item " \
"where code not in (select code from transaction where sell_date='0' group by code) group by code"
result=self.engine_bot.execute(query).fetchall()
for item in result:
......@@ -672,18 +681,18 @@ class Open_Api(QAxWidget):
self.set_input_value("계좌번호",self.account_no)
self.comm_rq_data("opt10076_req","opt10076",0,"0350")
if self.not_contract['주문구분']=="+매수":
if self.not_contract['미체결수량']==0:
contract_check=0
if self._data['주문구분']=='+매수':
if self._data['미체결수량']==0:
chegyul_check=0
else:
contract_check=1
elif self.not_contract['주문구분']=='':
self.create_transaction_history(self.today,item.code,0,0,item.rate)
chegyul_check=1
elif self._data['주문구분']=='':
self.db_to_transaction(self.today,item.code,0,0,item.rate)
continue
else:
continue
self.create_transaction_history(self.not_contract['주문번호'],item.code,contract_check,self.not_contract['체결가'],item.rate)
self.db_to_transaction(self.not_contract['주문번호'],item.code,contract_check,self.not_contract['체결가'],item.rate)
# posses_item 테이블을 업데이트 했을 경우 setting data 테이블에 업데이트 한 날짜를 표시
def setting_data_posses_stock(self):
......@@ -736,8 +745,9 @@ class Open_Api(QAxWidget):
else:
return str(0)
def check_contract(self):
query="select code from transaction_history where contract_check='1' and (sell date='0' or sell_date='')"
# 체결이 완료되었는지 확인하고 transaction(거래내역) 테이블을 업데이트하는 함수
def check_chegyul(self):
query="select code from transaction where chegyul_check='1'"
rows=self.engine_bot.execute(query).fetchall()
for r in rows:
......@@ -746,18 +756,30 @@ class Open_Api(QAxWidget):
self.set_input_value("계좌번호",self.account_no)
self.comm_rq_data("opt10076_req","opt10076",0,"0350")
query="update transaction_history set contract_check='0' where code='{}' and sell_date='0'"
query=f"update transaction set chegyul_check='0' where code='{r.code}' and sell_data='0' " \
f"order by buy_date desc limit 1"
# 거래가 완료된 항목은 주문번호가 존재하지 않음
# 거래가 완료된 항목에 대해서 contract_check항목을 '0'으로 업데이트
if not self.not_contract['주문번호']:
self.engine_bot.execute(query.format(r.code))
self.engine_bot.execute(query)
# 미체결 수량이 없을 경우 contract_check항목을 '0'으로 업데이트
elif self.not_contract['미체결수량']==0:
logger.debug("미체결 항목이 없습니다")
self.engine_bot.execute(query.format(r.code))
self.engine_bot.execute(query)
else:
logger.debug("미체결 종목이 존재합니다")
# 매도했을 경우 possessed_item(보유종목) 테이블에서 항목을 삭제
def delete_possessed_item(self,code):
query=f"delete from possessed_item where code={code}"
self.engine_bot.execute(query)
# 매도한 후 transaction 테이블 업데이트
def check_sell_final(self,code):
query=f"update transaction chegyul_check='0', sell_date='{self.today_time}' " \
f"where code='{code}' and sell_date='0' order by buy_date desc"
self.engine_bot.execute(query)
# posses_item테이블에는 존재하지만 transaction_history테이블에 존재하지 않는 항목에 대해 업데이트
def final_check_contract(self):
query="select code from transaction_history" \
......@@ -778,6 +800,58 @@ class Open_Api(QAxWidget):
"where code='%s' and sell_date='%s'"
self.engine_bot.execute(query%(0,self.today_time,code,0))
# 현재 보유하고 있는 종목의 수를 반환하는 함수
def get_count_possessed_item(self):
query="select count(*) from possessed_item"
result=self.engine_bot.execute(query).fetchall()
return result[0][0]
# setting_data에 possessed_item 항목을 업데이트
def set_setting_data_possessed_item(self):
query=f"update setting_data set possessed_item={self.today}"
self.engine_bot.execute(query)
def get_total_data_min(self,code,code_name,start):
self.ohlcv=defaultdict(list)
self.set_input_value("종목코드",code)
self.set_input_value("틱범위",1)
self.set_input_value("수정주가구분",1)
self.comm_rq_data("opt10080_req","opt10080",0,"1999")
self.is_craw_table_exist=False
if self.is_min_craw_table_exist(code_name):
self.is_craw_table_exist=True
self.craw_db_last_min=self.get_craw_db_last_min(code_name)
self.craw_db_last_min_sum_volume=self.get_craw_db_last_min_sum_volume(code_name)
else:
self.craw_db_last_min=str(0)
self.craw_db_last_min_sum_volume=0
while self.remained_data:
time.sleep(TR_REQ_TIME_INTERVAL)
self.set_input_value("종목코드",code)
self.set_input_value("틱범위",1)
self.set_input_value("수정주가구분",1)
self.comm_rq_data("opt10080_req","opt10080",2,"1999")
if self.ohlcv['date'][-1]<self.craw_db_last_min:
break
time.sleep(TR_REQ_TIME_INTERBVAL)
if len(self.ohlcv['date']==0 or self.ohlcv['date'][0]==''):
return []
if self.ohlcv['date']=='':
return []
df = DataFrame(self.ohlcv, columns=['date', 'open', 'high', 'low', 'close', 'volume', 'sum_volume'])
return df
# 주식일봉차트조회 요청 함수 - 하나의 데이터만 저장
def _opt10081(self, sRQName, sTrCode):
code = self._get_comm_data(sTrCode, sRQName, 0, "종목코드")
......
No preview for this file type
No preview for this file type