python 金融量化分析

金融概念

均线:

短期均线下穿长期均线 下跌 -- 死叉

短期均线上穿长期均线 上涨 -- 金叉

但是有滞后性

金融分析

基本面分析

  • 公司分析 财务数据 业绩报告
  • 行业分析

技术面分析

各项技术指标

  • K线
  • 平均线
  • KDJ

金融量化投资

  • 避免主观情绪
  • 及时跟踪市场变化
  • 多角度的观察 和 多层次的模型
  • 在决定投资策略后,能通过回测验证效果

量化策略

核心内容

  • 选股
  • 择时
  • 仓位管理
  • 止盈止亏

量化投资与Python

第三方模块

  • numpy 数值计算
  • pandas 数据分析
  • matplot 图标绘制

Python进行写

  • 自己写框架
  • 在线平台 聚宽 米筐 优矿 Quantopian
  • 开源框架RQalpha

IPython

  • tab 自动补全
  • ? 搜索
    a.? 查询a的所有的方法
    a.__
    __? a的所有的私有的方法
  • a.a*? 过滤历史中a开头的
  • %run 执行脚本
  • %paste 运行粘贴板的内容
  • ! 执行系统命令
    !ipconfig

魔术命令:

  • %timeit func() 测试代码的执行时间 适合运行时间小的代码
    这个会执行很多次取平均值
In [37]: %timeit func(a,b)
The slowest run took 14.25 times longer than the fastest. This could mean that a
n intermediate result is being cached.
10000000 loops, best of 3: 166 ns per loop
  • %time func() 适合运行时间长的代码
  • %pdb on 调试
    p 打印 q 退出
  • %pdb off 关闭调试
  • 历史命令
    以xx开头的进行过滤 xx加上箭头
    _代表上一个历史
    __代表上两个历史
    ___代表上面三个

_34 34是输入代码
_i34 输入

jupyter notebook

会生成一个token 进行远程连接 pycharm支持

与IDE进行交互 jupyter notebook

在cmd中输入jupyter notebook,会启动jupyter,可以在浏览器上进行编辑。

与pycharm进行交互,输入token

点击运行的时候输入token=fb9ae30019c4b001f7bd06e1154774d1ba4e1b02a87d557b

Numpy

Numpy高性能的科学计算和数据分析包,一个多维数组结构,高效且节省空间
ndarray 多维数组对象

array()		将列表转换为数组,可选择显式指定dtype
arange()		range的numpy版,支持浮点数
linspace()	类似arange(),第三个参数为数组长度
zeros()		根据指定形状和dtype创建全0数组
ones()		根据指定形状和dtype创建全1数组
empty()		根据指定形状和dtype创建空数组(随机值)
eye()		根据指定边长和dtype创建单位矩阵
  • 创建:ndarray
import numpy as np
np.array([1,2,3])

可以for循环遍历:

for i in _:  # _ 是上面返回的对象
    print(i)

多维数组 数据类型必须是一样的

  • sys.getsizeof() 查看占用的内存
import sys

a = list(range(100))
sys.getsizeof(a) # 1008

b = np.array(range(100))
sys.getsizeof(b)  # 496
  • np.dot() 点乘
import random

prize = [round(random.uniform(10,20),2) for i in range(20)] # round(x,y) x 是随机数 y 是位数 
num =[random.randint(1,10) for i in range(20)]
for i,j in zip(prize,num):
    sum+=i*j

不用for循环

np_prize = np.array(prize)
np_num = np.array(num)
np.dot(np_prize,np_num)
或者:
np_prize*np_num
_.sum()
  • 查看数据类型:
In [61]: np_prize.dtype # 
Out[61]: dtype('float64') # 根据系统的默认环境
  • dtype 数组的数据类型
  • size
np.array(range(10000))
array([   0,    1,    2, ..., 9997, 9998, 9999])
a= _
a.size  # 10000
  • shape 数组维度的大小
    是一个元组
a.shape
(10000,)  # 这里代表的是一维

多维数组

b = np.array([[1,2,3],[4,5,6]])
b.shape # (2,3) 2行3列的数组
  • ndim 查看维度

a.ndim -- 1
b.ndim -- 2

  • 数据类型转换astype
b = np.array([[1,2,3],[4,5,6]])
b.astype('float32')
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]], dtype=float32)
  • 在构造的时候改变数据类型
a = range(10)
c = np.array(a,dtype='float32')
  • arange

arange 是numpy中的一种类型 和range是一样的,和range的区别是设置步长可以是小数
np.arange()生成一个range

z = np.arange(1,4,0.2)

np.array(np.arange(10))  
np.array(range(10)) 
  • np.linspace(0,10,15) 线性空间 一共分成了15份 代表了数组空间的大小

  • np.zeros np.ones
    创建多维的,传入一个shape 数组

