Issue
I am looking for a way to distribute a positive number proportionally to a list of numbers based on their value (higher gets more). Think of it as distributing a fixed bonus amount based on everyone's performance (pnl).
This is simple if the numbers are all positive. The prorata weight of [1,2,3] would be [1/6, 2/6, 3/6]. But I am not sure how to handle the case for something like [-1, 2, 3] in code?
Solution
In the absence of additional information: if the weights for [1,2,3] are [1/6, 2/6, 3/6], then for [-1,2,3] they would be [-1/4, 2/4, 3/4].
Example:
def get_weights(p, nums):
total = sum(nums)
return [p * num / total for num in nums]
print(get_weights(1, [1, 2, 3]))
print(get_weights(1, [-1, 2, 3]))
Output:
[0.16666666666666666, 0.3333333333333333, 0.5]
[-0.25, 0.5, 0.75]
UPDATED:
Based on OP's updated question and comments, one "bonus" policy that could be adopted is:
- allocate a "base bonus" pool from which everyone receives an equal base bonus
- in addition, allocate a "rank bonus" pool from which everyone receives an additional bonus pro rata with their performance ranking
- for the balance of the bonus pool, everyone with positive performance receives an additional bonus pro rata with their performance.
Example:
performance = [-1,2,3,-1]
bonus_pool = 1
base_bonus = 0.1
rank_bonus = 0.1
# rank items in the list `performance` and allocate the rank_bonus pro rata to rank
from collections import Counter
c = Counter(performance)
rank = {x[1][0][0]:(x[0] + 1, x[1][0][1]) for x in enumerate(zip(sorted(c.items())))}
total_rank = sum(v[0]*v[1] for v in rank.values())
pro_rata_bonus = 1 - base_bonus - rank_bonus
total_pro_rata = sum(x for x in performance if x > 0)
n = len(performance)
bonus_base = [bonus_pool * base_bonus / n for k in performance]
bonus_rank = [bonus_pool * rank_bonus * rank[k][0] / total_rank for k in performance]
bonus_pro_rata = [bonus_pool * pro_rata_bonus * max(k, 0) / total_pro_rata for k in performance]
bonus = [bonus_pool * (base_bonus / n + rank_bonus * rank[k][0] / total_rank +
pro_rata_bonus * max(k, 0) / total_pro_rata) for k in performance]
print(f'performance :', end=''); [print(f' {x:5}',end='') for x in performance]; print(f' TOTAL: {sum(performance):5}')
print(f'bonus_base :', end=''); [print(f' {x:0.3f}',end='') for x in bonus_base]; print(f' TOTAL: {sum(bonus_base):0.3f}')
print(f'bonus_rank :', end=''); [print(f' {x:0.3f}',end='') for x in bonus_rank]; print(f' TOTAL: {sum(bonus_rank):0.3f}')
print(f'bonus_pro_rata:', end=''); [print(f' {x:0.3f}',end='') for x in bonus_pro_rata]; print(f' TOTAL: {sum(bonus_pro_rata):0.3f}')
print(f'---------------', end=''); [print(f'------',end='') for x in bonus]; print()
print(f'bonus :', end=''); [print(f' {x:0.3f}',end='') for x in bonus]; print(f' TOTAL: {sum(bonus):0.3f}')
Output:
performance : -1 2 3 -1 TOTAL: 3
bonus_base : 0.025 0.025 0.025 0.025 TOTAL: 0.100
bonus_rank : 0.014 0.029 0.043 0.014 TOTAL: 0.100
bonus_pro_rata: 0.000 0.320 0.480 0.000 TOTAL: 0.800
---------------------------------------
bonus : 0.039 0.374 0.548 0.039 TOTAL: 1.000
Answered By - constantstranger
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.