Commit 5158f0d4 authored by Carlos Ungil's avatar Carlos Ungil
Browse files

Initial commit

parents
Loading
Loading
Loading
Loading

README.md

0 → 100644
+103 −0
Original line number Diff line number Diff line
```
;; tested on Windows (SBCL 64-bit, ClozurCL 32/64-bit, Lispworks 6.0 32-bit)
;; the test suite should run without any errors: (asdf:test-system :bloomie)

(ql:quickload :bloomie)

(bb:open-session)

;; FIELDS

(bb:field-info "MILITARY_REVENUE")
(bb:field-info "M1090")
(bb:field-info '("px_last" "pe_ratio") :documentation nil)

(mapcar #'bb:field-mnemonic (bb:field-search "military"))

(loop for cat in (bb:categorized-field-search "PRESID*")
   do (format t "~&~A :~{ ~A~}" (bb:category-name cat)
	      (loop for fld in (bb:category-fields cat) collect (bb:field-mnemonic fld))))

(length (bb:field-list :type :real-time))
(length (bb:field-list :type :static)) ;; 57k+ fields

;; INSTRUMENTS

(bb:instruments "entropy")
(bb:instruments "entropy" :max-results 5)
(bb:instruments "entropy" :yellow-key :corp)
(bb:instruments "entropy" :yellow-key :indx)

(bb:govt "rome")
(bb:govt "rome" :max-results 1)
(bb:govt "rome" :ticker "ROM")
(bb:govt "rome" :ticker "ROM" :partial-match nil)
(bb:govt "rome" :ticker "ROMCTY" :partial-match nil)

(bb:curve "genev")
(bb:curve "" :curve-id "bi758")
(bb:curve "garch" :currency-code "CHF" :max-results 3)
(bb:curve "" :currency-code :chf :type :irs)
(mapcar #'curve-currency (bb:curve nil :currency-code "jpy" :subtype "spread"))

;; REFERENCE

(bb:bdp '("AAPL US Equity" "MSFT US Equity") '("PX_LAST" "BEST_EPS"))
(bb:bdp '("AAPL US Equity" "MSFT US Equity") '("XXXXXX" "YYYYYY" "PX_LAST"))
(bb:bdp '("AAAAPLE US Equity" "MSFT US Equity") '("XXXXXX" "YYYYYY" "PX_LAST"))
(let ((bb:*raise-all-errors* t))
  (bb:bdp '("AAAAPL US Equity" "MSFT US Equity") '("XXXXXX" "YYYYYY" "PX_LAST")))

;; HISTORICAL

(bb:bdh '("AAPL US Equity" "MSFT US Equity") '("PX_LAST" "VOLUME")
	:start-date "20170501" :end-date "20170510" :periodicity :daily)
(bb:bdh "AAPL US Equity" "PE_RATIO" :start-date "1995-12-31" :periodicity :yearly)

;; INTRADAY BARS

(bb:ibar "AAPL US Equity" "BID" :bar-size '(4 :hour)
	 :start-date-time "2017-08-08" :end-date-time "2017-08-11")
(bb:ibar "AAPL US Equity" "TRADE" :bar-size '(1 :m)
	 :start-date-time "2017-08-08T14" :end-date-time "2017-08-08T14:05")

;; PORTFOLIO

(bb:portfolio-tickers "U12345678-1")
(bb:portfolio-tickers "U12345678-1" "2017-08-04")
(bb:portfolio-weights "U12345678-1")
(bb:portfolio-positions "U12345678-1")
(bb:portfolio-data "U12345678-1")
(bb:portfolio-data "XXX")

;; EQUITY SCREENING

(bb:screen-tickers "Global Automotive Parts Retailers")
(bb:screen-tickers "Global Automotive Parts Retailers" :folder "General")
(bb:screen-tickers "Global Automotive Parts Retailers" :folder "Popular")

;; EARNINGS

(bb:get-earnings-dates "AAPL US")
(bb:get-earnings "AAPL US" :start "2016-12-31")
(bb:get-earnings "AAPL US" :start "2016-12-31" :currency "EUR")

;; PRODUCTS

(loop for ticker in (bb:index-composition "SPX") for prods = (bb:product-list ticker)
   when prods do (format t "~A~10T~A~&" ticker (length prods)))
(bb:product-list "VRTX US")
(bb:product-forecast "VRTX US" "Orkambi")
(bb:product-forecast "VRTX US" "Orkambi" :year '(2017 2018 2019 2020))
(bb:product-forecast "VRTX US" "Orkambi" :year 2020 :source :all)
(bb:product-forecast "VRTX US" "Orkambi" :stat :all)
(bb:product-forecast "VRTX US" "Orkambi" :stat :revisions)

;; EXPORT SCHEMAS AND FIELD DEFINITIONS

(bb:document-schemas) ;; can be incomplete, see function docstring

(bb:document-fields) ;; can be incomplete, see function docstring

(bb:close-session)
```

