欢迎大家订阅《教你用 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. 动态、静态编译以及MD、MDd、MT、MTd编译

    本文转自:https://blog.csdn.net/u012273127/article/details/71419499 一.问题的引出 最近在VS2012中新建了一个MFC的工程,在自己电脑上运 ...

  2. VMWare:vSphere6 企业版参考序列号

    HV4WC-01087-1ZJ48-031XP-9A843 NF0F3-402E3-MZR80-083QP-3CKM2 4F6FX-2W197-8ZKZ9-Y31ZM-1C3LZ JZ2E9-6D2D ...

  3. input 属性radio中设置checked 不生效

    同一个页面中有许多地方都用到了单选按钮并设置了默认选中 , 结果在运行的时候发现单选按钮没有被默认选中 由于是复制然后修改个别属性 ,然后直接使用的 , 所以name值忘记修改了 , 单选框是根据na ...

  4. 定义 java 基本数据类型

    package debug; class Demo { /* * 定义八种基本数据类型,如下 */ public static void main(String[] args) { //define ...

  5. GUI_事件监听机制与ActionListener演示

    事件监听机制组成: 事件源:(awt包或者swing包中的那些图形界面组件)(被打的那个人,被点击的组件,可以承受某些事件,但不是所有事件都能承受) 事件:每个事件源都有自己特有的对应事件和共性事件( ...

  6. python 在windows下的 虚拟环境

    解决 python 环境问题 windows 下安装 pip install virtualenv virtualenv的基本使用 1.1 创建虚拟环境 virtualenv venv 为环境指定Py ...

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

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

  8. 【转】MySQL 当记录不存在时insert,当记录存在时update

    MySQL当记录不存在时insert,当记录存在时更新:网上基本有三种解决方法 第一种: 示例一:insert多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语句 ...

  9. 小度之家SDK功能介绍

    https://developer.dueros.baidu.com/doc/device-devkit/intro_markdown

  10. esp8266(0) AT指令

    http://www.shaoguoji.cn/2017/01/15/ESP8266-usage/ 注意事项 使用WiFi模块的一些细节及注意事项 模块使用3.3V供电,一定注意电源的稳定,一些USB ...