NumPy 秘籍中文第二版:三、掌握常用函数
原文:NumPy Cookbook - Second Edition
协议:CC BY-NC-SA 4.0
译者:飞龙
在本章中,我们将介绍许多常用函数:
sqrt()
,log()
,arange()
,astype()
和sum()
ceil()
,modf()
,where()
,ravel()
和take()
sort()
和outer()
diff()
,sign()
和eig()
histogram()
和polyfit()
compress()
和randint()
我们将在以下秘籍中讨论这些功能:
- 斐波纳契数求和
- 查找素因数
- 查找回文数
- 稳态向量
- 发现幂律
- 逢低定期交易
- 随机模拟交易
- 用 Eratosthenes 筛子来筛选质数
简介
本章介绍常用的 NumPy 函数。 这些是您每天将要使用的函数。 显然,用法可能与您不同。 NumPy 函数太多,以至于几乎不可能全部了解,但是本章中的函数是我们应该熟悉的最低要求。
斐波纳契数求和
在此秘籍中,我们将求和值不超过 400 万的斐波纳契数列中的偶数项。斐波那契数列是从零开始的整数序列,其中每个数字都是前两个数字的和,但(当然)前两个数字除外 ,零和一(0、1、1、2、3、5、8、13、21、34、55、89 …)。
该序列由斐波那契(Fibonacci)在 1202 年发布,最初不包含零。 实际上,早在几个世纪以前,印度数学家就已经知道了它。 斐波那契数在数学,计算机科学和生物学中都有应用。
注意
有关更多信息,请阅读 Wikipedia 关于斐波那契数字的文章。
该秘籍使用基于黄金比例的公式,这是一个无理数,具有与pi
相当的特殊性质。 黄金比例由以下公式给出:
我们将使用sqrt()
,log()
,arange()
,astype()
和sum()
函数。 斐波那契数列的递归关系具有以下解,涉及黄金比率:
操作步骤
以下是本书代码包中sum_fibonacci.py
文件中此秘籍的完整代码:
import numpy as np#Each new term in the Fibonacci sequence is generated by adding the previous two terms.
#By starting with 1 and 2, the first 10 terms will be:#1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...#By considering the terms in the Fibonacci sequence whose values do not exceed four million,
#find the sum of the even-valued terms.#1\. Calculate phi
phi = (1 + np.sqrt(5))/2
print("Phi", phi)#2\. Find the index below 4 million
n = np.log(4 * 10 ** 6 * np.sqrt(5) + 0.5)/np.log(phi)
print(n)#3\. Create an array of 1-n
n = np.arange(1, n)
print(n)#4\. Compute Fibonacci numbers
fib = (phi**n - (-1/phi)**n)/np.sqrt(5)
print("First 9 Fibonacci Numbers", fib[:9])#5\. Convert to integers
# optional
fib = fib.astype(int)
print("Integers", fib)#6\. Select even-valued terms
eventerms = fib[fib % 2 == 0]
print(eventerms)#7\. Sum the selected terms
print(eventerms.sum())
的第一件事是计算黄金分割率,也称为黄金分割或黄金平均值。
-
使用
sqrt()
函数计算5
的平方根:phi = (1 + np.sqrt(5))/2 print("Phi", phi)
这印出了中庸之道:
Phi 1.61803398875
-
接下来,在秘籍中,我们需要找到低于 400 万的斐波那契数的指数。 维基百科页面中提供了一个公式,我们将使用该公式进行计算。 我们需要做的就是使用
log()
函数转换对数。 我们不需要将结果四舍五入为最接近的整数。 在秘籍的下一步中,这将自动为我们完成:n = np.log(4 * 10 ** 6 * np.sqrt(5) + 0.5)/np.log(phi) print(n)
n
的值如下:33.2629480359
-
arange()
函数是许多人都知道的非常基本的函数。 不过,出于完整性考虑,我们将在这里提及:n = np.arange(1, n)
-
我们可以使用一个方便的公式来计算斐波那契数。 我们将需要黄金比例和该秘籍中上一步中的数组作为输入参数。 打印前九个斐波那契数字以检查结果:
fib = (phi**n - (-1/phi)**n)/np.sqrt(5) print("First 9 Fibonacci Numbers", fib[:9])
注意
我本可以进行单元测试而不是打印声明。 单元测试是测试一小段代码(例如函数)的测试。 秘籍的这种变化是您的练习。
提示
查看第 8 章,“质量保证”,以获取有关如何编写单元测试的指针。
顺便说一下,我们不是从数字 0 开始的。 上面的代码给了我们一系列预期的结果:
First 9 Fibonacci Numbers [ 1\. 1\. 2\. 3\. 5\. 8\. 13\. 21\. 34.]
您可以根据需要将此权限插入单元测试。
-
转换为整数。
此步骤是可选的。 我认为最后有一个整数结果是很好的。 好的,我实际上想向您展示
astype()
函数:fib = fib.astype(int) print("Integers", fib)
为简短起见,此代码为我们提供了以下结果:
Integers [ 1 1 2 3 5 8 13 21 34... snip ... snip ...317811 514229 832040 1346269 2178309 3524578]
-
选择偶数项。
此秘籍要求我们现在选择偶数项。 如果遵循第 2 章,“高级索引和数组概念”中的“布尔值索引”秘籍,这对您来说应该很容易 :
eventerms = fib[fib % 2 == 0] print(eventerms)
我们去了:
[ 2 8 34 144 610 2584 10946 46368 196418 832040 3524578]
工作原理
在此秘籍中,我们使用了sqrt()
,log()
,arange()
,astype()
和sum()
函数。 其描述如下:
函数 | 描述 |
---|---|
sqrt() | 此函数计算数组元素的平方根 |
log() | 此函数计算数组元素的自然对数 |
arange() | 此函数创建具有指定范围的数组 |
astype() | 此函数将数组元素转换为指定的数据类型 |
sum() | 此函数计算数组元素的总和 |
另见
- 第 2 章,“高级索引和数组概念”中的“布尔值索引”秘籍
查找素因数
素因数是质数,它们精确地除以整数而不会留下余数。 对于较大的数字,找到主要因子似乎几乎是不可能的。 因此,素因数在密码学中具有应用。 但是,使用正确的算法 – Fermat 因式分解方法和 NumPy – 对于小数而言,因式分解变得相对容易。 想法是将N
分解为两个数字,c
和d
,根据以下等式:
我们可以递归应用因式分解,直到获得所需的素因子。
操作步骤
以下是解决找到最大质数因子 600851475143 的问题所需的全部代码(请参见本书代码包中的fermatfactor.py
文件):
from __future__ import print_function
import numpy as np#The prime factors of 13195 are 5, 7, 13 and 29.#What is the largest prime factor of the number 600851475143 ?N = 600851475143
LIM = 10 ** 6def factor(n):#1\. Create array of trial valuesa = np.ceil(np.sqrt(n))lim = min(n, LIM)a = np.arange(a, a + lim)b2 = a ** 2 - n#2\. Check whether b is a squarefractions = np.modf(np.sqrt(b2))[0]#3\. Find 0 fractionsindices = np.where(fractions == 0)#4\. Find the first occurrence of a 0 fractiona = np.ravel(np.take(a, indices))[0]# Or a = a[indices][0]a = int(a)b = np.sqrt(a ** 2 - n) b = int(b)c = a + bd = a - bif c == 1 or d == 1:returnprint(c, d)factor(c)factor(d)factor(N)
该算法要求我们为a
尝试一些试验值:
-
创建试验值的数组。
创建一个 NumPy 数组并消除循环需求是有意义的。 但是,应注意不要创建一个在内存需求方面太大的数组。 在我的系统上,一百万个元素的数组似乎正好合适:
a = np.ceil(np.sqrt(n)) lim = min(n, LIM) a = np.arange(a, a + lim) b2 = a ** 2 - n
我们使用
ceil()
函数以元素为单位返回输入的上限。 -
获取
b
数组的小数部分。现在我们应该检查
b
是否为正方形。 使用 NumPymodf()
函数获取b
数组的分数部分:fractions = np.modf(np.sqrt(b2))[0]
-
查找
0
分数。调用
where()
NumPy 函数以找到零分数的索引,其中小数部分是0
:indices = np.where(fractions == 0)
-
找到零分数的第一个出现。
首先,使用上一步中的
indices
数组调用take()
NumPy 函数,以获取零分数的值。 现在,使用ravel()
NumPy 函数将这个数组变得扁平:a = np.ravel(np.take(a, indices))[0]
提示
这条线有些令人费解,但是确实演示了两个有用的功能。 写
a = a[indices][0]
会更简单。此代码的输出如下:
1234169 486847 1471 839 6857 71
工作原理
我们使用ceil()
,modf()
,where()
,ravel()
和take()
NumPy 函数递归地应用了费马分解。 这些函数的说明如下:
函数 | 描述 |
---|---|
ceil() | 计算数组元素的上限 |
modf() | 返回浮点数数字的分数和整数部分 |
where() | 根据条件返回数组索引 |
ravel() | 返回一个扁平数组 |
take() | 从数组中获取元素 |
查找回文数
回文数字在两种方式下的读取相同。 由两个 2 位数字的乘积组成的最大回文为9009 = 91 x 99
。让我们尝试查找由两个 3 位数字的乘积组成的最大回文。
操作步骤
以下是本书代码包中palindromic.py
文件的完整程序:
import numpy as np#A palindromic number reads the same both ways.
#The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 x 99.#Find the largest palindrome made from the product of two 3-digit numbers.#1\. Create 3-digits numbers array
a = np.arange(100, 1000)
np.testing.assert_equal(100, a[0])
np.testing.assert_equal(999, a[-1])#2\. Create products array
numbers = np.outer(a, a)
numbers = np.ravel(numbers)
numbers.sort()
np.testing.assert_equal(810000, len(numbers))
np.testing.assert_equal(10000, numbers[0])
np.testing.assert_equal(998001, numbers[-1])#3\. Find largest palindromic number
for number in numbers[::-1]:s = str(numbers[i])if s == s[::-1]:print(s)break
我们将使用最喜欢的 NumPy 函数arange()
创建一个数组,以容纳从 100 到 999 的三位数。
-
创建一个三位数的数字数组。
使用
numpy.testing
包中的assert_equal()
函数检查数组的第一个和最后一个元素:a = np.arange(100, 1000) np.testing.assert_equal(100, a[0]) np.testing.assert_equal(999, a[-1])
-
创建乘积数组。
现在,我们将创建一个数组,以将三位数数组的元素的所有可能乘积与其自身保持在一起。 我们可以使用
outer()
函数来完成此操作。 需要使用ravel()
将生成的数组弄平,以便能够轻松地对其进行迭代。 在数组上调用sort()
方法,以确保数组正确排序。 之后,我们可以进行一些检查:numbers = np.outer(a, a) numbers = np.ravel(numbers) numbers.sort() np.testing.assert_equal(810000, len(numbers)) np.testing.assert_equal(10000, numbers[0]) np.testing.assert_equal(998001, numbers[-1])
该代码打印 906609,它是回文数。
工作原理
我们看到了outer()
函数的作用。 此函数返回两个数组的外部乘积。 两个向量的外部乘积(一维数字列表)创建一个矩阵。 这与内部乘积相反,该乘积返回两个向量的标量数。 外部产品用于物理,信号处理和统计。 sort()
函数返回数组的排序副本。
更多
检查结果可能是一个好主意。 稍微修改一下代码,找出哪两个 3 位数字产生我们的回文码。 尝试以 NumPy 方式实现最后一步。
稳态向量
马尔科夫链是一个至少具有两个状态的系统。 有关马尔可夫链的详细信息,请参阅这里。 时间t
的状态取决于时间t-1
的状态,仅取决于t-1
的状态。 系统在这些状态之间随机切换。 链没有关于状态的任何记忆。 马尔可夫链通常用于对物理,化学,金融和计算机科学中的现象进行建模。 例如,Google 的 PageRank 算法使用马尔可夫链对网页进行排名。
我想为股票定义一个马尔可夫链。 假设状态为震荡,上涨和下跌的状态。 我们可以根据日末收盘价确定稳定状态。
在遥远的未来,或理论上经过无限长的时间之后,我们的马尔可夫链系统的状态将不再改变。 这称为稳定状态。 动态平衡是一种稳态。 对于股票而言,达到稳定状态可能意味着关联公司已变得稳定。 随机矩阵A
包含状态转移概率,当应用于稳态时,它会产生相同的状态x
。 为此的数学符号如下:
解决此问题的另一种方法是特征值和特征向量。特征值和特征向量是线性代数的基本概念,并且在量子力学,机器学习和其他科学中应用。
操作步骤
以下是本书代码包中steady_state_vector.py
文件中稳态向量示例的完整代码:
from __future__ import print_function
from matplotlib.finance import quotes_historical_yahoo
from datetime import date
import numpy as nptoday = date.today()
start = (today.year - 1, today.month, today.day)quotes = quotes_historical_yahoo('AAPL', start, today)
close = [q[4] for q in quotes]states = np.sign(np.diff(close))NDIM = 3
SM = np.zeros((NDIM, NDIM))signs = [-1, 0, 1]
k = 1for i, signi in enumerate(signs):#we start the transition from the state with the specified signstart_indices = np.where(states[:-1] == signi)[0]N = len(start_indices) + k * NDIM# skip since there are no transitions possibleif N == 0:continue#find the values of states at the end positionsend_values = states[start_indices + 1]for j, signj in enumerate(signs):# number of occurrences of this transition occurrences = len(end_values[end_values == signj])SM[i][j] = (occurrences + k)/float(N)print(SM)
eig_out = np.linalg.eig(SM)
print(eig_out)idx_vec = np.where(np.abs(eig_out[0] - 1) < 0.1)
print("Index eigenvalue 1", idx_vec)x = eig_out[1][:,idx_vec].flatten()
print("Steady state vector", x)
print("Check", np.dot(SM, x))
现在我们需要获取数据:
-
获取一年的数据。
一种实现方法是使用 matplotlib(请参阅第 1 章的“安装 matplotlib”秘籍,如有必要)。 我们将检索去年的数据。 这是执行此操作的代码:
today = date.today() start = (today.year - 1, today.month, today.day) quotes = quotes_historical_yahoo('AAPL', start, today)
-
选择收盘价。
现在,我们有了 Yahoo 金融的历史数据。 数据表示为元组列表,但我们仅对收盘价感兴趣。
元组中的第一个元素代表日期。 其次是开盘价,最高价,最低价和收盘价。 最后一个元素是音量。 我们可以选择以下收盘价:
close = [q[4] for q in quotes]
收盘价是每个元组中的第五个数字。 现在我们应该有大约 253 个收盘价的清单。
-
确定状态。
我们可以通过使用
diff()
NumPy 函数减去连续天的价格来确定状态。 然后,通过差异的符号给出状态。sign()
NumPy 函数返回-1
为负数,1
为正数,否则返回0
。states = np.sign(np.diff(close))
-
将随机矩阵初始化为
0
值。对于每个过渡,我们有三个可能的开始状态和三个可能的结束状态。 例如,如果我们从启动状态开始,则可以切换到:
- 向上
- 平面
- 下
使用
zeros()
NumPy 函数初始化随机矩阵:NDIM = 3 SM = np.zeros((NDIM, NDIM))
-
对于每个符号,选择相应的开始状态索引。
现在,代码变得有些混乱。 我们将不得不使用实际的循环! 我们将遍历所有可能的符号,并选择与每个符号相对应的开始状态索引。 使用
where()
NumPy 函数选择索引。 在这里,k
是一个平滑常数,我们将在后面讨论:signs = [-1, 0, 1] k = 1for i, signi in enumerate(signs):#we start the transition from the state with the specified signstart_indices = np.where(states[:-1] == signi)[0]
-
平滑和随机矩阵。
现在,我们可以计算每个过渡的出现次数。 将其除以给定开始状态的跃迁总数,就可以得出随机矩阵的跃迁概率。 顺便说一下,这不是最好的方法,因为它可能过度拟合。
在现实生活中,我们可能有一天收盘价不会发生变化,尽管对于流动性股票市场来说这不太可能。 处理零出现的一种方法是应用加法平滑。 这个想法是在我们发现的出现次数上增加一个常数,以消除零。 以下代码计算随机矩阵的值:
N = len(start_indices) + k * NDIM# skip since there are no transitions possible if N == 0:continue#find the values of states at the end positions end_values = states[start_indices + 1]for j, signj in enumerate(signs):# number of occurrences of this transition occurrences = len(end_values[end_values == signj])SM[i][j] = (occurrences + k)/float(N)print(SM)
前述代码所做的是基于出现次数和加性平滑计算每个可能过渡的过渡概率。 在其中一个测试运行中,我得到了以下矩阵:
[[ 0.5047619 0.00952381 0.48571429][ 0.33333333 0.33333333 0.33333333][ 0.33774834 0.00662252 0.65562914]]
-
特征值和特征向量。
要获得特征值和特征向量,我们将需要
linalg
NumPy 模块和eig()
函数:eig_out = numpy.linalg.eig(SM) print(eig_out)
eig()
函数返回一个包含特征值的数组和另一个包含特征向量的数组:(array([ 1\. , 0.16709381, 0.32663057]), array([[ 5.77350269e-01, 7.31108409e-01, 7.90138877e-04],[ 5.77350269e-01, -4.65117036e-01, -9.99813147e-01],[ 5.77350269e-01, -4.99145907e-01, 1.93144030e-02]]))
-
为特征值
1
选择特征向量。目前,我们只对特征值
1
的特征向量感兴趣。 实际上,特征值可能不完全是1
,因此我们应该建立误差容限。 我们可以在0.9
和1.1
之间找到特征值的索引,如下所示:idx_vec = np.where(np.abs(eig_out[0] - 1) < 0.1) print("Index eigenvalue 1", idx_vec)x = eig_out[1][:,idx_vec].flatten()
此代码的其余输出如下:
Index eigenvalue 1 (array([0]),) Steady state vector [ 0.57735027 0.57735027 0.57735027] Check [ 0.57735027 0.57735027 0.57735027]
工作原理
我们获得的特征向量的值未标准化。 由于我们正在处理概率,因此它们应该合计为一个。 在此示例中介绍了diff()
,sign()
和eig()
函数。 它们的描述如下:
函数 | 描述 |
---|---|
diff() | 计算离散差。 默认情况下是一阶。 |
sign() | 返回数组元素的符号。 |
eig() | 返回数组的特征值和特征向量。 |
另见
- 第 1 章,“使用 IPython”中的“安装 matplotlib”秘籍
发现幂律
为了这个秘籍目的,假设我们正在经营一家对冲基金。 让它沉入; 您现在是百分之一的一部分!
幂律出现在很多地方。 有关更多信息,请参见这里。 在这样的定律中,一个变量等于另一个变量的幂:
例如,帕累托原理是幂律。 它指出财富分配不均。 这个原则告诉我们,如果我们按照人们的财富进行分组,则分组的规模将成倍地变化。 简而言之,富人不多,亿万富翁更少。 因此是百分之一
假设在收盘价对数回报中存在幂定律。 当然,这是一个很大的假设,但是幂律假设似乎到处都有。
我们不想交易太频繁,因为每笔交易涉及交易成本。 假设我们希望根据重大调整(换句话说就是大幅下降)每月进行一次买卖。 问题是要确定适当的信号,因为我们要在大约 20 天内每 1 天启动一次交易。
操作步骤
以下是本书代码包中powerlaw.py
文件的完整代码:
from matplotlib.finance import quotes_historical_yahoo
from datetime import date
import numpy as np
import matplotlib.pyplot as plt#1\. Get close prices.
today = date.today()
start = (today.year - 1, today.month, today.day)quotes = quotes_historical_yahoo('IBM', start, today)
close = np.array([q[4] for q in quotes])#2\. Get positive log returns.
logreturns = np.diff(np.log(close))
pos = logreturns[logreturns > 0]#3\. Get frequencies of returns.
counts, rets = np.histogram(pos)
# 0 counts indices
indices0 = np.where(counts != 0)
rets = rets[:-1] + (rets[1] - rets[0])/2
# Could generate divide by 0 warning
freqs = 1.0/counts
freqs = np.take(freqs, indices0)[0]
rets = np.take(rets, indices0)[0]
freqs = np.log(freqs)#4\. Fit the frequencies and returns to a line.
p = np.polyfit(rets,freqs, 1)#5\. Plot the results.
plt.title('Power Law')
plt.plot(rets, freqs, 'o', label='Data')
plt.plot(rets, p[0] * rets + p[1], label='Fit')
plt.xlabel('Log Returns')
plt.ylabel('Log Frequencies')
plt.legend()
plt.grid()
plt.show()
首先,让我们从 Yahoo 金融获取过去一年的历史日末数据。 之后,我们提取该时段的收盘价。 在上一秘籍中描述了这些步骤:
-
获得正的对数回报。
现在,计算收盘价的对数回报。 有关对数回报中的更多信息,请参考这里。
首先,我们将获取收盘价的对数,然后使用
diff()
NumPy 函数计算这些值的第一个差异。 让我们从对数回报中选择正值:logreturns = np.diff(np.log(close)) pos = logreturns[logreturns > 0]
-
获得回报的频率。
我们需要使用
histogram()
函数获得回报的频率。 返回计数和垃圾箱数组。 最后,我们需要记录频率,以获得良好的线性关系:counts, rets = np.histogram(pos) # 0 counts indices indices0 = np.where(counts != 0) rets = rets[:-1] + (rets[1] - rets[0])/2 # Could generate divide by 0 warning freqs = 1.0/counts freqs = np.take(freqs, indices0)[0] rets = np.take(rets, indices0)[0] freqs = np.log(freqs)
-
拟合频率并返回一条线。
使用
polyfit()
函数进行线性拟合:p = np.polyfit(rets,freqs, 1)
-
绘制结果。
最后,我们将绘制数据并将其与 matplotlib 线性拟合:
plt.title('Power Law') plt.plot(rets, freqs, 'o', label='Data') plt.plot(rets, p[0] * rets + p[1], label='Fit') plt.xlabel('Log Returns') plt.ylabel('Log Frequencies') plt.legend() plt.grid() plt.show()
我们得到一个很好的线性拟合,收益率和频率图,如下所示:
工作原理
histogram()
函数计算数据集的直方图。 它返回直方图值和桶的边界。 polyfit()
函数将数据拟合给定阶数的多项式。 在这种情况下,我们选择了线性拟合。 我们发现了幂律法-您必须谨慎地提出此类主张,但证据看起来很有希望。
另见
- 第 1 章,“使用 IPython”中的“安装 matplotlib”秘籍
histogram()
函数的文档页面polyfit()
函数的文档页面
逢低定期交易
股票价格周期性地下跌和上涨。 我们将研究股价对数收益的概率分布,并尝试一个非常简单的策略。 该策略基于对均值的回归。 这是弗朗西斯·高尔顿爵士最初在遗传学中发现的一个概念。 据发现,高大父母的孩子往往比父母矮。 矮小父母的孩子往往比父母高。 当然,这是一种统计现象,没有考虑基本因素和趋势,例如营养改善。 均值回归也与股票市场有关。 但是,它不提供任何保证。 如果公司开始生产不良产品或进行不良投资,则对均值的回归将无法节省股票。
让我们首先下载股票的历史数据,例如AAPL
。 接下来,我们计算收盘价的每日对数回报率。 我们将跳过这些步骤,因为它们在上一个秘籍中已经完成。
准备
如有必要,安装 matplotlib 和 SciPy。 有关相应的秘籍,请参见“另请参见”部分。
操作步骤
以下是本书代码包中periodic.py
文件的完整代码:
from __future__ import print_function
from matplotlib.finance import quotes_historical_yahoo
from datetime import date
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt#1\. Get close prices.
today = date.today()
start = (today.year - 1, today.month, today.day)quotes = quotes_historical_yahoo('AAPL', start, today)
close = np.array([q[4] for q in quotes])#2\. Get log returns.
logreturns = np.diff(np.log(close))#3\. Calculate breakout and pullback
freq = 0.02
breakout = scipy.stats.scoreatpercentile(logreturns, 100 * (1 - freq) )
pullback = scipy.stats.scoreatpercentile(logreturns, 100 * freq)#4\. Generate buys and sells
buys = np.compress(logreturns < pullback, close)
sells = np.compress(logreturns > breakout, close)
print(buys)
print(sells)
print(len(buys), len(sells))
print(sells.sum() - buys.sum())#5\. Plot a histogram of the log returns
plt.title('Periodic Trading')
plt.hist(logreturns)
plt.grid()
plt.xlabel('Log Returns')
plt.ylabel('Counts')
plt.show()
现在来了有趣的部分:
-
计算突破和回调。
假设我们要每年进行五次交易,大约每 50 天进行一次。 一种策略是在价格下跌一定百分比时进行买入(回调),而在价格上涨另一百分比时进行卖出(突破)。
通过设置适合我们交易频率的百分比,我们可以匹配相应的对数回报。 SciPy 提供
scoreatpercentile()
函数,我们将使用:freq = 0.02 breakout = scipy.stats.scoreatpercentile(logreturns, 100 * (1 - freq) ) pullback = scipy.stats.scoreatpercentile(logreturns, 100 * freq)
-
产生买卖。
使用
compress()
NumPy 函数为我们的收盘价数据生成买卖。 该函数根据条件返回元素:buys = np.compress(logreturns < pullback, close) sells = np.compress(logreturns > breakout, close) print(buys) print(sells) print(len(buys), len(sells)) print(sells.sum() - buys.sum())
AAPL
和 50 天期间的输出如下:[ 77.76375466 76.69249773 102.72 101.2 98.57 ] [ 74.95502967 76.55980292 74.13759123 80.93512599 98.22 ] 5 5 -52.1387025726
因此,如果我们买卖
AAPL
股票五次,我们将损失 52 美元。 当我运行脚本时,经过更正后整个市场都处于恢复模式。 您可能不仅要查看AAPL
的股价,还可能要查看APL
和SPY
的比率。SPY
可以用作美国股票市场的代理。 -
绘制对数回报的直方图。
只是为了好玩,让我们用 matplotlib 绘制对数回报的直方图:
plt.title('Periodic Trading') plt.hist(logreturns) plt.grid() plt.xlabel('Log Returns') plt.ylabel('Counts') plt.show()
直方图如下所示:
工作原理
我们遇到了compress()
函数,该函数返回一个数组,其中包含满足给定条件的输入的数组元素。 输入数组保持不变。
另见
- 第 1 章,“使用 IPython”中的“安装 matplotlib”秘籍
- 第 2 章,“高级索引和数组概念”中的“安装 SciPy”秘籍
- 本章中的“发现幂律”秘籍
compress()
函数文档页面
随机模拟交易
在先前的秘籍中,我们尝试了一种交易想法。 但是,我们没有基准可以告诉我们所获得的结果是否良好。 在这种情况下,通常以我们应该能够击败随机过程为前提进行随机交易。 我们将从交易年度中随机抽出几天来模拟交易。 这应该说明使用 NumPy 处理随机数。
准备
如有必要,安装 matplotlib。 请参考相应秘籍的“另请参见”部分。
操作步骤
以下是本书代码包中random_periodic.py
文件的完整代码:
from __future__ import print_function
from matplotlib.finance import quotes_historical_yahoo
from datetime import date
import numpy as np
import matplotlib.pyplot as pltdef get_indices(high, size):#2\. Generate random indicesreturn np.random.randint(0, high, size)#1\. Get close prices.
today = date.today()
start = (today.year - 1, today.month, today.day)quotes = quotes_historical_yahoo('AAPL', start, today)
close = np.array([q[4] for q in quotes])nbuys = 5
N = 2000
profits = np.zeros(N)for i in xrange(N):#3\. Simulate tradesbuys = np.take(close, get_indices(len(close), nbuys))sells = np.take(close, get_indices(len(close), nbuys))profits[i] = sells.sum() - buys.sum()print("Mean", profits.mean())
print("Std", profits.std())#4\. Plot a histogram of the profits
plt.title('Simulation')
plt.hist(profits)
plt.xlabel('Profits')
plt.ylabel('Counts')
plt.grid()
plt.show()
首先,我们需要一个数组,其中填充了随机整数:
-
生成随机索引。
您可以使用
randint()
NumPy 函数生成随机整数。 这将与一个交易年度的随机日期相关联:return np.random.randint(0, high, size)
-
模拟交易。
您可以使用上一步中的随机指数来模拟交易。 使用
take()
NumPy 函数从步骤 1 的数组中提取随机收盘价:buys = np.take(close, get_indices(len(close), nbuys)) sells = np.take(close, get_indices(len(close), nbuys)) profits[i] = sells.sum() - buys.sum()
-
绘制大量模拟的利润直方图:
plt.title('Simulation') plt.hist(profits) plt.xlabel('Profits') plt.ylabel('Counts') plt.grid() plt.show()
以下是
AAPL
的 2,000 个模拟结果的直方图的屏幕截图,一年内进行了五次买卖:
工作原理
我们使用了randint()
函数,该函数可以在numpy.random
模块中找到。 该模块包含更方便的随机生成器,如下表所述:
函数 | 描述 |
---|---|
rand() | 从[0,1] 上的均匀分布中创建一个数组,其形状基于大小参数。 如果未指定大小,则返回单个浮点数。 |
randn() | 从均值0 和方差1 的正态分布中采样值。 大小参数的作用与rand() 相同。 |
randint() | 返回一个给定下限,可选上限和可选输出形状的整数数组。 |
另见
- 第 1 章,“使用 IPython”中的“安装 matplotlib”秘籍
用 Eratosthenes 筛子筛选质数
Eratosthenes 筛子是一种过滤质数的算法。 迭代地标识找到的质数的倍数。 根据定义,倍数不是质数,可以消除。 此筛子对于不到 1000 万的质数有效。 现在让我们尝试找到第 10001 个质数。
操作步骤
第一步是创建自然数列表:
-
创建一个连续整数列表。 NumPy 为此具有
arange()
函数:a = np.arange(i, i + LIM, 2)
-
筛选出
p
的倍数。我们不确定这是否是 Eratosthenes 想要我们做的,但是它有效。 在下面的代码中,我们传递 NumPy 数组,并去除除以
p
时余数为零的所有元素:a = a[a % p != 0]
以下是此问题的完整代码:
from __future__ import print_function import numpy as npLIM = 10 ** 6 N = 10 ** 9 P = 10001 primes = [] p = 2#By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.#What is the 10 001st prime number?def sieve_primes(a, p):#2\. Sieve out multiples of pa = a[a % p != 0]return afor i in xrange(3, N, LIM):#1\. Create a list of consecutive integersa = np.arange(i, i + LIM, 2)while len(primes) < P:a = sieve_primes(a, p)primes.append(p)p = a[0]print(len(primes), primes[P-1])
相关文章:

