欢迎大家订阅《教你用 Python 进阶量化交易》专栏!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外已陆续推出一些手记来辅助同学们学习本专栏内容,目前已推出如下扩展篇:

在第一篇《管理概率==理性交易》中笔者结合一个简单的市场模型介绍了为什么在没有概率优势的前提下参与交易会亏钱,其实股票交易和玩一个游戏、做一个项目理念是相通的,需要章法、需要制定策略,否则就和抛硬币赌博一样一样的,用量化交易可以帮助我们管理好概率,更理性的去下单。

在第二篇《线性回归拟合股价沉浮》中笔者在专栏《股票交易策略开发:走势线性回归选股策略》小节的基础上对线性回归方法的策略应用做进一步的扩展介绍。由于线性回归作用于股票收盘价的整个周期,前后两段完全相反的周期会彼此作用,最终影响拟合的角度值,于是笔者设定窗口期用移动窗口的方式拟合股价的走势,寻找角度曲线的拐点以预示新一轮的反转走势,给大家提供一个衍生的策略思路。

在第三篇《最大回撤评价策略风险》中笔者在专栏
《股票交易数据可视化:买卖区间下策略收益绘制》的基础上对策略的最大回撤指标做一定的扩展介绍。投资是有风险的,那么如何去衡量这个风险呢?最大回撤率就是一种直观的将风险切实量化的指标,它描述了买入股票后,在策略出现最糟糕的情况下会损失多少钱,这也直接关系到了风险策略中止损因子的设定。

在第四篇《寻找最优化策略参数》中笔者在专栏
《股票交易策略开发:趋势突破择时策略》的基础上对寻找最优化策略参数的方法做一些扩展介绍。对于寻找最优化参数的方法可以选择枚举法或者蒙特卡洛法。枚举法适用于解决效率要求不高,样本规模小的问题。蒙特卡洛法得到的结果并不一定是最优的,但是在大规模样品的场合下可以更快地找到近似最优结果。

在第五篇《标记A股市场涨跌周期》中笔者在专栏
《股票交易数据的自动下载》的基础上对matplotlib绘图工具的使用方法做一些扩展介绍,在A股历史走势图中标记出市场涨跌周期。

在第六篇《Tushare Pro接口介绍》中笔者在《股票交易数据的自动下载》的基础上扩展介绍使用Tushare Pro版本获取财经和股票交易数据的方法。


本次场外篇笔者在《用装饰器注册股票池》的基础上对装饰器的进行扩展介绍,通过装饰器方式实现timeit测试函数执行时间功能。

当我们对一个函数或若干语句的执行时间要求较高时,希望能够测试得到该代码的开销时间是多少。比如遍历计算每个交易日股票数据的价格波动,如下所示:

df_sh['diff_price'] = df_sh.apply(lambda row: (row['high']-row['low']), axis =1)
"""
date open close ... volume code diff_price
0 2018-01-02 3314.03 3348.33 ... 202278860.0 sh 35.02
1 2018-01-03 3347.74 3369.11 ... 213836149.0 sh 34.63
2 2018-01-04 3371.00 3385.71 ... 206955288.0 sh 27.53
3 2018-01-05 3386.46 3391.75 ... 213060681.0 sh 21.82
4 2018-01-08 3391.55 3409.48 ... 236165106.0 sh 28.17
"""

最先想到的是采用Python内置time模块来测试代码运行时间,使用时导入模块,如下所示:

import time

其中time.perf_counter()和time.process_time() 可以实现我们的需求。
time.perf_counter():返回计时器的精准时间(系统的运行时间),包含整个系统的睡眠时间。由于返回值的基准点是未定义的,所以,只有连续调用的结果之间的差才是有效的。

time.process_time() :返回当前进程执行 CPU 的时间总和,不包含睡眠时间。由于返回值的基准点是未定义的,所以,只有连续调用的结果之间的差才是有效的。

