第一章-学习之前的认知

影响股价的因素

1、公司自身因素2、心理因素3、行业因素4、经济因素5、市场因素6、政治因素

金融量化投资

量化投资的优势1、避免主观情绪,人性弱点和认知偏差,选择更加客观2、能同时包括多角度的观察和多层次的模型3、及时跟踪市场变化,不断发现新的统计模型,寻找交易机会4、在决定投资策略后,能通过回测验证其效果

量化策略

通过一套固定的逻辑来分析、判断和决策,自动地进行股票交易

策略的周期

实现想法、学习知识

实现策略:python

检验策略:回测、模拟交易

实盘交易

优化策略,放弃策略

第二章-科学计算基础包---numpy

量化投资和python

为什么选择python呢?

其他选择:excel、SAS/SPSS(统计软件,无编程)、R(功能太单一,制作数据分析)

量化投资实际上就是分析数据从而做出决策的过程

python数据处理相关模块1、NumPy:数组批量计算2、pandas:灵活的表计算3、Matplotlib:数据可视化

怎么使用python进行量化投资

自己编写

NumPy+ pandas +Matplotlib....

在线平台

聚宽、优矿、米筐、Quantopian....

开源框架

RQAlpha、QUANTAXIS....

IPython的使用

pip3 install ipthon

也可以直接安装anacoda ,集成了ipython、NumPy pandas Matplotlib 等许多python的常用模块和框架

与python解释器的使用方法一致

TAB键自动完成

?内省、查看具体信息

?进行模糊匹配,命名空间搜索

!执行系统命令

某些命令不用加也能执行

??两个问号

快捷键

IPython的魔术命令

%timeit 很费事,他要跑很多次

%paste 执行剪切板中的python代码

%pdb 在异常发生后自动进入调试模式,使用on

然后就可以使用pdb相关的命令,进行调试状态

p命令最常用,打印的意思

%魔术命令

命令的历史可以使用上下方向键,或者%hist查看命令历史

_ 表示上一次的输出

__ 表示上两个命令

_48 第多少的结果

_i48 第多少行的结果的字符串形式

%bookmark 目录标签系统

IPython Notebook-Jupyter的初识

安装jupyter

使用notebook

进入了jupyter的web界面

创建新的notebook

出现一个小问题:编写的代码不能运行且前面的提示符In[*]

查看命令行,出现错误提示

将软件降级安装后,解决问题

可以用notebook写博客,支持makedown,而且他可以将页面直接输出成很多文本形式

正戏-Numpy模块

Numpy简介

实例展示为什么要使用numpy

例子:已知若干家跨国公司的市值,将其换算成人民币

普通的函数方法

1、将公司市值存储成列表或者其他格式2、创建变量,存储汇率2、遍历列表3、做乘法运算,放入新的列表

用numpy

例子2:已知每件商品的价格和每件商品的数量,计算总金额

还是用a作为价格,再创建一个数组作为每件商品的数量

计算每件商品的价格

计算总金额

ndarray-多维数组对象

ndarray-常用属性

In [26]: a.ndim

Out[26]: 1In [27]: a.size

Out[27]: 50In [28]: a.shape

Out[28]: (50,)-----------------------------In [30]: b = np.array([[1,2,3,],[4,5,6]])

In [31]: b.ndim

Out[31]: 2In [32]: b.size

Out[32]: 6In [33]: b.shape

Out[33]: (2, 3)-----------------------------三维-第三个维度相当于笔记本的每一页,翻个页就到另一面

In [35]: c = np.array([[[1,2,3,],[4,5,6]],[[1,2,3],[1,2,3]]])

In [36]: c

Out[36]:

array([[[1, 2, 3],

[4, 5, 6]],

[[1, 2, 3],

[1, 2, 3]]])

In [37]: c.shape

Out[37]: (2, 2, 3)------------------------------------数组的转置

In [39]: c =c.T

In [40]: c

Out[40]:

array([[[1, 1],

[4, 1]],

[[2, 2],

[5, 2]],

[[3, 3],

[6, 3]]])

In [41]: c =c.T

In [42]: c

Out[42]:

array([[[1, 2, 3],

[4, 5, 6]],

[[1, 2, 3],

[1, 2, 3]]])

ndarray-数据类型

查看数据类型

In [24]: a.dtype

Out[24]: dtype('float64')

我们使用的巨大部分都是数字类型,它本身就是用来做计算的

64位数的长度是多少(2**63-1)

In [25]: 2**64-1Out[25]: 18446744073709551615

numpy-array的创建

In [1]: #可以这样创建一个10位全是0的数组

In [2]: importnumpy as np

In [3]: a = np.array([0]*10)

In [4]: a

Out[4]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

In [5]: #也可以用zeros创建

In [6]: b = np.zeros(10)

In [7]: b

Out[7]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

In [8]: #可以看见都是0.,说明他是一个浮点数,来看一下类型

In [9]: b.dtype

Out[9]: dtype('float64')

In [10]: #创建的时候指定类型,不使用默认的,直接用int

In [11]: c = np.zeros(10,dtype='int')

In [12]: c

Out[12]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

In [13]: c.dtype

Out[13]: dtype('int32')

In [14]: #创建全是1的数组

In [15]: d = np.ones(10)

In [16]: d

Out[16]: array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

In [17]: #看一下empty的用法,创建空数组,里面放的都是随机数

In [18]: e = np.empty(50)

In [19]: e

Out[19]:

array([1.23004319e-311, 1.23004150e-311, 2.95806213e-311, 1.26927730e-277,5.54041819e+228, 2.84855906e-311, 5.97288716e-299, 3.28487474e-311,9.43293441e-314, 2.26784710e-308, 1.23004306e-311, 1.23002517e-311,3.38460664e+125, 6.69053866e+151, 6.56693077e-085, 1.03564308e-308,1.33360293e+241, 1.71632673e+243, 5.96115807e+228, 1.71011791e+214,5.67517369e-311, 1.00562508e-248, 2.85308965e-313, 2.14793507e-308,1.38760675e+219, 2.92135768e+209, 2.21211602e+214, 2.28723653e-308,6.96983359e+228, 1.33360298e+241, 2.11280666e+161, 1.29883065e+219,1.11074825e-310, 1.46972270e-200, 4.97508544e-313, 4.65203811e+151,4.66820502e+180, 5.61168418e-313, 3.81674046e-308, 1.33360303e+241,1.54523733e-310, 5.03961303e-266, 3.99046880e-008, 2.08868046e-310,2.53185169e-212, 7.44726967e-251, 1.39069238e-309, 2.75926410e-306,4.90398331e-307, 5.23951796e+202])

In [20]: #这些随机值是,之前内存的残存值。这个empty有什么用呢?

In [21]: #为了之后给里面赋值,因为它相对于zeros和ones创建的时候少了1个步骤,会更快一点

In [22]: #arange可以指定步长为小数,pyton中是不可以的

In [24]: f = np.arange(1,10,0.3)

In [25]: f

Out[25]:

