On a quick glance I'd suggest (in addition to the responses already given) to (a) use a more efficient structure for holding events (Data.Sequence or maybe Pipes) since (++) has bad performance when the left argument is large (as is definitely your case), (b) for all of your "static" types, add a strictness annotation and possibly an {-# UNBOX #-}, (c) consider replacing System.Random with mwc-random, it's more efficient and has better randomness.
Diving into processOrder since it's the big time/space hog I think strictness annotations might help uniformly since there's a lot of packing/unpacking going on. To really dig in you can add some manual SCC annotations or dump core on it and see what's doing all the indirection.
These are all pretty general, high-level Haskell performance notes, by which I mean if you learn them once you'll be able to apply them much more quickly in the future whenever you find bottlenecks.
Yeah, a good starting point is that if something is running slow, and if there's lists involved, look at how you're using them. Also, as a special case, replace String with (strict or lazy) Text or Bytestring, as appropriate.
Would like to note I've spent more time trying to optimize this[1] than writing code, however.
http://stackoverflow.com/questions/21654081/how-do-i-optimis...