도움말
인텔리퀀트의 사용방법과 메뉴얼입니다.

5. Basket을 활용한 포트폴리오 관리

인텔리 퀀트에서는 여러 종목을 한번에 관리하기 위해 Basket 객체를 제공합니다.

1. Stock객체 필터링

대부분의 경우에는 위에서 처럼 직접적으로 종목코드를 통해 가져오지 않고 필터링을 거쳐 원하는 종목들을 가져오게 됩니다.
(물론 채권이나 인덱스 ETF같은 경우에는 직접 코드를 통해 가져와야 합니다.)

우선은 종목을 필터링하는 함수를 작성합니다.
이 함수는 stock 객체를 인자로 받아서 true 또는 false를 리턴하는 함수여야 합니다.

우선은 예제를 살펴보겠습니다.

function filterfunc(stock) {
    return (stock.getMarketCapital() > 10000); //시가총액이 100억 이상인 종목으로 필터링
}

var universe0 = IQStock.filter( filterfunc ); //필터를 통과한 stock 객체의 배열
for (var i = 0; i < universe0.length; i++) {
    var stock = universe0[i];
    logger.debug(' code:' + stock.code + ', name:' + stock.name); //각 종목의 코드와 이름을 출력함
}

위 예제에서 filterfunc 함수는 stock을 인자로 받고 시가총액을 기준으로 true또는 false를 리턴합니다.
이런식으로 사용자가 원하는 필터링 함수를 만들어서 특정 조건을 통과한 종목만 가져올 수 있습니다.
시가총액과 20일간 거래 대금 평균이 어느정도 이상인 종목만을 걸러서 가져오거나,
PER가 특정 값 이상인 경우에만 선별적으로 가져와서 추가적인 계산을 할 수 있습니다.

Basket은 종목을 담고 주문내는 방식이 처음 보면 생소할 수도 있습니다.
그냥 종목을 추가하고 한번에 주문을 내주면 직관적이니까요.
하지만 저희가 제공하는 Basket은 대부분의 가치투자자들이 사용하는 방법을 그대로 사용할 수 있도록 했습니다.
처음엔 조금 복잡해 보이지만 믿고 따라 오시면 왜 이런 방법을 사용했는지 이해하실수 있을겁니다.
만약 이해가 안되신다면 맨아래 저희 연락처로 항의 주시기 바랍니다.

그리고 중요한 것은 꼭 Basket객체를 사용해야 하는것은 아닙니다.
Account객체에 직접 주문을 내도 시뮬레이션은 문제없이 동작합니다.


Basket에 종목을 담고 주문을 내는 과정

1. Basket 객체를 생성한다. 이때 Basket에 담을 종목 수를 정의한다.
2. 종목을 선정하는 buildPortfolio 함수를 정의한다.

이렇게 정의하는 이유는 성격이 다른 여러 포트폴리오를 다루기 쉽게 하기 위해서 입니다.
각각의 포트폴리오를 만드는 방식을 Basket에 정의하고 그 Basket에다 주문 명령만 내리는 방식이 더 직관적이기 때문입니다.

다음은 샘플 코드입니다.

var stock_port;
var short_port;
var stock_weight = 0.8;
var short_weight = 0.2;

function initialize() {
    stock_port = new Basket(IQAccount.getDefaultAccount(), 20, IQEnvironment.aum * stock_weight);
    short_port = new Basket(IQAccount.getDefaultAccount(), 1, IQEnvironment.aum * short_weight);

    stock_port.setPortfolioBuilder(stockPortfolioBuilder);
    short_port.setPortfolioBuilder(shortPortfolioBuilder);
}

function getPER(stock) {
    if (stock.getClose() === 0 || stock.getFundamentalNetProfit() === 0) {
        return -1;
    }
    var per = stock.getMarketCapital() / (stock.getFundamentalNetProfit() * 4);
    return 1/per;
}

function filterfunc(stock) {
    return (stock.getMarketCapital() > 10000); //시가총액이 100억 이상인 종목으로 필터링
}

function shortPortfolioBuilder(targetSize) {
    return [IQStock.getStock("A153130")]; //KODEX 인버스 ETF
}

function stockPortfolioBuilder(targetSize) {
    var universe = IQStock.filter( filterfunc );
    logger.debug('List_universe size = ' + universe.length);

    var sortedByPer = universe.slice().sort(function(a,b){return getPER(b)-getPER(a);});
    var port = sortedByPer.slice(0, targetSize);
    return port;
}

function onDayClose(now) {
    if (now.getDate() == 15) {  //매월 15일에만 주문을 낸다.
        var totalEquity = IQAccount.getDefaultAccount().getTotalEquity();   // 계좌 총 평가액
        stock_port.setBudget(totalEquity * stock_weight);
        stock_port.buildPortfolio();
        stock_port.orderBasket();

        logger.debug('cash = ' + IQAccount.getDefaultAccount().cash + ', OPEN VALUE = ' + stock_port.getEquityOpenValue());
    }
}

위에서 보시는 것처럼 onDayClose 함수에서 buildPortfolio 함수가 호출되면 basket에 등록된 portfolioBuilder 함수가 필요한 종목들을 선정하여 배열로 리턴합니다.