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>
This commit is contained in:
Senofy
2026-03-12 03:17:09 -05:00
co-authored by Claude Sonnet 4.6
parent 881c210366
commit d945e0038f
7 changed files with 400 additions and 20 deletions
+7
View File
@@ -512,6 +512,13 @@ 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');
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)
const res = await axios.get(
`https://demo.tradovateapi.com/v1/contract/suggest?t=${encodeURIComponent(productName)}&l=20`,
{ headers: { Authorization: `Bearer ${this.accessInfo.accessToken}` } }