计算期权变动量的最佳做法

时间:2019-05-04 12:03:10

标签: python function local-variables

期权是基于某些潜在证券的价值(通常是股票价格)的衍生合约。正式而言,在定价模型下,期权价格是s0,当前基础证券价格,其他参数(波动率,利率,股息率等)的 lot 的函数,以及一些可能的kwargs

期权的Delta是相对于基础证券价格的价格变化率。实际上,这是像

一样实现的

(calc_price(s0 + ds, **kwargs) - calc_price(s0 - ds, **kwargs)) / (2 * ds)

我想做的是将get_delta作为Option类的方法实现。现在,我为该选项实现了定价模型:

class Option:
    def __init__(self, s0, lots_of_args, **kwargs):
        self.s0 = s0

        # actually there's a list of lots of args, not packed
        self.lots_of_args = lots_of_args
        # actually kwargs are unpacked either,
        self.kwargs = kwargs

    def calc_price(self):
        price = ...
        return price

    def get_delta(self, ds=.05):
        cd = Option(self.s0 - ds, self.lots_of_args, **self.kwargs).calc_price()
        cu = Option(self.s0 + ds, self.lots_of_args, **self.kwargs).calc_price()   
        return (cu - cd) / (2 * ds)

问题在于,除了s0之外,确实还有一个 lot 个参数(表示为 lots_of_args ,但实际上它们不是单个arg,但其中有十二个),因此我真的很讨厌将它们一个一个地复制到get_delta函数中。我需要一种方法来确定传递给__init__的arg的字典。当然,首先想到的是使用locals()。但是,存在一些问题:

  1. 包含了额外的self arg。

  2. kwargs没有打开包装。

  3. doc on locals()建议不要修改locals()返回的字典,所以我认为del的{​​{1}} arg和{ {1}}开箱的self

有人可以帮忙吗?谢谢。

3 个答案:

答案 0 :(得分:2)

如何复制?

import copy

class Option:
    def __init__(self, s0, lots_of_args, **kwargs):
        self.s0 = s0

    def calc_price(self):
        price = ...
        return price

    def get_delta(self, ds=.05):
        cd = copy.copy(self)
        cd.s0 -= ds
        cu = copy.copy(self)
        cu.s0 += ds

        return (cu.calc_price() - cd.calc_price()) / (2 * ds)

如果您的类具有某些dict / list attrs(或使用其他可变类的attrs),那么您可能想要使用copy.deepcopy(例如,如果calc_price()更改了这些属性)。

您可以定义__copy__方法来自定义创建副本的方式。

答案 1 :(得分:1)

如果您只需要复制这些“大量的args”而无需更改它们,则可以使用类似于namedtuple_replace方法的方法:

>>> import collections
>>> Option = collections.namedtuple('Option', 'a b c d e f')
>>> opt = Option(a=1, b=2, c=3, d=4, e=5, f=6)
>>> opt
Option(a=1, b=2, c=3, d=4, e=5, f=6)
>>> new_opt = opt._replace(a=74)
>>> new_opt
Option(a=74, b=2, c=3, d=4, e=5, f=6)  # only 'a' changed, all other args remained the same

然后您的get_delta()方法将如下所示:

def get_delta(self, ds=.05):
    cd = self._replace(s0=self.s0 - ds).calc_price()
    cu = self._replace(s0=self.s0 + ds).calc_price()   
    return (cu - cd) / (2 * ds)

是直接从namedtuple继承还是创建自己的类似_replace的方法都由您决定。

答案 2 :(得分:0)

为什么不修改calc_price方法以包含ds? 然后,get_delta简化为以正负ds调用calc_price:

def calc_price(self, ds=0):
    s0 = self.s0 + ds 
    price = ... return price 

def get_delta(self, ds=.05): 
    cd = self.calc_price(-ds)
    cu = self.calc_price(ds) 
    return (cu - cd) / (2 * ds) here