(in-package #:chatikbot) (defparameter +yahoo-url+ "https://query.yahooapis.com/v1/public/yql" "Yahoo Finance API endpoint") (defparameter +yahoo-query+ "select Name,Rate from yahoo.finance.xchange where pair in (~{\"~A\"~^,~})") (defparameter +brent-url+ "http://www.cmegroup.com/CmeWS/mvc/Quotes/Future/424/G") (defvar *rate-pairs* '("USDRUB" "EURRUB" "GBPRUB")) (defun get-rates (&optional (pairs *rate-pairs*)) (let ((response (json-request +yahoo-url+ :parameters (append '(("format" . "json") ("env" . "store://datatables.org/alltableswithkeys")) (list (cons "q" (format nil +yahoo-query+ pairs))))))) (when (aget "error" response) (error "Error in rates request")) (loop for rate in (aget "rate" (aget "results" (aget "query" response))) collect (cons (aget "Name" rate) (read-from-string (aget "Rate" rate)))))) (defun get-brent () (handler-case (let ((last (read-from-string (aget "last" (first (aget "quotes" (json-request +brent-url+))))))) (when (numberp last) last)) (error (e) (log:error e)))) (defparameter +btc-e-usd-url+ "https://btc-e.com/api/2/btc_usd/ticker" "BTC-e BTC/USD ticker url") (defun get-btc-e () (handler-case (aget "last" (aget "ticker" (json-request +btc-e-usd-url+))) (error (e) (log:error e)))) (defun get-serie (series idx) (loop for row in series when (elt row idx) collect (list (first row) (elt row idx)))) (defun range (seq &key (key 'identity)) (loop for item in seq for value = (funcall key item) minimizing value into min maximizing value into max finally (return (values min max)))) (defvar *chart-points* 800 "Data points in chart") (defun make-chart (series names) (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 ((+ 90 *chart-points*) (floor (* 3 *chart-points*) 4)) (loop for serie in names for idx from 1 do (adw-charting:add-series serie (get-serie series idx))) (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 fmt))) (adw-charting:set-axis :y "RUB" :draw-gridlines-p t :label-formatter "~,2F") (adw-charting:save-file "chart.png"))))