You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
High-performance columnar time-series database for quantitative finance
kdb+ functionality • Pythonic API • Zero-copy NumPy • SIMD-accelerated
WayyDB is a C++ time-series database with Python bindings, designed for quantitative research and trading systems. It provides kdb+-like temporal join operations with a modern, accessible API—no q language required.
Why WayyDB?
Challenge
WayyDB Solution
kdb+ costs $100K+/year
Open source, free forever
q language learning curve
Pythonic API you already know
Pandas/Polars lack temporal joins
Native aj() and wj() primitives
Memory copies kill performance
Zero-copy NumPy via mmap
Slow aggregations
AVX2/AVX-512 SIMD acceleration
Features
As-of Join (aj) — For each trade, find the most recent quote. O(n log m) via binary search on sorted indices
Window Join (wj) — Get all quotes within a time window around each trade
Zero-copy NumPy — Columns are memory-mapped; to_numpy() returns views, not copies
SIMD Aggregations — Sum, avg, min, max accelerated with AVX2 intrinsics
Window Functions — Moving average, EMA, rolling std with O(n) complexity
Persistent Storage — Tables saved as memory-mapped files for instant loading
Streaming API — FastAPI REST + WebSocket endpoints for real-time tick ingestion and subscription
Pluggable Pub/Sub — InMemory (default) or Redis backend for distributed deployments
Installation
pip install wayy-db
Or build from source:
git clone https://github.com/wayy-research/wayydb.git
cd wayydb
pip install -e .
# For each trade, get the most recent quote for that symbolresult=wdb.ops.aj(trades, quotes, on=["symbol"], as_of="timestamp")
# Result contains trade columns + quote columns (bid, ask)print(result["bid"].to_numpy()) # [149.5, 379.5, 150.5, 380.5, 151.5]
# Create persistent databasedb=wdb.Database("/data/markets")
# Add table (automatically saved)db.add_table(trades)
# Later: reload with zero-copy mmapdb2=wdb.Database("/data/markets")
trades=db2["trades"] # Instant load via memory mapping# Access data without copyingprices=trades["price"].to_numpy() # Zero-copy view into mmap'd file
Pandas/Polars Interop
importpandasaspdimportpolarsaspl# From pandasdf=pd.DataFrame({"timestamp": [...], "price": [...]})
table=wdb.from_pandas(df, name="from_pandas", sorted_by="timestamp")
# From polarsdf=pl.DataFrame({"timestamp": [...], "price": [...]})
table=wdb.from_polars(df, name="from_polars", sorted_by="timestamp")
# To dict (for conversion back)data=table.to_dict() # {"timestamp": np.array, "price": np.array, ...}
API Reference
Core Classes
Class
Description
Database(path="")
Container for tables. Empty path = in-memory
Table(name="")
Columnar table with optional sorted index
Column
Typed column with zero-copy NumPy access
Table Methods
table.num_rows# Number of rowstable.num_columns# Number of columnstable.column_names() # List of column namestable.sorted_by# Column used for temporal ordering (or None)table["col"] # Get column by nametable.to_dict() # Export as {name: np.array} dicttable.save(path) # Save to directoryTable.load(path) # Load from directory (copies data)Table.mmap(path) # Memory-map from directory (zero-copy)
Operations (wayy_db.ops)
Aggregations
Function
Description
sum(col)
Sum of values (SIMD)
avg(col)
Mean of values
min(col)
Minimum value
max(col)
Maximum value
std(col)
Standard deviation
Temporal Joins
Function
Description
aj(left, right, on, as_of)
As-of join: most recent right row for each left row