NumPy 秘籍中文第二版:三、掌握常用函数
原文:NumPy Cookbook - Second Edition 协议:CC BY-NC-SA 4.0 译者:飞龙 在本章中,我们将介绍许多常用函数: sqrt(),log(),arange(),astype()和sum()ceil(),modf()&…...

蓝桥杯基础17:BASIC-02试题 序列求和
资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 问题描述 求123...n的值。 输入格式 输入包括一个整数n。 输出格式 输出一行,包括一个整数,表示123...n…...
vue移动端实现vue-pdf在线预览与展示,并且解决页面汉字空白的问题
vue移动端实现pdf的页面在线预览展示,CMapReaderFactory可以解决文字不展示、空白问题 //1、安装依赖vue-pdf npm install --save vue-pdf//2、使用组件 <pdf v-for"i in numPages" ref"pdfs" :src"pdfUrl" :key"i" …...
代码随想录算法训练营第四十九天 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II
打卡第49天,买卖股票系列了 今日任务 ● 121. 买卖股票的最佳时机 ● 122.买卖股票的最佳时机II 121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#x…...
【职场篇】程序员是否吃青春饭?程序员在35岁之后是否需要转行?
你们好 那么众所周知呢像空姐 还有模特这种职业呢 都是吃青春饭的 那么到了一定年龄呢 他们可能就不做这一行了 那么其实程序员这个职业呢 有的人认为他也是吃青春饭的 普遍人都认为呢 如果程序员做到35岁呢 没有转管理岗位 可能以后就没有什么前途了 可能就要考虑换别的行业了…...

