quantopian / alphalens

Performance analysis of predictive (alpha) stock factors
http://quantopian.github.io/alphalens
Apache License 2.0
3.2k stars 1.12k forks source link

#help wanted: alphalens.performance.factor_weights returns negative weights #325

Closed Frankein closed 5 years ago

Frankein commented 5 years ago

When I input factors with negative values to alphalens, and then calculate the factor returns by default factor weighted method, it turns out that alphalens.performance.factor_weights returns negative weights.

import alphalens
import numpy as np
...#[build factor data]
 weights_1 = \
    alphalens.performance.factor_weights(factor_data[factor_data['factor_quantile'].isin([1])], False, False, False)
factor_data[factor_data['factor_quantile'].isin([1])]['factor'].head()
weights_1 = weights_1.unstack()
weights_1.head()
np.sum(weights_1, axis=1)

factor_data[factor_data['factor_quantile'].isin([1])]['factor'].head() returns:

date asset
2015-01-05 000004.SZ -0.345028 000020.SZ -0.373581 000038.SZ -0.373581 000546.SZ -0.351614 000736.SZ -0.343482 Name: factor, dtype: float64

It show the following (weights_1.head()): asset 000004.SZ 000011.SZ ... 603998.SH 603999.SH date ...
2015-01-05 -0.003744 NaN ... -0.003902 NaN 2015-01-06 -0.003730 NaN ... -0.003897 NaN 2015-01-07 -0.003729 NaN ... -0.003909 NaN 2015-01-08 -0.003709 NaN ... -0.003915 NaN 2015-01-09 -0.003723 NaN ... -0.003917 NaN

And(np.sum(weights_1, axis=1)): date 2015-01-05 -1.0 2015-01-06 -1.0 2015-01-07 -1.0 2015-01-08 -1.0 2015-01-09 -1.0 2015-01-12 -1.0 2015-01-13 -1.0 2015-01-14 -1.0 2015-01-15 -1.0 2015-01-16 -1.0 2015-01-19 -1.0 2015-01-20 -1.0 2015-01-21 -1.0 2015-01-22 -1.0 2015-01-23 -1.0 2015-01-26 -1.0 2015-01-27 -1.0 2015-01-28 -1.0 2015-01-29 -1.0 2015-01-30 -1.0 2015-02-02 -1.0 2015-02-03 -1.0 2015-02-04 -1.0 2015-02-05 -1.0 2015-02-06 -1.0 2015-02-09 -1.0 2015-02-10 -1.0 2015-02-11 -1.0 2015-02-12 -1.0 2015-02-13 -1.0

2018-08-28 -1.0 2018-08-29 -1.0 2018-08-30 -1.0 2018-08-31 -1.0 2018-09-03 -1.0 2018-09-04 -1.0 2018-09-05 -1.0 2018-09-06 -1.0 2018-09-07 -1.0 2018-09-10 -1.0 2018-09-11 -1.0 2018-09-12 -1.0 2018-09-13 -1.0 2018-09-14 -1.0 2018-09-17 -1.0 2018-09-18 -1.0 2018-09-19 -1.0 2018-09-20 -1.0 2018-09-21 -1.0 2018-09-25 -1.0 2018-09-26 -1.0 2018-09-27 -1.0 2018-09-28 -1.0 2018-10-08 -1.0 2018-10-09 -1.0 2018-10-10 -1.0 2018-10-11 -1.0 2018-10-12 -1.0 2018-10-15 -1.0 2018-10-16 -1.0 Freq: C, Length: 921, dtype: float64

Therefore, I infer that the first quantile portfolio is weighted negatively. Moreover, if I use alphalens.performance.factor_cumulative_returns the function will certainly returns a decreasing curve, which is not what I want.

I just wondering that why negative weighting is meaningful and why the alphalens.performance.factor_weights designed in this way?

Lastly, another simple question is that how can I fullfill monthly rebalance within alphalens? Thanks a lot!

Best, Frank

Frankein commented 5 years ago

issue closed.

'''
    long_short : bool, optional
        if True enforce a dollar neutral long-short portfolio: asset weights
        will be computed by demeaning factor values and dividing by the sum of
        their absolute value (achieving gross leverage of 1) which will cause
        the portfolio to hold both long and short positions and the total
        weights of both long and short positions will be equal.
        If False the portfolio weights will be computed dividing the factor
        values and  by the sum of their absolute value (achieving gross
        leverage of 1). Positive factor values will generate long positions and
        negative factor values will produce short positions so that a factor
        with only posive values will result in a long only portfolio.
'''

If anyone want long only portfolio with negative factor value, make sure what the parameter implied first.