Programming performance/Yasuo Common Lisp

From HaskellWiki
< Programming performance
Revision as of 16:40, 6 February 2015 by Yasuo (talk | contribs) (Created page with "<syntaxhighlight lang="lisp"> #| CL-USER> (lisp-implementation-type) "Clozure Common Lisp" CL-USER> (lisp-implementation-version) "Version 1.6-r14468M (DarwinX8664)" CL-USER>...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
#|
CL-USER> (lisp-implementation-type)
"Clozure Common Lisp"
CL-USER> (lisp-implementation-version)
"Version 1.6-r14468M  (DarwinX8664)"
CL-USER> (run)
1950-01-04 closing=16.85 change%=1.1404594 cash=10000 assets=NIL
1950-01-05 closing=16.93 change%=0.47477698 cash=10000 assets=NIL
...
2007-03-01 closing=1403.17 change%=-0.25944346 cash=12389.992 assets=(#S(PURCHASE :AMOUNT 0.9840075 :ORIGINAL-PRICE 1399.04))
2007-03-02 closing=1387.17 change%=-1.1402752 cash=12389.992 assets=(#S(PURCHASE :AMOUNT 0.9840075 :ORIGINAL-PRICE 1399.04))
13754.978 (#S(PURCHASE :AMOUNT 0.9840075 :ORIGINAL-PRICE 1399.04))
NIL
CL-USER> 
|#

(defun read-gspc ()
  (with-open-file (s "gspc.txt" :direction :input)
    (do ((result)
	 (line (read-line s nil)
	       (read-line s nil)))
	((null line) result)
      (unless (eql (char (string-left-trim #(#\Space #\Tab) line) 0) #\#)
	(push line result)))))

(defun date (record)
  (subseq record 0 (position #\Space record)))

(defun closing-cost (record)
  (read-from-string (subseq record (1+ (position #\Space record :from-end t)))))

(defun percent-change (old-price new-price)
  (* 100 (/ (- new-price old-price) old-price)))

(defstruct purchase amount original-price)

;; - Whenever the closing cost is down 3% or more from the previous closing cost, buy shares with 10% of current cash.
;; - Whenever the closing cost is up 6% or more from the original purchase price, sell back the full amount of stock purchased at that price.
;; - Sell off any remaining assets after the last day.

(defun run ()
  (let ((assets)
	(cash 10000)
	(records (read-gspc)))
    (map nil #'(lambda (day-1-record day-2-record)
		 (let* ((cost1 (closing-cost day-1-record))
			(cost2 (closing-cost day-2-record))
			(change (percent-change cost1 cost2)))
		   ;; buy
		   (when (<= change -3)
		     (let ((cost (* cash 1/10)))
		       (decf cash cost)
		       (push (make-purchase :amount (/ cost cost2) :original-price cost2) assets)
		       (format t "buy ~S~%" (car assets))))
		   ;; sell
		   (labels ((high-enough (asset)
			      (let ((change (percent-change (purchase-original-price asset) cost2)))
				(>= change 6))))
		     (dolist (asset (remove-if-not #'high-enough assets))
		       (incf cash (* (purchase-amount asset) cost2))
		       (format t "sell ~S change%=~A~%" asset (percent-change (purchase-original-price asset) cost2)))
		     (setf assets (remove-if #'high-enough assets)))
		   ;; display
		   (format t "~A closing=~A change%=~A cash=~A assets=~S~%" (date day-2-record) (closing-cost day-2-record) change cash assets)))
	 records
	 (cdr records))
    
    ;; sell remaining assets
    (dolist (asset assets)
      (incf cash (* (purchase-amount asset) (closing-cost (car (last records))))))
    ;; display
    (format t "~A ~S~%" cash assets)))