예전글 per+pbr 샘플 알고리즘에서 전체계좌수익률(총자산)이 -3프로도달시 손절하는 로직좀 부탁드립니다..
밑에는 샘플알고리즘입니다..
/*
초기 예수금 1000만원
1. KOSPI 종목 대상. ETF 제외
2. 총 계좌평가액 중 90%를 리밸런싱에 사용(10%는 현금보유)
3. (PBR 순위 + PER 순위) 합산 순위 상위 20개 종목으로 매달 리밸런싱
*/
var basket; // 주식 종목들을 담을 Basket
var STOCK_WEIGHT = 0.9; // 주식 비율 현금 보유를 10%
var MAX_SIZE = 20; // 각 바스켓에 최대 20주 편입
// 이 전략이 초기화되면 Initialize 함수가 호출됩니다.
function initialize() {
var account = IQAccount.getDefaultAccount();
basket = new Basket(account, MAX_SIZE, IQEnvironment.aum * STOCK_WEIGHT);
//빌더 함수를 정의합니다.
basket.setPortfolioBuilder(portfolioBuilder);
}
//portfolioBuilder 함수에서 사용할 필터링 함수를 정의합니다.
function stockFilter(stock) {
if (stock.getMarketCapital() === 0) { return false; }
if (stock.getFundamentalTotalAsset() === 0) { return false; }
if (stock.getClose() === 0) { return false; } // filter out delisted stocks
if (stock.getTradingValue() === 0) { return false; } // 거래정지 중인 종목 제외
if (stock.market != 1 || stock.isETF) { return false; } // KOSPI만 & ETF 제외
if (stock.getFundamentalNetProfit() <= 0) { return false; } // 당기 순이익 0 이하 종목 제외
if (stock.getFundamentalTotalEquity <= 0) { return false; } // 당기 자본총계 0 이하 종목 제외
return true;
}
function portfolioBuilder(targetSize) {
//특정 조건에 부합하는 종목만으로 필터링한 종목들만으로 유니버스를 구성합니다.
var universe = IQStock.filter(stockFilter);
logger.debug("universe size = " + universe.length);
//PBR 내림차순으로 정렬 (PBR 낮은 종목이 배열 뒤에 오도록)
var sortedByPbr = universe.slice().sort( function(a, b) { return b.getPBR() - a.getPBR(); });
//PER 내림차순으로 정렬 (PER 낮은 종목이 배열 뒤에 오도록)
var sortedByPer = universe.slice().sort( function(a, b) { return b.getPER() - a.getPER(); });
//각 종목에 (PBR 순위 + PER 순위) 점수를 저장합니다.
//PBR 순위 = sortedByPbr 배열에서 해당 종목의 위치
//PER 순위 = sortedByPer 배열에서 해당 종목의 위치
universe.forEach( function(stock) {
stock.setScore('rank_sum', sortedByPbr.indexOf(stock) + sortedByPer.indexOf(stock));
});
//합산 점수 내림차순으로 정렬
var modelPortfolio = universe.slice().sort( function(a, b) {
return b.getScore('rank_sum') - a.getScore('rank_sum');
});
//필터링되고 합산점수 내림차순으로 정렬된 종목들 중 상위 20종목으로 포트폴리오를 구성합니다.
return modelPortfolio.slice(0, targetSize);
}
var lastRebalMonth = -1;
var startDate = 1;
//시뮬레이션 기간동안 매일 매일 호출됩니다.
//호출되는 시점이 언제인지는 Date 객체인 now파라메터를 통해 알 수 있습니다.
function onDayClose(now) {
// 매달 초에 리밸런싱을 수행합니다.
if ((now.getMonth() != lastRebalMonth && now.getDate() >= startDate)) {
var totalEquity = IQAccount.totalEquity(); // 계좌의 총평가금액(주식평가액+예수금 모두)
//계좌 총평가금액 중 90%를 리밸런싱에 사용합니다.
basket.setBudget(totalEquity * STOCK_WEIGHT);
basket.buildPortfolio();
lastRebalMonth = now.getMonth();
}
}