array([1. , 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4. , 4.3, 4.6,4.9, 5.2, 5.5, 5.8, 6.1, 6.4, 6.7, 7. , 7.3, 7.6, 7.9, 8.2, 8.5,8.8, 9.1, 9.4, 9.7])

In [26]: #linspace线性空间,和arange非常相,但是完全不一样,把指定的范围数字分成间隔相同的份数,最后一个参数是数组的长度,即份数

In [31]: k = np.linspace(0,5,10) 或者是 np.linespace(0,5,num=10)

In [32]: k #并且linspace不像arange不包含最后一个数,它是包含最后一个数的,可以在最后看见5

Out[32]:

array([0. ,0.55555556, 1.11111111, 1.66666667, 2.22222222,2.77777778, 3.33333333, 3.88888889, 4.44444444, 5. ])

In [27]: g = np.linspace(1,100,100)

In [28]: g

Out[28]:

array([1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.,12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22.,23., 24., 25., 26., 27., 28., 29., 30., 31., 32., 33.,34., 35., 36., 37., 38., 39., 40., 41., 42., 43., 44.,45., 46., 47., 48., 49., 50., 51., 52., 53., 54., 55.,56., 57., 58., 59., 60., 61., 62., 63., 64., 65., 66.,67., 68., 69., 70., 71., 72., 73., 74., 75., 76., 77.,78., 79., 80., 81., 82., 83., 84., 85., 86., 87., 88.,89., 90., 91., 92., 93., 94., 95., 96., 97., 98., 99.,100.])

In [33]: #eye 生成单位矩阵,对角线上都是1,不做线性代数,基本不会遇到

In [37]: w = np.eye(5)

In [38]: w

Out[38]:

array([[1., 0., 0., 0., 0.],

[0.,1., 0., 0., 0.],

[0., 0.,1., 0., 0.],

[0., 0., 0.,1., 0.],

[0., 0., 0., 0.,1.]])

ndarray-批量运算

比较运算最后得到的是布尔值

如何快速生成一个二维数组

In [39]: np.arange(15).reshape((3,5))

Out[39]:

array([[ 0,1, 2, 3, 4],

[5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]])

ndarray-索引

array([[ 0, 1, 2, 3, 4],

[5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]])

In [40]: a = np.arange(15).reshape((3,5))

In [41]: a[2,2]

Out[41]: 12

adarray-切片

也是前包后不包

In [46]: f

Out[46]:

array([1. , 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4. , 4.3, 4.6,4.9, 5.2, 5.5, 5.8, 6.1, 6.4, 6.7, 7. , 7.3, 7.6, 7.9, 8.2, 8.5,8.8, 9.1, 9.4, 9.7])

In [48]: f[1:3]

Out[48]: array([1.3, 1.6])

但是数组切片,为了省空间,在切片的时候只是浅拷贝

如果要不影响原数组,切片的时候使用copy

In [55]: b = f[0:5]

In [56]: b

Out[56]: array([1. , 1.3, 1.6, 1.9, 2.2])

In [57]: b[0] = 5In [58]: b

Out[58]: array([5. , 1.3, 1.6, 1.9, 2.2])

In [59]: f

Out[59]:

array([5. , 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4. , 4.3, 4.6,4.9, 5.2, 5.5, 5.8, 6.1, 6.4, 6.7, 7. , 7.3, 7.6, 7.9, 8.2, 8.5,8.8, 9.1, 9.4, 9.7])

使用copy

b = f[0:5].copy()

多行切片

In [49]: a

Out[49]:

array([[ 0,1, 2, 3, 4],

[5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]])

In [50]: #多行切片,可以看做是[切行,切列]

In [54]: a[0:2,0:2]

Out[54]:

array([[0,1],

[5, 6]])

ndarray-布尔型索引

需求:选出列表中大于5的数

In [60]: importrandom#用列表的filter方法

In [61]: a = [random.randint(0,10) for i in range(20)]

In [62]: a

Out[62]: [1, 2, 1, 6, 1, 8, 6, 7, 3, 0, 6, 8, 2, 6, 0, 1, 4, 10, 0, 3]

In [63]: list(filter(lambda x:x>5, a))

Out[63]: [6, 8, 6, 7, 6, 8, 6, 10]#用数组的布尔值索引

In [64]: a =np.array(a)

In [65]: a[a>5]

Out[65]: array([ 6, 8, 6, 7, 6, 8, 6, 10])

In [66]: #布尔型索引的原理

In [67]: #第一步 a>5

In [68]: a>5Out[68]:

array([False, False, False, True, False, True, True, True, False,

False, True, True, False, True, False, False, False, True,

False, False])

In [69]: #第二步,返回每一位置为ture的位置的值

In [70]: b = np.array([1,2,3])

In [71]: c =np.array([True,False,True])

In [72]: b[c]

Out[72]: array([1, 3])

需求2:选出数组中大于5的偶数

题外:and 和 & 有什么区别?

ndarray-花式索引

注意:多维数组中,花式索引和花式索引不能出现在,逗号的两边

Numpy-通用函数

abs-批量求绝对值

In [2]: a = np.arange(-5,5)

In [3]: a

Out[3]: array([-5, -4, -3, -2, -1, 0, 1, 2, 3, 4])#直接用abs也可以

In [4]: abs(a)

Out[4]: array([5, 4, 3, 2, 1, 0, 1, 2, 3, 4])#严谨的用法是np.abs

In [5]: np.abs(a)

Out[5]: array([5, 4, 3, 2, 1, 0, 1, 2, 3, 4])

aqrt-开方

#直接使用会报错,没有这个sqrt,找不到

In [7]: sqrt(a)---------------------------------------------------------------------------NameError Traceback (most recent call last) in ()----> 1sqrt(a)

NameError: name'sqrt' is notdefined#math模块下有sqrt

In [8]: importmath#报错,sqrt一次只能处理一个值

In [11]: math.sqrt(a)---------------------------------------------------------------------------TypeError Traceback (most recent call last) in ()----> 1math.sqrt(a)

TypeError: only size-1arrays can be converted to Python scalars#使用np.sqrt ,因为负数不能求开方

In [10]: np.sqrt(a)

F:\Python36\Scripts\ipython3:1: RuntimeWarning: invalid value encountered insqrt

Out[10]:

array([ nan, nan, nan, nan, nan,

0. ,1. , 1.41421356, 1.73205081, 2. ])

把一个小数变成整数-取整和保留小数位

In [12]: a = 1.6

#这种取整,叫做向0取整

In [13]: int(a)

Out[13]: 1

#这种叫做四舍五入

In [14]: round(a)

Out[14]: 2

#向上取整-ceil

In [15]: math.ceil(a)

Out[15]: 2

#向下取整-floor

In [16]: math.floor(a)

Out[16]: 1

#使用np

In [18]: a

Out[18]: array([-5.5, -4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5])#向下取整

In [19]: np.floor(a)

Out[19]: array([-6., -5., -4., -3., -2., -1., 0., 1., 2., 3., 4.])#向上取整

In [22]: np.ceil(a)

Out[22]: array([-5., -4., -3., -2., -1., -0., 1., 2., 3., 4., 5.])#四舍五入

