最全百倍加速!Python量化策略的算法性能提升指南_技术性策略python,阿里面试被放鸽子

如果你也是看准了Python,想自学Python,在这里为大家准备了丰厚的免费学习大礼包,带大家一起学习,给大家剖析Python兼职、就业行情前景的这些事儿。

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、全套PDF电子书

书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

成为一个Python程序员专家或许需要花费数年时间,但是打下坚实的基础只要几周就可以,如果你按照我提供的学习路线以及资料有意识地去实践,你就有很大可能成功!
最后祝你好运!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

for new_tick in test_data:
    # 使用numpy数组的底层数据偏移来实现数据更新
    data_window[0:ma_length-1] = data_window[1:ma_length]
    data_window[-1] = new_tick
    ma.append(data_window.mean())

return ma

**ma\_numpy\_right测试结果**


* 单次耗时:0.614300012589秒
* 单个数据点耗时:6.17386947325微秒


速度比ma\_basic提高了大约2倍,看来NumPy也就这么回事了。


### JIT神器:Numba


关心过Python性能的朋友应该都听过PyPy的大名,通过重新设计的Python解释器,PyPy内建的JIT技术号称可以将Python程序的速度提高几十倍(相比于CPython),可惜由于兼容性的问题并不适合于量化策略开发这一领域。


幸运的是,我们还有Anaconda公司推出的Numba。Numba允许用户使用基于LLVM的JIT技术,对程序内想要提高性能的部分(函数)进行局部优化。同时Numba在设计理念上更加务实:可以直接在CPython中使用,和其他常用的Python模块的兼容性良好,并且最爽的是使用方法傻瓜到了极点:



使用numba加速,ma_numba函数和ma_basic完全一样

import numba

@numba.jit
def ma_numba(data, ma_length):
ma = []
data_window = data[:ma_length]
test_data = data[ma_length:]

for new_tick in test_data:
data_window.pop(0)
data_window.append(new_tick)
sum_tick = 0
for tick in data_window:
sum_tick += tick
ma.append(sum_tick/ma_length)

return ma


**ma\_numba测试结果**


* 单次耗时:0.043700003624秒
* 单个数据点耗时:0.439196016321微秒


OMG!就加了一行@numba.jit,性能竟然提高了26倍!这估计是按照代码修改行数算,性价比最高的优化方案了。


### 改写算法


从编程哲学的角度来看,想提高计算机程序的速度,一个最基本的原则就是降低算法复杂度。看到这里估计早就有量化老手ma\_basic不爽了,弄个复杂度O(N)的算法来算平均值,就不能缓存下求和的结果,把复杂度降低到O(1)么?



将均线计算改写为高速算法

def ma_online(data, ma_length):
ma = []
data_window = data[:ma_length]
test_data = data[ma_length:]

# 缓存的窗口内数据求和结果
sum_buffer = 0

for new_tick in test_data:
    old_tick = data_window.pop(0)
    data_window.append(new_tick)

    # 如果缓存结果为空,则先通过遍历求第一次结果
    if not sum_buffer:
        sum_tick = 0
        for tick in data_window:
            sum_tick += tick
        ma.append(sum_tick/ma_length)

        # 将求和结果缓存下来
        sum_buffer = sum_tick
    else:
        # 这里的算法将计算复杂度从O(n)降低到了O(1)
        sum_buffer = sum_buffer - old_tick + new_tick
        ma.append(sum_buffer/ma_length)

return ma

**ma\_online测试结果**


* 单次耗时:0.0348000049591秒
* 单个数据点耗时:0.349748793559微秒


哲学果然才是最强大的力量!!!  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/dc46b354293f4ba69b1ebed5b8d386f7.png)  
 (索罗斯:其实我是个哲学家。)


改写算法后的ma\_online无需JIT就超越了ma\_numba,将性能提高到了33倍(对比ma\_basic),如果再把numba加上会如何?



高速算法和numba结合,ma_online_numba函数和ma_online完全一样

@numba.jit
def ma_online_numba(data, ma_length):
ma = []
data_window = data[:ma_length]
test_data = data[ma_length:]

sum_buffer = 0

for new_tick in test_data:
    old_tick = data_window.pop(0)
    data_window.append(new_tick)

    if not sum_buffer:
        sum_tick = 0
        for tick in data_window:
            sum_tick += tick
        ma.append(sum_tick/ma_length)
        sum_buffer = sum_tick
    else:
        sum_buffer = sum_buffer - old_tick + new_tick
        ma.append(sum_buffer/ma_length)

return ma

**ma\_online\_numba测试结果**


* 单次耗时:0.0290000200272秒
* 单个数据点耗时:0.29145748771微秒


尽管性能进一步提升了到了40倍,不过相比较于ma\_numba对比ma\_basic的提升没有那么明显,果然哲学的力量还是太强大了。


### 终极武器:Cython


到目前为止使用纯Python环境下的优化方法我们已经接近了极限,想要再进一步就得发挥Python胶水语言的特性了:使用其他扩展语言。由于CPython虚拟机的开发语言是C,因此在性能提升方面的扩展语言主要选择就是C/C++,相关的工具包括ctypes、cffi、Swig、Boost.Python等,尽管功能十分强大,不过以上工具都无一例外的需要用户拥有C/C++语言相关的编程能力,对于很多Python用户而言是个比较麻烦的事。