此处使用time.perf_counter()方法实现,如下所示:

start = time.perf_counter()
#运行的程序
df_sh['diff_price'] = df_sh.apply(lambda row: (row['high']-row['low']), axis =1)
#运行的程序
elapsed = (time.perf_counter() - start)
print("Time used:",elapsed)
# Time used: 0.00546605699999958

另外可以使用Python更强大的计时库timeit测试执行时间,使用时导入timeit,如下所示:

from timeit import timeit

用timeit()测试一个函数的执行时间可按timeit(函数名_字符串,运行环境_字符串,number=运行次数)这个方式来实现,如下所示:

elapsed = timeit('func()', 'from __main__ import func', number=1)
print("Time used:",elapsed)
#Time used: 0.005263746999999985

由于电脑永远都有其他程序也在占用着资源,因此我们的程序不可能最高效地执行该函数。所以一般会进行多次试验,取最少的执行时间为真正的执行时间。此时可以使用repeat方法,使用时需要导入repeat ,如下所示:

from timeit import repeat

使用repeat方法和timeit用法相似,多了一个repeat参数,表示重复测试的次数(默认值为3),返回值为一个时间的列表,如下所示:

t_elapsed = repeat('func()', 'from __main__ import func', number=1, repeat=5)
print("Time used:",t_elapsed)
print("Time of min used:",min(t_elapsed))
#Time used: [0.005254602999999136, 0.005191876999999678, 0.00529747400000069, 0.005051099999999309, 0.005246075000000516]
#Time of min used: 0.005051099999999309

回到本篇的主题内容——装饰器,装饰器顾名思义就是“装饰”其他函数,为其他函数添加附加功能,原则上不能修改被装饰的函数的代码,也不能修改被装饰的函数的调用方式,这也是装饰器“厉害”的地方。

以上无论使用time,还是timeit,都需要对被测函数添加实现的代码,那么尝试使用装饰器来解决这个痛点,如下所示:

def timeit(func):
def wrapper(*args, **kwargs):
start = time.perf_counter()
func(*args, **kwargs)
elapsed = (time.perf_counter() - start)
print("Time used: %s ", elapsed)
return wrapper @timeit
def func_diff():
df_sh['diff_price'] = df_sh.apply(lambda row: (row['high']-row['low']), axis =1) # timeit(func_diff)()
func_diff()#Time used: %s 0.005055395000000074

关于装饰器的基础原理介绍,大家可以参阅专栏中的讲解,此处再次提炼下其关键点。执行func_diff()等价于执行timeit(func_diff)(),把函数作为一个变量传递给timeit函数, 此处timeit为二层嵌套的高阶函数。电动叉车

假如要像timeit模块那样有repeat、number参数扩展测试的需求,可以再进一步升级下装饰器,如下所示:

# use decorator method with parameter
def timer_para(number = 3, repeat = 3):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(repeat):
start = time.perf_counter()
for _ in range(number):
func(*args, **kwargs)
elapsed = (time.perf_counter() - start)
print("Time of %s used: %s ", i, elapsed)
return wrapper
return decorator @timer_para(number = 2, repeat = 2)
def func_diff_par():
df_sh['diff_price'] = df_sh.apply(lambda row: (row['high']-row['low']), axis =1) # timer_para(number = 2, repeat = 2)(func_diff_par)()
func_diff_par()
#Time of %s used: %s 0 0.01577713199999997
#Time of %s used: %s 1 0.015201944999999939

执行func_diff_par ()等价于执行timer_para(number = 2)(func_diff_par)(),此处timeit为三层嵌套的高阶函数,第1层是timer_para(number = 2),返回第2层decorator函数,第2层函数decorator接受func_diff_par函数作为参数进行调用,返回第三层函数wrapper。如此一来只需要使用@xxxx就可以一劳永逸地对所有函数测试执行时间了!!!