np.zeros(10,dtype='int32')  # 创建的时候指定数据类型 默认创建的带小数
In [97]: np.zeros((3,5))
Out[97]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

In [98]: np.zeros((3,5,10))  # 创建的三维数组
Out[98]:
array([[[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]],

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

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

全0:np.zeros(10) 全1:np.ones()

里面是元组
二维:
np.zeros((3,5))

三维
np.zeros((3,5,10))

  • np.empty

ones zeros在创建的时候会开辟内存,但是empty不会,如果之前的内存空间被释放了,empty有可能会被填充
np.empty(10)
开辟内存 不填充数,使用内存原来的值

  • np.eye(5) 单位矩阵
In [103]: np.eye(5)
Out[103]:
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.]])

切片和索引

可以进行乘方 加减等运算 同时不同for循环

 a
 array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
 a[0]
 0
 c= a**2
 c
 array([ 0,  1,  4,  9, 16, 25, 36, 49, 64, 81])
 b = a+1
 b
 array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])

俩个同样大的数组进行运算

a=a  a**

二维数组的切片

a = np.arange(15).reshape(3,5) # 先创建一个一维的 然后把形状转换成二维 但是必须是总数一致的
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

In [124]: a[0][0]
Out[124]: 0

In [125]: a[1][3]
Out[125]: 8

维的也可以用逗号进行切片,逗号左边代表行,右边代表列

a[1,3] -- 8

In [127]: a[:2,1:3]  # 先切行 再切列
Out[127]:
array([[1, 2],
       [6, 7]])

numpy的切片和列表的切片不同

列表的切片是通过copy复制出来的,新复制的修改不会影响原来的值,但是numpy的数组是创建的一个视图,视图修改后,原来的也会修改,这种是针对大数据设计的。可以通过copy解决

In [129]: a
Out[129]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [130]: a= b
In [131]: b
Out[131]: array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
In [132]: b[2:6]
Out[132]: array([3, 4, 5, 6])
In [133]: b[0] = 111
In [134]: a
Out[134]: array([111,   2,   3,   4,   5,   6,   7,   8,   9,  10])
In [135]: b
Out[135]: array([111,   2,   3,   4,   5,   6,   7,   8,   9,  10])

b是a的视图

b = a[:4].copy() 这样就是复制的

布尔型的索引

布尔型索引:将同样大小的布尔数组传进索引,会返回一个由所有True对应位置的元素的数组

a = [random.randint(1,20) for i in range(10)]
aa = np.array(a)
aa<5
Out[144]: array([False,  True,  True,  True, False, False, False, False, False,
False], dtype=bool)

aa[aa<5]
array([4, 1, 2, 4])  # 通过bool就能进行索引出True的值

a[b]

b是一个bool数组

小于5而且是偶数的 使用&
a[(aa<5) & (aa%2==0)]

或 |

非 ~

numpy花式索引

 aa
 array([ 4,  9,  1, 20,  2, 13,  7,  4,  9,  5])
 aa[[1,3,5]]
 array([ 9, 20, 13])
In [158]: a[:,1:4]  # 切片 先切行,再切列
Out[158]:
array([[ 1,  2,  3],
       [ 6,  7,  8],
       [11, 12, 13]])

In [159]: a[:,[1,3]]  # 花式索引
Out[159]:
array([[ 1,  3],  
       [ 6,  8],
       [11, 13]])

Numpy通用函数

  • math中的
  • rint round 四舍五入
a = np.arange(0,5,0.2)
a= np.array(a)
np.round(a)
np.rint(b)
  • ceil 向上取整
math.ceil(3.5)  # 结果是4
np.ceil()
  • floor 向下取整
math.floor(3.5) # 结果是3
np.floor()
  • trunc 向0取整
math.trunc(-3.5) # 结果是-3
math.trunc(3.5) # 结果是3
  • np.modf 把整数部分和小数部分都变成数组
In [188]: a
Out[188]:
array([ 0. ,  0.2,  0.4,  0.6,  0.8,  1. ,  1.2,  1.4,  1.6,  1.8,  2. ,
        2.2,  2.4,  2.6,  2.8,  3. ,  3.2,  3.4,  3.6,  3.8,  4. ,  4.2,
        4.4,  4.6,  4.8])

In [189]: np.modf(a)
Out[189]:
(array([ 0. ,  0.2,  0.4,  0.6,  0.8,  0. ,  0.2,  0.4,  0.6,  0.8,  0. ,
         0.2,  0.4,  0.6,  0.8,  0. ,  0.2,  0.4,  0.6,  0.8,  0. ,  0.2,
         0.4,  0.6,  0.8]),
 array([ 0.,  0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,
         2.,  2.,  3.,  3.,  3.,  3.,  3.,  4.,  4.,  4.,  4.,  4.]))

