API Reference

Core API

Load data, start a portfolio, place orders, move the clock and read market data.

On this page
  1. Load Data
    1. load-dataset
  2. Start a Portfolio
    1. init-portfolio
  3. Place Orders
    1. order
    2. end-order
  4. Move Through Time
    1. get-date
    2. next-date
    3. get-next-date
    4. get-prev-n-date
    5. date-after-n-trading-days
  5. Read Market Data
    1. get-info
    2. get-info-map
    3. available-permnos
    4. get-permno-info
    5. get-permno-price
    6. get-permno-by-key
    7. permno-tic and tic-permno
    8. get-prev-n-days
    9. get-prev-n-days-map
    10. get-permno-prev-n-days

These are the functions every strategy uses. The examples run on the bundled sample dataset (see Get Started), mostly with the clock at 1990-01-08. Functions for Yahoo Finance data, fundamentals and portfolio strategies have their own pages: Yahoo Finance Data, Fundamentals and Strategy Helpers.

How to read this page: each function has a table of its arguments, then what it returns and an example. Arguments in [square brackets] are optional. Lines starting with => are what you type at the REPL; the lines below them are what it prints or returns.

Load Data

load-dataset

Load a dataset that has been converted into the backtester's layout (see Data and Trading Rules).

ArgumentTypeFunctionRemarks
dirStringThe path of the dataset directory
role"main" / "compustat"Whether this is the main (CRSP-style) dataset or the supplementary Compustat-style datasetLoad at most one of each.
[func]FunctionA function that augments the dataset when it is loadedPass add-aprc for the main dataset: it adds the adjusted price columns that init-portfolio requires. It rewrites the files in place the first time and does nothing afterwards.

Return

"Date range: {start date} ~ {end date}"

Example

=> (load-dataset "resources/sample-data/main" "main" add-aprc)
The dataset is already furnished by add-aprc. No more modification is needed.
"Date range: 1990-01-02 ~ 1990-03-30"
=> (load-dataset "resources/sample-data/compustat" "compustat")
"Date range: 1989-09-30 ~ 1989-12-31"

To load a dataset built from Yahoo Finance, use load-yahoo-dataset instead: it loads the prices as the main dataset, already furnished with the adjusted prices, together with the fundamentals.

Start a Portfolio

init-portfolio

Set the starting date and capital. Calling it again restarts the backtester: the portfolio, all records, indicators and automations are reset, and orders that have not filled yet are dropped.

ArgumentTypeFunctionRemarks
dateStringThe starting dateIf this date is missing in the dataset (e.g. it is a weekend), the nearest earlier date is used instead. If there is none, the nearest later date. It cannot be the last date of the dataset.
capitalNumberThe initial capitalGiven in the form of cash

Return

"Date: {actual starting date (may be different from date)} Cash: ${capital}"

Example

=> (init-portfolio "1990-01-06" 10000) ;; a Saturday
"Date: 1990-01-05 Cash: $10000"

Remarks

  • Set parameters such as update-output-dir or update-reinvest-dividends before calling init-portfolio (see Parameters).
  • More details about the portfolio can be found here.

Place Orders

order

Buy or sell a number of shares of a security. The order fills at the closing price of the next trading day on which the security has a price (see Trading Logic).

ArgumentTypeFunctionRemarks
securityStringThe target security
quantityNumberPositive means buy, negative means sellThe trading amount, or the target holding when :remaining is true.
[:expiration]IntegerNumber of trading days the order stays pendingBy default, ORDER-EXPIRATION (3).
[:remaining]BooleanWhether quantity is the holding to end up with, rather than the amount to tradeBy default, false. (order "10001" 0 :remaining true) closes the position.
[:leverage]BooleanWhether the order may borrow cash (buying beyond your cash) or shares (short selling)By default, LEVERAGE (true). Borrowing must respect INITIAL-MARGIN.
[:print]BooleanWhether to print the order when it fillsBy default, PRINT (false).
[:direct]BooleanWhether to write the order to out_order_record.csv when it fillsBy default, DIRECT (true). Files are written only when an output directory is set with update-output-dir.

Return

All pending orders, as a map keyed by [expiry date, security].

Example

