going somewhere

This commit is contained in:
didier amyot committed 2018-07-08 12:46:15 -04:00
1 parent 9f36d28ce2
commit 519ac9ce07
7 files changed
+114 -46

No files matched your search

+50 -6
View File
@@ -6,7 +6,47 @@
[skirmish.util :refer :all]
[clojure.core.async :refer [chan go >! <! pub]]))
(def empty-book {:sell (create-sell-book) :buy (create-buy-book)})
(def empty-book {:sell (create-sell-book)
:buy (create-buy-book)
:id 0})
(defn retrieve-new-book-order-from-trade [trade book]
(let [book-id (:book.order/book-id trade)
f #(= book-id (:book.order/id %))
ret-order (first (filter f book))
new-quantity (- (:quantity ret-order 10) (:book.order/quantity trade));; (- (:quantity ret-order) (:book.order/quantity trade))
totally-fulfilled? (= (:book.order/quantity trade) (:quantity ret-order))]
(into ret-order {:status (if totally-fulfilled? :totally-fulfilled :partially-fulfilled)
:status-dual-id (:book.order/order-id trade)
:quantity new-quantity})));;;;
(defn ff [order trade]
(let [new-order-quantity (- (:quantity order) (:book.order/quantity trade))
totally-fulfilled? (= 0 new-order-quantity)
dual-id (:book.order/book-id trade)]
(into order {:status (if totally-fulfilled? :totally-fulfilled :partially-fulfilled)
:status-dual-id dual-id
:quantity new-order-quantity})))
(defn get-processed-orders-in-trades [order book trades]
(let [trades-orders (sequence (map #(retrieve-new-book-order-from-trade % book)) trades)
processed-orders (rest (reductions ff order trades))]
(interleave trades-orders processed-orders)))
(defn get-processed-orders [order leftover-order trades book]
"Computes all the intermediary orders that took place during
a the trade."
(let [ret [(assoc order :status :inserted)]
ret (into ret (get-processed-orders-in-trades order book trades))
ret (if (seq leftover-order)
(conj ret (assoc leftover-order :status :inserted-into-book))
leftover-order)]
ret))
(defn process-abstract [order reference-book same-type-book]
@@ -15,30 +55,34 @@
[new-reference-book new-same-type-book leftover-order trades]))
(defn process-sell-order [{sell-book :sell buy-book :buy} order]
(defn process-sell-order [{sell-book :sell buy-book :buy id :id} order]
(let [[new-buy-book new-sell-book new-order trades] (process-abstract order buy-book sell-book)
new-book {:sell new-sell-book :buy new-buy-book}]
new-book {:sell new-sell-book :buy new-buy-book :id (inc id)}]
[new-book new-order trades]))
(defn process-buy-order [{sell-book :sell buy-book :buy} order]
(defn process-buy-order [{sell-book :sell buy-book :buy id :id} order]
(let [[new-sell-book new-buy-book new-order trades] (process-abstract order sell-book buy-book)
new-book {:sell new-sell-book :buy new-buy-book}]
new-book {:sell new-sell-book :buy new-buy-book :id (inc id)}]
[new-book new-order trades]))
(defn process-order [book order]
(if (sell? order)
(process-sell-order book order)
(process-buy-order book order)))
(defn process-orders [initial-book incoming-order-channel]
(let [trades-channel (chan)
new-book-order-channel (chan)]
(go (loop [order (<! incoming-order-channel) book initial-book]
(let [[new-book new-order new-trades] (process-order book order)]
(when (not (nil? new-order)) (>! new-book-order-channel new-order))
(doseq [trade new-trades] (>! trades-channel trade))
(doseq [trade new-trades] (>! trades-channel trade)) ;; TODO: user clojure.core.async/onto-chan
(recur (<! incoming-order-channel) new-book))))
[(pub trades-channel :book.order/type) (pub new-book-order-channel :type)]))
(def create-exchange-for-security process-orders)
+21 -18
View File
@@ -9,15 +9,15 @@
;; sell-book contains all the sell orders. The second
;; called buy-book contains all the buy orders.
(defn create-sell-book [& args]
(defn create-sell-book [& orders]
"Creates a sell book with the orders in it."
(let [cmp #(compare (:price %1) (:price %2))]
(apply sorted-list-by cmp args)))
(apply sorted-list-by cmp orders)))
(defn create-buy-book [& args]
(defn create-buy-book [& orders]
"Creates a buy book with the orders in it."
(let [cmp #(compare (:price %2) (:price %1))]
(apply sorted-list-by cmp args)))
(def book {:sell (create-sell-book) :buy (create-sell-book)})
(apply sorted-list-by cmp orders)))
(defn buy? [order]
(= :buy (:type order)))
@@ -25,13 +25,13 @@
(defn sell? [order]
(= (:type order) :sell))
(defn sell-order-fullfillable? [book-order order]
(defn- sell-order-fullfillable? [book-order order]
(>= (:price book-order) (:price order)))
(defn buy-order-fullfillable? [book-order order]
(defn- buy-order-fullfillable? [book-order order]
(<= (:price book-order) (:price order)))
(defn create-sell-trade-factory [order-to-fulfill]
(defn- create-sell-trade-factory [order-to-fulfill]
(fn [trade book-order]
(let [already-fulfilled (:book.order/already-fulfilled trade 0)
qtn-to-fulfill (min (:quantity book-order) (- (:quantity order-to-fulfill) already-fulfilled))
@@ -44,7 +44,7 @@
:order-id (:book.order/id order-to-fulfill)
:book-id (:book.order/id book-order)}))))
(defn create-buy-trade-factory [order-to-fulfill]
(defn- create-buy-trade-factory [order-to-fulfill]
(fn [trade book-order]
(let [already-fulfilled (:book.order/already-fulfilled trade 0)
qtn-to-fulfill (min (:quantity book-order) (- (:quantity order-to-fulfill) already-fulfilled))
@@ -57,21 +57,21 @@
:order-id (:book.order/id order-to-fulfill)
:book-id (:book.order/id book-order)}))))
(defn create-trade-factory [order-to-fulfill]
(defn- create-trade-factory [order-to-fulfill]
(if (sell? order-to-fulfill)
(create-sell-trade-factory order-to-fulfill)
(create-buy-trade-factory order-to-fulfill)))
(defn create-trades [order-to-fulfill sell-book]
(defn- create-trades [order-to-fulfill sell-book]
(let [create-trade (create-trade-factory order-to-fulfill)
trades (reductions create-trade {} sell-book)
ret (rest (take-while some? trades))]
(map #(dissoc % :book.order/already-fulfilled) ret)))
(defn partial-trade? [trade order]
(defn- partial-trade? [trade order]
(not= (:quantity order) (:book.order/quantity trade)))
(defn compute-partial-order [order trade]
(defn- compute-partial-order [order trade]
(assoc order :quantity (- (:quantity order) (:book.order/quantity trade 0))))
(defn- drop-in-sorted-list [n sorted-list]
@@ -80,22 +80,25 @@
(<= (count sorted-list) n) (empty sorted-list)
:else (drop n sorted-list)));;
(defn compute-new-book-after-trades [book trades]
(defn- compute-new-book-after-trades [book trades]
(let [new-book (drop-in-sorted-list (-> trades count dec) book)
possible-partial-trade (last trades)]
(if (partial-trade? possible-partial-trade (first new-book))
(conj (rest new-book) (compute-partial-order (first new-book) possible-partial-trade))
(rest new-book))))
(defn leftover-order [order trades]
(defn- leftover-order [order trades]
(let [traded-quantity (reduce + (map :book.order/quantity trades))
leftover-quantity (- (:quantity order) traded-quantity)]
(when (pos? leftover-quantity)
(assoc order :quantity leftover-quantity))))
(defn match-order-in-book [book order]
"Matches the order within the book. Returns the applied trades,
the resulting book and left over order if the input order has not
been entirely fulfilled."
(let [trades (create-trades order book)
new-book (compute-new-book-after-trades book trades)
new-buy-order (leftover-order order trades)]
[trades new-book new-buy-order]))
leftover-order (leftover-order order trades)]
[trades new-book leftover-order]))
+11
View File
@@ -11,6 +11,17 @@
(s/def :book.order/price pos-int?)
(s/def :book.order/quantity pos-int?)
(s/def :book.order/id pos-int?)
(s/def :book.order/status #{:inserted ;; maybe called acknklowdlge.
:partially-matched
:totally-matched
:inserted-into-book
:partially-fulfilled
:totally-fulfilled
:withdrawn}) ;; for instance the order has been canceled
(s/def :book.order/status-dual-id :book.order/id)
(s/def :book.order/order (s/keys :req-un [:book.order/type :book.order/price :book.order/quantity] :opt [:book.order/id]))
;; A trade is defined by the bellow map...