In [190]: x,y = np.modf(a)

In [191]: x
Out[191]:
array([ 0. ,  0.2,  0.4,  0.6,  0.8,  0. ,  0.2,  0.4,  0.6,  0.8,  0. ,
        0.2,  0.4,  0.6,  0.8,  0. ,  0.2,  0.4,  0.6,  0.8,  0. ,  0.2,
        0.4,  0.6,  0.8])

In [192]: y
Out[192]:
array([ 0.,  0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  2.,  2.,  2.,
        2.,  2.,  3.,  3.,  3.,  3.,  3.,  4.,  4.,  4.,  4.,  4.])
  • isinf

inf是无限大的意思,当分母是0的时候,比值是无限大的

In [194]: a = np.array([1,2,3])
In [195]: b = np.array([1,2,0])
In [196]: a/b
E:/softinstall2017/anaconda/Scripts/ipython-script.py:1: RuntimeWarning: divide
by zero encountered in true_divide
  if __name__ == '__main__':
Out[196]: array([  1.,   1.,  inf])  
In [215]: c
Out[215]: array([  1.,   1.,  inf])
In [216]: np.isinf(c)
Out[216]: array([False, False,  True], dtype=bool)
  • isnan

分母和分子都是0的时候 比值是nan not a number 也是代表缺失的数

用np.isnan()

In [198]: a = np.array([1,2,0])
In [199]: b = np.array([1,2,0])
In [200]: a/b
E:/softinstall2017/anaconda/Scripts/ipython-script.py:1: RuntimeWarning: invalid
 value encountered in true_divide
  if __name__ == '__main__':
Out[200]: array([  1.,   1.,  nan])  not a number
In [210]: c
Out[210]: array([  1.,   1.,  nan])

In [211]: np.isnan(c)
Out[211]: array([False, False,  True], dtype=bool)

把所有不是nan的取出来
a[~np.isnan(a)]

  • np.maximum(a,b)

maximum mininum 是比较两个数组中的每一个位置的大小,然后把最大或者最小的值并返回一个数组

a = np.array([1,2,0])
b = np.array([3,1,6])
np.maximum(a,b)
array([3, 2, 6])  # 结果是一个数组 

数学和统计方法

sum求和
cumsum 累计求和 返回一个数组 前面每一个数的和
a.mean() 求平均数
var 方差
min
max 返回数组中的最大值
argmin
argmax 返回最大值的下标

In [222]: a
Out[222]: array([1, 2, 0])

In [223]: b
Out[223]: array([3, 1, 6])

In [224]: np.sum(a) # 求和
Out[224]: 3

In [225]: np.mean(a) # 求平均值
Out[225]: 1.0

In [226]: np.var(a)  # 求方差
Out[226]: 0.66666666666666663

In [227]: np.max(a)  # 求数组中的最大值
Out[227]: 2

In [228]: np.min(a) # 求数组中的最小值
Out[228]: 0

In [229]: np.argmax(a) # 求数组中下标最大值的索引
Out[229]: 1

In [230]: np.argmin(a)
Out[230]: 2

In [231]: np.cumsum(a) # 累计求和 
Out[231]: array([1, 3, 3], dtype=int32)

随机数生成

random.uniform(1.0,10) 小数的范围
random.random() 返回0-1
(random.random()*9)+1
random.randint() 整数
random.shuffle(a) 洗牌
random.choice() str list 返回一个

np.random.rand 0-1 原来的random

给一个形状产生一个随机的数据

生成一个随机的二维数组

In [3]: np.random.randint(1,10,(3,5))
Out[3]:
array([[3, 2, 3, 9, 6],
       [6, 6, 2, 3, 8],
       [7, 6, 3, 1, 5]])
rand		给定形状产生随机数组(0到1之间的数) 替换了random.random
randint		给定形状产生随机整数
choice		给定形状产生随机选择
shuffle		与random.shuffle相同
uniform		给定形状产生随机数组

Pandas 数据分析

Pandas是基于numpy构建的

  • DataFrame
  • Series
  • 时间序列
  • 灵活处理缺失数据

安装:pip install pandas
使用:import pandas as pd

Series

类似数组和字典的结合体,所以字典和数组的特性都能使用,是有序的

Series的左侧默认是0 1 2 3 这样的索引,右侧是values

In [5]: pd.Series([1,2,3,4])
Out[5]:
0    1
1    2
2    3
3    4
dtype: int64

In [6]: pd.Series([11,22,33,44])
Out[6]:
0    11
1    22
2    33
3    44
dtype: int64

自定义索引

重点是index = list()是一个列表,或者是index=['a','b','c','d']

In [8]: pd.Series([11,22,33,44],index=list('abcd'))
Out[8]:
a    11
b    22
c    33
d    44
dtype: int64

Series特性

