Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Valid point. In that example it's using a list to hold each bar because I was focusing on the iteration and the raw data came from a yahoo api utility.

You could use a struct or a class which would give you accessor functions, and would be better for a real program.

You setup a struct:

  (defstruct bar date open high low close vol)
And this would be a one-time conversion of the data:

  (mapcar (lambda (b)
            (apply 'make-bar
                   (mapcan 'list '(:date :open :high :low :close :vol) b)))
          cl-user::*spy2006*)
Then you can access the elements with nicer names:

  (bar-date bar)
  (bar-high bar)
  ...etc...
(If you use DEFCLASS you can do a few more things.)

That would make the revised COMBINE-BARS look like the following, which has more context, and would yield a BAR struct back.

  (defun combine-bars (bars)
      "Summarize a sequence of BARS into one bar."
      (let ((opening-bar (first bars))
            (closing-bar (car (last bars))))
        (series::let ((zbars (scan 'list bars)))
          (make-bar :date (bar-date opening-bar)
                    :open (bar-open opening-bar)
                    :high (collect-max (map-fn 'float #'bar-high zbars))
                    :low (collect-min (map-fn 'float #'bar-low zbars))
                    :close (bar-close closing-bar)
                    :vol (collect-sum (map-fn 'integer #'bar-vol zbars))))))

(edit: added revised combine-bars)


Another trick is to define the struct like (defstruct (foo :type list) ....) and then you can use the struct accessors on any list of the appropriate size. (Or, if you want constant time element access, specify the type as vector)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: