def model_best(y1, y2, samples=<NUM_LIT:1000>, progressbar=True):

y = np.concatenate((y1, y2))<EOL>mu_m = np.mean(y)<EOL>mu_p = <NUM_LIT> * <NUM_LIT:1> / np.std(y)**<NUM_LIT:2><EOL>sigma_low = np.std(y) / <NUM_LIT:1000><EOL>sigma_high = np.std(y) * <NUM_LIT:1000><EOL>with pm.Model() as model:<EOL><INDENT>group1_mean = pm.Normal('<STR_LIT>', mu=mu_m, tau=mu_p,<EOL>testval=y1.mean())<EOL>group2_mean = pm.Normal('<STR_LIT>', mu=mu_m, tau=mu_p,<EOL>testval=y2.mean())<EOL>group1_std = pm.Uniform('<STR_LIT>', lower=sigma_low,<EOL>upper=sigma_high, testval=y1.std())<EOL>group2_std = pm.Uniform('<STR_LIT>', lower=sigma_low,<EOL>upper=sigma_high, testval=y2.std())<EOL>nu = pm.Exponential('<STR_LIT>', <NUM_LIT:1> / <NUM_LIT>, testval=<NUM_LIT>) + <NUM_LIT><EOL>returns_group1 = pm.StudentT('<STR_LIT>', nu=nu, mu=group1_mean,<EOL>lam=group1_std**-<NUM_LIT:2>, observed=y1)<EOL>returns_group2 = pm.StudentT('<STR_LIT>', nu=nu, mu=group2_mean,<EOL>lam=group2_std**-<NUM_LIT:2>, observed=y2)<EOL>diff_of_means = pm.Deterministic('<STR_LIT>',<EOL>group2_mean - group1_mean)<EOL>pm.Deterministic('<STR_LIT>',<EOL>group2_std - group1_std)<EOL>pm.Deterministic('<STR_LIT>', diff_of_means /<EOL>pm.math.sqrt((group1_std**<NUM_LIT:2> +<EOL>group2_std**<NUM_LIT:2>) / <NUM_LIT:2>))<EOL>pm.Deterministic('<STR_LIT>',<EOL>returns_group1.distribution.variance**<NUM_LIT> *<EOL>np.sqrt(<NUM_LIT>))<EOL>pm.Deterministic('<STR_LIT>',<EOL>returns_group2.distribution.variance**<NUM_LIT> *<EOL>np.sqrt(<NUM_LIT>))<EOL>pm.Deterministic('<STR_LIT>', returns_group1.distribution.mean /<EOL>returns_group1.distribution.variance**<NUM_LIT> *<EOL>np.sqrt(<NUM_LIT>))<EOL>pm.Deterministic('<STR_LIT>', returns_group2.distribution.mean /<EOL>returns_group2.distribution.variance**<NUM_LIT> *<EOL>np.sqrt(<NUM_LIT>))<EOL>trace = pm.sample(samples, progressbar=progressbar)<EOL><DEDENT>return model, trace<EOL>

Bayesian Estimation Supersedes the T-Test

This model runs a Bayesian hypothesis comparing if y1 and y2 come
from the same distribution. Returns are assumed to be T-distributed.

In addition, computes annual volatility and Sharpe of in and
out-of-sample periods.

This model replicates the example used in:
Kruschke, John. (2012) Bayesian estimation supersedes the t
test. Journal of Experimental Psychology: General.

Parameters
----------
y1 : array-like
    Array of returns (e.g. in-sample)
y2 : array-like
    Array of returns (e.g. out-of-sample)
samples : int, optional
    Number of posterior samples to draw.

Returns
-------
model : pymc.Model object
    PyMC3 model containing all random variables.
trace : pymc3.sampling.BaseTrace object
    A PyMC3 trace object that contains samples for each parameter
    of the posterior.

See Also
--------
plot_stoch_vol : plotting of tochastic volatility model


def model_stoch_vol(data, samples=<NUM_LIT>, progressbar=True):

from pymc3.distributions.timeseries import GaussianRandomWalk<EOL>with pm.Model() as model:<EOL><INDENT>nu = pm.Exponential('<STR_LIT>', <NUM_LIT:1.> / <NUM_LIT:10>, testval=<NUM_LIT>)<EOL>sigma = pm.Exponential('<STR_LIT>', <NUM_LIT:1.> / <NUM_LIT>, testval=<NUM_LIT>)<EOL>s = GaussianRandomWalk('<STR_LIT:s>', sigma**-<NUM_LIT:2>, shape=len(data))<EOL>volatility_process = pm.Deterministic('<STR_LIT>',<EOL>pm.math.exp(-<NUM_LIT:2> * s))<EOL>pm.StudentT('<STR_LIT:r>', nu, lam=volatility_process, observed=data)<EOL>trace = pm.sample(samples, progressbar=progressbar)<EOL><DEDENT>return model, trace<EOL>

Run stochastic volatility model.

This model estimates the volatility of a returns series over time.
Returns are assumed to be T-distributed. lambda (width of
T-distributed) is assumed to follow a random-walk.

Parameters
----------
data : pandas.Series
    Return series to model.
samples : int, optional
    Posterior samples to draw.

Returns
-------
model : pymc.Model object
    PyMC3 model containing all random variables.
trace : pymc3.sampling.BaseTrace object
    A PyMC3 trace object that contains samples for each parameter
    of the posterior.

See Also
--------
plot_stoch_vol : plotting of tochastic volatility model


def plot_stoch_vol(data, trace=None, ax=None):

if trace is None:<EOL><INDENT>trace = model_stoch_vol(data)<EOL><DEDENT>if ax is None:<EOL><INDENT>fig, ax = plt.subplots(figsize=(<NUM_LIT:15>, <NUM_LIT:8>))<EOL><DEDENT>data.abs().plot(ax=ax)<EOL>ax.plot(data.index, np.exp(trace['<STR_LIT:s>', ::<NUM_LIT:30>].T), '<STR_LIT:r>', alpha=<NUM_LIT>)<EOL>ax.set(title='<STR_LIT>', xlabel='<STR_LIT>', ylabel='<STR_LIT>')<EOL>ax.legend(['<STR_LIT>', '<STR_LIT>'],<EOL>frameon=True, framealpha=<NUM_LIT:0.5>)<EOL>return ax<EOL>

Generate plot for stochastic volatility model.

Parameters
----------
data : pandas.Series
    Returns to model.
trace : pymc3.sampling.BaseTrace object, optional
    trace as returned by model_stoch_vol
    If not passed, sample from model.
ax : matplotlib.axes object, optional
    Plot into axes object

Returns
-------
ax object

See Also
--------
model_stoch_vol : run stochastic volatility model


def scoreatpercentile(cum_preds, p):<EOL><INDENT>return [stats.scoreatpercentile(<EOL>c, p) for c in cum_preds.T]<EOL><DEDENT>cum_preds = np.cumprod(preds + <NUM_LIT:1>, <NUM_LIT:1>) * starting_value<EOL>perc = {p: scoreatpercentile(cum_preds, p) for p in (<NUM_LIT:5>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>)}<EOL>return perc<EOL>

Compute 5, 25, 75 and 95 percentiles of cumulative returns, used
for the Bayesian cone.

Parameters
----------
preds : numpy.array
    Multiple (simulated) cumulative returns.
starting_value : int (optional)
    Have cumulative returns start around this value.
    Default = 1.

Returns
-------
dict of percentiles over time
    Dictionary mapping percentiles (5, 25, 75, 95) to a
    timeseries.