通过key和下标进行索引,充分说明了Series符合字典和列表的特性

In [13]: a
Out[13]:
a    11
b    22
c    33
d    44
dtype: int64

In [14]: a['a']  # 通过key进行索引
Out[14]: 11

In [15]: a[0] # 通过下标进行索引
Out[15]: 11

a.index 返回索引对象
a.values 获取值

In [17]: a.index
Out[17]: Index(['a', 'b', 'c', 'd'], dtype='object')  返回的索引是一个对象

In [18]: a.values
Out[18]: array([11, 22, 33, 44], dtype=int64)

Series支持NumPy模块的特性(下标):

  • 从ndarray创建Series:Series(arr)
  • 与标量运算:sr*2
  • 两个Series运算:sr1+sr2
  • 索引:sr[0], sr[[1,2,4]]
  • 切片:sr[0:2]
  • 通用函数:np.abs(sr)
  • 布尔值过滤:sr[sr>0]
In [21]: pd.Series(np.array([1,2,3]))  从ndarray创建Series
Out[21]:
0    1
1    2
2    3
dtype: int32

############## 标量运算  两个标量运算 ##############
In [22]: a
Out[22]:
a    11
b    22
c    33
d    44
dtype: int64

In [23]: a+2
Out[23]:
a    13
b    24
c    35
d    46
dtype: int64

In [26]: a+a
Out[26]:
a    22
b    44
c    66
d    88
dtype: int64
########### 索引 花式索引 布尔索引##############

In [32]: a[[1,2]]  # 花式索引
Out[32]:
b    22
c    33
dtype: int64

In [34]: a[a>20]  # bool索引
Out[34]:
b    22
c    33
d    44
dtype: int64

In [35]: a>20
Out[35]:
a    False
b     True
c     True
d     True
dtype: bool

Series支持字典的特性(标签):

  • 从字典创建Series:Series(dic),
  • in运算:’a’ in sr
  • 键索引:sr['a'], sr[['a', 'b', 'd']]
In [36]: pd.Series({'a':1,'b':2,'c':3}) # 从字典创建Series
Out[36]:
a    1
b    2
c    3
dtype: int64

#### in运算
In [37]: a
Out[37]:
a    11
b    22
c    33
d    44
dtype: int64

In [38]: 'a' in a  标签表在数组中的时候返回True
Out[38]: True

In [39]: 'sss' in a
Out[39]: False

a.get('a') -- 11  get到 就返回相应的value
a.get('asdfa',default=0) # get在没有的时候也没有返回值,通过default可以设置在没有的key的时候的返回值



### series 切片

In [42]: a['a':'c'] # 只有在标签的时候才是顾头顾尾,这样设计的原因是取的时候不知道下一个值是什么,而索引可以通过+1获取下一个
Out[42]:
a    11
b    22
c    33
dtype: int64

In [43]: a[0:3] # 索引的时候仍然是顾头不顾尾
Out[43]:
a    11
b    22
c    33
dtype: int64

标签 也可以切片 顾头顾尾
只有在这种时候是

在索引是0 1 2。。。的时候还是顾头不顾尾

pandas整数索引:

a[] 中既可以是标签又可以是索引,在整数索引的时候,输入下标进行索引会出现问题
a.iloc(-1) 按照下标解释
a.loc[] 按照标签解释

a = pd.Series(np.arange(20))
b= a[10:].copy()
In [9]: b
Out[9]:
10    10
11    11
12    12
13    13
14    14
15    15
16    16
17    17
18    18
19    19
dtype: int32

b不能用b[-1] 进行索引取值

In [10]: b[-1:]  # 加冒号进行索引取值
Out[10]:
19    19
dtype: int32

In [14]: b[10]  # 只有既是标签又是索引的时候 才能通过切片取到
Out[14]: 10


######### loc  iloc   #########

Out[15]:
10    10
11    11
12    12
13    13
14    14
15    15
16    16
17    17
18    18
19    19
dtype: int32

In [16]: b.iloc[0]  # iloc是通过下标进行索引
Out[16]: 10

In [17]: b.loc[10] # loc 是通过标签进行索引
Out[17]: 10

Pandas数据对齐

pandas在运算时,会按索引进行对齐然后计算。如果存在不同的索引,则结果的索引是两个操作数索引的并集。

In [19]:a =  pd.Series(np.array([1,2,3,4]),index=list('abcd'))
Out[19]:
a    1
b    2
c    3
d    4
dtype: int32

In [22]: b =pd.Series(np.array([1,2,3,4]),index=list('acdb'))

In [23]: a.values
Out[23]: array([1, 2, 3, 4])

In [24]: b.values
Out[24]: array([1, 2, 3, 4])

In [25]: b.values + b.values
Out[25]: array([2, 4, 6, 8])  # 通过values相加的时候是数组相加

