커뮤니티
내가 만든 전략들과 지식을 공유하고 토론합니다.

인기글 F-스코어 전략에 대한 문의입니다.

밸류퀀트 2018.02.20 08:52 조회수  797 추천 0

안녕하세요? 좋은 플랫폼을 제공해 주셔서 감사합니다.


인기글 중 F-스코어 전략에 대해 문의 드리려고 합니다.

아래 전체 코드가 있고요,

여기서 cut_line을 통해 F-스코어 9,8,7... 점 종목들을 바스켓에

담는것 같습니다.

그런데 개별 바스켓(9점, 8점, 7점 ... )에 담긴 종목수, 종목명을 알고 싶은데

어떤 코드를 추가해야 할까요?


        cut_line = 9;

        basket.buildPortfolio();   

        basket.reset();

        basket.targetSize = MAX_SIZE;

    

        var pf_list = targetSize;

        logger.debug("pf_list = " + pf_list.length); //필터 통과한 종목 수 확인       


        basket.setBudget(Equity0 * STOCK_WEIGHT);

        basket.buildPortfolio();


위 부분에서, 노란색 음영 코드를 추가해 보고, 이리 저리 변경해보았는데

잘 안되더라고요.

조언 좀 부탁드리겠습니다.

감사합니다.


--------------------------------------------------------------------------------------------------------

이하 전체 코드


var basket;                // 주식 종목들을 담을 Basket

var basket1;                // 주식 종목들을 담을 Basket

var basket2;                // 주식 종목들을 담을 Basket

var basket3;                // 주식 종목들을 담을 Basket

var basket4;                // 주식 종목들을 담을 Basket

var basket5;                // 주식 종목들을 담을 Basket

var basket6;                // 주식 종목들을 담을 Basket

var basket7;                // 주식 종목들을 담을 Basket

var basket8;                // 주식 종목들을 담을 Basket

var basket9;                // 주식 종목들을 담을 Basket


var STOCK_WEIGHT = 0.97;    // 주식 비율 현금 보유를 3%

var MAX_SIZE = 15;         // 기본 셋팅용



// 이 전략이 초기화되면 Initialize 함수가 호출됩니다.

