Source code for pymarket.statistics.profits

import pandas as pd
import numpy as np
from collections import OrderedDict


[docs]def calculate_profits( bids, transactions, reservation_prices=None, fees=None, **kwargs): """Extras from the transactions and the bids the profit of each player and the market maker Parameters ---------- bids : pd.DataFrame Collections of bids to be used transactions : pd.DataFrame Collection of transactions to be taken into account reservation_prices : dict, (Default value = None) Maping between users and their reservation prices. If None, it is assumed that each user bided truthfully and the information is extracted from the bid. fees : np.ndarray, (Default value = None) List of fees that each user has to pay to trade in the market. Returns ------- profit: dict A dictionary with three values: * player_bid: A list with the profits of each user using their bids as reservation prices * player_reservation: Same as above but using their reservation prices, if none are provided, it is the same as `player_bid` * market: profit of the market maker Examples --------- >>> tm = pm.TransactionManager() >>> bm = pm.BidManager() >>> bm.add_bid(1, 3, 0) 0 >>> bm.add_bid(1, 2, 1) 1 >>> bm.add_bid(1.5, 1, 2, False) 2 >>> tm.add_transaction(0, 1, 2, 2, False) 0 >>> tm.add_transaction(2, 1, 2, 0, False) 1 >>> rp = {2: 0} >>> profits = calculate_profits(bm.get_df(), tm.get_df(), ... reservation_prices=rp) >>> profits['player_bid'] array([1., 0., 1.]) >>> profits['player_reservation'] array([1., 0., 2.]) >>> profits['market'] 0.0 """ users = sorted(bids.user.unique()) buyers = bids.loc[bids['buying']].index.values sellers = bids.loc[~bids['buying']].index.values if reservation_prices is None: reservation_prices = OrderedDict() for i, x in bids.iterrows(): if i not in reservation_prices: reservation_prices[i] = x.price if fees is None: fees = np.zeros(bids.user.unique().shape[0]) profit = OrderedDict() for case in ['bid', 'reservation']: tmp = bids.reset_index().rename(columns={'index': 'bid'}).copy() tmp = tmp[['bid', 'price', 'buying', 'user']] if case == 'reservation': tmp.price = tmp.apply( lambda x: reservation_prices.get(x.bid, x.price), axis=1) merged = transactions.merge(tmp, on='bid').copy() merged['gain'] = merged.apply(lambda x: get_gain(x), axis=1) profit_player = merged.groupby('user')['gain'].sum() # print(profit_player) profit_player = np.array([profit_player.get(x, 0) for x in users]) profit['player_{}'.format(case)] = profit_player.astype('float64') if case == 'bid': # print(merged) mb = merged.loc[merged['buying']] ms = merged.loc[~merged['buying']] # print(ms) # print(ms.quantity.sum(), mb.quantity.sum()) # print(ms.price_x * ms.quantity) profit_market = (mb.price_x * mb.quantity).values.sum() profit_market -= (ms.price_x * ms.quantity).values.sum() profit_market += fees.sum() profit['market'] = profit_market.astype('float64') return profit
[docs]def get_gain(row): """Finds the gain of the row Parameters ---------- row : pandas row Row obtained by merging a transaction with a bid dataframe Returns ------- gain The gain obtained by the row """ gap = row.price_y - row.price_x if not row.buying: gap = - gap return gap * row.quantity