4

I'm a bit stuck with this one and tried some stuff mentioned here but didn't help. Basically, I've got these arrays:

returns = np.array([0.01, 0.2, 0.05, -0.01, 0.3, -0.5])
weights = np.array([0.3, 0.25, 0.2, 0.15, 0.1, 0])

The idea is to create dynamic weighting in which highest weight matches with highest return. I tried sorting two arrays (or lists) depending on one another but it doesn't help (as mentioned here: Sorting list based on values from another list?), since it really depends on weight initialization.

Desired output would be (weights change their position depending on max/min and in between values of the returns array):

returns = np.array([0.01, 0.2, 0.05, -0.01, 0.3, -0.5])
weights = np.array([0.15, 0.25, 0.2, 0.1, 0.3, 0])

This generally would go row by row through some simple iteration but I cannot seem to crack the problem first. Sorting both separately and then matching ascending / descending order) is no good, since returns array has to be unsorted. Any ideas?

Piotr
  • 87
  • 5

3 Answers3

2

It looks like you need to use inverse of np.argsort. For simplicity, it could be called ranks. So you can get ranks of returns like so:

_, ranks = np.unique(np.argsort(returns), return_index=True)
>>> ranks
array([2, 4, 3, 1, 5, 0], dtype=int64)

And a remaining part is:

>>> np.sort(weights)[ranks]
array([0.15, 0.25, 0.2 , 0.1 , 0.3 , 0.  ])

Alternative way

Following discussion on similar topic, I found that assignment of inverse argsort could be done also in this way:

a1 = np.argsort(returns)
a2 = np.argsort(weights)
weights[a1] = weights[a2] 
>>> weights
array([0.15, 0.25, 0.2 , 0.1 , 0.3 , 0.  ])
mathfux
  • 5,759
  • 1
  • 14
  • 34
1

Check this out:

import numpy as np
returns = np.array([0.01, 0.2, 0.05, -0.01, 0.3, -0.5])
weights = np.array([0.3, 0.25, 0.2, 0.15, 0.1, 0])

temp_dict = dict(zip(sorted(returns), sorted(weights)))

for index, el in enumerate(weights):
    weights[index] = temp_dict[returns[index]]

print(returns)
print(weights)

The output will be:

[ 0.01  0.2   0.05 -0.01  0.3  -0.5 ]
[0.15 0.25 0.2  0.1  0.3  0.  ]
Nimantha
  • 6,405
  • 6
  • 28
  • 69
lorenzozane
  • 1,214
  • 1
  • 5
  • 15
0

First we find the correct ordering in 'returns' and then we apply this order to the sorted version of 'weights'.

import numpy as np

returns = np.array([0.01, 0.2, 0.05, -0.01, 0.3, -0.5])
weights = np.array([0.3, 0.25, 0.2, 0.15, 0.1, 0])

correctOrderReturns = np.argsort(returns)[::-1] # [4 1 2 0 3 5] Indices of the correct order from max to min in "returns"
sortedWeights = np.sort(weights)[::-1] # [0.3  0.25 0.2  0.15 0.1  0.  ] Ordered list from max to min of weights

for i in range (len(weights)):
    weights[correctOrderReturns[i]] = sortedWeights[i]    

print (returns) #[ 0.01  0.2   0.05 -0.01  0.3  -0.5 ]
print (weights) #[0.15 0.25 0.2  0.1  0.3  0.  ]

This prints the desired output:

Returns: [ 0.01 0.2 0.05 -0.01 0.3 -0.5 ]

Weights: [0.15 0.25 0.2 0.1 0.3 0. ]

Nimantha
  • 6,405
  • 6
  • 28
  • 69
rodvictor
  • 323
  • 1
  • 10