PYTHON/Kiwoom Open API

키움증권 Open API - 차트 데이터 관리 DB 제작 (2)

  • -

지난 게시글에서 item_savepoint라는 데이터베이스 안에 item_savepoint라는 테이블을 생성한 채로 마무리했으니 이번 게시글에서는 그 내용에 이어서 item_savepoint라는 테이블 안에 종목 코드들을 입력하고 차트 데이터를 저장한 경우에는 저장이 된 날짜를 입력하도록 하는 방법에 대해 알아볼 예정이다.

 

종목코드 입력하기

item_savepoint 안에는 'code'와 'sv_day'라는 두 개의 칼럼이 있는데, 그 중 code라는 부분에 종목 코드를 입력하기 위한 코드는 어떤 구조를 갖추고 있는지 알아보자. 결론부터 말하자면, 앞의 게시글에서도 여러 번 사용했었지만 cur.execute()라는 형태를 이용하되, 그 안에서 사용할 명령어는 INSERT이다. 즉, 무언갈 생성할 때에는 CREATE, 제거할 때에는 DROP 또는 DELETE, 정보를 변경할 때에는 UPDATE, 정보를 입력할 때에는 INSERT이다. UPDATE의 경우에는 입력하고자 하는 정보가 들어갈 행과 열 그리고 어떤 값을 어떤 값으로 변경할지를 확인하는 것이다. 차트 데이터가 언제 일자를 기준으로 저장되어 있는지를 확인하기 위해서는 굳이 복잡한 UPDATE보다는 INSERT를 사용하는 것이 편하다고 생각하기 때문에, INSERT를 사용할 예정이다. INSERT 명령어의 기본적인 형태는 아래와 같다.

  • cur.execute("INSERT INTO 'db_name'.'table_name' (columns_name) VALUES (data)") 

그렇다면 이 역시 하나의 함수로 제작해서 관리한다면 정말 편할테니, 이에 대한 함수도 제작하고 넘어가도록 하자. 함수를 제작할 때 사용할 변수로는 위의 내용에서 확인할 수 있듯이 db_name, table_name, columns_name, data의 네 개다.

def insert_into(db_name, table_name, columns_name, data):
	connect = mysql.connector.connect(user='root', password=PASSWORD, host='127.0.0.1', charset='utf8mb4')
	cur = connect.cursor()

	send_message = "INSERT INTO `" + db_name + "`.`" + table_name + "` (" + columns_name + ") VALUES ('" + data + "');"
	cur.execute(send_message)
	connect.commit()

이 코드에서 cur.execute()의 괄호 안에 명령어를 입력하지 않고 send_message라는 변수에 입력하고 이 변수를 사용하는 이유는 바로 000020과 같은 종목코드의 형태 때문이다. 즉, cur.execute()안에 000020은 아무리 str()을 씌우든 뭘 하든 간에 MySQL 안에는 앞의 '0000'을 제외한 '20'만 들어가게 되는 오류가 발생한다. 따라서 send_message를 통해 명령어를 만들어준 후에 cur.execute()안에 전달해주면 000020과 같은 형태로 입력된다. 

이제 Open API에 관한 코드가 들어 있는 파일로 돌아와서, if문 하단에 다음과 같이 코드를 제작한 후에 코드를 실행시키면 아래와 같은 결과를 얻을 수 있다. (본인의 경우에는 앞서 제작한 insert_into 함수나 check_db, check_table 세 개의 함수는 모두 posting_mysql이라는 파일 안에 있다.) 

code_list = trade.filtered_code()
print(code_list)

for code in code_list:
	posting_mysql.insert_into('item_savepoint', 'item_savepoint', 'code', str(code))
	print("종목코드:", code, " DB에 입력되었습니다.")
종목코드: 000020  DB에 입력되었습니다.
종목코드: 000040  DB에 입력되었습니다.
종목코드: 000050  DB에 입력되었습니다.
종목코드: 000060  DB에 입력되었습니다.
종목코드: 000070  DB에 입력되었습니다.
종목코드: 000080  DB에 입력되었습니다.
종목코드: 000100  DB에 입력되었습니다.
종목코드: 000120  DB에 입력되었습니다.

 

 