In [26]: a+b  # pandas 先对齐 再相加
Out[26]:
a    2
b    6
c    5
d    7
dtype: int32

两个数组,标签对齐是全部的。

没有的时候会出现NaN 缺失值

In [29]: b =pd.Series(np.array([1,2,3]),index=list('acd'))

In [30]: a =pd.Series(np.array([1,2,3]),index=list('bca'))

In [31]: a+b  # 没有对应值的时候会出现NaN
Out[31]:
a    4.0
b    NaN
c    4.0
d    NaN
dtype: float64

如何在两个Series对象相加时将缺失值设为0?

sr1.add(sr2, fill_value=0)

处理缺失值NaN:
a.add(b,fill_value=0) 没有的自动补0

In [56]: a.add(b)
Out[56]:
a    4.0
b    NaN
c    4.0
d    NaN
dtype: float64

In [57]: a.add(b,fill_value = 0)
Out[57]:
a    4.0
b    1.0
c    4.0
d    3.0
dtype: float64

灵活的算术方法:add, sub, div, mul

add sub div mul 在运算的时候都可以用fill_value进行填充0

pandas 缺失数据

pandas中的缺失数据是NaN ,等价于np.NaN,内置的None也会被处理成NaN

处理缺失数据的相关方法:

  • dropna() 过滤掉值为NaN的行
  • fillna() 填充缺失数据
  • snull() 返回布尔数组,缺失值对应为True
  • notnull() 返回布尔数组,缺失值对应为False
    过滤缺失数据:sr.dropna() 或 sr[sr.notnull()]
    填充缺失数据:sr.fillna(0)

注意的是pandas处理数据的时候是返回一个新的值,原来的值没有修改

c.dropna() 没有修改原来的

In [72]: c.dropna()   把c中的NaN删除了,并重新返回一个值
Out[72]:
a    4.0
c    4.0
dtype: float64

In [73]: c  # 原来的c值是不变的
Out[73]:
a    4.0
b    NaN
c    4.0
d    NaN
dtype: float64
  • c[c.isnull()] 里面是Bool索引
  • c[~c.isnull()] 非NaN
  • c[c.notnull()] 非NaN
In [86]: c[~c.isnull()] # 对其取非就拿到了没有NaN的值
Out[86]:
a    4.0
c    4.0
dtype: float64

In [87]: c[c.isnull()]  # isnull()函数 本质是通过bool索引获取的
Out[87]:
b   NaN
d   NaN
dtype: float64


In [89]: c[c.notnull()]  # c.notnull() 函数直接获取非NaN的值
Out[89]:
a    4.0
c    4.0
dtype: float64:
  • c.fillna(0) 把所有缺失的填0

还可以填充平均数c.fillna(c.mean())

In [91]: c.fillna(0)
Out[91]:
a    4.0
b    0.0
c    4.0
d    0.0
dtype: float64

In [93]: c.fillna(c.mean())  # 填充c的平均数 注意这里是mean() 有括号 函数 没有括号会报错
Out[93]:
a    4.0
b    4.0
c    4.0
d    4.0
dtype: float64

Series中的函数都加括号 mean() add() cumsume()

DataFrame

是一个表格型的数据结构,是二维的,可看做含有Series的字典,并且共用一个索引,这和索引可以看做是数据库中的主键

创建 pd.DateFrame()

创建方式一:
当one two 分别与索引看的时候,可以看做是单独的Series

In [94]: pd.DataFrame({'one':[1,2,3,4],'two':[4,3,2,1]})
    ...:
Out[94]:
   one  two
0    1    4
1    2    3
2    3    2
3    4    1

也可以自定义索引


In [98]: pd.DataFrame({'one':[1,2,3,4],'two':[7,8,9,3]},index=['a','b','c','d'])
Out[98]:
   one  two
a    1    7
b    2    8
c    3    9
d    4    3

创建方式二:

通过Series的方式创建

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

从csv文件读取数据

csv文件 是通过逗号隔开的

  • pd.read_csv('文件名') 或者是文件对象
  • a.to_csv('') 保存新的csv文件
    没有指定行索引,保存的时候会自动添加一列索引
In [104]: a.to_csv('new_csv')

In [105]: pd.read_csv('new_csv')
Out[105]:
      Unnamed: 0    id        date    open   close    high     low
0              0     0  2007-03-01  22.074  20.657  22.503  20.220
1              1     1  2007-03-02  20.750  20.489  20.944  20.256
2              2     2  2007-03-05  20.300  19.593  20.384  19.218
3              3     3  2007-03-06  19.426  19.977  20.308  19.315
4              4     4  2007-03-07  19.995  20.520  20.706  19.827
5              5     5  2007-03-08  20.353  20.273  20.454  20.167
  • a.index 行索引
