|
|
@@ -167,8 +167,15 @@
|
|
|
(db-execute "update finance_orders set amount = ?, close = ?, close_at = ? WHERE rowid = ?"
|
|
|
amount close close-at row-id))
|
|
|
|
|
|
-(defun db/orders-get (chat-id)
|
|
|
- (db-select "select rowid, user_id, user_name, symbol, amount, open, open_at, close, close_at from finance_orders where chat_id = ? order by open_at, close_at" chat-id))
|
|
|
+(defun db/order-del (row-id)
|
|
|
+ (db-execute "delete from finance_orders WHERE rowid = ?" row-id))
|
|
|
+
|
|
|
+(defun db/orders-get (chat-id &optional user-id symbol opened)
|
|
|
+ (db-select "select rowid, user_id, user_name, symbol, amount, open, open_at, close, close_at from finance_orders where chat_id = ? and (user_id = ? or ?) and (symbol = ? or ?) and (close is null or ?) order by open_at, close_at"
|
|
|
+ chat-id
|
|
|
+ user-id (if (or (null user-id) (member user-id *admins*)) 1 0)
|
|
|
+ symbol (if (null symbol) 1 0)
|
|
|
+ (if opened 0 1)))
|
|
|
|
|
|
;; Cron
|
|
|
(defcron process-rates ()
|
|
|
@@ -246,7 +253,9 @@
|
|
|
(get-symbol-label (agets info :symbol))
|
|
|
(format-ts (local-time:unix-to-timestamp (agets info :open-at)))
|
|
|
(agets info :open)
|
|
|
- (if (> (or (agets info :income) 0) 0) "📈" "📉")
|
|
|
+ (if (agets info :open-p)
|
|
|
+ (if (> (or (agets info :income) 0) 0) "📈" "📉")
|
|
|
+ (if (> (or (agets info :income) 0) 0) "🏆" "🐟"))
|
|
|
(if (agets info :open-p) "now"
|
|
|
(format-ts (local-time:unix-to-timestamp (agets info :close-at))))
|
|
|
(or (agets info :close) 0)
|
|
|
@@ -276,9 +285,58 @@
|
|
|
(log:error "~A" e)
|
|
|
(bot-send-message chat-id "/hodl buy <SYM> <AMT> <PRICE> [YYYY-MM-DD]"))))
|
|
|
|
|
|
+(defun handle-hodl-sell (chat-id from args)
|
|
|
+ (handler-case
|
|
|
+ (let* ((symbol (get-label-symbol (nth 1 args)))
|
|
|
+ (amount (parse-float (nth 2 args)))
|
|
|
+ (close (parse-float (nth 3 args)))
|
|
|
+ (close-at (if (nth 4 args) (local-time:parse-timestring (nth 4 args)) (local-time:now)))
|
|
|
+ (user-id (agets from "id"))
|
|
|
+ (orders (db/orders-get chat-id user-id symbol t))
|
|
|
+ (total-amount (apply #'+ (mapcar #'(lambda (o) (parse-float (nth 4 o))) orders))))
|
|
|
+ (if (> amount total-amount)
|
|
|
+ (bot-send-message chat-id (format nil "Нет у тебя столько ~A! (не хватает ~A)"
|
|
|
+ (nth 1 args)
|
|
|
+ (- amount total-amount)))
|
|
|
+ (progn
|
|
|
+ (loop for order in orders
|
|
|
+ for order-amount = (parse-float (nth 4 order))
|
|
|
+ while (> amount 0)
|
|
|
+ when (> order-amount amount)
|
|
|
+ do (db/order-buy chat-id (nth 1 order) (nth 2 order) (nth 3 order)
|
|
|
+ (princ-to-string (- order-amount amount))
|
|
|
+ (nth 5 order) (nth 6 order))
|
|
|
+ do (progn
|
|
|
+ (db/order-sell (nth 0 order)
|
|
|
+ (princ-to-string (min amount order-amount))
|
|
|
+ (princ-to-string close)
|
|
|
+ (local-time:timestamp-to-unix close-at))
|
|
|
+ (decf amount order-amount)))
|
|
|
+ (handle-hodl-show chat-id))))
|
|
|
+ (error (e)
|
|
|
+ (log:error "~A" e)
|
|
|
+ (bot-send-message chat-id "/hodl sell <SYM> <AMT> <PRICE> [YYYY-MM-DD]"))))
|
|
|
+
|
|
|
+(defun handle-hodl-del (chat-id from args)
|
|
|
+ (handler-case
|
|
|
+ (let* ((symbol (get-label-symbol (nth 1 args)))
|
|
|
+ (amount (or (nth 2 args) (error "no amount")))
|
|
|
+ (order (find amount (db/orders-get chat-id (agets from "id") symbol)
|
|
|
+ :key #'(lambda (r) (nth 4 r)) :test #'equal)))
|
|
|
+ (if order
|
|
|
+ (progn
|
|
|
+ (db/order-del (car order))
|
|
|
+ (handle-hodl-show chat-id))
|
|
|
+ (bot-send-message chat-id (format nil "Не нашёл ~A ~A :(" amount (nth 1 args)))))
|
|
|
+ (error (e)
|
|
|
+ (log:error "~A" e)
|
|
|
+ (bot-send-message chat-id "/hodl del <SYM> <AMT>"))))
|
|
|
+
|
|
|
(def-message-cmd-handler handle-hodl (:hodl :hodlers)
|
|
|
(cond
|
|
|
((equal (car args) "buy") (handle-hodl-buy chat-id (agets message "from") args))
|
|
|
+ ((equal (car args) "sell") (handle-hodl-sell chat-id (agets message "from") args))
|
|
|
+ ((equal (car args) "del") (handle-hodl-del chat-id (agets message "from") args))
|
|
|
(:otherwise (handle-hodl-show chat-id))))
|
|
|
|
|
|
|