In [23]: np.round(a)

Out[23]: array([-6., -4., -4., -2., -2., -0., 0., 2., 2., 4., 4.])#rint和round是一样的

In [20]: np.rint(a)

Out[20]: array([-6., -4., -4., -2., -2., -0., 0., 2., 2., 4., 4.])#向0取整

In [21]: np.trunc(a)

Out[21]: array([-5., -4., -3., -2., -1., -0., 0., 1., 2., 3., 4.])

注:这里的round用的是"四舍六入五成双,奇进偶不进"的方法。对于大量的计算而言,比普通的四舍五入要更科学

modf-把小数和整数部分分开获取

In [26]: np.modf(a)

Out[26]:

(array([-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5]),

array([-5., -4., -3., -2., -1., -0., 0., 1., 2., 3., 4.]))

In [27]: x,y =_

In [28]: x

Out[28]: array([-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 0.5, 0.5])

In [29]: y

Out[29]: array([-5., -4., -3., -2., -1., -0., 0., 1., 2., 3., 4.])

isnan和isinf-浮点数特殊值的判定

In [31]: a = np.ones(5)

In [32]: a

Out[32]: array([1., 1., 1., 1., 1.])

In [33]: a[1] =0

In [34]: a

Out[34]: array([1., 0., 1., 1., 1.])

In [36]: b = a/a

F:\Python36\Scripts\ipython3:1: RuntimeWarning: invalid value encountered intrue_divide

In [37]: a

Out[37]: array([1., 0., 1., 1., 1.])

In [38]: b

Out[38]: array([ 1., nan, 1., 1., 1.])

In [39]: 1 inb

Out[39]: True#这样判断对nan是无用的

In [40]: np.nan inb

Out[40]: False#isnan的作用

In [41]: np.isnan(b)

Out[41]: array([False, True, False, False, False])

isnan用来取值

In [42]: b[np.isnan(b)]

Out[42]: array([nan])

In [43]: b[~np.isnan(b)]

Out[43]: array([1., 1., 1., 1.])

inf-比任何数都大

In [44]: np.inf > 1000000000000000000000000000000Out[44]: True

In [45]: float('inf') > 1000000000000000000000000000000000Out[45]: True

inf和isinf的使用

In [46]: a = np.array([3,4,5,6,7])

In [47]: b = np.array([3,0,5,0,7])

In [48]: a/b

F:\Python36\Scripts\ipython3:1: RuntimeWarning: divide by zero encountered intrue_divide

Out[48]: array([ 1., inf, 1., inf, 1.])#和np.nan不一样,是相等的

In [49]: np.inf ==np.inf

Out[49]: True

In [50]: c = a/b

F:\Python36\Scripts\ipython3:1: RuntimeWarning: divide by zero encountered intrue_divide

In [51]: c

Out[51]: array([ 1., inf, 1., inf, 1.])#取出不是inf的值

In [52]: c[c!=np.inf]

Out[52]: array([1., 1., 1.])#取出不是inf的值,用~

In [53]: c[~np.isinf(c)]

Out[53]: array([1., 1., 1.])

二元函数

add 加

substract 减

multiply 乘

divide 除

power 乘方

mod 取模

maximum-对两个数组的每一个都取一个最大值

In [58]: a

Out[58]: array([3, 4, 5, 6, 7])

In [59]: b

Out[59]: array([1, 6, 8, 9, 2])

In [60]: np.maximum(a,b)

Out[60]: array([3, 6, 8, 9, 7])

mininum-和maxinum一样的用法,只是对比取最小的值

更改数组形状-reshape和resize和ravel

a = np.random.random((3,2))

a#reshape 并不改变原始数组

a.reshape(2, 3)

array([[0.91122299, 0.93234796, 0.86025081],

[0.33770259, 0.13627525, 0.78460434]])#查看 a

array([[0.91122299, 0.93234796],

[0.86025081, 0.33770259],

[0.13627525, 0.78460434]])#resize 会改变原始数组

a.resize(2, 3)#查看 a

array([[0.91122299, 0.93234796, 0.86025081],

[0.33770259, 0.13627525, 0.78460434]])

# 展平数组-数组变成一行

a.ravel()

array([0.91122299, 0.93234796, 0.86025081, 0.33770259, 0.13627525,

0.78460434])

拼合数组-vstack和hstack

a = np.random.randint(10,size=(3,3))

b= np.random.randint(10,size=(3,3))

a,b

out:

(array([[1, 4, 7],

[5, 6, 6],

[6, 4, 5]]),

array([[8, 3, 1],

[1, 5, 8],

[5, 0, 6]]))#垂直拼合

np.vstack((a,b))

out:

array([[1, 4, 7],

[5, 6, 6],

[6, 4, 5],

[8, 3, 1],

[1, 5, 8],

[5, 0, 6]])#水平拼合

np.hstack((a,b))

array([[1, 4, 7, 8, 3, 1],

[5, 6, 6, 1, 5, 8],

[6, 4, 5, 5, 0, 6]])

分割数组-vsplit和hsplit

#沿横轴分割数组

np.hsplit(a,3)

[array([[1],

[5],

[6]]),

array([[4],

[6],

[4]]),

array([[7],

[6],

[5]])]#沿纵轴分割数组

np.vsplit(a,3)

[array([[1, 4, 7]]), array([[5, 6, 6]]), array([[6, 4, 5]])]

数组排序

#生成示例数组

a = np.array(([1, 4, 3], [6, 2, 9], [4, 7, 2]))

a

array([[1, 4, 3],

[6, 2, 9],

[4, 7, 2]])#返回每列最大值

np.max(a, axis=0)

array([6, 7, 9])#返回每行最小值

np.min(a,axis=1)

array([1, 2, 2])#返回每列最大值索引

np.argmax(a,axis=0)

array([1, 2, 1])#返回每行最小值索引

np.argmin(a,axis=1)

array([0,1, 2])

numpy-统计方法和随机数生成

#统计中位数

np.median(a, axis=0)#统计各行的算术平均值

np.mean(a, axis=1)#统计各列的加权平均值

np.average(a, axis=0)#统计各行的方差

np.var(a, axis=1)#统计数组各列的标准偏差

np.std(a, axis=0)

数学时间

1 2 3 4 5平均数:3方差 :每个数-3的值的平方,加在一起,再除以数字的个数

标准差:对方差开平方根

方差用来计算数组内数值的范围

平均数加减两倍方差的结果活落在90%的范围上

矩阵乘法

矩阵乘法运算(注意与a*b的区别)

A = np.array([[1,2],[3,4]])

B = np.array([[5,6],[7,8]])

np.dot(A,B)

array([[19, 22],

[43, 50]])

数学函数

#求三角函数

a = np.array([10,20,30,40,50])

np.sin(a)

array([-0.54402111, 0.91294525, -0.98803162, 0.74511316, -0.26237485])#以自然对数为底数的指数函数

np.exp(a)

array([2.20264658e+04, 4.85165195e+08, 1.06864746e+13, 2.35385267e+17,5.18470553e+21])#方根的运算-开平方