bloomie.asd

0 → 100644
+39 −0
Original line number Diff line number Diff line
(asdf:defsystem #:bloomie
    :name "bloomie"
    :serial t
    :description "BLPAPI wrapper (http://www.bloomberglabs.com/api/)"
    :author "Carlos Ungil <ungil@mac.com>"
    :license "MIT"
    :serial t
    :in-order-to ((test-op (test-op "bloomie-test")))
    :components ((:module #:ffi :pathname "ffi" :components ((:static-file "blpapi-3.11.1.1.h")))
		 (:file "package")
		 (:file "wrapper")
		 (:file "helper")
		 (:file "session")
		 (:file "values")
		 (:file "element")
		 (:file "response")
		 (:file "request")
		 ;; no CFFI / FLI especific code after this point
		 (:file "tree")
		 (:file "field-info")
		 (:file "instruments")
		 (:file "reference")
		 (:file "historical")
		 (:file "intraday")
		 (:file "screen")
		 (:file "portfolio")
		 (:file "indices")
		 (:file "earnings")
		 (:file "recommendations")
		 (:file "products"))
    :depends-on (:local-time :cl-unification #-lispworks :cl-autowrap #-lispworks :cl-plus-c))

(defsystem #:bloomie-test
    :name "bloomie test suite"
    :author "Carlos Ungil <ungil@mac.com>"
    :license "MIT"
    :depends-on (:bloomie :fiveam)
    :components ((:file "test"))
    :perform (asdf:test-op (o s) (declare (ignore o s)) (uiop:symbol-call :bloomie.test '#:run)))

earnings.lisp

0 → 100644
+22 −0
Original line number Diff line number Diff line
(in-package :bloomie)

(defstruct (eps-announcement (:conc-name eps-))
  period date time reported comparable estimated)

(defun get-earnings (ticker &key start end currency)
  "Returns the fiscal period, date, time and reported/comparable/estimated EPS 
for earnings announcements in the given period. The currency can also be set."
  (loop for (period date time reported comparable estimated)
     in (second (second (first (bdp (format nil "~A Equity" ticker)
				    '("EARN_ANN_DT_TIME_HIST_WITH_EPS")
				    :overrides (append
						(when start `(("START_DT" ,(bbdate start))))
						(when end `(("END_DT" ,(bbdate end))))
						(when currency `(("EQY_FUND_CRNCY" ,currency))))))))
     collect (make-eps-announcement :period period :date date :time time
				    :reported reported :comparable comparable :estimated estimated)))

(defun get-earnings-dates (ticker)
  "Returns (date fiscal-period) pairs for the whole history of earnings announcements."
  (second (second (first (bdp (format nil "~A Equity" ticker) '("ERN_ANN_DT_AND_PER"))))))

element.lisp

0 → 100644
+141 −0
Original line number Diff line number Diff line
(in-package :bloomie)

(defvar *data-types*
  (loop for s in (apropos-list "+BLPAPI-DATATYPE-" "BB.FFI")
     collect (cons (symbol-value s) (intern (subseq (string-trim "+" (symbol-name s)) (length "BLPAPI-DATATYPE-")) "KEYWORD"))))

#+lispworks
(setf *data-types* '((1 . :BOOL) (3 . :BYTE) (9 . :BYTEARRAY) (2 . :CHAR)
		     (16 . :CHOICE) (17 . :CORRELATION-ID) (10 . :DATE)
		     (13 . :DATETIME) (12 . :DECIMAL) (14 . :ENUMERATION)
		     (6 . :FLOAT32) (7 . :FLOAT64) (4 . :INT32) (5 . :INT64)
		     (15 . :SEQUENCE) (8 . :STRING) (11 . :TIME)))

(defun decode-data-type (x)
  (or (cdr (assoc x *data-types*)) (error "data-type ~A not in ~A" x *data-types*)))

#+lispworks
(defun get-element (elements name)
  (multiple-value-bind (res element)
      (bb.ffi::blpapi-element-get-element elements nil name nil)
    (check-errors res)
    element))

#-lispworks
(defun get-element (elements name)
  (plus-c:c-with ((element :pointer))
    (check-errors (bb.ffi:blpapi-element-get-element elements (element plus-c:&) name nil))
    (autowrap:wrap-pointer element 'bb.ffi:blpapi-element-t)))

#+lispworks
(defun set-element (elements name values)
  (let ((s (get-element elements name)))
    (dolist (val values)
      (check-errors (bb.ffi::blpapi-element-set-value-string
		     s val (fli:cast-integer -1 '(:unsigned :int)))))))

#-lispworks
(defun set-element (elements name values)
  ;;; bb.ffi:+blpapi-element-index-end+ is -1, but I cannot pass this value as :unsigned-int
  ;;; (cffi:with-foreign-object (x :unsigned-int) (setf (cffi:mem-aref x :int) -1) (cffi:mem-aref x :unsigned-int))
  (let ((s (get-element elements name)))
    (dolist (val values)
      (check-errors (bb.ffi:blpapi-element-set-value-string s val 4294967295)))))

#+lispworks
(defun append-element (elements)
  (multiple-value-bind (res element)
      (bb.ffi::blpapi-element-append-element elements nil)
    (check-errors res)
    element))

#-lispworks
(defun append-element (elements)
  (plus-c:c-with ((element :pointer))
    (check-errors (bb.ffi:blpapi-element-append-element elements (element plus-c:&)))
    (autowrap:wrap-pointer element 'bb.ffi:blpapi-element-t)))

#+lispworks
(defun get-element-at (elements i)
  (multiple-value-bind (res val)
      (bb.ffi::blpapi-element-get-element-at elements nil i)
    (check-errors res)
    val))

#-lispworks
(defun get-element-at (elements i)
  (plus-c:c-with ((val :pointer))
    (check-errors (bb.ffi:blpapi-element-get-element-at elements (val plus-c:&) i))
    val))

#+lispworks
(defun get-choice (element)
  (multiple-value-bind (res choice)
      (bb.ffi::blpapi-element-get-choice element nil)
    (check-errors res)
    choice))

#-lispworks
(defun get-choice (element)
  (plus-c:c-with ((choice :pointer))
    (check-errors (bb.ffi:blpapi-element-get-choice element (choice plus-c:&)))
    choice))

(defun element-info (element)
  (list (bb.ffi::blpapi-element-name-string element)
	:datatype (decode-data-type (bb.ffi::blpapi-element-datatype element))
	:isarray (bb.ffi::blpapi-element-is-array element)
	:nelements (bb.ffi::blpapi-element-num-elements element)
	:iscomplex (bb.ffi::blpapi-element-is-complex-type element)
	:nvalues (bb.ffi::blpapi-element-num-values element)
	:isreadonly (bb.ffi::blpapi-element-is-read-only element)
	:isnull (bb.ffi::blpapi-element-is-null element)
	:schema (decode-schema element)))

(defun decode-type-definition (def)
  (list :name (name-string-and-destroy (bb.ffi::blpapi-schema-type-definition-name def))
	:description (bb.ffi::blpapi-schema-type-definition-description def)
	:datatype (decode-data-type (bb.ffi::blpapi-schema-type-definition-datatype def))))

(defun decode-schema (element)
  (let ((def (bb.ffi::blpapi-element-definition element)))
    (list :name (name-string-and-destroy (bb.ffi::blpapi-schema-element-definition-name def))
	  :alt-names (let ((nalternative (bb.ffi::blpapi-schema-element-definition-num-alternate-names def)))
		       (if (plusp nalternative)
			   (loop for i below nalternative
			      collect (name-string-and-destroy
				       (bb.ffi::blpapi-schema-element-definition-get-alternate-name def i)))))
	  :description (bb.ffi::blpapi-schema-element-definition-description def)
	  :type (decode-type-definition (bb.ffi::blpapi-schema-element-definition-type def))
	  :status (bb.ffi::blpapi-schema-element-definition-status def)
	  :min-values (bb.ffi::blpapi-schema-element-definition-min-values def)
	  :max-values (bb.ffi::blpapi-schema-element-definition-max-values def))))

(defun decode-element (element)
  (assert (or (zerop (bb.ffi::blpapi-element-is-array element))
	      (zerop (bb.ffi::blpapi-element-is-complex-type element))))
  (assert (string= (name-string-and-destroy (bb.ffi::blpapi-element-name element))
  		   (bb.ffi::blpapi-element-name-string element)))
  (cons (intern (bb.ffi::blpapi-element-name-string element) "KEYWORD")
	(ecase (decode-data-type (bb.ffi::blpapi-element-datatype element))
	  (:date (loop for i below (bb.ffi::blpapi-element-num-values element)
		    collect (value-as-date element i)))
	  (:datetime (loop for i below (bb.ffi::blpapi-element-num-values element)
			collect (value-as-date element i t)))
	  (:bool (loop for i below (bb.ffi::blpapi-element-num-values element)
		    collect (value-as-bool element i)))
	  (:int32 (loop for i below (bb.ffi::blpapi-element-num-values element)
		     collect (value-as-int32 element i)))
	  (:int64 (loop for i below (bb.ffi::blpapi-element-num-values element)
		     collect (value-as-int64 element i)))
	  (:float64 (loop for i below (bb.ffi::blpapi-element-num-values element)
		       collect (value-as-float64 element i)))
	  (:string (loop for i below (bb.ffi::blpapi-element-num-values element)
		      collect (value-as-string element i)))
	  (:sequence (if (= 1 (bb.ffi::blpapi-element-is-array element))
			 (loop for i below (bb.ffi::blpapi-element-num-values element)
			    collect (decode-element (value-as-element element i)))
			 (loop for i below (bb.ffi::blpapi-element-num-elements element)
			    collect (decode-element (get-element-at element i)))))
	  (:enumeration (list (value-as-string element 0)))
	  (:choice (decode-element (get-choice element))))))

examples.lisp

0 → 100644
+101 −0
Original line number Diff line number Diff line
;; tested on Windows (SBCL 64-bit, ClozurCL 32/64-bit, Lispworks 6.0 32-bit)
;; the test suite should run without any errors: (asdf:test-system :bloomie)

(ql:quickload :bloomie)

(bb:open-session)

;; FIELDS

(bb:field-info "MILITARY_REVENUE")
(bb:field-info "M1090")
(bb:field-info '("px_last" "pe_ratio") :documentation nil)

(mapcar #'bb:field-mnemonic (bb:field-search "military"))

(loop for cat in (bb:categorized-field-search "PRESID*")
   do (format t "~&~A :~{ ~A~}" (bb:category-name cat)
	      (loop for fld in (bb:category-fields cat) collect (bb:field-mnemonic fld))))

(length (bb:field-list :type :real-time))
(length (bb:field-list :type :static)) ;; 57k+ fields

;; INSTRUMENTS

(bb:instruments "entropy")
(bb:instruments "entropy" :max-results 5)
(bb:instruments "entropy" :yellow-key :corp)
(bb:instruments "entropy" :yellow-key :indx)

(bb:govt "rome")
(bb:govt "rome" :max-results 1)
(bb:govt "rome" :ticker "ROM")
(bb:govt "rome" :ticker "ROM" :partial-match nil)
(bb:govt "rome" :ticker "ROMCTY" :partial-match nil)

(bb:curve "genev")
(bb:curve "" :curve-id "bi758")
(bb:curve "garch" :currency-code "CHF" :max-results 3)
(bb:curve "" :currency-code :chf :type :irs)
(mapcar #'curve-currency (bb:curve nil :currency-code "jpy" :subtype "spread"))

;; REFERENCE

(bb:bdp '("AAPL US Equity" "MSFT US Equity") '("PX_LAST" "BEST_EPS"))
(bb:bdp '("AAPL US Equity" "MSFT US Equity") '("XXXXXX" "YYYYYY" "PX_LAST"))
(bb:bdp '("AAAAPLE US Equity" "MSFT US Equity") '("XXXXXX" "YYYYYY" "PX_LAST"))
(let ((bb:*raise-all-errors* t))
  (bb:bdp '("AAAAPL US Equity" "MSFT US Equity") '("XXXXXX" "YYYYYY" "PX_LAST")))

;; HISTORICAL

(bb:bdh '("AAPL US Equity" "MSFT US Equity") '("PX_LAST" "VOLUME")
	:start-date "20170501" :end-date "20170510" :periodicity :daily)
(bb:bdh "AAPL US Equity" "PE_RATIO" :start-date "1995-12-31" :periodicity :yearly)

;; INTRADAY BARS

(bb:ibar "AAPL US Equity" "BID" :bar-size '(4 :hour)
	 :start-date-time "2017-08-08" :end-date-time "2017-08-11")
(bb:ibar "AAPL US Equity" "TRADE" :bar-size '(1 :m)
	 :start-date-time "2017-08-08T14" :end-date-time "2017-08-08T14:05")

;; PORTFOLIO

(bb:portfolio-tickers "U12345678-1")
(bb:portfolio-tickers "U12345678-1" "2017-08-04")
(bb:portfolio-weights "U12345678-1")
(bb:portfolio-positions "U12345678-1")
(bb:portfolio-data "U12345678-1")
(bb:portfolio-data "XXX")

;; EQUITY SCREENING

(bb:screen-tickers "Global Automotive Parts Retailers")
(bb:screen-tickers "Global Automotive Parts Retailers" :folder "General")
(bb:screen-tickers "Global Automotive Parts Retailers" :folder "Popular")

;; EARNINGS

(bb:get-earnings-dates "AAPL US")
(bb:get-earnings "AAPL US" :start "2016-12-31")
(bb:get-earnings "AAPL US" :start "2016-12-31" :currency "EUR")

;; PRODUCTS

(loop for ticker in (bb:index-composition "SPX") for prods = (bb:product-list ticker)
   when prods do (format t "~A~10T~A~&" ticker (length prods)))
(bb:product-list "VRTX US")
(bb:product-forecast "VRTX US" "Orkambi")
(bb:product-forecast "VRTX US" "Orkambi" :year '(2017 2018 2019 2020))
(bb:product-forecast "VRTX US" "Orkambi" :year 2020 :source :all)
(bb:product-forecast "VRTX US" "Orkambi" :stat :all)
(bb:product-forecast "VRTX US" "Orkambi" :stat :revisions)

;; EXPORT SCHEMAS AND FIELD DEFINITIONS

(bb:document-schemas) ;; can be incomplete, see function docstring

(bb:document-fields) ;; can be incomplete, see function docstring

(bb:close-session)
Loading