=> (order "10001" 10)
{["1990-01-11" "10001"] {:place "1990-01-08", :expire "1990-01-11", :permno "10001", :quantity 10, :remaining false, :leverage true, :print false, :direct true}}

=> (order "10002" 5 :remaining true :expiration 5) ;; hold 5 shares of 10002
{["1990-01-11" "10001"] {...}, ["1990-01-15" "10002"] {:place "1990-01-08", :expire "1990-01-15", :permno "10002", :quantity 5, :remaining true, :leverage true, :print false, :direct true}}

end-order

Call this at the end of your strategy. It closes every position at today's closing price, updates the evaluation report once more, closes the CSV files and ends the run; after it, order and next-date do nothing until init-portfolio is called again. A security with no price today is booked as cash at its last value.

The run also ends by itself on the last date of the dataset, when the total value drops below zero, or on a margin call (see Parameters).

Arguments: none

Example

=> (end-order)
true
=> (next-date)
nil

Move Through Time

The backtester has a date pointer that acts as its global clock. You can move it forward but not back, and you only see market information up to "today", never the future (see Key Concepts). The functions below read or move the date pointer.

get-date

Get today's date.

Arguments: none

Return

A string representing the current date.

Example

=> (get-date)
"1990-01-05"

next-date

Move the date pointer forward to the next trading day in the dataset, skipping weekends and holidays. On the new day it revalues the holdings, charges loan interest, checks the margin, fills pending orders and runs automations.

Arguments: none

Return

The new date. nil once the run has ended (through end-order, a margin call, or reaching the last date of the dataset).

Example

=> (next-date)
"1990-01-08"

get-next-date

Get the next trading day without moving the date pointer.

Arguments: none

Return

A date string, or nil on the last date of the dataset.

Example

=> (get-date)
"1990-01-05"
=> (get-next-date)
"1990-01-08"

get-prev-n-date

Get the date n trading days before the current date (skipping weekends and holidays).

ArgumentTypeFunctionRemarks
nPositive IntegerNumber of days to look back

Return

A date string, or nil if the search passes the first date of the dataset.

Example

=> (get-date)
"1990-01-08"
=> (get-prev-n-date 3)
"1990-01-03"

date-after-n-trading-days

Get the date n trading days after a given date.

ArgumentTypeFunctionRemarks
dateStringThe date to count from
nPositive IntegerNumber of days to look ahead

Return

A date string, or the last date of the dataset if fewer than n trading days remain.

Example

=> (date-after-n-trading-days "1990-01-08" 3)
"1990-01-11"

Read Market Data

Each row is a map keyed by the dataset's column names (see Essential column names). When a Compustat dataset is loaded, the rows also contain the Compustat columns of the matching filing.

get-info

Get all the market information for today, as a sequence of maps. There is also get-info-map, a format better suited to looking up a specific security.

Arguments: none

Return

A sequence of maps, one per security that trades today.

Example

=> (get-info)
[{:ASKHI 50.58, :CUM-RET -0.005342844410495502, :date "1990-01-08", :INIT-PRICE 50.67, :OPENPRC 50.49, :TICKER "AAA", :APRC 50.4, :BIDLO 50.28, :RET 5.955926146516966E-4, :CFACPR 1.0, :PRC 50.4, :PERMNO "10001"} {:ASKHI 116.79, :CUM-RET -0.02671833211289444, :date "1990-01-08", :INIT-PRICE 118.72, :OPENPRC 116.37, :TICKER "BBB", :APRC 115.58999999999999, :BIDLO 114.99, :RET -0.011544381734222675, :CFACPR 2.0, :PRC 115.59, :PERMNO "10002"} {:ASKHI 20.11, :CUM-RET -0.013965314248641295, :date "1990-01-08", :INIT-PRICE 20.19, :OPENPRC 20.03, :TICKER "CCC", :APRC 19.91, :BIDLO 19.9, :RET -0.00945273631840804, :CFACPR 1.0, :PRC 19.91, :PERMNO "10003"}]

get-info-map

Get all the market information for today, as a map from security to its information.

Arguments: none

Return

A map whose keys are all the securities available today.

Example

=> (get-info-map)
{"10001" {:ASKHI 50.58, :CUM-RET -0.005342844410495502, :date "1990-01-08", :INIT-PRICE 50.67, :OPENPRC 50.49, :TICKER "AAA", :APRC 50.4, :BIDLO 50.28, :RET 5.955926146516966E-4, :CFACPR 1.0, :PRC 50.4, :PERMNO "10001"}, "10002" {...}, "10003" {...}}

