Commit Graph
30 Commits
Author SHA1 Message Date
Brandon LiandClaude Opus 4.6 009f7471c2 Count only days that hit minDayPnL toward trading day requirement
The state API was returning client.daysTraded (any non-zero day) as the
displayed daysTraded. Firms count only days that hit minDayPnL toward
the min trading day requirement.

When cfg.min_day_pnl > 0, filter dailyPnL by that threshold and use the
filtered count. Otherwise fall back to client.daysTraded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-26 02:57:14 -05:00
Brandon LiandClaude Opus 4.6 8204cd138b Show stage-aware + consistency-adjusted profit target on dashboards
State API now returns effectiveProfitTarget = max(stage profit target,
maxDay/consistency). When a big day forces the consistency rule, this
reflects the actual amount needed to complete the stage — not just the
base profit target.

Main dashboard and account detail page now display this instead of the
raw cfg.profitTarget.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 02:20:11 -05:00
Brandon LiandClaude Opus 4.6 670ee9fbeb Require equityProfit; return null when balance invalid
computeDailyTarget now requires equityProfit (amount - accountSize) and
returns null when it's undefined/null/NaN. 0 is still a valid value.

- Removed totalProfit parameter (was only used as fallback)
- Callers handle null by skipping the account (eligibility) or throwing
  (execution paths)
- State API sets dailyTarget to null when no valid balance, avoids
  incorrect targetHit computation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-21 20:00:52 -05:00
Brandon LiandClaude Opus 4.6 cd0f1e6fac Use equity-based profit for profitTarget comparison
Instead of relying on dailyPnL sum (which can miss reports or be out
of sync with account balance), use (amount - accountSize) as the actual
profit when comparing against profitTarget. Consistency calc still uses
dailyPnL totalProfit for realTarget.

Also unconditionally floor the min-day reservation at minDayPnL — if
equity + (days × minDay) >= target, we coast on min-day.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 20:08:16 -05:00
Brandon LiandClaude Opus 4.6 4025ed2f41 Fix contract resolver: use Yahoo continuous contract price matching
Replace volume-based contract selection with Yahoo Finance continuous
contract price matching ({PRODUCT}=F). The old approach compared volumes
across front/roll candidates, which failed when serial months had
deceptive volume (6EJ26 > 6EM26) or Yahoo was rate-limited (all 0s).

Now fetches the continuous contract price and matches it against
candidates within 0.1% tolerance. Falls back to roll1 if Yahoo fails.
Also adds User-Agent header to avoid 429 rate limiting.

Verified: GC=F price matches GCM26, 6E=F price matches 6EM26.

Also fixes stale 'Random' comment in auto-trade.ts and cleans up
frontVolume/rolledVolume references from settings page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 18:19:51 -05:00
Brandon LiandClaude Opus 4.6 df793bfd70 Fix consistency bug, rename Random to Auto, add stop-after-all, direction pills, copy-trade
Bug fixes:
- Fix computeDailyTarget when consistency is 0% or 100%: treat as no constraint,
  letting min-day reservation or full remaining profit drive the target
- Rename 'Random' to 'Auto' across entire codebase (types, API, UI, scheduler)

Features:
- Add "Stop after all eligible" checkbox: auto-stops scheduler when all
  configured accounts are dead, inactive, already traded, or challenge complete
- Show position direction in status pill: "Long" (green) / "Short" (red)
  instead of generic "In Trade" (blue)
- Add "Copy to Max" button: copies current trade direction to remaining
  eligible accounts up to max_concurrent_accounts limit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 02:50:31 -05:00
Brandon LiandClaude Opus 4.6 8d9a9a5ea9 Rename Random to Auto in UI and always show + on last stage
- Display "Auto" instead of "Random" for symbol/action selectors
- Last withdrawal stage always shows "+" suffix (even with one stage)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:55:20 -05:00
Brandon LiandClaude Opus 4.6 70b1362d3e Add per-stage withdrawal targets with consistency and min trading days
- Add withdrawal stage system: each stage defines profit target, consistency,
  and min trading days for post-withdrawal challenge cycles
