Pipeline values are often both positive and negative. Fed to optimize, positives become long and negatives shorted.
When using TargetWeights instead of MaximizeAlpha, there are various ways to normalize them for a target leverage of 1.0.
Decided to toss this out there as I've been using it quite a bit.
def before_trading_start(context, data):
context.out = pipeline_output('pipe')
context.alpha = norm(context, context.out.alpha)
def norm(c, d): # d data, it's a series, normalize it pos, neg separately
do_demean = 1 # centering all values around 0
preserve_zero_values = 1 # change to 0 if incoming zero-weights should simply be dropped.
trim_pos_neg_to_same_number_each = 1 # same number of stocks for positive & negative
if not len(d): return d # In case empy.
d = d[ d == d ] # Insure no nans.
if do_demean: # If all pos or neg, shift for both pos & neg.
if d.min() >= 0 or d.max() <= 0:
d -= d.mean()
zeros = None
if preserve_zero_values:
zeros = d[ d == 0 ]
pos = d[ d > 0 ]
neg = d[ d < 0 ]
if trim_pos_neg_to_same_number_each:
num = min(len(pos), len(neg))
pos = pos.sort_values(ascending=False).head(num)
neg = neg.sort_values(ascending=False).tail(num)
pos /= pos.sum()
neg = -(neg / neg.sum())
ret = pos.append(neg)
if preserve_zero_values and zeros is not None:
ret = ret.append(zeros)
return ret
[edited]