From ac61fbb8f80f5a10f1fe0719a21cc4be1331f534 Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Mon, 23 Mar 2026 09:34:11 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20quadratic=20market=20impact=20=E2=80=94?= =?UTF-8?q?=20larger=20trades=20cost=20more?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1-lot fills at bid/ask. 4-lot moves the market. impact_scale = 1 + (|delta|/max_position)^2, ranges [1.0, 2.0]. Teaches the model that max-size positions are 2x more expensive to enter. Makes the 9-exposure granularity meaningful — 25% positions are cheaper to enter/exit than 100% positions. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/ml/src/cuda_pipeline/experience_kernels.cu | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ml/src/cuda_pipeline/experience_kernels.cu b/crates/ml/src/cuda_pipeline/experience_kernels.cu index 52eb55c00..baa78facb 100644 --- a/crates/ml/src/cuda_pipeline/experience_kernels.cu +++ b/crates/ml/src/cuda_pipeline/experience_kernels.cu @@ -473,7 +473,13 @@ extern "C" __global__ void experience_env_step( float tx_cost = 0.0f; if (delta != 0.0f) { - tx_cost = fabsf(delta) * raw_close * tx_cost_multiplier * spread_scale; + /* Market impact: larger trades cost more (quadratic in size). + * A 1-lot order fills at bid/ask. A 4-lot order moves the market. + * impact_scale = 1 + |delta/max_position|^2 — ranges from 1.0 to 2.0. + * This teaches the model that scaling to max position is expensive. */ + float size_ratio = fabsf(delta) / (max_position > 0.0f ? max_position : 1.0f); + float impact_scale = 1.0f + size_ratio * size_ratio; + tx_cost = fabsf(delta) * raw_close * tx_cost_multiplier * spread_scale * impact_scale; cash -= delta * raw_close; cash -= tx_cost; position = target_position;