Debug the Impact Model
Learn this problemProblem 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
- Let
impactParams = [k, decay, halfSpread]. The accumulated impact starts at0. - For the current request, use direction
+1forBUYand-1forSELL. - Emit
reference + direction * halfSpread + accumulatedImpact. The current request must not affect its own quote. - Compute the current size impact as
direction * k * quantity * (1 - liquidityScore). - 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 nonnegativek,decayin[0, 1], and nonnegativehalfSpread.reference > 0and every quantity is positive.0 <= liquidityScore <= 1.- Every side is exactly
BUYorSELL. - Every input and intermediate result fits in a finite
double.