2463   904595.00  601318
2464   506834.00  601318
2465   657610.00  601318
2466   667132.00  601318
2467   491294.00  601318
2468   616005.00  601318
2469  1147936.00  601318

[2470 rows x 9 columns]

In [106]: df = a

In [107]: df.index
Out[107]: RangeIndex(start=0, stop=2470, step=1)  # 索引是顾头不顾尾的

  • a.columns 列索引
In [108]: df.columns  列索引返回的是字符串
Out[108]: Index(['id', 'date', 'open', 'close', 'high', 'low', 'volume', 'code']
, dtype='object')
  • a.values 返回的是二维数组 去掉索引后

  • a.T 转置

  • a.describe() 快速统计 平均值 中间值 (注意的是有括号的)

快速返回的值包含 总数count平均值 mean

In [112]: df.describe()
Out[112]:
                id         open        close         high          low  \
count  2470.000000  2470.000000  2470.000000  2470.000000  2470.000000
mean   1234.500000    25.910605    25.932880    26.361828    25.520403
std     713.171905     9.571887     9.580407     9.776995     9.387243
min       0.000000     9.361000     9.361000     9.649000     8.965000
25%     617.250000    18.891000    18.894500    19.166500    18.688000
50%    1234.500000    22.587500    22.571500    22.973000    22.189500
75%    1851.750000    31.769000    31.845500    32.260500    31.483250
max    2469.000000    64.337000    64.333000    66.236000    63.006000

             volume      code
count  2.470000e+03    2470.0
mean   4.781578e+05  601318.0
std    5.650142e+05       0.0
min    2.543527e+04  601318.0
25%    1.948375e+05  601318.0
50%    3.016310e+05  601318.0
75%    4.918206e+05  601318.0
max    8.433281e+06  601318.0
  • 索引改名
    df.index.name = 'new_id',这样会新增加一列
In [17]: df.index.name = 'new_id'

In [18]: df
Out[18]:
          id        date    open   close
