function computeRecessionCandidates(data, dates, dateColumn, priceColumn, recessionRate) {
const L = data.length;
let relativeLows = [0];
let curPos = 1;
let records = [];
while (curPos < L) {
const curDate = data[curPos][dateColumn];
const curPrice = data[curPos][priceColumn];
const endPos = seekDates(dates, addYears(curDate, 1));
const sliced = data.slice(curPos, endPos+1);
if (d3.min(sliced, d => d[priceColumn]) >= curPrice) {
const lastLowPos = getLast(relativeLows);
const maxPosOffset = d3.maxIndex(data.slice(lastLowPos, curPos), d => d[priceColumn]);
const maxPos = lastLowPos + maxPosOffset;
const maxPrice = data[maxPos][priceColumn];
const discount = 1 - recessionRate
if (maxPrice * discount > curPrice) {
const preHighDate = data[maxPos][dateColumn];
const preHighClose = data[maxPos][priceColumn];
records.push({
preHighDate: preHighDate,
preHighClose: preHighClose,
lowDate: curDate,
lowClose: curPrice,
change: getChangeInPercentage(preHighClose, curPrice),
duration: getElaspedTime(preHighDate, curDate)
});
relativeLows.push(curPos);
}
curPos += 1;
} else {
let minPosOffset = d3.minIndex(data.slice(curPos, endPos), d => d[priceColumn]);
if (minPosOffset == 0) {
curPos += 1;
} else {
let minPos = curPos + minPosOffset;
curPos = minPos;
}
}
}
return records;
}