본문 바로가기

컴퓨터 활용/구글스프레드시트 응용

국내 ETF 구성 종목 가져오기 @ 구글 스프레드 시트 이용

어떤 분이 ETF 구성종목을 가져올 수 없나고 질문을 했었는데 저도 마침 필요한 부분이라 한번 만들어 봤습니다.
네이버 증권에서 국내 ETF를 검색 해보면 ETF의 구성종목이란 곳이 있습니다.

TIGER 2차전지테마 라고 검색 해보면 https://finance.naver.com/item/coinfo.nhn?code=305540 이 나오는데

여기에 있는 CU 당 구성종목을 IMPORTHTML 함수를 이용하여 가지고 오려고 하면 실패를 합니다. 이유는 실제 HTML 페이지가 아니라 자바스크립트의 변수 데이터 형태로 저장이 되어 있거나  AJAX 비동기 방식으로 페이지에서 표(Table) 을 먼저 가지고 온 다음 데이터는 나중에 별도의 명령으로 가져와 덧붙이는 방식으로 구현되기 때문입니다. 다행히 변수형태로 페이지내에 저장이 되어 해당 데이터를 뽑아 내어 아주 쉽게 구현 할 수 있었습니다.

그래서 TIGER ETF 홈페이지에 가서 상품을 찾아 봤는데
https://www.tigeretf.com/npc/product/product.do?ksdFund=KR7305540007

이것은 IMPORTHTML 함수로 크롤링이 되더라고요 쉽게는 가능하지만 한국증권금융의 펀드코드로 입력 받게 되어 있어 주식 관리에서 활용하려면 종목코드로 찾아야 하기 때문에 사용이 불가 하였습니다.

KODEX ETF는 http://www.kodex.com/product_view.do?fId=2ETFB1 인데 별도의 ID를 부여하지만 AJAX 방식으로 가져오고 있어서 구글 스프레드 시트의 함수로는 수집이 불가능했습니다.

첫 번째 시트는 TIGER ETF 사이트에서 IMPORTHTML 방식으로 데이터를 가져오는 방식입니다.

다음 2곳에서 가져 오도록 했습니다.

1) 에프엔가이드 (FNGuide)

- URL : http://comp.fnguide.com/svo2/asp/etf_snapshot.asp?gicode=A305540

- ETF에 포함된 TOP 10 종목만 가져옴
- 함수명은 getETFholdings("종목코드");

2) 와이즈리포트(WiseReport)

- URL : https://navercomp.wisereport.co.kr/v2/ETF/index.aspx?cmp_cd=305540

- ETF에 포함된 전 종목을 가져옴 / 주식 수 까지
- 함수명은 getETFholdingsByWiseReport("종목코드")

 

구글 시트 주소  

https://docs.google.com/spreadsheets/d/1hhsEmeIOd3mzMpZ2NqlsrlhyA8noceir8jHzoAt_ImE/edit?usp=sharing

 

좀 더 많은 정보를 제공하는 와이즈리포트를 대상으로 설명을 드리면

정보페이지에서 CTRL + U 키를 누르면 소스보기가 가능한데 653번째 줄에 var CU_data = 로 시작되는 부분의 데이터입니다 .

실제 데이터는 

var CU_data = {"grid_data":[{"TRD_DT":"2021-04-02","AGMT_STK_CNT":673.00,"STK_NM_KOR":"포스코케미칼","ETF_WEIGHT":12.48},....], "chart_data":[...]};

이렇게 되어 있습니다.

자바스크립트의 JSON.parse 함수로 문자를 JSON 형태의 데이터로 만들 수 있습니다
{ "grid_data" 로 부터 마지막의 } 까지 데이터를 취하는 것이죠. 최종적으로 뽑아진 JSON 데이터의 구조는 다음과 같습니다.

{
	"grid_data": [
		{
			"TRD_DT": "2021-04-02",
			"AGMT_STK_CNT": 8008.0,
			"STK_NM_KOR": "삼성전자",
			"ETF_WEIGHT": 31.5
		}
	]
}

 

소스는 다음과 같습니다. 도구 메뉴의 스크립트 편집기에 있습니다.

자바스크립트의 .search 함수로 특정 문자 열이 있는 위치를 찾고 substring 메소드로 해당 부분을 취하는 방식입니다. 그래서 구해진 문자열은 JSON Parse 로 들어가서 데이타로 변환 된 후 변수에 담기게 됩니다.

다음은 for 문으로 루프를 돌려 2차원 배열인 ETFarr 배열에 담기게 됩니다.

ETFarr[행][열] 로 구성 됩니다.

// 와이즈 리포트 
function getETFholdingsByWiseReport(code){
 
  var url = 'https://navercomp.wisereport.co.kr/v2/ETF/index.aspx?cmp_cd='+code;
  var html = UrlFetchApp.fetch(url).getContentText(); 
  
  var searchstring = 'var CU_data = ';
  var ETFarr = [];
  var index = html.search(searchstring); // searchstring 이 있는 위치 
  
  if (index >= 0) 
  {
    var pos1 = index + searchstring.length; // { 이 있는 위치 
    var t = html.substring(pos1);
    var pos2 = t.search('\n\r');  // 줄 끌이 있는 위치 
    var v = t.substring(0,pos2).split(";")[0]; // ; 로 분리후 첫번째 배열요소만 취함
  }
  
    
  var jsonData = JSON.parse(v); // JSON 라이브러리로 문자를 자바스크립트 변수로 변환 
  var arr = jsonData["grid_data"]; 

  ETFarr.push(["순번","종목명",	"주식수","구성비율", "기준일"]);

  for(var i=0; i<arr.length;i++)
  {
    ETFarr.push( [  i+1, 
                   arr[i].STK_NM_KOR,
                   arr[i].AGMT_STK_CNT,
                   arr[i].ETF_WEIGHT, 
                   arr[i].TRD_DT
                  ]);
  }
  
  return ETFarr;
}