np.sqrt(a)

array([3.16227766, 4.47213595, 5.47722558, 6.32455532, 7.07106781])#方根的运算-求立方

np.power(a,3)

array([1000, 8000, 27000, 64000, 125000])

随机数

#创建二维随机数组

np.random.rand(2, 3)

array([[0.46181641, 0.06400509, 0.93763711],

[0.67133387, 0.0801051 , 0.81633397]])#创建二维随机整数数组

np.random.randint(5, size=(2, 3))

array([[4, 2, 2],

[4, 0, 0]])

In [61]: np.random.randint(0,10,10)

Out[61]: array([6, 4, 8, 4, 0, 4, 9, 1, 5, 7])#生成多维随机数组

In [62]: np.random.randint(0,10,(3,5)) 或者如上一个例子所示 使用size参数

Out[62]:

array([[4, 5, 7, 7, 8],

[4, 1, 5, 1, 4],

[2, 3, 9, 6, 8]])#0-1之间的随机数

In [63]: np.random.rand(10)

Out[63]:

array([0.97926997, 0.17454168, 0.52831388, 0.28070782, 0.2715298,0.2749287 , 0.44007621, 0.56472258, 0.53291951, 0.30727733])#指定数组中的随机数

In [64]: np.random.choice([1,2,3,4,5,6],10)

Out[64]: array([1, 2, 5, 5, 2, 1, 5, 1, 3, 1])

In [65]: np.random.choice([1,2,3,4,5,6],(2,3))

Out[65]:

array([[5, 2, 3],

[3, 4, 4]])#uniform 平均分布,出现每一个小数的概率都一样

In [67]: np.random.uniform(2.0,4.0,10)

Out[67]:

array([3.30135597, 2.5034658 , 3.80415042, 3.58323964, 2.82819204,3.45701693, 2.51628589, 3.94588971, 2.46530701, 3.269412])

In [68]: np.random.uniform(2,4,10)

Out[68]:

array([3.99532675, 2.27704994, 2.44378248, 2.33492658, 3.79537452,2.6754694 , 3.04022564, 2.12863367, 3.27047096, 3.70261513])

In [69]: #random中所有的方法都被numpy重写过

fromfunction-依据自定义函数创建数组

>>> deff(x,y):

...return 10*x+y

...>>> b = fromfunction(f,(5,4),dtype=int)>>>b

array([[ 0,1, 2, 3],

[10, 11, 12, 13],

[20, 21, 22, 23],

[30, 31, 32, 33],

[40, 41, 42, 43]])#

np.fromfunction(lambda i,j:i+j,(3,3))

array([[0.,1., 2.],

[1., 2., 3.],

[2., 3., 4.]])#生成的规则就是数组中每一个元素所在位置的索引值作为x和y的值

还有很多高级功能没有说,numpy相对于pandas来说是比较基础的包

接下来请领教pandas

第三章-数据分析核心包---pandas

series-一维数据对象

In [72]: importpandas as pd

In [73]: pd.Series([2,3,4,5])

Out[73]:

02

1 3

2 4

3 5dtype: int64

In [74]: pd.Series([2,3,4,5],index=['a','b','c','d'])

Out[74]:

a2b3c4d5dtype: int64

In [75]: #所以说serries更像是列表和字典的结合体

In [76]: pd.Series(np.arange(5))

Out[76]:

0 01 1

2 2

3 3

4 4dtype: int32

In [77]: #在制定了索引之后,用原来的下标还是能访问

In [82]: sr = pd.Series([2,3,4,5],index=['a','b','c','d'])

In [83]: sr

Out[83]:

a2b3c4d5dtype: int64

In [84]: sr[2]

Out[84]: 4

#所以他有两种索引方式,一种是下标,一种是标签,像字典的key

Series-使用特性

#字典创建Series

In [85]: sr = pd.Series({'a':1,'b':2})

In [86]: sr

Out[86]:

a1b2

#键索引

dtype: int64

In [88]: sr['a']

Out[88]: 1

#in的用法

In [89]: 'a' insr

Out[89]: True#通过字典创建,也能使用下标索引

In [87]: sr[1]

Out[87]: 2

#和字典有一点不一样,写for循环的时候,for字典循环的是key,而Series遍历的是值

In [90]: for i insr:

...:print(i)

...:1

2

#获取索引

In [91]: sr.index

Out[91]: Index(['a', 'b'], dtype='object')

In [93]: sr.index[0]

Out[93]: 'a'

#获取值

In [94]: sr.values

Out[94]: array([1, 2], dtype=int64)

In [95]: sr.values[0]

Out[95]: 1

#花式索引

In [101]: sr = pd.Series(a,index=['a','b','c','d','e'])

In [102]: sr

Out[102]:

a3b4c5d6e7dtype: int32

In [103]: sr[['a','e','c']]

Out[103]:

a3e7c5dtype: int32#标签索引来切片,它是前包后也包的

In [106]: sr['b':'d']

Out[106]:

b4c5d6dtype: int32

Series-整数索引问题

In [107]: sr = pd.Series(np.arange(10))

In [108]: sr

Out[108]:

0 01 1

2 2

3 3

4 4

5 5

6 6

7 7

8 8

9 9dtype: int32

In [111]: sr2 = sr[5:].copy()

In [112]: sr2

Out[112]:5 5

6 6

7 7

8 8

9 9dtype: int32#问题开始了,sr2的下标索引并不是从0开始的

In [113]: sr2[5]

Out[113]: 5

#因为这个时候是有歧义的,所以,如果索引是整数类型,则根据整数进行下标取值的时候,总是面相标签的

解决办法:loc和iloc

In [114]: sr2.loc[5]

Out[114]: 5In [115]: sr2.iloc[-1]

Out[115]: 9

#因为长度只有5,所以使用sr.iloc[5]会报错

Series-数据对齐

按照标签索引进行计算

In [117]: sr1 = pd.Series([12,23,34],index=['c','a','d'])

In [118]: sr2 = pd.Series([11,20,10],index=['d','c','a'])

In [119]: sr1+sr2

Out[119]:

a33c32d45dtype: int64

pandas中长度不一样也可以计算,并引入NaN数据作为数据缺失值

In [120]: sr1 = pd.Series([12,23,34],index=['c','a','d'])

In [121]: sr2 = pd.Series([11,20,10,16],index=['d','c','a','b'])

In [122]: sr1+sr2

Out[122]:

a33.0b NaN

c32.0d45.0dtype: float64

In [123]: sr1 = pd.Series([12,23,34],index=['c','a','d'])

In [124]: sr2 = pd.Series([11,20,10],index=['c','a','b'])

In [125]: sr1+sr2

Out[125]:

a43.0b NaN

c23.0d NaN

dtype: float64

但是有的时候,我不需要他出现NaN

In [126]: sr1.add(sr2,fill_value=0)

Out[126]:

a43.0b10.0c23.0d34.0dtype: float64

Series-缺失数据和处理确实数据

处理缺失数据有两种思路-删除和填充

判断有没有缺失数据-isnull和notnull

