Skip to content

Instantly share code, notes, and snippets.

@pauloromeira
Last active September 20, 2021 03:21
Show Gist options
  • Save pauloromeira/147624af7922876de29eae4a042ab66f to your computer and use it in GitHub Desktop.
Save pauloromeira/147624af7922876de29eae4a042ab66f to your computer and use it in GitHub Desktop.
Apps Script (Google Sheets) - Balance Portfolio
/* ---------- General Helpers ---------- */
function _sort_idxs(items) {
return items.map((item, idx) => [item, idx]).sort().map(i => i[1]);
}
function _sort_apply(idxs, items) {
return idxs.map(idx => items[idx]);
}
function _sort_restore(idxs, items) {
var restored = new Array(idxs.length);
items.map((item, i) => { restored[idxs[i]] = item; });
return restored;
}
/* ---------- Specific Helpers ---------- */
function _heights(widths, areas) {
return widths.map((width, i) => areas[i]/width);
}
function _max_height(widths, heights, amount, count) {
var curr_amount = 0;
var curr_width = 0;
for (var i = 0; i < (count - 1); i++) {
let next_width = curr_width + widths[i];
let next_amount = curr_amount + next_width * (heights[i + 1] - heights[i]);
if (next_amount >= amount)
break;
curr_width = next_width;
curr_amount = next_amount;
}
return heights[i] + (amount - curr_amount) / (curr_width + widths[i]);
}
/* ---------- Main ---------- */
function balance_portfolio(weights, balances, amount, title, count) {
var widths = weights.flat();
var heights = _heights(widths, balances.flat());
count = count && typeof(count) === "number" ? Math.min(count, heights.length) : heights.length;
// Apply: sort by heights
var idxs = _sort_idxs(heights);
widths = _sort_apply(idxs, widths);
heights = _sort_apply(idxs, heights);
// Calculate max_height
var max_height = heights[heights.length - 1];
if (typeof(amount) === "number")
max_height = _max_height(widths, heights, amount, count);
// Calculate results
var results = heights.map((h, i) => i < count ? Math.max(max_height - h, 0) * widths[i]: 0);
// Restore: sort by heights
results = _sort_restore(idxs, results);
if (title)
results.unshift(title);
return results;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment