Fix contract resolver: use Yahoo continuous contract price matching

Replace volume-based contract selection with Yahoo Finance continuous
contract price matching ({PRODUCT}=F). The old approach compared volumes
across front/roll candidates, which failed when serial months had
deceptive volume (6EJ26 > 6EM26) or Yahoo was rate-limited (all 0s).

Now fetches the continuous contract price and matches it against
candidates within 0.1% tolerance. Falls back to roll1 if Yahoo fails.
Also adds User-Agent header to avoid 429 rate limiting.

Verified: GC=F price matches GCM26, 6E=F price matches 6EM26.

Also fixes stale 'Random' comment in auto-trade.ts and cleans up
frontVolume/rolledVolume references from settings page.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Brandon Li
2026-03-30 18:19:51 -05:00
co-authored by Claude Opus 4.6
parent 9a24692c1a
commit 4025ed2f41
4 changed files with 102 additions and 86 deletions
+2 -9
View File
@@ -11,8 +11,6 @@ interface Instrument {
interface ResolvedContract {
name: string;
alternative?: string;
frontVolume?: number;
rolledVolume?: number;
}
interface AppSettings {
@@ -238,7 +236,7 @@ export default function SettingsPage() {
<tbody>
{instruments.map((instr) => {
const c = contracts[instr.symbol];
const wasRolled = c?.alternative && c.rolledVolume != null && c.frontVolume != null && c.rolledVolume > c.frontVolume;
const wasRolled = !!c?.alternative;
return (
<tr key={instr.symbol} className="border-b border-slate-100 last:border-0">
<td className="px-4 py-2.5 font-mono font-semibold text-slate-800">
@@ -250,14 +248,9 @@ export default function SettingsPage() {
<span className={`font-mono text-sm ${wasRolled ? 'text-amber-600 font-semibold' : 'text-slate-600'}`}>
{c.name}
</span>
{c.frontVolume != null && c.rolledVolume != null && (
<span className="text-xs text-slate-400">
vol {Math.max(c.frontVolume, c.rolledVolume).toLocaleString()}
</span>
)}
{wasRolled && (
<span className="text-xs bg-amber-100 text-amber-700 px-1.5 py-0.5 rounded font-medium">
rolled
rolled from {c.alternative}
</span>
)}
</div>