Python金融大数据分析——第8章 高性能的Pyhon 笔记 - 日理万妓 2022-05-21 05:54 396阅读 0赞 * 第8章 高性能的Python * 8.1 Python范型与性能 * 8.2 内存布局与性能 * 8.3 并行计算 * 8.3.1 蒙特卡洛算法 * 8.3.2 顺序化计算 * 8.4 多处理 * 8.5 动态编译 * 8.5.1 介绍性示例 * 8.5.2 二项式期权定价方法 * 8.6 用Cython进行静态编译 * 8.7 在GPU上生成随机数 # 第8章 高性能的Python # 许多高性能库可以用于加速Python代码的执行: • Cython 用于合并Py由on和C语言静态编译范型。 • IPython.parallel 用于在本地或者在群集上并行执行代码/函数。 • numexpr 用于快速数值运算。 • multiprocessing Python内建的(本地)并行处理模块。 • Numba 用于为CPU动态编译Python代码。 • NumbaPro 用于为多核CPU和GPU动态编译Python代码。 定义一个方便的函数,可以系统性地比较在相同或者不同数据集上执行不同函数的性能: def perf_comp_data(func_list, data_list, rep=3, number=1): """ Function to compare the performance of different function. :param func_list: list with function names as strings :param data_list: list with data set names as strings :param rep: number of repetitions of the whole comparison :param number: number of executions for every function :return: """ from timeit import repeat res_list = {} for name in enumerate(func_list): stmt = name[1] + '(' + data_list[name[0]] + ')' setup = "from __main__ import " + name[1] + ', ' + data_list[name[0]] results = repeat(stmt=stmt, setup=setup, repeat=rep, number=number) res_list[name[1]] = sum(results) / rep res_sort = sorted(res_list.items(), key=lambda item: item[1]) for item in res_sort: rel = item[1] / res_sort[0][1] print('function:' + item[0][1] + ', av.item sec: %9.5f, ' % item[1] + 'relative: %6.1f' % rel) ## 8.1 Python范型与性能 ## 在金融学中与其他科学及数据密集学科一样, 大数据集上的数值计算相当费时。举个例子, 我们想要在包含 50 万个数值的数组上求取某个复杂数学表达式的值。我们选择公式中的表达式,它的每次计算都会带来一定的计算负担。除此之外,该公式没有任何特殊的含义。 数学表达式示例 ![数学表达式示例][70] def perf_comp_data(func_list, data_list, rep=3, number=1): """ Function to compare the performance of different function. :param func_list: list with function names as strings :param data_list: list with data set names as strings :param rep: number of repetitions of the whole comparison :param number: number of executions for every function :return: """ from timeit import repeat res_list = {} for name in enumerate(func_list): stmt = name[1] + '(' + data_list[name[0]] + ')' setup = "from __main__ import " + name[1] + ', ' + data_list[name[0]] results = repeat(stmt=stmt, setup=setup, repeat=rep, number=number) res_list[name[1]] = sum(results) / rep res_sort = sorted(res_list.items(), key=lambda item: item[1]) for item in res_sort: rel = item[1] / res_sort[0][1] print('function:' + item[0] + ', av.item sec: %9.5f, ' % item[1] + 'relative: %6.1f' % rel) # 8.1 Python范型与性能 from math import * # 很容易转换为一个Python函数 def f(x): return abs(cos(x)) ** 0.5 + sin(2 + 3 * x) # 使用range函数,我们可以高效地生成一个包含 50 万个数值的列表对象 I = 500000 a_py = range(I) # 包含显式循环的标准Python函数 def f1(a): res = [] for x in a: res.append(f(x)) return res # 包含隐含循环的迭代子方法 def f2(a): return [f(x) for x in a] # 包含隐含循环、使用eval的选代子方法 def f3(a): ex = 'abs(cos(x))**0.5+sin(2+3*x)' return [eval(ex) for x in a] # Numy向量化实现 import numpy as np a_np = np.arange(I) def f4(a): return (np.abs(np.cos(a)) ** 0.5 + np.sin(2 + 3 * a)) # 专用库numexpr求数值表达式的值。 这个库内建了多线程执行支持 # numexpr单线程实现 import numexpr as ne def f5(a): ex='abs(cos(a))**0.5+sin(2+3*a)' ne.set_num_threads(1) return ne.evaluate(ex) # nwexpr多线程实现 def f6(a): ex = 'abs(cos(a))**0.5+sin(2+3*a)' ne.set_num_threads(16) return ne.evaluate(ex) %%time r1=f1(a_py) r2=f2(a_py) r3=f3(a_py) r4=f4(a_np) r5=f5(a_np) r6=f6(a_np) # Wall time: 35.1 s # NumPy函数alJclose可以轻松地检查两个(类) ndarray对象是否包含相同数据 np.allclose(r1,r2) # True np.allclose(r1,r3) # True np.allclose(r1,r4) # True np.allclose(r1,r5) # True np.allclose(r1,r6) # True # 使用perf_comp_data函数 func_list=['f1','f2','f3','f4','f5','f6'] data_list=['a_py','a_py','a_py','a_np','a_np','a_np'] perf_comp_data(func_list,data_list) # function:f6, av.item sec: 0.01623, relative: 1.0 # function:f5, av.item sec: 0.04650, relative: 2.9 # function:f4, av.item sec: 0.07293, relative: 4.5 # function:f2, av.item sec: 1.17137, relative: 72.2 # function:f1, av.item sec: 1.33291, relative: 82.1 # function:f3, av.item sec: 33.47790, relative: 2062.2 ## 8.2 内存布局与性能 ## import numpy as np np.zeros((3,3),dtype=np.float64,order='C') # array([[ 0., 0., 0.], # [ 0., 0., 0.], # [ 0., 0., 0.]]) # 元素在内存中存储的顺序:C表示类似C(行优先) c=np.array([[1.,1.,1.], [2.,2.,2.], [3.,3.,3.]],order='C') # F表示类似Fortran (列优先) f=np.array([[1.,1.,1.], [2.,2.,2.], [3.,3.,3.]],order='F') x = np.random.standard_normal((3, 1500000)) C = np.array(x, order='C') F = np.array(x, order='F') x = 0.0 %timeit C.sum(axis=0) # 10 loops, best of 3: 19.3 ms per loop %timeit C.sum(axis=1) # 100 loops, best of 3: 10.3 ms per loop # 第一个轴上计算总和比第二个轴慢了将近一倍 %timeit C.std(axis=0) # 10 loops, best of 3: 112 ms per loop %timeit C.std(axis=1) # 10 loops, best of 3: 57.6 ms per loop %timeit F.sum(axis=0) # 10 loops, best of 3: 70.7 ms per loop %timeit F.sum(axis=1) # 10 loops, best of 3: 84.2 ms per loop # 两个轴的相对差值并不太大 %timeit F.std(axis=0) # 1 loop, best of 3: 253 ms per loop %timeit F.std(axis=1) # 1 loop, best of 3: 227 ms per loop # 与类似C的布局相比, 类似F这种布局的性能更差 ## 8.3 并行计算 ## ### 8.3.1 蒙特卡洛算法 ### 期权的蒙特卡洛估值是导致高计算负担的金融算法之一。作为特例,我们选择Black-Scholes-Meron设置下的欧式看涨期权价值蒙特卡洛估值函数。在这种设置下,所要估值的期权标的遵循随机微分方程式(SDE),如下公式。St是时间t的标的价值;r是一个常数——无风险短期利率;σ是恒定瞬时波动率;Z是布朗运动。 Black-Scholes-Metron SDE ![Black-Scholes-Metron SDE][] 欧式看涨期权的蒙特卡洛估算函数 ![欧式看涨期权的蒙特卡洛估算函数][70 1] def bsm_mcs_valuation(strike): """ Dynamic Black-Scholes-Merton Monte Carlo estimator for European calls. :param strike: :return: """ import numpy as np S0=100.;T=1.0;r=0.05;vola=0.2 M=50;I=2000 dt=T/M rand=np.random.standard_normal((M+1,I)) S=np.zeros((M+1,I));S[0]=S0 for t in range(1,M+1): S[t]=S[t-1]*np.exp((r-0.5*vola**2)*dt+vola*np.sqrt(dt)*rand[t]) value=(np.exp(-r*T)*np.sum(np.maximum(S[-1]-strike,0))/I) return value ### 8.3.2 顺序化计算 ### 作为基准用例, 我们对不同行权价的100种期权进行估值。seq\_value函数计算蒙特卡洛估算函数。返回包含行权价和估值结果的列表对象: def seq_value(n): """ Sequential option valuation :param n: number of option valuations/strikes :return: """ strikes=np.linspace(80,120,n) option_values=[] for strike in strikes: option_values.append(bsm_mcs_valuation(strike)) return strikes,option_values n=100 # number of options to be valued %time strikes,option_values_seq=seq_value(n) # Wall time: 1.39 s import matplotlib.pyplot as plt plt.figure(figsize=(8,4)) plt.plot(strikes,option_values_seq,'b') plt.plot(strikes,option_values_seq,'r.') plt.grid(True) plt.xlabel('strikes') plt.ylabel('European call option values') ![通过蒙特卡洛模拟估算的欧式看涨期极价值][70 2] ## 8.4 多处理 ## 有时候在本地并行执行代码是很有益的。 这就是 “标准” Pthon 模 块 multiprocessing 的用武之地: import numpy as np import multiprocessing as mp import math import matplotlib.pyplot as plt def simulate_geometric_brownian_motion(p): M,I=p # time steps,paths S0=100;r=0.05;sigma=0.2;T=1.0 # model parameters dt=T/M paths=np.zeros((M+1,I)) paths[0]=S0 for t in range(1,M+1): paths[t]=paths[t-1]*np.exp((r-0.5*sigma**2)*dt+sigma*math.sqrt(dt)*np.random.standard_normal(I)) return paths paths=simulate_geometric_brownian_motion((5,2)) paths # array([[ 100. , 100. ], # [ 98.75585496, 86.36316092], # [ 109.5045796 , 82.00664539], # [ 92.85348223, 81.23649105], # [ 73.79002067, 81.99661207], # [ 67.4225339 , 89.39928928]]) if __name__ == '__main__': I=10000 # number of paths M=100 # number of time steps t=100 # number of tasks/simulations # running on server with 8 cores/16 threads from time import time times=[] for w in range(1,17): t0=time() pool=mp.Pool(processes=w) # the pool of workers result = pool.map(simulate_geometric_brownian_motion,t*[(M,I),]) # the mapping of the function to the list of parameter tuples times.append(time()-t0) plt.plot(range(1, 17), times) plt.plot(range(1, 17), times, 'ro') plt.grid(True) plt.xlabel('number of processes') plt.ylabel('time in seconds') plt.title('%d Monte Carlo simulations' % t) 性能和可用核心数量成正比。 不过, 超线程在本例中不能带来太多好处(甚至更糟) 简易的并行化 金融学中的许多问题可以应用简单的并行化技术, 例如, 在算法的不同实例之间没有共享数据时。Python的multiprocesing模块可以高效地利用现代硬件架构的能力, 一般不需要改变基本算法或者并行执行的Python函数. ## 8.5 动态编译 ## Numba ([http://numba.pydata.org][http_numba.pydata.org])是开源 、 NumPy 感知的优化Python 代码编译器。它使用 LLVM 编译器基础架构,将Python 字节代码编译专门用于 NumPy运行时和SciPy模块的机器代码。 ### 8.5.1 介绍性示例 ### from math import cos,log def f_py(I,J): res=0 for i in range(I): for j in range(J): res+=int(cos(log(1))) return res I,J=5000,5000 %time f_py(I,J) # Wall time: 30 s # 25000000 def f_np(I, J): a = np.ones((I, J), dtype=np.float64) return int(np.sum(np.cos(np.log(a)))), a %time res, a = f_np(I, J) # Wall time: 1.34 s a.nbytes # 200000000 import numba as nb f_nb=nb.jit(f_py) %time f_nb(I,J) # Wall time: 741 ms # 25000000 func_list=['f_py','f_np','f_nb'] data_list=3*['I,J'] perf_comp_data(func_list,data_list) # function:f_nb, av.item sec: 0.00001, relative: 1.0 # function:f_np, av.item sec: 1.36470, relative: 156714.8 # function:f_py, av.item sec: 29.53817, relative: 3391993.0 速效方法 改善(数值算法)性能的许多方法都需要花费可观的精力。利用Python和Numba, 就有了需要最少精力的 一种方法一一般来说, 只需要导入境库和一行附加代码 . 它不能用于所有类型算法,但是往往值得(简单地) 一试, 有时候确实能够快速取得效果。 ### 8.5.2 二项式期权定价方法 ### 前面使用蒙特卡洛模拟方法、 利用并行计算估计欧式看涨期权的价值。估算期权价值的另一种流行数值方法是二项式期权定价模型。 这种模型和Black-Scholes-Meron设置一样有风险资产(指数或者股票)以及无风险资产(债券)。 和蒙特卡洛方法一样,从当天到期权到期日的时间间隔被分为通常等距的子间隔Δt, 如果时间s的指数水平为Ss, 则 t = s+Δt 时的指数水平为St = Ss·m , 其中m是从{u, d \} 中随机选取(![这里写图片描述][70 3] )。r是 一个常数一一无风险利率。 风险中立的上涨概率为![这里写图片描述][70 4]。 对该模型进行参数化: # model & option parameters S0=100. # initial index level T=1. # call option maturity r=0.05 # constant short rate vola=0.20 # constant volatility factor of diffusion # time parameters M=1000 #time steps dt=T/M # length of time interval df= exp(-r*dt) # discount factor per time interval # binomial parameters u=exp(vola*sqrt(dt)) # up-movement d=1/u # down-movement q=(exp(r*dt)-d)/(u-d) # martingale probability 欧式期权二项式算法的实现主要包含如下部分: **指数水平模拟** 连步模拟指数水平。 **内在价值计算** 计算到期日和每个时间步的内在价值。 **风险中性折算** 逐步折算(预期)内在价值直到达到现值。 在Python中,这可能采取函数binomial\_py中的形式。该面数使用NumPy ndarray对象作为基本数据结构, 并实现3个不同的嵌套循环,以实现上述的3个步骤: from math import * # model & option parameters S0=100. # initial index level T=1. # call option maturity r=0.05 # constant short rate vola=0.20 # constant volatility factor of diffusion # time parameters M=1000 #time steps dt=T/M # length of time interval df= exp(-r*dt) # discount factor per time interval # binomial parameters u=exp(vola*sqrt(dt)) # up-movement d=1/u # down-movement q=(exp(r*dt)-d)/(u-d) # martingale probability import numpy as np def binomial_py(strike): """ Binomial option pricing via looping :param strike:float strike price of the European call option :return: """ # LOOP 1 - Index Levels S=np.zeros((M+1,M+1),dtype=np.float64) # index level array S[0,0]=S0 z1=0 for j in range(1,M+1,1): z1=z1+1 for i in range(z1+1): S[i,j]=S[0,0]*(u**j)*(d**(i*2)) # LOOP 2 - Inner Values iv = np.zeros((M+1,M+1),dtype=np.float64) # inner value array z2=0 for j in range(0,M+1,1): for i in range(z2+1): iv[i,j]=max(S[i,j]-strike,0) z2=z2+1 # LOOP 3 - Valuation pv = np.zeros((M+1,M+1),dtype=np.float64) # present value array pv[:,M]=iv[:,M] # initialize last time point z3=M+1 for j in range(M-1,-1,-1): z3=z3-1 for i in range(z3): pv[i,j]=(q*pv[i,j+1]+(1-q)*pv[i+1,j+1])*df return pv[0,0] 上函数使用前面指定的参数. 返回欧式看涨期权的现值: %time round(binomial_py(100),3) # Wall time: 4.23 s # 10.449 将这个结果与蒙特卡洛函数bsm\_mcs\_valuation返回的估算结果比较 %time round(bsm_mcs_valuation(100),3) # Wall time: 15 ms # 10.183 两个值很类似,它们只是“相似” 而不是相同。是因为蒙特卡洛估值和bsm\_mcs\_valuaton所实现的算法都不是很精确, 不同的随机数会导致(稍有)不同的估算结果, 对于健全的蒙特卡洛估算来说, 每次模拟使用2000Q条路径也可能略少一些(但是可以得到较高的估值速度)。 相比之下, 本例中的二项式期权估价使用 1000 个时间步已经相当精确,但是花费的时间也长得多。 可以尝试 NumPy 向量化技术,从二项式方法中得到同样精确、但是速度更快的结果。 binomial\_np 函数初看有些神秘,但是, 当运行单独的构建步骤并检查结果, 后台( NumPy )发生的操作就显而易见了: def binomial_np(strike): """ Binomial option pricing with NumPy :param strike: float strike price of the European call option :return: """ # Index Levels with NumPy mu=np.array(M+1) mu=np.resize(mu,(M+1,M+1)) md=np.transpose(mu) mu=u**(mu-md) S=S0*mu*md # Valuation Loop pv=np.maximum(S-strike,0) z=0 for t in range(M-1,-1,-1): # backward iteration pv[0:M-z,t]=(q*pv[0:M-z,t+1]+(1-q)*pv[1:M-z+1,t+1])*df z+=1 return pv[0,0] 下面我们简单地看看后台的情况。 为了简洁和易于理解, 只考虑 M = 4 的时间步。第一步如下: # 第一步 M = 4 # four time steps only mu = np.arange(M + 1) mu # array([0, 1, 2, 3, 4]) # 第二步 mu = np.resize(mu, (M + 1, M + 1)) mu # array([[0, 1, 2, 3, 4], # [0, 1, 2, 3, 4], # [0, 1, 2, 3, 4], # [0, 1, 2, 3, 4], # [0, 1, 2, 3, 4]]) # 第三步 md = np.transpose(mu) md # array([[0, 0, 0, 0, 0], # [1, 1, 1, 1, 1], # [2, 2, 2, 2, 2], # [3, 3, 3, 3, 3], # [4, 4, 4, 4, 4]]) # 第四步 mu = u ** (mu - md) mu.round(3) # array([[ 1. , 1.006, 1.013, 1.019, 1.026], # [ 0.994, 1. , 1.006, 1.013, 1.019], # [ 0.987, 0.994, 1. , 1.006, 1.013], # [ 0.981, 0.987, 0.994, 1. , 1.006], # [ 0.975, 0.981, 0.987, 0.994, 1. ]]) # 第五步 md = d ** md md.round(3) # array([[ 1. , 1. , 1. , 1. , 1. ], # [ 0.994, 0.994, 0.994, 0.994, 0.994], # [ 0.987, 0.987, 0.987, 0.987, 0.987], # [ 0.981, 0.981, 0.981, 0.981, 0.981], # [ 0.975, 0.975, 0.975, 0.975, 0.975]]) # 最后将所有步骤聚合起来 S = S0 * mu * md S.round(3) # array([[ 100. , 100.634, 101.273, 101.915, 102.562], # [ 98.743, 99.37 , 100. , 100.634, 101.273], # [ 97.502, 98.121, 98.743, 99.37 , 100. ], # [ 96.276, 96.887, 97.502, 98.121, 98.743], # [ 95.066, 95.669, 96.276, 96.887, 97.502]]) 在ndarray对象S中,只有上三角矩阵是重要的。虽然这种方法进行的计算多于原则上的需要,但是这种方法和预计的一样,比严重依赖Python级别嵌套循环的第一个版本快得多: M=1000 # reset number of time steps %time round(binomial_np(100),3) # Wall time: 1.03 s # 0.0 这个结果不太对 Numba在金融算法中也是很重要 binomial_nb=nb.jit(binomial_py) %time round(binomial_nb(100),3) # Wall time: 1.58 s # 10.449 我们还没有看出对NumPy向盘化版本有多少加速效果,因为第一次调用编译后的函数涉及一些开销。因此,使用 prf\_comp\_func函数应该更现实地揭示出不同实现的性能对比。显然,Numba编译版本确实明显快于NumPy版本: func_list=['binomial_py','binomial_np','binomial_nb'] K=100 data_list=3*['K'] perf_comp_data(func_list,data_list) # function:binomial_nb, av.item sec: 0.12641, relative: 1.0 # function:binomial_np, av.item sec: 0.96281, relative: 7.6 # function:binomial_py, av.item sec: 4.26450, relative: 33.7 我们可以得出如下结论: **效率**:使用Nnmba只需要花费很少的额外精力。原始函数往往完全不需要改变;你所需要做的就是调用jlt函数。 **加速**:Numba往往带来执行速度的显著提高.不仅和纯Py曲。n相比是如此.即使对向量化的NumPy实现也有明显优势。 **内存**:使用Numba不需要初始化大型数组对象;编译器专门为手上的问题生成机器代码(和Numpy的 “通用 ” 函数相比)并维持和纯Python相同的内存效率。 ## 8.6 用Cython进行静态编译 ## Numba的优势是对任意函数应用该方法毫不费力。但是,Numba只能为某些问题 “毫不费力 ” 地产生显著的性能改善。另一种方法更为灵活,但是也需要更多精力,这就是通过Cython的静态编译, Cython是Python和C语言的混血儿。从Python的角度看,需要注意的主要不同是静态类型声明(和 C语言相同)和一个单独的编译步骤(和任何编译语言相同)。 # 正常的Python代码: def f_py(I, J): res = 0. # we work on a float object for i in range(I): for j in range(J * I): res += 1 return res I,J=500,500 %time f_py(I,J) # Wall time: 9 s # Out[4]: 125000000.0 使用Cython静态类型声明的嵌套循环 创建一个名为nested\_loop.pyx的文件 # Nested loop example with Cython # nested_loop.pyx def f_cy(int I,int J): cdef double res = 0 # double float nuch slower than in or long for i in range(I): for j in range(J*I): res+=1 return res 在这个简单的例子中不需要任何特殊的C模块 ,导人模块有一种简单的方法一一就是通过pyximport import pyximport pyximport.install() # 直接从Cython模块中导人 import sys sys.path.append('E:\python_for_finance\chapter08') # path to the Cython script # not needed if in same directory from nested_loop import f_cy # 如果报错: Unable to find vcvarsall.bat # 是因为找不到vcvarsall.bat,这个问题件是在VS目录下的, # 我的VS2015的目录是 E:\Program Files (x86)\Microsoft Visual Studio 14.0 # 但是里面没有这个文件。这时可以在VS中添加一个C++项目,VS会提醒安装新的软件包,继续安装就可以了 # 安装好后就可以搜到vcvarsall.bat了 # 然后添加环境变量 # VS90COMNTOOLS : E:\Program Files (x86)\Microsoft Visual Studio 14.0\VC I, J = 500, 500 %time res = f_cy(I, J) # Wall time: 131 ms res # 125000000.0 在IPython Notebook中工作时,使用Cython有一个更便利的方法: %load_ext Cython %%cython def f_cy(int I,int J): cdef double res = 0 # double float nuch slower than in or long for i in range(I): for j in range(J*I): res+=1 return res I, J = 500, 500 %time res = f_cy(I, J) # Wall time: 131 ms 性能结果相同 res # 125000000.0 看看Numba在这种情况下能起什么作用 import numba as nb f_nb=nb.jit(f_py) %time res=f_nb(I,J) # Wall time: 947 ms # 第一次调用函数时, 性能比 Cython 版本差(第一次调用 Numba 编译函数总是有某些开销) %time res=f_nb(I,J) # Wall time: 131 ms 再次调用,性能就相同了 ## 8.7 在GPU上生成随机数 ## 最后 一个主题是使用设备进行大规模的并行操作——也就是通用图形处理单元(GPGPU 或者简称 GPU )。 要使用 Nvidia GPU , 就必须安装 CUDA (统一计算设备架构, [https://developer.nvidia..com][https_developer.nvidia..com] )。利用 Nvidia GPU 的简单方法之一是使用 NumbaPro,这个由 Contnuum Analytics 开发的高性能库为 GPU(或者多核 CPU )动态编译 Python。 有一个金融领域可以从 GPU 的使用中得到很大的好处:蒙特卡洛模拟。 特别是(伪)随机数生成。 [70]: /images/20220521/43eec89b3f2c4638bb32f45623f62770.png [Black-Scholes-Metron SDE]: /images/20220521/be8d2fd27c4a41918817782671680859.png [70 1]: /images/20220521/73023a5e2f784978874204ccb2414f62.png [70 2]: /images/20220521/60db7a66c19e4388927a70331c417908.png [http_numba.pydata.org]: http://numba.pydata.org [70 3]: https://img-blog.csdn.net/20180701193833701?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjAxODI1OA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70 [70 4]: /images/20220521/cef8c147f9b14a7b80bdcc83578a5ad4.png [https_developer.nvidia..com]: https://developer.nvidia..com
相关 Python金融大数据分析——第10章 推断统计学 笔记3 第10章 推断统计学 10.4 风险测度 10.4.1 风险价值 10.4.2 信用 向右看齐/ 2022年05月21日 12:24/ 0 赞/ 265 阅读
相关 Python金融大数据分析——第10章 推断统计学 笔记1 第10章 推断统计学 10.1 随机数 10.2 模拟 10.2.1 随机变量 心已赠人/ 2022年05月21日 08:30/ 0 赞/ 246 阅读
相关 Python金融大数据分析——第9章 数学工具 笔记 第9章 数学工具 9.1 逼近法 9.1.1 回归 9.1.2 插值 ╰半橙微兮°/ 2022年05月21日 06:45/ 0 赞/ 474 阅读
相关 Python金融大数据分析——第8章 高性能的Pyhon 笔记 第8章 高性能的Python 8.1 Python范型与性能 8.2 内存布局与性能 8.3 并行计算 - 日理万妓/ 2022年05月21日 05:54/ 0 赞/ 397 阅读
相关 Python金融大数据分析——第6章 金融时间序列 笔记 第6章 金融时间序列 6.1 pandas基础 6.1.1 使用DataFrame类的第一步 我会带着你远行/ 2022年05月21日 01:14/ 0 赞/ 469 阅读
相关 Python金融大数据分析——第10章 推断统计学 笔记2 第10章 推断统计学 10.3 估值 10.3.1 欧式期权 10.3.2 美式期权 系统管理员/ 2022年05月20日 20:09/ 0 赞/ 394 阅读
相关 Python金融大数据分析——第16章 金融模型的模拟 笔记 第16章 金融模型的模拟 16.1 随机数生成 16.2 泛型模拟类 16.3 几何布朗运动 野性酷女/ 2022年05月20日 08:18/ 0 赞/ 358 阅读
相关 Python金融大数据分析——第15章 估值框架 笔记 第15章 估值框架 15.1 资产定价基本定理 15.1.1 简单示例 15.1.2 痛定思痛。/ 2022年05月20日 08:17/ 0 赞/ 619 阅读
相关 Python金融大数据分析——第13章 面向对象 笔记 第13章 面向对象和图形用户界面 13.1 面向对象 13.1.1 Python类基础知识 不念不忘少年蓝@/ 2022年05月20日 03:15/ 0 赞/ 338 阅读
相关 Python金融大数据分析——第12章 Excel集成 笔记 第12章 Excel集成 12.1 基本电子表格交互 12.1.1 生成工作簿(.xls) 淡淡的烟草味﹌/ 2022年05月20日 00:46/ 0 赞/ 249 阅读
还没有评论,来说两句吧...