Scaled Colorscale for heatmap (python)

I have a situation where I am tracking historical returns (dynamically), and if negative, I want all colors to be red, (different shades of red depending on how much negative it is), and if positive, I want all colors to be green (also depending on how much bigger than zero). For example: returns with -1.02 will be light red whereas returns of -5.6 is dark red. Similarly, returns that are 0.9 is light green and 6% returns will be dark green.

Implementing the above with this colorscale for example: colorscale = [ [0.0, ‘rgb(153,0,13)’], [0.1, ‘rgb(203,24,29)’], [0.2, ‘rgb(239,59,44)’], [0.3, ‘rgb(251,106,74)’], [0.4, ‘rgb(252,146,114)’], [0.5, ‘rgb(252,187,161)’],[0.55, ‘rgb(199,233,192)’],[0.65, ‘rgb(161,217,155)’], [0.75, ‘rgb(116,196,118)’], [0.85, ‘rgb(65,171,93)’],[0.95, ‘rgb(35,139,69)’], [1, ‘rgb(0,109,44)’]]

yields some unexpected behavior. Because the first number is a “normalized” number, I may end up with a negative return of -0.62 with a light green color. (If most of the values are negative for example).
But that number should be light red.

Is there a way for me to get the desired behavior? If so, how?

Thanks for any tips.

If you want to make sure that the colourscale is mapped to symmetrically around zero you could use the zmin and zmax arguments to the heatmap. If you set zmax and zmin to be the same distance from 0, then the central colour will be zero, and you can just use a RedGreen colourmap. E.g. go.Heatmap(z=returns, zmin=-20, zmax=20).

If you don’t know in advance the magnitude of the returns, you could do something like extremum = max(np.max(returns), np.abs(np.min(returns))) and then set zmin=-extremum, zmax=extremum. Does this make sense?

I reckon you can also get similar results using zmid.