rquantlib
rquantlib copied to clipboard
New vanilla option FD schemes
Hello,
I have tweaked americanOptionEngine
to handle the new FD schemes described here for European options. (See EuropeanOptionTest::testPDESchemes()
) It seems to work fine, although some unit tests would be good.
I'm also interested to add FD schemes to europeanOptionEngine
, for comparison purposes mostly, but I haven't yet.
Would you be interested in a PR? If so, I need to clean up a few (small) things before I push changes to my repo, and possibly discuss the interface for the EuropeanOption function. Adding an engine
parameter as the last argument would likely make the most sense, to not break compatibility. But, this would be inconsistent with AmericanOption, where engine
comes before the discrete dividend vectors.
Thanks as always for your work on this, and let me know your thoughts!
Would you be interested in a PR?
Sure, especially from experienced contributors.
Remind me, again, why we want FDs for European Options that do have closed form solutions?
Ha, don't know if I'm an experienced contributor, but my C++ skills have gotten a little better since last time!
I think the main reason is to cope with discrete dividends. For dividends, currently AnalyticDividendEuropeanEngine
is used. From what I understand of the Quantlib code, they use an escrowed dividend approach (though it looks like dividends are discounted at r_f-d and not at r_f, not sure why). I don't believe it's much of a problem with European options, but since other schemes are available, it would be nice to benchmark them.
An additional reason could be to check the approximation schemes do converge to BSM, and how quickly. Probably a nice sanity check before using them on American options, where we don't have the closed-form solution.
I’ve pushed changes for AmericanOption to my cloned repo:
https://github.com/fcocquemas/rquantlib/
However, I haven’t submitted a pull request yet. Two main reasons.
-
I noticed
makeOption()
in utils.cpp, which is copied from an (old) QL test. It basically does all the work of setting up EuropeanOption (without discrete dividend) and cleans upeuropeanOptionEngine
. However, the many algorithms inmakeOption()
are not exposed. It would perhaps be valuable to change that. I could repackage my changes asmakeAmericanOption()
, and changemakeOption()
tomakeEuropeanOption()
, and add some parameter for discrete dividends - in essence move most of the logic out ofeuropeanOptionEngine
andamericanOptionEngine
. Or, just removemakeOption
, since most of it is currently not used, and merged that back intoeuropeanOptionEngine
.I would also like to add the FD schemes to
europeanOptionEngine
. CurrentlyCrankNicolson
is set up inmakeOption
, but not accessible.Note that parameters timeSteps, gridPoints, and engine would have to be added to europeanOptionEngine and the corresponding R function. The order would either be different from the American counterpart, or we’d have to break backward compatibility, which is probably worse. What do you think?
-
I still need to change the documentation, but I want to make sure point 1 is finalized before I do. Should I also add tests? I’m not sure what the best approach is here. QL does not have great coverage, especially for American options. Here’s the code I used to make sure all the models were working (only tests one set of parameters):
https://gist.github.com/fcocquemas/4f8dfed4bae94e8c23c4c46c8bd68623
Let me know your thoughts. I wager you’ll have some suggestions on my code. While I was at it, I added all the Greeks back to the BaroneAdesiWhaley approximation method. I couldn’t figure out the reason they were off.
-
Good point / good plan. We can generalize as needed. Concurrent with your PR or in another?
-
Tests are great. I am converting my packages to using (R package) tinytest. And if you look for example at this branch in RcppEigen (where I am currently doing this) and compare it to the old way (using RUnit) you will see it is like night and day. Now we have simple + clean C++ files in in
cpp/
within the tests, and just call them. We could (should !!) easily do that for RQuantLib and then build on that.
Deal?
PS Wasn;t that the set of greeks that was on/off upstream for a while?
Deal!
- Up to you. I think getting all engines done in one PR could be better? Especially wrt changes to the documentation/interface.
I think a generic template for makeOption that could handle VanillaOption
and DividendVanillaOption
would make sense. (Templating is still new to my skill set, but this should be simple enough.) Then glue logic to make sure we don't call a combination that doesn't work in europeanOptionEngine
and americanOptionEngine
?
- Wow, it looks SO MUCH NICER. I'm going to use tinytest going forward, for sure. How should this fit in point 1? It's a mostly independent task, I think?
PS. No idea. Can't find anything about it in the QL changelog.
Sounds good to me. Re 1) why don't you plow along with the options related changes (but not yet tests). Once I am done with RcppEigen I can convert RQuantLib -- it is perfect bite-sized code work for my short commute. In a week or so that should be done and we can get to 2) of adding some first tests for your new FD schemes ... and then take a deep breath and maybe add more tests from QL and in general?
As for the (non-analytical) greeks, I think we had "many" of them "at inception" and then some "disappeared" so I had empty placeholders. And now I may have missed that they are back. So thanks for filling that in.
Sounds good to me, too.
For the Greeks, with the FD schemes you only get the delta and the gamma. However, with BaroneAdesiWhaley, you get the full set (explicit formulas).
FYI -- I just merged #140 so we now have tinytest which should make adding tests pretty easy.
Nice. We can probably borrow some tests from Quantlib.
I'm still trying to refactor so that there's not too much duplicated code. One issue I'm having is figuring out how to detect which Greeks are provided or not. Not all schemes provide them/all of them. I'd rather avoid more if()
spaghetti if there's a nicer way to do that.