I would like to use Yahoo to get stock prices from within an Emacs Lisp program. I have two questions.
How do I make the http GET?
What is the best what to store the data in Elisp so I can make comparisons of the data? In other words, should I use one hash table, several hash tables, or lists to represent that data returned from Yahoo?
Here's the basic outline of what I'd like to do.
;; Call Yahoo to get equity prices
;;
;; Yahoo Input:
;; http://download.finance.yahoo.com/d/quotes.csv?s=AAPL+GOOG&f=sb2b3jkm6
;; Yahoo Output:
;; "AAPL",211.98,211.82,78.20,215.59,+17.90%
;; "GOOG",602.94,601.69,282.75,629.51,+18.27%
;;
;; Symbol, ask, bid, 52 week low, 52 week high, % change from 200 day mavg
;;
;; Yahoo format described here: http://www.gummy-stuff.org/Yahoo-data.htm
(defun get-price-url (tickers)
"
s = symbol
b2 = ask real-time
b3 = bid real-time
j = 52 week low
k = 52 week high
"
(concat "http://download.finance.yahoo.com/d/quotes.csv?s="
(mapconcat 'identity tickers "+") "&f=sb2b3jk"))
(setq lst '("AAPL" "GOOG" "MSFT" "ORCL"))
(setq url (get-price-url lst))
;; Call Yahoo with Url, process results and place in a data structure
;;
;; Return results sorted by largest change in 200 day mavg, in descending order
;;
Here's some code to get you started; I show how to grab the url to a buffer, parse each line and then display the ticker and price of each item. You can modify it from there to do what you need.
This parses each line of stock data into a list, and it's straight forward to grab the values using the first, second, third functions, or using nth. You can write functions to grab each element you want, such as get-ticker(quote) which would just return (first ticker)
I wouldn't over think what kind of data structure to use; whatever is easiest is fine. If you need high performance then you shouldn't be using emacs lisp for this anyway.
(defun test()
(interactive)
(let ((quotes (get-quotes '("AAPL" "GOOG" "MSFT" "ORCL" "ERTS" "THQI") "sb")))
(show-quotes quotes)))
(defun show-quotes(quotes)
(dolist (quote quotes)
(message (format "%s $%.2f" (first quote) (string-to-number (second quote))))))
(defun get-quotes(tickers field-string)
"Given a list of ticker names and a string of fields to return as above, this grabs them
from Yahoo, and parses them"
(let ((results-buffer (get-yahoo-quotes-to-buffer (get-price-url tickers field-string))))
(switch-to-buffer results-buffer)
(parse-quote-buffer results-buffer)))
(defun get-price-url (tickers field-string)
"Set up the get url"
(concat "http://download.finance.yahoo.com/d/quotes.csv?s="
(mapconcat 'identity tickers "+")
"&f=" field-string))
(defun get-yahoo-quotes-to-buffer(url)
"Retrieve the quotes to a buffer and return it"
(url-retrieve-synchronously url))
(defun parse-quote-buffer(b)
"Parse the buffer for quotes"
(goto-line 1)
(re-search-forward "^\n")
(beginning-of-line)
(let ((res nil))
(while (> (point-max) (point))
(setf res (cons (split-string (thing-at-point 'line) ",") res))
(forward-line 1))
(reverse res)))
Check out http://edward.oconnor.cx/elisp/. Edward has some examples of interacting with various services using HTTP, and if you can't find a Yahoo client library you could write one using these techniques.
Related
I'm writing code where the user picks from a list of choices. I have defined my list in the following:
;contains the options the user can pick
(define choices (list "choice1" "choice2" "choice3" "choice4" "choice5" "choice6" "OPENING VALUE" "HIGHEST VALUE" "LOWEST VALUE" "CLOSING VALUE" "VOLUME OF SHARES" "ADJUSTED CLOSING VALUE"))
My button gets the name from the list from the following code(only showing one example). In this case it takes the third item from the list:
[label (list-ref choices 2)]
and when I want to change the name then I use the line of code:
(send choice-4-9 set-label (list-ref choices 9))
My prof commented that I should bind names to 6 7 etc so your code would be readable. I'm still a little confused on what he meant by that and how I would do so.
He means for each index, define an identifier bound to that index, ideally named after what it means, e.g.:
(define choice1 0)
(define choice2 1)
(define choice3 2)
....
So now you can write [label (list-ref choices choice3)] instead of [label (list-ref choices 2)]. The code is more readable, and easier to change if necessary because you can change the binding of the identifier rather than every place where the number appears in code.
Incidentally, what you're doing now is called using "magic numbers."
The previous answer is good and I have upvoted it. I only want to mention that a common data structure for something like this is an association list, where you associate something like a symbol or number to a value, and then look it up using assq, assv, or assoc depending on the whether your lookup name requires eq?, eqv?, or equal? respectively. Consider:
(define choices
'((shoot . "Shoot!")
(run . "Run away!")
(reload . "Reload")
(appraise . "Search your surroundings")))
(define (get-label choice)
(let ((result (assq choice choices)))
(if (not result)
(error "???") ; handle as you see fit
(cdr result))))
;;;;;;;;;;;;;;;;
Welcome to DrRacket, version 6.4 [3m].
Language: racket/base [custom]; memory limit: 8192 MB.
> (get-label 'shoot)
"Shoot!"
>
I'm making a random sentence generator using Scheme (Pretty Big), and I'm having trouble defining temporary variables. I want to make something like this:
<NOUN1> <VERB1> <NOUN2> <but> <NOUN2> <VERB1> <NOUN2> <also>
Example: Sharks eat fish, but fish eat fish also.
I have word lists, and functions to choose a word from said list. Then, I use append to create a function. I am able to do:
(define (sentence)
(append (getNoun) '(and) (getNoun) (getVerb)))
However, I am unable to figure out a way to temporarily define a variable.
I have this so far:
(define (sentence1)
(append (getNoun)
(lambda (verb getVerb)
(noun getNoun))
(verb) (noun) '(but) (noun) (verb) (noun)))
Hints/Help please?
You are looking for let.
http://docs.racket-lang.org/reference/let.html
Here is an example usage:
(define (my-proc age)
(let ([age-plus-10 (+ age 10)])
(printf "age is ~a" age)
(printf "age-plus-10 is ~a" age-plus-10)))
Notice how we can temporarily define age-plus-10 and then use it later.
How could I use the sort-regexp-fields to emulate the sort-numeric-fields. I tried like this:
123
345
90
80
1999
M-x sort-regexp-fields
Regexp specifying records to sort: \ ([0-9]+\)
Regexp specifying key within record: \, \#1
But it can’t work.
what I really want to sort is something like this:
foo index: 123
index: 345 boo
…
the question is: I want to sort the lines by the number after the word “index”, but the number is not in the same field, they just have a word “index” before it. what should I do to complete this? anybody can help me?
sort-regexp-fields doesn't do lexicographical compare, and there's no trivial way to get it to do that. That said, we can use a trick of defining our own command, and using that command to signal to some advice to shoe-horn in a lexicographical compare.
The following command does what you want, provided you mark the region around the lines you want to compare:
(defun my-line-sort (begin end)
(interactive "r")
(sort-regexp-fields nil "^.*: +\\([0-9]+\\).*$" "\\1" begin end))
(defun compare-buffer-substrings-lexigraphically (b1 b2)
(< (string-to-number (buffer-substring-no-properties (car b1) (cdr b1)))
(string-to-number (buffer-substring-no-properties (car b2) (cdr b2)))))
(defadvice sort-subr (before sort-subr-lexical-compare activate)
"In special case, force predicate to be a lexical compare"
(when (eq this-command 'my-line-sort)
(ad-set-arg 5 'compare-buffer-substrings-lexigraphically)))
If I understand your situation correctly, this will do what you want:
M-xsort-regexp-fieldsRETindex: \([0-9]+\)RET\1RET
probably an easy question: I want to wrap the "(format ..)" function of Scheme in order to handle my debugging output (including the wrapping of the format-string).
As "format" takes a variable number of arguments my wrapper would need to do that too yielding the question on how I tell scheme to have an ellipsis-parameter and how to reference it.
I thought of something like this:
(define debugPrint
(lambda (formatString ELLIPSIS_PARAMETER)
(if debug
(format #t (string-append "<!--" formatString "-->") ELLIPSIS_PARAMETER)
()
)
)
)
Thank You for your help in advance!
There is dot notation for this:
(define (debugPrint formatString . params)
(if debug
(apply format #t (string-append "<!--" formatString "-->") params)
'()))
Take note on apply as dot notation wraps all parameters in list and when you use (debugPrint "~a: ~a" key name), the formatString will be bound to "~a: ~a" and params will be bound to (key name) (sure the values of key and name, not symbols ;).
I'd like to export or replicate a scheme environment in another guile process. The algorithm I'm imagining would do something like this to serialize:
(map (lambda (var val) (display (quasiquote (define ,var ,val))
(newline))
(get-current-environment))
And then I'd read/eval that on the other end.
However, while there are functions that return the current environment, they are in some internal format that I can't just map across. How can I "walk" the environment as the above? Alternatively, how else can I replicate an environment into another process?
you may decompose the so-called "current-environment" like this:
(define (get-current-binding-list)
(let* ((e (current-module)) ;; assume checking current-module
(h (struct-ref e 0)) ;; index 0 is current vars hashtable
)
(hash-map->list cons h) ;; return a vars binding list
))
and you can call (get-current-binding-list) to get variables binding list in current-module.
Please note that each element in this list is a pair of symbol and variable type, say, (symbol-name . variable-type). So you may print it like this:
for a instance ,you got a var binding:
(define abc 5)
then:
(let ((vl (get-current-binding-list)))
(assoc-ref vl 'abc)
)
==> #<variable 9bb5108 value: 5>
This result is a "variable type" of variable "abc". You can get it's value with variable-ref procedure.
So you can trace all the bindings and do something ,in your code ,it's simply print var-name and var-value.
I know my answer is too brief, but I think there's enough information to help you to find more details in the manual.
Hope this will help you.
You can't really serialize Scheme environment. I don't known even it's possible to (portably) serialize continuations. Oh, and don't forget about FFIs. Ports and threads are unserializable too.