Search

Basket

목차

개요

Basket여러 종목을 하나의 포트폴리오 단위로 묶어 한 번에 주문을 처리하는 객체입니다.
Account.buy() / Account.sell()로 종목별 주문을 직접 내는 것과 달리, Basket모델 포트폴리오 개념을 사용합니다. 목표 포트폴리오를 정의하면, 현재 보유 내역과의 차이만 자동으로 매수·매도 주문을 처리합니다.
Basket 객체는 IQAccount 같은 싱글톤이 아니라 new 키워드로 직접 생성합니다.
// 생성자: new Basket(account, targetSize, budget) var stock_port = new Basket(IQAccount.getDefaultAccount(), 20, IQEnvironment.aum * 0.8);
JavaScript
복사

포트폴리오 운용 흐름

initialize() └─ Basket 생성 + setPortfolioBuilder() 등록 onDayClose() — 리밸런싱일마다 └─ setBudget() → 예산 재계산 └─ buildPortfolio() → 포트폴리오 빌더 실행 → 목표 종목 선정 └─ onDayClose() 종료 후 자동 주문 처리 (매도 후 매수)
Plain Text
복사

1. 생성자

new Basket(account, targetSize, budget)
JavaScript
복사
파라미터
타입
설명
account
Account
이 바스켓이 주문을 낼 계좌 객체
targetSize
number
바스켓에 담을 목표 종목 수
budget
number
바스켓 전체 예산 (원/달러). 개별 종목 예산 = budget / targetSize
function initialize() { // 기본 계좌 전액을 하나의 바스켓으로 운용 (최대 20종목) var port = new Basket(IQAccount.getDefaultAccount(), 20, IQEnvironment.aum); }
JavaScript
복사
현재 제약: 종목별 진입 금액은 budget / targetSize동일비중만 지원합니다.

2. 속성 (Properties)

속성
타입
설명
account
Account
주문을 낼 계좌 객체
targetSize
number
목표 종목 수
budget
number
현재 설정된 총 예산

3. setPortfolioBuilder(func) — 빌더 함수 등록

buildPortfolio() 호출 시 실행할 포트폴리오 빌더 함수를 등록합니다.
빌더 함수는 targetSize를 파라미터로 받아 담고 싶은 Stock 객체 배열을 반환해야 합니다. 반환된 배열 내 종목들이 buildPortfolio()에 의해 목표 포트폴리오로 설정됩니다. 일반적으로 initialize() 안에서 등록합니다.

파라미터

파라미터
타입
설명
func
function(targetSize: number) → Stock[]
targetSize를 받아 목표 종목 배열을 반환하는 함수

반환값

없음.

Sample

function initialize() { stock_port = new Basket(IQAccount.getDefaultAccount(), 20, IQEnvironment.aum * 0.8); stock_port.setPortfolioBuilder(stockPortfolioBuilder); } function stockPortfolioBuilder(targetSize) { var universe = IQStock.filter(function(stock) { return stock.market === 1 && !stock.isETF && stock.isListed() && stock.manage === 0 && stock.getMarketCapital() > 50000; }); // PER 오름차순 상위 targetSize 종목 반환 universe.sort(function(a, b) { return a.getPER() - b.getPER(); }); return universe.slice(0, targetSize); }
JavaScript
복사

4. buildPortfolio() — 포트폴리오 생성

등록된 빌더 함수를 실행하여 현재 시점 기준 목표 포트폴리오를 생성합니다.
setBudget()으로 예산을 재설정한 뒤 호출하는 것이 일반적입니다. onDayClose() 종료 후 자동으로 현재 보유 내역과 목표 포트폴리오의 차이를 계산하여 필요한 매도·매수 주문을 처리합니다.

파라미터

없음.

반환값

없음.

주의사항

buildPortfolio() 호출만으로는 즉시 주문이 처리되지 않습니다. onDayClose() 함수 실행이 완전히 끝난 시점에 IQEnvironment.simulationMethod 설정에 따라 당일 종가 또는 익일 시가·평균가로 주문이 체결됩니다. • setPortfolioBuilder()로 빌더 함수를 먼저 등록해야 합니다.

Sample

function onDayClose(now) { if (!IQDate.isRebalancingDay(now)) return; var totalEquity = IQAccount.getDefaultAccount().getTotalEquity(); stock_port.setBudget(totalEquity * 0.8); // 예산 재계산 stock_port.buildPortfolio(); // 목표 포트폴리오 생성 → 자동 주문 }
JavaScript
복사

5. setBudget(amount) / getBudget() — 예산 관리

setBudget(amount)

바스켓의 총 예산을 설정합니다. 리밸런싱 시점마다 계좌 총 평가액을 기준으로 재계산하여 호출하는 것이 일반적입니다.
파라미터
타입
설명
amount
number
설정할 총 예산 (원/달러)

getBudget()

현재 설정된 바스켓 총 예산을 반환합니다.
반환값: number
stock_port.setBudget(IQAccount.getDefaultAccount().getTotalEquity() * 0.8); logger.debug('현재 예산: ' + IQUtil.getNumberWithCommas(stock_port.getBudget().toFixed(0)));
JavaScript
복사

6. getCurrentEggs() — 구성 종목 조회

현재 바스켓에 담긴 모든 BasketEgg 객체의 배열을 반환합니다.

파라미터

없음.

반환값

BasketEgg[]BasketEgg 객체의 배열
var eggs = stock_port.getCurrentEggs(); logger.debug('포트폴리오 종목 수: ' + eggs.length); for (var i = 0; i < eggs.length; i++) { var egg = eggs[i]; logger.debug((i + 1) + '. ' + egg.stock.name + ' | 목표수량: ' + egg.quantity + '주' + ' | 종가: ' + IQUtil.getNumberWithCommas(egg.stock.getClose().toFixed(0))); }
JavaScript
복사

7. getEquityOpenValue() — 바스켓 평가액

바스켓에 담긴 모든 종목의 평가액 합계를 반환합니다. 현금은 포함하지 않습니다.

파라미터

없음.

반환값

number — 바스켓 내 종목 수량 × 당일 종가의 합계
logger.debug('바스켓 총 평가액: ' + IQUtil.getNumberWithCommas(stock_port.getEquityOpenValue().toFixed(0)));
JavaScript
복사

8. enter(stock, quantity) / leave(stock, quantity) / reset() — 직접 편입·편출

setPortfolioBuilder() / buildPortfolio() 없이 개별 종목을 직접 바스켓에 추가하거나 제거할 때 사용합니다.

enter(stock, quantity) — 직접 편입

바스켓에 종목을 직접 추가합니다.
중요: quantity목표 보유 수량입니다. 현재 10주를 보유 중이고 12주로 늘리고 싶다면 quantity12로 지정합니다.
파라미터
타입
설명
stock
Stock
편입할 종목의 Stock 객체
quantity
number
목표 보유 수량 (주). 현재 보유량과 관계없이 최종 목표 수량을 지정.
var sse = IQStock.getStock('A005930'); stock_port.reset(); // 기존 직접 편입 종목 초기화 stock_port.enter(sse, 100); // 삼성전자 100주를 목표로 편입
JavaScript
복사

leave(stock, quantity) — 직접 편출

바스켓에서 종목을 직접 제거합니다.
중요: quantity매도할 수량(차분)입니다. 10주를 보유 중이고 2주만 팔고 싶다면 quantity2로 지정합니다.
파라미터
타입
설명
stock
Stock
편출할 종목의 Stock 객체
quantity
number
매도할 수량 (주). 보유량에서 차감할 양.
var sse = IQStock.getStock('A005930'); stock_port.leave(sse, 2); // 삼성전자 2주 매도
JavaScript
복사

reset() — 직접 편입 초기화

enter()로 직접 추가한 종목 전체를 삭제합니다. 다음 enter() 호출 전 초기화 용도로 사용합니다.
stock_port.reset(); stock_port.enter(IQStock.getStock('A005930'), 50); stock_port.enter(IQStock.getStock('A000660'), 30);
JavaScript
복사

9. 활용 패턴

패턴 1: 주식·채권 멀티 바스켓 — 월별 리밸런싱 (기본 패턴)

주식과 채권(단기채 ETF)을 각각의 바스켓으로 분리하여 운용합니다.
var stock_port, bond_port; var STOCK_WEIGHT = 0.8; var BOND_WEIGHT = 0.2; function initialize() { var acc = IQAccount.getDefaultAccount(); stock_port = new Basket(acc, 20, IQEnvironment.aum * STOCK_WEIGHT); bond_port = new Basket(acc, 1, IQEnvironment.aum * BOND_WEIGHT); stock_port.setPortfolioBuilder(stockBuilder); bond_port.setPortfolioBuilder(bondBuilder); IQDate.addRebalSchedule(IQDate.setMonthlyStart(1)); } function bondBuilder(targetSize) { return [IQStock.getStock('A157450')]; // TIGER 단기통안채 } function stockBuilder(targetSize) { var universe = IQStock.filter(function(stock) { return stock.market === 1 && !stock.isETF && stock.isListed() && stock.manage === 0 && stock.getMarketCapital() > 100000; // 시총 1000억 이상 }); universe.sort(function(a, b) { return b.getPBR() - a.getPBR(); }); // PBR 내림차순 return universe.slice(0, targetSize); } function onDayClose(now) { if (!IQDate.isRebalancingDay(now)) return; var totalEquity = IQAccount.getDefaultAccount().getTotalEquity(); stock_port.setBudget(totalEquity * STOCK_WEIGHT); bond_port.setBudget(totalEquity * BOND_WEIGHT); stock_port.buildPortfolio(); bond_port.buildPortfolio(); logger.info('리밸런싱 완료 | 주식바스켓: ' + IQUtil.getNumberWithCommas(stock_port.getEquityOpenValue().toFixed(0)) + ' | 채권바스켓: ' + IQUtil.getNumberWithCommas(bond_port.getEquityOpenValue().toFixed(0))); }
JavaScript
복사

패턴 2: 분기 리밸런싱 — 한국 재무데이터 업데이트 시점 활용

한국 재무데이터가 업데이트되는 4월·6월·9월·12월 1일에 리밸런싱합니다.
var port; function initialize() { port = new Basket(IQAccount.getDefaultAccount(), 15, IQEnvironment.aum); port.setPortfolioBuilder(perPbrBuilder); // 4월, 6월, 9월, 12월 1일 리밸런싱 스케줄 등록 IQDate.addRebalSchedule(IQDate.setSpecificDate(4, 1)); IQDate.addRebalSchedule(IQDate.setSpecificDate(6, 1)); IQDate.addRebalSchedule(IQDate.setSpecificDate(9, 1)); IQDate.addRebalSchedule(IQDate.setSpecificDate(12, 1)); } function perPbrBuilder(targetSize) { var universe = IQStock.filter(function(stock) { return stock.market === 1 && !stock.isETF && stock.isListed() && stock.manage === 0 && stock.getPER() > 0 && stock.getPBR() > 0 && stock.getMarketCapital() > 50000; }); for (var i = 0; i < universe.length; i++) { var s = universe[i]; var score = (1 / s.getPER()) + (1 / s.getPBR()); // 저PER·저PBR 합산 점수 s.setScore('combo', score); } universe.sort(function(a, b) { return b.getScore('combo') - a.getScore('combo'); }); return universe.slice(0, targetSize); } function onDayClose(now) { if (!IQDate.isRebalancingDay(now)) return; port.setBudget(IQAccount.getDefaultAccount().getTotalEquity() * 0.95); // 5% 현금 유보 port.buildPortfolio(); }
JavaScript
복사

패턴 3: enter() / leave() 직접 편입·편출

빌더 패턴 없이 특정 종목을 직접 바스켓에 추가·제거합니다.
var etf_port; function initialize() { etf_port = new Basket(IQAccount.getDefaultAccount(), 3, IQEnvironment.aum); } function onDayClose(now) { if (!IQDate.isRebalancingDay(now)) return; var budget = IQAccount.getDefaultAccount().getTotalEquity() * 0.95; etf_port.setBudget(budget); var perShare = budget / 3; var kodex200 = IQStock.getStock('A069500'); // KODEX 200 var tiger = IQStock.getStock('A157450'); // TIGER 단기통안채 var kodexInv = IQStock.getStock('A153130'); // KODEX 인버스 etf_port.reset(); etf_port.enter(kodex200, Math.floor(perShare / kodex200.getClose())); etf_port.enter(tiger, Math.floor(perShare / tiger.getClose())); etf_port.enter(kodexInv, Math.floor(perShare / kodexInv.getClose())); }
JavaScript
복사

buildPortfolio() vs enter() 비교

구분
setPortfolioBuilder() + buildPortfolio()
reset() + enter()
용도
알고리즘 기반 동적 종목 선정
고정 종목 또는 수동 구성
종목 수
targetSize 기준 자동 결정
직접 지정
수량 결정
budget / targetSize 기반 자동 계산
직접 지정 (목표 수량)
권장 사용처
퀀트 팩터 기반 포트폴리오
ETF 자산배분, 고정 포트폴리오

주의사항

budget의 100%를 투자하면 수수료·거래세 지출로 현금이 부족해질 수 있습니다. 항상 총 예산의 5% 이상을 현금으로 유지하도록 setBudget(totalEquity * 0.95) 형태로 사용하세요.
buildPortfolio() 호출 후 실제 매매는 onDayClose() 종료 시점에 처리됩니다. 이때 IQEnvironment.simulationMethod 설정에 따라 체결 시점이 달라집니다. 당일 종가 설정이면 onDayClose() 종료 후 다음 날로 넘어가기 전에 계좌에 즉시 반영되고, 익일 시가·평균가 설정이면 다음 날 onDayClose() 호출 직전에 반영됩니다.
enter(stock, quantity)quantity목표 보유 수량(절댓값)이고, leave(stock, quantity)quantity매도할 수량(차분)임에 주의하세요.
orderBasket() 함수는 deprecated 되었습니다. 사용하지 마세요.

관련 API

BasketEgg 객체 — 바스켓에 담긴 종목 단건 객체 (stock, quantity, ratio)
Account 객체 — 계좌 잔고·평가액 조회 및 직접 매수/매도
IQAccount 객체 — 계좌 컨테이너. getDefaultAccount()
IQStock 객체 — 종목 필터링 및 개별 종목 조회
IQDate 객체 — 리밸런싱 스케줄 설정 및 날짜 판별
IQEnvironment 객체 — 초기 AUM, 시뮬레이션 방법 등 환경 설정 조회