<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def create_pyfolio_input(factor_data, period, capital=None, long_short=True, group_neutral=False, equal_weight=False, quantiles=None, groups=None, benchmark_period='1D'):
 """ Simulate a portfolio using the input factor and returns the portfolio performance data properly formatted for Pyfolio analysis. For more details on how this portfolio is built see: - performance.cumulative_returns (how the portfolio returns are computed) - performance.factor_weights (how assets weights are computed) Parameters factor_data : pd.DataFrame - MultiIndex A MultiIndex DataFrame indexed by date (level 0) and asset (level 1), containing the values for a single alpha factor, forward returns for each period, the factor quantile/bin that factor value belongs to, and (optionally) the group the asset belongs to. - See full explanation in utils.get_clean_factor_and_forward_returns period : string 'factor_data' column name corresponding to the 'period' returns to be used in the computation of porfolio returns capital : float, optional If set, then compute 'positions' in dollar amount instead of percentage 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. group_neutral : bool, optional If True simulates a group neutral portfolio: the portfolio weights will be computed so that each group will weigh the same. if 'long_short' is enabled the factor values demeaning will occur on the group level resulting in a dollar neutral, group neutral, long-short portfolio. If False group information will not be used in weights computation. equal_weight : bool, optional if True the assets will be equal-weighted. If long_short is True then the factor universe will be split in two equal sized groups with the top assets in long positions and bottom assets in short positions. if False the assets will be factor-weighed, see 'long_short' argument quantiles: sequence[int], optional Use only specific quantiles in the computation. By default all quantiles are used groups: sequence[string], optional Use only specific groups in the computation. By default all groups are used benchmark_period : string, optional By default benchmark returns are computed as the factor universe mean daily returns but 'benchmark_period' allows to choose a 'factor_data' column corresponding to the returns to be used in the computation of benchmark returns. More generally benchmark returns are computed as the factor universe returns traded at 'benchmark_period' frequency, equal weighting and long only Returns ------- returns : pd.Series Daily returns of the strategy, noncumulative. - Time series with decimal returns. - Example: 2015-07-16 -0.012143 2015-07-17 0.045350 2015-07-20 0.030957 2015-07-21 0.004902 positions : pd.DataFrame Time series of dollar amount (or percentage when 'capital' is not provided) invested in each position and cash. - Days where stocks are not held can be represented by 0. - Non-working capital is labelled 'cash' - Example: index 'AAPL' 'MSFT' cash 2004-01-09 13939.3800 -14012.9930 711.5585 2004-01-12 14492.6300 -14624.8700 27.1821 2004-01-13 -13853.2800 13653.6400 -43.6375 benchmark : pd.Series Benchmark returns computed as the factor universe mean daily returns. """


    #
    # Build returns:
    # we don't know the frequency at which the factor returns are computed but
    # pyfolio wants daily returns. So we compute the cumulative returns of the
    # factor, then resample it at 1 day frequency and finally compute daily
    # returns
    #
    cumrets = factor_cumulative_returns(factor_data,
                                        period,
                                        long_short,
                                        group_neutral,
                                        equal_weight,
                                        quantiles,
                                        groups)
    cumrets = cumrets.resample('1D').last().fillna(method='ffill')
    returns = cumrets.pct_change().fillna(0)

    #
    # Build positions. As pyfolio asks for daily position we have to resample
    # the positions returned by 'factor_positions' at 1 day frequency and
    # recompute the weights so that the sum of daily weights is 1.0
    #
    positions = factor_positions(factor_data,
                                 period,
                                 long_short,
                                 group_neutral,
                                 equal_weight,
                                 quantiles,
                                 groups)
    positions = positions.resample('1D').sum().fillna(method='ffill')
    positions = positions.div(positions.abs().sum(axis=1), axis=0).fillna(0)
    positions['cash'] = 1. - positions.sum(axis=1)

    # transform percentage positions to dollar positions
    if capital is not None:
        positions = positions.mul(
            cumrets.reindex(positions.index) * capital, axis=0)

    #
    #
    #
    # Build benchmark returns as the factor universe mean returns traded at
    # 'benchmark_period' frequency
    #
    fwd_ret_cols = utils.get_forward_returns_columns(factor_data.columns)
    if benchmark_period in fwd_ret_cols:
        benchmark_data = factor_data.copy()
        # make sure no negative positions
        benchmark_data['factor'] = benchmark_data['factor'].abs()
        benchmark_rets = factor_cumulative_returns(benchmark_data,
                                                   benchmark_period,
                                                   long_short=False,
                                                   group_neutral=False,
                                                   equal_weight=True)
        benchmark_rets = benchmark_rets.resample(
            '1D').last().fillna(method='ffill')
        benchmark_rets = benchmark_rets.pct_change().fillna(0)
        benchmark_rets.name = 'benchmark'
    else:
        benchmark_rets = None

    return returns, positions, benchmark_rets