종목코드 입력 시 발생하는 오류

종목코드를 입력하는 코드를 실행했을 때, 오류가 발생하는 몇 가지 경우들이 있다. 

mysql.connector.errors.ProgrammingError: 1054 (42S22): Unknown column '00104K' in 'field list'

이는 종목 코드에 K가 들어 있어서 오류가 발생하는 것인데, 00104K를 네이버에 검색해보면 'CJ4우(전환)'이라는 이름이 나온다. 우선주는 걸렀음에도 불구하고 아직 남아 있는 것을 보니, 미처 발견하지 못했던 것으로 보인다. 따라서 우리는 filtered_code() 함수 내에 "4우" in codename이라는 내용을 추가함으로써 해당 오류를 해결할 수 있다. 

 

mysql.connector.errors.DataError: 1136 (21S01): Column count doesn't match value count at row 1

이 오류는 칼럼의 수와 값의 수가 일치하지 않는다는 것인데, 원인을 찾아보면 어렵지 않게 확인할 수 있다. 즉, 입력하고자 하는 종목코드가 없는데 INSERT INTO를 사용한 경우에 발생하는 오류인 것이다. 실제로 filtered_code() 함수의 결과값을 보면 맨 뒤에 아무런 종목코드 없이 ''으로 표시된 부분이 있는데, 그것 때문에 발생하는 오류인 것이다.

오류 처리의 경우에는 try:와 except:를 통해서 처리할 수 있는데, 일단 for문을 try:문으로 감싸고 try:와 같은 열에 except를 입력해주면 된다.

try:
  for code in code_list:
    posting_mysql.insert_into('item_savepoint', 'item_savepoint', 'code', code)
    print("종목코드:", code, " DB에 입력되었습니다.")
except:

이제 except 뒤 부분에는 발생한 오류를 입력해주어야 하는데, 위의 경우에는 mysql.connector.errors.DataError가 오류의 이름에 해당한다. 따라서 except 뒤에 해당 내용을 적어준 후에, pass를 입력해주면 된다. 다시 말해 try문 아래의 코드를 실행하다가 mysql.connector.errors.DataError 오류가 발생한 경우에는 pass하라는 것이다. 다만 우리는 mysql을 임포트한 파일이 posting_mysql이기 때문에, 해당 오류 처리 역시 posting_mysql.mysql.connector.error.DataError로 입력해주어야 오류 처리가 제대로 된다.

try:
	for code in code_list:
		posting_mysql.insert_into('item_savepoint', 'item_savepoint', 'code', code)
		print("종목코드:", code, " DB에 입력되었습니다.")
except posting_mysql.mysql.connector.errors.DataError:
	pass

 


728x90

 

 

차트 데이터 저장한 후에 item_savepoint에 저장값 입력하기

