# RTB, SSPs is True 2nd Price Auction Program

I've created this program that is intended to check if SSPs in RTB auctions run true second price auction.

The program is running properly and returning the values as desired. I would like to get some feedback on these elements:

• Code structure (right usage of class, function, comments, variable names, class names, etc.)
• How can I make it run faster on a large set of data (i.e. 1 billion input). From my understanding, my code is of complexity $O(n)$, where runtime will grow with the number of lines in the file uploaded?

# Pyhton 3.6
"""
Created on Fri Nov  3 19:52:49 2017
@author: tcrepineau

Purpose: this program is intended to check if SSPs run true second price auctions.

Methodology: we will plot a graph of the ratio of the winning bid and the max bid in the x-axis
the percentage of impressions in the y-axis.

Assumptions: in a true second price auction, the probability of the winning bid to be equal to the max bid
is (1/[b - a]) where b represents the higher bound of possible bids (i.e if max bid = \$4, possible bids
are 400), and a the minimum possibility of bids (i.e 0.01).

Data: TBD
"""

import matplotlib.pyplot as plt
from collections import defaultdict
import numpy as np

IMPRESSIONS = 0
COST = 1
MAX_BID_UI = 2
RATIO = 3

"""Return a dictionary mapping every instance of exchange to (impressions, cost, max_bid_ui), where
exchange is a string impression is an integer, and cost and max_bid_ui are floats rounded to 2 decimals
in a tuple. Each line in the file represents a specific instance of an impression [ideally]
occurring in an exchange. Structure -> {exchange:(impressions, cost, max_bid_ui)}"""

exchange_data_info = defaultdict(list)
inputFile = open(filename)
exchange, impressions, cost, max_bid_ui = line.split(',')
exchange_data_info[exchange].append((int(impressions), float(cost),float(max_bid_ui)))

return exchange_data_info

class noExchange(Exception):
"""Raise no exchange if value enter as an exchange filter is not found in the dataset"""
def __init__(self,data_list_exchange):
self.data_list_exchange = data_list_exchange

def __str__(self):
error_message = 'You have entered an incorrect exchange name. Please be sure to pick one from the following list: '
exchange_list = []
for k,v in self.data_list_exchange.items():
exchange_list.append(k)

error_message = error_message + ', '.join(exchange_list)

return error_message

class pickExchange(object):
"""This class is used to filter SSPs and run test on 1 specific SSP at a time"""

##Initialize data
def __init__(self, data_list, exchange):
self.data_list = data_list
self.exchange = exchange

##Iterate through data list and add key corresponding to SSP chosen to new dict. {filtered_data_list}
##k = keys in dict. (i.e exchanges) & v = values in dict. (i.e a tuple of (impressions,cost,max_bid_uI))
def filterExchange(self):
for k, v in self.data_list.items():
if self.exchange not in self.data_list:
raise noExchange(self.data_list)
if self.exchange == None:
return self.data_list
if k.lower() == self.exchange.lower():
return {k: self.data_list[k]}

##Call def filterExchange(self) method to filter data based on SSP chosen
def getFilteredExchange(self):
return self.filterExchange()

class bidsRatio(object):
"""This class compute the ratio of win bid over the max bid entered"""

## Initialize data
def __init__(self, data_set):
self.data_set = data_set

##Compute the ratio of max bid over win bid and create a new dictionnary with initial value + ratio
## key = exchange & value = tuple containing impressions, max_bid_ui, cost, ratio_win_max
def computeRatio(self):
dict_with_ratio = {}
for k,v in self.data_set.items():
for i in range(len(v)):
ratio_win_max = round(v[i][COST]/v[i][MAX_BID_UI],2)
v[i] = v[i] + (ratio_win_max,)

dict_with_ratio[k] = v

return dict_with_ratio

##Call def computeRatio(self) and return the computed ratio
def getRatio(self):
return self.computeRatio()

def runAuctionTest(filename, exchange = None):
filtered_input_data = pickExchange(inputData, exchange).getFilteredExchange()
compute_ratio_list = bidsRatio(filtered_input_data).getRatio()

return plotGraph(compute_ratio_list, exchange)

def plotGraph(final_data_set, exchange):
ratios = []
bins = []
for k,v in final_data_set.items():
for i in range(len(v)):
#ratios.append(v[i][RATIO])
ratios += v[i][IMPRESSIONS] * [(v[i][RATIO])]

for i in np.arange(0.0,1.0,0.01):
bins.append(round(i,2))

plt.hist(ratios, bins,normed=True , histtype='bar', rwidth=0.9, label=exchange)
plt.xlabel('Ratios')
plt.ylabel('% Impressions')
plt.title('True 2nd Price Auction')
plt.legend()
plt.show()