好在Python社区对于偷懒的追求是永无止境的,Cython这一终极武器应运而生。关于Cython的详细介绍可以去官网看,简单来它的主要作用就是允许用户以非常接近Python的语法来实现非常接近C的性能。


先来试试最简单的方法:完全不修改任何代码,只是把函数放到.pyx文件里,调用Cython编译成.pyd扩展模块。



基础的cython加速

def ma_cython(data, ma_length):
ma = []
data_window = data[:ma_length]
test_data = data[ma_length:]

for new_tick in test_data:
    data_window.pop(0)
    data_window.append(new_tick)

    sum_tick = 0
    for tick in data_window:
        sum_tick += tick
    ma.append(sum_tick/ma_length)

return ma

**ma\_cython测试结果**


* 单次耗时:0.600800013542秒
* 单个数据点耗时:6.03819109088微秒


ma\_cython和ma\_basic的代码完全相同,简单使用Cython编译后性能提高了大约1倍,不过这和之前我们已经达成的优化效果比可以说是毫无吸引力。


Cython官方的Quick Start里,第一步是教会用户如何去编译程序,第二步就是如何使用静态声明来大幅提高性能,所以我们的下一步就是:静态声明+高速算法。



cython和高速算法

def ma_cython_online(data, ma_length):
# 静态声明变量
cdef int sum_buffer, sum_tick, old_tick, new_tick

ma = []
data_window = data[:ma_length]
test_data = data[ma_length:]
sum_buffer = 0

for new_tick in test_data:
    old_tick = data_window.pop(0)
    data_window.append(new_tick)

    if not sum_buffer:
        sum_tick = 0
        for tick in data_window:
            sum_tick += tick
        ma.append(sum_tick/ma_length)

        sum_buffer = sum_tick
    else:
        sum_buffer = sum_buffer - old_tick + new_tick
        ma.append(sum_buffer/ma_length)

return ma

**ma\_cython\_online测试结果**


* 单次耗时:0.00980000495911秒
* 单个数据点耗时:0.0984925121518微秒  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/2a07394600a34b7b9f377c8bee667a8c.png)  
 117倍!!!比ma\_online\_numba的速度还提高了接近3倍,98纳秒的计算速度已经足以满足大部分毫秒级别高频策略的延时需求。


主要的功臣是这行:



> 
> cdef int sum\_buffer, sum\_tick, old\_tick, new\_tick
> 
> 
> 


把函数中用到的变量静态声明成int类型后,Cython在编译时无需再考虑Python对象的动态性特点,可以把整个函数高度优化成类似静态语言的实现,从而达到了接近C语言的运行性能,再加上复杂度O(1)的高速算法,有这个级别的性能提升也就不足为奇了。


附上简单的Cython使用指南:


1. 把要使用Cython编译的函数放到.pyx文件中,比如test.pyx
2. 创建setup.py用于设置相关编译选项
3. 打开cmd或者terminal进入到test.pyx和setup.py所在的文件夹
4. 运行python setup.py build\_ext --inplace,执行编译
5. 若编译成功则在当前文件夹下会出现test.pyd
6. 打开python像使用其他模块一样载入(import)test.pyd使用


### 写在最后


感谢Numba、Cython和哲学的强大力量,作者最终装逼成功,从自己挖的“百倍加速”这个坑里爬了出来,不用当标题党了。


最终的算法性能对比图:  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/eb81c43e7dbb4a1f95dfcc12ba6af62c.png)  
 **最后做一些总结吧:**


1. 现实工作中遇到需要优化Python程序性能时,首先要做的就是去寻找程序里延时较大的热点代码,找到了问题所在,解决方案才有意义;
2. 所有的优化工作都应该基于测试来一步步推进,同样的优化方法对于不同类型的代码效果可能是截然相反的,同时错误的优化方法还不如不要优化(比如ma\_numpy\_wrong);
3. 只需增加一句代码(@numba.jit)就能实现加速的Numba无疑是性价比最高的优化方案,值得优先尝试,不过需要注意numba的JIT技术局限性比较大(主要针对数值计算相关的逻辑);
4. 学习如何降低算法复杂度和编写更高效的算法,可以在潜移默化中提高自己的编程水平,在长期而言是对Quant或者程序员最有价值的优化方法;
5. 如果其他优化方法都无法达到令你满意的性能水平,试试Cython(记得一定要加静态声明);
6. 一个好的程序架构设计非常重要,把功能不同的计算逻辑分解到不同的函数里,适当降低每个函数的代码行数,会有助于后期的性能优化工作。


### 关于Python学习资料:


**朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】。**  
 ![](https://img-blog.csdnimg.cn/0b4e12ce755a46d2a0d6502e8ed1a507.png#pic_center)


### 一、Python所有方向的学习路线


Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/a6067e55c54b49078778d56ea0db7fe2.png)


### 二、Python必备开发工具


![在这里插入图片描述](https://img-blog.csdnimg.cn/e496e6652efd47f5bbe73ad2ee082d4a.png)


### 三、Python视频合集


观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c6ac9e53d20b448ab9f2837b7f173b94.png)


### 四、实战案例


光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。![在这里插入图片描述](https://img-blog.csdnimg.cn/7b7d7e133d984b85a09422c3ccfa7396.png)


### 五、Python练习题




现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。



分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

![](https://img-blog.csdnimg.cn/img_convert/21b2604bd33c4b6713f686ddd3fe5aff.png)



**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 27
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值