def load_factors():
    """Load risk factor returns.

    Factors
    -------
    Symbol      Description                                            Source
    ------      ----------                                             ------
    MKT                                                                French
    SMB         Size (small minus big)                                 French
    HML         Value (high minus low)                                 French
    RMW         Profitability (robust minus weak)                      French
    CMA         Investment (conservative minus aggressive)             French
    UMD         Momentum (up minus down)                               French
    STR         Short-term reversal                                    French
    LTR         Long-term reversal                                     French
    BETA        Beta                                                   French
    ACC         Accruals                                               French
    VAR         Variance                                               French
    IVAR        Residual variance                                      French
    EP          Earnings-to-price                                      French
    CP          Cash flow-to-price                                     French
    DP          Dividend-to-price                                      French
    BAB         Betting against beta                                   AQR
    QMJ         Quality minus junk                                     AQR
    HMLD        Value (high minus low) [modified version]              AQR
    LIQ         Liquidity                                              Pastor
    BDLB        Bond lookback straddle                                 Hsieh
    FXLB        Curency lookback straddle                              Hsieh
    CMLB        Commodity lookback straddle                            Hsieh
    IRLB        Interest rate lookback straddle                        Hsieh
    STLB        Stock lookback straddle                                Hsieh
    PUT         CBOE S&P 500 PutWrite Index                            CBOE
    BXM         CBOE S&P 500 BuyWrite Index®                           CBOE
    RXM         CBOE S&P 500 Risk Reversal Index                       CBOE

    Source Directory
    ----------------
    Source      Link
    ------      ----
    French      http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html  # noqa
    Pastor      http://faculty.chicagobooth.edu/lubos.pastor/research/liq_data_1962_2016.txt  # noqa
    AQR         https://www.aqr.com/library/data-sets
    Hsieh       https://faculty.fuqua.duke.edu/~dah7/HFData.htm
    Fed         https://fred.stlouisfed.org/
    CBOE        http://www.cboe.com/products/strategy-benchmark-indexes
    """

    # TODO: factors elegible for addition
    #   VIIX, VIIZ, XIV, ZIV, CRP (AQR)
    #   http://www.cboe.com/micro/buywrite/monthendpricehistory.xls ends 2016
    #   could use:
    #   http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/putdailyprice.csv

    # Warning: slow, kludgy data retrieval follows
    # ------------------------------------------------------------------------

    # `tgt` will become a list of DataFrames and eventually concatenated
    tgt = []

    # MKT, SMB, HML, RMW, CMA, RF, UMD, STR, LTR
    facs = [
        "F-F_Research_Data_5_Factors_2x3",
        "F-F_Momentum_Factor",
        "F-F_ST_Reversal_Factor",
        "F-F_LT_Reversal_Factor",
    ]

    for fac in facs:
        tgt.append(pdr.DataReader(fac, "famafrench", DSTART)[0])

    # BETA, ACC, VAR, IVAR require some manipulation to compute returns
    # in the dual-sort method of Fama-French
    for i in ["BETA", "AC", "VAR", "RESVAR"]:
        ser = pdr.DataReader(
            "25_Portfolios_ME_" + i + "_5x5", "famafrench", DSTART
        )[0]
        ser = ser.iloc[:, [0, 5, 10, 15, 20]].mean(axis=1) - ser.iloc[
            :, [4, 9, 14, 19, 24]
        ].mean(axis=1)
        ser = ser.rename(i)
        tgt.append(ser)

    # E/P, CF/P, D/P (univariate sorts, quintile spreads)
    for i in ["E-P", "CF-P", "D-P"]:
        ser = pdr.DataReader(
            "Portfolios_Formed_on_" + i, "famafrench", DSTART
        )[0]
        ser = ser.loc[:, "Hi 20"] - ser.loc[:, "Lo 20"]
        ser = ser.rename(i)
        tgt.append(ser)

    tgt = [df.to_timestamp(how="end") for df in tgt]

    # BAB, QMJ, HMLD
    # TODO: performance is poor here, runtime is eaten up by these 3
    links = {
        "BAB": "http://bit.ly/2hWyaG8",
        "QMJ": "http://bit.ly/2hUBSgF",
        "HMLD": "http://bit.ly/2hdVb7G",
    }
    for key, value in links.items():
        ser = pd.read_excel(value, header=18, index_col=0)["USA"] * 100
        ser = ser.rename(key)
        tgt.append(ser)

    # Lookback straddles
    link = "http://faculty.fuqua.duke.edu/~dah7/DataLibrary/TF-Fac.xls"
    straddles = pd.read_excel(link, header=14, index_col=0)
    straddles.index = pd.DatetimeIndex(
        straddles.index.astype(str) + "01"
    ) + offsets.MonthEnd(1)
    straddles = straddles * 100.0
    tgt.append(straddles)

    # LIQ
    link = "http://bit.ly/2pn2oBK"
    liq = pd.read_csv(
        link,
        skiprows=14,
        delim_whitespace=True,
        header=None,
        usecols=[0, 3],
        index_col=0,
        names=["date", "LIQ"],
    )
    liq.index = pd.DatetimeIndex(
        liq.index.astype(str) + "01"
    ) + offsets.MonthEnd(1)
    liq = liq.replace(-99, np.nan) * 100.0
    tgt.append(liq)

    # USD, HY
    fred = pdr.DataReader(["DTWEXB", "BAMLH0A0HYM2"], "fred", DSTART)
    fred = fred.asfreq("D", method="ffill").fillna(method="ffill").asfreq("M")
    fred.loc[:, "DTWEXB"] = fred["DTWEXB"].pct_change() * 100.0
    fred.loc[:, "BAMLH0A0HYM2"] = fred["BAMLH0A0HYM2"].diff()
    tgt.append(fred)

    # PUT, BXM, RXM (CBOE options strategy indices)
    link1 = "http://www.cboe.com/micro/put/put_86-06.xls"
    link2 = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/putdailyprice.csv"  # noqa

    put1 = pd.read_excel(
        link1, index_col=0, skiprows=6, header=None
    ).rename_axis("DATE")
    put2 = pd.read_csv(
        link2, index_col=0, parse_dates=True, skiprows=7, header=None
    ).rename_axis("DATE")
    put = (
        pd.concat((put1, put2))
        .rename(columns={1: "PUT"})
        .iloc[:, 0]
        .asfreq("D", method="ffill")
        .fillna(method="ffill")
        .asfreq("M")
        .pct_change()
        * 100.0
    )
    tgt.append(put)

    link1 = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/bxmarchive.csv"  # noqa
    link2 = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/bxmcurrent.csv"  # noqa

    bxm1 = pd.read_csv(
        link1, index_col=0, parse_dates=True, skiprows=5, header=None
    ).rename_axis("DATE")
    bxm2 = pd.read_csv(
        link2, index_col=0, parse_dates=True, skiprows=4, header=None
    ).rename_axis("DATE")
    bxm = (
        pd.concat((bxm1, bxm2))
        .rename(columns={1: "BXM"})
        .iloc[:, 0]
        .asfreq("D", method="ffill")
        .fillna(method="ffill")
        .asfreq("M")
        .pct_change()
        * 100.0
    )
    tgt.append(bxm)

    link = "http://www.cboe.com/publish/scheduledtask/mktdata/datahouse/rxm_historical.csv"  # noqa
    rxm = (
        pd.read_csv(
            link, index_col=0, parse_dates=True, skiprows=2, header=None
        )
        .rename(columns={1: "RXM"})
        .rename_axis("DATE")
        .iloc[:, 0]
        .asfreq("D", method="ffill")
        .fillna(method="ffill")
        .asfreq("M")
        .pct_change()
        * 100.0
    )
    tgt.append(rxm)

    # Clean up data retrieved above
    # -----------------------------------------------------------------

    factors = pd.concat(tgt, axis=1).round(2)
    newnames = {
        "Mkt-RF": "MKT",
        "Mom   ": "UMD",
        "ST_Rev": "STR",
        "LT_Rev": "LTR",
        "RESVAR": "IVAR",
        "AC": "ACC",
        "PTFSBD": "BDLB",
        "PTFSFX": "FXLB",
        "PTFSCOM": "CMLB",
        "PTFSIR": "IRLB",
        "PTFSSTK": "STLB",
        "DTWEXB": "USD",
        "BAMLH0A0HYM2": "HY",
    }
    factors.rename(columns=newnames, inplace=True)

    # Get last valid RF date; returns will be constrained to this date
    factors = factors[: factors["RF"].last_valid_index()]

    # Subtract RF for long-only factors
    subtract = ["HY", "PUT", "BXM", "RXM"]

    for i in subtract:
        factors.loc[:, i] = factors[i] - factors["RF"]

    return factors
