Lazy evaluation is popular in functional programming, whereby the evaluation of expressions is deferred until when they are actually needed. The purely functional language Haskell defaults to lazy evaluation for all function evaluations. It is one of the core building blocks in functional programming underpinning the notion of functional composition which is very powerful (or lazy - sorry...) once you get used to treating functions as first class types.
But, I digress, a simple use case is in generating infinite streams of values, whereby each value is only generated when needed. This enables you to create sequences of values such as Fibonacci numbers, or even replicate stochastic processes.
For instance, we can use a GARCH(1,1) model to generate a volatility forecast, where our volatility at time is given by the following variance equation.
The value of parameters , and should be found using an optimisation algorithm which I'll talk more about in another post.
The following function defines a GARCH(1,1) annualised volatility generator:
from math import sqrt import numpy as np def lazy_garch(omega, alpha, beta, var): last_var = var epsilon = np.random.randn() * sqrt(var) while True: var = omega + (alpha * epsilon**2) + (beta * last_var) yield sqrt(var) * sqrt(252.0) last_var = var epsilon = np.random.randn() * sqrt(last_var)
The parameters configure the generator, and the yield expression provides our next value which we access via the iterator next() function.
garch = lazy_garch(omega, alpha, beta, var) # define our generator garch.next() # generate a value
We now have a generator we can use in our GARCH models.