Как рассчитать смешанный сбор? - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь рассчитать комиссию за управление инвестициями, используя график комиссий.Например, предположим, что сумма инвестиций составляет 5 000 000 долларов США, и это график выплат:

  • 1 000 000 и менее: 1,00%
  • 2 000 000: 0,75%
  • 3 000 000:0,50%
  • 3 000 001 +: 0,25%

Если для долларов до 1 000 000 взимается 1,00%, а для долларов свыше 3 000 000 - 0,25%.Мне нужно придумать смешанную цену, используя javascript (ответ в этом случае будет 0,55% или 27 500 долларов США).

Как вы получите ответ, если сумма, которую мы используем в качестве примера,5 000 000 долларов США и приведенный выше график платежей?

  • 1 000 000 долларов США * 0,0100 = 10 000 долларов США (плата за первые 1 миллион долларов США)
  • 1 000 000 долларов США * 0,0075 = 7500 долларов США (плата за первые 1 миллион долларов США)
  • 1 000 000 * 0,0050 = 5 000 долл. США (плата за третьи 1 млн. Долл. США)
  • 2 000 000 долл. США * 0,0025 = 5 000 долл. США (все свыше 3 млн. Долл. США)

Таким образом, для управления 5 000 000 долл. США потребуетсяобщая сумма вышеуказанных сборов (27 500 долл. США).И 27 500 долл. США / 5 000 000 долл. США = 0,55%, что является нашей «смешанной комиссией».

Предостережение заключается не в том, что каждый график выплат выглядит именно так.Некоторые имеют разные сборы и ограничения.

Каковы результаты моего исследования этой проблемы до сих пор?Я не нашел качественный пример функции, которая могла бы выполнить это на SO.Кажется, что все многоуровневые расчеты цены для SO определяют только одну цену для данного количества товаров, а не смешанную цену, хотя, как я пытаюсь достичь здесь.

Мой график комиссий потенциально может выглядеть примерно так:

fee_schedule: [
{ fee: 0.0100, limit: 1000000},
{ fee: 0.0075, limit: 2000000},
{ fee: 0.0050, limit: 3000000},
{ fee: 0.0025, limit: Infinity}
]

Это направление, с которого я начал, но ударился о стену в моей голове, потому что увидел, как пишу смехотворно длинную функцию.

function determineFee(schedule, amount) {
   schedule.forEach(tier => {
    if (amount <= tier.limit) {
     // is this a path I should go down?
    }
   }
  //
}

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Вот еще одна возможность:

const blended = (schedule) => (amount) =>
  schedule.reduce ((sum, {fee, limit}, idx, sched) => {
    const top = Math.min (limit, amount)
    const bottom = idx == 0 ? 0 : sched[idx - 1].limit
  
    return sum + (top > bottom ? fee * (top - bottom) : 0)
  }, 0)

const blendedFee = (schedule) => {
  const calc = blended(schedule)
  return (amount) => calc(amount) / amount
}

const fee_schedule = [
  { fee: 0.0100, limit: 1000000},
  { fee: 0.0075, limit: 2000000},
  { fee: 0.0050, limit: 3000000},
  { fee: 0.0025, limit: Infinity}
]

console.log (blended (fee_schedule) (5000000))
console.log (blendedFee (fee_schedule) (5000000))

Обратите внимание, что это карри, поэтому вы можете сохранить ссылку на blended (fee_schedule) или blendedFee (fee_schedule), если вам понадобится повторно использовать их для различных сумм кредита.

Это не включает в себя умный ранний выход из ответа Нины, но я думаю, что легче следовать.

0 голосов
/ 28 февраля 2019

Вы можете построить дельту последнего или нулевого и фактического лимита или, если это последний элемент, взять Infinity, чтобы использовать комиссию для остатка оставшегося значения.

Затем сделатьпроверьте, меньше ли значение, чем дельта.Если значение равно true, рассчитайте плату для остального значения и завершите цикл.

В противном случае рассчитайте плату из дельты, уменьшите значение дельтой и присвойте лимит как последнее значение, чтобы иметь это значение для следующегопетля.

function getFee(value) {
    var fee = 0;

    fee_schedule.some((o, i, a) => {
        var delta = i + 1 === a.length
                ? Infinity
                : o.limit - (a[i - 1] && a[i - 1].limit || 0);

        if (value < delta) {
            fee += value * o.fee;
            return true;
        }
        fee += delta * o.fee;
        value -= delta;
    });

    return fee;
}

var fee_schedule = [{ fee: 0.0100, limit: 1000000 }, { fee: 0.0075, limit: 2000000 }, { fee: 0.0050, limit: 3000000 }, { fee: 0.0025, limit: 4000000 }],
    value = 5000000,
    fee = getFee(value);

console.log(fee);

Для более короткого подхода вы можете изменить набор данных и использовать только размер слота для пределов с одним миллионом для первых трех элементов и Infinity для последнего.

function getFee(value) {
    var sum = 0;

    fee_schedule.some(({ fee, limit }) => {
        var v = value < limit ? value : limit;
        sum += v * fee;
        return !(value -= v);
    });

    return sum;
}

var fee_schedule = [{ fee: 0.0100, limit: 1000000 }, { fee: 0.0075, limit: 1000000 }, { fee: 0.0050, limit: 1000000 }, { fee: 0.0025, limit: Infinity }],
    value = 5000000,
    fee = getFee(value);

console.log(fee);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...