안녕하세요? 좋은 플랫폼을 제공해 주셔서 감사합니다.
인기글 중 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();
}
}