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
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)