In [127]: sr.isnull()

Out[127]:

0 False1False2Falsedtype: bool

删掉缺失数据的方法

#恶意直接利用索引取值的方法

In [132]: sr[sr.notnull()]

Out[132]:

a43.0c23.0dtype: float64#使用dropna 删除

In [134]: sr.dropna()

Out[134]:

a43.0c23.0dtype: float64

填充的方法

#使用fillna填充

In [133]: sr.fillna(0)

Out[133]:

a43.0b0.0c23.0d0.0dtype: float64

有的时候,不喜欢看见0 ,我们可以填充一个平均值

In [135]: sr.fillna(sr.mean())

Out[135]:

a43.0b33.0c23.0d33.0dtype: float64

pandas在计算平均值的时候,会跳过nan。如果不想跳过去,可以加一些参数

Series小结

Series的特性-数组+字典的结合体-整数索引的问题-loc和iloc

数据对齐-面向标签和缺失值

缺失值的处理-删除和填充

pandas的mean求平均值的特点的使用

DataFrame-二维数据对象

#第一种创建范式

In [137]: df=pd.DataFrame({'one':[1,2,3,],'two':[4,5,6]})

In [138]: df

Out[138]:

one two

01 4

1 2 5

2 3 6

#第二种创建方式

In [140]: pd.DataFrame({'one':pd.Series([1,2,3],index=['a','b','c']),'two':pd.Series([4,5,6,7],index=['a','b','c','d'])})

Out[140]:

one two

a1.0 4b2.0 5c3.0 6d NaN7

#还有很多种创建的方式...

文件读写操作

vim test.csv

a,b,c1,2,3

4,5,6

7,8,9

读取csv文件

In [145]: pd.read_csv('test.csv')

Out[145]:

a b c

01 2 3

1 4 5 6

2 7 8 9

保存文件为csv

In [147]: df

Out[147]:

a b c

01 2 3

1 4 5 6

2 7 8 9In [148]: df.to_csv('test2.csv')

DataFrame-常用属性

index用来获取行索引,values获取的值是二维数组, 这是和Series一样的地方

In [156]: df =_140

In [157]: df

Out[157]:

one two

a1.0 4b2.0 5c3.0 6d NaN7In [158]: df.index

Out[158]: Index(['a', 'b', 'c', 'd'], dtype='object')

In [159]: df.values

Out[159]:

array([[1., 4.],

[2., 5.],

[3., 6.],

[nan,7.]])

转置T-把行变成列,列变成行,且一列都成了一个属性(所有的转置默认都会)

可以指定属性dtype

In [160]: df.T

Out[160]:

a b c d

one1.0 2.0 3.0NaN

two4.0 5.0 6.0 7.0

获取列索引columns

In [163]: df.columns

Out[163]: Index(['one', 'two'], dtype='object')

快速统计

In [165]: df.describe()

Out[165]:

one two

count3.0 4.000000  个数mean2.0 5.500000  平均数    std1.0 1.290994  标准差min1.0 4.000000  最小值

25% 1.5 4.750000  25%位置的数

50% 2.0 5.500000  中位数

75% 2.5 6.250000  75%位置的数max3.0 7.000000  最大数

DataFrame-索引和切片

#先选列。再选行

In [168]: df

Out[168]:

one two

a1.0 4b2.0 5c3.0 6d NaN7In [169]: df['one']['a']

Out[169]: 1.0In [170]: df['one'][1]

Out[170]: 2.0In [171]: df['one'][0]

Out[171]: 1.0

建议使用loc或者iloc指定,并不建议使用双中括号

In [172]: df.loc['a','one']

Out[172]: 1.0In [173]: df.loc['a',:]

Out[173]:

one1.0two4.0Name: a, dtype: float64

灵活搭配使用

In [174]: df.loc[['a','c'],:]

Out[174]:

one two

a1.0 4c3.0 6

DataFrame-数据对齐与缺失数据

DataFrame在使用dropna时,如果一行有一个缺失值,会将整行都删除

指定how=‘all’,删除全部是nan的行

In [177]: df.loc[['c','d'],'two'] =np.nan

In [178]: df

Out[178]:

one two

a1.0 4.0b2.0 5.0c3.0NaN

d NaN NaN

In [179]: df.dropna(how='all')

Out[179]:

one two

a1.0 4.0b2.0 5.0c3.0NaN#how 默认的值是any,也就是只要有nan就都会删除

如何把有一列中有缺失值的那一列都删除?

axis参数意思是-轴,默认是0,是0的时候,指定的是行,1指定的是列

In [184]: df

Out[184]:

one two

a1.0 4.0b2.0 5.0c3.0NaN

d5.0NaN

In [185]: df.dropna(axis=1)

Out[185]:

one

a1.0b2.0c3.0d5.0

pandas-其他常用方法

排序中的ascending=False是倒序,by是指定排序的行(列)

当排序的列(行)有nan的时候,都默认放在了最后,不参与排序

numpy的所有通用函数都适于用pandas

pandas-时间对象处理

datetime中将时间字符串转化成时间对象

In [186]: importdatetime

In [187]: datetime.datetime.strptime('2010-01-01','%Y-%m-%d')

Out[187]: datetime.datetime(2010, 1, 1, 0, 0)

记忆strptime p--parse 解析

记忆strftime f--format 格式化

但是不是所有人写时间的格式都像这样的,有一个库可以帮我们做这件事

importdateutil

In [191]: dateutil.parser.parse('02/03/2010')

Out[191]: datetime.datetime(2010, 2, 3, 0, 0)

In [192]: dateutil.parser.parse('02-03-2010')

Out[192]: datetime.datetime(2010, 2, 3, 0, 0)

In [193]: dateutil.parser.parse('2010-JAN-10')

Out[193]: datetime.datetime(2010, 1, 10, 0, 0)

pandas中的to_datetime就是引用了这个模块,进行批量转换

In [194]: pd.to_datetime(['02-03-2010','2010-JAN-10'])

Out[194]: DatetimeIndex(['2010-02-03', '2010-01-10'], dtype='datetime64[ns]', freq=None)

注意:得到对象第DatetimeIndex

时间对象生成-date_range

In [195]: pd.date_range('2010-01-01','2010-05-01')

Out[195]:

DatetimeIndex(['2010-01-01', '2010-01-02', '2010-01-03', '2010-01-04','2010-01-05', '2010-01-06', '2010-01-07', '2010-01-08','2010-01-09', '2010-01-10',

...'2010-04-22', '2010-04-23', '2010-04-24', '2010-04-25','2010-04-26', '2010-04-27', '2010-04-28', '2010-04-29','2010-04-30', '2010-05-01'],

dtype='datetime64[ns]', length=121, freq='D')

使用periods指定长度

pd.date_range? 查看帮助中的参数帮助信息

start : str or datetime-like, optional

Left boundforgenerating dates.

end : stror datetime-like, optional

Right boundforgenerating dates.

periods : integer, optional 长度

Number of periods to generate.

freq : stror DateOffset, default 'D' 频率 H-小时 W-周 W-MON W-WENFrequency strings can have multiples, e.g.'5H'. See //B-工作日

