Ejemplo n.º 1
0
# Grid parameters
rate_Spot_Var = 0.5  # Proportion to solve in the var step

spot_max = 1500.0
var_max = 13.0

nspots = 100
nvols = 100

spotdensity = 7.0  # infinity is linear?
varexp = 4

spots = utils.sinh_space(k, spot_max, spotdensity, nspots)
spot = spots[min(abs(spots - spot)) == abs(spots - spot)][0]
k = spots[min(abs(spots - k)) == abs(spots - k)][0]
vars = utils.exponential_space(0.00, v0, var_max, varexp, nvols)
# vars = [v0]
# spots = linspace(0.0, spot_max, nspots)
# vars = linspace(0.0, var_max, nvols)
# plot(spots); title("Spots"); show()
# plot(vars); title("Vars"); show()

trims = (k * .2 < spots) & (spots < k * 2.0)
trimv = (0.01 < vars) & (vars < 1)  # v0*2.0)
trims = slice(None)
trimv = slice(None)

# Does better without upwinding here
up_or_down_spot = ''
up_or_down_var = ''
flip_idx_var = min(find(vars > theta))
Ejemplo n.º 2
0
    def __init__(self, option,
            grid=None,
            spot_max=1500.0,
            spot_min=0.0,
            spots=None,
            vars=None,
            var_max=10.0,
            nspots=100,
            nvols=100,
            spotdensity=7.0,
            varexp=4.0,
            force_exact=True,
            flip_idx_var=False,
            flip_idx_spot=False,
            schemes=None,
            coefficients=None,
            boundaries=None,
            cache=True,
            verbose=True,
            force_bandwidth=None
            ):
        """@option@ is a HestonOption"""
        self.cache = cache
        assert isinstance(option, Option)
        self.option = option

        if not coefficients:
            def mu_s(t, *dim):
                # return option.interest_rate.value - 0.5 * dim[1]
                return option.interest_rate.value * dim[0]
            def gamma2_s(t, *dim):
                # return 0.5 * dim[1]
                return 0.5 * dim[1] * dim[0]**2
            def mu_v(t, *dim):
                if np.isscalar(dim[0]):
                    if dim[0] == 0:
                        return 0
                ret = option.variance.reversion * (option.variance.mean - dim[1])
                ret[dim[0]==0] = 0
                return ret
            def gamma2_v(t, *dim):
                if np.isscalar(dim[0]):
                    if dim[0] == 0:
                        return 0
                ret = 0.5 * option.variance.volatility**2 * dim[1]
                ret[dim[0]==0] = 0
                return ret
            def cross(t, *dim):
                # return option.correlation * option.variance.volatility * dim[1]
                return option.correlation * option.variance.volatility * dim[0] * dim[1]

            coefficients = {()   : lambda t: -option.interest_rate.value,
                    (0,) : mu_s,
                    (0,0): gamma2_s,
                    (1,) : mu_v,
                    (1,1): gamma2_v,
                    (0,1): cross,
                    }

        if not boundaries:
            boundaries = {
                            # D: U = 0              VN: dU/dS = 1
                    # (0,)  : ((0, lambda t, *dim: 0.0), (1, lambda t, *dim: np.exp(dim[0]))),
                    (0,)  : ((0, lambda t, *dim: 0.0), (1, lambda t, *dim: 1.0)),
                            # D: U = 0              Free boundary
                    # (0,0) : ((0, lambda t, *dim: 0.0), (None, lambda t, *dim:  np.exp(dim[0]))),
                    (0,0) : ((0, lambda t, *dim: 0.0), (None, lambda t, *dim: 1.0)),
                            # Free boundary at low variance
                    (1,)  : ((None, lambda t, *dim: None),
                            # # D intrinsic value at high variance
                            # (0, lambda t, *dim: np.exp(-option.interest_rate.value * t) * dim[0])
                            (None, lambda t, *dim: None)
                            # (0, lambda t, *dim: dim[0])
                            ),
                            # We know from the PDE that this will be 0 because
                            # the vol is 0 at the low boundary
                    (1,1) : ((1, lambda t, *dim: 0),
                            # D intrinsic value at high variance
                            # (0, lambda t, *dim: np.exp(-option.interest_rate.value * t) * np.maximum(0.0, np.exp(dim[0])-option.strike))),
                            (None, lambda t, *dim: None)
                            # (0, lambda t, *dim: dim[0])
                            # (0, lambda t, *dim: 0)
                            )
                    }

        if isinstance(option, BarrierOption):
            if option.top:
                if option.top[0]: # Knockin, not sure about implementing this
                    raise NotImplementedError("Knockin barriers are not supported.")
                else:
                    spot_max = option.top[1]
                    if grid:
                        assert np.allclose(spot_max, max(grid.mesh[0]))
                    boundaries[(0,)] = (boundaries[(0,)][0], (0, lambda *x: 0.0))
                    boundaries[(0,0)] = boundaries[(0,)]
            if option.bottom:
                if option.bottom[0]: # Knockin, not sure about implementing this
                    raise NotImplementedError("Knockin barriers are not supported.")
                else:
                    spot_min = option.bottom[1]
                    boundaries[(0,)] = ((0, lambda *x: 0.0), boundaries[(0,)][1])
                    boundaries[(0,0)] = boundaries[(0,)]


        if grid:
            self.spots = grid.mesh[0]
            self.vars = grid.mesh[1]
        else:
            if vars is None:
                # vars = np.linspace(0, var_max, nvols)
                vars = utils.exponential_space(0.00, option.variance.value, var_max,
                                            varexp, nvols,
                                            force_exact=force_exact)
            self.vars = vars
            if spots is None:
                # spots = np.linspace(0,spot_max,nspots)
                if isinstance(option, BarrierOption) and option.top and not option.top[0]:
                        p = 3
                        # spots = np.linspace(0, spot_max**p, nspots)**(1.0/p)
                        spots = utils.exponential_space(0.00, self.option.strike, spot_max,
                                                    1.0/p, nspots,
                                                    force_exact=force_exact)
                        print "Barrier spots"
                else:
                    spots = utils.sinh_space(option.strike-spot_min, spot_max-spot_min, spotdensity, nspots, force_exact=force_exact) + spot_min
            self.spots = spots
            grid = Grid([self.spots, self.vars], initializer=lambda *x: np.maximum(x[0]-option.strike,0))


        newstrike = self.spots[np.argmin(np.abs(self.spots - option.strike))]
        self.spots[np.argmin(np.abs(self.spots - option.spot))] = option.spot
        # if newstrike != option.strike:
            # print "Strike %s -> %s" % (option.strike, newstrike)
            # option.strike = newstrike
        # if newspot != option.spot:
            # print "Spot %s -> %s" % (option.spot, newspot)
            # option.spot = newspot

        if flip_idx_var is True: # Need explicit boolean True
            flip_idx_var = bisect_left(
                    np.round(self.vars, decimals=5),
                    np.round(option.variance.mean, decimals=5))
        if flip_idx_spot is True: # Need explicit boolean True
            flip_idx_spot = bisect_left(
                    np.round(self.spots, decimals=5),
                    np.round(option.strike, decimals=5))


        if schemes is None:
            schemes = {}
        else:
            schemes = {k : list(v) for k, v in schemes.items()}
            # for k,v in new.items():
                # assert schemes[k] is not v
            # schemes = new
        if (0,) not in schemes:
            schemes[(0,)] = [{"scheme": "center"}]
        if flip_idx_spot is not False:
            schemes[(0,)].append({"scheme": 'forward', "from" : flip_idx_spot})

        if (1,) not in schemes:
            schemes[(1,)] = [{"scheme": "center"}]
        if flip_idx_var is not False:
            schemes[(1,)].append({"scheme": 'backward', "from" : flip_idx_var})

        if verbose:
            print "(0,): Start with %s differencing." % (schemes[(0,)][0]['scheme'],)
            if len(schemes[(0,)]) > 1:
                print "(0,): Switch to %s differencing at %i." % (schemes[(0,)][1]['scheme'], schemes[(0,)][1]['from'])
            print "(1,): Start with %s differencing." % (schemes[(1,)][0]['scheme'],)
            if len(schemes[(1,)]) > 1:
                print "(1,): Switch to %s differencing at %i." % (schemes[(1,)][1]['scheme'], schemes[(1,)][1]['from'])


        self.grid = grid
        self.coefficients = coefficients
        self.boundaries = boundaries
        self.schemes = schemes
        self.force_bandwidth = force_bandwidth
        self._initialized = False
