8 min read

In this article, by Timothy Washington, author of the book Clojure for Finance, we will cover the following topics:

  • Modeling the stock price activity
  • Function evaluation
  • First-Class functions
  • Lazy evaluation
  • Basic Clojure functions and immutability
  • Namespace modifications and creating our first function

(For more resources related to this topic, see here.)

Modeling the stock price activity

There are many types of banks. Commercial entities (large stores, parking areas, hotels, and so on) that collect and retain credit card information, are either quasi banks, or farm out credit operations to bank-like processing companies. There are more well-known consumer banks, which accept demand deposits from the public. There are also a range of other banks such as commercial banks, insurance companies and trusts, credit unions, and in our case, investment banks. As promised, this article will slowly build up a set of lagging price indicators that follow a moving stock price time series. In order to do that, I think it’s useful to touch on stock markets, and to crudely model stock price activity. A stock (or equity) market, is a collection of buyers and sellers trading economic assets (usually companies). The stock (or shares) of those companies can be equities listed on an exchange (New York Stock Exchange, London Stock Exchange, and others), or may be those traded privately.

In this exercise, we will do the following:

  • Crudely model the stock price movement, which will give us a test bed for writing our lagging price indicators
  • Introduce some basic features of the Clojure language

Function evaluation

The Clojure website has a cheatsheet (http://clojure.org/cheatsheet) with all of the language’s core functions. The first function we’ll look at is rand, a function that randomly gives you a number within a given range. So in your edgar/ project, launch a repl with the lein repl shell command. After a few seconds, you will enter repl (Read-Eval-Print-Loop). Again, Clojure functions are executed by being placed in the first position of a list. The function’s arguments are placed directly afterwards.

  • In your repl, evaluate (rand 35) or (rand 99) or (rand 43.21) or any number you fancy
  • Run it many times to see that you can get any different floating point number, within 0 and the upper bound of the number you provided

First-Class functions

The next functions we’ll look at are repeatedly and fn. repeatedly is a function that takes another function and returns an infinite (or length n if supplied) lazy sequence of calls to the latter function. This is our first encounter of a function that can take another function. We’ll also encounter functions that return other functions. Described as First-Class functions, this falls out of lambda calculus and is one of the central features of functional programming.

As such, we need to wrap our previous (rand 35) call in another function. fn is one of Clojure’s core functions, and produces an anonymous, unnamed function. We can now supply this function to repeatedly.

In your repl, if you evaluate (take 25 (repeatedly (fn [] (rand 35)))), you should see a long list of floating point numbers with the list’s tail elided.

Lazy evaluation

We only took the first 25 of the (repeatedly (fn [] (rand 35))) result list, because the list (actually a lazy sequence) is infinite. Lazy evaluation (or laziness) is a common feature in functional programming languages. Being infinite, Clojure chooses to delay evaluating most of the list until it’s needed by some other function that pulls out some values. Laziness benefits us by increasing performance and letting us more easily construct control flow. We can avoid needless calculation, repeated evaluations, and potential error conditions in compound expressions. Let’s try to pull out some values with the take function. take itself, returns another lazy sequence, of the first n items of a collection.

Evaluating (take 25 (repeatedly (fn [] (rand 35)))) will pull out the first 25 repeatedly calls to rand which generates a float between 0 and 35.

Basic Clojure functions and immutability

There’s many operations we can perform over our result list (or lazy sequence). One of the main approaches of functional programming is to take a data structure, and perform operations over top of it to produce a new data structure, or some atomic result (a string, number, and so on). This may sound inefficient at first. But most FP languages employ something called immutability to make these operations efficient. Immutable data structures are the ones that cannot change once they’ve been created. This is feasible as most immutable, FP languages use some kind of structural data sharing between an original and a modified version. The idea is that if we run evaluate (conj [1 2 3] 4), the resulting [1 2 3 4] vector shares the original vector of [1 2 3]. The only additional resource that’s assigned is for any novelty that’s been introduced to the data structure (the 4). There’s a more detailed explanation of (for example) Clojure’s persistent vectors here:

  • conj: This conjoins an element to a collection—the collection decides where. So conjoining an element to a vector (conj [1 2 3] 4) versus conjoining an element to a list (conj ‘(1 2 3) 4) yield different results. Try it in your repl.
  • map: This passes a function over one or many lists, yielding another list. (map inc [1 2 3]) increments each element by 1.
  • reduce (or left fold): This passes a function over each element, accumulating one result. (reduce + (take 100 (repeatedly (fn [] (rand 35))))) sums the list.
  • filter: This constrains the input by some condition.
  • >=: This is a conditional function, which tests whether the first argument is greater than or equal to the second function. Try (>= 4 9) and (>= 9 1).
  • fn: This is a function that creates a function. This unnamed or anonymous function can have any instructions you choose to put in there.

So if we only want numbers above 12, we can put that assertion in a predicate function. Try entering the below expression into your repl:

(take 25 (filter (fn [x] (>= x 12))
             (repeatedly (fn [] (rand 35)))))

Modifying the namespaces and creating our first function

We now have the basis for creating a function. It will return a lazy infinite sequence of floating point numbers, within an upper and lower bound. defn is a Clojure function, which takes an anonymous function, and binds a name to it in a given namespace. A Clojure namespace is an organizational tool for mapping human-readable names to things like functions, named data structures and such. Here, we’re going to bind our function to the name generate-prices in our current namespace. You’ll notice that our function is starting to span multiple lines. This will be a good time to author the code in your text editor of choice. I’ll be using Emacs:

  1. Open your text editor, and add this code to the file called src/edgar/core.clj. Make sure that (ns edgar.core) is at the top of that file.
  2. After adding the following code, you can then restart repl. (load “edgaru/core”) uses the load function to load the Clojure code in your in src/edgaru/core.clj:
    (defn generate-prices [lower-bound upper-bound]
         (filter (fn [x] (>= x lower-bound))
                 (repeatedly (fn [] (rand upper-bound)))))

The Read-Eval-Print-Loop

In our repl, we can pull in code in various namespaces, with the require function. This applies to the src/edgar/core.clj file we’ve just edited. That code will be in the edgar.core namespace:

  1. In your repl, evaluate (require ‘[edgar.core :as c]). c is just a handy alias we can use instead of the long name.
  2. You can then generate random prices within an upper and lower bound. Take the first 10 of them like this (take 10 (c/generate-prices 12 35)).
  3. You should see results akin to the following output. All elements should be within the range of 12 to 35:
    (29.60706184716407 12.507593971664075 19.79939384292759 31.322074615579716 19.737852534147326 25.134649707849572 19.952195022152488 12.94569843904663   23.618693004455086 14.695872710062428)

There’s a subtle abstraction in the preceding code that deserves attention. (require ‘[edgar.core :as c]) introduces the quote symbol. is the reader shorthand for the quote function. So the equivalent invocation would be (require (quote [edgar.core :as c])). Quoting a form tells the Clojure reader not to evaluate the subsequent expression (or form). So evaluating ‘(a b c) returns a list of three symbols, without trying to evaluate a. Even though those symbols haven’t yet been assigned, that’s okay, because that expression (or form) has not yet been evaluated.

But that begs a larger question. What is reader? Clojure (and all Lisps) are what’s known as homoiconic. This means that Clojure code is also data. And data can be directly output and evaluated as code. The reader is the thing that parses our src/edgar/core.clj file (or (+ 1 1) input from the repl prompt), and produces the data structures that are evaluated. read and eval are the 2 essential processes by which Clojure code runs. The evaluation result is printed (or output), usually to the standard output device. Then we loop the process back to the read function. So, when the repl reads, your src/edgar/two.clj file, it’s directly transforming that text representation into data and evaluating it. A few things fall out of that. For example, it becomes simpler for Clojure programs to directly read, transform and write out other Clojure programs. The implications of that will become clearer when we look at macros. But for now, know that there are ways to modify or delay the evaluation process, in this case by quoting a form.

Summary

In this article, we learned about basic features of the Clojure language and how to model the stock price activity. Besides these, we also learned function evaluation, First-Class functions, the lazy evaluation method, namespace modifications and creating our first function.

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here