Дополню чуть чуть по архитектуре, чисто инженерное без других подробностей. Возможно будет комуто полезно на потом. Зачем вся эта нагрузка на хранение и почему я к этому пришел. Стоит учитывать, что я тупой и ленивый по сравнению с крутыми ребятами, хотя и есть определенная командная экспертиза в ит решениях. Возможно покритикуете или дадите совет, если уже на следующем уровне. Есть доступ к серверам и видяхам в простое, поэтому возможно архитектура сейчас переусложнена ради будущих возможностей. Это только часть системы для другого рабочего продукта, может быть слишком оверповеред на будущее, но обьясню просто на примере пересечения машек с различными периодами. Основной язык питон, маленько cpp и go. Таймфрейм это не минутки точно из-за времени расчетов и общения воркеров. Часы и дни успевает даже в одно ядро локально без воркеров, остальные таймфремы ниже зависит от нагрузки и ресурсов.
В начале я как все в риалтайме считал параметры, что то с ними делал, получал решение, бектестил и тд. Для МЛ, возпроизводимости и контроля ошибок начал записывать данные и версионировать. Если сделать ансамбль решений на основе данных машек и скажем данных из другого инструмента, получится очень много выходных данных. Плюс они повторяются в расчетах. Для ускорения расчетов очень помогает цитонирование питона или переписывание кода в подключаемую .cpp библиотеку. Это увеличивает скорость до 12 раз. Возникла комбинаторная сложность от пересечений, время обработки увеличилось, в метрики не укладывались. Для того, чтобы не считать каждый раз, сделал такого рода ацикличный граф, те заранее считаю нужные данные и отдаю только цифру по ключу. В итоге пришел к решению, что сначала считаю все нужные узлы и пути этого графа. Потом данные сохраняю в базу. Такой мини даталейк получился.
Воркер кода решения по пайплайну запускается в кубере, считает какието свои там расчеты, по окончанию отдает результат в хранение. Если решению нужны данные, воркер хранения его запрашивает(сейчас в бд и на диске), хранит какоето время в памяти или на диске, отдает по ключу какую либо цифру. По истечению памяти вытесняется, другими данными.
Для определенной скажем свечи, тика или даты, есть свой составной ид хранения, в который входит интрумент, группа, тайфрейм и прочее такое, они разбиты по базам, отдельным таблсетам по скорости, некоторые базы фактически в памяти.
Звучит как работа для хадуп кластера или чегото похожего, пока все на коленке. Пробовали в различных вариациях хранить в json и .pickle файлах, бинарных данных, проблемы с инодами при хранении, вернулись к изначальным базам, как единым точкам хранения. Данные растут и усложняются, не хватает скорости и дисков.
Каждый ид занимает кучу данных, внутри скажем 40к параметров на ид, в целом есть и больше при подгонке теста параметра. Постгрес слабо сжимает данные от 2кб, этого не достаточно.
Пришли к тому, раз все равно данные отдаются из памяти обычно и запрашиваются из базы не частно, просто жмем сериализованный словарь значений гзипом и пишем в базу. Получается строка размеров 2-10мб на ключ. Когда место в хранилище переходит на нескольок ТБ, тогда удаляю старое. Когда чистится от старых данных, потом вакум и подтормаживание.
Все свелось к key[]->value[], скорость зависит от доступных ресурсов.