def elementwise_divide(a: MatrixVector2D, b: matrix) -> MatrixVector2D: if a.shape == b.shape: x = divide(a.x, b) y = divide(a.y, b) return MatrixVector2D(x, y) else: raise ValueError('MatrixVector2D and matrix shapes not the same.')
def elementwise_divide(a: MatrixVector, b: matrix) -> MatrixVector: if a.shape == b.shape: x = divide(a.x, b) y = divide(a.y, b) z = divide(a.z, b) return MatrixVector(x, y, z) else: raise ValueError('The shape of a and b need to be the same.')
def elementwise_divide(a: MatrixVector, b: matrix) -> MatrixVector: if a.shape == b.shape: x = divide(a.x, b) y = divide(a.y, b) z = divide(a.z, b) return MatrixVector(x, y, z) else: raise ValueError()
def phi_doublet_matrix(vecs: MatrixVector, rls: MatrixVector, sgnz: matrix): mags = vecs.return_magnitude() ms = divide(vecs.x, rls.y) ths = arctan(ms) ths[rls.y == 0.0] = piby2 gs = multiply(ms, divide(rls.z, mags)) Js = arctan(gs) Js[rls.y == 0.0] = piby2 phids = Js - multiply(sgnz, ths) return phids, mags
def phi_trailing_doublet_matrix(rls: MatrixVector, sgnz: matrix): ths = zeros(rls.shape, dtype=float) chky = absolute(rls.y) < tol ths[rls.y > 0.0] = piby2 ths[rls.y < 0.0] = -piby2 ths[chky] = -piby2 gs = zeros(rls.shape, dtype=float) divide(rls.z, rls.y, where=logical_not(chky), out=gs) Js = arctan(gs) Js[rls.y == 0.0] = -piby2 phids = Js - multiply(sgnz, ths) return phids
def vel_doublet_matrix(av, am, bv, bm): adb = elementwise_dot_product(av, bv) abm = multiply(am, bm) dm = multiply(abm, abm+adb) axb = elementwise_cross_product(av, bv) axbm = axb.return_magnitude() chki = (axbm == 0.0) chki = logical_and(axbm >= -tol, axbm <= tol) chkd = absolute(dm) < tol fac = zeros(axbm.shape, dtype=float) divide(am+bm, dm, where=logical_not(chkd), out=fac) velvl = elementwise_multiply(axb, fac) velvl.x[chki] = 0.0 velvl.y[chki] = 0.0 velvl.z[chki] = 0.0 return velvl
def phi_doublet_matrix(vecs: MatrixVector, sgnz: matrix): mags = vecs.return_magnitude() chkm = mags < tol chky = absolute(vecs.y) < tol vecs.y[chky] = 0.0 ms = zeros(mags.shape, dtype=float) divide(vecs.x, vecs.y, where=logical_not(chky), out=ms) ths = arctan(ms) ths[chky] = piby2 ts = zeros(mags.shape, dtype=float) divide(vecs.z, mags, where=logical_not(chkm), out=ts) gs = multiply(ms, ts) Js = arctan(gs) Js[chky] = piby2 phids = Js - multiply(sgnz, ths) return phids, mags
def __init__(self,order,cutoff,Fs,filtertype): self.order = order self.Fs = Fs self.Wn = self.Fs*0.5 # Time 0.5 to create float type self.type = filtertype; self.num, self.den = butter(self.order,np.divide(cutoff,self.Wn),self.type) self.A, self.B, self.C, self.D = tf2ss(self.num,self.den) self.Xnn = np.zeros((np.size(self.A,1),1))
def velocity_matrix(ra: MatrixVector, rb: MatrixVector, rc: MatrixVector, betm: float = 1.0, tol: float = 1e-12): if ra.shape != rb.shape: return ValueError() numi = rc.shape[0] numj = ra.shape[1] ra = ra.repeat(numi, axis=0) rb = rb.repeat(numi, axis=0) rc = rc.repeat(numj, axis=1) a = rc - ra b = rc - rb a.x = a.x / betm b.x = b.x / betm am = a.return_magnitude() bm = b.return_magnitude() # Velocity from Bound Vortex adb = elementwise_dot_product(a, b) abm = multiply(am, bm) dm = multiply(abm, abm + adb) axb = elementwise_cross_product(a, b) axbm = axb.return_magnitude() chki = (axbm == 0.0) chki = logical_and(axbm >= -tol, axbm <= tol) veli = elementwise_multiply(axb, divide(am + bm, dm)) veli.x[chki] = 0.0 veli.y[chki] = 0.0 veli.z[chki] = 0.0 # Velocity from Trailing Vortex A axx = MatrixVector(zeros(a.shape, dtype=float), a.z, -a.y) axxm = axx.return_magnitude() chka = (axxm == 0.0) vela = elementwise_divide(axx, multiply(am, am - a.x)) vela.x[chka] = 0.0 vela.y[chka] = 0.0 vela.z[chka] = 0.0 # Velocity from Trailing Vortex B bxx = MatrixVector(zeros(b.shape, dtype=float), b.z, -b.y) bxxm = bxx.return_magnitude() chkb = (bxxm == 0.0) velb = elementwise_divide(bxx, multiply(bm, bm - b.x)) velb.x[chkb] = 0.0 velb.y[chkb] = 0.0 velb.z[chkb] = 0.0 return veli, vela, velb
def phi_source_matrix(am, bm, dab, rl, phid): numrab = am + bm + dab denrab = am + bm - dab Pab = divide(numrab, denrab) Pab[denrab == 0.0] = 1.0 Qab = log(Pab) tmps = multiply(rl.y, Qab) phis = -multiply(rl.z, phid) - tmps return phis, Qab
def phi_source_matrix(am, bm, dab, rl, phid): numrab = am+bm+dab denrab = am+bm-dab Pab = divide(numrab, denrab) chkd = absolute(denrab) < tol Pab[chkd] = 1.0 Qab = log(Pab) tmps = multiply(rl.y, Qab) phis = -multiply(rl.z, phid) - tmps return phis, Qab
def phi_trailing_doublet_matrix(rls: MatrixVector, sgnz: matrix, faco: float): ths = zeros(rls.shape, dtype=float) ths[rls.y > 0.0] = piby2 ths[rls.y == 0.0] = -piby2 * faco ths[rls.y < 0.0] = -piby2 gs = divide(rls.z, rls.y) Js = arctan(gs) Js[rls.y == 0.0] = -piby2 * faco phids = Js - multiply(sgnz, ths) return phids
def betas(prices_m): """ Count beta parameters for all stocks, described in 'prices_m' matrix, according to 'index' benchmark. :param prices_m: matrix of prices. Each column represents a stock. Each row represents price at successive time stamp :return: matrix with betas. Each column represents a stock. Each row represents beta at successive time period """ returns_m = ml.divide(ml.subtract(prices_m[1:], prices_m[:-1]), prices_m[:-1]) index_m = ml.matrix(index).T index_returns_m = ml.divide(ml.subtract(index_m[1:], index_m[:-1]), index_m[:-1]) result = ml.empty((k, prices_m.shape[1])) for i in range(k): for j in range(stock_amount): x = returns_m[:, j] y = index_returns_m[:, i] result[i, j] = np.cov(x, y, rowvar=0)[0][1]/np.var(y) return result
def vel_doublet_matrix(av, am, bv, bm): adb = elementwise_dot_product(av, bv) abm = multiply(am, bm) dm = multiply(abm, abm + adb) axb = elementwise_cross_product(av, bv) axbm = axb.return_magnitude() chki = (axbm == 0.0) chki = logical_and(axbm >= -tol, axbm <= tol) velvl = elementwise_multiply(axb, divide(am + bm, dm)) velvl.x[chki] = 0.0 velvl.y[chki] = 0.0 velvl.z[chki] = 0.0 return velvl
def signal(prices, index): """ Signals to buy/sell stocks. Returns tuple (X1, X2, ..., Xn), where n is amount of stocks, Xi is one of the ('sell', 'buy', None). :param prices: list of price lists of stocks, in time ascending order :param index: list of k(!) price lists of benchmark values for k last periods, in time ascending order, with same time frame as stocks. """ def betas(prices_m): """ Count beta parameters for all stocks, described in 'prices_m' matrix, according to 'index' benchmark. :param prices_m: matrix of prices. Each column represents a stock. Each row represents price at successive time stamp :return: matrix with betas. Each column represents a stock. Each row represents beta at successive time period """ returns_m = ml.divide(ml.subtract(prices_m[1:], prices_m[:-1]), prices_m[:-1]) index_m = ml.matrix(index).T index_returns_m = ml.divide(ml.subtract(index_m[1:], index_m[:-1]), index_m[:-1]) result = ml.empty((k, prices_m.shape[1])) for i in range(k): for j in range(stock_amount): x = returns_m[:, j] y = index_returns_m[:, i] result[i, j] = np.cov(x, y, rowvar=0)[0][1]/np.var(y) return result def regime(reduced_returns_m): """ Make a regime switch based on PCA standard deviation acceleration. :param reduced_returns_m: matrix of PCA. Each column represents a stock. Each row represents price at successive time stamp :return: one of the strings, 'momentum' - if trend is ment to continue its movement, 'mean_reversion' - otherwise """ cross_sect_vol = np.std(reduced_returns_m, axis=1) changes = cross_sect_vol[1:] - cross_sect_vol[:-1] squared_changes = np.square(changes) distance_times = reduced_returns_m.shape[0] - 1 # because there is # T - 1 changes distance = np.zeros(distance_times) for t in range(distance_times): sum_amount = min(t + 1, H) for i in range(sum_amount): distance[t] += squared_changes[t - i, 0] distance[t] = np.sqrt(distance[t]) signal = distance[1:] - distance[:-1] if np.max(signal) > 0: return 'momentum' else: return 'mean_reversion' prices_m = ml.matrix(prices).T # Preparing main matrices for further computations try: log_returns_m = np.log(ml.divide(prices_m[1:], prices_m[:-1])) except TypeError as e: raise WrongPricesError(prices_m) time_period, stock_amount = log_returns_m.shape mean_log_returns_m = ml.average(log_returns_m, axis=0) demeaned_log_returns_m = log_returns_m - mean_log_returns_m covariation_m = demeaned_log_returns_m.T * demeaned_log_returns_m # Count eigenvectors of covariation matrix and compose PCA matrix from them e_values, e_vectors = eig(covariation_m) abs_e_values = np.absolute(e_values) # TODO: np.absolute(e_vectors) or something like that indexed_abs_e_values = [(i, v) for i, v in enumerate(abs_e_values)] w = sorted(indexed_abs_e_values, reverse=False, key=lambda x: x[1]) e_vectors_m = ml.empty((stock_amount, k)) for j in range(k): e_vectors_m[:, j] = e_vectors[:, w[j][0]] # Main part: project returns on PCA universe reduced_returns_m = (e_vectors_m.T * demeaned_log_returns_m.T).T # Count beta parameters with respect to given benchmark index betas_m = betas(prices_m) time = time_period - time_shift if time < H: raise WrongParameterException("time_shift should be less than H") # Collect data from returns in one vector accumulated_reduced_returns = ml.zeros((1, k)) for i in range(H): accumulated_reduced_returns += reduced_returns_m[time - 1 - i] # Make a prediction about further returns behaviour estimation = accumulated_reduced_returns * betas_m + \ mean_log_returns_m if regime_switcher: regime = regime(reduced_returns_m) else: regime = 'mean_reversion' # Finally, decide for each stock, whether we need to sell it as # overvalued or buy as undervalued. Other way around for momentum switch max_recent_log_returns = log_returns_m[-H:].max(0) result = [] for i in range(stock_amount): if max_recent_log_returns[0, i] > estimation[0, i] + epsilon: if regime == 'mean_reversion': result.append('sell') else: result.append('buy') elif max_recent_log_returns[0, i] < estimation[0, i] - epsilon: if regime == 'mean_reversion': result.append('buy') else: result.append('sell') else: result.append(None) return result
def derivative(mat: matrix, var: matrix, axis: int = 0): return divide(diff(mat, axis), diff(var, axis))