How to write a win cost model
In this document, we'll write a win cost model to account for expenses associated with an actual bid. This is needed in at least 3 situations:
- Reserve a realistic amount of money when a bid is performed
- Take the decision to bid
- Account for the actual cost of the impression
Sections of the source code presented here for the win cost model is available in the rtbkit's repository.
We need to be able to handle situations such as "when we win at win-price X, we've actually spent X * alpha + beta" where (for example) alpha = 1 + margins and beta = fixed cost of data and/or ad serving incurred on win.
For example, a margin in this context could be 5% of media costs. So the cost of the impression was X but the spent was 1.05 * X. The beta costs include for example the cost of ad-serving. If the cost of the impression was X, and it costs 0.02$cpm to serve the impression, then the spent should be X + 0.02$cpm.
Writing the win cost model itself is simple. Consider this:
Amount linearWinCostModel(WinCostModel const & model,
Bid const & bid,
Amount const & price)
{
double m = model.data["m"].asDouble();
Amount b = Amount::fromJson(model.data["b"]);
return price * m + b;
}
Here, we have a simple function that basically takes a WinCostModel
with some amount to return the actual win cost. Note that it uses the data of the WinCostModel
to get the required information for the computation. Here, alpha (m) is a scalar factor and beta (b) is a fixed amount added to the cost of the impression.
The next step is to create a WinCostModel
instance when a new bid request is received. Assuming that you're writing your own exchange connector, this is achieved by overwriting the getWinCostModel
function of the ExchangeConnector
.
WinCostModel
getWinCostModel(Auction const & auction, AgentConfig const & agent) {
Json::Value data;
data["m"] = 1.05;
data["b"] = MicroUSD_CPM(2000.0).toJson();
return WinCostModel("linear", data);
}
Note that the WinCostModel
only requires a unique string identifier. The data member is used to keep track of whatever is needed to actually compute the real win cost. In this case, we inject the value of alpha (m) and beta (b) that are used by our linear win cost model.
If needed, other informations from the actual auction or from the bidding agent can also be used.
The last step is to register the win cost model function and make it available for use. This is done by creating a shared library and by registering the function.
The name of the shared library needs to match the name of the win cost model so that it can be dynamically loaded. For instance, the linear cost model should be in liblinear_win_cost_model.so.
Then, make sure that the function is registed like so:
namespace {
struct AtInit {
AtInit() {
WinCostModel::registerModel("linear", linearWinCostModel);
} atInit;
}
And you're done.
- Getting Started
- Pull Request Guidelines
- Coding Standards
- Demo Stack
- How to compile static filters test
- RTBkit Binary Package
- Architecture
- Bid Request Lifecycle
- ZooKeeper Nodes
- Load Shedding
- Banker
- Post Auction Loop State Machine
- Post-Auction Loop Sharding
- ZMQ Endpoints