RustQuant
RustQuant copied to clipboard
Implement a `Surface` type.
A Surface
type could represent a volatility surface, for example.
It would simply by a type with a space
dimension (e.g. strikes, spot) and a time
dimension (e.g. dates, seconds, whatever).
Possibly implement as a collection of Curve
s, with aligned initial/terminal timestamps.
I could mess with this potentially. Where were you wanting this to go? Do you want visualization?
Visualisation is not very high on the list, but could possibly make a new macro to plot a surface, e.g. plot_matrix!
(similar to the current plot_vector!
). Definitely would be a nice sanity check, and not too difficult.
The idea is that we need fairly generic Curve
and Surface
types that can represent things like yield curves, volatility surfaces, and such. These would mainly be used for pricing instruments like bonds and options.
Edit: I've come back to this issue many times and have yet to be able to settle on an implementation. For example, for the Surface
type, deciding whether to use a BTreeMap<f64, Curve>
or use something like polars::DataFrame
, ndarray::Array
, or nalgebra::Matrix
.
They each have their pros and cons. For example, obviously ndarray
or nalgebra
are better choices if we need to perform any array operations/algebra, but they don't have named dimensions which polars
or a BTreeMap
would give us.
Any thoughts ?
Typical way to store curves or surfaces is to store a mesh and a function or the function values if you have a function defined on the surface. A question would be how general do you want these meshes? For instance, do you want polygonal meshes?
If I had to guess, most of the curves/surfaces would start as graphs of functions, e.g., a curve of the form (x,f(x))
or a surface of the form (x,y,f(x,y))
. Do you want to store implicit surfaces? E.g., (x,y,z) : f(x,y,z)==0
?
My gut tells me that using ndarray
or polars
would be the choice here. With ndarray
you may want to build additional structure to store some kind of metadata as you suggest.
The function may be unknown, and the curve may simply be some market data, such as the US yield curve:
Date | 1 Mo | 2 Mo | 3 Mo | 4 Mo | 6 Mo | 1 Yr | 2 Yr | 3 Yr | 5 Yr | 7 Yr | 10 Yr | 20 Yr | 30 Yr |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
02/01/2024 | 5.49 | 5.51 | 5.42 | 5.38 | 5.15 | 4.68 | 4.20 | 3.96 | 3.80 | 3.83 | 3.87 | 4.21 | 4.10 |
In this case, we would then have the inverse problem of calibrating some function to the data, such as the Nelson-Siegel-Svensson model, which we could then also use to interpolate between the data (needed for bond pricing, etc).
And the key thing here is that we need the curves/surfaces to handle date-based indexing/construction, with my preference being time::Date
as it is what I've used in RQ so far.
ndarray
has the benefit of nice array ops, while polars
would make data IO super nice.
Which would you consider a better choice ?
Maybe polars is safe to go with given it can do a lot of nice formatting/etc. However, and not to just go back and forth, but it wouldn't be too hard to go from ndarray to polars and vice versa if need be.
If we can ensure that we can fit various models to the data and interpolation works, then polars would be awesome
I realised Polars has a to_ndarray()
method for both their Series
and DataFrame
types, so that makes life easier.