Skip to content

How to write a win cost model

Rémi Attab edited this page Mar 12, 2014 · 5 revisions

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.

Motivation

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.

Win Cost Model

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.

Exchange Connector

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.

Factory

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.

Clone this wiki locally