차트 데이터를 저장한 후에 저장값을 입력하는 부분 역시 하나의 함수를 사용함으로써 보다 간편하게 처리할 수 있다. 이 부분은 'sv_day'에 일봉 차트 데이터를 저장했는지의 여부를 입력할 때 뿐만 아니라 분봉 데이터 등 다양한 경우에 사용할 수 있기 때문에 정말 유용할 것이다. 따라서 이번에도 마찬가지로 UPDATE 명령어에 대한 처리 함수를 제작해주도록 하자. UPDATE는 아래와 같은 방식으로 사용할 수 있다. 

  • cur.exectue("UPDATE 'db_name'.'table_name' SET 'columns_name'='data', WHERE 'columns_name'='data'

앞 부분의 db_name과 table_name은 생략하도록 하고, SET 부분과 WHERE 부분만 보도록 하자. 먼저 SET 뒤에 있는 'columns_name'과 'data' 부분은, 각각 우리가 입력하고자 하는 데이터가 들어갈 칼럼의 이름과 입력할 데이터를 의미한다. 다음으로 WHERE 뒤에 있는 'columns_name'과 'data'는 우리가 설정할 조건에 해당한다. 가령, 우리는 이 형식을 아래와 같이 사용할 예정이다.

  • cur.execute("UPDATE 'item_savepoint'.'item_savepoint' SET 'sv_day'='20210101', WHERE 'code'='000020'

즉 칼럼명이 'code'이고 그 값이 000020인 곳에 칼럼명 'sv_day' 아래에 '20210101'이라는 값을 입력하라는 것이다. 

def update_data(db_name, table_name, columns_name, data, where_columns, where_data):
	connect = mysql.connector.connect(user='root', password=PASSWORD, host='127.0.0.1', charset='utf8mb4')
	cur = connect.cursor()

	update_data = "UPDATE `" + db_name + "`.`" + table_name + "` SET `" + columns_name + "`='" + data + "' WHERE `" + where_columns + "`='" + where_data + "'"
	cur.execute(update_data)
	connect.commit()

 

차트 데이터를 저장하는 게시글에서 작성했던 차트 데이터 저장 관련 코드는 아래와 같다.

for code in code_list:
	print("종목 코드:", code)
	trade.rq_chart_data(code, "20210101", 1)
	df_day_data = pandas.DataFrame(trade.day_data, columns=['date', 'open', 'high', 'low', 'close', 'volume', 'trade_volume'])
	print(df_day_data)
	df_day_data.to_sql(name="s" + code, con=engine_all, index=False, if_exists='replace')
	print("종목코드:", code, "  데이터베이스에 저장되었습니다.")

 

그렇다면 이제 차트 데이터는 저장 했으니, 오늘 일자로 저장되었음을 item_savepoint 데이터베이스에 입력하도록 하자. (이와 관련하여 거래일 기준 최신 일자를 반환하는 코드를 다른 게시글에서 작성했었다. 해당 코드를 이용하여 최신 거래일을 불러온 후에, insert_into 함수의 변수로 전달해주도록 하자. 본인의 경우에는 해당 게시글 내에 있는 함수를 posting_mysql 파일 안에 제작해두었다.)

 

거래일 기준 최신 일자 조회하기

기본적으로 키움증권에서 일봉 데이터를 요청할 때 또는 데이터베이스에서 데이터를 조회하고자 할 때, 특정 일자를 대입해야 하는 경우들이 있는데 특히 데이터베이스에서 데이터를 조회하고

trustyou.tistory.com

 

for code in code_list:
	trade.rq_chart_data(code, "20210101", 1)
	df_day_data = pandas.DataFrame(trade.day_data, columns=['date', 'open', 'high', 'low', 'close', 'volume', 'trade_volume'])
	print(df_day_data)
	df_day_data.to_sql(name="s" + code, con=engine_all, index=False, if_exists='replace')
	print("종목코드:", code, "  데이터베이스에 저장되었습니다.")

	latest_date = posting_mysql.latest_date()
	posting_mysql.update_data('item_savepoint', 'item_savepoint', 'sv_day', latest_date[0], 'code', code)

이제 코드를 실행하게 되면 특정 종목 코드에 대한 차트 데이터를 불러온 후에 to_sql 함수를 통해 데이터베이스에 저장을 하게 되고, 저장을 한 이후에는 item_savepoint라는 데이터베이스의 item_savepoint라는 테이블 안에 sv_day라는 칼럼을 찾아서 latest_date라는 거래일 기준 최신 일자를 입력하게 된다.

코드를 실행한 이후 WorkBench 내에서 item_savepoint 데이터베이스 안에 저장되어 있는 item_savepoint 테이블을 불러오면, 아래와 같이 저장이 잘 되고 있는 모습을 확인할 수 있다.

 

이제 차트 데이터를 관리하는 데이터베이스를 제작하는 내용은 여기서 마무리 짓도록 하고, 다음 포스팅에서는 저장된 데이터베이스를 불러와서 저장되어 있는 일자를 바탕으로 최신일자인지 아닌지를 판단하도록 하고, 최신일자가 아닌 경우에만 차트 데이터를 업데이트하도록 하는 코드에 대해 알아볼 계획이다.

 

 


728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.