revert: drop exit-gate configurability, hardcode the replay-validated values

Operator call: no per-strategy configurability for exit pacing — it added
config fields, UI and plumbing nobody wanted. Back to plain constants in
auto_trader_throttle.go, now set to the replay-validated values instead
of the original guesses (4154 cycles, 3-fold robust search over only the
7 exit params, everything else fixed at the live config):

- min hold 90m, noise-close window 3h, noise band -2%..+3%,
  bypasses -3%/+8% (all inside the searched top-20 ranges)
- re-entry cooldown 4h — the one clear signal: top-20 configs cluster
  tightly at 3.8-4.0h; re-entering a just-closed symbol was a consistent
  loss source

Removes the 7 RiskControlConfig fields + accessors, the Strategy Studio
'exit pacing' row, the frontend type fields, and the fields from stored
strategy configs in data/data.db. Prompt guidance is static text again,
matching the constants.
This commit is contained in:
tinkle-community
2026-07-26 13:27:59 +09:00
parent 434301cb09
commit 574ddfb1ae
6 changed files with 47 additions and 241 deletions

View File

@@ -2321,68 +2321,6 @@ export function StrategyStudioPage() {
</select>
</label>
</div>
<div className="mt-4 grid gap-4 sm:grid-cols-3">
<label className="space-y-2">
<span className="text-xs text-nofx-text-muted">
{text(language, '最小持仓时间', 'Min hold')}
</span>
<select
value={risk.min_hold_minutes ?? 90}
onChange={(event) =>
patchRisk({
min_hold_minutes: Number(event.target.value),
})
}
className="w-full rounded-lg border border-[rgba(26,24,19,0.14)] bg-nofx-bg px-3 py-2 text-sm text-nofx-text"
>
{[30, 60, 90, 120, 180, 240].map((value) => (
<option key={value} value={value}>
{value >= 60 ? `${value / 60}h` : `${value}m`}
</option>
))}
</select>
</label>
<label className="space-y-2">
<span className="text-xs text-nofx-text-muted">
{text(language, '横盘仓锁定窗口', 'Flat-close window')}
</span>
<select
value={risk.noise_hold_minutes ?? 180}
onChange={(event) =>
patchRisk({
noise_hold_minutes: Number(event.target.value),
})
}
className="w-full rounded-lg border border-[rgba(26,24,19,0.14)] bg-nofx-bg px-3 py-2 text-sm text-nofx-text"
>
{[60, 120, 180, 240, 360, 480].map((value) => (
<option key={value} value={value}>
{`${value / 60}h`}
</option>
))}
</select>
</label>
<label className="space-y-2">
<span className="text-xs text-nofx-text-muted">
{text(language, '同币再入冷却', 'Re-entry cooldown')}
</span>
<select
value={risk.reentry_cooldown_minutes ?? 90}
onChange={(event) =>
patchRisk({
reentry_cooldown_minutes: Number(event.target.value),
})
}
className="w-full rounded-lg border border-[rgba(26,24,19,0.14)] bg-nofx-bg px-3 py-2 text-sm text-nofx-text"
>
{[30, 60, 90, 120, 180].map((value) => (
<option key={value} value={value}>
{value >= 60 ? `${value / 60}h` : `${value}m`}
</option>
))}
</select>
</label>
</div>
</div>
</div>

View File

@@ -209,14 +209,4 @@ export interface RiskControlConfig {
min_position_size: number; // Min position size in USDT (CODE ENFORCED)
min_risk_reward_ratio: number; // Min take_profit / stop_loss ratio (AI guided)
min_confidence: number; // Min AI confidence to open position (AI guided)
// Exit throttle gates (CODE ENFORCED, 0/absent = backend defaults).
// PnL thresholds are PRICE-move percentages (leverage-independent).
min_hold_minutes?: number; // AI closes blocked before this unless a bypass fires
noise_hold_minutes?: number; // flat closes inside the noise band blocked until this
reentry_cooldown_minutes?: number; // same-symbol reopen cooldown after a close
early_stop_bypass_pct?: number; // price loss unlocking an early close (negative)
early_tp_bypass_pct?: number; // price profit unlocking an early close (positive)
noise_loss_floor_pct?: number; // noise band lower edge (negative)
noise_profit_ceiling_pct?: number; // noise band upper edge (positive)
}