Ejemplo n.º 3
0
                 , mean_variance = 0.04
                 , vol_of_variance = 0.4
                 , correlation = 0.3
                 )

spot_max = 1500.0
var_max = 13.0

nspots = 100
nvols = 100

spotdensity = 7.0  # infinity is linear?
varexp = 4

spots = utils.sinh_space(H.strike, spot_max, spotdensity, nspots)
vars = utils.exponential_space(0.00, H.variance.value, var_max, varexp, nvols)
# vars = [v0]
# spots = np.linspace(0.0, spot_max, nspots)
# vars = np.linspace(0.0, var_max, nvols)
# plot(spots); title("Spots"); show()
# plot(vars); title("Vars"); show()

H.strike = spots[min(abs(spots - H.strike)) == abs(spots - H.strike)][0]
H.spot = spots[min(abs(spots - H.spot)) == abs(spots - H.spot)][0]
def init(spots, vars):
    return np.maximum(0, spots - H.strike)
Gi = Grid(mesh=(spots, vars), initializer=init)
G = Gi.copy()
V_init = G.domain.copy()

trims = (H.strike * .2 < spots) & (spots < H.strike * 2.0)
Ejemplo n.º 4
0
# Grid parameters
rate_Spot_Var = 0.5  # Proportion to solve in the var step

spot_max = 1500.0
var_max = 13.0

nspots = 100
nvols = 100

spotdensity = 7.0  # infinity is linear?
varexp = 4

spots = utils.sinh_space(k, spot_max, spotdensity, nspots)
spot = spots[min(abs(spots - spot)) == abs(spots - spot)][0]
k = spots[min(abs(spots - k)) == abs(spots - k)][0]
vars = utils.exponential_space(0.00, v0, var_max, varexp, nvols)
# vars = [v0]
# spots = linspace(0.0, spot_max, nspots)
# vars = linspace(0.0, var_max, nvols)
# plot(spots); title("Spots"); show()
# plot(vars); title("Vars"); show()

trims = (k * .2 < spots) & (spots < k * 2.0)
trimv = (0.01 < vars) & (vars < 1)  # v0*2.0)
trims = slice(None)
trimv = slice(None)

# Does better without upwinding here
up_or_down_spot = ''
up_or_down_var = ''
flip_idx_var = min(find(vars > theta))