:ref:`here` fora list of //1H20min

frequency aliases.

date_range的参数freq可以各种花式定义时间间隔

tz : strortzinfo, optional

Time zone namefor returning localized DatetimeIndex, forexample'Asia/Hong_Kong'. By default, the resulting DatetimeIndex istimezone-naive.

normalize : bool, default False

Normalize start/end dates to midnight before generating date range.

name : str, default None

Name of the resulting DatetimeIndex.

closed : {None,'left', 'right'}, optional

Make the interval closed with respect to the given frequency to

the'left', 'right', or both sides (None, the default).

得到的是Timestamp对象,可以将其用to_pydatetime转换成时间对象

还可以转成字符串

date_range的参数freq可以各种花式定义时间间隔

时间序列

生成的时间对象可以用来构建时间序列的

In [198]: sr = pd.Series(np.arange(5),index=pd.date_range('2010-01-01',periods=5))

In [199]: sr

Out[199]:2010-01-0102010-01-02 1

2010-01-03 2

2010-01-04 3

2010-01-05 4Freq: D, dtype: int32

那么有什么作用呢?直观的好处就是以时间为索引获取指定范围的数据

In [200]: sr = pd.Series(np.arange(100),index=pd.date_range('2010-01-01',periods=100))

In [201]: sr['2010-03']

Out[201]:2010-03-01 59

2010-03-02 60

2010-03-03 61

2010-03-04 62

2010-03-05 63

2010-03-06 64

2010-03-07 65

2010-03-08 66

2010-03-09 67

2010-03-10 68

2010-03-11 69

2010-03-12 70

2010-03-13 71

2010-03-14 72

2010-03-15 73

2010-03-16 74

2010-03-17 75

2010-03-18 76

2010-03-19 77

2010-03-20 78

2010-03-21 79

2010-03-22 80

2010-03-23 81

2010-03-24 82

2010-03-25 83

2010-03-26 84

2010-03-27 85

2010-03-28 86

2010-03-29 87

2010-03-30 88

2010-03-31 89Freq: D, dtype: int32

还比如  sr['2017':'2018']

特别方便

resample函数--重新取样

#以周为单位取和

In [203]: sr.resample('W').sum()

Out[203]:2010-01-03 3

2010-01-10 42

2010-01-17 91

2010-01-24 140

2010-01-31 189

2010-02-07 238

2010-02-14 287

2010-02-21 336

2010-02-28 385

2010-03-07 434

2010-03-14 483

2010-03-21 532

2010-03-28 581

2010-04-04 630

2010-04-11 579Freq: W-SUN, dtype: int32

truncate是类似切片的函数,意义不大,因为都可以通过切片操作来取值

pandas-文件处理

读取文件

例子:

header= none

names的使用

在一个数据表中,如果某一列中有None,这整个列的类型都会变成object,变成了字符串

本来应该是float的

但是因为有none,变成了字符串

nan可以解释成浮点数,但是none无法解释,

解决:用na_values

写入文件

写入文件示例:

Python中读取excel的时候需要安装模块xlrd

......还有很多内容

要多多练习,才能掌握,变成自己的

第四章-数据可视化工具包---matplotlib

如果在命令行或者pycharm中运行,会弹出对话框,可以进行拖动、放大等操作...

plot函数

plot用来绘制点图或者线图,两个参数(即x和y)

还有第三个参数,一个字符串,来决定线的样式(示例:v是小三角,用短线和点连接,显示红色)

也可以使用参数传递(color=‘red’,marker=‘^’,linestyle='-.')

我想画多条线?该如何操作

show函数,调用之后,之前的plot都出现在一张图上了

Matplotlib-图像标注

plt.legend的用法之一

pandas和Matplotlib

直接使用

作业:绘制数学函数图像

画布与子图

fig.add_subplot(2,2,1) 其中 2,2的意思就是把画布分成2x24份,最后的1是第一个位置

Matplotlib支持的图类型

条形图

饼图

折线图-matplot.finance

matplotlib.finance.子包中有许多绘制金融相关图的函数接口

绘制K线图:matplotlib.finance.candlestick_ochl函数

参数的帮助信息

导入模块并给数据添加了一个time字段

第五章-金融数据分析基础实战

tushare包介绍

Tushare是一个免费、开源的财经数据接口包。

练习1-股票数据分析

1、使用tushare包获取某股票的历史行情数据2、输出该股票所有收盘比开盘上涨3%以上的日期3、输出该股票所有开盘比前日收盘跌幅超过2%的日期(用shift错位)4、加入我从2010年1月1日开始,每月第一个交易日买入一手股票,每年最后一个交易日卖出所有股票,

到今天为止,我的收益如何?

tushare接口的使用和shift函数,resample的使用

练习2-查找历史金叉死叉的日期

编写代码

第一个量化策略

initialize函数

handle_data函数,每个单位时间执行一次回测

策略实现

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):#1、设置股票池为沪深300的所有成分股

g.security = get_index_stocks('000300.XSHG')

# 基准收益

set_benchmark('000300.XSHG') # 持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')## 回测函数

defhandle_data(context, data):#每只股票买多少的问题,账户金额/股票个数的长度=每个股票分多少钱

#一般情况下先卖后买

tobuy =[]for stock ing.security:#获取股票当前的开盘价

p =get_current_data()[stock].day_open#查看是否持有这只股票

amount =context.portfolio.positions[stock].total_amount#股票的持仓成本

cost =context.portfolio.positions[stock].avg_cost#3、如果当前股价比买入时上涨了25%,则清仓止盈

if amount > 0 and p >= cost * 1.25:

order_target(stock,0)#止盈

#4、如果当前股价比买入时下跌了10%,则卖出止损

if amount > 0 and p <= cost *0.9:

order_target(stock,0)#止损

#2、如果当前股价小于10元且当前不持仓,则买入

if p <= 10.0 and amount ==0:

tobuy.append(stock)

order(stock,1000)iftobuy:

cost_per_stock= context.portfolio.available_cash /len(tobuy)for per intobuy:

order_value(per,cost_per_stock)

双均线策略-最简单只股票

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股

g.security = ['601318.XSHG']

g.p1= 5g.p2= 10

defhandle_data(context, data):for stock ing.security:#金叉:如果5日均线大于10日均线,且没有持仓

#死叉:如果5日均线小于10日均线,并且持仓

#获取历史数据

df =attribute_history(stock,g.p2)

m10= df['close'].mean()

m5= df['close'][-5:].mean()if m10 > m5 and stock incontext.portfolio.positions:#死叉卖出

order_target(stock, 0)if m10 < m5 and stock not incontext.portfolio.positions:

order(stock,context.portfolio.available_cash* 0.8)

在回测图上添加其他的图

因子选股策略

查询财务数据

get_fundanmentals

策略编写

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股范围

g.security = get_index_stocks('000300.XSHG')#获取数据,在官网数据选项卡中找到valuation表

g.q =query(valuation).filter(valuation.code.in_(g.security))#要定期跟新调仓