Python进阶量化交易专栏场外篇7- 装饰器计算代码时间的更多相关文章

  1. Python进阶量化交易场外篇5——标记A股市场涨跌周期

    新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...

  2. Python进阶量化交易场外篇4——寻找最优化策略参数

    新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...

  3. Python进阶量化交易场外篇3——最大回撤评价策略风险

    新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...

  4. Python开发【第十四篇】装饰器

    装饰器 什么是装饰器? ​ 装饰器是一个函数,主要作用是用来给包装另一个函数或者类 包装的目的是不改变原函数名(或类名)的情况下改变或添加被包装对象的功能 函数装饰器 是指装饰器是一个函数,传入的是一 ...

  5. Noah的学习笔记之Python篇:装饰器

    Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang  (http://www.cnblogs.com/noahzn/) ...

  6. 使用python装饰器计算函数运行时间的实例

    使用python装饰器计算函数运行时间的实例 装饰器在python里面有很重要的作用, 如果能够熟练使用,将会大大的提高工作效率 今天就来见识一下 python 装饰器,到底是怎么工作的. 本文主要是 ...

  7. python语法生成器、迭代器、闭包、装饰器总结

    1.生成器 生成器的创建方法: (1)通过列表生成式创建 可以通过将列表生成式的[]改成() eg: # 列表生成式 L = [ x*2 for x in range(5)] # L = [0, 2, ...

  8. Python自动化面试必备 之 你真明白装饰器么?

    Python自动化面试必备 之 你真明白装饰器么? 装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多小白来讲,这个功能 有点绕 ...

  9. python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解

    python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...

随机推荐

  1. 简单易懂的程序语言入门小册子(1):基于文本替换的解释器,lambda演算

    最近比较闲,打算整理一下之前学习的关于程序语言的知识.主要的内容其实就是一边设计程序语言一边写解释器实现它.这些知识基本上来自Programming Languages and Lambda Calc ...

  2. js计算两个日期的天数差值

    js计算两个日期的天数差值 通过两个日期计算这两个日期之间的天数差值 /** * 计算天数差的函数,通用 * @param sDate1 * @param sDate2 * @returns {Num ...

  3. January 15th, 2018 Week 03rd Monday

    We got things to do. Places to go. People to see. Futures to make. 我们有很多事情要做,有很多地方要去,有很多人要见,有很多美好的未来 ...

  4. Git的上传步骤

    Git的上传步骤 1.Git的命令基础 Git是当下最流行的版本控制工具(VCS),由linux系统之父linus开发.它能实现 团队中的代码协作开发,它在代码同步和代码管理方面功能强大,理念先进. ...

  5. 捕获海康威视IPCamera图像,转成OpenCV能够处理的图像(二)

    海康威视IPCamera图像捕获 捕获海康威视IPCamera图像.转成OpenCV能够处理的IplImage图像(一) 捕获海康威视IPCamera图像.转成OpenCV能够处理的IplImage图 ...

  6. zookeeper+kafka集群安装之中的一个

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/cheungmine/article/details/26678877 zookeeper+kafka ...

  7. for-in和for-of,forEach和Map

    for-in和for-of 1. for-in循环实际是为循环”enumerable“对象而设计的,是用来循环带有字符串key的对象的. 使用for in会遍历数组所有的可枚举属性,包括原型.所以fo ...

  8. go标准库的学习-database/sql/driver

    参考:https://studygolang.com/pkgdoc 1>导入方式: import "database/sql/driver" driver包定义了应被数据库驱 ...

  9. 树莓派3b安装Apache2+PHP+MySQL+phpyadmin

    树莓派型号:3B+ 系统环境:2017-04-10-raspbian-jessie 先更新一下源 BASIC sudo apt-get update 安装Apache2 BASIC sudo apt- ...

  10. easyui datagrid JS加载样式 表头乱

    解决方案,找了下资料,加一个遮罩层,提升用户体验. <script type="text/javascript"> var width = document.docum ...