Load risk factor returns.

    Factors
    -------
    Symbol      Description                                            Source
    ------      ----------                                             ------
    MKT                                                                French
    SMB         Size (small minus big)                                 French
    HML         Value (high minus low)                                 French
    RMW         Profitability (robust minus weak)                      French
    CMA         Investment (conservative minus aggressive)             French
    UMD         Momentum (up minus down)                               French
    STR         Short-term reversal                                    French
    LTR         Long-term reversal                                     French
    BETA        Beta                                                   French
    ACC         Accruals                                               French
    VAR         Variance                                               French
    IVAR        Residual variance                                      French
    EP          Earnings-to-price                                      French
    CP          Cash flow-to-price                                     French
    DP          Dividend-to-price                                      French
    BAB         Betting against beta                                   AQR
    QMJ         Quality minus junk                                     AQR
    HMLD        Value (high minus low) [modified version]              AQR
    LIQ         Liquidity                                              Pastor
    BDLB        Bond lookback straddle                                 Hsieh
    FXLB        Curency lookback straddle                              Hsieh
    CMLB        Commodity lookback straddle                            Hsieh
    IRLB        Interest rate lookback straddle                        Hsieh
    STLB        Stock lookback straddle                                Hsieh
    PUT         CBOE S&P 500 PutWrite Index                            CBOE
    BXM         CBOE S&P 500 BuyWrite Index®                           CBOE
    RXM         CBOE S&P 500 Risk Reversal Index                       CBOE

    Source Directory
    ----------------
    Source      Link
    ------      ----
    French      http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html  # noqa
    Pastor      http://faculty.chicagobooth.edu/lubos.pastor/research/liq_data_1962_2016.txt  # noqa
    AQR         https://www.aqr.com/library/data-sets
    Hsieh       https://faculty.fuqua.duke.edu/~dah7/HFData.htm
    Fed         https://fred.stlouisfed.org/
    CBOE        http://www.cboe.com/products/strategy-benchmark-indexes