Skip to content

removing deprecated pd.TimeGrouper and using the .xs multi level indexing versus [] #625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 27 additions & 25 deletions pyfolio/capacity.py
Original file line number Diff line number Diff line change
@@ -18,10 +18,9 @@ def daily_txns_with_bar_data(transactions, market_data):
transactions : pd.DataFrame
Prices and amounts of executed trades. One row per trade.
- See full explanation in tears.create_full_tear_sheet
market_data : pd.DataFrame
Daily market_data
- DataFrame has a multi-index index, one level is dates and another is
market_data contains volume & price, equities as columns
market_data : pd.Panel
Contains "volume" and "price" DataFrames for the tickers
in the passed positions DataFrames

Returns
-------
@@ -35,8 +34,9 @@ def daily_txns_with_bar_data(transactions, market_data):
txn_daily = pd.DataFrame(transactions.assign(
amount=abs(transactions.amount)).groupby(
['symbol', pd.Grouper(freq='D')]).sum()['amount'])
txn_daily['price'] = market_data.xs('price', level=1).unstack()
txn_daily['volume'] = market_data.xs('volume', level=1).unstack()
txn_daily['price'] = market_data.xs('price', level='market_data').unstack()
txn_daily['volume'] = market_data.xs('volume',
level='market_data').unstack()

txn_daily = txn_daily.reset_index().set_index('date')

@@ -64,10 +64,10 @@ def days_to_liquidate_positions(positions, market_data,
positions: pd.DataFrame
Contains daily position values including cash
- See full explanation in tears.create_full_tear_sheet
market_data : pd.DataFrame
Daily market_data
- DataFrame has a multi-index index, one level is dates and another is
market_data contains volume & price, equities as columns
market_data : pd.Panel
Panel with items axis of 'price' and 'volume' DataFrames.
The major and minor axes should match those of the
the passed positions DataFrame (same dates and symbols).
max_bar_consumption : float
Max proportion of a daily bar that can be consumed in the
process of liquidating a position.
@@ -84,16 +84,18 @@ def days_to_liquidate_positions(positions, market_data,
Datetime index, symbols as columns.
"""

DV = market_data.xs('volume', level=1) * market_data.xs('price', level=1)
roll_mean_dv = DV.rolling(window=mean_volume_window,
dv = market_data.xs('volume', level='market_data') * \
market_data.xs('price', level='market_data')

roll_mean_dv = dv.rolling(window=mean_volume_window,
center=False).mean().shift()
roll_mean_dv = roll_mean_dv.replace(0, np.nan)

positions_alloc = pos.get_percent_alloc(positions)
positions_alloc = positions_alloc.drop('cash', axis=1)

days_to_liquidate = (positions_alloc * capital_base) / \
(max_bar_consumption * roll_mean_dv)
(max_bar_consumption * roll_mean_dv)

return days_to_liquidate.iloc[mean_volume_window:]

@@ -112,10 +114,10 @@ def get_max_days_to_liquidate_by_ticker(positions, market_data,
positions: pd.DataFrame
Contains daily position values including cash
- See full explanation in tears.create_full_tear_sheet
market_data : pd.DataFrame
Daily market_data
- DataFrame has a multi-index index, one level is dates and another is
market_data contains volume & price, equities as columns
market_data : pd.Panel
Panel with items axis of 'price' and 'volume' DataFrames.
The major and minor axes should match those of the
the passed positions DataFrame (same dates and symbols).
max_bar_consumption : float
Max proportion of a daily bar that can be consumed in the
process of liquidating a position.
@@ -169,10 +171,10 @@ def get_low_liquidity_transactions(transactions, market_data,
transactions : pd.DataFrame
Prices and amounts of executed trades. One row per trade.
- See full explanation in create_full_tear_sheet.
market_data : pd.DataFrame
Daily market_data
- DataFrame has a multi-index index, one level is dates and another is
market_data contains volume & price, equities as columns
market_data : pd.Panel
Panel with items axis of 'price' and 'volume' DataFrames.
The major and minor axes should match those of the
the passed positions DataFrame (same dates and symbols).
last_n_days : integer
Compute for only the last n days of the passed backtest data.
"""
@@ -186,8 +188,8 @@ def get_low_liquidity_transactions(transactions, market_data,
txn_daily_w_bar = txn_daily_w_bar[txn_daily_w_bar.date > md]

bar_consumption = txn_daily_w_bar.assign(
max_pct_bar_consumed=(
txn_daily_w_bar.amount/txn_daily_w_bar.volume)*100
max_pct_bar_consumed=(txn_daily_w_bar.amount /
txn_daily_w_bar.volume) * 100
).sort_values('max_pct_bar_consumed', ascending=False)
max_bar_consumption = bar_consumption.groupby('symbol').first()

@@ -228,8 +230,8 @@ def apply_slippage_penalty(returns, txn_daily, simulate_starting_capital,
simulate_traded_dollars = txn_daily.price * simulate_traded_shares
simulate_pct_volume_used = simulate_traded_shares / txn_daily.volume

penalties = simulate_pct_volume_used**2 \
* impact * simulate_traded_dollars
penalties = (simulate_pct_volume_used ** 2 *
impact * simulate_traded_dollars)

daily_penalty = penalties.resample('D').sum()
daily_penalty = daily_penalty.reindex(returns.index).fillna(0)