def to_ulcer_performance_index(prices, rf=0., nperiods=None):
    """
    Converts from prices -> `ulcer performance index <https://www.investopedia.com/terms/u/ulcerindex.asp>`_.

    See https://en.wikipedia.org/wiki/Ulcer_index

    Args:
        * prices (Series, DataFrame): Prices
        * rf (float, Series): `Risk-free rate of return <https://www.investopedia.com/terms/r/risk-freerate.asp>`_. Assumed to be expressed in
            yearly (annualized) terms or return series
        * nperiods (int): Used to deannualize rf if rf is provided (non-zero)

    """
    if type(rf) is float and rf != 0 and nperiods is None:
        raise Exception('nperiods must be set if rf != 0 and rf is not a price series')

    er = prices.to_returns().to_excess_returns(rf, nperiods=nperiods)

    return np.divide(er.mean(), prices.to_ulcer_index())