#1、定义天数变量,在handle_data中计数,每天+1,当days%30==0的时候,执行调仓

#这是没30个交易日调一次

#2、使用run_monthly(handle,1),定义handle用来跟新的函数,1表示第一个交易日

#这是每月调一次

run_monthly(handle,1)#定义自己的仓位最多有20只股票

g.N = 20

defhandle(context):#注意,有的函数方法会报错,因为平台支持的第三方平台的版本所导致

df = get_fundamentals(g.q)[['code','market_cap']]

df= df.sort_values('market_cap').iloc[:g.N,:]#新选出的股票池

to_hold = df['code'].values#手上可能有一些股票,有的留着,没有的卖掉,添加新的

for stock incontext.portfolio.positions:#手上的股票没在to_hold中,买掉

if stock not into_hold:

order_target(stock,0)

to_buy= [stock for stock in to_hold if stock not incontext.portfolio.positions]ifto_buy:

cash_per_stock= context.portfolio.available_cash /len(to_buy)for per into_buy:

order_value(per,cash_per_stock)

注意停牌的股票的过滤

取前30个,把停牌的(paused)过滤掉,在取前20个

多因子选股策略

市值小

净资产收益率要高

如何同时综合多个因子

...

补充知识-标准化

标准化,归一化,数据预处理的方法

编码实现

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股范围

g.security = get_index_stocks('000002.XSHG')#获取数据,在官网数据选项卡中找到valuation表,市值数据在这个表中

#找到roe在,indicator表中

g.q =query(valuation,indicator).filter(valuation.code.in_(g.security))#要定期跟新调仓

#1、定义天数变量,在handle_data中计数,每天+1,当days%30==0的时候,执行调仓

#这是没30个交易日调一次

#2、使用run_monthly(handle,1),定义handle用来跟新的函数,1表示第一个交易日

#这是每月调一次

#定义自己的仓位最多有20只股票

g.N = 20run_monthly(handle,1)defhandle(context):#注意,有的函数方法会报错,因为平台支持的第三方平台的版本所导致

df = get_fundamentals(g.q)[['code','market_cap','roe']]#进行归一化

df['market_cap'] = (df['market_cap']) - df['market_cap'].min()) / (df['market_cap'].max() - df['market_cap'].min())

df['roe'] = (df['roe']) - df['roe'].min()) / (df['roe'].max() - df['roe'].min())#增加一列作为评分,收益率越大越好,市值越小越好。最后的结果越大越好

df['score'] = df['roe'] - df['market_cap']#选最后20只

df = df.sort_values('score').iloc[-g.N:,:]#新选出的股票池

to_hold = df['code'].values#手上可能有一些股票,有的留着,没有的卖掉,添加新的

for stock incontext.portfolio.positions:#手上的股票没在to_hold中,买掉

if stock not into_hold:

order_target(stock,0)

to_buy= [stock for stock in to_hold if stock not incontext.portfolio.positions]ifto_buy:

cash_per_stock= context.portfolio.available_cash /len(to_buy)for per into_buy:

order_value(per,cash_per_stock)

还可以增加权重、增加更多的因子

均值回归理论

均值回归策略是一个选股策略

编码实现

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股范围

g.security = get_index_stocks('000002.XSHG')#均线

g.ma_days = 30

#股票数量

g.stock_num = 10run_monthly(handle,1)defhandle(context):

sr= pandas.Series(index=g.security)for stock insr.index:

ma= attribute_history(stock, g.ma_days)['close'].mean()

p=get_current_data()[stock].day_open#计算偏离程度

ratio = (ma-p) /ma

sr[stock]=ratio#不用sort,有一个更快的函数nlargest

#新选出的股票池

to_hold =sr.nlargest(g.stock_num).index.values#手上可能有一些股票,有的留着,没有的卖掉,添加新的

for stock incontext.portfolio.positions:#手上的股票没在to_hold中,买掉

if stock not into_hold:

order_target(stock,0)

to_buy= [stock for stock in to_hold if stock not incontext.portfolio.positions]ifto_buy:

cash_per_stock= context.portfolio.available_cash /len(to_buy)for per into_buy:

order_value(per,cash_per_stock)

布林带策略

上下N取小了不好,去大了等于没取,因为很难触碰,上下可以取不同的N

编码实现

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股范围

g.security = ('600036.XSHG')

g.M= 20 #试验过20比较好

g.k = 2 #听说1.7比较好#初始化策略

defhandle_data(context, data):

sr= attribute_history(g.security,g.M)['close']

ma=sr.mean()

up= ma + g.k *sr.std()

down= ma - g.k *sr.std()

p=get_current_data()[g.security].day_open

cash=context.portfolio.available_cashif p < down and g.security not incontext.portfolio.positions:

order_value(g.security, cash)elif p >up and g.security incontext.portfolio.positions:

order_target(g.security, 0)

可以继续尝试其他股票或者多只股票

多只股票牵涉资金分配的问题

多尝试几个参数,看效果如何

布林带比较窄的时候,说明波动小,将不适合短线交易,也可将其作为一个因子

加入止损操作

PEG策略

市盈率是什么

PEG策略说明

PEG选股

编码实现

市盈率有静态的和动态的两种,我们使用静态的pe_ratio,在valuation表中

收益增长率inc_net_profit_year_on_year,在indicator里面

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股范围

g.security = get_index_stocks('000300.XSHG')

g.q=query(valuation.code,valuation.pe_ratio,indicator.inc_net_profit_year_on_year).filter(valuation.code.in_(g.security))

g.N= 20run_monthly(handle,1)defhandle(context):

df=get_fundamentals(g.q)#过滤负值的PEG

df = df[(df['pe_ratio'] > 0) & (df['inc_net_profit_year_on_year'] >0) ]#计算peg

df['peg'] = df['pe_ratio'] /df['inc_net_profit_year_on_year']/100df= df.sort_values('peg')

to_hold= df['code'][:g.N].valuesprint(to_hold)#手上可能有一些股票,有的留着,没有的卖掉,添加新的

for stock incontext.portfolio.positions:#手上的股票没在to_hold中,买掉

if stock not into_hold:

order_target(stock,0)

to_buy= [stock for stock in to_hold if stock not incontext.portfolio.positions]ifto_buy:

cash_per_stock= context.portfolio.available_cash /len(to_buy)for per into_buy:

order_value(per,cash_per_stock)

动量策略和反转策略

编码实现

importjqdataimportmathimportnumpy as npimportpandas as pdimportdatetimedefinitialize(context):