def vwap(transaction):<EOL><INDENT>if transaction.amount.sum() == <NUM_LIT:0>:<EOL><INDENT>warnings.warn('<STR_LIT>')<EOL>return np.nan<EOL><DEDENT>return (transaction.amount * transaction.price).sum() /transaction.amount.sum()<EOL><DEDENT>out = []<EOL>for sym, t in txn.groupby('<STR_LIT>'):<EOL><INDENT>t = t.sort_index()<EOL>t.index.name = '<STR_LIT>'<EOL>t = t.reset_index()<EOL>t['<STR_LIT>'] = t.amount > <NUM_LIT:0><EOL>t['<STR_LIT>'] = (t.order_sign.shift(<EOL><NUM_LIT:1>) != t.order_sign).astype(int).cumsum()<EOL>t['<STR_LIT>'] = ((t.dt.sub(t.dt.shift(<NUM_LIT:1>))) ><EOL>max_delta).astype(int).cumsum()<EOL>grouped_price = (t.groupby(('<STR_LIT>',<EOL>'<STR_LIT>'))<EOL>.apply(vwap))<EOL>grouped_price.name = '<STR_LIT>'<EOL>grouped_rest = t.groupby(('<STR_LIT>', '<STR_LIT>')).agg({<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>'})<EOL>grouped = grouped_rest.join(grouped_price)<EOL>out.append(grouped)<EOL><DEDENT>out = pd.concat(out)<EOL>out = out.set_index('<STR_LIT>')<EOL>return out<EOL>

Merge transactions of the same direction separated by less than
    max_delta time duration.

    Parameters
    ----------
    transactions : pd.DataFrame
        Prices and amounts of executed round_trips. One row per trade.
        - See full explanation in tears.create_full_tear_sheet

    max_delta : pandas.Timedelta (optional)
        Merge transactions in the same direction separated by less
        than max_delta time duration.

    Returns
    -------
    transactions : pd.DataFrame


transactions = _groupby_consecutive(transactions)<EOL>roundtrips = []<EOL>for sym, trans_sym in transactions.groupby('<STR_LIT>'):<EOL><INDENT>trans_sym = trans_sym.sort_index()<EOL>price_stack = deque()<EOL>dt_stack = deque()<EOL>trans_sym['<STR_LIT>'] = trans_sym.price *np.sign(trans_sym.amount)<EOL>trans_sym['<STR_LIT>'] = trans_sym.amount.abs().astype(int)<EOL>for dt, t in trans_sym.iterrows():<EOL><INDENT>if t.price < <NUM_LIT:0>:<EOL><INDENT>warnings.warn('<STR_LIT>'<EOL>'<STR_LIT>')<EOL>continue<EOL><DEDENT>indiv_prices = [t.signed_price] * t.abs_amount<EOL>if (len(price_stack) == <NUM_LIT:0>) or(copysign(<NUM_LIT:1>, price_stack[-<NUM_LIT:1>]) == copysign(<NUM_LIT:1>, t.amount)):<EOL><INDENT>price_stack.extend(indiv_prices)<EOL>dt_stack.extend([dt] * len(indiv_prices))<EOL><DEDENT>else:<EOL><INDENT>pnl = <NUM_LIT:0><EOL>invested = <NUM_LIT:0><EOL>cur_open_dts = []<EOL>for price in indiv_prices:<EOL><INDENT>if len(price_stack) != <NUM_LIT:0> and(copysign(<NUM_LIT:1>, price_stack[-<NUM_LIT:1>]) != copysign(<NUM_LIT:1>, price)):<EOL><INDENT>prev_price = price_stack.popleft()<EOL>prev_dt = dt_stack.popleft()<EOL>pnl += -(price + prev_price)<EOL>cur_open_dts.append(prev_dt)<EOL>invested += abs(prev_price)<EOL><DEDENT>else:<EOL><INDENT>price_stack.append(price)<EOL>dt_stack.append(dt)<EOL><DEDENT><DEDENT>roundtrips.append({'<STR_LIT>': pnl,<EOL>'<STR_LIT>': cur_open_dts[<NUM_LIT:0>],<EOL>'<STR_LIT>': dt,<EOL>'<STR_LIT>': price < <NUM_LIT:0>,<EOL>'<STR_LIT>': pnl / invested,<EOL>'<STR_LIT>': sym,<EOL>})<EOL><DEDENT><DEDENT><DEDENT>roundtrips = pd.DataFrame(roundtrips)<EOL>roundtrips['<STR_LIT>'] = roundtrips['<STR_LIT>'].sub(roundtrips['<STR_LIT>'])<EOL>if portfolio_value is not None:<EOL><INDENT>pv = pd.DataFrame(portfolio_value,<EOL>columns=['<STR_LIT>']).assign(date=portfolio_value.index)<EOL>roundtrips['<STR_LIT:date>'] = roundtrips.close_dt.apply(lambda x:<EOL>x.replace(hour=<NUM_LIT:0>,<EOL>minute=<NUM_LIT:0>,<EOL>second=<NUM_LIT:0>))<EOL>tmp = roundtrips.join(pv, on='<STR_LIT:date>', lsuffix='<STR_LIT:_>')<EOL>roundtrips['<STR_LIT>'] = tmp.pnl / tmp.portfolio_value<EOL>roundtrips = roundtrips.drop('<STR_LIT:date>', axis='<STR_LIT>')<EOL><DEDENT>return roundtrips<EOL>

Group transactions into "round trips". First, transactions are
    grouped by day and directionality. Then, long and short
    transactions are matched to create round-trip round_trips for which
    PnL, duration and returns are computed. Crossings where a position
    changes from long to short and vice-versa are handled correctly.

    Under the hood, we reconstruct the individual shares in a
    portfolio over time and match round_trips in a FIFO-order.

    For example, the following transactions would constitute one round trip:
    index                  amount   price    symbol
    2004-01-09 12:18:01    10       50      'AAPL'
    2004-01-09 15:12:53    10       100      'AAPL'
    2004-01-13 14:41:23    -10      100      'AAPL'
    2004-01-13 15:23:34    -10      200       'AAPL'

    First, the first two and last two round_trips will be merged into a two
    single transactions (computing the price via vwap). Then, during
    the portfolio reconstruction, the two resulting transactions will
    be merged and result in 1 round-trip trade with a PnL of
    (150 * 20) - (75 * 20) = 1500.

    Note, that round trips do not have to close out positions
    completely. For example, we could have removed the last
    transaction in the example above and still generated a round-trip
    over 10 shares with 10 shares left in the portfolio to be matched
    with a later transaction.

    Parameters
    ----------
    transactions : pd.DataFrame
        Prices and amounts of executed round_trips. One row per trade.
        - See full explanation in tears.create_full_tear_sheet

    portfolio_value : pd.Series (optional)
        Portfolio value (all net assets including cash) over time.
        Note that portfolio_value needs to beginning of day, so either
        use .shift() or positions.sum(axis='columns') / (1+returns).

    Returns
    -------
    round_trips : pd.DataFrame
        DataFrame with one row per round trip.  The returns column
        contains returns in respect to the portfolio value while
        rt_returns are the returns in regards to the invested capital
        into that partiulcar round-trip.


closed_txns = transactions[['<STR_LIT>', '<STR_LIT>', '<STR_LIT>']]<EOL>pos_at_end = positions.drop('<STR_LIT>', axis=<NUM_LIT:1>).iloc[-<NUM_LIT:1>]<EOL>open_pos = pos_at_end.replace(<NUM_LIT:0>, np.nan).dropna()<EOL>end_dt = open_pos.name + pd.Timedelta(seconds=<NUM_LIT:1>)<EOL>for sym, ending_val in open_pos.iteritems():<EOL><INDENT>txn_sym = transactions[transactions.symbol == sym]<EOL>ending_amount = txn_sym.amount.sum()<EOL>ending_price = ending_val / ending_amount<EOL>closing_txn = {'<STR_LIT>': sym,<EOL>'<STR_LIT>': -ending_amount,<EOL>'<STR_LIT>': ending_price}<EOL>closing_txn = pd.DataFrame(closing_txn, index=[end_dt])<EOL>closed_txns = closed_txns.append(closing_txn)<EOL><DEDENT>closed_txns = closed_txns[closed_txns.amount != <NUM_LIT:0>]<EOL>return closed_txns<EOL>

Appends transactions that close out all positions at the end of
the timespan covered by positions data. Utilizes pricing information
in the positions DataFrame to determine closing price.

Parameters
----------
positions : pd.DataFrame
    The positions that the strategy takes over time.
transactions : pd.DataFrame
    Prices and amounts of executed round_trips. One row per trade.
    - See full explanation in tears.create_full_tear_sheet

Returns
-------
closed_txns : pd.DataFrame
    Transactions with closing transactions appended.


sector_round_trips = round_trips.copy()<EOL>sector_round_trips.symbol = sector_round_trips.symbol.apply(<EOL>lambda x: sector_mappings.get(x, '<STR_LIT>'))<EOL>sector_round_trips = sector_round_trips.dropna(axis=<NUM_LIT:0>)<EOL>return sector_round_trips<EOL>

Translates round trip symbols to sectors.

Parameters
----------
round_trips : pd.DataFrame
    DataFrame with one row per round trip trade.
    - See full explanation in round_trips.extract_round_trips
sector_mappings : dict or pd.Series, optional
    Security identifier to sector mapping.
    Security ids as keys, sectors as values.

Returns
-------
sector_round_trips : pd.DataFrame
    Round trips with symbol names replaced by sector names.


stats = {}<EOL>stats['<STR_LIT>'] = agg_all_long_short(round_trips, '<STR_LIT>', PNL_STATS)<EOL>stats['<STR_LIT>'] = agg_all_long_short(round_trips, '<STR_LIT>',<EOL>SUMMARY_STATS)<EOL>stats['<STR_LIT>'] = agg_all_long_short(round_trips, '<STR_LIT>',<EOL>DURATION_STATS)<EOL>stats['<STR_LIT>'] = agg_all_long_short(round_trips, '<STR_LIT>',<EOL>RETURN_STATS)<EOL>stats['<STR_LIT>'] =round_trips.groupby('<STR_LIT>')['<STR_LIT>'].agg(RETURN_STATS).T<EOL>return stats<EOL>

Generate various round-trip statistics.

    Parameters
    ----------
    round_trips : pd.DataFrame
        DataFrame with one row per round trip trade.
        - See full explanation in round_trips.extract_round_trips

    Returns
    -------
    stats : dict
       A dictionary where each value is a pandas DataFrame containing
       various round-trip statistics.

    See also
    --------
    round_trips.print_round_trip_stats


stats = gen_round_trip_stats(round_trips)<EOL>print_table(stats['<STR_LIT>'], float_format='<STR_LIT>'.format,<EOL>name='<STR_LIT>')<EOL>print_table(stats['<STR_LIT>'], float_format='<STR_LIT>'.format, name='<STR_LIT>')<EOL>print_table(stats['<STR_LIT>'], float_format='<STR_LIT>'.format,<EOL>name='<STR_LIT>')<EOL>print_table(stats['<STR_LIT>'] * <NUM_LIT:100>, float_format='<STR_LIT>'.format,<EOL>name='<STR_LIT>')<EOL>if not hide_pos:<EOL><INDENT>stats['<STR_LIT>'].columns = stats['<STR_LIT>'].columns.map(format_asset)<EOL>print_table(stats['<STR_LIT>'] * <NUM_LIT:100>,<EOL>float_format='<STR_LIT>'.format, name='<STR_LIT>')<EOL><DEDENT>

Print various round-trip statistics. Tries to pretty-print tables
    with HTML output if run inside IPython NB.

    Parameters
    ----------
    round_trips : pd.DataFrame
        DataFrame with one row per round trip trade.
        - See full explanation in round_trips.extract_round_trips

    See also
    --------
    round_trips.gen_round_trip_stats


(returns,<EOL>positions,<EOL>factor_returns,<EOL>factor_loadings) = _align_and_warn(returns,<EOL>positions,<EOL>factor_returns,<EOL>factor_loadings,<EOL>transactions=transactions,<EOL>pos_in_dollars=pos_in_dollars)<EOL>positions = _stack_positions(positions, pos_in_dollars=pos_in_dollars)<EOL>return ep.perf_attrib(returns, positions, factor_returns, factor_loadings)<EOL>

Attributes the performance of a returns stream to a set of risk factors.

Preprocesses inputs, and then calls empyrical.perf_attrib. See
empyrical.perf_attrib for more info.

Performance attribution determines how much each risk factor, e.g.,
momentum, the technology sector, etc., contributed to total returns, as
well as the daily exposure to each of the risk factors. The returns that
can be attributed to one of the given risk factors are the
`common_returns`, and the returns that _cannot_ be attributed to a risk
factor are the `specific_returns`, or the alpha. The common_returns and
specific_returns summed together will always equal the total returns.

Parameters
----------
returns : pd.Series
    Returns for each day in the date range.
    - Example:
        2017-01-01   -0.017098
        2017-01-02    0.002683
        2017-01-03   -0.008669

positions: pd.DataFrame
    Daily holdings (in dollars or percentages), indexed by date.
    Will be converted to percentages if positions are in dollars.
    Short positions show up as cash in the 'cash' column.
    - Examples:
                    AAPL  TLT  XOM  cash
        2017-01-01    34   58   10     0
        2017-01-02    22   77   18     0
        2017-01-03   -15   27   30    15

                        AAPL       TLT       XOM  cash
        2017-01-01  0.333333  0.568627  0.098039   0.0
        2017-01-02  0.188034  0.658120  0.153846   0.0
        2017-01-03  0.208333  0.375000  0.416667   0.0

factor_returns : pd.DataFrame
    Returns by factor, with date as index and factors as columns
    - Example:
                    momentum  reversal
        2017-01-01  0.002779 -0.005453
        2017-01-02  0.001096  0.010290

factor_loadings : pd.DataFrame
    Factor loadings for all days in the date range, with date and ticker as
    index, and factors as columns.
    - Example:
                           momentum  reversal
        dt         ticker
        2017-01-01 AAPL   -1.592914  0.852830
                   TLT     0.184864  0.895534
                   XOM     0.993160  1.149353
        2017-01-02 AAPL   -0.140009 -0.524952
                   TLT    -1.066978  0.185435
                   XOM    -1.798401  0.761549

transactions : pd.DataFrame, optional
    Executed trade volumes and fill prices. Used to check the turnover of
    the algorithm. Default is None, in which case the turnover check is
    skipped.

    - One row per trade.
    - Trades on different names that occur at the
      same time will have identical indicies.
    - Example:
        index                  amount   price    symbol
        2004-01-09 12:18:01    483      324.12   'AAPL'
        2004-01-09 12:18:01    122      83.10    'MSFT'
        2004-01-13 14:12:23    -75      340.43   'AAPL'

pos_in_dollars : bool
    Flag indicating whether `positions` are in dollars or percentages
    If True, positions are in dollars.

Returns
-------
tuple of (risk_exposures_portfolio, perf_attribution)

risk_exposures_portfolio : pd.DataFrame
    df indexed by datetime, with factors as columns
    - Example:
                    momentum  reversal
        dt
        2017-01-01 -0.238655  0.077123
        2017-01-02  0.821872  1.520515

perf_attribution : pd.DataFrame
    df with factors, common returns, and specific returns as columns,
    and datetimes as index
    - Example:
                    momentum  reversal  common_returns  specific_returns
        dt
        2017-01-01  0.249087  0.935925        1.185012          1.185012
        2017-01-02 -0.003194 -0.400786       -0.403980         -0.403980


def compute_exposures(positions, factor_loadings, stack_positions=True,<EOL>pos_in_dollars=True):

if stack_positions:<EOL><INDENT>positions = _stack_positions(positions, pos_in_dollars=pos_in_dollars)<EOL><DEDENT>return ep.compute_exposures(positions, factor_loadings)<EOL>

Compute daily risk factor exposures.

Normalizes positions (if necessary) and calls ep.compute_exposures.
See empyrical.compute_exposures for more info.

Parameters
----------
positions: pd.DataFrame or pd.Series
    Daily holdings (in dollars or percentages), indexed by date, OR
    a series of holdings indexed by date and ticker.
    - Examples:
                    AAPL  TLT  XOM  cash
        2017-01-01    34   58   10     0
        2017-01-02    22   77   18     0
        2017-01-03   -15   27   30    15

                        AAPL       TLT       XOM  cash
        2017-01-01  0.333333  0.568627  0.098039   0.0
        2017-01-02  0.188034  0.658120  0.153846   0.0
        2017-01-03  0.208333  0.375000  0.416667   0.0

        dt          ticker
        2017-01-01  AAPL      0.417582
                    TLT       0.010989
                    XOM       0.571429
        2017-01-02  AAPL      0.202381
                    TLT       0.535714
                    XOM       0.261905

factor_loadings : pd.DataFrame
    Factor loadings for all days in the date range, with date and ticker as
    index, and factors as columns.
    - Example:
                           momentum  reversal
        dt         ticker
        2017-01-01 AAPL   -1.592914  0.852830
                   TLT     0.184864  0.895534
                   XOM     0.993160  1.149353
        2017-01-02 AAPL   -0.140009 -0.524952
                   TLT    -1.066978  0.185435
                   XOM    -1.798401  0.761549

stack_positions : bool
    Flag indicating whether `positions` should be converted to long format.

pos_in_dollars : bool
    Flag indicating whether `positions` are in dollars or percentages
    If True, positions are in dollars.

Returns
-------
risk_exposures_portfolio : pd.DataFrame
    df indexed by datetime, with factors as columns.
    - Example:
                    momentum  reversal
        dt
        2017-01-01 -0.238655  0.077123
        2017-01-02  0.821872  1.520515


summary = OrderedDict()<EOL>total_returns = perf_attrib['<STR_LIT>']<EOL>specific_returns = perf_attrib['<STR_LIT>']<EOL>common_returns = perf_attrib['<STR_LIT>']<EOL>summary['<STR_LIT>'] =ep.annual_return(specific_returns)<EOL>summary['<STR_LIT>'] =ep.annual_return(common_returns)<EOL>summary['<STR_LIT>'] =ep.annual_return(total_returns)<EOL>summary['<STR_LIT>'] =ep.sharpe_ratio(specific_returns)<EOL>summary['<STR_LIT>'] =ep.cum_returns_final(specific_returns)<EOL>summary['<STR_LIT>'] =ep.cum_returns_final(common_returns)<EOL>summary['<STR_LIT>'] =ep.cum_returns_final(total_returns)<EOL>summary = pd.Series(summary, name='<STR_LIT>')<EOL>annualized_returns_by_factor = [ep.annual_return(perf_attrib[c])<EOL>for c in risk_exposures.columns]<EOL>cumulative_returns_by_factor = [ep.cum_returns_final(perf_attrib[c])<EOL>for c in risk_exposures.columns]<EOL>risk_exposure_summary = pd.DataFrame(<EOL>data=OrderedDict([<EOL>(<EOL>'<STR_LIT>',<EOL>risk_exposures.mean(axis='<STR_LIT>')<EOL>),<EOL>('<STR_LIT>', annualized_returns_by_factor),<EOL>('<STR_LIT>', cumulative_returns_by_factor),<EOL>]),<EOL>index=risk_exposures.columns,<EOL>)<EOL>return summary, risk_exposure_summary<EOL>

Takes perf attribution data over a period of time and computes annualized
multifactor alpha, multifactor sharpe, risk exposures.


risk_exposures, perf_attrib_data = perf_attrib(<EOL>returns,<EOL>positions,<EOL>factor_returns,<EOL>factor_loadings,<EOL>transactions,<EOL>pos_in_dollars=pos_in_dollars,<EOL>)<EOL>perf_attrib_stats, risk_exposure_stats =create_perf_attrib_stats(perf_attrib_data, risk_exposures)<EOL>percentage_formatter = '<STR_LIT>'.format<EOL>float_formatter = '<STR_LIT>'.format<EOL>summary_stats = perf_attrib_stats.loc[['<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>']]<EOL>for col_name in (<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>):<EOL><INDENT>summary_stats[col_name] = percentage_formatter(summary_stats[col_name])<EOL><DEDENT>summary_stats['<STR_LIT>'] = float_formatter(<EOL>summary_stats['<STR_LIT>']<EOL>)<EOL>print_table(summary_stats, name='<STR_LIT>')<EOL>print_table(<EOL>risk_exposure_stats,<EOL>name='<STR_LIT>',<EOL>formatters={<EOL>'<STR_LIT>': float_formatter,<EOL>'<STR_LIT>': percentage_formatter,<EOL>'<STR_LIT>': percentage_formatter,<EOL>},<EOL>)<EOL>

Calls `perf_attrib` using inputs, and displays outputs using
`utils.print_table`.


def plot_returns(perf_attrib_data, cost=None, ax=None):

if ax is None:<EOL><INDENT>ax = plt.gca()<EOL><DEDENT>returns = perf_attrib_data['<STR_LIT>']<EOL>total_returns_label = '<STR_LIT>'<EOL>cumulative_returns_less_costs = _cumulative_returns_less_costs(<EOL>returns,<EOL>cost<EOL>)<EOL>if cost is not None:<EOL><INDENT>total_returns_label += '<STR_LIT>'<EOL><DEDENT>specific_returns = perf_attrib_data['<STR_LIT>']<EOL>common_returns = perf_attrib_data['<STR_LIT>']<EOL>ax.plot(cumulative_returns_less_costs, color='<STR_LIT:b>',<EOL>label=total_returns_label)<EOL>ax.plot(ep.cum_returns(specific_returns), color='<STR_LIT:g>',<EOL>label='<STR_LIT>')<EOL>ax.plot(ep.cum_returns(common_returns), color='<STR_LIT:r>',<EOL>label='<STR_LIT>')<EOL>if cost is not None:<EOL><INDENT>ax.plot(-ep.cum_returns(cost), color='<STR_LIT:k>',<EOL>label='<STR_LIT>')<EOL><DEDENT>ax.set_title('<STR_LIT>')<EOL>ax.set_ylabel('<STR_LIT>')<EOL>configure_legend(ax)<EOL>return ax<EOL>

Plot total, specific, and common returns.

Parameters
----------
perf_attrib_data : pd.DataFrame
    df with factors, common returns, and specific returns as columns,
    and datetimes as index. Assumes the `total_returns` column is NOT
    cost adjusted.
    - Example:
                    momentum  reversal  common_returns  specific_returns
        dt
        2017-01-01  0.249087  0.935925        1.185012          1.185012
        2017-01-02 -0.003194 -0.400786       -0.403980         -0.403980

cost : pd.Series, optional
    if present, gets subtracted from `perf_attrib_data['total_returns']`,
    and gets plotted separately

ax :  matplotlib.axes.Axes
    axes on which plots are made. if None, current axes will be used

Returns
-------
ax :  matplotlib.axes.Axes


if ax is None:<EOL><INDENT>ax = plt.gca()<EOL><DEDENT>ax.hist(alpha_returns, color='<STR_LIT:g>', label='<STR_LIT>')<EOL>ax.set_title('<STR_LIT>')<EOL>ax.axvline(<NUM_LIT:0>, color='<STR_LIT:k>', linestyle='<STR_LIT>', label='<STR_LIT>')<EOL>avg = alpha_returns.mean()<EOL>ax.axvline(avg, color='<STR_LIT:b>', label='<STR_LIT>'.format(avg))<EOL>configure_legend(ax)<EOL>return ax<EOL>

Plot histogram of daily multi-factor alpha returns (specific returns).

Parameters
----------
alpha_returns : pd.Series
    series of daily alpha returns indexed by datetime

ax :  matplotlib.axes.Axes
    axes on which plots are made. if None, current axes will be used

Returns
-------
ax :  matplotlib.axes.Axes


if ax is None:<EOL><INDENT>ax = plt.gca()<EOL><DEDENT>factors_to_plot = perf_attrib_data.drop(<EOL>['<STR_LIT>', '<STR_LIT>'], axis='<STR_LIT>', errors='<STR_LIT:ignore>'<EOL>)<EOL>factors_cumulative = pd.DataFrame()<EOL>for factor in factors_to_plot:<EOL><INDENT>factors_cumulative[factor] = ep.cum_returns(factors_to_plot[factor])<EOL><DEDENT>for col in factors_cumulative:<EOL><INDENT>ax.plot(factors_cumulative[col])<EOL><DEDENT>ax.axhline(<NUM_LIT:0>, color='<STR_LIT:k>')<EOL>configure_legend(ax, change_colors=True)<EOL>ax.set_ylabel('<STR_LIT>')<EOL>ax.set_title(title)<EOL>return ax<EOL>

Plot each factor's contribution to performance.

Parameters
----------
perf_attrib_data : pd.DataFrame
    df with factors, common returns, and specific returns as columns,
    and datetimes as index
    - Example:
                    momentum  reversal  common_returns  specific_returns
        dt
        2017-01-01  0.249087  0.935925        1.185012          1.185012
        2017-01-02 -0.003194 -0.400786       -0.403980         -0.403980

ax :  matplotlib.axes.Axes
    axes on which plots are made. if None, current axes will be used

title : str, optional
    title of plot

Returns
-------
ax :  matplotlib.axes.Axes


if ax is None:<EOL><INDENT>ax = plt.gca()<EOL><DEDENT>for col in exposures:<EOL><INDENT>ax.plot(exposures[col])<EOL><DEDENT>configure_legend(ax, change_colors=True)<EOL>ax.set_ylabel('<STR_LIT>')<EOL>ax.set_title(title)<EOL>return ax<EOL>

Parameters
----------
exposures : pd.DataFrame
    df indexed by datetime, with factors as columns
    - Example:
                    momentum  reversal
        dt
        2017-01-01 -0.238655  0.077123
        2017-01-02  0.821872  1.520515

ax :  matplotlib.axes.Axes
    axes on which plots are made. if None, current axes will be used

Returns
-------
ax :  matplotlib.axes.Axes


missing_stocks = positions.columns.difference(<EOL>factor_loadings.index.get_level_values(<NUM_LIT:1>).unique()<EOL>)<EOL>num_stocks = len(positions.columns) - <NUM_LIT:1><EOL>missing_stocks = missing_stocks.drop('<STR_LIT>')<EOL>num_stocks_covered = num_stocks - len(missing_stocks)<EOL>missing_ratio = round(len(missing_stocks) / num_stocks, ndigits=<NUM_LIT:3>)<EOL>if num_stocks_covered == <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>if len(missing_stocks) > <NUM_LIT:0>:<EOL><INDENT>if len(missing_stocks) > <NUM_LIT:5>:<EOL><INDENT>missing_stocks_displayed = (<EOL>"<STR_LIT>"<EOL>).format(len(missing_stocks),<EOL>'<STR_LIT:U+002CU+0020>'.join(missing_stocks[:<NUM_LIT:5>].map(str)),<EOL>missing_stocks[-<NUM_LIT:1>])<EOL>avg_allocation_msg = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>missing_stocks_displayed = (<EOL>"<STR_LIT>"<EOL>).format(list(missing_stocks))<EOL>avg_allocation_msg = "<STR_LIT>"<EOL><DEDENT>missing_stocks_warning_msg = (<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT:\n>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT:\n>"<EOL>"<STR_LIT>"<EOL>).format(<EOL>missing_stocks_displayed,<EOL>missing_ratio,<EOL>avg_allocation_msg,<EOL>positions[missing_stocks[:<NUM_LIT:5>].union(missing_stocks[[-<NUM_LIT:1>]])].mean(),<EOL>)<EOL>warnings.warn(missing_stocks_warning_msg)<EOL>positions = positions.drop(missing_stocks, axis='<STR_LIT>',<EOL>errors='<STR_LIT:ignore>')<EOL><DEDENT>missing_factor_loadings_index = positions.index.difference(<EOL>factor_loadings.index.get_level_values(<NUM_LIT:0>).unique()<EOL>)<EOL>missing_factor_loadings_index = positions.index.difference(<EOL>factor_loadings.index.get_level_values(<NUM_LIT:0>).unique()<EOL>)<EOL>if len(missing_factor_loadings_index) > <NUM_LIT:0>:<EOL><INDENT>if len(missing_factor_loadings_index) > <NUM_LIT:5>:<EOL><INDENT>missing_dates_displayed = (<EOL>"<STR_LIT>"<EOL>).format(<EOL>missing_factor_loadings_index[<NUM_LIT:0>],<EOL>missing_factor_loadings_index[-<NUM_LIT:1>]<EOL>)<EOL><DEDENT>else:<EOL><INDENT>missing_dates_displayed = list(missing_factor_loadings_index)<EOL><DEDENT>warning_msg = (<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>).format(len(missing_factor_loadings_index), missing_dates_displayed)<EOL>warnings.warn(warning_msg)<EOL>positions = positions.drop(missing_factor_loadings_index,<EOL>errors='<STR_LIT:ignore>')<EOL>returns = returns.drop(missing_factor_loadings_index, errors='<STR_LIT:ignore>')<EOL>factor_returns = factor_returns.drop(missing_factor_loadings_index,<EOL>errors='<STR_LIT:ignore>')<EOL><DEDENT>if transactions is not None and pos_in_dollars:<EOL><INDENT>turnover = get_turnover(positions, transactions).mean()<EOL>if turnover > PERF_ATTRIB_TURNOVER_THRESHOLD:<EOL><INDENT>warning_msg = (<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT:\n>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>)<EOL>warnings.warn(warning_msg)<EOL><DEDENT><DEDENT>return (returns, positions, factor_returns, factor_loadings)<EOL>

Make sure that all inputs have matching dates and tickers,
and raise warnings if necessary.


if pos_in_dollars:<EOL><INDENT>positions = get_percent_alloc(positions)<EOL><DEDENT>positions = positions.drop('<STR_LIT>', axis='<STR_LIT>')<EOL>positions = positions.stack()<EOL>positions.index = positions.index.set_names(['<STR_LIT>', '<STR_LIT>'])<EOL>return positions<EOL>

Convert positions to percentages if necessary, and change them
to long format.

Parameters
----------
positions: pd.DataFrame
    Daily holdings (in dollars or percentages), indexed by date.
    Will be converted to percentages if positions are in dollars.
    Short positions show up as cash in the 'cash' column.

pos_in_dollars : bool
    Flag indicating whether `positions` are in dollars or percentages
    If True, positions are in dollars.


if costs is None:<EOL><INDENT>return ep.cum_returns(returns)<EOL><DEDENT>return ep.cum_returns(returns - costs)<EOL>


return '<STR_LIT>' % x<EOL>


try:<EOL><INDENT>import zipline.assets<EOL><DEDENT>except ImportError:<EOL><INDENT>return asset<EOL><DEDENT>if isinstance(asset, zipline.assets.Asset):<EOL><INDENT>return asset.symbol<EOL><DEDENT>else:<EOL><INDENT>return asset<EOL><DEDENT>

If zipline asset objects are used, we want to print them out prettily
within the tear sheet. This function should only be applied directly
before displaying.


def wrapper(df, *args, **kwargs):<EOL><INDENT>if df.ndim == <NUM_LIT:1>:<EOL><INDENT>return func(df, *args, **kwargs)<EOL><DEDENT>elif df.ndim == <NUM_LIT:2>:<EOL><INDENT>return df.apply(func, *args, **kwargs)<EOL><DEDENT><DEDENT>return wrapper<EOL>

Decorator so that functions can be written to work on Series but
may still be called with DataFrames.


if isinstance(table, pd.Series):<EOL><INDENT>table = pd.DataFrame(table)<EOL><DEDENT>if name is not None:<EOL><INDENT>table.columns.name = name<EOL><DEDENT>html = table.to_html(float_format=float_format, formatters=formatters)<EOL>if header_rows is not None:<EOL><INDENT>n_cols = html.split('<STR_LIT>')[<NUM_LIT:1>].split('<STR_LIT>')[<NUM_LIT:0>].count('<STR_LIT>')<EOL>rows = '<STR_LIT>'<EOL>for name, value in header_rows.items():<EOL><INDENT>rows += ('<STR_LIT>' +<EOL>'<STR_LIT>') % (name, n_cols, value)<EOL><DEDENT>html = html.replace('<STR_LIT>', '<STR_LIT>' + rows)<EOL><DEDENT>display(HTML(html))<EOL>

Pretty print a pandas DataFrame.

Uses HTML output if running inside Jupyter Notebook, otherwise
formatted text output.

Parameters
----------
table : pandas.Series or pandas.DataFrame
    Table to pretty-print.
name : str, optional
    Table name to display in upper left corner.
float_format : function, optional
    Formatter to use for displaying table elements, passed as the
    `float_format` arg to pd.Dataframe.to_html.
    E.g. `'{0:.2%}'.format` for displaying 100 as '100.00%'.
formatters : list or dict, optional
    Formatters to use by column, passed as the `formatters` arg to
    pd.Dataframe.to_html.
header_rows : dict, optional
    Extra rows to display at the top of the table.


return (x - np.mean(x)) / np.std(x)<EOL>

Standardize an array with mean and standard deviation.

Parameters
----------
x : np.array
    Array to standardize.

Returns
-------
np.array
    Standardized array.


def detect_intraday(positions, transactions, threshold=<NUM_LIT>):

daily_txn = transactions.copy()<EOL>daily_txn.index = daily_txn.index.date<EOL>txn_count = daily_txn.groupby(level=<NUM_LIT:0>).symbol.nunique().sum()<EOL>daily_pos = positions.drop('<STR_LIT>', axis=<NUM_LIT:1>).replace(<NUM_LIT:0>, np.nan)<EOL>return daily_pos.count(axis=<NUM_LIT:1>).sum() / txn_count < threshold<EOL>

Attempt to detect an intraday strategy. Get the number of
positions held at the end of the day, and divide that by the
number of unique stocks transacted every day. If the average quotient
is below a threshold, then an intraday strategy is detected.

Parameters
----------
positions : pd.DataFrame
    Daily net position values.
     - See full explanation in create_full_tear_sheet.
transactions : pd.DataFrame
    Prices and amounts of executed trades. One row per trade.
     - See full explanation in create_full_tear_sheet.

Returns
-------
boolean
    True if an intraday strategy is detected.


def check_intraday(estimate, returns, positions, transactions):

if estimate == '<STR_LIT>':<EOL><INDENT>if positions is not None and transactions is not None:<EOL><INDENT>if detect_intraday(positions, transactions):<EOL><INDENT>warnings.warn('<STR_LIT>' +<EOL>'<STR_LIT>' +<EOL>'<STR_LIT>')<EOL>return estimate_intraday(returns, positions, transactions)<EOL><DEDENT>else:<EOL><INDENT>return positions<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return positions<EOL><DEDENT><DEDENT>elif estimate:<EOL><INDENT>if positions is not None and transactions is not None:<EOL><INDENT>return estimate_intraday(returns, positions, transactions)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return positions<EOL><DEDENT>

Logic for checking if a strategy is intraday and processing it.

Parameters
----------
estimate: boolean or str, optional
    Approximate returns for intraday strategies.
    See description in tears.create_full_tear_sheet.
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in create_full_tear_sheet.
positions : pd.DataFrame
    Daily net position values.
     - See full explanation in create_full_tear_sheet.
transactions : pd.DataFrame
    Prices and amounts of executed trades. One row per trade.
     - See full explanation in create_full_tear_sheet.

Returns
-------
pd.DataFrame
    Daily net position values, adjusted for intraday movement.


def estimate_intraday(returns, positions, transactions, EOD_hour=<NUM_LIT>):

<EOL>txn_val = transactions.copy()<EOL>txn_val.index.names = ['<STR_LIT:date>']<EOL>txn_val['<STR_LIT:value>'] = txn_val.amount * txn_val.price<EOL>txn_val = txn_val.reset_index().pivot_table(<EOL>index='<STR_LIT:date>', values='<STR_LIT:value>',<EOL>columns='<STR_LIT>').replace(np.nan, <NUM_LIT:0>)<EOL>txn_val['<STR_LIT:date>'] = txn_val.index.date<EOL>txn_val = txn_val.groupby('<STR_LIT:date>').cumsum()<EOL>txn_val['<STR_LIT>'] = txn_val.abs().sum(axis=<NUM_LIT:1>)<EOL>condition = (txn_val['<STR_LIT>'] == txn_val.groupby(<EOL>pd.TimeGrouper('<STR_LIT>'))['<STR_LIT>'].transform(max))<EOL>txn_val = txn_val[condition].drop('<STR_LIT>', axis=<NUM_LIT:1>)<EOL>txn_val['<STR_LIT>'] = -txn_val.sum(axis=<NUM_LIT:1>)<EOL>positions_shifted = positions.copy().shift(<NUM_LIT:1>).fillna(<NUM_LIT:0>)<EOL>starting_capital = positions.iloc[<NUM_LIT:0>].sum() / (<NUM_LIT:1> + returns[<NUM_LIT:0>])<EOL>positions_shifted.cash[<NUM_LIT:0>] = starting_capital<EOL>txn_val.index = txn_val.index.normalize()<EOL>corrected_positions = positions_shifted.add(txn_val, fill_value=<NUM_LIT:0>)<EOL>corrected_positions.index.name = '<STR_LIT>'<EOL>corrected_positions.columns.name = '<STR_LIT>'<EOL>return corrected_positions<EOL>

Intraday strategies will often not hold positions at the day end.
This attempts to find the point in the day that best represents
the activity of the strategy on that day, and effectively resamples
the end-of-day positions with the positions at this point of day.
The point of day is found by detecting when our exposure in the
market is at its maximum point. Note that this is an estimate.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in create_full_tear_sheet.
positions : pd.DataFrame
    Daily net position values.
     - See full explanation in create_full_tear_sheet.
transactions : pd.DataFrame
    Prices and amounts of executed trades. One row per trade.
     - See full explanation in create_full_tear_sheet.

Returns
-------
pd.DataFrame
    Daily net position values, resampled for intraday behavior.


if (rets.index[<NUM_LIT:0>] < benchmark_rets.index[<NUM_LIT:0>])or (rets.index[-<NUM_LIT:1>] > benchmark_rets.index[-<NUM_LIT:1>]):<EOL><INDENT>clipped_rets = rets[benchmark_rets.index]<EOL><DEDENT>else:<EOL><INDENT>clipped_rets = rets<EOL><DEDENT>return clipped_rets<EOL>

Drop entries from rets so that the start and end dates of rets match those
of benchmark_rets.

Parameters
----------
rets : pd.Series
    Daily returns of the strategy, noncumulative.
     - See pf.tears.create_full_tear_sheet for more details

benchmark_rets : pd.Series
    Daily returns of the benchmark, noncumulative.

Returns
-------
clipped_rets : pd.Series
    Daily noncumulative returns with index clipped to match that of
    benchmark returns.


try:<EOL><INDENT>df.index = df.index.tz_localize('<STR_LIT>')<EOL><DEDENT>except TypeError:<EOL><INDENT>df.index = df.index.tz_convert('<STR_LIT>')<EOL><DEDENT>return df<EOL>

For use in tests; applied UTC timestamp to DataFrame.


return df[df.columns[<NUM_LIT:0>]]<EOL>

For use in tests; converts DataFrame's first column to Series.


SETTINGS['<STR_LIT>'] = func<EOL>

Registers the 'returns_func' that will be called for
retrieving returns data.

Parameters
----------
func : function
    A function that returns a pandas Series of asset returns.
    The signature of the function must be as follows

    >>> func(symbol)

    Where symbol is an asset identifier

Returns
-------
None


def get_symbol_rets(symbol, start=None, end=None):

return SETTINGS['<STR_LIT>'](symbol,<EOL>start=start,<EOL>end=end)<EOL>

Calls the currently registered 'returns_func'

Parameters
----------
symbol : object
    An identifier for the asset whose return
    series is desired.
    e.g. ticker symbol or database ID
start : date, optional
    Earliest date to fetch data for.
    Defaults to earliest date available.
end : date, optional
    Latest date to fetch data for.
    Defaults to latest date available.

Returns
-------
pandas.Series
    Returned by the current 'returns_func'


def configure_legend(ax, autofmt_xdate=True, change_colors=False,<EOL>rotation=<NUM_LIT:30>, ha='<STR_LIT:right>'):

chartBox = ax.get_position()<EOL>ax.set_position([chartBox.x0, chartBox.y0,<EOL>chartBox.width * <NUM_LIT>, chartBox.height])<EOL>handles, labels = ax.get_legend_handles_labels()<EOL>handles_and_labels_sorted = sorted(zip(handles, labels),<EOL>key=lambda x: x[<NUM_LIT:0>].get_ydata()[-<NUM_LIT:1>],<EOL>reverse=True)<EOL>handles_sorted = [h[<NUM_LIT:0>] for h in handles_and_labels_sorted]<EOL>labels_sorted = [h[<NUM_LIT:1>] for h in handles_and_labels_sorted]<EOL>if change_colors:<EOL><INDENT>for handle, color in zip(handles_sorted,<EOL>cycle(COLORS)):<EOL><INDENT>handle.set_color(color)<EOL><DEDENT><DEDENT>ax.legend(handles=handles_sorted,<EOL>labels=labels_sorted,<EOL>frameon=True,<EOL>framealpha=<NUM_LIT:0.5>,<EOL>loc='<STR_LIT>',<EOL>bbox_to_anchor=(<NUM_LIT>, <NUM_LIT:1>),<EOL>fontsize='<STR_LIT>')<EOL>if autofmt_xdate:<EOL><INDENT>for label in ax.get_xticklabels():<EOL><INDENT>label.set_ha(ha)<EOL>label.set_rotation(rotation)<EOL><DEDENT><DEDENT>

Format legend for perf attribution plots:
- put legend to the right of plot instead of overlapping with it
- make legend order match up with graph lines
- set colors according to colormap


colors = []<EOL>colormap = cm.cmap_d[cmap_name]<EOL>for i in np.linspace(<NUM_LIT:0>, <NUM_LIT:1>, n_samples):<EOL><INDENT>colors.append(colormap(i))<EOL><DEDENT>return colors<EOL>


def var_cov_var_normal(P, c, mu=<NUM_LIT:0>, sigma=<NUM_LIT:1>):

alpha = sp.stats.norm.ppf(<NUM_LIT:1> - c, mu, sigma)<EOL>return P - P * (alpha + <NUM_LIT:1>)<EOL>

Variance-covariance calculation of daily Value-at-Risk in a
portfolio.

Parameters
----------
P : float
    Portfolio value.
c : float
    Confidence level.
mu : float, optional
    Mean.

Returns
-------
float
    Variance-covariance.


return ep.max_drawdown(returns)<EOL>

Determines the maximum drawdown of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.

Returns
-------
float
    Maximum drawdown.

Note
-----
See https://en.wikipedia.org/wiki/Drawdown_(economics) for more details.


return ep.annual_return(returns, period=period)<EOL>

Determines the mean annual growth rate of returns.

Parameters
----------
returns : pd.Series
    Periodic returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
period : str, optional
    Defines the periodicity of the 'returns' data for purposes of
    annualizing. Can be 'monthly', 'weekly', or 'daily'.
    - Defaults to 'daily'.

Returns
-------
float
    Annual Return as CAGR (Compounded Annual Growth Rate).


return ep.annual_volatility(returns, period=period)<EOL>

Determines the annual volatility of a strategy.

Parameters
----------
returns : pd.Series
    Periodic returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
period : str, optional
    Defines the periodicity of the 'returns' data for purposes of
    annualizing volatility. Can be 'monthly' or 'weekly' or 'daily'.
    - Defaults to 'daily'.

Returns
-------
float
    Annual volatility.


return ep.calmar_ratio(returns, period=period)<EOL>

Determines the Calmar ratio, or drawdown ratio, of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
period : str, optional
    Defines the periodicity of the 'returns' data for purposes of
    annualizing. Can be 'monthly', 'weekly', or 'daily'.
    - Defaults to 'daily'.

Returns
-------
float
    Calmar ratio (drawdown ratio) as float. Returns np.nan if there is no
    calmar ratio.

Note
-----
See https://en.wikipedia.org/wiki/Calmar_ratio for more details.


return ep.omega_ratio(returns,<EOL>required_return=annual_return_threshhold)<EOL>

Determines the Omega ratio of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
annual_return_threshold : float, optional
    Minimum acceptable return of the investor. Annual threshold over which
    returns are considered positive or negative. It is converted to a
    value appropriate for the period of the returns for this ratio.
    E.g. An annual minimum acceptable return of 100 translates to a daily
    minimum acceptable return of 0.01848.
        (1 + 100) ** (1. / 252) - 1 = 0.01848
    Daily returns must exceed this value to be considered positive. The
    daily return yields the desired annual return when compounded over
    the average number of business days in a year.
        (1 + 0.01848) ** 252 - 1 = 99.93
    - Defaults to 0.0

Returns
-------
float
    Omega ratio.

Note
-----
See https://en.wikipedia.org/wiki/Omega_ratio for more details.


@deprecated(msg=DEPRECATION_WARNING)<EOL>def sortino_ratio(returns, required_return=<NUM_LIT:0>, period=DAILY):

return ep.sortino_ratio(returns, required_return=required_return)<EOL>

Determines the Sortino ratio of a strategy.

Parameters
----------
returns : pd.Series or pd.DataFrame
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
required_return: float / series
    minimum acceptable return
period : str, optional
    Defines the periodicity of the 'returns' data for purposes of
    annualizing. Can be 'monthly', 'weekly', or 'daily'.
    - Defaults to 'daily'.

Returns
-------
depends on input type
series ==> float
DataFrame ==> np.array

    Annualized Sortino ratio.


@deprecated(msg=DEPRECATION_WARNING)<EOL>def downside_risk(returns, required_return=<NUM_LIT:0>, period=DAILY):

return ep.downside_risk(returns,<EOL>required_return=required_return,<EOL>period=period)<EOL>

Determines the downside deviation below a threshold

Parameters
----------
returns : pd.Series or pd.DataFrame
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
required_return: float / series
    minimum acceptable return
period : str, optional
    Defines the periodicity of the 'returns' data for purposes of
    annualizing. Can be 'monthly', 'weekly', or 'daily'.
    - Defaults to 'daily'.

Returns
-------
depends on input type
series ==> float
DataFrame ==> np.array

    Annualized downside deviation


@deprecated(msg=DEPRECATION_WARNING)<EOL>def sharpe_ratio(returns, risk_free=<NUM_LIT:0>, period=DAILY):

return ep.sharpe_ratio(returns, risk_free=risk_free, period=period)<EOL>

Determines the Sharpe ratio of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
risk_free : int, float
    Constant risk-free return throughout the period.
period : str, optional
    Defines the periodicity of the 'returns' data for purposes of
    annualizing. Can be 'monthly', 'weekly', or 'daily'.
    - Defaults to 'daily'.

Returns
-------
float
    Sharpe ratio.
np.nan
    If insufficient length of returns or if if adjusted returns are 0.

Note
-----
See https://en.wikipedia.org/wiki/Sharpe_ratio for more details.


return ep.alpha_beta(returns, factor_returns=factor_returns)<EOL>

Calculates both alpha and beta.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
factor_returns : pd.Series
    Daily noncumulative returns of the benchmark factor to which betas are
    computed. Usually a benchmark such as market returns.
     - This is in the same style as returns.

Returns
-------
float
    Alpha.
float
    Beta.


return ep.alpha(returns, factor_returns=factor_returns)<EOL>

Calculates annualized alpha.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
factor_returns : pd.Series
    Daily noncumulative returns of the benchmark factor to which betas are
    computed. Usually a benchmark such as market returns.
     - This is in the same style as returns.

Returns
-------
float
    Alpha.


return ep.beta(returns, factor_returns)<EOL>

Calculates beta.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
factor_returns : pd.Series
    Daily noncumulative returns of the benchmark factor to which betas are
    computed. Usually a benchmark such as market returns.
     - This is in the same style as returns.

Returns
-------
float
    Beta.


return ep.stability_of_timeseries(returns)<EOL>

Determines R-squared of a linear fit to the cumulative
log returns. Computes an ordinary least squares linear fit,
and returns R-squared.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.

Returns
-------
float
    R-squared.


return ep.tail_ratio(returns)<EOL>

Determines the ratio between the right (95%) and left tail (5%).

For example, a ratio of 0.25 means that losses are four times
as bad as profits.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.

Returns
-------
float
    tail ratio


return ep.tail_ratio(returns) *(<NUM_LIT:1> + ep.annual_return(returns))<EOL>

Common sense ratio is the multiplication of the tail ratio and the
Gain-to-Pain-Ratio -- sum(profits) / sum(losses).

See http://bit.ly/1ORzGBk for more information on motivation of
this metric.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.

Returns
-------
float
    common sense ratio


return starting_value * (returns / returns.iloc[<NUM_LIT:0>])<EOL>

Normalizes a returns timeseries based on the first value.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
starting_value : float, optional
   The starting returns (default 1).

Returns
-------
pd.Series
    Normalized returns.


return ep.cum_returns(returns, starting_value=starting_value)<EOL>

Compute cumulative returns from simple returns.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
starting_value : float, optional
   The starting returns (default 1).

Returns
-------
pandas.Series
    Series of cumulative returns.

Notes
-----
For increased numerical accuracy, convert input to log returns
where it is possible to sum instead of multiplying.


return ep.aggregate_returns(returns, convert_to=convert_to)<EOL>

Aggregates returns by week, month, or year.

Parameters
----------
returns : pd.Series
   Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.
convert_to : str
    Can be 'weekly', 'monthly', or 'yearly'.

Returns
-------
pd.Series
    Aggregated returns.


def rolling_beta(returns, factor_returns,<EOL>rolling_window=APPROX_BDAYS_PER_MONTH * <NUM_LIT:6>):

if factor_returns.ndim > <NUM_LIT:1>:<EOL><INDENT>return factor_returns.apply(partial(rolling_beta, returns),<EOL>rolling_window=rolling_window)<EOL><DEDENT>else:<EOL><INDENT>out = pd.Series(index=returns.index)<EOL>for beg, end in zip(returns.index[<NUM_LIT:0>:-rolling_window],<EOL>returns.index[rolling_window:]):<EOL><INDENT>out.loc[end] = ep.beta(<EOL>returns.loc[beg:end],<EOL>factor_returns.loc[beg:end])<EOL><DEDENT>return out<EOL><DEDENT>

Determines the rolling beta of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
factor_returns : pd.Series or pd.DataFrame
    Daily noncumulative returns of the benchmark factor to which betas are
    computed. Usually a benchmark such as market returns.
     - If DataFrame is passed, computes rolling beta for each column.
     - This is in the same style as returns.
rolling_window : int, optional
    The size of the rolling window, in days, over which to compute
    beta (default 6 months).

Returns
-------
pd.Series
    Rolling beta.

Note
-----
See https://en.wikipedia.org/wiki/Beta_(finance) for more details.


def rolling_regression(returns, factor_returns,<EOL>rolling_window=APPROX_BDAYS_PER_MONTH * <NUM_LIT:6>,<EOL>nan_threshold=<NUM_LIT:0.1>):

<EOL>ret_no_na = returns.dropna()<EOL>columns = ['<STR_LIT>'] + factor_returns.columns.tolist()<EOL>rolling_risk = pd.DataFrame(columns=columns,<EOL>index=ret_no_na.index)<EOL>rolling_risk.index.name = '<STR_LIT>'<EOL>for beg, end in zip(ret_no_na.index[:-rolling_window],<EOL>ret_no_na.index[rolling_window:]):<EOL><INDENT>returns_period = ret_no_na[beg:end]<EOL>factor_returns_period = factor_returns.loc[returns_period.index]<EOL>if np.all(factor_returns_period.isnull().mean()) < nan_threshold:<EOL><INDENT>factor_returns_period_dnan = factor_returns_period.dropna()<EOL>reg = linear_model.LinearRegression(fit_intercept=True).fit(<EOL>factor_returns_period_dnan,<EOL>returns_period.loc[factor_returns_period_dnan.index])<EOL>rolling_risk.loc[end, factor_returns.columns] = reg.coef_<EOL>rolling_risk.loc[end, '<STR_LIT>'] = reg.intercept_<EOL><DEDENT><DEDENT>return rolling_risk<EOL>

Computes rolling factor betas using a multivariate linear regression
(separate linear regressions is problematic because the factors may be
confounded).

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
factor_returns : pd.DataFrame
    Daily noncumulative returns of the benchmark factor to which betas are
    computed. Usually a benchmark such as market returns.
     - Computes rolling beta for each column.
     - This is in the same style as returns.
rolling_window : int, optional
    The days window over which to compute the beta. Defaults to 6 months.
nan_threshold : float, optional
    If there are more than this fraction of NaNs, the rolling regression
    for the given date will be skipped.

Returns
-------
pandas.DataFrame
    DataFrame containing rolling beta coefficients to SMB, HML and UMD


exposure = positions.drop('<STR_LIT>', axis=<NUM_LIT:1>).abs().sum(axis=<NUM_LIT:1>)<EOL>return exposure / positions.sum(axis=<NUM_LIT:1>)<EOL>

Calculates the gross leverage of a strategy.

Parameters
----------
positions : pd.DataFrame
    Daily net position values.
     - See full explanation in tears.create_full_tear_sheet.

Returns
-------
pd.Series
    Gross leverage.


def value_at_risk(returns, period=None, sigma=<NUM_LIT>):

if period is not None:<EOL><INDENT>returns_agg = ep.aggregate_returns(returns, period)<EOL><DEDENT>else:<EOL><INDENT>returns_agg = returns.copy()<EOL><DEDENT>value_at_risk = returns_agg.mean() - sigma * returns_agg.std()<EOL>return value_at_risk<EOL>

Get value at risk (VaR).

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
period : str, optional
    Period over which to calculate VaR. Set to 'weekly',
    'monthly', or 'yearly', otherwise defaults to period of
    returns (typically daily).
sigma : float, optional
    Standard deviations of VaR, default 2.


def perf_stats(returns, factor_returns=None, positions=None,<EOL>transactions=None, turnover_denom='<STR_LIT>'):

stats = pd.Series()<EOL>for stat_func in SIMPLE_STAT_FUNCS:<EOL><INDENT>stats[STAT_FUNC_NAMES[stat_func.__name__]] = stat_func(returns)<EOL><DEDENT>if positions is not None:<EOL><INDENT>stats['<STR_LIT>'] = gross_lev(positions).mean()<EOL>if transactions is not None:<EOL><INDENT>stats['<STR_LIT>'] = get_turnover(positions,<EOL>transactions,<EOL>turnover_denom).mean()<EOL><DEDENT><DEDENT>if factor_returns is not None:<EOL><INDENT>for stat_func in FACTOR_STAT_FUNCS:<EOL><INDENT>res = stat_func(returns, factor_returns)<EOL>stats[STAT_FUNC_NAMES[stat_func.__name__]] = res<EOL><DEDENT><DEDENT>return stats<EOL>

Calculates various performance metrics of a strategy, for use in
plotting.show_perf_stats.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
factor_returns : pd.Series, optional
    Daily noncumulative returns of the benchmark factor to which betas are
    computed. Usually a benchmark such as market returns.
     - This is in the same style as returns.
     - If None, do not compute alpha, beta, and information ratio.
positions : pd.DataFrame
    Daily net position values.
     - See full explanation in tears.create_full_tear_sheet.
transactions : pd.DataFrame
    Prices and amounts of executed trades. One row per trade.
    - See full explanation in tears.create_full_tear_sheet.
turnover_denom : str
    Either AGB or portfolio_value, default AGB.
    - See full explanation in txn.get_turnover.

Returns
-------
pd.Series
    Performance metrics.


def perf_stats_bootstrap(returns, factor_returns=None, return_stats=True,<EOL>**kwargs):

bootstrap_values = OrderedDict()<EOL>for stat_func in SIMPLE_STAT_FUNCS:<EOL><INDENT>stat_name = STAT_FUNC_NAMES[stat_func.__name__]<EOL>bootstrap_values[stat_name] = calc_bootstrap(stat_func,<EOL>returns)<EOL><DEDENT>if factor_returns is not None:<EOL><INDENT>for stat_func in FACTOR_STAT_FUNCS:<EOL><INDENT>stat_name = STAT_FUNC_NAMES[stat_func.__name__]<EOL>bootstrap_values[stat_name] = calc_bootstrap(<EOL>stat_func,<EOL>returns,<EOL>factor_returns=factor_returns)<EOL><DEDENT><DEDENT>bootstrap_values = pd.DataFrame(bootstrap_values)<EOL>if return_stats:<EOL><INDENT>stats = bootstrap_values.apply(calc_distribution_stats)<EOL>return stats.T[['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>']]<EOL><DEDENT>else:<EOL><INDENT>return bootstrap_values<EOL><DEDENT>

Calculates various bootstrapped performance metrics of a strategy.

    Parameters
    ----------
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    factor_returns : pd.Series, optional
        Daily noncumulative returns of the benchmark factor to which betas are
        computed. Usually a benchmark such as market returns.
         - This is in the same style as returns.
         - If None, do not compute alpha, beta, and information ratio.
    return_stats : boolean (optional)
        If True, returns a DataFrame of mean, median, 5 and 95 percentiles
        for each perf metric.
        If False, returns a DataFrame with the bootstrap samples for
        each perf metric.

    Returns
    -------
    pd.DataFrame
        if return_stats is True:
        - Distributional statistics of bootstrapped sampling
        distribution of performance metrics.
        if return_stats is False:
        - Bootstrap samples for each performance metric.


def calc_bootstrap(func, returns, *args, **kwargs):

n_samples = kwargs.pop('<STR_LIT>', <NUM_LIT:1000>)<EOL>out = np.empty(n_samples)<EOL>factor_returns = kwargs.pop('<STR_LIT>', None)<EOL>for i in range(n_samples):<EOL><INDENT>idx = np.random.randint(len(returns), size=len(returns))<EOL>returns_i = returns.iloc[idx].reset_index(drop=True)<EOL>if factor_returns is not None:<EOL><INDENT>factor_returns_i = factor_returns.iloc[idx].reset_index(drop=True)<EOL>out[i] = func(returns_i, factor_returns_i,<EOL>*args, **kwargs)<EOL><DEDENT>else:<EOL><INDENT>out[i] = func(returns_i,<EOL>*args, **kwargs)<EOL><DEDENT><DEDENT>return out<EOL>

Performs a bootstrap analysis on a user-defined function returning
    a summary statistic.

    Parameters
    ----------
    func : function
        Function that either takes a single array (commonly returns)
        or two arrays (commonly returns and factor returns) and
        returns a single value (commonly a summary
        statistic). Additional args and kwargs are passed as well.
    returns : pd.Series
        Daily returns of the strategy, noncumulative.
         - See full explanation in tears.create_full_tear_sheet.
    factor_returns : pd.Series, optional
        Daily noncumulative returns of the benchmark factor to which betas are
        computed. Usually a benchmark such as market returns.
         - This is in the same style as returns.
    n_samples : int, optional
        Number of bootstrap samples to draw. Default is 1000.
        Increasing this will lead to more stable / accurate estimates.

    Returns
    -------
    numpy.ndarray
        Bootstrapped sampling distribution of passed in func.


return pd.Series({'<STR_LIT>': np.mean(x),<EOL>'<STR_LIT>': np.median(x),<EOL>'<STR_LIT>': np.std(x),<EOL>'<STR_LIT>': np.percentile(x, <NUM_LIT:5>),<EOL>'<STR_LIT>': np.percentile(x, <NUM_LIT>),<EOL>'<STR_LIT>': np.percentile(x, <NUM_LIT>),<EOL>'<STR_LIT>': np.percentile(x, <NUM_LIT>),<EOL>'<STR_LIT>': np.subtract.reduce(<EOL>np.percentile(x, [<NUM_LIT>, <NUM_LIT>])),<EOL>})<EOL>

Calculate various summary statistics of data.

    Parameters
    ----------
    x : numpy.ndarray or pandas.Series
        Array to compute summary statistics for.

    Returns
    -------
    pandas.Series
        Series containing mean, median, std, as well as 5, 25, 75 and
        95 percentiles of passed in values.


valley = np.argmin(underwater)  <EOL>peak = underwater[:valley][underwater[:valley] == <NUM_LIT:0>].index[-<NUM_LIT:1>]<EOL>try:<EOL><INDENT>recovery = underwater[valley:][underwater[valley:] == <NUM_LIT:0>].index[<NUM_LIT:0>]<EOL><DEDENT>except IndexError:<EOL><INDENT>recovery = np.nan  <EOL><DEDENT>return peak, valley, recovery<EOL>

Determines peak, valley, and recovery dates given an 'underwater'
DataFrame.

An underwater DataFrame is a DataFrame that has precomputed
rolling drawdown.

Parameters
----------
underwater : pd.Series
   Underwater returns (rolling drawdown) of a strategy.

Returns
-------
peak : datetime
    The maximum drawdown's peak.
valley : datetime
    The maximum drawdown's valley.
recovery : datetime
    The maximum drawdown's recovery.


returns = returns.copy()<EOL>df_cum = cum_returns(returns, <NUM_LIT:1.0>)<EOL>running_max = np.maximum.accumulate(df_cum)<EOL>underwater = df_cum / running_max - <NUM_LIT:1><EOL>return get_max_drawdown_underwater(underwater)<EOL>

Determines the maximum drawdown of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
    - See full explanation in :func:`~pyfolio.timeseries.cum_returns`.

Returns
-------
float
    Maximum drawdown.

Note
-----
See https://en.wikipedia.org/wiki/Drawdown_(economics) for more details.


returns = returns.copy()<EOL>df_cum = ep.cum_returns(returns, <NUM_LIT:1.0>)<EOL>running_max = np.maximum.accumulate(df_cum)<EOL>underwater = df_cum / running_max - <NUM_LIT:1><EOL>drawdowns = []<EOL>for t in range(top):<EOL><INDENT>peak, valley, recovery = get_max_drawdown_underwater(underwater)<EOL>if not pd.isnull(recovery):<EOL><INDENT>underwater.drop(underwater[peak: recovery].index[<NUM_LIT:1>:-<NUM_LIT:1>],<EOL>inplace=True)<EOL><DEDENT>else:<EOL><INDENT>underwater = underwater.loc[:peak]<EOL><DEDENT>drawdowns.append((peak, valley, recovery))<EOL>if (len(returns) == <NUM_LIT:0>) or (len(underwater) == <NUM_LIT:0>):<EOL><INDENT>break<EOL><DEDENT><DEDENT>return drawdowns<EOL>

Finds top drawdowns, sorted by drawdown amount.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
top : int, optional
    The amount of top drawdowns to find (default 10).

Returns
-------
drawdowns : list
    List of drawdown peaks, valleys, and recoveries. See get_max_drawdown.


df_cum = ep.cum_returns(returns, <NUM_LIT:1.0>)<EOL>drawdown_periods = get_top_drawdowns(returns, top=top)<EOL>df_drawdowns = pd.DataFrame(index=list(range(top)),<EOL>columns=['<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>',<EOL>'<STR_LIT>'])<EOL>for i, (peak, valley, recovery) in enumerate(drawdown_periods):<EOL><INDENT>if pd.isnull(recovery):<EOL><INDENT>df_drawdowns.loc[i, '<STR_LIT>'] = np.nan<EOL><DEDENT>else:<EOL><INDENT>df_drawdowns.loc[i, '<STR_LIT>'] = len(pd.date_range(peak,<EOL>recovery,<EOL>freq='<STR_LIT:B>'))<EOL><DEDENT>df_drawdowns.loc[i, '<STR_LIT>'] = (peak.to_pydatetime()<EOL>.strftime('<STR_LIT>'))<EOL>df_drawdowns.loc[i, '<STR_LIT>'] = (valley.to_pydatetime()<EOL>.strftime('<STR_LIT>'))<EOL>if isinstance(recovery, float):<EOL><INDENT>df_drawdowns.loc[i, '<STR_LIT>'] = recovery<EOL><DEDENT>else:<EOL><INDENT>df_drawdowns.loc[i, '<STR_LIT>'] = (recovery.to_pydatetime()<EOL>.strftime('<STR_LIT>'))<EOL><DEDENT>df_drawdowns.loc[i, '<STR_LIT>'] = (<EOL>(df_cum.loc[peak] - df_cum.loc[valley]) / df_cum.loc[peak]) * <NUM_LIT:100><EOL><DEDENT>df_drawdowns['<STR_LIT>'] = pd.to_datetime(df_drawdowns['<STR_LIT>'])<EOL>df_drawdowns['<STR_LIT>'] = pd.to_datetime(df_drawdowns['<STR_LIT>'])<EOL>df_drawdowns['<STR_LIT>'] = pd.to_datetime(<EOL>df_drawdowns['<STR_LIT>'])<EOL>return df_drawdowns<EOL>

Places top drawdowns in a table.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
top : int, optional
    The amount of top drawdowns to find (default 10).

Returns
-------
df_drawdowns : pd.DataFrame
    Information about top drawdowns.


return returns.rolling(rolling_vol_window).std()* np.sqrt(APPROX_BDAYS_PER_YEAR)<EOL>

Determines the rolling volatility of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
rolling_vol_window : int
    Length of rolling window, in days, over which to compute.

Returns
-------
pd.Series
    Rolling volatility.


return returns.rolling(rolling_sharpe_window).mean()/ returns.rolling(rolling_sharpe_window).std()* np.sqrt(APPROX_BDAYS_PER_YEAR)<EOL>

Determines the rolling Sharpe ratio of a strategy.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
rolling_sharpe_window : int
    Length of rolling window, in days, over which to compute.

Returns
-------
pd.Series
    Rolling Sharpe ratio.

Note
-----
See https://en.wikipedia.org/wiki/Sharpe_ratio for more details.


def simulate_paths(is_returns, num_days,<EOL>starting_value=<NUM_LIT:1>, num_samples=<NUM_LIT:1000>, random_seed=None):

samples = np.empty((num_samples, num_days))<EOL>seed = np.random.RandomState(seed=random_seed)<EOL>for i in range(num_samples):<EOL><INDENT>samples[i, :] = is_returns.sample(num_days, replace=True,<EOL>random_state=seed)<EOL><DEDENT>return samples<EOL>

Gnerate alternate paths using available values from in-sample returns.

Parameters
----------
is_returns : pandas.core.frame.DataFrame
    Non-cumulative in-sample returns.
num_days : int
    Number of days to project the probability cone forward.
starting_value : int or float
    Starting value of the out of sample period.
num_samples : int
    Number of samples to draw from the in-sample daily returns.
    Each sample will be an array with length num_days.
    A higher number of samples will generate a more accurate
    bootstrap cone.
random_seed : int
    Seed for the pseudorandom number generator used by the pandas
    sample method.

Returns
-------
samples : numpy.ndarray


def summarize_paths(samples, cone_std=(<NUM_LIT:1.>, <NUM_LIT>, <NUM_LIT>), starting_value=<NUM_LIT:1.>):

cum_samples = ep.cum_returns(samples.T,<EOL>starting_value=starting_value).T<EOL>cum_mean = cum_samples.mean(axis=<NUM_LIT:0>)<EOL>cum_std = cum_samples.std(axis=<NUM_LIT:0>)<EOL>if isinstance(cone_std, (float, int)):<EOL><INDENT>cone_std = [cone_std]<EOL><DEDENT>cone_bounds = pd.DataFrame(columns=pd.Float64Index([]))<EOL>for num_std in cone_std:<EOL><INDENT>cone_bounds.loc[:, float(num_std)] = cum_mean + cum_std * num_std<EOL>cone_bounds.loc[:, float(-num_std)] = cum_mean - cum_std * num_std<EOL><DEDENT>return cone_bounds<EOL>

Gnerate the upper and lower bounds of an n standard deviation
cone of forecasted cumulative returns.

Parameters
----------
samples : numpy.ndarray
    Alternative paths, or series of possible outcomes.
cone_std : list of int/float
    Number of standard devations to use in the boundaries of
    the cone. If multiple values are passed, cone bounds will
    be generated for each value.

Returns
-------
samples : pandas.core.frame.DataFrame


def forecast_cone_bootstrap(is_returns, num_days, cone_std=(<NUM_LIT:1.>, <NUM_LIT>, <NUM_LIT>),<EOL>starting_value=<NUM_LIT:1>, num_samples=<NUM_LIT:1000>,<EOL>random_seed=None):

Determines the upper and lower bounds of an n standard deviation
cone of forecasted cumulative returns. Future cumulative mean and
standard devation are computed by repeatedly sampling from the
in-sample daily returns (i.e. bootstrap). This cone is non-parametric,
meaning it does not assume that returns are normally distributed.

Parameters
----------
is_returns : pd.Series
    In-sample daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.
num_days : int
    Number of days to project the probability cone forward.
cone_std : int, float, or list of int/float
    Number of standard devations to use in the boundaries of
    the cone. If multiple values are passed, cone bounds will
    be generated for each value.
starting_value : int or float
    Starting value of the out of sample period.
num_samples : int
    Number of samples to draw from the in-sample daily returns.
    Each sample will be an array with length num_days.
    A higher number of samples will generate a more accurate
    bootstrap cone.
random_seed : int
    Seed for the pseudorandom number generator used by the pandas
    sample method.

Returns
-------
pd.DataFrame
    Contains upper and lower cone boundaries. Column names are
    strings corresponding to the number of standard devations
    above (positive) or below (negative) the projected mean
    cumulative returns.


returns_dupe = returns.copy()<EOL>returns_dupe.index = returns_dupe.index.map(pd.Timestamp)<EOL>ranges = OrderedDict()<EOL>for name, (start, end) in PERIODS.items():<EOL><INDENT>try:<EOL><INDENT>period = returns_dupe.loc[start:end]<EOL>if len(period) == <NUM_LIT:0>:<EOL><INDENT>continue<EOL><DEDENT>ranges[name] = period<EOL><DEDENT>except BaseException:<EOL><INDENT>continue<EOL><DEDENT><DEDENT>return ranges<EOL>

Extracts returns based on interesting events. See
gen_date_range_interesting.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in tears.create_full_tear_sheet.

Returns
-------
ranges : OrderedDict
    Date ranges, with returns, of all valid events.


def deprecated_dec(fn):<EOL><INDENT>@wraps(fn)<EOL>def wrapper(*args, **kwargs):<EOL><INDENT>warnings.warn(<EOL>msg or "<STR_LIT>" % fn.__name__,<EOL>category=DeprecationWarning,<EOL>stacklevel=stacklevel<EOL>)<EOL>return fn(*args, **kwargs)<EOL><DEDENT>return wrapper<EOL><DEDENT>return deprecated_dec<EOL>

Used to mark a function as deprecated.
Parameters
----------
msg : str
    The message to display in the deprecation warning.
stacklevel : int
    How far up the stack the warning needs to go, before
    showing the relevant calling lines.
Usage
-----
@deprecated(msg='function_a is deprecated! Use function_b instead.')
def function_a(*args, **kwargs):


if isinstance(txn['<STR_LIT>'], dict):<EOL><INDENT>sid = txn['<STR_LIT>']['<STR_LIT>']<EOL>symbol = txn['<STR_LIT>']['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>sid = txn['<STR_LIT>']<EOL>symbol = txn['<STR_LIT>']<EOL><DEDENT>return {'<STR_LIT>': sid,<EOL>'<STR_LIT>': symbol,<EOL>'<STR_LIT>': txn['<STR_LIT>'],<EOL>'<STR_LIT>': txn['<STR_LIT>'],<EOL>'<STR_LIT>': txn['<STR_LIT>'],<EOL>'<STR_LIT>': txn['<STR_LIT>'],<EOL>'<STR_LIT>': txn['<STR_LIT>']}<EOL>

Maps a single transaction row to a dictionary.

Parameters
----------
txn : pd.DataFrame
    A single transaction object to convert to a dictionary.

Returns
-------
dict
    Mapped transaction.


transaction_list = []<EOL>for dt in transactions.index:<EOL><INDENT>txns = transactions.loc[dt]<EOL>if len(txns) == <NUM_LIT:0>:<EOL><INDENT>continue<EOL><DEDENT>for txn in txns:<EOL><INDENT>txn = map_transaction(txn)<EOL>transaction_list.append(txn)<EOL><DEDENT><DEDENT>df = pd.DataFrame(sorted(transaction_list, key=lambda x: x['<STR_LIT>']))<EOL>df['<STR_LIT>'] = -df['<STR_LIT>'] * df['<STR_LIT>']<EOL>df.index = list(map(pd.Timestamp, df.dt.values))<EOL>return df<EOL>

Formats a transaction DataFrame.

Parameters
----------
transactions : pd.DataFrame
    Contains improperly formatted transactional data.

Returns
-------
df : pd.DataFrame
    Daily transaction volume and dollar ammount.
     - See full explanation in tears.create_full_tear_sheet.


txn_norm = transactions.copy()<EOL>txn_norm.index = txn_norm.index.normalize()<EOL>amounts = txn_norm.amount.abs()<EOL>prices = txn_norm.price<EOL>values = amounts * prices<EOL>daily_amounts = amounts.groupby(amounts.index).sum()<EOL>daily_values = values.groupby(values.index).sum()<EOL>daily_amounts.name = "<STR_LIT>"<EOL>daily_values.name = "<STR_LIT>"<EOL>return pd.concat([daily_values, daily_amounts], axis=<NUM_LIT:1>)<EOL>

Extract daily transaction data from set of transaction objects.

Parameters
----------
transactions : pd.DataFrame
    Time series containing one row per symbol (and potentially
    duplicate datetime indices) and columns for amount and
    price.

Returns
-------
pd.DataFrame
    Daily transaction volume and number of shares.
     - See full explanation in tears.create_full_tear_sheet.


def adjust_returns_for_slippage(returns, positions, transactions,<EOL>slippage_bps):

slippage = <NUM_LIT> * slippage_bps<EOL>portfolio_value = positions.sum(axis=<NUM_LIT:1>)<EOL>pnl = portfolio_value * returns<EOL>traded_value = get_txn_vol(transactions).txn_volume<EOL>slippage_dollars = traded_value * slippage<EOL>adjusted_pnl = pnl.add(-slippage_dollars, fill_value=<NUM_LIT:0>)<EOL>adjusted_returns = returns * adjusted_pnl / pnl<EOL>return adjusted_returns<EOL>

Apply a slippage penalty for every dollar traded.

Parameters
----------
returns : pd.Series
    Daily returns of the strategy, noncumulative.
     - See full explanation in create_full_tear_sheet.
positions : pd.DataFrame
    Daily net position values.
     - See full explanation in create_full_tear_sheet.
transactions : pd.DataFrame
    Prices and amounts of executed trades. One row per trade.
     - See full explanation in create_full_tear_sheet.
slippage_bps: int/float
    Basis points of slippage to apply.

Returns
-------
pd.Series
    Time series of daily returns, adjusted for slippage.


def get_turnover(positions, transactions, denominator='<STR_LIT>'):

txn_vol = get_txn_vol(transactions)<EOL>traded_value = txn_vol.txn_volume<EOL>if denominator == '<STR_LIT>':<EOL><INDENT>AGB = positions.drop('<STR_LIT>', axis=<NUM_LIT:1>).abs().sum(axis=<NUM_LIT:1>)<EOL>denom = AGB.rolling(<NUM_LIT:2>).mean()<EOL>denom.iloc[<NUM_LIT:0>] = AGB.iloc[<NUM_LIT:0>] / <NUM_LIT:2><EOL><DEDENT>elif denominator == '<STR_LIT>':<EOL><INDENT>denom = positions.sum(axis=<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>".format(denominator)<EOL>)<EOL><DEDENT>denom.index = denom.index.normalize()<EOL>turnover = traded_value.div(denom, axis='<STR_LIT:index>')<EOL>turnover = turnover.fillna(<NUM_LIT:0>)<EOL>return turnover<EOL>

- Value of purchases and sales divided
by either the actual gross book or the portfolio value
for the time step.

Parameters
----------
positions : pd.DataFrame
    Contains daily position values including cash.
    - See full explanation in tears.create_full_tear_sheet
transactions : pd.DataFrame
    Prices and amounts of executed trades. One row per trade.
    - See full explanation in tears.create_full_tear_sheet
denominator : str, optional
    Either 'AGB' or 'portfolio_value', default AGB.
    - AGB (Actual gross book) is the gross market
    value (GMV) of the specific algo being analyzed.
    Swapping out an entire portfolio of stocks for
    another will yield 200% turnover, not 100%, since
    transactions are being made for both sides.
    - We use average of the previous and the current end-of-period
    AGB to avoid singularities when trading only into or
    out of an entire book in one trading period.
    - portfolio_value is the total value of the algo's
    positions end-of-period, including cash.

Returns
-------
turnover_rate : pd.Series
    timeseries of portfolio turnover rates.


with self.mutex:<EOL><INDENT>if not len(self.queue): <EOL><INDENT>raise Empty<EOL><DEDENT>utcnow = dt.datetime.utcnow()<EOL>if self.queue[<NUM_LIT:0>][<NUM_LIT:0>] <= utcnow:<EOL><INDENT>self.ready.notify()<EOL>return <NUM_LIT:0><EOL><DEDENT>return (self.queue[<NUM_LIT:0>][<NUM_LIT:0>] - utcnow).total_seconds()<EOL><DEDENT>

Return the wait time in seconds required to retrieve the
item currently at the head of the queue.

Note that there is no guarantee that a call to `get()` will
succeed even if `ask()` returns 0. By the time the calling
thread reacts, other threads may have caused a different
item to be at the head of the queue.


with self.mutex:<EOL><INDENT>return len(self.queue)<EOL><DEDENT>

Return the approximate size of the queue.

The answer will not be reliable, as producers and consumers
can change the queue size before the result can be used.


<EOL>if user_details:<EOL><INDENT>user_details['<STR_LIT>'] = True<EOL><DEDENT>response = make_get_request(session, '<STR_LIT>', params_data=user_details)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise SelfNotRetrievedException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>

Get details about the currently authenticated user


def get_user_by_id(session, user_id, user_details=None):

if user_details:<EOL><INDENT>user_details['<STR_LIT>'] = True<EOL><DEDENT>response = make_get_request(<EOL>session, '<STR_LIT>'.format(user_id), params_data=user_details)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise UserNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>


response = make_get_request(session, '<STR_LIT>')<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return response.json()['<STR_LIT:result>']['<STR_LIT:id>']<EOL><DEDENT>else:<EOL><INDENT>raise UserIdNotRetrievedException(<EOL>'<STR_LIT>' % response.text, response.text)<EOL><DEDENT>


jobs_data = {<EOL>'<STR_LIT>': job_ids<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>', json_data=jobs_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>raise UserJobsNotAddedException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>

Add a list of jobs to the currently authenticated user


jobs_data = {<EOL>'<STR_LIT>': job_ids<EOL>}<EOL>response = make_put_request(session, '<STR_LIT>', json_data=jobs_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>raise UserJobsNotSetException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>

Replace the currently authenticated user's list of jobs with a new list of
jobs


jobs_data = {<EOL>'<STR_LIT>': job_ids<EOL>}<EOL>response = make_delete_request(session, '<STR_LIT>', json_data=jobs_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>raise UserJobsNotDeletedException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>

Remove a list of jobs from the currently authenticated user


<EOL>response = make_get_request(session, '<STR_LIT>', params_data=query)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise UsersNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def create_project(session, title, description,<EOL>currency, budget, jobs):

project_data = {'<STR_LIT:title>': title,<EOL>'<STR_LIT:description>': description,<EOL>'<STR_LIT>': currency,<EOL>'<STR_LIT>': budget,<EOL>'<STR_LIT>': jobs<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>', json_data=project_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>project_data = json_data['<STR_LIT:result>']<EOL>p = Project(project_data)<EOL>p.url = urljoin(session.url, '<STR_LIT>' % p.seo_url)<EOL>return p<EOL><DEDENT>else:<EOL><INDENT>raise ProjectNotCreatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'],<EOL>)<EOL><DEDENT>


def create_hourly_project(session, title, description,<EOL>currency, budget, jobs, hourly_project_info):

project_data = {'<STR_LIT:title>': title,<EOL>'<STR_LIT:description>': description,<EOL>'<STR_LIT>': currency,<EOL>'<STR_LIT>': budget,<EOL>'<STR_LIT>': jobs,<EOL>'<STR_LIT:type>': '<STR_LIT>',<EOL>'<STR_LIT>': hourly_project_info<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>', json_data=project_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>project_data = json_data['<STR_LIT:result>']<EOL>p = Project(project_data)<EOL>p.url = urljoin(session.url, '<STR_LIT>' % p.seo_url)<EOL>return p<EOL><DEDENT>else:<EOL><INDENT>raise ProjectNotCreatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'],<EOL>)<EOL><DEDENT>


def create_local_project(session, title, description,<EOL>currency, budget, jobs, location):

project_data = {'<STR_LIT:title>': title,<EOL>'<STR_LIT:description>': description,<EOL>'<STR_LIT>': currency,<EOL>'<STR_LIT>': budget,<EOL>'<STR_LIT>': jobs,<EOL>'<STR_LIT>': True,<EOL>'<STR_LIT:location>': location<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>', json_data=project_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>project_data = json_data['<STR_LIT:result>']<EOL>p = Project(project_data)<EOL>p.url = urljoin(session.url, '<STR_LIT>' % p.seo_url)<EOL>return p<EOL><DEDENT>else:<EOL><INDENT>raise ProjectNotCreatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'],<EOL>)<EOL><DEDENT>


def create_hireme_project(session, title, description,<EOL>currency, budget, jobs, hireme_initial_bid):

jobs.append(create_job_object(id=<NUM_LIT>))  <EOL>project_data = {'<STR_LIT:title>': title,<EOL>'<STR_LIT:description>': description,<EOL>'<STR_LIT>': currency,<EOL>'<STR_LIT>': budget,<EOL>'<STR_LIT>': jobs,<EOL>'<STR_LIT>': True,<EOL>'<STR_LIT>': hireme_initial_bid<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>', json_data=project_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>project_data = json_data['<STR_LIT:result>']<EOL>p = Project(project_data)<EOL>p.url = urljoin(session.url, '<STR_LIT>' % p.seo_url)<EOL>return p<EOL><DEDENT>else:<EOL><INDENT>raise ProjectNotCreatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'],<EOL>)<EOL><DEDENT>


<EOL>response = make_get_request(session, '<STR_LIT>', params_data=query)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise ProjectsNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def get_project_by_id(session, project_id, project_details=None, user_details=None):

<EOL>query = {}<EOL>if project_details:<EOL><INDENT>query.update(project_details)<EOL><DEDENT>if user_details:<EOL><INDENT>query.update(user_details)<EOL><DEDENT>response = make_get_request(<EOL>session, '<STR_LIT>'.format(project_id), params_data=query)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise ProjectsNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>


search_data = {<EOL>'<STR_LIT>': query,<EOL>'<STR_LIT>': limit,<EOL>'<STR_LIT>': offset,<EOL>}<EOL>if search_filter:<EOL><INDENT>search_data.update(search_filter)<EOL><DEDENT>if project_details:<EOL><INDENT>search_data.update(project_details)<EOL><DEDENT>if user_details:<EOL><INDENT>search_data.update(user_details)<EOL><DEDENT>endpoint = '<STR_LIT>'.format('<STR_LIT>' if active_only else '<STR_LIT:all>')<EOL>response = make_get_request(session, endpoint, params_data=search_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise ProjectsNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def place_project_bid(session, project_id, bidder_id, description, amount,<EOL>period, milestone_percentage):

bid_data = {<EOL>'<STR_LIT>': project_id,<EOL>'<STR_LIT>': bidder_id,<EOL>'<STR_LIT:description>': description,<EOL>'<STR_LIT>': amount,<EOL>'<STR_LIT>': period,<EOL>'<STR_LIT>': milestone_percentage,<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>', json_data=bid_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>bid_data = json_data['<STR_LIT:result>']<EOL>return Bid(bid_data)<EOL><DEDENT>else:<EOL><INDENT>raise BidNotPlacedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def get_bids(session, project_ids=[], bid_ids=[], limit=<NUM_LIT:10>, offset=<NUM_LIT:0>):

get_bids_data = {}<EOL>if bid_ids:<EOL><INDENT>get_bids_data['<STR_LIT>'] = bid_ids<EOL><DEDENT>if project_ids:<EOL><INDENT>get_bids_data['<STR_LIT>'] = project_ids<EOL><DEDENT>get_bids_data['<STR_LIT>'] = limit<EOL>get_bids_data['<STR_LIT>'] = offset<EOL>response = make_get_request(session, '<STR_LIT>', params_data=get_bids_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise BidsNotFoundException(<EOL>message=json_data['<STR_LIT:message>'], error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>


def get_milestones(session, project_ids=[], milestone_ids=[], user_details=None, limit=<NUM_LIT:10>, offset=<NUM_LIT:0>):

get_milestones_data = {}<EOL>if milestone_ids:<EOL><INDENT>get_milestones_data['<STR_LIT>'] = milestone_ids<EOL><DEDENT>if project_ids:<EOL><INDENT>get_milestones_data['<STR_LIT>'] = project_ids<EOL><DEDENT>get_milestones_data['<STR_LIT>'] = limit<EOL>get_milestones_data['<STR_LIT>'] = offset<EOL>if user_details:<EOL><INDENT>get_milestones_data.update(user_details)<EOL><DEDENT>response = make_get_request(<EOL>session, '<STR_LIT>', params_data=get_milestones_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise MilestonesNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>


def get_milestone_by_id(session, milestone_id, user_details=None):

<EOL>endpoint = '<STR_LIT>'.format(milestone_id)<EOL>response = make_get_request(session, endpoint, params_data=user_details)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise MilestonesNotFoundException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>


headers = {<EOL>'<STR_LIT:Content-Type>': '<STR_LIT>'<EOL>}<EOL>bid_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>'<EOL>}<EOL>endpoint = '<STR_LIT>'.format(bid_id)<EOL>response = make_put_request(session, endpoint, headers=headers,<EOL>params_data=bid_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>json_data = response.json()<EOL>raise BidNotAwardedException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>']<EOL>)<EOL><DEDENT>


headers = {<EOL>'<STR_LIT:Content-Type>': '<STR_LIT>'<EOL>}<EOL>bid_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>'<EOL>}<EOL>endpoint = '<STR_LIT>'.format(bid_id)<EOL>response = make_put_request(session, endpoint, headers=headers,<EOL>params_data=bid_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>json_data = response.json()<EOL>raise BidNotRevokedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


headers = {<EOL>'<STR_LIT:Content-Type>': '<STR_LIT>'<EOL>}<EOL>bid_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>'<EOL>}<EOL>endpoint = '<STR_LIT>'.format(bid_id)<EOL>response = make_put_request(session, endpoint, headers=headers,<EOL>params_data=bid_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>json_data = response.json()<EOL>raise BidNotAcceptedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


headers = {<EOL>'<STR_LIT:Content-Type>': '<STR_LIT>'<EOL>}<EOL>bid_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>'<EOL>}<EOL>endpoint = '<STR_LIT>'.format(bid_id)<EOL>response = make_put_request(session, endpoint, headers=headers,<EOL>params_data=bid_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>json_data = response.json()<EOL>raise BidNotRetractedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


headers = {<EOL>'<STR_LIT:Content-Type>': '<STR_LIT>'<EOL>}<EOL>bid_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>'<EOL>}<EOL>endpoint = '<STR_LIT>'.format(bid_id)<EOL>response = make_put_request(session, endpoint, headers=headers,<EOL>params_data=bid_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>json_data = response.json()<EOL>raise BidNotHighlightedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def create_milestone_payment(session, project_id, bidder_id, amount,<EOL>reason, description):

milestone_data = {<EOL>'<STR_LIT>': project_id,<EOL>'<STR_LIT>': bidder_id,<EOL>'<STR_LIT>': amount,<EOL>'<STR_LIT>': reason,<EOL>'<STR_LIT:description>': description<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>',<EOL>json_data=milestone_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>milestone_data = json_data['<STR_LIT:result>']<EOL>return Milestone(milestone_data)<EOL><DEDENT>else:<EOL><INDENT>raise MilestoneNotCreatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def post_track(session, user_id, project_id, latitude, longitude):

tracking_data = {<EOL>'<STR_LIT>': user_id,<EOL>'<STR_LIT>': project_id,<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': latitude,<EOL>'<STR_LIT>': longitude<EOL>}<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>',<EOL>json_data=tracking_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise TrackNotCreatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>

Start tracking a project by creating a track


def update_track(session, track_id, latitude, longitude, stop_tracking=False):

tracking_data = {<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': latitude,<EOL>'<STR_LIT>': longitude,<EOL>},<EOL>'<STR_LIT>': stop_tracking<EOL>}<EOL>response = make_put_request(session, '<STR_LIT>'.format(track_id),<EOL>json_data=tracking_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise TrackNotUpdatedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>

Updates the current location by creating a new track point and appending
it to the given track


def get_track_by_id(session, track_id, track_point_limit=None, track_point_offset=None):

tracking_data = {}<EOL>if track_point_limit:<EOL><INDENT>tracking_data['<STR_LIT>'] = track_point_limit<EOL><DEDENT>if track_point_offset:<EOL><INDENT>tracking_data['<STR_LIT>'] = track_point_offset<EOL><DEDENT>response = make_get_request(session, '<STR_LIT>'.format(track_id),<EOL>params_data=tracking_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:result>']<EOL><DEDENT>else:<EOL><INDENT>raise TrackNotFoundException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def release_milestone_payment(session, milestone_id, amount):

params_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>',<EOL>}<EOL>milestone_data = {<EOL>'<STR_LIT>': amount,<EOL>}<EOL>endpoint = '<STR_LIT>'.format(milestone_id)<EOL>response = make_put_request(session, endpoint, params_data=params_data,<EOL>json_data=milestone_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>raise MilestoneNotReleasedException(message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


params_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>',<EOL>}<EOL>endpoint = '<STR_LIT>'.format(milestone_id)<EOL>response = make_put_request(session, endpoint, params_data=params_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>raise MilestoneNotRequestedReleaseException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


params_data = {<EOL>'<STR_LIT:action>': '<STR_LIT>',<EOL>}<EOL>endpoint = '<STR_LIT>'.format(milestone_id)<EOL>response = make_put_request(session, endpoint, params_data=params_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>return json_data['<STR_LIT:status>']<EOL><DEDENT>else:<EOL><INDENT>raise MilestoneNotCancelledException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>


def create_milestone_request(session, project_id, bid_id, description, amount):

milestone_request_data = {<EOL>'<STR_LIT>': project_id,<EOL>'<STR_LIT>': bid_id,<EOL>'<STR_LIT:description>': description,<EOL>'<STR_LIT>': amount,<EOL>}<EOL>response = make_post_request(session, '<STR_LIT>',<EOL>json_data=milestone_request_data)<EOL>json_data = response.json()<EOL>if response.status_code == <NUM_LIT:200>:<EOL><INDENT>milestone_request_data = json_data['<STR_LIT:result>']<EOL>return MilestoneRequest(milestone_request_data)<EOL><DEDENT>else:<EOL><INDENT>raise MilestoneRequestNotCreatedException(<EOL>message=json_data['<STR_LIT:message>'],<EOL>error_code=json_data['<STR_LIT>'],<EOL>request_id=json_data['<STR_LIT>'])<EOL><DEDENT>