From 70d4e9f47f47c08a65710685a50551afb95e50a9 Mon Sep 17 00:00:00 2001 From: didier amyot Date: Thu, 31 May 2018 14:22:11 -0400 Subject: [PATCH] beautify code --- src/book/core.clj | 113 ++++++++++++++++++---------------------- test/book/core_test.clj | 26 ++++----- 2 files changed, 64 insertions(+), 75 deletions(-) diff --git a/src/book/core.clj b/src/book/core.clj index 4751503..65bea9d 100644 --- a/src/book/core.clj +++ b/src/book/core.clj @@ -25,24 +25,11 @@ (let [cmp #(compare (:price %2) (:price %1))] (apply sorted-list-by cmp args))) - - - - (def book {:sell (create-sell-book) :buy (create-sell-book)}) - (defn buy? [order] (= :buy (:type order))) - -(defn create-trade [order-to-fulfill book-order] - #:book.order{:type (:type book-order) - :quantity (:quantity order-to-fulfill) - :price (min (:price order-to-fulfill) (:price book-order)) - :order-id (:book.order/id order-to-fulfill) - :book-id (:book.order/id book-order)}) - (defn sell? [order] (= (:type order) :sell)) @@ -52,24 +39,38 @@ (defn buy-order-fullfillable? [book-order order] (<= (:price book-order) (:price order))) +(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)) + can-fulfill? (sell-order-fullfillable? book-order order-to-fulfill)] + (when (and can-fulfill? (< 0 qtn-to-fulfill)) + #:book.order{:type :buy + :quantity qtn-to-fulfill + :already-fulfilled (+ already-fulfilled qtn-to-fulfill) + :price (max (:price book-order) (:price order-to-fulfill)) + :order-id (:book.order/id order-to-fulfill) + :book-id (:book.order/id book-order)})))) + +(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)) + can-fulfill? (buy-order-fullfillable? book-order order-to-fulfill)] + (when (and can-fulfill? (< 0 qtn-to-fulfill)) + #:book.order{:type :sell + :quantity qtn-to-fulfill + :already-fulfilled (+ already-fulfilled qtn-to-fulfill) + :price (min (:price book-order) (:price order-to-fulfill)) + :order-id (:book.order/id order-to-fulfill) + :book-id (:book.order/id book-order)})))) + (defn create-trade-factory [order-to-fulfill] - (let [trade-type (if (sell? order-to-fulfill) :buy :sell) - trade-price (if (sell? order-to-fulfill) max min) - fulfillable? (if (sell? order-to-fulfill) sell-order-fullfillable? buy-order-fullfillable?)] - (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)) - can-fulfill? (fulfillable? book-order order-to-fulfill)] - (when (and can-fulfill? (< 0 qtn-to-fulfill)) - #:book.order{:type trade-type - :quantity qtn-to-fulfill - :already-fulfilled (+ already-fulfilled qtn-to-fulfill) - :price (trade-price (:price book-order) (:price order-to-fulfill)) - :order-id (:book.order/id order-to-fulfill) - :book-id (:book.order/id book-order)}))))) + (if (sell? order-to-fulfill) + (create-sell-trade-factory order-to-fulfill) + (create-buy-trade-factory order-to-fulfill))) - -(defn create-sell-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))] @@ -78,54 +79,42 @@ (defn partial-trade? [trade order] (not= (:quantity order) (:book.order/quantity trade))) - (defn compute-partial-order [order trade] (assoc order :quantity (- (:quantity order) (:book.order/quantity trade 0)))) - -(defn compute-new-sell-book-after-trades [sell-book trades] +(defn compute-new-book-after-trades [sell-book trades] (let [new-book (drop (-> trades count dec) sell-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] (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-buy-order-in-sell-book [sell-book order] - (let [trades (create-sell-trades order sell-book) - new-book (compute-new-sell-book-after-trades sell-book trades) +(defn match-order-in-book [sell-book order] + (let [trades (create-trades order sell-book) + new-book (compute-new-book-after-trades sell-book trades) new-buy-order (leftover-order order trades)] [trades new-book new-buy-order])) -(defn match-sell-order-in-buy-book [buy-book order] - (let [trades (create-sell-trades order buy-book) - new-book (compute-new-sell-book-after-trades buy-book trades) - new-buy-order (leftover-order order trades)] - [trades new-book new-buy-order])) - - -(defn place-buy-order [book order] - (match-buy-order-in-sell-book (:sell book) order) - (println :bingo)) ;; should return multiple "trade" and a new book - - -(defn place-order [book order] - (if (buy? order) - (place-buy-order book order))) - - -(defn -main - [& args] - (let [order (-> args first edn/read-string)] - (if (not (s/valid? :book.order/order order)) - (println "invalid order :( ") - (println (place-order book order))))) - - +;(defn place-buy-order [book order] +; (match-buy-order-in-sell-book (:sell book) order) +; (println :bingo)) ;; should return multiple "trade" and a new book +; +;(defn place-order [book order] +; (if (buy? order) +; (place-buy-order book order))) +; +; +;(defn -main +; [& args] +; (let [order (-> args first edn/read-string)] +; (if (not (s/valid? :book.order/order order)) +; (println "invalid order :( ") +; (println (place-order book order))))) +; +; diff --git a/test/book/core_test.clj b/test/book/core_test.clj index 96f2971..d51b48e 100644 --- a/test/book/core_test.clj +++ b/test/book/core_test.clj @@ -7,28 +7,28 @@ (testing "Simplest case I." (let [sell-book (create-sell-book {:type :sell :quantity 10 :price 2 :book.order/id 101}) order {:type :buy :quantity 10 :price 2 :book.order/id 102} - [trades new-book] (match-buy-order-in-sell-book sell-book order)] + [trades new-book] (match-order-in-book sell-book order)] (is (empty? new-book)) (is (= trades [#:book.order{:quantity 10 :price 2 :book-id 101 :order-id 102 :type :sell}])))) (testing "Simplest case II." (let [sell-book (create-sell-book {:type :sell :quantity 10 :price 2 :book.order/id 103}) order {:type :buy :quantity 10 :price 3 :book.order/id 104} - [trades new-book] (match-buy-order-in-sell-book sell-book order)] + [trades new-book] (match-order-in-book sell-book order)] (is (empty? new-book)) (is (= trades [#:book.order{:quantity 10 :price 2 :book-id 103 :order-id 104 :type :sell}])))) (testing "Simplest case III." (let [sell-book (create-sell-book {:type :sell :quantity 10 :price 2 :book.order/id 105}) order {:type :buy :quantity 8 :price 2 :book.order/id 106} - [trades new-book] (match-buy-order-in-sell-book sell-book order)] + [trades new-book] (match-order-in-book sell-book order)] (is (= new-book [{:type :sell :quantity 2 :price 2 :book.order/id 105}])) (is (= trades [#:book.order{:quantity 8 :price 2 :book-id 105 :order-id 106 :type :sell}])))) (testing "Simplest case IV." (let [sell-book (create-sell-book {:type :sell :quantity 2 :price 12 :book.order/id 107} {:type :sell :quantity 8 :price 13 :book.order/id 108}) order {:type :buy :quantity 10 :price 13 :book.order/id 109} - [trades new-book] (match-buy-order-in-sell-book sell-book order)] + [trades new-book] (match-order-in-book sell-book order)] (is (empty? new-book)) (is (= trades [#:book.order{:quantity 2 :price 12 :book-id 107 :order-id 109 :type :sell} #:book.order{:quantity 8 :price 13 :book-id 108 :order-id 109 :type :sell}])))) @@ -36,7 +36,7 @@ (testing "Simplest case V." (let [sell-book (create-sell-book {:type :sell :quantity 2 :price 12 :book.order/id 113} {:type :sell :quantity 8 :price 13 :book.order/id 114}) order {:type :buy :quantity 9 :price 13 :book.order/id 115} - [trades new-book] (match-buy-order-in-sell-book sell-book order)] + [trades new-book] (match-order-in-book sell-book order)] (is (= new-book (create-sell-book {:type :sell :quantity 1 :price 13 :book.order/id 114}))) (is (= trades [#:book.order{:quantity 2 :price 12 :book-id 113 :order-id 115 :type :sell} #:book.order{:quantity 7 :price 13 :book-id 114 :order-id 115 :type :sell}])))) @@ -44,7 +44,7 @@ (testing "Simplest case VI." (let [sell-book (create-sell-book {:type :sell :quantity 2 :price 12 :book.order/id 116} {:type :sell :quantity 8 :price 13 :book.order/id 117}) order {:type :buy :quantity 21 :price 13 :book.order/id 118} - [trades new-book leftover-order] (match-buy-order-in-sell-book sell-book order)] + [trades new-book leftover-order] (match-order-in-book sell-book order)] (is (empty? new-book)) (is (= trades [#:book.order{:quantity 2 :price 12 :book-id 116 :order-id 118 :type :sell} #:book.order{:quantity 8 :price 13 :book-id 117 :order-id 118 :type :sell}])) @@ -53,7 +53,7 @@ (testing "Simplest case VII." (let [sell-book (create-sell-book {:type :sell :quantity 2 :price 12 :book.order/id 116} {:type :sell :quantity 8 :price 13 :book.order/id 117}) order {:type :buy :quantity 21 :price 10 :book.order/id 118} - [trades new-book leftover-order] (match-buy-order-in-sell-book sell-book order)] + [trades new-book leftover-order] (match-order-in-book sell-book order)] (is (= new-book sell-book)) (is (= trades [])) (is (= leftover-order order))))) @@ -63,21 +63,21 @@ (testing "Simplest case I." (let [buy-book (create-buy-book {:type :buy :quantity 10 :price 2 :book.order/id 101}) order {:type :sell :quantity 10 :price 2 :book.order/id 102} - [trades new-book] (match-sell-order-in-buy-book buy-book order)] + [trades new-book] (match-order-in-book buy-book order)] (is (= new-book [])) (is (= trades [#:book.order{:quantity 10 :price 2 :book-id 101 :order-id 102 :type :buy}])))) (testing "Simplest case II." (let [buy-book (create-buy-book {:type :buy :quantity 10 :price 4 :book.order/id 103}) order {:type :sell :quantity 10 :price 3 :book.order/id 104} - [trades new-book] (match-sell-order-in-buy-book buy-book order)] + [trades new-book] (match-order-in-book buy-book order)] (is (= new-book [])) (is (= trades [#:book.order{:quantity 10 :price 4 :book-id 103 :order-id 104 :type :buy}])))) (testing "Simplest case III." (let [buy-book (create-buy-book {:type :buy :quantity 10 :price 2 :book.order/id 105}) order {:type :sell :quantity 8 :price 2 :book.order/id 106} - [trades new-book] (match-sell-order-in-buy-book buy-book order)] + [trades new-book] (match-order-in-book buy-book order)] (is (= new-book [{:type :buy :quantity 2 :price 2 :book.order/id 105}])) (is (= trades [#:book.order{:quantity 8 :price 2 :book-id 105 :order-id 106 :type :buy}])))) @@ -85,7 +85,7 @@ (let [buy-book (create-buy-book {:type :buy :quantity 2 :price 14 :book.order/id 107} {:type :buy :quantity 8 :price 13 :book.order/id 108}) order {:type :sell :quantity 10 :price 13 :book.order/id 109} - [trades new-book] (match-sell-order-in-buy-book buy-book order)] + [trades new-book] (match-order-in-book buy-book order)] (is (= new-book [])) (is (= trades [#:book.order{:quantity 2 :price 14 :book-id 107 :order-id 109 :type :buy} #:book.order{:quantity 8 :price 13 :book-id 108 :order-id 109 :type :buy}])))) @@ -94,7 +94,7 @@ (let [buy-book (create-buy-book {:type :buy :quantity 2 :price 14 :book.order/id 113} {:type :buy :quantity 8 :price 13 :book.order/id 114}) order {:type :sell :quantity 9 :price 13 :book.order/id 115} - [trades new-book] (match-sell-order-in-buy-book buy-book order)] + [trades new-book] (match-order-in-book buy-book order)] (= new-book (create-buy-book {:type :buy :quantity 1 :price 13 :book.order/id 114})) (is (= trades [#:book.order{:quantity 2 :price 14 :book-id 113 :order-id 115 :type :buy} #:book.order{:quantity 7 :price 13 :book-id 114 :order-id 115 :type :buy}])))) @@ -103,7 +103,7 @@ (let [sell-book (create-buy-book {:type :buy :quantity 2 :price 14 :book.order/id 116} {:type :buy :quantity 8 :price 13 :book.order/id 117}) order {:type :sell :quantity 21 :price 13 :book.order/id 118} - [trades new-book leftover-order] (match-sell-order-in-buy-book sell-book order)] + [trades new-book leftover-order] (match-order-in-book sell-book order)] (is (empty? new-book)) (is (= trades [#:book.order{:quantity 2 :price 14 :book-id 116 :order-id 118 :type :buy} #:book.order{:quantity 8 :price 13 :book-id 117 :order-id 118 :type :buy}]))