available-permnos

Get all securities available today.

Arguments: none

Return

A sequence of permno strings.

Example

=> (available-permnos)
("10001" "10002" "10003")

get-permno-info

Get the information for a security.

ArgumentTypeFunctionRemarks
[date]StringThe date to look upBy default, today.
permnoStringThe security

Return

A map of information if the security has data on that date, otherwise nil.

Example

=> (get-permno-info "10001")
{:ASKHI 50.58, :CUM-RET -0.005342844410495502, :date "1990-01-08", :INIT-PRICE 50.67, :OPENPRC 50.49, :TICKER "AAA", :APRC 50.4, :BIDLO 50.28, :RET 5.955926146516966E-4, :CFACPR 1.0, :PRC 50.4, :PERMNO "10001"}

=> (get-permno-info "99999")
nil

get-permno-price

Like get-permno-info, but get only the price of the security (the closing price, or the opening price if PRICE-KEY is changed).

ArgumentTypeFunctionRemarks
[date]StringThe date to look upBy default, today.
permnoStringThe security

Return

A number, or nil if the security has no data on that date.

Example

=> (get-permno-price "10001")
50.4
=> (get-permno-price "1990-01-03" "10001")
50.81

get-permno-by-key

Like get-permno-info, but get the value of one key.

ArgumentTypeFunctionRemarks
[date]StringThe date to look upBy default, today.
permnoStringThe security
keyKeywordThe keyOne of the dataset's columns

Return

The value, of a type depending on the key, if the map contains the key, otherwise nil.

Example

=> (get-permno-by-key "10001" :TICKER)
"AAA"
=> (get-permno-by-key "10001" :None)
nil

permno-tic and tic-permno

Translate between security identifiers and ticker symbols, using today's data (needs a :TICKER column).

Example

=> (permno-tic "10001")
["AAA"]
=> (tic-permno "AAA")
["10001"]

get-prev-n-days

Get the information of the past n trading days (not including today).

ArgumentTypeFunctionRemarks
[n]Positive IntegerThe number of days to look backIf not given, return a lazy sequence of all previous days.
The result may be shorter than n if it reaches the first date of the dataset.

Return

A sequence (length <= n) of sequences of maps (one per security), in descending time order, i.e. the most recent date first.

Example

=> (map #(map :PERMNO %) (get-prev-n-days 2))
(("10001" "10002" "10003") ("10002" "10001" "10003"))

;; a common way to get the information of the past n days including today:
=> (conj (get-prev-n-days (- n 1)) (get-info))

get-prev-n-days-map

Like get-prev-n-days, but each day is a map from security to its information, as in get-info-map.

Example

=> (map keys (get-prev-n-days-map 2))
(("10001" "10002" "10003") ("10002" "10001" "10003"))

get-permno-prev-n-days

Get the information of a security for the past n trading days (not including today).

ArgumentTypeFunctionRemarks
permnoStringThe security
nPositive IntegerThe number of days to look backIf the security is absent on some of these days, the result is shorter than n.

Return

A sequence (length <= n) of maps, in descending time order, i.e. the most recent date first.

Example

=> (get-permno-prev-n-days "10001" 2)
({:ASKHI 50.55, :CUM-RET -0.00593825973025941, :date "1990-01-05", :INIT-PRICE 50.67, :OPENPRC 50.06, :TICKER "AAA", :APRC 50.36999999999999, :BIDLO 49.91, :RET 0.0029868578255674016, :CFACPR 1.0, :PRC 50.37, :PERMNO "10001"} {:ASKHI 50.89, :CUM-RET -0.0089206657583795, :date "1990-01-04", :INIT-PRICE 50.67, :OPENPRC 50.83, :TICKER "AAA", :APRC 50.22, :BIDLO 50.05, :RET -0.011611887423735534, :CFACPR 1.0, :PRC 50.22, :PERMNO "10001"})

;; a common way to get the information of the past n days including today:
=> (conj (get-permno-prev-n-days "10001" (- n 1)) (get-permno-info "10001"))
({today's info} {yesterday's info} ...)