feat: capital floor protection — 25% max drawdown terminates episode

PDT $25K rule protection: if equity drops below 75% of peak_equity,
the episode terminates (done=1) with a -1.0 penalty reward and forced
flat. The model learns that approaching the floor = game over.

Uses peak_equity (not initial_capital) so it adapts as account grows.
With $35K initial, floor triggers at ~$26.25K — above the $25K minimum.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-03-23 09:33:03 +01:00
parent 235323d34b
commit a247c77543

View File

@@ -649,12 +649,27 @@ extern "C" __global__ void experience_env_step(
- hold_time_penalty;
}
/* ---- Capital floor protection (PDT $25K rule) ---- */
/* If equity drops to 25% drawdown from peak, terminate the episode.
* With $35K initial, this triggers at ~$26.25K — above the $25K PDT minimum.
* Uses peak_equity (not initial_capital) so it adapts as account grows.
* The model learns: approaching the floor = game over = zero future reward. */
float new_portfolio_value = cash + position * raw_next;
float capital_floor = peak_equity * 0.75f;
if (new_portfolio_value < capital_floor) {
/* Force flat — emergency exit all positions */
position = 0.0f;
cash = new_portfolio_value;
new_portfolio_value = cash;
/* Massive penalty — approaching the floor is catastrophic */
reward = -1.0f;
}
/* ---- Done detection ---- */
int next_bar = bar_idx + 1;
int done = (next_bar >= total_bars) ? 1 : 0;
int done = (next_bar >= total_bars || new_portfolio_value < capital_floor) ? 1 : 0;
/* ---- Update full portfolio state (PORTFOLIO_STRIDE=14) ---- */
float new_portfolio_value = cash + position * raw_next;
ps[0] = position;
ps[1] = cash;
ps[2] = new_portfolio_value;