summaryrefslogtreecommitdiff
path: root/scripts/paper-trade-test.scm
blob: 29d12185481f257d7a84649891a1aa903e1270b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
(use-modules (ibkr api) (ibkr types)
	     (json)
	     (srfi srfi-1) (srfi srfi-64)
	     (ice-9 format))

;; connect
(display "connecting to ibkr api\n")
(define base "http://localhost:5000")
(format #t "connected: ~a\n" (auth-status-connected (auth-status base)))
(sleep 1)

;; check mkt
(display "querying market data\n")
(define ibkr (contract-for-stock-ticker base "IBKR" "NASDAQ"))
(define ibkr-id (contract-id ibkr))
(define ibkr-ref-px (contract-snapshot base ibkr-id 'last-trade))
(format #t "contract-id(IBKR)=~a\n" ibkr-id)
(format #t "last-trade(IBKR)=$~a\n" ibkr-ref-px)
(sleep 1)

;; acct info
(display "querying account info\n")
(define accts (accounts base))
(define acct (car accts))
(define acct-id (account-id acct))
(define pos-t0 (positions base acct-id))
(define bal-t0 (ledger-cash-balance (ledger base acct-id "USD")))
(format #t "balance(t0)=$~a\n" bal-t0)
(format #t "account-type=~a\n" (account-type acct))
(if (not (equal? (account-type acct) "DEMO"))
    (exit 1))
(sleep 1)

;; buy
(define buy (make-order acct-id ibkr-id "MARKET" "BUY" "IOC" 10.0))
(format #t "buy-order=~a\n" buy)
(define buy-preview (order-preview base acct-id buy))
(format #t "buy-preview=~a\n" buy-preview)
(define buy-warning (order-submit base acct-id buy)) ;; no market data?
(format #t "buy-warning=~a\n" buy-warning)
(define buy-reply (order-confirm base (order-warning-id buy-warning)))
(format #t "buy-reply=~a\n" buy-reply)
(define buy-oid (order-reply-order-id buy-reply))
(format #t "buy-oid=~a\n" buy-oid)
(format #t "sleeping to wait for fill\n") (sleep 5) ;; wait for fill
(define buy-status (order-status base buy-oid))
(format #t "buy-status=~a\n" buy-status)
(define buy-px (string->number (order-status-average-price buy-status)))
(define buy-qty (string->number (order-status-quantity buy-status)))
(define pos-t1 (positions base acct-id))
(define bal-t1 (ledger-cash-balance (ledger base acct-id "USD")))

(display "sleeping to avoid rate limit\n") (sleep 5)

;; sell
(define sell (make-order acct-id ibkr-id "MARKET" "SELL" "IOC" 10.0))
(format #t "sell-order=~a\n" sell)
(define sell-preview (order-preview base acct-id sell))
(format #t "sell-preview=~a\n" sell-preview)
(define sell-warning (order-submit base acct-id sell)) ;; no market data?
(format #t "sell-warning=~a\n" sell-warning)
(define sell-reply (order-confirm base (order-warning-id sell-warning)))
(format #t "sell-reply=~a\n" sell-reply)
(define sell-oid (order-reply-order-id sell-reply))
(format #t "sell-oid=~a\n" sell-oid)
(format #t "sleeping to wait for fill\n") (sleep 5) ;; wait for fill
(define sell-status (order-status base sell-oid))
(format #t "sell-status=~a\n" buy-status)
(define sell-px (string->number (order-status-average-price sell-status)))
(define sell-qty (string->number (order-status-quantity sell-status)))
(define pos-t2 (positions base acct-id))
(define bal-t2 (ledger-cash-balance (ledger base acct-id "USD")))

;; checks
(define (position poslst contract-id)
  (find
   (lambda (p)
     (equal? (string->number (position-contract-id p)) contract-id))
   poslst))
(define (abs-rel-diff a b) (/ (* 2 (abs (- a b))) (+ (abs a) (abs b))))
(define (within-n-percent n a b) (< (* 100 (abs-rel-diff a b)) n))
(test-begin "paper-trade")
(test-approximate "ibkr-qty-t0" 0 (position-quantity (position pos-t0 ibkr-id)) 1e-3)
(test-approximate "ibkr-qty-t1" 10 (position-quantity (position pos-t1 ibkr-id)) 1e-3)
(test-approximate "ibkr-qty-t2" 0 (position-quantity (position pos-t2 ibkr-id)) 1e-3)
(test-approximate "ibkr-buy-qty" 10 buy-qty 1e-3)
(test-approximate "ibkr-sell-qty" 10 sell-qty 1e-3)
(test-assert "buy-px-close-to-ref-px" (within-n-percent 5 buy-px ibkr-ref-px))
(test-assert "sell-px-close-to-ref-px" (within-n-percent 5 sell-px ibkr-ref-px))

;; don't forget commission!
(test-approximate "bal-t1-expected" (- bal-t0 (* 10.0 buy-px)) bal-t1 1.05)
(test-approximate "bal-t2-expected" (+ bal-t1 (* 10.0 sell-px)) bal-t2 1.05)

(test-end "paper-trade")