[EMAIL PROTECTED] (Harvey J. Stein) writes:
> I was surprised that the compiler doesn't figure out that s is a
> fixnum as well, given that I start off by assigning it to zero, and
> only add fixnums to it, but in retrospect, to do be completely
> correct, the compiler would have to sum the series to be able to
> safely deduce this, so of course it won't.
Following up on this, I liberally sprinkled additional declarations
around the code. This got me out of GC & into the range of C code
(no more than 50% slower). I'm probably down to the speed of the
random number generator now. However, I still get some weird notes &
warnings from the compiler. Maybe someone can clue me in on them.
Here's the code.
(eval-when (compile)
(proclaim '(optimize (speed 3) (safety 1) (space 0) (debug 0))))
(defconstant SQRT2OVERE (the double-float (sqrt (/ 2d0 (exp 1d0)))))
(eval-when (compile)
(proclaim '(type double-float SQRT2OVERE)))
;; (eval-when (compile)
;; (proclaim '(inline one-normal-rand
;; callpay)))
(defun one-normal-rand ()
(declare (values (double-float)))
(loop
(let* ((u (random 1d0))
(u1 (random 1d0))
(v (* SQRT2OVERE (- (* 2d0 u1) 1d0)))
(x (/ v u))
(y (/ (* x x) 4d0)))
(if (or (<= y (- 1d0 u))
(<= y (- (log u))))
(return x)))))
(defun callpay (s k)
(declare (type double-float s k)
(values double-float))
(- (max s k)
k))
(defun bsmc (s0 sigma mat k r steps trials)
(declare (type (double-float (0d0) 1d100) s0 sigma mat r)
; (type (integer 1 1000000) steps trials))
(type fixnum steps trials))
"(BSMC S0 SIGMA MAT K R STEPS TRIALS &optional (debug ())) Returns
Black Scholes option price for an option with maturity MAT & strike K,
on a stock with initial price S0 and volatility SIGMA. Risk free rate
is R. Monte-carlo of 2*TRIALS paths of STEPS timesteps each. Turn on
DEBUG to dump intermediate values. Uses antithetic sampling."
(let* ((dt (/ mat steps))
(drift (* (- r (* .5d0 sigma sigma)) mat))
(vol (* sigma (sqrt dt)))
(sumval 0d0))
(declare (type (double-float (0d0)) dt drift vol sumval))
(dotimes (i trials)
(declare (type (integer 1 1000000) i))
(let ((s 0d0))
(declare (type (double-float (0d0) 1d100) s))
(dotimes (j steps)
(declare (type (integer 1 1000000) j))
(incf s (one-normal-rand)))
(incf sumval
(+
(callpay (* s0 (exp (+ drift (* vol s))))
k)
(callpay (* s0 (exp (+ drift (* vol (- s)))))
k)))))
(* (exp (* -1d0 r mat))
(/ sumval trials 2d0))))
Here are the notes:
Converted ONE-NORMAL-RAND.
Compiling DEFUN ONE-NORMAL-RAND:
File: /home/hjstein/Quadrus/bsmc-cl-min6.lisp
In: DEFUN ONE-NORMAL-RAND
(DEFUN ONE-NORMAL-RAND ()
(DECLARE (VALUES #))
(LOOP
(LET* #
#)))
Note: Doing float to pointer coercion (cost 13) to "<return value>".
Converted CALLPAY.
Compiling DEFUN CALLPAY:
File: /home/hjstein/Quadrus/bsmc-cl-min6.lisp
In: DEFUN CALLPAY
(DEFUN CALLPAY (S K)
(DECLARE (TYPE DOUBLE-FLOAT S K) (VALUES DOUBLE-FLOAT))
(- (MAX S K) K))
Note: Doing float to pointer coercion (cost 13) to "<return value>".
Converted BSMC.
Compiling DEFUN BSMC:
File: /home/hjstein/Quadrus/bsmc-cl-min6.lisp
In: DEFUN BSMC
(LET* ((DT #) (DRIFT #) (VOL #) (SUMVAL 0.0d0))
(DECLARE (TYPE # DT DRIFT VOL ...))
(DOTIMES (I TRIALS)
(DECLARE #)
(LET # ..)))
Warning: The binding of SUMVAL is not a
(VALUES &OPTIONAL (DOUBLE-FLOAT (0.0d0)) &REST T):
0.0d0
(DOTIMES (I TRIALS)
(DECLARE (TYPE # I))
(LET (#)
(DECLARE #)
(DOTIMES # # #) ..))
--> DO BLOCK
==>
(LET ((I 0) (#:G0 TRIALS))
(DECLARE (TYPE UNSIGNED-BYTE I))
(DECLARE (TYPE # I))
(TAGBODY
(GO #:G2) ..))
Warning: The binding of I is not a
(VALUES &OPTIONAL (INTEGER 1 1000000) &REST T):
0
(LET ((S 0.0d0))
(DECLARE (TYPE # S))
(DOTIMES (J STEPS) (DECLARE #) (INCF S #))
(INCF SUMVAL (+ # #)))
Warning: The binding of S is not a
(VALUES &OPTIONAL (DOUBLE-FLOAT (0.0d0) 1.0d+100) &REST T):
0.0d0
(DOTIMES (J STEPS) (DECLARE (TYPE # J)) (INCF S (ONE-NORMAL-RAND)))
--> DO BLOCK
==>
(LET ((J 0) (#:G3 STEPS))
(DECLARE (TYPE UNSIGNED-BYTE J))
(DECLARE (TYPE # J))
(TAGBODY (GO #:G5) #:G4 (INCF S #) (PSETQ J #) ...))
Warning: The binding of J is not a
(VALUES &OPTIONAL (INTEGER 1 1000000) &REST T):
0
(DEFUN BSMC (S0 SIGMA MAT K R ...)
(DECLARE (TYPE # S0 SIGMA MAT ...) (TYPE FIXNUM STEPS TRIALS))
"(BSMC S0 SIGMA MAT K R STEPS TRIALS &optional (debug ())) Returns
Black Scholes option price for an option with maturity MAT & strike K,
on a stock with initial price S0 and volatility SIGMA. Risk free rate ..)
Note: Doing float to pointer coercion (cost 13) to "<return value>".
Byte Compiling Top-Level Form:
Compilation unit finished.
4 warnings
3 notes
Surprisingly, the compiler figured out that sumval & s aren't really
positive! Declaring them double-float instead of with a range got rid
of 2 of the warnings.
But, what about the other warnings? The manual talks about using
integer ranges instead of fixnum, so as to avoid promotion to a
bignum. However, this seems to conflict with the definition of
dotimes, which seems to declare the interation variable to be an
unsigned-byte. What to do about this? I guess I don't need to
declare them, but then (if I recall correctly, I'll have to check to
make sure) I start getting notes about coersions again, and I have
trouble giving good declarations to the fixnum args to bsmc.
Once this is explained, all that's left to explain are the coersion to
pointer notes.
The next step will be to try using the same random number generator &
heavy duty work. I presume that if I'm not GCing, and I'm not getting
compiler warnings about types, then I've got everything down to
appropriate applications of typed (non-generic) arithmetic.
Comments?
--
Harvey Stein
Bloomberg LP
[EMAIL PROTECTED]