diff --git a/README.md b/README.md
index 5ae87ec..0d292ef 100644
--- a/README.md
+++ b/README.md
@@ -114,7 +114,7 @@ the batch firm's list, at random but weighted:
- **Efficiency** — one contract's typical daily move ÷ one tick of spread
(from Yahoo's hourly candles over the past week, measured once a day).
- Commissions don't count; they're shown, never used to choose.
+ Commissions don't count — they barely differ between instruments.
- **Session timing** — at the open every instrument gets a 10% floor and the
weights follow efficiency; toward the last entry (14:55 CT) the floor fades
and the weight moves sharply to the fastest movers.
@@ -126,7 +126,7 @@ the batch firm's list, at random but weighted:
listed product (MNQ when NQ is listed).
Every draw logs its odds. `GET /api/instruments` shows each firm's list with
-entry cost, daily move, hold and chance (`?simulate=10000` runs the real draw
+spread, daily move, hold and chance (`?simulate=10000` runs the real draw
with no orders), and the master's Firms page shows the same next to each
instrument.
diff --git a/app/api/instruments/route.ts b/app/api/instruments/route.ts
index 3f3caf7..7d17c05 100644
--- a/app/api/instruments/route.ts
+++ b/app/api/instruments/route.ts
@@ -1,5 +1,4 @@
import { NextRequest, NextResponse } from 'next/server';
-import { getClients } from '@/lib/clients';
import { getCachedCatalog } from '@/lib/firm-catalog';
import {
ensureMarket, firmInstruments, futuresRootsHere, instrumentStatsFor, instrumentsSource, isFuturesFirm, simulateDraws,
@@ -13,13 +12,12 @@ const EXAMPLE_LEG = { leg: 1000, stopDollars: Infinity, maxPositionSize: 0 };
/**
* GET /api/instruments — what each firm trades (the master's lists) and, for
- * futures firms, how the Auto draw sees every instrument right now: entry
- * cost, one contract's daily move, the hold of a $1,000 leg, the chance.
+ * futures firms, how the Auto draw sees every instrument right now: a tick
+ * of spread, one contract's daily move, the hold of a $1,000 leg, the chance.
* ?simulate=N adds N draws from the real draw code — no orders.
*/
export async function GET(req: NextRequest) {
await ensureMarket(CME_ROOTS, 8_000);
- const clients = getClients();
const n = Math.min(100_000, Math.max(0, Math.floor(Number(req.nextUrl.searchParams.get('simulate')) || 0)));
const firms = getCachedCatalog().map((firm) => {
const instruments = firmInstruments(firm);
@@ -30,7 +28,7 @@ export async function GET(req: NextRequest) {
platform: firm.platform,
source: instrumentsSource(firm),
instruments,
- ...(futures ? { stats: instrumentStatsFor(firm, clients.get(firm.id), { ...EXAMPLE_LEG, account: 'a $1,000 leg' }) } : {}),
+ ...(futures ? { stats: instrumentStatsFor(firm, { ...EXAMPLE_LEG, account: 'a $1,000 leg' }) } : {}),
...(futures && n > 0 ? { simulated: simulateDraws(instruments, EXAMPLE_LEG, n) } : {}),
};
});
diff --git a/app/settings/page.tsx b/app/settings/page.tsx
index e13654e..08d972c 100644
--- a/app/settings/page.tsx
+++ b/app/settings/page.tsx
@@ -20,7 +20,6 @@ interface InstrumentsOverview {
symbol: string;
listed: boolean;
spreadDollars: number;
- feesPerSide: number | null;
dailyMoveDollars: number | null;
holdHours: number | null;
disabled: boolean;
@@ -470,7 +469,7 @@ export default function SettingsPage() {
| Symbol |
Contract |
- Entry |
+ Spread |
Daily move |
Hold |
Chance now |
@@ -487,8 +486,8 @@ export default function SettingsPage() {
{c?.name ?? '—'}
{c?.alternative && rolled from {c.alternative}}
-
- {x ? `$${x.spreadDollars.toFixed(2)}${x.feesPerSide !== null ? ` + $${x.feesPerSide.toFixed(2)}` : ''}` : '—'}
+ |
+ {x ? `$${x.spreadDollars.toFixed(2)}` : '—'}
|
{x?.dailyMoveDollars != null ? `$${x.dailyMoveDollars.toLocaleString()}` : '—'}
diff --git a/lib/auto-trade.ts b/lib/auto-trade.ts
index 9cd2865..b90a38e 100644
--- a/lib/auto-trade.ts
+++ b/lib/auto-trade.ts
@@ -22,7 +22,7 @@ import {
} from './trading-logic';
import { getSetting, setSetting } from './db';
import { POINT_VALUES, housekeepingRoot } from './instrument-specs';
-import { firmInstruments, drawFuturesInstrument, recordMeasuredFee, type LegShape } from './instruments';
+import { firmInstruments, drawFuturesInstrument, type LegShape } from './instruments';
import { errorMessage, isClientReady, isOrderNotPlaced, type PlatformClient, type PlatformContract, type PickContext } from './platform-client';
// ── process-wide state ───────────────────────────────────────────────────────
@@ -1230,7 +1230,6 @@ async function fireLeg(
await new Promise(r => setTimeout(r, 1000));
const updatedCash = client.accountCashBalances[acc.id] ?? { amount: 0, realizedPnL: 0 };
measured = entryCommissionMeasured(item.cash.realizedPnL, updatedCash.realizedPnL, contracts);
- if (measured !== null && !item.drain) recordMeasuredFee(item.firm.id, symbolLabel, measured / contracts);
entryFee = measured ?? FALLBACK_COMMISSION_PER_CONTRACT * contracts;
}
// The stop. On a measured-fee firm whose fee didn't show, the daily-loss
diff --git a/lib/instruments.ts b/lib/instruments.ts
index 9df6ca6..a9cbe78 100644
--- a/lib/instruments.ts
+++ b/lib/instruments.ts
@@ -10,8 +10,8 @@
* near the last entry, nothing expected to hold 12 hours or more.
*
* Movement comes from Yahoo's hourly candles (7 days, measured once per trade
- * date); the spread is one tick. Fees are shown, never used to choose:
- * Tradovate's fee parameters, or TopstepX's last measured fill.
+ * date); the spread is one tick. Commissions play no part — they barely
+ * differ between instruments.
*/
import axios from 'axios';
@@ -76,8 +76,6 @@ const CONCURRENCY = 4;
const g = globalThis as typeof globalThis & {
__futuresMarket?: Map;
__futuresMarketInflight?: Map>;
- __futuresFees?: Map; at: number }>;
- __futuresMeasuredFees?: Map;
};
const market = (g.__futuresMarket ??= new Map());
const inflight = (g.__futuresMarketInflight ??= new Map());
@@ -143,33 +141,6 @@ export function marketOf(root: string): { price: number | null; dailyMove: numbe
return m ? { price: m.price, dailyMove: m.dailyMove, error: m.error } : null;
}
-// ── fees (shown, never used to choose) ─────────────────────────────────────
-
-const feeCache = (g.__futuresFees ??= new Map());
-const measuredFees = (g.__futuresMeasuredFees ??= new Map());
-
-/** A fill's commission per contract per side, for platforms with no fee
- * lookup (TopstepX). */
-export function recordMeasuredFee(firmId: string, root: string, perContract: number): void {
- if (Number.isFinite(perContract) && perContract >= 0) measuredFees.set(`${firmId}|${root}`, Math.round(perContract * 100) / 100);
-}
-
-/** Tradovate's fee parameters, fetched once per trade date per firm. */
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export function refreshFees(firm: { id: string; platform: string }, client: any): void {
- if (firm.platform !== 'tradovate' || typeof client?.fetchInstrumentFees !== 'function') return;
- const cached = feeCache.get(firm.id);
- if (cached && cached.tradeDate === currentTradeDateCT() && (Object.keys(cached.fees).length > 0 || Date.now() - cached.at < RETRY_MS)) return;
- feeCache.set(firm.id, { tradeDate: currentTradeDateCT(), fees: cached?.fees ?? {}, at: Date.now() });
- void Promise.resolve(client.fetchInstrumentFees([...CME_ROOTS]))
- .then((fees: Record) => feeCache.set(firm.id, { tradeDate: currentTradeDateCT(), fees: fees ?? {}, at: Date.now() }))
- .catch((err: unknown) => console.warn(`[instruments] fee lookup failed: ${errorMessage(err)}`));
-}
-
-export function feesPerSide(firmId: string, root: string): number | null {
- return feeCache.get(firmId)?.fees[root] ?? measuredFees.get(`${firmId}|${root}`) ?? null;
-}
-
// ── the draw ────────────────────────────────────────────────────────────────
/** The batch's leg, for the hold estimate: its dollars, its stop (Infinity =
@@ -240,17 +211,14 @@ export function simulateDraws(roots: readonly string[], leg: LegShape | null, n:
/**
* A futures firm's instruments as the draw sees them right now: every CME
- * root with its entry cost, movement and contract, and — sized for `lead`'s
+ * root with its spread, movement and contract, and — sized for `lead`'s
* next leg — the listed ones' holds, the ones over the cap, and each one's
* chance.
*/
export function instrumentStatsFor(
firm: FirmLike & { id: string },
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- client: any,
lead: (LegShape & { account: string }) | null,
): InstrumentStats {
- refreshFees({ id: firm.id, platform: firm.platform }, client);
const listed = firmInstruments(firm);
const board = futuresBoard(listed, lead);
const disabled = new Set(board.disabled);
@@ -269,7 +237,6 @@ export function instrumentStatsFor(
listed: listed.includes(root),
contract: getCachedContract(root)?.name ?? null,
spreadDollars: spreadDollars(root),
- feesPerSide: feesPerSide(firm.id, root),
dailyMoveDollars: dailyMove === null ? null : Math.round(dailyMove),
holdHours: holdHours === null ? null : Math.round(holdHours * 10) / 10,
disabled: listed.includes(root) ? disabled.has(root) : holdHours !== null && holdHours >= MAX_HOLD_HOURS,
diff --git a/lib/master-protocol.ts b/lib/master-protocol.ts
index 552fa4d..dc935f7 100644
--- a/lib/master-protocol.ts
+++ b/lib/master-protocol.ts
@@ -138,8 +138,6 @@ export interface InstrumentStats {
contract: string | null;
/** One tick of spread on one contract, in dollars. */
spreadDollars: number;
- /** The firm's fees per contract per side; null when unknown. */
- feesPerSide: number | null;
/** One contract's typical daily move (1σ), in dollars. */
dailyMoveDollars: number | null;
holdHours: number | null;
diff --git a/lib/reporter.ts b/lib/reporter.ts
index 1ef970e..1215d0f 100644
--- a/lib/reporter.ts
+++ b/lib/reporter.ts
@@ -427,7 +427,7 @@ function instrumentStatsBlock(
const shape = accountLegShape(client, acc, tradeDate);
if (shape) { lead = { ...shape, account: acc.name }; break; }
}
- return { instrumentStats: instrumentStatsFor(f, client, lead) };
+ return { instrumentStats: instrumentStatsFor(f, lead) };
}
/**
|