- Target Same Equity mode accounts for withdrawn amounts when computing
  effective profit target (profitTarget - remainingProfit)
- Store fund transaction timestamps for time-aware cycle filtering
  (withdrawals before 9 AM CT include that day in new cycle)
- Expose full P&L history (fullDailyPnL) for calendar/equity curve display
  across all cycles, with DB fallback for pre-restart data
- Show stage number (#1, #2, etc.) on calendar cells
- Hide consistency reference line when consistency is 0% or 100%
- Settings UI: "After First W/D" column with same-equity checkbox,
  expandable stage sub-rows with profit/consistency/days inputs
- Default target_same_equity to 1 for new and existing account configs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 05:27:13 -05:00
Brandon LiandClaude Sonnet 4.6 4252adfbea Show fund transactions (W/D) on calendar, equity curve, and cash history table
- Persist fund transactions to SQLite (fund_transactions table) so they
  survive beyond Tradovate's 28-day report window
- Calendar: highlight W/D dates in amber with the amount shown below the day
- Equity curve: reduce running equity at withdrawal dates and show a vertical
  dashed amber line labelled W/D
- New Cash History table below calendar listing all trades and W/D events
  sorted newest-first

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 04:16:24 -05:00
Brandon Li 131c9bca9f Use resolved active contracts for orders 2026-03-18 00:52:25 -05:00
SenofyandClaude Opus 4.6 f498594b16 Add configurable trading hours setting
Dropdown on settings page with two options:
- Full CME (5:00 PM – 3:00 PM CT) with 5 min buffer
- Equity Hours (8:30 AM – 3:00 PM CT) with 5 min buffer
Setting is read live each tick, no restart needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 19:57:48 -05:00
SenofyandClaude Opus 4.6 f112118090 Add master dashboard reporter and settings UI
- New reporter module that pushes firm stats (total accounts, accounts
  traded, in trade) to a configurable master dashboard every 30 seconds
- Add Instance Name and Dashboard URL fields to the settings page
- Register master_dashboard_url and instance_name in settings API
- Seed default (empty) values for new settings in db

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 03:01:48 -05:00
SenofyandClaude Sonnet 4.6 1e1b837cf3 Show daily target below profit target in accounts table
Displays the server-computed dailyTarget.amount as a secondary line
"$X today" under the profit target in the Target column.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 12:59:50 -05:00
SenofyandClaude Sonnet 4.6 b7952a83ef Fix 400 error when starting scheduler with Random symbol
Skip POINT_VALUES validation for 'Random' — the symbol is resolved
to a real instrument inside runTrade before any point value lookup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 03:52:41 -05:00
SenofyandClaude Sonnet 4.6 245a15666e Add configurable tick interval (time between trades)
- Seed tick_interval_seconds setting (default 60s)
- Expose tick_interval_seconds via GET/PATCH /api/settings
- startScheduler reads the setting at start time; enforces 5s minimum
- getSchedulerStatus returns intervalSeconds for the UI
- Main page: "Every [__] s" input in idle bar — saves on blur, persists across
  restarts; running state displays "every Ns" next to symbol/action

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 03:42:54 -05:00
SenofyandClaude Sonnet 4.6 39d7c5761c Add Random symbol option to trade controls
- Symbol dropdown now includes a "Random" option alongside enabled instruments
- runTrade resolves 'Random' to a random enabled instrument once per batch,
  so all accounts in the same tick trade the same symbol
- Import getInstruments in auto-trade.ts to support the resolution

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 03:38:03 -05:00
SenofyandClaude Sonnet 4.6 cade280b2d Auto-fetch contract on symbol enable; hide contract when disabled
- POST /api/instruments/contracts now accepts optional { symbols[] } body
  to resolve a subset rather than all enabled instruments
- Settings toggle() fires a targeted resolve when enabling a symbol,
  merging the result into contracts state without a full page refresh
- Active Contract cell is hidden (null) when the instrument is disabled

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 03:34:51 -05:00
SenofyandClaude Sonnet 4.6 6d3e8b6065 Add per-firm banned symbols feature
- lib/db.ts: new firm_banned_symbols table with getBannedSymbols,
  isSymbolBanned, and setBannedSymbol helpers
- app/api/firms/[id]/banned-symbols/route.ts: GET lists banned symbols,
  PATCH toggles a ban for a given symbol
- app/api/firms/route.ts: include bannedSymbols[] in firm list response
- app/firms/[id]/settings/page.tsx: Instruments section shows all
  globally-enabled symbols with a red toggle to ban/unban; banned
  symbols display a "SYMBOL BANNED" pill next to their name
- app/page.tsx: FirmRows shows "ES BANNED" (or current symbol) pill next
  to the firm name when the selected trade symbol is banned for that firm
- lib/auto-trade.ts: skip firms entirely when the trade symbol is banned
- types.ts: add bannedSymbols field to FirmConfig

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 03:29:16 -05:00
SenofyandClaude Sonnet 4.6 d945e0038f Add volume-based contract auto-resolver and CLAUDE.md
- New lib/contract-resolver.ts: picks the best contract month for each
  symbol by comparing Yahoo Finance volume between the front month
  (Tradovate suggest API) and the roll target (rollcontract API)
- lib/clients.ts: auto-resolves all enabled instruments 15s after startup
  and again daily at midnight via a setInterval check
- lib/tradovate-class.ts: findFrontMonthContract checks resolver cache
  first before falling back to the suggest API
- app/api/instruments/contracts/route.ts: GET returns cached contracts,
  POST triggers a fresh resolve
- app/settings/page.tsx: shows active contract + rolled badge per symbol;
  auto-resolves on load if cache is empty; removed manual Resolve button
- app/api/debug/route.ts: include entity data in recentEntityEvents
- CLAUDE.md: instructs Claude to always work on main

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 03:17:09 -05:00
SenofyandClaude Opus 4.6 881c210366 Add sidebar navigation with responsive bottom bar
Three pages: AutoTrader, AutoBuyer, AutoRequester. Fixed left sidebar
on desktop (md+), bottom tab bar on mobile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:00:41 -05:00
SenofyandClaude Sonnet 4.6 a13096ea86 Add Random direction option — picks Buy or Sell once per batch
All accounts in the same batch trade the same resolved direction.
Each new batch (after positions are flat) picks a fresh random direction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 03:35:50 -05:00
SenofyandClaude Sonnet 4.6 8848f90b11 Use Cash History report for true after-fee daily P&L, Fills FIFO as fallback
- Primary: Cash History report sums non-Fund-Transaction Deltas per day,
  capturing broker platform fees not present in the Fills report
- Fallback: Fills + FIFO used when Cash History 404s (passed/completed accounts)
- Extracts requestReport() as shared helper to reduce duplication
- debug PATCH endpoint now accepts optional `name` param to test any report

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 20:37:05 -05:00
SenofyandClaude Sonnet 4.6 570a54fe60 Fix fetchDaysTraded to use reports API with bearer auth and correct daysTraded counting
- Replace fill/ldeps and fill/list approaches with Tradovate reports API
- Add bearer auth to getreport polling (root cause of prior 404s)
- Use endDate = tomorrow to ensure current-session fills are included
- Count all traded days when minDayPnL is 0, otherwise count days >= minDayPnL
- Add PATCH /api/debug endpoint for proxying raw Tradovate API calls

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 18:57:12 -05:00
SenofyandClaude Sonnet 4.6 ce2075f603 Add privacy toggle, min-day P&L reservation, and extra-day MNQ trades
- Privacy button: masks account names beyond the first 5 chars with bullets;
  eye/eye-off icon toggles the mode in the header toolbar

- computeDailyTarget: accepts minDayPnL + minTradingDays params; when a
  positive min floor is set and mandatory days remain, reserves future-day
  profit so each day hits the floor (cap = remaining - futureReserve, floor
  = minDayPnL); returns effectiveMinDay directly once profit target is met
  but days are not yet satisfied

- auto-trade: passes minDayPnL/minTradingDays to computeDailyTarget; for
  zero-floor accounts that have met the profit target but still owe trading
  days, trades 1 MNQ in-and-out at market (extra-day mode) and bypasses the
  normal target=0 skip gate via isMnqExtraDay flag

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 13:45:26 -05:00
SenofyandClaude Sonnet 4.6 49580c6bb4 Add max_position_size to account configs
- DB migration: ALTER TABLE account_configs ADD COLUMN max_position_size INTEGER NOT NULL DEFAULT 0
- Added max_position_size to AccountConfigRow, createAccountConfig, updateAccountConfig in lib/db.ts
- Added maxPositionSize to AccountConfig type in types.ts (0 = no limit)
- GET /api/firms/[id] now returns maxPositionSize per account
- POST /api/firms/[id]/accounts and PUT /api/account-configs/[id] accept maxPositionSize
- Firm settings page: new Max Contracts column (blank = no limit)
- auto-trade: contracts capped at maxPositionSize when > 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 03:51:09 -05:00
SenofyandClaude Sonnet 4.6 b2a1bdd1c3 Add auto-trade scheduler with batch locking, commission gross-up, and sync gate
- Auto-trade scheduler fires every 60s; uses Promise.allSettled batch so no new trades fire while any position from the current batch is open
- Commission gross-up: read entryCommission from cash.realizedPnL after fill (fallback 2.5×contracts), grossTarget = target + 2×entryCommission
- Sync gate: TradovateClient.syncComplete flag; scheduler skips tick until every client finishes initial position/balance sync
- Contracts formula changed to Math.ceil so $1500 target = 2 contracts
- Removed all fee caching (perContractFees, recentFills, fillFee handler) from tradovate-class.ts
- Removed firm_fees table, getFirmFees, upsertFirmFee from db.ts
- Deleted instrument-configs API routes; removed Fees UI from firm settings page
- /api/instruments returns full {symbol, enabled}[] objects; dashboard filters to enabled-only for trade selector
- Added auto-trade, debug, orders, settings, and trade API routes
- Instrument selector on dashboard now driven by enabled instruments from DB

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 03:31:47 -05:00
SenofyandClaude Sonnet 4.6 532c2e2279 Add daily target logic and consistency reference line to equity curve
- lib/trading-logic.ts: computeDailyTarget() computes the next trading
  day's profit target via two paths:
  • No positive days yet → profitTarget × consistency (first day)
  • Positive days exist → maxDay / consistency gives the total profit
    needed to satisfy the consistency rule; target maxDay when far away,
    or the exact remaining amount when close
- Account detail page: display "Next Trading Day Amount" in Objectives card
- Equity curve: add indigo dashed reference line for the consistency target
  (maxDay / consistency), labelled top-left to avoid overlapping the amber
  profit-target line (top-right)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:26:40 -05:00
SenofyandClaude Sonnet 4.6 dd18f91584 Add full Next.js autotrader app with SQLite persistence and live Tradovate data
- SQLite DB (better-sqlite3) with firms, account_configs, firm_fees, instruments tables
- REST API routes: firms CRUD, account configs CRUD, state, accounts, instruments
- Live Tradovate WebSocket client: login, sync, positions, auto-liq thresholds
- Dashboard (app/page.tsx): per-firm account list with balance, day P&L, days traded,
  target progress, and Dead/Inactive/Flat status based on Tradovate auto-liq floors
- Account detail page: objectives progress, daily P&L chart, consistency tracking
- Per-firm settings page: account configs and instrument fee management
- Dead detection uses trailingMaxDrawdownLimit - trailingMaxDrawdown from
  userAccountAutoLiqs; filters Tradovate sentinel value (999999999 = no limit)
- FIFO P&L engine with commission accounting for daily P&L history
- Removed manual maxLoss fallback in favour of live Tradovate auto-liq data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:03:21 -05:00
Senofy a9b6acd479 Initial Commit 2026-03-07 22:07:02 -06:00
Senofy b33c43aa0c Initial commit from Create Next App 2026-03-07 21:13:43 -06:00