Datascript Portfolio

This is to demonstrate a super small portfolio as seen in the XTDB Portfolio workbook page in Datascript

Before we get started, we'll start with a deps.edn that includes xtdb

{:deps
 {org.clojure/clojure {:mvn/version "1.10.3"}
  org.clojure/tools.deps.alpha
  {:git/url "https://github.com/clojure/tools.deps.alpha.git"
   :sha "e4fb92eef724fa39e29b39cc2b1a850567d490dd"}
  compliment/compliment {:mvn/version "0.3.11"}
  datascript/datascript {:mvn/version "1.4.2"}}}
Extensible Data Notation
(require '[datascript.core :as d])
0.0s

Schema

need more info on schema usage. Unlike XTDB, in Datascript, we quire some sechema setup. This identifies attributes like :issuer as references to other entities. In RDF terms that means another subject, in OO terms it means another object.

(def schema {:issuer {:db/valueType :db.type/ref :db/cardinality :db.cardinality/one}
              :asset    {:db/valueType :db.type/ref :db/cardinality :db.cardinality/one}
              :holdings {:db/valueType :db.type/ref :db/cardinality :db.cardinality/many}})
(def conn (d/create-conn schema))
0.0s

This creates a utility to view portfolios at 4 asof valuation dates

Load up initial portfolio

(d/transact! conn
             [ ;; add 3 companies
              {:db/id ":company/t1", :name "IBM"}
              {:db/id ":company/t2", :name "JP Morgan"}
              {:db/id -100, :name "Ford"}
              ;; add 3 assets based on those companies
              {:db/id ":security/t1",
               :issuer ":company/t1" :ticker "IBM",
               :type :Equity}
              {:db/id ":security/t2", 
               :issuer ":company/t2" :ticker "JPM",
               :type :Equity}
              {:db/id ":security/t3",
               :issuer -100 :ticker "F",
               :type :Equity}
              ;; add 2 positions (portfolio unspecified)
              {:db/id ":pm/p1", :asset ":security/t1", :quantity 100}
              {:db/id ":pm/p2", :asset ":security/t2", :quantity 200}
              ;; add portfolio (with those 2 positions)
              {:db/id ":p/p1", 
               :holdings [":pm/p1" ":pm/p2"],
               :name "My Trading Portfolio"}])
0.6s
;; use pull syntax to get security info and issuer name
(d/q '[:find (pull ?security  ["*" {:issuer [:name]}])
       :where [?security :ticker "F"]]
     @conn)
0.0s
(d/q '[:find (pull ?h [:quantity {:asset [:ticker {:issuer [:name]}]}])
       :where [?port :name "My Trading Portfolio"]
              [?port :holdings ?h]]
     @conn)
0.1s
;; same info flattened
(d/q '[:find ?t ?q ?n
       :where [?port :name "My Trading Portfolio"]
              [?port :holdings ?h]
              [?h :quantity ?q]
              [?h :asset ?a]
              [?a :ticker ?t]
              [?a :issuer ?c]
              [?c :name ?n]]
     @conn)
0.1s
(->> (d/q '[:find ?t ?q ?n
       :where [?port :name "My Trading Portfolio"]
              [?port :holdings ?h]
              [?h :quantity ?q]
              [?h :asset ?a]
              [?a :ticker ?t]
              [?a :issuer ?c]
              [?c :name ?n]]
     @conn)
 (apply map vector)
 (map vector [:ticker :quantity :name])
 (into {}))
0.0s
Runtimes (1)