Problem · Simulation

Debug the Impact Model

Learn this problem
HardMillennium logoMillenniumNEW GRADINTERNOA

Problem statement

A market-making desk quotes an ordered stream of client requests for one asset. Each completed request leaves a temporary signed market impact that biases later quotes and then decays. The supplied implementation produces the expected first quote, but its state drifts across a multi-request stream. Repair the recurrence without changing the method signature.

Buggy implementation to repair

The source's request objects are represented here by the portable parallel-array interface. This implementation intentionally retains the reported decay-placement defect:

public double[] quoteImpactStream(double reference, double[] impactParams, double liquidityScore, String[] sides, double[] quantities) {
    double k = impactParams[0];
    double decay = impactParams[1];
    double halfSpread = impactParams[2];
    double accumulatedImpact = 0.0;
    double[] quotes = new double[sides.length];
    boolean first = true;

    for (int i = 0; i < sides.length; i++) {
        double direction = sides[i].equals("BUY") ? 1.0 : -1.0;
        double signedSpread = direction * halfSpread;
        if (first) {
            quotes[i] = reference + signedSpread;
            first = false;
        } else {
            quotes[i] = reference + signedSpread + accumulatedImpact;
        }
        double currentSizeImpact = direction * k * quantities[i] * (1.0 - liquidityScore);
        accumulatedImpact = accumulatedImpact * decay + currentSizeImpact;
    }
    return quotes;
}

Correct quote and state rules

  1. Let impactParams = [k, decay, halfSpread]. The accumulated impact starts at 0.
  2. For the current request, use direction +1 for BUY and -1 for SELL.
  3. Emit reference + direction * halfSpread + accumulatedImpact. The current request must not affect its own quote.
  4. Compute the current size impact as direction * k * quantity * (1 - liquidityScore).
  5. After emitting the quote, update the state to (accumulatedImpact + currentSizeImpact) * decay. The resulting value biases the next request.

Return one quote per request in the original order.

Function

quoteImpactStream(reference: double, impactParams: double[], liquidityScore: double, sides: String[], quantities: double[]) → double[]

Examples

Example 1

reference = 100impactParams = [0.01,0.5,0.1]liquidityScore = 0.8sides = ["BUY","BUY","SELL"]quantities = [10,20,5]return = [100.1,100.11,99.925]

The first quote has no prior impact. Its accepted BUY contributes 0.02 before decay, so the next offset is 0.01. The second BUY leaves an offset of 0.025 for the SELL quote.

Example 2

reference = 50impactParams = [0.2,0.7,0.05]liquidityScore = 1sides = ["SELL","BUY"]quantities = [100,250]return = [49.95,50.05]

Perfect liquidity makes every size-impact contribution zero, so only the side-specific half spread changes each quote.

Example 3

reference = 10impactParams = [0.1,0,0.2]liquidityScore = 0sides = ["BUY","BUY"]quantities = [3,4]return = [10.2,10.2]

A decay of zero clears the updated state after every request, so the second request also sees zero prior impact.

Constraints

  • 1 <= sides.length = quantities.length <= 500.
  • impactParams.length = 3, representing nonnegative k, decay in [0, 1], and nonnegative halfSpread.
  • reference > 0 and every quantity is positive.
  • 0 <= liquidityScore <= 1.
  • Every side is exactly BUY or SELL.
  • Every input and intermediate result fits in a finite double.

More Millennium problems

drafts saved locally
public double[] quoteImpactStream(double reference, double[] impactParams, double liquidityScore, String[] sides, double[] quantities) {
    // write your code here
}
reference100
impactParams[0.01,0.5,0.1]
liquidityScore0.8
sides["BUY","BUY","SELL"]
quantities[10,20,5]
expected[100.1,100.11,99.925]
checking account