Gini index can be evaluated to be negative by your code, "The Gini coefficient is double of the area between the Lorenz Curve and the 45◦ diagonal line", so in your code metrics.py::line56, it should be like raw = df.apply(lambda x: abs(2 * x.sum() / df.shape[0] - 1.))
while I push a mr to you which shows a example of gini can be negative and it pass the unitest .
this case shows a bad model which predict high-life-value users's scores lowest, so it's gini is negative since it's line is under the Lorenz Curve.
mr link: #17