Squeeze · system design

Platform Architecture & Tech Stack

Provider adapters collect prices, asset data, news, filings, short interest, fundamentals, alternative data, and general economic data into shared stores. Airflow schedules ingestion and maintenance; Kafka delivers news revisions for processing. A Java query service exports database results as Parquet, and a Python SDK returns them as Polars DataFrames.

System map

Select a path to highlight its components, or select a component for its responsibilities.

Airflow · scheduled ingestion and maintenancePrice jobs · asset data · news · filings · fundamentals · scanner snapshotsAdditional ingestion · alternative data · general economic dataScheduling / job invocationdownloadverify / loadwarehouse SQLParquetDataFramesnormalizeupsertrelational SQLchanged rows¹publish / ackconsumeprocessed revisions + model inputsPrice providerAlpaca · completed datesPrice ingestionPython · Parquet stagingClickHousePrice bars + daily factorsQuery serviceJava · Spring Boot · JDBCPython SDKHTTP → Parquet → PolarsReference & other dataAssets · filings · economic dataEvent ingestionNormalize · identify · upsertPostgreSQLReference · events · processingResearch & modelssq-core · sq-modelsRevision publisherKeyset cursor · acknowledged pagesKafkaKeyed news-revision streamNews processingClean · deduplicate · targetSolid arrows: data movement · dashed arrows: orchestration · ¹ Publisher reads changes via the query service and SDK.
Selected component

PostgreSQL

Holds assets, canonical events, source associations, share/float observations, earnings, scanner snapshots, processed news/model inputs, inference results, and durable operational queues.

Price ingestion and adjustment maintenance

The price path uses staged batch loads. Alpaca supplies raw minute bars and daily price series; task manifests retain ingestion lineage rather than repeating it on every row. Airflow invokes the existing Python jobs.

Certified price ingestion · advancing only after successful validation
  1. DownloadFetch completed historical dates into task-specific temporary Parquet partitions.
  2. ValidateCheck finite positive price fields, OHLC ordering, activity fields, and daily exchange-session dates.
  3. Load & verifyInsert accepted partitions into ClickHouse and verify their database contents.
  4. Reconcile factorsDerive stored daily price/volume adjustment factors from accepted raw and adjusted daily observations.
  5. Certify intervalRun warehouse validation before advancing the incremental completion cursor.
  6. Maintain adjustmentsAudit for corporate-action changes; refresh and verify affected daily histories and factors.
  7. Clean stagingRemove temporary partitions only after the relevant load and maintenance work succeeds.

Airflow task dependency

advance_prices
      ↓
maintain_adjustments
      ↓
cleanup_staging

The incremental job retries its uncommitted date interval after failure. An exclusive staging lock prevents concurrent executable price pipelines from interfering with each other.

Stored series and derived views

Raw M1, raw D1, split-adjusted D1, all-adjusted D1, and daily factors are stored. Other intraday bars aggregate raw minutes at exchange-session boundaries; adjustments are applied after aggregation. Weekly, monthly, and yearly views aggregate the selected daily series.

Corporate-action maintenance preserves raw M1 and targets daily-history corrections and factor rebuilding. Derived VWAP is labeled as estimated rather than canonical vendor VWAP.

Extending the streaming layer to live prices

Architecture extension · not currently a live-price deployment. Kafka is not specific to news. The publisher/topic/consumer boundary can be reused for live market data, while keeping the existing historical price-ingestion and certification path.

Live-price extension · proposed data path
  1. Market-data publisherA live feed adapter validates and timestamps incoming price events.
  2. Price topicsPartition by a stable instrument key to keep each instrument’s events together under a fixed partitioning scheme.
  3. Validation consumersA consumer group checks schemas, duplicates, event times, sequence gaps, and corrections.
  4. Storage consumersBatch accepted bars into ClickHouse with retry-safe writes and explicit handling of bar finality.
  5. Independent groupsFeature builders or alerting applications can consume the stream separately without changing the feed publisher.

What is reusable

Versioned event contracts, keyed publication, acknowledged checkpoints, durable consumer offsets, and idempotent processing already exist in the news path. Separate price topics and groups would let price processing scale independently of article preprocessing.

What live prices still require

A price-event schema and feed publisher; event-time, sequence, late-arrival, correction, and duplicate handling; and integration with the existing canonical bar and adjustment contracts. Topic retention must match replay needs—news compaction settings should not be copied blindly to a price-history stream.

The checked-in Kafka foundation currently starts with one broker, one news partition, and replication factor one. More parallel workers require a deliberate partition plan; resilient multi-broker operation requires replication and capacity planning. Repartitioning also needs an ordering/migration strategy. Load tests, lag monitoring, retention sizing, and recovery verification are needed before claiming live-price throughput or availability.