Use resolved active contracts for orders
This commit is contained in:
@@ -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
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user