Example #1
0
    def generate_paths(self, fixed_seed=False, day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()
        M = len(se.time_grid)
        I = self.paths
        paths = np.zeros((M, I))
        paths[0] = self.initial_value
        if self.correlated is False:
            sn1 = sn_random_numbers((1, M, I), fixed_seed=fixed_seed)
        else:
            sn1 = self.random_numbers
        sn2 = sn_random_numbers((1, M, I), fixed_seed=fixed_seed)
        rj = self.lamb * (np.exp(self.mu + 0.5 * self.delt**2) - 1)
        short_rate = self.discount_curve.short_rate

        for t in range(1, len(self.time_grid)):
            if self.correated in False:
                ran = sn1(t)
            else:
                ran = np.dot(self.cholesky_matrix, sn1[:, t, :])
                ran = ran[self.rn_set]
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
            poi = np.random.poisson(self.lamb * dt, I)
            paths[t] = paths[t - 1] + (
                np.exp((short_rate - rj - 0.5 * self.volatility**2) * dt +
                       self.volatility * np.sqrt(dt) * ran) +
                (np.exp(self.mu + self.delt * sn2[t]) - 1) * poi)
        self.instrument_value = paths
    def generate_paths(self, fixed_seed=False, day_count=365.):
        if self.time_grid is None:
            # method from generic simulation class
            self.generate_time_grid()
        # number of dates for time grid
        M = len(self.time_grid)
        # number of paths
        I = self.paths
        # ndarray initialization for path simulation
        paths = np.zeros((M, I))
        # initialize first date with initial_value
        paths[0] = self.initial_value
        if self.correlated is False:
            # if not correlated, generate random numbers
            sn1 = sn_random_numbers((1, M, I),
                                    fixed_seed=fixed_seed)
        else:
            # if correlated, use random number object as provided
            # in market environment
            sn1 = self.random_numbers

        # standard normally distributed pseudorandom numbers
        # for the jump component
        sn2 = sn_random_numbers((1, M, I),
                                fixed_seed=fixed_seed)

        rj = self.lamb * (np.exp(self.mu + 0.5 * self.delt ** 2) - 1)

        short_rate = self.discount_curve.short_rate
        for t in range(1, len(self.time_grid)):
            # select the right time slice from the relevant
            # random number set
            if self.correlated is False:
                ran = sn1[t]
            else:
                # only with correlation in portfolio context
                ran = np.dot(self.cholesky_matrix, sn1[:, t, :])
                ran = ran[self.rn_set]
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
            # difference between two dates as year fraction
            poi = np.random.poisson(self.lamb * dt, I)
            # Poisson-distributed pseudorandom numbers for jump component
            paths[t] = paths[t - 1] * (
                np.exp((short_rate - rj -
                        0.5 * self.volatility ** 2) * dt +
                       self.volatility * np.sqrt(dt) * ran) +
                (np.exp(self.mu + self.delt * sn2[t]) - 1) * poi)
        self.instrument_values = paths
Example #3
0
    def generate_paths(self, fixed_seed=False, day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()
              # method from generic simulation class
        # number of dates for time grid    
        M = len(self.time_grid)
        # number of paths
        I = self.paths
        # array initialization for path simulation
        paths = np.zeros((M, I))
        # initialize first date with initial_value
        paths[0] = self.initial_value
        if self.correlated is False:
            # if not correlated, generate random numbers
            sn1 = sn_random_numbers((1, M, I),
                                     fixed_seed=fixed_seed)
        else:
            # if correlated, use random number object as provided
            # in market environment
            sn1 = self.random_numbers
        
        # standard normally distributed pseudorandom numbers
        # for the jump component
        sn2 = sn_random_numbers((1, M, I),
                                 fixed_seed=fixed_seed)

        rj = self.lamb * (np.exp(self.mu + 0.5 * self.delt ** 2) - 1)

        short_rate = self.discount_curve.short_rate
        for t in range(1, len(self.time_grid)):
            # select the right time slice from the relevant
            # random number set
            if self.correlated is False:
                ran = sn1[t]
            else:
                # only with correlation in portfolio context
                ran = np.dot(self.cholesky_matrix, sn1[:, t, :])
                ran = ran[self.rn_set]
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
              # difference between two dates as year fraction
            poi = np.random.poisson(self.lamb * dt, I)
              # Poisson-distributed pseudorandom numbers for jump component
            paths[t] = paths[t - 1] * (np.exp((short_rate - rj
                                        - 0.5 * self.volatility ** 2) * dt
                                    + self.volatility * np.sqrt(dt) * ran)
                                    + (np.exp(self.mu + self.delt * 
                                        sn2[t]) - 1) * poi)
        self.instrument_values = paths
Example #4
0
    def generate_paths(self, fixed_seed=True, day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()
        M = len(self.time_grid)
        I = self.paths
        paths = np.zeros((M, I))
        paths_ = np.zeros_like(paths)
        paths[0] = self.initial_value
        paths_[0] = self.initial_value
        if self.correlated is False:
            rand = sn_random_numbers((1, M, I), fixed_seed=fixed_seed)
        else:
            rand = self.random_numbers

        for t in range(1, len(self.time_grid)):
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
            if self.correlated is False:
                ran = rand[t]
            else:
                ran = np.dot(self.cholesky_matrix, rand[:, t, :])
                ran = ran[self.rn_set]

            # full truncation Euler discretization
            paths_[t] = (paths_[t - 1] + self.kappa *
                         (self.theta - np.maximum(0, paths_[t - 1, :])) * dt +
                         np.sqrt(np.maximum(0, paths_[t - 1, :])) *
                         self.volatility * np.sqrt(dt) * ran)
            paths[t] = np.maximum(0, paths_[t])
        self.instrument_values = paths
    def generate_paths(self, fixed_seed=False, day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()

        num_dates = len(self.time_grid)
        num_paths = self.paths
        paths_1 = np.zeros((num_dates, num_paths))
        paths_2 = np.zeros_like(paths_1)
        paths_1[0] = self.initial_value
        paths_2[0] = self.initial_value

        # decide the correct random numbers basted correlation
        if self.correlated is False:
            sn = sn_random_numbers((1, num_dates, num_paths), fixed_seed=fixed_seed)
        else:
            sn = self.random_numbers

        # Generate paths:
        for t in range(1, len(self.time_grid)):
            # time interval
            dt = (self.time_grid[t] - self.time_grid[t-1]).days / day_count

            # choose the correct random number
            if self.correlated is False:
                random_num = sn[t]
            else:
                random_num = np.dot(self.cholesky_matrix, sn[:, t, :])
                random_num = random_num[t]

            # full trunctation with Euler Discretization
            paths_2[t] = (paths_2[t-1] + self.kappa * (self.theta - np.maximum(0, paths_2[t-1, :])) * dt
                          + self.volatility * np.sqrt(np.maximum(0, paths_2[t-1, :])) * np.sqrt(dt) * random_num)
            paths_1[t] = np.maximum(0, paths_2[t])

        self.instrument_values = paths_1
    def generate_path(self, fixed_seed=False, day_count=365):
        if self.time_grid is None:
            self.generate_time_grid()
        M = len(self.time_grid)
        I = self.paths
        paths = np.zeros((M, I))
        paths[0] = self.initial_value
        if not self.correlated:
            rand = sn_random_numbers((1, M, I), fixed_seed=fixed_seed)
        else:
            rand = self.random_numbers
        short_rate = self.discount_curve.short_rate

        for t in range(1, len(self.time_grid)):
            if not self.correlated:
                ran = rand[t]
            else:
                ran = np.dot(self.cholesky_matrix, rand[:, t, :])
                ran = ran[self.rn_set]
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count

            paths[t] = paths[t - 1] * np.exp(
                (short_rate - 0.5 * self.volatility**2) * dt +
                self.volatility * np.sqrt(dt) * ran)
        self.instrument_values = paths
Example #7
0
    def generate_paths(self, fixed_seed=True, day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()
        M = len(self.time_grid)
        I = self.paths
        paths = np.zeros((M, I))
        paths_ = np.zeros_like(paths)
        paths[0] = self.initial_value
        paths_[0] = self.initial_value
        if self.correlated is False:
            rand = sn_random_numbers((1, M, I),
                                     fixed_seed=fixed_seed)
        else:
            rand = self.random_numbers

        for t in range(1, len(self.time_grid)):
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
            if self.correlated is False:
                ran = rand[t]
            else:
                ran = np.dot(self.cholesky_matrix, rand[:, t, :])
                ran = ran[self.rn_set]

            # full truncation Euler discretization
            paths_[t] = (paths_[t - 1] + self.kappa
                         * (self.theta - np.maximum(0, paths_[t - 1, :])) * dt
                         + np.sqrt(np.maximum(0, paths_[t - 1, :]))
                         * self.volatility * np.sqrt(dt) * ran)
            paths[t] = np.maximum(0, paths_[t])
        self.instrument_values = paths
    def generate_paths(self, fixed_seed=False,day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()
            # method from generic simulation class
        # number of dates for time grid
        M = len(self.time_grid)
        # number of paths
        I = self.paths
        # array initialization for path simulation
        paths = np.zeros((M, I))
        paths_ = np.zeros_like(paths)
        # initialize first date with initial_value
        paths[0] = self.initial_value
        paths_[0] = self.initial_value
        if self.correlated is False:
            # if not correlated, generate random numbers
            rand = sn_random_numbers((1, M, I),
                                    fixed_seed=fixed_seed)
        else:
            # if correlated, use random number object as provided
            rand = self.random_numbers

        for t in range(1, len(self.time_grid)):
            dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count

            if self.correlated is False:
                ran = rand[t]
            else:
                ran = np.dot(self.cholesky_matrix, rand[:, t, :])
                ran = ran[self.rn_set]

            # full truncation Euler discretization
            paths_[t] = (paths_[t - 1] + self.kappa
                         * (self.theta - np.maximum(0, paths_[t - 1, :])) * dt
                         + np.sqrt(np.maximum(0, paths_[t - 1, :]))
                         * self.volatility * np.sqrt(dt) * ran)

            paths[t] = np.maximum(0, paths_[t])

        self.instrument_values = paths
 def generate_paths(self, fixed_seed=False, day_count=365.):
     if self.time_grid is None:
         self.generate_time_grid()
         # method from generoc simulation class
     # number of dates for time grid
     M = len(self.time_grid)
     # number of paths
     I = self.paths
     # array initialization for path simulation
     paths = np.zeros((M, I))
     # initialize first date with initial_value
     paths[0] = self.initial_value
     if not self.correlated:
         # if not correlated, generate random numbers
         # when shape[0] is 1, returns a 2 x 2 matrix
         rand = sn_random_numbers((1, M, I),
                                  fixed_seed=fixed_seed)
     else:
         # if correlated, use random number object as provided
         # in market environment
         rand = self.random_numbers
     short_rate = self.discount_curve.short_rate
     # get short rate for drift of process
     for t in range(1, len(self.time_grid)):
         # select the right time slice from the relevant
         # random number set
         if not self.correlated:
             ran = rand[t]
         else:
             ran = np.dot(self.cholesky_matrix, rand[:, t, :])
             ran = ran[self.rn_set]
         dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
         # difference between two dates as year fraction
         paths[t] = paths[t - 1] * np.exp((short_rate - 0.5
                                           * self.volatility ** 2) * dt
                                          + self.volatility * np.sqrt(dt) * ran)
         # generate simulated values for the respective date
     self.instrument_values = paths
Example #10
0
 def generate_paths(self, fixed_seed=False, day_count=365.):
     if self.time_grid is None:
         self.generate_time_grid()
         # method from generic simulation class
     # number of dates for time grid
     M = len(self.time_grid)
     # number of paths
     I = self.paths
     # array initialization for path simulation
     paths = np.zeros((M, I))
     # initialize first date with initial_value
     paths[0] = self.initial_value
     if not self.correlated:
         # if not correlated, generate random numbers
         rand = sn_random_numbers((1, M, I),
                                  fixed_seed=fixed_seed)
     else:
         # if correlated, use random number object as provided
         # in market environment
         rand = self.random_numbers
     short_rate = self.discount_curve.short_rate
     # get short rate for drift of process
     for t in range(1, len(self.time_grid)):
         # select the right time slice from the relevant
         # random number set
         if not self.correlated:
             ran = rand[t]
         else:
             ran = np.dot(self.cholesky_matrix, rand[:, t, :])
             ran = ran[self.rn_set]
         dt = (self.time_grid[t] - self.time_grid[t - 1]).days / day_count
         # difference between two dates as year fraction
         paths[t] = paths[t - 1] * np.exp((short_rate - 0.5
                                           * self.volatility ** 2) * dt
                                          + self.volatility * np.sqrt(dt) * ran)
         # generate simulated values for the respective date
     self.instrument_values = paths
    def generate_paths(self, fixed_seed=False, day_count=365.):
        if self.time_grid is None:
            self.generate_time_grid()

        # initialization for path simulation, and initialize the first date
        num_dates = len(self.time_grid)
        num_paths = self.paths
        paths = np.zeros((num_dates, num_paths))
        paths[0] = self.initial_value

        if not self.correlated:
            # if not correlated, generate random numbers
            random_nums = sn_random_numbers((1, num_dates, num_paths), fixed_seed=fixed_seed)
        else:
            # if correlated, use provided random numbers from mkt env
            random_nums = self.random_numbers

        # get the short rate for GBM drift
        short_rate = self.discount_curve.short_rate

        # generate the paths
        for t in range(1,len(self.time_grid)):
            # choose the correct time step
            # depending on if correalted
            if not self.correlated:
                rand = random_nums[t]
            else:
                rand = np.dot(self.cholesky_matrix, random_nums[:,t,:])
                rand = rand(self.rn_set)

            # calculate dt: difference between two simulated dates in year's fraction
            dt = (self.time_grid[t] - self.time_grid[t-1]).days / day_count
            # generate the simulated values at the current time grid
            paths[t] = paths[t-1] * np.exp((short_rate - 0.5*self.volatility**2)*dt
                                           + self.volatility*np.sqrt(dt) * rand)

        self.instrument_values = paths
    def __init__(self,
                 name,
                 positions,
                 val_env,
                 assets,
                 correlations=None,
                 fixed_seed=False):
        self.name = name
        self.positions = positions
        self.val_env = val_env
        self.assets = assets
        self.underlyings = set()
        self.correlations = correlations
        self.time_grid = None
        self.underlying_objects = {}
        self.valuation_objects = {}
        self.fixed_seed = fixed_seed
        self.special_dates = []
        for pos in self.positions:
            # determine earliest starting_date
            self.val_env.constants['starting_date'] = \
                                                      min(self.val_env.constants['starting_date'],
                                                          positions[pos].mar_env.pricing_date)
            # determine latest date of relevance
            self.val_env.constants['final_date'] = \
                                                   max(self.val_env.constants['final_date'],
                                                       positions[pos].mar_env.constants['maturity'])
            # collect all underlyings
            # add to set; avoids redundancy
            self.underlyings.add(positions[pos].underlying)
        # generate general time grid
        start = self.val_env.constants['starting_date']
        end = self.val_env.constants['final_date']
        time_grid = pd.date_range(
            start=start, end=end,
            freq=self.val_env.constants['frequency']).to_pydatetime()
        time_grid = list(time_grid)
        for pos in self.positions:
            maturity_date = positions[pos].mar_env.constants['maturity']
            if maturity_date not in time_grid:
                time_grid.insert(0, maturity_date)
                self.special_dates.append(maturity_date)
            if start not in time_grid:
                time_grid.insert(0, start)
            if end not in time_grid:
                time_grid.append(end)
            # delete duplicate entries
            time_grid = list(set(time_grid))
            # sort dates in time_grid
            time_grid.sort()
            self.time_grid = np.array(time_grid)
            self.val_env.add_list('time_grid', self.time_grid)

            if correlations is not None:
                # take care of correlations
                ul_list = sorted(self.underlyings)
                correlation_matrix = np.zeros((len(ul_list), len(ul_list)))
                np.fill_diagonal(correlation_matrix, 1.0)
                correlation_matrix = pd.DataFrame(correlation_matrix,
                                                  index=ul_list,
                                                  columns=ul_list)
                for i, j, corr in correlations:
                    corr = min(corr, 0.999999999999)
                    # fill correlation matrix
                    correlation_matrix.loc[i, j] = corr
                    correlation_matrix.loc[j, i] = corr
                # determine Cholesky matrix
                cholesky_matrix = np.linalg.cholesky(
                    np.array(correlation_matrix))
                # dictionary with index positions for the
                # slice of the random number array to be used by
                # respective underlying
                rn_set = {
                    asset: ul_list.index(asset)
                    for asset in self.underlyings
                }
                # random numbers array, to be used by
                # all underlyings (if correlations exist)
                random_numbers = sn_random_numbers(
                    (len(rn_set), len(
                        self.time_grid), self.val_env.constants['paths']),
                    fixed_seed=self.fixed_seed)
                # add all to valuation environment that is
                # to be shared with every underlying
                self.val_env.add_list('cholesky_matrix', cholesky_matrix)
                self.val_env.add_list('random_numbers', random_numbers)
                self.val_env.add_list('rn_set', rn_set)

                for asset in self.underlyings:
                    # select market environment of asset
                    mar_env = self.assets[asset]
                    # add valuation environment to market environment
                    mar_env.add_environment(val_env)
                    # select right simulation class
                    model = models[mar_env.constants['model']]
                    # instantiate simulation object
                    if correlations is not None:
                        self.underlying_objects[asset] = model(asset,
                                                               mar_env,
                                                               corr=True)
                    else:
                        self.underlying_objects[asset] = model(asset,
                                                               mar_env,
                                                               corr=False)
                for pos in positions:
                    # select right valuation class (European, American)
                    val_class = otypes[positions[pos].otype]
                    # pick market environment and add valuation environment
                    mar_env = positions[pos].mar_env
                    mar_env.add_environment(self.val_env)
                    # instantiate valuation class
                    self.valuation_objects[pos] = \
                                                  val_class(name=positions[pos].name,
                                                            mar_env=mar_env,
                                                            underlying=self.underlying_objects[
                                                                positions[pos].underlying],
                                                            payoff_func=positions[pos].payoff_func)