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>
This commit is contained in:
Senofy
2026-03-09 18:57:12 -05:00
co-authored by Claude Sonnet 4.6
parent 95e7433941
commit 570a54fe60
10 changed files with 218 additions and 66 deletions
+7 -16
View File
@@ -15,12 +15,6 @@ import {
Dot,
} from 'recharts';
import type { FirmConfig, FirmState, AccountState, AccountConfig } from '@/types';
import { computeDailyTarget } from '@/lib/trading-logic';
interface DailyPnL {
date: string;
pnl: number;
}
function getAccountConfig(name: string, firm: FirmConfig): AccountConfig | undefined {
return [...firm.accounts]
@@ -178,20 +172,15 @@ export default function AccountPage() {
const [account, setAccount] = useState<AccountState | null>(null);
const [cfg, setCfg] = useState<AccountConfig | null>(null);
const [firmName, setFirmName] = useState('');
const [dailyPnL, setDailyPnL] = useState<DailyPnL[]>([]);
useEffect(() => {
async function load() {
const [stateRes, firmsRes, dailyRes] = await Promise.all([
const [stateRes, firmsRes] = await Promise.all([
fetch('/api/state'),
fetch('/api/firms'),
fetch(`/api/accounts/${accountId}/daily-pnl`),
]);
const states: FirmState[] = await stateRes.json();
const firms: FirmConfig[] = await firmsRes.json();
const daily: DailyPnL[] = await dailyRes.json();
setDailyPnL(daily);
for (const firmState of states) {
const acc = firmState.accounts.find((a) => a.id === accountId);
@@ -223,6 +212,9 @@ export default function AccountPage() {
);
}
// dailyPnL comes from state — same source as dailyTarget, no separate fetch needed.
const dailyPnL = account.dailyPnL;
const hasLossLimit = cfg != null && cfg.minDayPnL !== -999;
const daysPassed = cfg != null && account.daysTraded >= cfg.minTradingDays;
// Dead when balance hits Tradovate's auto-liquidation floor
@@ -237,15 +229,14 @@ export default function AccountPage() {
: Math.round(fifoTotal * 100) / 100;
const profitPct = cfg?.accountSize ? (totalProfit / cfg.accountSize) * 100 : null;
const profitPassed = cfg != null && totalProfit >= cfg.profitTarget;
const dailyTarget = cfg && !isDead
? computeDailyTarget(cfg.profitTarget, cfg.consistency, totalProfit, dailyPnL)
: null;
// dailyTarget is computed server-side in the state API — single source of truth.
const dailyTarget = account.dailyTarget ?? null;
const lossPassed = !hasLossLimit || (cfg != null && totalProfit >= cfg.minDayPnL);
// Consistency target: the total profit level at which the best day no longer
// violates the consistency ratio. Only meaningful once a positive day exists.
const maxDayPnL = dailyPnL.length > 0 ? Math.max(...dailyPnL.filter(d => d.pnl > 0).map(d => d.pnl)) : 0;
const consistencyTarget = cfg && maxDayPnL > 0
const consistencyTarget = cfg && cfg.consistency > 0 && maxDayPnL > 0
? Math.round(maxDayPnL / cfg.consistency * 100) / 100
: null;