I am pricing financial instruments, and each financial instrument object requires a day counter as a property. There are 4 kinds of day counters which have different implementations for each of their two methods, year_fraction
and day_count
. This day counter property on financial instruments is used in other classes when pricing, to know how to discount curves appropriately, etc. However, all of the day count methods are static, and doing nothing more than applying some formula.
So despite everything I've read online telling me to not use static methods and just have module-level functions instead, I couldn't see a way to nicely pass around the correct DayCounter without implementing something like this
class DayCounter:
__metaclass__ = abc.ABCMeta
@abc.abstractstaticmethod
def year_fraction(start_date, end_date):
raise NotImplementedError("DayCounter subclass must define a year_fraction method to be valid.")
@abc.abstractstaticmethod
def day_count(start_date, end_date):
raise NotImplementedError("DayCounter subclass must define a day_count method to be valid.")
class Actual360(DayCounter):
@staticmethod
def day_count(start_date, end_date):
# some unique formula
@staticmethod
def year_fraction(start_date, end_date):
# some unique formula
class Actual365(DayCounter):
@staticmethod
def day_count(start_date, end_date):
# some unique formula
@staticmethod
def year_fraction(start_date, end_date):
# some unique formula
class Thirty360(DayCounter):
@staticmethod
def day_count(start_date, end_date):
# some unique formula
@staticmethod
def year_fraction(start_date, end_date):
# some unique formula
class ActualActual(DayCounter):
@staticmethod
def day_count(start_date, end_date):
# some unique formula
@staticmethod
def year_fraction(start_date, end_date):
# some unique formula
So that in a pricing engine for some particular instrument that is passed an instrument as a parameter, I can use the instrument's day counter property as needed.
Am I missing something more idiomatic / stylistically acceptable in Python or does this seem like appropriate use for static method-only classes?
Example:
I have a class FxPricingEngine, which has an __init__
method passed an FxInstrument and subsequent underlying_instrument
property. Then in order to use the Value
method of my pricing engine I need to discount a curve with a particular day counter. I have a YieldCurve
class with a discount
method to which I pass self.underlying_instrument.day_counter.year_fraction
such that I can apply the correct formula. Really all that the classes are serving to do is provide some logical organization for the unique implementations.
As it is, object orientation does not make any sense in your scenario: there is no data associated with an instance of your types, so any two objects of some type (e.g. Thirty360
) are going to be equal (i.e. you only have singletons).
It looks like you want to be able to parametrise client code on behaviour - the data which your methods operate on is not given in a constructor but rather via the arguments of the methods. In that case, plain free functions may be a much more straight forward solution.
For instance, given some imaginary client code which operates on your counters like:
def f(counter):
counter.day_count(a, b)
# ...
counter.year_fraction(x, y)
...you could just as well imagine passing two functions as arguments right away instead of an object, e.g. have
def f(day_count, year_fraction):
day_count(a, b)
# ...
year_fraction(x, y)
On the caller side, you would pass plain functions, e.g.
f(thirty360_day_count, thirty360_year_fraction)
If you like, you could also have different names for the functions, or you could define them in separate modules to get the namespacing. You could also easily pass special functions like way (for instance if you only need the day_count to be correct but the year_fraction could be a noop).