Today I needed to get really busy on the next phase of my web server/services - intraday alerts. Basically, we need to have a system whereby it's relatively easy to configure multiple alerts based on the data we collect about the company during the day. The first test is a simple one - if the P/L of any portfolio jumps more than a $1 mil in one tick - either way, then it's something I need to know about because it's likely bad data.
You can think of a lot more business-useful cases where it's not the data that's wrong, as in this first case, but that is going to bring into focus the moving average code I wrote as well as a much more complicated set of rules than simple edge-triggering. So what I wanted to do was to make a system a lot like we had with InfoShop in my last job: basic tools all wired together, but not configured until they are put in place in a configuration file.
I like the Java Properties file format for this, but primarily in it's ability to dovetail nicely with the System Properties and overlay multiple files, one on top of the other. The idea is to have the property files specified in the web.xml file as a list where order matters, and the list is loaded and layered on top of the System Properties so that the complete configuration of any component can be parsed from this map.
Then, I'll have as one named property a list of names. These will then be added to the 'baseProperty' name - something used to keep the Property namespace clean, and these will then be parsed and created by the system. It's a pretty easy way to have a config file do all the building and running you need while not having it be as overly complex as say, Spring.
My initial file looks like:
#
# List all the named alerts to create
#
FC.Alerts=CrazyJump
#
# CrazyJump - send email on big jump
#
FC.Alert.CrazyJump.ClassName=com.chicagotrading.firecache.trigger.BasicAlert
FC.Alert.CrazyJump.Portfolio=[*]
FC.Alert.CrazyJump.AlertExpr=abs((pnlSumNet - lastPnlSumNet)*fxToUSD) > 1000000
FC.Alert.CrazyJump.MailTo=robert.beaty@chicagotrading.com
FC.Alert.CrazyJump.Message="Portfolio " + portfolio + " jumped"
And from this, it's pretty easy to see where the name is used, and that there are a few mandatory properties for each named alert - the ClassName for instance. But there can be a lot of optional ones as well - dictated by the class that is functioning as the alert.
This is where the BasicAlert comes into play - we needed to build it with all the capabilities a general alert would need. Like the ability to parse expressions... send emails... create messages. All these things will be needed by the subclasses that will be the far more interesting alerts to write with far more complex business logic.
Still, it'll be relatively easy. We have a simple init() method that will be called, and then an onUpdate() for each updated row to check. It's a pretty simple pattern that's been used a lot in Java, which is why I used it. There's almost no Java coder that won't recognize this when he sees it. Consequently, it'll be easy for just about anyone to pick up and make an alert.
It took me the majority of the day to get this to the point that I think it's ready to use. Lots of set-up for the uses I'm trying to see will need to be covered. Thankfully, I've done something like this a couple of times before and have a really good idea about what needs to be done for the vast majority of the cases, and a few little things that will make even the odd-ball case possible.
I'm tired, and that's the way I like it. Leave it all on the track. Hold nothing back.