( “树” 之 DFS) 226. 翻转二叉树 ——【Leetcode每日一题】
226. 翻转二叉树 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1] 示例 2: 输入:root [2,1,3] 输出:[…...

实验7---myBatis和Spring整合
实验七 myBatis和Spring整合 一、实验目的及任务 通过该实验,掌握mybatis和spring整合方法,掌握生成mapper实现类的两种生成方式。 二、实验环境及条件 主机操作系统为Win10,Tomcat,j2sdk1.6或以上版本。 三、实验实施步骤 略 四、实验报告内…...

DJ3-4 传输层(第四节课)
目录 一、TCP 概述 二、TCP 报文段的首部字段格式 三、TCP 往返时延的估计和超时 1. 估计往返时间 2. RTT 估计例子 3. 估计往返时间的偏差 4. 设置重传超时间隔 一、TCP 概述 全双工服务:允许在同一时间同一连接上,数据能够双向传输。注意&#…...

2023爱分析·商业智能应用解决方案市场厂商评估报告:数聚股份
目录 1. 研究范围定义 2. 商业智能应用解决方案市场分析 3. 厂商评估:数聚股份 4. 入选证书 1. 研究范围定义 商业智能(BI)是在实现数据集成和统一管理的基础上,利用数据存储和处理、分析与展示等技术,满足企…...
Kotlin方法执行顺序
方法的执行顺序 主构造函数init代码块次构造函数...

Ubuntu系统配置SonarQube + cppcheck + Jenkins
SonarQube1. postgresql安装及配置1.1 安装postgresql1.2 创建sonarqube用户1.3 设置数据库2. 安装sonarqube2.1 设置sonarqube2.2 修改sonarqube目录权限2.3 sonar.properties2.4 设置systemd管理sonarqube2.5 web3. 配置sonarscanner3.1 下载3.2 配置4. 配置cppcheck4.1 下载…...
Spring @Valid 不生效 问题记录
校验的简单使用: 在Spring中,我们可以使用Valid注解对实体进行校验。在Controller的方法参数中添加Valid注解,然后在实体类的属性上添加校验注解,例如NotNull、Size等。例如: RestController public class UserContr…...

五步教你如何注册一个公司网站
在今天的数字化时代,每个公司都需要一个强大的线上存在感。注册一个公司网站是实现这一目标的第一步。但是,对于许多公司而言,这个过程可能有些困难。因此,在本文中,我将介绍一个五步计划,让您轻松注册一个…...

CSS绘制气泡对话框样式(有边框)
1、效果图 2、难点和思路 难点:上面那个带边框的小三角不好实现 思路:画两个不同大小的div,使其基本重叠(两个大小不同,不完全重叠,让红色的露出一点边边),让白色div放到最上层&…...

12款 Macmini A1347 跑 Stable Diffusion,20多分钟一张图
设备 2012款 Macmini A1347 12款 mini A1347 跑 Stable Diffusion 要20多分钟一张图 来欣赏一下20分钟画出来的图片 a black and white cat 环境:...

流量控制和拥塞控制的原理和区别
文章目录先介绍下重传机制和滑动窗口超时重传快速重传SACK方法Duplicate SACK滑动窗口发送方缓存窗口接收方缓存窗口流量控制小结拥塞控制慢开始算法拥塞避免算法快重传快恢复先介绍下重传机制和滑动窗口 超时重传 重传机制的其中一个方式,就是发送数据时…...
金融机构断卡行动中外部数据
“断卡行动”,近几年逐渐走入大众视野,是国家在从根源上整治网络及金融犯罪层面的重大举措。相信很多朋友在日常生活中已经有所体会了,比如我们在办理电话卡及银行卡的时候要经过很多审核机制,同时发卡后还会限制卡片的一些转账等…...

携程总监的单元测试是怎么样写的?
大家都知道,开发软件的时候为代码编写单元测试是很好的。但实际上,光有测试还不够,还要编写好的测试,这同样重要。 要做到这一点,考虑遵循一些固执的原则,对测试代码给予一些关爱: 1. 保持测试…...

算法每日一题:P2089 烤鸡 -DFS练习
😚一个不甘平凡的普通人,日更算法学习和打卡,期待您的关注和认可,陪您一起学习打卡!!!😘😘😘 🤗专栏:每日算法学习 💬个人…...
Spring中的循环依赖是什么?如何解决它?
循环依赖是指两个或多个Bean之间相互依赖,导致它们无法被正确地初始化。在Spring中,当两个或多个Bean之间存在循环依赖时,Spring容器无法决定哪个Bean应该先初始化,因此会抛出BeanCurrentlyInCreationException异常,从…...
Ntfs!ReadIndexBuffer函数分析之nt!CcGetVirtualAddress函数之nt!CcGetVacbMiss
第一部分: NtfsMapStream( IrpContext, Scb, LlBytesFromIndexBlocks( IndexBlock, Scb->ScbType.Index.IndexBlockByteShift ), Scb->ScbType.Index.BytesPerIndexBuffer, &am…...

LangGraph--Agent工作流
Agent的工作流 下面展示了如何创建一个“计划并执行”风格的代理。 这在很大程度上借鉴了 计划和解决 论文以及Baby-AGI项目。 核心思想是先制定一个多步骤计划,然后逐项执行。完成一项特定任务后,您可以重新审视计划并根据需要进行修改。 般的计算图如…...
数据库、数据仓库、数据中台、数据湖相关概念
文章目录 序言1数据库,数据仓库,数据中台,数据湖-概念对比释义1.1概念产生的时间顺序1.2在使用功能方面对比1.3在使用工具方面对比 2数据仓库2.1数据仓库的发展阶段2.2 数据仓库的设计2.3数据仓库常用工具,方法2.3.1分析型数据库和…...
LeetCode--25.k个一组翻转链表
解题思路: 1.获取信息: (1)给定一个链表,每k个结点一组进行翻转 (2)余下不足k个结点,则不进行交换 2.分析题目: 其实就是24题的变题,24题是两两一组进行交换&…...

CAD多面体密堆积3D插件
插件介绍 CAD多面体密堆积3D插件可在AutoCAD内建立三维随机多面体密堆积模型。 插件内置物理动力学模拟算法,通过模拟重力、碰撞等现象,使多面体在虚拟环境中发生自然堆积,进而实现真实的堆积效果。多面体堆积模拟中存在的局部穿模问题可通…...

three.js 零基础到入门
three.js 零基础到入门 什么是 three.js为什么使用 three.js使用 Three.js1. 创建场景示例 2.创建相机3. 创建立方体并添加网格地面示例 5. 创建渲染器示例 6. 添加效果(移动/雾/相机跟随物体/背景)自动旋转示例效果 相机自动旋转示例 展示效果 实现由远到近的雾示例展示效果 T…...
Linux 用户层 和 内核层锁的实现
目录 一、系统调用futex介绍1. 核心机制2. 常见操作3. 工作流程示例(互斥锁)4. 优势5. 注意事项6. 典型应用 二、Linux中用户态的锁和内核的锁不是同一个实现吗?2.1 本质区别2.2 用户态锁如何工作(以 pthread_mutex 为例ÿ…...
Android第十五次面试总结(第三方组件和adb命令)
Android 第三方组件转为系统组件核心流程 这通常是在进行 Android 系统定制(如 ROM 开发、固件制作)时完成,目的是让第三方应用拥有更高的权限和系统身份。主要过程如下: 核心准备:签名!赋予系统身份 …...

基于Scala实现Flink的三种基本时间窗口操作
目录 代码结构 代码解析 (1) 主程序入口 (2) 窗口联结(Window Join) (3) 间隔联结(Interval Join) (4) 窗口同组联结(CoGroup) (5) 执行任务 代码优化 (1) 时间戳分配 (2) 窗口大小 (3) 输出格式…...

行为型设计模式之Mediator(中介者)
行为型设计模式之Mediator(中介者) 1)意图 用一个中介对象来封装一系列的对象的交互。中介者使各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 2)结构 其中ÿ…...