> My idea is to write something like TradeStation  or NinjaTrader, only for the Mac.<br>> It would be quite nifty to use SPJ's financial combinator approach<br><br>I was experimenting with a Haskell EDSL for financial trading not too long ago. My favorite strategy so far is the parallel parser combinator approach. It allows users to run many parallel trading strategies in a nice single-threaded way that's easy to reason about and straightforward to compose new trading strategies.
<br><br>The idea is that the user composes an 'openPosition' and 'closePosition' trading strategies from a combinator library and gives them to the trading platform. The user's trading strategies are nothing more than a numeric parser combinators. With each incoming quote, the trading platform kicks off the user's 'openPosition' trading strategy. When a strategy succeeds (a successful parse), the trading platform opens a position for the user. Once a position is opened, the platform starts running the user's 'closePosition' strategy. The closePosition parser is run the same way and when it succeeds, the user's position is closed.
<br><br>To implement, I leveraged Twan van Laarhoven's ParseP library (<a href="http://twan.home.fmf.nl/parsep/">http://twan.home.fmf.nl/parsep/</a>), which at least for my
simple experiments, was incredibly complete and stable given its 0.1
version number. Why ParseP and not Parsec or ReadP? Parsec doesn't have an unbiased choice operator and ReadP only works on strings.<br><br>Implementing context-free trading strategies like limit orders is very easy (limitOrder price = satisfy (>= price)), but context-sensitive strategies, such as "match the longest string of increasing numbers" is quite a bit more painful. Below are some of my experiments (also on hpaste:
<a href="http://hpaste.org/3756">http://hpaste.org/3756</a>). If anybody could offer more elegant solutions, I'd love to hear because this still feels overly complicated to me. 'testUpThenDown' matches an input stream that increases then decreases. 'testNumericFib' will try to match as much of the Fibonacci sequence as possible.
<br><br><br>import Text.ParserCombinators.ParseP<br>import qualified Text.ParserCombinators.ParseP.Greedy as Greedy<br>import Control.Applicative<br>import Data.Monoid<br><br>testUpThenDown = print $ runParser coaster [1, 2, 1]
<br>testNumericFib = print $ runParser (fib (Sum 1) (Sum 1)) (map Sum [2, 3, 5, 7, 1])<br>testAlphaFib = print $ runParser (fib "a" "b") ["ab", "bab", "cad"]<br><br>fib :: (Eq a, Monoid a) => a -> a -> Parser a p [a]
<br>fib n1 n2 = Greedy.option  (do<br> n3 <- satisfy (== (n1 `mappend` n2)) <br> ns <- fib n2 n3<br> return (n3:ns))<br><br>coaster :: Ord a => Parser a p ([a], [a])<br>coaster = do<br> seed <- get<br>
up <- increasing seed<br> down <- decreasing (last up)<br> return (seed:up, down)<br><br>increasing seed = trend (<) seed<br>decreasing seed = trend (>) seed<br><br>trend :: (Monad (Parser a p)) => (a -> a -> Bool) -> a -> Parser a p [a]
<br>trend f = many1WithContext (satisfy . f)<br><br>manyWithContext p = Greedy.option  . many1WithContext p<br><br>many1WithContext p seed = do<br> n <- p seed<br> ns <- manyWithContext p n<br> return (n:ns)
<br><br><br>Thanks,<br>Greg<br><br><br><br><br><div class="gmail_quote">On Nov 7, 2007 5:02 PM, Joel Reymont <<a href="mailto:firstname.lastname@example.org">email@example.com</a>> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I need to pick among the usual list of suspects for a commercial<br>product that I'm writing. The suspects are OCaml, Haskell and Lisp and<br>the product is a trading studio. My idea is to write something like<br>TradeStation  or NinjaTrader, only for the Mac.
<br><br>It would be quite nifty to use SPJ's financial combinator approach<br>and, for example, embed Yi (Haskell editor).<br><br>One of the key features of the product would be the ability to model<br>your trading logic using a trading DSL. I'm thinking that this DSL
<br>could well be Haskell but I'm concerned about stepping into a minefield.<br><br>I will need to embed GHC into the app, for example, and I understand<br>that the GHC API does not offer unloading of code at the moment. I
<br>would prefer not to bundle GHC separately so I don't think the hs-<br>plugins approach would work for me. Maybe I'm mistaken.<br><br>Most of all, I'm concerned that my users will need to face the error<br>
reports from GHC and could get tripped by laziness, i.e. write<br>something that would make the app run out of memory. Off the top of my<br>head I can't figure out a way to limit what my users can do without<br>analyzing the Haskell AST within the GHC API and complaining if
<br>necessary.<br><br>Can someone with experience in offering a Haskell DSL to their users<br>please comment?<br><br>Notice that I'm not even mentioning being concerned with the<br>unpredictable effects of laziness. There's probably a reason why Jane
<br>St Capital is using OCaml instead of Haskell. I'm not going to play in<br>that league but my knee-jerk reaction is to use OCaml or Lisp and<br>avoid laziness altogether. I just can't see how laziness can help in
<br>processing real-time price data.<br><br> Thanks, Joel<br><br> <a href="http://www.tradestation.com/default_2.shtm" target="_blank">http://www.tradestation.com/default_2.shtm</a><br> <a href="http://www.ninjatrader.com/webnew/index.htm" target="_blank">
http://www.ninjatrader.com/webnew/index.htm</a><br><br>--<br><a href="http://wagerlabs.com" target="_blank">http://wagerlabs.com</a><br><br><br><br><br><br>_______________________________________________<br>Haskell-Cafe mailing list
<br><a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br><a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br></blockquote>