Dealing with Tricky End-of-Day Pricing Issues
One of the things that has come up in recent days is the quality of the end-of-day marks that the greek engine is using. The code tries pretty hard to get the right number, and it does a good job on getting the 'close' right, but it's another thing when it comes to calculating the last value of the day. After all, the greeks are meant to calculate on the 'close' - just the 'last', and that is the real problem.
The option pricer in the engine looks for the 'spot' - the price of the underlying that is used in the calculations, and it has a rather complex logical path based on the instrument type of the underlying, and what data is defined for it. Not hard to see, but sufficiently complex. In order to make it so that we include the 'close' in this logic might make it a lot worse before it gets better.
For example, we have the logic that an option will only be updated if it's a valid trading day (no need for weekends, holidays), and if it's during market hours for that instrument. The wrinkle here is that "during market hours" is updated only every couple of seconds at best, and what we really need is to look at the exchange timestamp on the message and see if it's something to include in the calculation set.
But we don't have that data in the right place in the code. It wasn't really designed for this, and there's where I blame myself. I allowed a junior guy who had been working with the legacy pricing server to lead the charge on this part of the code. As a consequence, it's a mess. It really is. We have objects with really questionable APIs, very bad separation of duties, etc. It's a mess.
But I have to live with it at this point, because so much is done, and the time required to fix it would not be allowed. That's a real shame. I'd like to fix it, and I'm not sure it's all that much time, but it's more than will be allowed, I'm sure. Even if it too no time, they'd oppose it on risk and rewards grounds.
So I have to figure out how to make this work with the tools at hand. Not as fun a job, but it's the job for today.
[12:35] UPDATE: well… I've got two little sections of code to work with. The first I've just put in is the check to make sure that - during market hours - the print must be a "qualified trade" from the exchange to update the 'last' price on the Instrument. The old code:
if (!isnan(aPrint.getPriceAsInt()) && ((mPrint.last.price != aPrint.getPriceAsInt()) || (mPrint.last.size != aPrint.getSize()) || (mPrint.last.exchange != aPrint.getExchange()))) { // update all the components of the print mPrint.last.price = aPrint.getPriceAsInt(); mPrint.last.size = aPrint.getSize(); mPrint.last.exchange = aPrint.getExchange(); // ...and don't forget the timestamp mPrintTimestamp = now; }
became:
bool isMH = isMarketHours(aPrint.getCreationTimestamp()); bool isLPC = aPrint.isLastPriceChanged(); if (!isnan(aPrint.getPriceAsInt()) && ((isMH && isLPC) || !isMH) && ((mPrint.last.price != aPrint.getPriceAsInt()) || (mPrint.last.size != aPrint.getSize()) || (mPrint.last.exchange != aPrint.getExchange()))) { // update all the components of the print mPrint.last.price = aPrint.getPriceAsInt(); mPrint.last.size = aPrint.getSize(); mPrint.last.exchange = aPrint.getExchange(); // ...and don't forget the timestamp mPrintTimestamp = now; }
The addition should work just as needed - if it's during the market hours, it needs to have the last price changed flag set. If not, take it anyway. Nice to have it be so surgical.