Bladeren bron

Average charts with defined step

Innokenty Enikeev 10 jaren geleden
bovenliggende
commit
7d0fe217b1
3 gewijzigde bestanden met toevoegingen van 27 en 15 verwijderingen
  1. 8 2
      chatikbot.lisp
  2. 4 3
      db.lisp
  3. 15 10
      finance.lisp

+ 8 - 2
chatikbot.lisp

@@ -203,11 +203,17 @@
              (eur (or (null args) (find "eur" args :test #'equal)))
              (gbp (or (null args) (find "gbp" args :test #'equal)))
              (brent (or (null args) (find "brent" args :test #'equal)))
+             (avg (or (some #'(lambda (a)
+                                (when (find (princ-to-string a) args :test #'equal)
+                                  (* a 60)))
+                            '(240 60 30 15 10 5 1))
+                      60))
              (rates (multiple-value-list (db-get-last-finance))))
         (if (or usd eur gbp brent)
             (let ((data (db-get-series
-                         (local-time:timestamp- (local-time:now) 1 :day)
-                         usd eur gbp brent)))
+                         (local-time:timestamp- (local-time:now)
+                                                (* 800 avg) :sec)
+                         usd eur gbp brent avg)))
               (telegram-send-photo chat-id
                                    (make-chart data :usd usd :eur eur :gbp gbp :brent brent)
                                    :caption

+ 4 - 3
db.lisp

@@ -31,8 +31,10 @@
              for col in (rest names)
              collect (cons (aget col map) (sqlite:statement-column-value statement i))))))
 
-(defun db-get-series (after-ts &optional usd eur gbp brent)
-  (let ((sql (format nil "select ts~:[~;,usd~]~:[~;,eur~]~:[~;,gbp~]~:[~;,brent~] from finance where ts >= ? order by ts" usd eur gbp brent)))
+(defun db-get-series (after-ts &optional usd eur gbp brent (avg 60))
+  (let ((sql (format nil
+                     "select ts/~a*~a~:[~;,avg(usd) as usd~]~:[~;,avg(eur) as eur~]~:[~;,avg(gbp) as gbp~]~:[~;,avg(brent) as brent~] from finance where ts >= ? group by ts/~a order by ts"
+                     avg avg usd eur gbp brent avg)))
     (sqlite:with-open-database (db (db-path) :busy-timeout 10)
       (loop
          with statement = (sqlite:prepare-statement db sql)
@@ -41,4 +43,3 @@
          collect (%finance-alist statement)
          finally (sqlite:finalize-statement statement)))))
 
-

+ 15 - 10
finance.lisp

@@ -41,18 +41,23 @@
      finally (return (values min max))))
 
 (defun make-chart (series &key (usd t) (eur t) (gbp t) (brent t))
-  (let ((flat (remove-if #'null (if (alexandria:circular-list-p series)
-                                     (flat-circular series)
-                                     series))))
-    (adw-charting:with-line-chart (1200 900)
-      (when usd (adw-charting:add-series "USD/RUB" (get-serie flat "USD/RUB")))
-      (when eur (adw-charting:add-series "EUR/RUB" (get-serie flat "EUR/RUB")))
-      (when gbp (adw-charting:add-series "GBP/RUB" (get-serie flat "GBP/RUB")))
+  (let* ((r (multiple-value-list (range series :key #'car)))
+         (fmt (if (<= (- (second r) (first r))
+                      (* 60 60 36))
+                  '((:hour 2) ":" (:min 2))
+                  '((:day 2) "." (:month 2) " " (:hour 2) ":" (:min 2)))))
+    (adw-charting:with-line-chart (890 600)
+      (when usd (adw-charting:add-series "USD/RUB" (get-serie series "USD/RUB")))
+      (when eur (adw-charting:add-series "EUR/RUB" (get-serie series "EUR/RUB")))
+      (when gbp (adw-charting:add-series "GBP/RUB" (get-serie series "GBP/RUB")))
       (when brent (adw-charting:add-series "Brent last day futures"
-                                           (get-serie flat "Brent")))
+                                           (get-serie series "Brent")))
       (adw-charting:set-axis
        :x "Time" :draw-gridlines-p t
-       :label-formatter #'(lambda (v) (local-time:format-timestring nil (local-time:unix-to-timestamp v)
-                                                               :format '((:hour 2) ":" (:min 2)))))
+       :label-formatter #'(lambda (v)
+                            (local-time:format-timestring
+                             nil
+                             (local-time:unix-to-timestamp v)
+                             :format fmt)))
       (adw-charting:set-axis :y "RUB" :draw-gridlines-p t :label-formatter "~,2F")
       (adw-charting:save-file "chart.png"))))