API Reference

Automation

Rules that run by themselves: a condition checked every trading day, and an action when it is true.

On this page
  1. Set and Cancel Automations
    1. set-automation
    2. cancel-automation
  2. Inspect Automations
    1. print-automation-list
    2. print-automation-history
  3. Note: Automations Are Independent

An automation is a condition paired with an action. The backtester checks every automation's condition on each trading day, at the end of next-date, and runs the action when the condition is true. Automations make stop-loss and take-profit orders, or any other rule, run by themselves while your strategy steps through time.

The example on this page is the automation.clj worksheet, which runs on the bundled sample dataset.

Set and Cancel Automations

set-automation

Register an automation.

ArgumentTypeFunctionRemarks
conditionFunctionA function of no arguments, checked every trading dayWrap it in condition so that print-automation-list can show its source.
actionFunctionA function of no arguments, run when the condition returns trueWrap it in action, likewise. Orders placed by the action fill on the next trading day, as usual.
[:max-dispatch]IntegerHow many times the action may runBy default, unlimited. The automation is removed once used up.
[:expiration]IntegerNumber of trading days after today the automation stays activeBy default, it never expires.

Return

The automation's id, an integer.

Example

Buy 100 shares of AAA, then protect the position: a stop-sell if the price falls under $49, and a limit-sell to take profit above $52. Each fires at most once.

(order "10001" 100 :print true)

(defn stop-sell
  "Sell qty shares once the price falls below prc."
  [permno prc qty]
  (set-automation
   (condition #(when-let [price (get-permno-price permno)] (< price prc)))
   (action #(order permno (- qty) :print true))
   :max-dispatch 1))

(defn limit-sell
  "Sell qty shares once the price rises above prc."
  [permno prc qty]
  (set-automation
   (condition #(when-let [price (get-permno-price permno)] (> price prc)))
   (action #(order permno (- qty) :print true))
   :max-dispatch 1))

(stop-sell "10001" 49 100)
(limit-sell "10001" 52 100)
;; => 2

cancel-automation

Remove an automation.

ArgumentTypeFunctionRemarks
idIntegerThe id returned by set-automation

Return

true

Example

(cancel-automation 1)
;; => true

init-portfolio removes all automations.

Inspect Automations

Print the active automations in a table.

(print-automation-list)
| :id |                                                          :condition |                                     :action | :max-dispatch | :expire-date |
|-----+---------------------------------------------------------------------+---------------------------------------------+---------------+--------------|
|   1 | (fn* [] (when-let [price (get-permno-price permno)] (< price prc))) | (fn* [] (order permno (- qty) :print true)) |             1 |        Never |
|   2 | (fn* [] (when-let [price (get-permno-price permno)] (> price prc))) | (fn* [] (order permno (- qty) :print true)) |             1 |        Never |

Print the days on which automations ran. Takes an optional number of rows, like print-order-record.

Running the example for 30 trading days:

(dotimes [_ 30]
  (next-date))
Order: 1990-01-03 | 10001 | 100.000000.
Automation 2 dispatched.
Order: 1990-01-19 | 10001 | -100.000000.
Automation 1 dispatched.
Order: 1990-01-30 | 10001 | -100.000000.
(print-automation-history)
|      :date | :automation |
|------------+-------------|
| 1990-01-18 |           2 |
| 1990-01-29 |           1 |

Note: Automations Are Independent

The price first rose above $52, so the limit-sell (automation 2) sold the 100 shares. Later it fell below $49, and the stop-sell (automation 1) sold 100 shares again. Since the portfolio no longer held any, that second sale opened a short position:

(print-order-record)
|      :date | :permno | :price | :aprc | :quantity |
|------------+---------+--------+-------+-----------|
| 1990-01-03 |   10001 |  50.81 | 50.81 |     100.0 |
| 1990-01-19 |   10001 |  51.85 | 51.85 |    -100.0 |
| 1990-01-30 |   10001 |  47.77 | 47.77 |    -100.0 |
(print-portfolio)
| :asset | :price |   :aprc | :quantity | :tot-val |
|--------+--------+---------+-----------+----------|
|   cash |    N/A |     N/A |       N/A | 14881.00 |
|  10001 |  48.01 | 48.0100 |    -100.0 | -4801.00 |

Automations do not know about each other. To make a pair where one cancels the other, cancel it in the action, or sell with (order permno 0 :remaining true), which only closes whatever position is left:

(action #(order "10001" 0 :remaining true :print true))