going somewhere
This commit is contained in:
1 parent
9f36d28ce2
commit
519ac9ce07
7 files changed
+114
-46
No files matched your search
@@ -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
@@ -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,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...
|
||||
|
||||
Reference in new issue
Block a user