mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-27 05:52:47 +08:00
Live decomposition of the 2026-07-23 drawdown (equity 62.6 -> 31.1 in one day, 43 fills, avg hold <1h despite a 4h min hold): both exit guards compared thresholds meant as price moves against leverage-multiplied margin PnL%, so raising leverage 5x -> 10x silently halved every trigger distance: - throttle bypass: -5% 'stop' unlocked AI closes at a -0.5% price wiggle (ETH -0.5%/44min, AAVE -0.9%/45min, MU -2.4%/14min all sailed through) - drawdown monitor: 'profit > 5%' armed at +0.5% price, then market-closed winners on a 40% giveback (SNDK +0.6%/35min, NVDA +0.3%/37min) — every winner strangled at breakeven while losers realized fast Fix: evaluate both guards on price-basis PnL (margin PnL% / leverage). Throttle thresholds keep their documented price meaning at any leverage; the drawdown monitor now arms only after a real +5% price move. Peak-PnL cache stays margin-basis for prompt display consistency. Replay simulator updated to the same price-basis semantics.
28 lines
920 B
Go
28 lines
920 B
Go
package trader
|
|
|
|
import "testing"
|
|
|
|
func TestDrawdownCloseArmsOnPriceBasisOnly(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
pricePnLPct float64
|
|
drawdownPct float64
|
|
shouldClose bool
|
|
}{
|
|
// +0.5% price move (what +5% margin at 10x used to arm on) must NOT
|
|
// arm the monitor, no matter how large the relative drawdown is.
|
|
{"tiny price gain big drawdown", 0.5, 60.0, false},
|
|
// Armed only from a real +5% price move, and still needs the 40% giveback.
|
|
{"real gain small drawdown", 6.0, 20.0, false},
|
|
{"real gain big drawdown", 6.0, 45.0, true},
|
|
{"at threshold not armed", 5.0, 45.0, false},
|
|
{"loss never triggers", -3.0, 80.0, false},
|
|
}
|
|
for _, c := range cases {
|
|
if got := shouldDrawdownClose(c.pricePnLPct, c.drawdownPct); got != c.shouldClose {
|
|
t.Fatalf("%s: shouldDrawdownClose(%.1f, %.1f) = %v, want %v",
|
|
c.name, c.pricePnLPct, c.drawdownPct, got, c.shouldClose)
|
|
}
|
|
}
|
|
}
|