Broker sessions rest while nothing needs them

A firm's client used to stay logged in around the clock, renewing on a fixed
timer overnight and at weekends. Now, once a firm has nothing open, nothing
pending and nothing left to trade before its next session for a random
15–45 minutes, its client disconnects and the dashboard shows it Resting.
It logs back in a random 20–50 minutes before the next session opens, at a
check-in every 3–7 Central daytime hours, or at once when trading starts, a
manual leg, copy trade, manual order or AutoBuyer run needs it. Token
renewals fall at random points (Tradovate 15–45 min before expiry, TopstepX
every 45–150 min). Settings → Trading → Rest idle broker sessions
(session_rest) turns it off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-10-21 13:28:47 -05:00
co-authored by Claude Opus 5.5
parent 6dd2528fe2
commit 5eb0ea7760
18 changed files with 872 additions and 41 deletions
+21 -1
View File
@@ -45,6 +45,7 @@ interface AppSettings {
instance_name: string | null;
instance_id: string | null;
trading_hours: string | null;
session_rest: string | null;
master_backup_token: string | null;
proxy_url: string | null;
user_agent: string | null;
@@ -64,6 +65,7 @@ export default function SettingsPage() {
const [contracts, setContracts] = useState<Record<string, ResolvedContract | null>>({});
const [maxConcurrent, setMaxConcurrent] = useState<string>('5');
const [tradingHours, setTradingHours] = useState<string>('full_cme');
const [sessionRest, setSessionRest] = useState<boolean>(true);
const [masterUrl, setMasterUrl] = useState<string>('');
const [catalog, setCatalog] = useState<{
version: number;
@@ -114,6 +116,7 @@ export default function SettingsPage() {
if (s.max_concurrent_accounts != null) {
setMaxConcurrent(s.max_concurrent_accounts);
}
setSessionRest(s.session_rest !== '0');
if (s.trading_hours != null) {
setTradingHours(s.trading_hours);
}
@@ -161,7 +164,7 @@ export default function SettingsPage() {
await fetch('/api/settings', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ max_concurrent_accounts: maxConcurrent, trading_hours: tradingHours, master_dashboard_url: masterUrl, instance_name: instanceName, master_backup_token: backupToken, proxy_url: proxyUrl }),
body: JSON.stringify({ max_concurrent_accounts: maxConcurrent, trading_hours: tradingHours, session_rest: sessionRest ? '1' : '0', master_dashboard_url: masterUrl, instance_name: instanceName, master_backup_token: backupToken, proxy_url: proxyUrl }),
});
setSaving(false);
setSaved(true);
@@ -280,6 +283,23 @@ export default function SettingsPage() {
<option value="equity_hours">Equity Hours (8:30 AM – 3:00 PM CT)</option>
</select>
</div>
<div className="flex items-center justify-between gap-4 border-t border-slate-100 px-4 py-3">
<div>
<p className="text-sm font-medium text-slate-800">Rest idle broker sessions</p>
<p className="text-xs text-slate-400 mt-0.5">
Log a firm out once nothing is open and nothing is left to trade before its next
session (weekends, the daily break, a finished day), and back in 20–50 min before
that session opens, with a check-in every few daytime hours. Off keeps every
session logged in around the clock.
</p>
</div>
<input
type="checkbox"
checked={sessionRest}
onChange={(e) => setSessionRest(e.target.checked)}
className="h-4 w-4 shrink-0 accent-blue-500"
/>
</div>
</div>
{/* ── Master Dashboard ── */}