Data Connector
In-memory кэш
Parquet читается с диска один раз при первом запросе. Последующие запросы — только срез в памяти.
Инвалидация автоматическая: кэш сбрасывается при изменении mtime файла. Это означает, что после prefetch.py следующий запрос перечитает файл. Данные всех инструментов хранятся независимо — _cache["EURUSD"], _cache["GBPUSD"] и т.д.
Срез по диапазону
Срез делается через df.loc[ts_from:ts_to], а не через boolean-маску.
На отсортированном DatetimeIndex это searchsorted (бинарный поиск, O(log N)), а не итерация по всем строкам (O(N)).
Для 10 лет M1 (~3.6 млн баров) разница: ~0.1 мс против ~50 мс.
data_start_ts / data_end_ts
Берутся из m1.index[0] и m1.index[-1] — полный M1-кэш до фильтра. Глобальные границы данных, не зависят от запроса. Нужны для infinite history (reachedStart).
Ресэмплинг: label="left", closed="left"
Бар H1 с меткой 09:00 содержит минуты [09:00, 09:59] включительно. closed="left" означает, что граница 10:00 уже принадлежит следующему бару. Это стандарт финансовых данных — время бара = момент открытия.
При from_ts/to_ts M1 фильтруется по диапазону, затем к результату применяется limit (.tail(limit)).