def test_pseudo(self): from pyculib import rand prng = rand.PRNG() prng.seed = 0xbeef N = 10 ary = np.zeros(N, dtype=np.float32) prng.uniform(ary, N) self.assertTrue(any(ary != 0)) iary = np.zeros(N, dtype=np.uint32) prng.poisson(iary, N) self.assertTrue(any(iary != 0))
def montecarlo(paths, dt, interest, volatility): c0 = interest - 0.5 * volatility**2 c1 = volatility * np.sqrt(dt) prng = curand.PRNG(rndtype=curand.PRNG.XORWOW) d_noises = cuda.device_array(paths.shape[0]) d_current = cuda.to_device(paths[:, 0]) d_next = cuda.device_array(paths.shape[0]) for j in range(1, paths.shape[1]): #for each time step #prices = paths[:, j - 1] #last prices # Now no slicing needed #gaussian noise for simulation #noises = np.random.normal(0., 1., prices.size) prng.normal(d_noises, 0., 1.) #simulate d_next = step(d_current, dt, c0, c1, d_noises) d_next.copy_to_host(paths[:, j]) d_next, d_current = d_current, d_next
def cuda_jit_montecarlo(timespan, n): """Compute the Monte Carlo scenarios :param timespan: Array of the time discretization :param n: Number of Monte Carlo paths :type timespan: M+1 array :type n: int :returns: (sorting_value, basis, expect_basis, expect_brownian_basis, riskfree_price, riskfree_delta, adjusted_price, adjusted_delta) :rtypes: (N x (M+1) array, N x Q x M array, N x Q x M array, N x Q x q x M array, N x 1 array, N x q array, Nx 1 array, N x q array) """ no_of_timesteps = timespan.shape[0] # M+1 stock_data = np.ones((n, 1)) * INITIAL_VALUE sorting_value = np.empty((n, no_of_timesteps)) basis = np.empty((n, BASIS_ORDER, no_of_timesteps - 1)) expect_basis = np.empty((n, BASIS_ORDER, no_of_timesteps - 1)) expect_brownian_basis = np.empty( (n, BASIS_ORDER, NUM_OF_BROWNIAN_MOTION, no_of_timesteps - 1)) riskfree_price = np.zeros((n, 1)) riskfree_delta = np.zeros((n, NUM_OF_BROWNIAN_MOTION)) adjusted_price = np.zeros((n, 1)) adjusted_delta = np.zeros((n, NUM_OF_BROWNIAN_MOTION)) blksz = 256 gridsz = int(math.ceil(float(n) / blksz)) # instantiate a CUDA stream for queueing async CUDA cmds stream = cuda.stream() # instantiate a cuRAND PRNG prng = rand.PRNG(rndtype=rand.PRNG.MRG32K3A, seed=int(time.time()), stream=stream) # Allocate device side array d_normdist = cuda.device_array(n * NUM_OF_BROWNIAN_MOTION, dtype=np.double, stream=stream) d_drift = cuda.device_array((n, NUM_OF_ASSETS), dtype=np.double, stream=stream) d_volatility = \ cuda.device_array((n, NUM_OF_ASSETS, NUM_OF_BROWNIAN_MOTION), dtype=np.double, stream=stream) d_sorting_value = cuda.device_array_like(sorting_value[:, 0], stream=stream) d_weighted_stock = cuda.device_array_like(stock_data, stream=stream) d_basis = cuda.device_array(n, dtype=np.double, stream=stream) d_basis_expectation = cuda.device_array(n, dtype=np.double, stream=stream) d_basis_brownian_expectation = cuda.device_array(n, dtype=np.double, stream=stream) d_price = cuda.device_array((n, 1), dtype=np.double, stream=stream) d_delta = cuda.device_array((n, NUM_OF_BROWNIAN_MOTION), dtype=np.double, stream=stream) step_cfg = cuda_jit_step_euler[gridsz, blksz, stream] # The forward simulation scheme for k in range(no_of_timesteps): # Calculate the time interval current_time = timespan[k] if k != 0: previous_time = timespan[k - 1] dt = current_time - previous_time if k != no_of_timesteps - 1: next_time = timespan[k + 1] forward_time_interval = next_time - current_time if k == 0: # transfer the initial prices d_last = cuda.to_device(stock_data, stream=stream) else: # call cuRAND to populate d_normdist with gaussian noises prng.normal(d_normdist, mean=0, sigma=1) # invoke step kernel asynchronously step_cfg(d_last, dt, d_drift, d_volatility, d_normdist) # Calculate the stock model parameters. cuda_jit_drift[gridsz, blksz, stream](d_last, MU_BAR, d_drift) cuda_jit_volatility[gridsz, blksz, stream](d_last, SIGMA_BAR, CHOLESKY_DECOMPOSITION, d_volatility) # Calculate the sorting value cuda_sorting_method[gridsz, blksz, stream](WEIGHT, d_last, d_sorting_value) sorting_value[:, k] = d_sorting_value.copy_to_host() # Calculate the basis function and its two types of expectations if k != 0: cuda_weighted_stock[gridsz, blksz, stream](WEIGHT, d_last, d_weighted_stock) for j in range(BASIS_ORDER): basis_partition = star_and_bin_array(j, NUM_OF_ASSETS) cuda_jit_basis[gridsz, blksz, stream](d_weighted_stock, basis_partition, j, d_basis) basis[:, j, k - 1] = d_basis.copy_to_host() if k != no_of_timesteps - 1: expect_basis[:, 0, k] = 1. expect_brownian_basis[:, 0, :, k] = 0. for j in range(1, BASIS_ORDER): basis_partition = star_and_bin_array(j, NUM_OF_ASSETS) basis_gradient_partition = star_and_bin_array( j - 1, NUM_OF_ASSETS) cuda_basis_expect[gridsz, blksz, stream](WEIGHT, d_last, current_time, d_drift, d_volatility, forward_time_interval, j, basis_partition, d_basis_expectation) expect_basis[:, j, k] = d_basis_expectation.copy_to_host() for l in range(d_volatility.shape[2]): cuda_basis_brownian_expect[gridsz, blksz, stream]( WEIGHT, d_last, current_time, d_drift, d_volatility, forward_time_interval, j, l, basis_gradient_partition, d_basis_brownian_expectation) expect_brownian_basis[:, j, l, k] = d_basis_brownian_expectation.copy_to_host( ) stream.synchronize() # This ensure all GPU work is completed # Calculate the termianl conditions cuda_payoff[gridsz, blksz, stream](d_last, WEIGHT, STRIKE, d_price) cuda_terminal_delta[gridsz, blksz, stream](d_last, WEIGHT, STRIKE, d_volatility, d_delta) riskfree_price[:, :] = d_price.copy_to_host() riskfree_price *= BUY_SELL adjusted_price[:, :] = d_price.copy_to_host() adjusted_price *= BUY_SELL riskfree_delta[:, :] = d_delta.copy_to_host() riskfree_delta *= BUY_SELL adjusted_delta[:, :] = d_delta.copy_to_host() adjusted_delta *= BUY_SELL return sorting_value, basis, expect_basis, expect_brownian_basis, riskfree_price, riskfree_delta, adjusted_price, adjusted_delta
import numpy as np from numba import vectorize import numpy as np from pyculib import rand as curand @vectorize(['float32(float32, float32)'], target='cuda') def Add(a, b): return a + b # Initialize arrays N = 100000 A = np.ones(N, dtype=np.float32) B = np.ones(A.shape, dtype=A.dtype) C = np.empty_like(A, dtype=A.dtype) # Add arrays on GPU C = Add(A, B) prng = curand.PRNG(rndtype=curand.PRNG.XORWOW) rand = np.empty(100000) prng.uniform(rand) print(rand[:10])
def generate_pos_2d(lcurve, rcurve, target_area, ly, ry, n, seed): nl = ly.size - 1 nr = ry.size - 1 assert (len(lcurve) == nl) assert (len(rcurve) == nr) if min(ly) != min(ry): assert (min(ly) == min(ry)) if max(ly) != max(ry): assert (max(ly) == max(ry)) def collect_2d(n, x, y): selected = np.ones(n, dtype=bool) for i in range(n): for j in range(nl): if ly[j] < y[i] and y[i] < ly[j + 1]: if lcurve[j].check(y[i]) > x[i]: selected[i] = False break if selected[i]: for j in range(nr): if ry[j] < y[i] and y[i] < ry[j + 1]: if rcurve[j].check(y[i]) < x[i]: selected[i] = False break pos = np.array([x[selected], y[selected]]) return pos, sum(selected) xmax = max([r.xmax() for r in rcurve]) xmin = min([l.xmin() for l in lcurve]) ymax = max(ly) ymin = min(ly) storming_area = (xmax - xmin) * (ymax - ymin) #print(xmax,xmin,ymax,ymin, storming_area) ratio = storming_area / target_area #print(ratio) # to do: if ratio > some threshold rotate the coordinates and implement methods for the corresponding change for the Class of curves, too ntmp = np.ceil(n * ratio).astype(int) i = 0 pos = np.empty((2, n), dtype=float) prng = rand.PRNG(rndtype=rand.PRNG.XORWOW, seed=seed) #qrng = rand.QRNG(rndtype=rand.QRNG.SCRAMBLED_SOBOL32, ndim=2) #count = 0 while (i < n): #irands = np.empty((2,ntmp), dtype='uint32') rands = np.empty(ntmp, dtype=float) prng.uniform(rands) #qrng.generate(irands) #rands = irands[0,:]/np.iinfo(np.dtype('uint32')).max x = xmin + (xmax - xmin) * rands prng.uniform(rands) #qrng.generate(irands) #rands = irands[1,:]/np.iinfo(np.dtype('uint32')).max y = ymin + (ymax - ymin) * rands acquired_pos, nselected = collect_2d(ntmp, x, y) if i + nselected > n: nselected = n - i pos[:, i:i + nselected] = acquired_pos[:, :nselected] i += nselected ntmp = np.ceil((n - i) * ratio).astype(int) #count += 1 #print(count) return pos