Python进阶量化交易专栏场外篇7- 装饰器计算代码时间
欢迎大家订阅《教你用 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- 装饰器计算代码时间的更多相关文章
- Python进阶量化交易场外篇5——标记A股市场涨跌周期
新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...
- Python进阶量化交易场外篇4——寻找最优化策略参数
新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...
- Python进阶量化交易场外篇3——最大回撤评价策略风险
新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...
- Python开发【第十四篇】装饰器
装饰器 什么是装饰器? 装饰器是一个函数,主要作用是用来给包装另一个函数或者类 包装的目的是不改变原函数名(或类名)的情况下改变或添加被包装对象的功能 函数装饰器 是指装饰器是一个函数,传入的是一 ...
- Noah的学习笔记之Python篇:装饰器
Noah的学习笔记之Python篇: 1.装饰器 2.函数“可变长参数” 3.命令行解析 注:本文全原创,作者:Noah Zhang (http://www.cnblogs.com/noahzn/) ...
- 使用python装饰器计算函数运行时间的实例
使用python装饰器计算函数运行时间的实例 装饰器在python里面有很重要的作用, 如果能够熟练使用,将会大大的提高工作效率 今天就来见识一下 python 装饰器,到底是怎么工作的. 本文主要是 ...
- python语法生成器、迭代器、闭包、装饰器总结
1.生成器 生成器的创建方法: (1)通过列表生成式创建 可以通过将列表生成式的[]改成() eg: # 列表生成式 L = [ x*2 for x in range(5)] # L = [0, 2, ...
- Python自动化面试必备 之 你真明白装饰器么?
Python自动化面试必备 之 你真明白装饰器么? 装饰器是程序开发中经常会用到的一个功能,用好了装饰器,开发效率如虎添翼,所以这也是Python面试中必问的问题,但对于好多小白来讲,这个功能 有点绕 ...
- python中“生成器”、“迭代器”、“闭包”、“装饰器”的深入理解
python中"生成器"."迭代器"."闭包"."装饰器"的深入理解 一.生成器 1.生成器定义:在python中,一边 ...
随机推荐
- Unity 4.6 GUI
一起来窥探Unity的下一代GUI 预览 UI组件 UI结构 Canvas Button Selection List(滑动列表)
- Ubuntu 12.10 Tty (字符终端) 显示中文,和字体大小设置
Tty通过修改默认的中文编码字符,和安装zhcon都无法显示中文.可安装fbterm来显示中文,命令:sudo apt-get install fbterm安装即可,进入Tty: (Ctrl+Alt+ ...
- 函数重载(overload)
重载的定义及特点 在同一个类中,允许存在一个以上的同名函数, 只要他们的参数个数或者参数类型不同(不仅指两个重载方法的参数类型不同,还指相同参数拥有不同的参数类型顺序)就构成重载. 重载只和参数列表有 ...
- 17秋 软件工程 团队第五次作业 Alpha Scrum12
各个成员今日完成的任务 Alpha版本完成. 项目的发布说明 本版本的新功能 1.部门人员管理,包括纳新申请与审核: 2.部门活动发布与查看: 3.部门活动相册: 4.子部门信息录入. 软件对运行环境 ...
- 解决Could not load file or assembly CefSharp.Core.dll的问题
这个问题的中文提示是: 未能加载文件或程序集“CefSharp.Core.dll”或它的某一个依赖项.找不到指定的模块 具体原因是因为CefSharp运行时需要Visual C++ Redistrib ...
- 布局:高度已知,布局一个三栏布局,左栏和右栏宽度为200px,中间自适应
需求:高度已知为200px,写出三栏布局,左栏和右栏各位200px,中间自适应,如下图所示: 方法一:float浮动布局 原理是:定义三个区块,需要注意的是中间的区块放在右边区块的下面,统一设置高度为 ...
- HDU - 5078 水题
题意:最大困难=距离 / 相邻时间 #include<cstring> #include<cstdio> #include<cmath> #define ll do ...
- CSS中background属性详解
CSS背景属性 background css 说明 background-image:url(图片的网址); 背景图 background: url( 图片的网址 ); 背景 background-c ...
- 1.9 Android程序签名打包
本节引言: 本节给大家介绍的是如何将我们的程序打包成Apk文件,并且为我们的Apk签名! 1.什么是签名,有什么用: Android APP都需要我们用一个证书对应用进行数字签名,不然的话是无法安装到 ...
- oracle备份信息查询
SELECT TRIM(START_TIME || '#'), TRIM(END_TIME || '#'), TRIM(CASE OUTPUT_DEVICE_TYPE ...