%%html
<style>
body {
font-family: "Arial", cursive, sans-serif; # font style of application
}
pre {
font-family: "Courier New"; # font style of cell outputs
}
</style>
Syntax error compiling at (REPL:0:0). Unable to resolve symbol: %%html in this context Syntax error compiling at (REPL:0:0). Unable to resolve symbol: <style> in this context Syntax error compiling at (REPL:0:0). Unable to resolve symbol: body in this context Syntax error reading source at (REPL:4:17). Invalid token: font-family:
Util.java: 221 clojure.lang.Util/runtimeException LispReader.java: 412 clojure.lang.LispReader/interpretToken LispReader.java: 305 clojure.lang.LispReader/read LispReader.java: 1398 clojure.lang.LispReader/readDelimitedList LispReader.java: 1355 clojure.lang.LispReader$MapReader/invoke LispReader.java: 285 clojure.lang.LispReader/read core.clj: 3768 clojure.core$read/invokeStatic core.clj: 3741 clojure.core$read/invoke main.clj: 433 clojure.main$repl$read_eval_print__9086$fn__9087/invoke main.clj: 432 clojure.main$repl$read_eval_print__9086/invoke main.clj: 458 clojure.main$repl$fn__9095/invoke main.clj: 368 clojure.main$repl/doInvoke RestFn.java: 1523 clojure.lang.RestFn/invoke AFn.java: 22 clojure.lang.AFn/run AFn.java: 22 clojure.lang.AFn/run Thread.java: 844 java.lang.Thread/run
; import libraries from kernel
(ns clojure-backtesting.demo
(:require [clojure.test :refer :all]
[oz.notebook.clojupyter :as oz]
[clojure-backtesting.data :refer :all]
[clojure-backtesting.order :refer :all]
[clojure-backtesting.evaluate :refer :all]
[clojure-backtesting.plot :refer :all]
[clojure-backtesting.counter :refer :all]
;;[clojure-backtesting.parameters :refer :all]
[clojure.string :as str]
[clojure.pprint :as pprint]
[java-time :as t]
[clojupyter.kernel.version :as ver]
[clojupyter.misc.helper :as helper]
) ;; require all libriaries from core
(:use clojure.pprint)
)
nil
; path to dataset = "../resources/CRSP-extract.csv"
; change it to the relative to your own dataset
;
(reset! data-set (add-aprc (read-csv-row "../resources/CRSP-extract.csv")));
;; initialise with current date and initial capital (= $10000)
(init-portfolio "1980-12-16" 10000);
The following code implements a simple trading strategy:
In a timespan of 10 days (inclusive of today),
;; define the "time span", i.e. to trade in the coming 10 days
(def num-of-days (atom 10))
(while (pos? @num-of-days)
(do
;; write your trading strategy here
(if (= 10 @num-of-days)
(do
(order "AAPL" 50) ; buy 50 stocks
(println ((fn [date] (str "Buy 50 stocks of AAPL on " date)) (get-date)))
)
)
(if (odd? @num-of-days)
(do
(order "AAPL" -10) ; sell 10 stocks
(println ((fn [date] (str "Sell 10 stocks of AAPL on " date)) (get-date)))
)
)
(update-eval-report (get-date))
; move on to the next trading day
(next-date)
; decrement counter
(swap! num-of-days dec)
)
)
; check whether counter == 0
(println ((fn [counter] (str "Counter: " counter)) @num-of-days))
Buy 50 stocks of AAPL on 1980-12-16 Sell 10 stocks of AAPL on 1980-12-17 Sell 10 stocks of AAPL on 1980-12-19 Sell 10 stocks of AAPL on 1980-12-23 Sell 10 stocks of AAPL on 1980-12-26 Sell 10 stocks of AAPL on 1980-12-30 Counter: 0
nil
(pprint/print-table (deref order-record))
| :date | :tic | :price | :quantity | :reference | |------------+------+---------+-----------+------------| | 1980-12-17 | AAPL | 25.9375 | 50 | 1 | | 1980-12-18 | AAPL | 26.6875 | -10 | 1 | | 1980-12-22 | AAPL | 29.6875 | -10 | 1 | | 1980-12-24 | AAPL | 32.5625 | -10 | 1 | | 1980-12-29 | AAPL | 36.0625 | -10 | 1 | | 1980-12-31 | AAPL | 34.1875 | -10 | 1 |
nil
;; view final portfolio
(view-portfolio)
| :asset | :price | :aprc | :quantity | :tot-val | |--------+---------+-------+-----------+----------| | cash | N/A | N/A | N/A | 10295 | | AAPL | 34.1875 | 29.42 | 0 | 0 |
nil
;; view portfolio value and return
(view-portfolio-record)
| :date | :tot-value | :daily-ret | :loan | :leverage | |------------+------------+------------+-------+-----------| | 1980-12-16 | $10000 | 0.00% | $0.00 | 0.00% | | 1980-12-17 | $10007 | 0.00% | $0.00 | 0.00% | | 1980-12-18 | $10026 | 0.00% | $0.00 | 0.00% | | 1980-12-22 | $10096 | 0.01% | $0.00 | 0.00% | | 1980-12-24 | $10168 | 0.01% | $0.00 | 0.00% | | 1980-12-29 | $10254 | 0.01% | $0.00 | 0.00% | | 1980-12-31 | $10295 | 0.00% | $0.00 | 0.00% |
nil
(eval-report)
| :date | :pnl-pt | :ret-da | :ret-r | :ret-tot | :sharpe-e | :sharpe-r | :tot-val | :vol-e | :vol-r | |------------+---------+---------+--------+----------+-----------+-----------+----------+--------+--------| | 1980-12-16 | $7 | 0.08% | 0.00% | 0.08% | 1.41% | 0.22% | $10007 | 0.06% | 0.01% | | 1980-12-17 | $13 | 0.19% | 0.01% | 0.27% | 2.81% | 0.45% | $10026 | 0.10% | 0.02% | | 1980-12-18 | $13 | 0.19% | 0.01% | 0.27% | 2.81% | 0.45% | $10026 | 0.10% | 0.02% | | 1980-12-19 | $32 | 0.70% | 0.00% | 0.96% | 3.07% | 0.10% | $10096 | 0.31% | 0.05% | | 1980-12-22 | $32 | 0.70% | 0.00% | 0.96% | 3.07% | 0.10% | $10096 | 0.31% | 0.05% | | 1980-12-23 | $42 | 0.71% | 0.01% | 1.67% | 4.88% | 0.11% | $10168 | 0.34% | 0.05% | | 1980-12-24 | $42 | 0.71% | 0.01% | 1.67% | 4.88% | 0.11% | $10168 | 0.34% | 0.05% | | 1980-12-26 | $50 | 0.84% | 0.01% | 2.51% | 6.80% | 0.09% | $10254 | 0.37% | 0.06% | | 1980-12-29 | $50 | 0.84% | 0.01% | 2.51% | 6.80% | 0.09% | $10254 | 0.37% | 0.06% | | 1980-12-30 | $49 | 0.40% | 0.01% | 2.91% | 8.62% | 0.10% | $10295 | 0.34% | 0.05% |
nil
Below are example codes that show how to plot different variables in the portfolio record / evaluation record.
(def data (deref portfolio-value))
#'clojure-backtesting.demo/data
; Add legend name to series
(def data-to-plot
(map #(assoc % :plot "portfolio")
data))
#'clojure-backtesting.demo/data-to-plot
(first data-to-plot)
{:date "1980-12-16", :tot-value 10000, :daily-ret 0.0, :loan 0.0, :leverage 0.0, :plot "portfolio"}
(plot-general data-to-plot :plot :date :daily-ret)
(def data (deref eval-record))
#'clojure-backtesting.demo/data
(first data)
{:date "1980-12-16", :pnl-pt 7.806415917975755, :ret-da 0.07803370496319298, :ret-r 0.0019683764070455023, :ret-tot 7.803370496319297E-4, :sharpe-e 1.4142135623730954, :sharpe-r 0.22471944370971253, :tot-val 10007.806415917976, :vol-e 0.05517816194058409, :vol-r 0.00875926165778608}
; Add legend name to series
(def data-to-plot
(map #(assoc % :plot "volatility")
data))
#'clojure-backtesting.demo/data-to-plot
(eval-report)
| :date | :pnl-pt | :ret-da | :ret-r | :ret-tot | :sharpe-e | :sharpe-r | :tot-val | :vol-e | :vol-r | |------------+---------+---------+--------+----------+-----------+-----------+----------+--------+--------| | 1980-12-16 | $7 | 0.08% | 0.00% | 0.08% | 1.41% | 0.22% | $10007 | 0.06% | 0.01% | | 1980-12-17 | $13 | 0.19% | 0.01% | 0.27% | 2.81% | 0.45% | $10026 | 0.10% | 0.02% | | 1980-12-18 | $13 | 0.19% | 0.01% | 0.27% | 2.81% | 0.45% | $10026 | 0.10% | 0.02% | | 1980-12-19 | $32 | 0.70% | 0.00% | 0.96% | 3.07% | 0.10% | $10096 | 0.31% | 0.05% | | 1980-12-22 | $32 | 0.70% | 0.00% | 0.96% | 3.07% | 0.10% | $10096 | 0.31% | 0.05% | | 1980-12-23 | $42 | 0.71% | 0.01% | 1.67% | 4.88% | 0.11% | $10168 | 0.34% | 0.05% | | 1980-12-24 | $42 | 0.71% | 0.01% | 1.67% | 4.88% | 0.11% | $10168 | 0.34% | 0.05% | | 1980-12-26 | $50 | 0.84% | 0.01% | 2.51% | 6.80% | 0.09% | $10254 | 0.37% | 0.06% | | 1980-12-29 | $50 | 0.84% | 0.01% | 2.51% | 6.80% | 0.09% | $10254 | 0.37% | 0.06% | | 1980-12-30 | $49 | 0.40% | 0.01% | 2.91% | 8.62% | 0.10% | $10295 | 0.34% | 0.05% |
nil
(plot-eval-record data-to-plot :plot :date :vol-e)
; Add rename legend
(def data-to-plot
(map #(assoc % :plot "sharpe ratio")
data))
(plot-eval-record data-to-plot :plot :date :sharpe-e)
(def data (deref order-record))
#'clojure-backtesting.demo/data
(first data)
{:date "1980-12-17", :tic "AAPL", :price 25.9375, :quantity 50, :reference 1}
; Add rename legend
(def data-to-plot
(map #(assoc % :plot "price")
data))
(plot-eval-record data-to-plot :plot :date :price)