function initialize() {

    IQEnvironment.stockTax = 0.013;    // 주식 세금 1.3% (슬리피지 1%포함)

    

    var account = IQAccount.getDefaultAccount();

    account.accountName = "9점";

    var account_1 = IQAccount.addAccount('0000-0000-01', '8점', IQEnvironment.aum);

    var account_2 = IQAccount.addAccount('0000-0000-02', '7점', IQEnvironment.aum);  

    var account_3 = IQAccount.addAccount('0000-0000-03', '6점', IQEnvironment.aum);

    var account_4 = IQAccount.addAccount('0000-0000-04', '5점', IQEnvironment.aum); 

    var account_5 = IQAccount.addAccount('0000-0000-05', '4점', IQEnvironment.aum);

    var account_6 = IQAccount.addAccount('0000-0000-06', '3점', IQEnvironment.aum); 

    var account_7 = IQAccount.addAccount('0000-0000-07', '2점', IQEnvironment.aum);

    var account_8 = IQAccount.addAccount('0000-0000-08', '1점', IQEnvironment.aum);   

    var account_9 = IQAccount.addAccount('0000-0000-09', '0점', IQEnvironment.aum);     


basket = new Basket(account, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket1 = new Basket(account_1, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket2 = new Basket(account_2, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);  

  basket3 = new Basket(account_3, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket4 = new Basket(account_4, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket5 = new Basket(account_5, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket6 = new Basket(account_6, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);  

  basket7 = new Basket(account_7, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket8 = new Basket(account_8, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);    

basket9 = new Basket(account_9, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);  


basket.setPortfolioBuilder(portfolioBuilder);    

    basket1.setPortfolioBuilder(portfolioBuilder);

    basket2.setPortfolioBuilder(portfolioBuilder);

basket3.setPortfolioBuilder(portfolioBuilder);    

    basket4.setPortfolioBuilder(portfolioBuilder);

    basket5.setPortfolioBuilder(portfolioBuilder);

basket6.setPortfolioBuilder(portfolioBuilder);    

    basket7.setPortfolioBuilder(portfolioBuilder);

    basket8.setPortfolioBuilder(portfolioBuilder);

    basket9.setPortfolioBuilder(portfolioBuilder);

    

}


//portfolioBuilder 함수에서 사용할 필터링 함수를 정의합니다.

function stockFilter(stock) {

    if (stock.getMarketCapital() == 0) { return false; }  //상장폐지종목 제외

    if (stock.getAdjClose() == 0) { return false; }       //상장폐지종목 제외

    if (stock.getClose() == 0) { return false; }         // filter out delisted stocks

    if (stock.getTradingValue() == 0) { return false; }  // 거래정지 중인 종목 제외

    if (stock.isETF) { return false; }            // ETF 제외

    if (stock.manage & 1) { return false; }       // 관리종목 제외

    if (stock.manage & 4) { return false; }       // 거래정지종목 제외

    if (stock.name.substr(stock.name.length -2) === "스팩") { return false; } //스팩 제외

    if (stock.name.substr(stock.name.length -2) === "우B") { return false; } //우선주 제외    

    if (stock.name.substr(stock.name.length -2) === "우C") { return false; } //우선주 제외    

    if (stock.name.substr(stock.name.length -1) === "우") { return false; } //우선주 제외     

    if (stock.name.substr(stock.name.length -3) === "우선주") { return false; } //우선주 제외          

    if (stock.name.substr(stock.name.length -1) === ")") { return false; } //우선주 제외  

    if (stock.name === "연우") { return true; } //else { return false; }     //우선주 제외     

    if (stock.name.substr(stock.name.length -2) === "1호") { return false; } //스팩 제외    

    if (stock.name.substr(stock.name.length -2) === "2호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "3호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "4호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "5호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "6호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "7호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "8호") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -2) === "9호") { return false; } //스팩 제외 

    if (stock.name.substr(stock.name.length -3) === "10호") { return false; } //스팩 제외 

    if (stock.name.substr(stock.name.length -3) === "개발1") { return false; } //스팩 제외

    if (stock.name.substr(stock.name.length -4) === "SPAC") { return false; } //스팩 제외  

    if (stock.name.substr(stock.name.length -3) === "ETN") { return false; } //ETN 제외

    if (stock.getMarketCapital() < 50000) { return false; } // 시가총액 500억 이상 기준

    if (stock.getTradingValue() < 100) { return false; } // 거래대금 1억 이상 기준

return true;

    

}



// PBR역순 구하기

function bp(stock) {

    return stock.getFundamentalTotalEquity() / stock.getMarketCapital(); }


function netProfit(stock) { // 최근 4분기 순이익

    stock.loadPrevData(1, 4, 0);

    return stock.getFundamentalNetProfit(0) + stock.getFundamentalNetProfit(1) + stock.getFundamentalNetProfit(2) + stock.getFundamentalNetProfit(3);

}

function cashflow(stock) { // 최근 4분기 영업현금

    stock.loadPrevData(1, 4, 0);

    return stock.getFundamentalOperatingCashFlow(0) + stock.getFundamentalOperatingCashFlow(1) + stock.getFundamentalOperatingCashFlow(2) + stock.getFundamentalOperatingCashFlow(3);

}

function cashflowlastyear(stock) { // 전년도 영업현금흐름

    stock.loadPrevData(2, 4, 0);

    return stock.getFundamentalOperatingCashFlow(4) + stock.getFundamentalOperatingCashFlow(5) + stock.getFundamentalOperatingCashFlow(6) + stock.getFundamentalOperatingCashFlow(7);

}

function ROAlastyear(stock) { // 전년도 총자산경상이익률

    stock.loadPrevData(2, 4, 0);

    return (stock.getFundamentalNetProfit(4) + stock.getFundamentalNetProfit(5) + stock.getFundamentalNetProfit(6) + stock.getFundamentalNetProfit(7)) / stock.getFundamentalTotalAsset(4);

}

function longtermDebt(stock) { // 총자산 대비 장기부채 비율

    return (stock.getFundamentalTotalAsset(0) - stock.getFundamentalTotalEquity(0) - stock.getFundamentalTotalLiability(0)) / stock.getFundamentalTotalAsset(0);

}

function longtermDebtlastyear(stock) { // 전년도 총자산 대비 장기부채 비율

    stock.loadPrevData(1, 4, 0);

    return (stock.getFundamentalTotalAsset(4) - stock.getFundamentalTotalEquity(4) - stock.getFundamentalCurrentLiability(4)) / stock.getFundamentalTotalAsset(4);

}

function currentRatio(stock) { // 유동부채 대비 유동자산 비율

    return stock.getFundamentalCurrentAsset(0) / stock.getFundamentalCurrentLiability(0);

}

function currentRatiolastyear(stock) { // 전년도 유동비율

    stock.loadPrevData(1, 4, 0);

    return stock.getFundamentalCurrentAsset(4) / stock.getFundamentalCurrentLiability(4);

}

function salesProfit(stock) { // 매출총이익

    return stock.getFundamentalRevenue(0) - stock.getFundamentalSalesCost(0);

}

function salesProfitlastyear(stock) { // 전년도 매출총이익

    stock.loadPrevData(1, 4, 0);

    return stock.getFundamentalRevenue(4) - stock.getFundamentalSalesCost(4);

}

function assetTurnover(stock) { // 총자산회전율

    return stock.getFundamentalRevenue(0) / stock.getFundamentalTotalAsset(0);

}

function assetTurnoverlastyear(stock) { // 전년도 총자산회전율

    stock.loadPrevData(1, 4, 0);

    return stock.getFundamentalRevenue(4) / stock.getFundamentalTotalAsset(4);

}


function f_score(stock) {

    stock.loadPrevData(1, 6, 0);

    var score = 0;

    if (netProfit(stock) > 0) {score = score + 1;} // 1. 순이익 > 0

    if (cashflow(stock) > cashflowlastyear(stock)) {score = score + 1;} // 2. 작년대비 영업활동현금흐름 증가

    if (stock.getROA() > ROAlastyear(stock)) {score = score + 1;} // 3. 작년대비 총자산경상이익률 증가

    if (cashflow(stock) > netProfit(stock)) {score = score + 1;} // 4. 영업활동현금흐름이 순이익 초과

    if (longtermDebt(stock) < longtermDebtlastyear(stock)) {score = score + 1;} // 5. 작년대비 총자산대비장기부채비율 감소

    if (currentRatio(stock) > currentRatiolastyear(stock)) {score = score + 1;} // 6. 작년대비 유동비율 증가

    if (stock.getNoOfShare(0) == stock.getNoOfShare(252) ) {score = score + 1;} // 7. 1년전 대비 주식수 변동없음

    if (salesProfit(stock) > salesProfitlastyear(stock)) {score = score + 1;} // 8. 작년대비 매출총이익 증가

    if (assetTurnover(stock) > assetTurnoverlastyear(stock)) {score = score + 1;} // 9. 작년대비 총자산회전율 증가

    

//    if (cashflow(stock) > 0) {score = score + 1;} // 영업현금 > 0  

//    logger.debug(stock.name + " " + stock.getNoOfShare(0) + " vs " + stock.getNoOfShare(252));    

//    logger.debug(stock.name + " " + stock.getFundamentalCapitalStock(0) + " vs " + stock.getFundamentalCapitalStock(4));

//    if (stock.getFundamentalCapitalStock(0) == stock.getFundamentalCapitalStock(4) ) {score = score + 1;} //  신규 주식발행 없음 (자본금 변동없음)

    //logger.debug(stock.name + " " + score + "점");

    return score;

}

    


function portfolioBuilder(targetSize) {

//특정 조건에 부합하는 종목만으로 필터링한 종목들만으로 유니버스를 구성합니다.

var universe = IQStock.filter(stockFilter);

    logger.debug("universe size = " + universe.length); //필터 통과한 종목 수 확인


// pbr 역순 정렬

    var sortedByPbr = universe.slice().sort( function(a, b) { return bp(b) - bp(a); });  

    sortedByPbr.forEach( function(stock) {// pbr점수매기기

        stock.setScore('bp_rank', sortedByPbr.indexOf(stock));   });    

    

/*    // PBR 필터링(역순 정렬했으니 상위 20%만 남기기)

    var pbr_list = sortedByPbr.filter(function(stock) {

        if ( stock.getScore('bp_rank') > (0.2 * sortedByPbr.length) ) { return false; }

        return true; } ); */


    // F-score 뽑기

    var F_score_list = sortedByPbr.filter(function(stock) {

        if (f_score(stock) != cut_line) {return false;} // 특정 점수(커트라인) 이외는 제거

        return true;

        } );  


// MAX_SIZE = (F_score_list.length === null) ? 0 : F_score_list.length; //포트 종목수 변경

    return F_score_list.slice(0, MAX_SIZE);

}



var lastRebalYear = 99;

var lastRebalMonth = 1; 

var startDate = 25;

var cut_line = 9;

var flag = 0;


//시뮬레이션 기간동안 매일 매일 호출됩니다.  

function onDayClose(now) {  

//    if ((now.getMonth() != lastRebalMonth && now.getDate() >= startDate)) { // 매달 초에 리밸런싱을 수행합니다.

if ((now.getYear() != lastRebalYear && now.getMonth() > -1 &&  now.getDate() >= startDate)) {

// if (flag == 0) {

    var account = IQAccount.getAccount('0000-0000-00'); // 9점

        var account_1 = IQAccount.getAccount('0000-0000-01');

        var account_2 = IQAccount.getAccount('0000-0000-02');

        var account_3 = IQAccount.getAccount('0000-0000-03');

        var account_4 = IQAccount.getAccount('0000-0000-04');

        var account_5 = IQAccount.getAccount('0000-0000-05');

        var account_6 = IQAccount.getAccount('0000-0000-06');

        var account_7 = IQAccount.getAccount('0000-0000-07');

        var account_8 = IQAccount.getAccount('0000-0000-08');

        var account_9 = IQAccount.getAccount('0000-0000-09'); // 0점

        

        var Equity0 = account.getTotalEquity();

        var Equity1 = account_1.getTotalEquity();

        var Equity2 = account_2.getTotalEquity();

        var Equity3 = account_3.getTotalEquity();

        var Equity4 = account_4.getTotalEquity();

        var Equity5 = account_5.getTotalEquity();

        var Equity6 = account_6.getTotalEquity();

        var Equity7 = account_7.getTotalEquity();

        var Equity8 = account_8.getTotalEquity();

        var Equity9 = account_9.getTotalEquity();

        

        cut_line = 9;

        basket.buildPortfolio();   

        basket.reset();

basket.targetSize = MAX_SIZE;

        basket.setBudget(Equity0 * STOCK_WEIGHT);

        basket.buildPortfolio();

        


        cut_line = 8;

        basket1.buildPortfolio();   

        basket1.reset();

basket1.targetSize = MAX_SIZE;        

        basket1.setBudget(Equity1 * STOCK_WEIGHT);        

        basket1.buildPortfolio();        


        cut_line = 7;

        basket2.buildPortfolio();   

        basket2.reset();

basket2.targetSize = MAX_SIZE;        

        basket2.setBudget(Equity2 * STOCK_WEIGHT);        

        basket2.buildPortfolio();

                    

        cut_line = 6;

        basket3.buildPortfolio();   

        basket3.reset();

basket3.targetSize = MAX_SIZE;

        basket3.setBudget(Equity3 * STOCK_WEIGHT);

        basket3.buildPortfolio();


        cut_line = 5;

        basket4.buildPortfolio();   

        basket4.reset();

basket4.targetSize = MAX_SIZE;        

        basket4.setBudget(Equity4 * STOCK_WEIGHT);        

        basket4.buildPortfolio();        


        cut_line = 4;

        basket5.buildPortfolio();   

        basket5.reset();

basket5.targetSize = MAX_SIZE;        

        basket5.setBudget(Equity5 * STOCK_WEIGHT);        

        basket5.buildPortfolio();

            

        cut_line = 3;

        basket6.buildPortfolio();   

        basket6.reset();

basket6.targetSize = MAX_SIZE;

        basket6.setBudget(Equity6 * STOCK_WEIGHT);

        basket6.buildPortfolio();


        cut_line = 2;

        basket7.buildPortfolio();   

        basket7.reset();

basket7.targetSize = MAX_SIZE;        

        basket7.setBudget(Equity7 * STOCK_WEIGHT);        

        basket7.buildPortfolio();        


        cut_line = 1;

        basket8.buildPortfolio();   

        basket8.reset();

basket8.targetSize = MAX_SIZE;        

        basket8.setBudget(Equity8 * STOCK_WEIGHT);        

        basket8.buildPortfolio();

    

        cut_line = 0;

        basket9.buildPortfolio();   

        basket9.reset();

basket9.targetSize = MAX_SIZE;        

        basket9.setBudget(Equity9 * STOCK_WEIGHT);        

        basket9.buildPortfolio();

        

     //   flag = 1;

        lastRebalYear = now.getYear();

     //   lastRebalMonth = now.getMonth();

}

}

댓글 1
그냥 그래프 아래에 있는 잔고보유 내역 탭을 클릭하시면 뜹니다
Prophit 2018.02.20 12:41
댓글 등록을 위해서 로그인해주세요.
 
최신 게시글