Use resolved active contracts for orders

This commit is contained in:
Brandon Li
2026-03-18 00:52:25 -05:00
parent f498594b16
commit 131c9bca9f
2 changed files with 13 additions and 7 deletions
+3 -3
View File
@@ -28,12 +28,12 @@ export async function POST(
const client = clients.get(firmId);
if (!client) return NextResponse.json({ error: 'Client not found for firm' }, { status: 404 });
// 1. Find the front-month contract
// 1. Find the active contract chosen by the shared resolver
const contract = await client.findFrontMonthContract(symbol);
if (!contract) {
return NextResponse.json({ error: `Could not find active front-month contract for ${symbol}` }, { status: 404 });
return NextResponse.json({ error: `Could not find an active contract for ${symbol}` }, { status: 404 });
}
console.log(`[order] front-month: ${contract.name} (id=${contract.id})`);
console.log(`[order] active contract: ${contract.name} (id=${contract.id})`);
// 2. Place the order — resolves with the fill event (includes commission/fees)
const fill = await client.sendOrder(accountId, contract.name, qty, action, orderType, price);
+10 -4
View File
@@ -4,6 +4,7 @@ import axios from 'axios';
import type { AccountItem, AuthLoginResponse, Contract } from './tradovate-helpers';
import { computeSec, randomUUIDV4 } from './tradovate-helpers';
import { POINT_VALUES } from './trading-logic';
import { getCachedContract, resolveContracts } from './contract-resolver';
export class TradovateClient {
private name: string;
@@ -543,18 +544,23 @@ export class TradovateClient {
async findFrontMonthContract(productName: string): Promise<{ id: number; name: string; tickSize: number } | null> {
if (!this.accessInfo?.accessToken) return null;
// Check the volume-based resolver cache first
const { getCachedContract } = require('./contract-resolver') as typeof import('./contract-resolver');
// Prefer the volume-based resolver so the trading path matches the settings page.
const cached = getCachedContract(productName);
if (cached) return { id: cached.id, name: cached.name, tickSize: cached.tickSize };
// Fallback: use suggest API directly (first call before resolver has run)
// If the cache is cold, resolve on demand with the same logic the settings page uses.
const resolved = await resolveContracts([productName], this.accessInfo.accessToken);
const contract = resolved[productName];
if (contract) {
return { id: contract.id, name: contract.name, tickSize: contract.tickSize };
}
// Last resort: fall back to Tradovate's ordered suggestions.
const res = await axios.get(
`https://demo.tradovateapi.com/v1/contract/suggest?t=${encodeURIComponent(productName)}&l=20`,
{ headers: { Authorization: `Bearer ${this.accessInfo.accessToken}` } }
);
const contracts: Array<{ id: number; name: string; status: string; providerTickSize: number }> = res.data ?? [];
// Front-month = first contract whose name starts with the product symbol (results are ordered front→back)
const match = contracts.find((c) => c.name.startsWith(productName));
if (!match) return null;
return { id: match.id, name: match.name, tickSize: match.providerTickSize ?? 0.25 };