Programming performance/Yasuo Common Lisp

From HaskellWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
#|
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)))