let trades = load("trades.csv")
from trades select where symbol == "AAPL" and size > 1000
Empirical uses type providers and automatic compile-time function evaluation to sample the CSV file and infer a type ahead of time. The above can be run in a REPL or in a stand-alone script and the result is statically typed! (There is no "gradual" or "optional" types; it is fully static.)Empirical has generic types, which is a syntactic sugar for templates. Here is an example of a five-minute volume-weighted average price (VWAP):
func wavg(ws, vs) = sum(ws * vs) / sum(ws)
from trades select vwap = wavg(size, price) by symbol, bar(timestamp, 5m)
I created Empirical for time-series analysis (I work in finance) and began with the question, "What if q/kdb+ were more like Haskell?" The result is very different from either language, but I wanted to make table actions feel dynamic even though they are fully static.To run a script that takes a command-line argument for the location of the CSV file, just supply the type ahead of time since there isn't a compile-time path to the file.
data Trade:
symbol: String,
timestamp: Timestamp,
price: Float64,
size: Int64
end
let trades = csv_load{Trade}(argv[1])
Feel free to try it out.