set_option('use_real_price', True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')

g.benchmark= '000300.XSHG'g.N= 10set_benchmark(g.benchmark)

run_monthly(handle,1)defhandle(context):

stocks= get_index_stocks('000300.XSHG')#这段时间的收盘价(attribu是选取一只股票多个时间的,history是选择多只股票)

#转置,相当于将股票代码放在了表头上

df_close = history(30, field='close', security_list=list(stocks)).T#增加ret列,表示收益率(最后一天的价格-第一天的价格)/ 第一天的价格

df_close['ret'] = (df_close.iloc[:,-1]-df_close.iloc[:,0])/df_close.iloc[:,0]#ascending = False 表示降序,即为动量策略,总选最好的

#ascending = True 反转策略

sorted_stocks = df_close.sort_values('ret', ascending =False).index

to_hold=sorted_stocks[:g.N]#手上可能有一些股票,有的留着,没有的卖掉,添加新的

for stock incontext.portfolio.positions:#手上的股票没在to_hold中,买掉

if stock not into_hold:

order_target(stock,0)

to_buy= [stock for stock in to_hold if stock not incontext.portfolio.positions]ifto_buy:

cash_per_stock= context.portfolio.available_cash /len(to_buy)for per into_buy:

order_value(per,cash_per_stock)

最后得出结论,A股市场的反转策略优于动量策略

羊驼交易法则

编码实现

#导入函数库

from jqdata import *

#初始化函数,设定基准等等

definitialize(context):

set_benchmark('000300.XSHG') #持有后不动

set_option('use_real_price',True)

set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003,

close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock')#选股范围

g.security = get_index_stocks('000300.XSHG')#看多长时间的 收益率

g.period = 30g.N= 10

#每次调整几只股票

g.change = 1

#标志位,第一次购买的时候购买的是10只

g.init =True

run_monthly(handle,1)defget_sorted_stocks(context,stocks):

df_close= history(g.period, field='close', security_list=stocks).T#增加ret列,表示收益率(最后一天的价格-第一天的价格)/ 第一天的价格

df_close['ret'] = (df_close.iloc[:,-1]-df_close.iloc[:,0])/df_close.iloc[:,0]#ascending = False 表示降序,即为动量策略,总选最好的

#ascending = True 反转策略

sorted_stocks = df_close.sort_values('ret', ascending =False)returnsorted_stocks.index.valuesdefhandle(context):ifg.init:

stocks=get_sorted_stocks(context, g.security)[:g.N]

cash= context.portfolio.available_cash * 0.9 /len(stocks)for stock instocks:

order_value(stock, cash)

g.init=Falsereturnstocks=get_sorted_stocks(context, context.portfolio.positions.keys())for stock instocks:if len(context.portfolio.positions) >=g.N:break

if stock not incontext.portfolio.positions:

order_value(stock, context.portfolio.available_cash* 0.9)

简易回测框架开发

框架内容

上下文信息保存:context

获取数据:

下单函数:

用户接口:

...

量化交易python 文件_python数据分析与量化交易相关推荐

  1. python量化分析数据_Python数据分析_量化分析.pdf

    法律声明  本课件包括:演示文稿,示例,代码,题库,视频和声 音等,小象学院拥有完全知识产权的权利:只限于善意 学习者在本课程使用,不得在课程范围外向任何第三方 散播.任何其他人或机构不得盗版.复制 ...

  2. 量化交易系统 python btc_GitHub - crabboy/abu: 阿布量化交易系统(股票,期权,期货,比特币,机器学习) 基于python的开源量化交易,量化投资架构...

    abu能够帮助用户自动完善策略,主动分析策略产生的交易行为,智能拦截策略生成的容易失败的交易单. 现阶段的量化策略还是人工编写的代码,abu量化交易系统的设计将会向着由计算机自动实现整套流程的方向迈进 ...

  3. python处理期货数据分析_量化交易分析第一步利用Tushare轻松获取股票期货行情数据...

    Tushare简介 Tushare是一个免费开源的python财经数据接口包,主要能够实现对股票.期货等金融数据从数据采集.清洗加工到数据存储的过程,能够为金融分析人员提供快速.整洁和多样的便于分析的 ...

  4. python定价_Python|机器学习与量化交易、定价高级训练营陆家嘴学

    Python|机器学习与量化交易.定价高级训练营陆家嘴学堂百度云下载 我买了这个课程,在此分享! 获取课程,请加幑信: 1403905263 (复制幑信号到幑信添加!) 或者扫下面码 <韩非子& ...

  5. 量化交易python入门书籍推荐_求量化投资入门书籍或课程推介。?

    入门,还是要看一个人的知识背景. 1.有一本:西蒙斯打开量化投资的黑箱,还有西蒙斯的文艺复兴公司的介绍(喜马拉雅),另外B站有西门斯的演讲. 通过对西蒙斯的了解,你要对自己的知识结构.背景.资源和量化 ...

  6. 简述python在量化金融中应用_Python金融与量化投资分析应用

    {getUnitName} {getLessonName} 敬请期待 免费 {getTaskName} 剩余观看时长:{watchLimitRemaining} 回放 {activityStartTi ...

  7. python 京东_Python数据分析-京东订单数据分析实战

    本次数据来源于京东,类目为大家电-家用电器-冰箱,抽取2020年5月25日10%数据,数据量为 70k+,在 jupyer notebook 内进行分析. 数据文件: 链接:迅雷云盘:提取码:ezQq ...

  8. python花数_Python数据分析实战,尾鸢花数据集数据分析

    本节所使用的尾鸢花数据集是Python中自带的数据集,常用于机器学习分类算法模型,其中sepal_length_cm.sepal_width_cm.petal_length_cm.petal_widt ...

  9. python学生分布_Python数据分析实战之分布分析

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:严小样儿 分布分析法,一般是根据分析目的,将数据进行分组,研究各组别 ...

最新文章

  1. 安装 python 虚拟环境
  2. Python中Numpy库中的Numpy常量
  3. Linux系统安装及配置——Centos-7-X86_64-DVD-2009
  4. 做女程序员是一种什么样的体验?
  5. 值得收藏的信息安全知名博客
  6. 小学计算机教室管理制度范本,《中小学微机室规章制度》.doc
  7. python中的return函数-python中return的返回和执行
  8. 黄聪:一个拼图工具的制作思路
  9. html5视频播放器 二 (功能实现及播放优化)
  10. 软件测试技术路线怎么走
  11. 预言机私享,Defi实战特训,一场对开放式金融认知新突围来了!
  12. 也来说说电影《少年班》中周知庸问王大法的问题
  13. 内外盘期货市场的介绍(一)
  14. 示波器学习(一):示波器的作用、类型和基本结构
  15. Photoshop钢笔工具抠图和图层填充
  16. 建木(Jianmu)----迈出建木第一步创建项目分组
  17. Markdown小菜狗子笔记
  18. QR分解、RQ分解与SVD
  19. 2W字!详解20道Redis经典面试题!(珍藏版)
  20. 堆排序的基本概念和基本思路

热门文章

  1. 如何用java代码给Word文档添加水印?
  2. [读书笔记]-《高能要事》-一次做好一件事
  3. Java语言概述以及环境搭建
  4. 算法竞赛---day1(等差素数列)
  5. 数据挖掘实战—家用热水器用户行为分析与事件识别
  6. 解决树莓派4B 3.5MM耳机接口没有声音的方法
  7. 算法分析与设计实验报告 ——二分搜索程序算法的实现
  8. 利用3D效果制作立体导航栏
  9. C++每日一练:打家劫室(详解动态规划法)
  10. 全球变化生态学尔雅课答案