new_id
0          0  2007-03-01  22.074  20.657
1          1  2007-03-02  20.750  20.489
2          2  2007-03-05  20.300  19.593
3          3  2007-03-06  19.426  19.977
  • 修改列名
    df.rename(columns={'':''} 传入一个字典 字典中是列名
In [19]: df.rename(columns={'open':'new_open'})
Out[19]:
          id        date  new_open   close    high     low
new_id

DF 切片和索引

df+[]是对列进行索引

df['close']

df[['close','open']]

先切片
df[0:10][['open','close']]

loc iloc 逗号 左边行 右边是列
df.loc[:,['close','open']]
df.loc[0:10,['close':'close']]

In [25]: df.loc[:10,['close','open']]   # 左边是行 右边是列
Out[25]:
         close    open
new_id
0       20.657  22.074
1       20.489  20.750
2       19.593  20.300
3       19.977  19.426
4       20.520  19.995
5       20.273  20.353
6       20.101  20.264
7       19.739  19.999
8       19.818  19.783
9       19.841  19.558
10      19.849  20.097

iloc 按照下标取值
df.iloc[:,0:10]

In [26]: df.iloc[:5,0:3] 先去行的下标 然后去列的下标
Out[26]:
        id        date    open
new_id
0        0  2007-03-01  22.074
1        1  2007-03-02  20.750
2        2  2007-03-05  20.300
3        3  2007-03-06  19.426
4        4  2007-03-07  19.995

  • 通过bool值过滤

df[df<20] 不符合的变成lnan

In [31]: df<20
Out[31]:
           id  date   open  close   high    low  volume   code
new_id
0        True  True  False  False  False  False   False  False
1        True  True  False  False  False  False   False  False
2        True  True  False   True  False   True   False  False
3        True  True   True   True  False   True   False  False
4        True  True   True  False  False   True   False  False
5        True  True  False  False  False  False   False  False
6        True  True  False  False  False   True   False  False
7        True  True   True   True   True   True   False  False
8        True  True   True   True   True   True   False  False

In [32]: df[df<20]  # 把所有小于20 的转换成NaN
Out[32]:
          id        date    open   close    high     low  volume  code
new_id
0        0.0  2007-03-01     NaN     NaN     NaN     NaN     NaN   NaN
1        1.0  2007-03-02     NaN     NaN     NaN     NaN     NaN   NaN
2        2.0  2007-03-05     NaN  19.593     NaN  19.218     NaN   NaN
3        3.0  2007-03-06  19.426  19.977     NaN  19.315     NaN   NaN
4        4.0  2007-03-07  19.995     NaN     NaN  19.827     NaN   NaN
5        5.0  2007-03-08     NaN     NaN     NaN     NaN     NaN   NaN
6        6.0  2007-03-09     NaN     NaN     NaN  19.735     NaN   NaN
7        7.0  2007-03-12  19.999  19.739  19.999  19.646     NaN   NaN
8        8.0  2007-03-13  19.783  19.818  19.982  19.699     NaN   NaN

df[df<20].fillna(0)

In [34]: df[df<20].fillna(0)
Out[34]:
          id        date    open   close    high     low  volume  code
new_id
0        0.0  2007-03-01   0.000   0.000   0.000   0.000     0.0   0.0
1        1.0  2007-03-02   0.000   0.000   0.000   0.000     0.0   0.0
2        2.0  2007-03-05   0.000  19.593   0.000  19.218     0.0   0.0
3        3.0  2007-03-06  19.426  19.977   0.000  19.315     0.0   0.0
4        4.0  2007-03-07  19.995   0.000   0.000  19.827     0.0   0.0
5        5.0  2007-03-08   0.000   0.000   0.000   0.000     0.0   0.0
6        6.0  2007-03-09   0.000   0.000   0.000  19.735     0.0   0.0
7        7.0  2007-03-12  19.999  19.739  19.999  19.646     0.0   0.0
8        8.0  2007-03-13  19.783  19.818  19.982  19.699     0.0   0.0

上面的不能直接用对不符合的填充0是因为date这一列的值是字符串类型,所以报错

In [43]: df2 = df.loc[:,'open':'code']
In [44]: df2
Out[44]:
          open   close    high     low      volume    code
new_id
0       22.074  20.657  22.503  20.220  1977633.51  601318
1       20.750  20.489  20.944  20.256   425048.32  601318
2       20.300  19.593  20.384  19.218   419196.74  601318
3       19.426  19.977  20.308  19.315   297727.88  601318
4       19.995  20.520  20.706  19.827   287463.78  601318

csv文件中的是字符串
df[df['data].isin(['2017-03-1'])]

DF 每一列的数据类型要一致

Pandas 数据对齐

dropna(how='all') 默认是any 全部是ana的时候删除

axis 轴 默认是0 位行 列1
dropna(how='all',axis=1) 删除列中全是ana的

In [53]: df3.dropna(how='all',axis=1)
Out[53]:
          close     code     high      low     open      volume
new_id
0        41.314  1202636   45.006   40.440   44.148  3955267.02
1        40.978  1202636   41.888   40.512   41.500   850096.64
2        19.593  1202636   40.768   19.218   40.600   838393.48
3        19.977  1202636   40.616   19.315   19.426   595455.76
4        41.040  1202636   41.412   19.827   19.995   574927.56
5        40.546  1202636   40.908   40.334   40.706   261967.66
6        40.202  1202636   40.706   19.735   40.528   321775.58
7        19.739  1202636   19.999   19.646   19.999   290706.12

DF中使用函数

In [54]: df['close'].mean() 对close取平均值
Out[54]: 25.93288016194329
  • 索引排序
    df.sort__index(ascending=True) 升序 默认
    df.sort__index(ascending=False) 降序排列

  • 列排序
    df.sort__values('close',ascending=True) 收盘价升序排列
    df.sort__values('close',ascending=False) 收盘价降序排列
    还可以传列表 代表排序优先级

  • df2.applymap(lambda x:x+1) applymap用在DataFrame
    map用在Series中

pandas从文件读取参数

读取excel文件

需要安装 pip3 install xlrd
pd.read_excel('文件名')

csv文件

pd.read_csv() 默认分隔符是,
pd.read_table() 默认分隔符是\t

pd.read_table('',sep=',') 也可以自己指定分隔符

header=None 列名会自动变成1 2 3.。
names = ['id','close'] 可以指定列名

index_col = 'data' 指定一列为索引

parse_dates = True 把所有的值试图转换成时间对象

parse_dates =['date'] 直接转换确定的列

na_values = ['none','nan','NaN']

In [77]: df1 = pd.read_csv('601318.csv',index_col='date',parse_dates=True)
In [79]: df = df1

In [80]: type(df.index[0])
Out[80]: pandas._libs.tslib.Timestamp

pandas写入文件参数

na_rep 默认输出的nan 是空的字符串,这里可以指定

df.to_csv() 后会加一列索引 -- index = False 不输出行索引

pandas 时间对象

datetime.datetime.strptime(str,'%Y-%m-%d')

把字符串转换成时间对象
pip3 install python-dateutil

datetil.parse.parse()

pd.to_datetime(['2017-11-12'])

Pandas的时间索引

pd.date_range('2017-01-01','2017-08-08')

时间频率:
freq
默认是D day

可选参数:
H hour
W week
B business 工作日
SM 半月
T minute
S second
A year

periods = 100 长度是100

praze_dates = ['date']

df['2017']

df['2017-02']

df['2017-02':'2017-08'] 时间切片 后面包含

算 两个均线 MA5 MA10 前4个设置成NaN
新加两列

前5个取平均

每次创建一个视图

金叉 死叉的交点

df['ma5']

Pandas DataFrame的结构像数据库

df.groupby().get_group()

pd.merge(left,right) 合并
pd.merge(left,right,on='key') 指定连表相等的值

Matplotlib

安装:pip install matplotlab

使用:import matplotlib.pyplot as plt

绘图方法:

  • 绘图函数:plt.plot() #调用函数生成图像
  • 显示图像:plt.show() #显示图像
    注意:每显示一次就会把创建的图对象数据清空,当需要再次显示的话,就需要再创建一个数据

绘图参数

  • 传值:仅传一个列表的话默认是y轴的数据,x赋值为0,1,2....;传入两个列表,分别代表x轴和y轴数据;
  • 线条属性:r-o :第一个代表颜色,第二个代表线条的样式,第三个代表点的形状【象形】。
线型linestyle(-,-.,--,..)
点型marker(v,^,s,*,H,+,x,D,o,…)
颜色color(b,g,r,y,k,w,…)

绘制一条线

plt.plot([1,2,3,4]) # 画一条直线 默认是蓝色的、
plt.plot([1,2,3,4],'ro') # 点图 r 代表红色 o 代表 dot 点
plt.plot([1,2,3,4],[2,3,4,5],'r-o') # 第一个列表是x轴 第二个是Y轴 后面是红色的点线

绘制多条线

可以在一个plot函数中写,也可以写多个plot函数,然后用plt.show()显示

plt.plot([1,2,3,6],[2,3,4,5],'r-o',[4,5,7,9],'bD')

plt.plot([1,2,3],'ro') 默认一个参数的时候 x轴 1 2 3

设置标题 x轴 y轴内容

先创建plot,然后进行设置

plt.plot([1,2,3,6],[2,3,4,5],'r-o',[4,5,7,9],'bD')
In [111]: plt.xlabel('x')

In [112]: plt.ylabel('y')

In [113]: plt.title('this is a title')

In [114]: plt.show()

对DataFrame数据进行绘制

pandas 内部支持继承了matplotlib

df[['open','close']].plot()
df['close'].plot()
plt.show()

最好的是单位一致的放在一起画图

绘制频率直方图

import numpy as np
x = np.random.randint(0,10,100) #随机生成100个数
plt.hist(x)
plt.show()

或者

plt.hist(x,np.arange(10))
plt.show()

画布与字图

  • 创建画布:
    fig = plt.figure()

  • 创建字图:
    ax1 = fig.add_subplot(2,2,1) 2*2 的第一个图
    ax1 = fig.add_subplot(2,2,1) #前两个参数代表子图所占大小,第三个参数表示是第几张图

ax2 = fig.add_subplot(2,2,2)

ax3 = fig.add_subplot(2,2,3)

ax4 = fig.add_subplot(2,2,4)

ax1.plot()

实现简单的量化框架

TuShare是一个免费、开源的python财经数据接口包。
http://tushare.org/index.html

先安装lxml: pip3 install lxml
安装tushare: pip3 install tushare

限制: 还有一定的顺序

股票停牌
钱不够
至少买一手 100 的倍数
成交量不超过当天的成交量
卖出不能超过持仓数

数据本地化 手续费 基准

在线平台

set_benchmark 设置基准

set_option 动态复权 避免分红等影响股价波动

get_index_stocks 获取成分股 就是沪深300的300只股票

avg_cost 每股的平均成本

定时运行函数:
run_monthly(handle,1) 第二个参数代表交易日

滑点 撮合交易的价格最后成交价会变动

获取历史数据 attribute_history
unit='1d' 按天回测

Context 中存的是账户的基本信息
股票数据
持仓数据
avaliable_cash 可用资金

position
   security 股票代码
   price 最新的价格
   total_mount 总仓位
   closeable_mount 可卖出的仓位 T+1

指标

  • alpha 正数 相对于风险 获得了超额收益
  • Beta 基准和投资的相关性
  • Sharpe 夏普比率 越大越好
  • 最大回撤 赔的最多的时候

最好把获取HS300的放在handle中

双均线策略

择时

因子选股策略

标准
多因子

  • 最小市值 市盈率
    市值-市盈率

均值回归理论

下跌的会重新回归均线

偏离程度(MA-P)/MA

动量策略

前一段时间好 买入

反转策略

前段时间不好 买入

布林带策略

择时

三条

上面的是价格压力线
下面是支撑线
中间是n日均线

PEG 策略

选股策略

市盈率 = 股价/每股收益

适用于成长型的公司

羊驼交易法则

随机买入
遗传算法

改良--动量 买入收益率最好的

海龟交易

唐奇安通道

上线
中线
下线

核心是 止损

posted @ 2017-08-21 23:11  hzxPeter  阅读(1294)  评论(1)    收藏  举报