diff --git a/src/agent/backtestRunner.ts b/src/agent/backtestRunner.ts index e91de2c..7f7a3e0 100644 --- a/src/agent/backtestRunner.ts +++ b/src/agent/backtestRunner.ts @@ -3,7 +3,7 @@ import { loadConfig } from "../config/loader.js"; import { getDb } from "../storage/db.js"; import { getBacktestBroker } from "../broker/index.js"; import { getStockOhlcv, getIndexOhlcv, type Bar } from "../data/sources/dnsePublic.js"; -import { DISCOVERY_UNIVERSE, discoverTickers } from "../tools/discover.js"; +import { DISCOVERY_UNIVERSE, discoverTickers, mapLimit } from "../tools/discover.js"; import { setActiveAsOf } from "./clock.js"; import { runTeamAnalysis } from "./team/index.js"; import type { FinalDecision, TeamEvent } from "./team/state.js"; @@ -259,10 +259,12 @@ export async function runBacktestSession( const fetchFrom = startSec - 7 * 86400; const fetchTo = endSec + 7 * 86400; const bars: Record = {}; - for (const t of universe) { + + await mapLimit(universe, 10, async (t) => { bars[t] = await getStockOhlcv(t, "30", fetchFrom, fetchTo); if (cb.signal?.aborted) throw new Error("aborted"); - } + }); + const vnindex = await getIndexOhlcv("VNINDEX", "30", fetchFrom, fetchTo); const intervalTurns = intervalCloses(vnindex, startSec, endSec, interval.minutes); diff --git a/src/data/sources/dnsePublic.ts b/src/data/sources/dnsePublic.ts index 151733c..3fb4f31 100644 --- a/src/data/sources/dnsePublic.ts +++ b/src/data/sources/dnsePublic.ts @@ -47,7 +47,7 @@ async function fetchOhlcs( export function seriesToBars(s: OhlcvSeries): Bar[] { const out: Bar[] = []; - for (let i = 0; i < s.t.length; i++) { + for (let i = 0; i < (s.t?.length || 0); i++) { if (s.c[i] == null) continue; // skip empty intraday slots out.push({ time: s.t[i]!, diff --git a/src/tools/discover.ts b/src/tools/discover.ts index 413e476..4f7b9a2 100644 --- a/src/tools/discover.ts +++ b/src/tools/discover.ts @@ -285,7 +285,7 @@ async function resolveUniverse( return { universe: "all_listed", tickers: await listedTickers(["HOSE", "HNX", "UPCOM"]) }; } -async function mapLimit( +export async function mapLimit( items: readonly T[], concurrency: number, fn: (item: T) => Promise,