"""Bidding module"""
import collections
import numpy as np
RunResults = collections.namedtuple('RunResults', ['total_clicks',
'total_impressions',
'total_ad_spend'])
[docs]class BidSimulator:
"""Simulates given bidding strategy on a dataset"""
[docs] def __init__(self, data, bidding_strategy):
"""Initialize bidding simulator.
Parameters
----------
data : pandas.DataFrame
Historical data containing features for model predicti n, bidding
price, winning price, impressions and click indicators.
bidding_strategy : func
Function that retuns bid given prospenity to click and data row
"""
self._data = data
self._bidding_strategy = bidding_strategy
[docs] def run(self, ctr_model=None):
"""Run bidding simulator
Parameters
----------
ctr_model : sklearn-like model
Binary classifier for click prospenity
Returns
-------
bids : list
Bids for each entry in the data"""
total_impressions = 0
total_ad_spend = 0
total_clicks = 0
for i, row in self._data.iterrows():
if ctr_model is not None:
prospenity = ctr_model.predict_proba(
row.drop(['click',
'paying_price']).values.reshape(1, -1))[0][1]
else:
prospenity = None
bid = self._bidding_strategy(prospenity, row)
if bid >= row['paying_price']:
total_impressions += 1
total_ad_spend += row['paying_price']
if row['click']:
total_clicks += 1
return RunResults(total_clicks, total_impressions, total_ad_spend)
[docs] @staticmethod
def metrics_report(run_results):
"""Generate metric let g:pymode_lint = 0u
Parameters
----------
run_results : RunResults
Returns
-------
cpc : float
Cost Per Click.
ctr : float
Click Through Rate.
cpm : float
Cost Per Mille.
"""
ctr = BidSimulator.ctr(run_results.total_clicks,
run_results.total_impressions)
cpm = BidSimulator.cpm(run_results.total_ad_spend,
run_results.total_impressions)
cpc = BidSimulator.cpc(run_results.total_ad_spend,
run_results.total_clicks)
report = "CTR:\t%.2f\nCPM:\t%.3f\nCPC:\t%.3f" % (ctr, cpm, cpc)
return report
[docs] @staticmethod
def ctr(num_of_clicks, num_of_impressions):
"""Claculate Click Through Rate - frequency of clicks on ads."""
return num_of_clicks / num_of_impressions \
if num_of_impressions > 0 else 0
[docs] @staticmethod
def cpm(total_spendings, num_of_impressions):
"""Calculate Cost Per Mille
- total cost advertiser pays for 1000 impressions."""
return total_spendings / num_of_impressions * 1000 \
if num_of_impressions > 0 else 0
[docs] @staticmethod
def cpc(total_spendings, num_of_clicks):
"""Calculate Cost Per Click"""
return total_spendings / num_of_clicks if num_of_clicks > 0 else 0
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
self._bidding_strategy.__class__.__name__)
[docs]class RandomBiddingStrategy(object):
"""Random strategy that places random pertribations of a base bid"""
[docs] def __init__(self, bid):
"""Create random bidding strategy
Parameters
----------
bid : float
Bid value
"""
self._bid = bid
[docs] def __call__(self, prospenity, row):
"""Execute bidding strategy
Parameters
----------
prospenity : float
prospenity to click
row : dict-like
data row with features, pricing, impression and click data
Returns
-------
bid_price : float
"""
return np.random.rand() * self._bid
[docs]class FlatBiddingStrategy():
"""Constant bid"""
[docs] def __init__(self, bid):
"""Create flat bidding strategy
Parameters
----------
bid : float
Bid value
"""
self._bid = bid
[docs] def __call__(self, prospenity, row):
"""Execute bidding strategy
Parameters
----------
prospenity : float
prospenity to click
row : dict-like
data row with features, pricing, impression and click data
Returns
-------
bid_price : float
"""
return self._bid
[docs]class GoalBiddingStrategy():
"""Bid based on prospenity"""
[docs] def __init__(self, bid):
"""Create bidding strategy
Parameters
----------
bid : float
Bid value
"""
self._bid = bid
[docs] def __call__(self, prospenity, row):
"""Execute bidding strategy
Parameters
----------
prospenity : float
prospenity to click
row : dict-like
data row with features, pricing, impression and click data
Returns
-------
bid_price : float
"""
return prospenity * self._bid
[docs]class EffectiveCPCBiddingStrategy(GoalBiddingStrategy):
"""Bid based on prospenity and CPC calculated from training data"""
[docs] def __init__(self, data):
"""Create bidding strategy
Parameters
----------
data : pd.DataFrame
Historical data
"""
effective_cpc = data['paying_price'].sum() / data['click'].sum()
print(effective_cpc)
super().__init__(effective_cpc)