import numpy as np
np.loadtxt(
'path',delimiter = ',',usecols = (0,2),unpack = False,
dtype = 'U10 f8',converters = {1:func} # 转换器函数字典
)
绘制收盘价格折线图
import numpy as np
import datetime as dt
import matplotlib.pyplot as mp
import matplotlib.dates as md
def dmy2ymd(dmy):
dmy = str(dmy,encoding = 'utf-8')
time = dt.datetime.strptime(dmy,'%d-%m-%Y')
t = time.date().strftime('%Y-%m-%d')
return t
dates,opening_prices,highest_prices,lowest_prices,closing_prices =
np.loadtxt('aapl.csv',delimiter = ',',usecols = (1,3,4,5,6),
unpack = True,dtype = 'M8[D],f8,f8,f8,f8',
converters = {1,dmy2ymd})
# 折线图
mp.figure('AAPL', facecolor='lightgray')
mp.title('AAPL', fontsize=16)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Price', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 设置x轴刻度定位器
ax = mp.gca()
ax.xaxis.set_major_locator(
md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(
md.DateFormatter('%d %b %Y'))
ax.xaxis.set_minor_locator(md.DayLocator())
# 为了日期显示合理,修改dates的dtype
dates = dates.astype(md.datetime.datetime)
mp.plot(dates, closing_prices, alpha=0.3,
color='dodgerblue', linewidth=2,
linestyle='--', label='AAPL CP')
mp.legend()
mp.show()
在上图基础上添加蜡烛图,即包含实体(开盘价、收盘价)和影线(最高价、最低价)的bar
# 控制实体与影线的颜色
rise = closing_prices >= opening_prices
color = np.array(
['white' if x else 'green' for x in rise])
ecolor = np.array(
['red' if x else 'green' for x in rise])
# 绘制实体
mp.bar(dates, closing_prices - opening_prices,
0.8, opening_prices, color=color,
edgecolor=ecolor, zorder=3)
# 绘制影线
mp.vlines(dates, lowest_prices, highest_prices,
color=ecolor)
np.mean(array)
np.average(array,weights = array2)
np.max()
np.min()
np.ptp()
# 返回下标
np.argmax()
np.argmin()
# 将满足条件的同维数组组合成新的数组
np.maximun(a_array,b_array)
np.minimum(a_array,b_array)
np.median(array)
np.std(array,[ddof=1]) 总体[样本]标准差
案例:绘制5日均线
import datetime as dt
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.dates as md
def dmy2ymd(dmy):
dmy = str(dmy, encoding='utf-8')
date = dt.datetime.strptime(dmy, '%d-%m-%Y').date()
ymd = date.strftime('%Y-%m-%d')
return ymd
dates, closing_prices = np.loadtxt('../data/aapl.csv', delimiter=',',
usecols=(1, 6), unpack=True, dtype='M8[D], f8', converters={1: dmy2ymd})
# 处理数据
sma51 = np.zeros(closing_prices.size - 4)
for i in range(sma51.size):
sma51[i] = closing_prices[i:i + 5].mean()
# 开始绘制5日均线
mp.figure('Simple Moving Average', facecolor='lightgray')
mp.title('Simple Moving Average', fontsize=20)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Price', fontsize=14)
ax = mp.gca()
# 设置水平坐标每个星期一为主刻度
ax.xaxis.set_major_locator(md.WeekdayLocator( byweekday=md.MO))
# 设置水平坐标每一天为次刻度
ax.xaxis.set_minor_locator(md.DayLocator())
# 设置水平坐标主刻度标签格式
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y'))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
dates = dates.astype(md.datetime.datetime)
mp.plot(dates, closing_prices, c='lightgray', label='Closing Price')
mp.plot(dates[4:], sma51, c='orangered', label='SMA-5(1)')
mp.legend()
mp.gcf().autofmt_xdate()
mp.show()
sma5 = np.convolve(array,np.ones(5)/5,'valid') # 'valid'==有效,same == 同维,full = 完全卷积
mp.plot(x[4:],sma5,color = 'green',alpha = 0.5,linewidth = 6, label ='sma5')
布林带的组成:中轨:移动平均线;上轨:中轨+2×标准差;下轨:中轨-2×标准差
API:
weights = np.exp(np.linspace(-1, 0, 5))
weights /= weights.sum()
em5 = np.convolve(closing_prices, weights[::-1], 'valid')
stds = np.zeros(em5.size)
for i in range(stds.size):
stds[i] = closing_prices[i:i + 5].std()
stds *= 2
lowers = medios - stds
uppers = medios + stds
mp.plot(dates, closing_prices, c='lightgray', label='Closing Price')
mp.plot(dates[4:], medios, c='dodgerblue', label='Medio')
mp.plot(dates[4:], lowers, c='limegreen', label='Lower')
mp.plot(dates[4:], uppers, c='orangered', label='Upper')
关键的一句API
x = np.linalg.lstsq(array_A, array_B)[0]
案例:
import numpy as np
import datetime as dt
import matplotlib.pyplot as mp
import matplotlib.dates as md
def dmy2ymd(dmy):
dmy = str(dmy, encoding='utf-8')
time = dt.datetime.strptime(dmy, '%d-%m-%Y')
t = time.date().strftime('%Y-%m-%d')
return t
dates, opening_prices, highest_prices, \
lowest_prices, closing_prices = np.loadtxt(
'../data/da_data/aapl.csv', delimiter=',',
usecols=(1, 3, 4, 5, 6), unpack=True,
dtype='M8[D], f8, f8, f8, f8',
converters={1: dmy2ymd})
# 绘制收盘价折线图
mp.figure('AAPL', facecolor='lightgray')
mp.title('AAPL', fontsize=16)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Price', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 设置x轴刻度定位器
ax = mp.gca()
ax.xaxis.set_major_locator(
md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(
md.DateFormatter('%d %b %Y'))
ax.xaxis.set_minor_locator(md.DayLocator())
# 为了日期显示合理,修改dates的dtype
dates = dates.astype(md.datetime.datetime)
mp.plot(dates, closing_prices,
color='dodgerblue', linewidth=2,
linestyle='--', label='AAPL CP')
# 线性预测
N = 4
# 预测每一天的股票价格
pred_prices = np.zeros(
closing_prices.size - 2 * N + 1)
for i in range(pred_prices.size):
A = np.zeros((N, N))
for j in range(N):
A[j, ] = closing_prices[i + j:i + j + N]
print('第%s个:'%i,A)
B = closing_prices[i + N: i + N * 2]
x = np.linalg.lstsq(A, B)[0]
# print(x)
pred = B.dot(x) # 点乘
pred_prices[i] = pred
mp.plot(dates[2 * N:], pred_prices[:-1],
'o-', color='orangered', label='Prediction')
mp.legend()
mp.gcf().autofmt_xdate()
mp.show()
趋势线
API:
import numpy as np
import datetime as dt
import matplotlib.pyplot as mp
import matplotlib.dates as md
def dmy2ymd(dmy):
dmy = str(dmy, encoding='utf-8')
time = dt.datetime.strptime(dmy, '%d-%m-%Y')
t = time.date().strftime('%Y-%m-%d')
return t
dates, opening_prices, highest_prices, \
lowest_prices, closing_prices = np.loadtxt(
'../da_data/aapl.csv', delimiter=',',
usecols=(1, 3, 4, 5, 6), unpack=True,
dtype='M8[D], f8, f8, f8, f8',
converters={1: dmy2ymd})
# 绘制收盘价折线图
mp.figure('AAPL', facecolor='lightgray')
mp.title('AAPL', fontsize=16)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Price', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
# 设置x轴刻度定位器
ax = mp.gca()
ax.xaxis.set_major_locator(
md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_major_formatter(
md.DateFormatter('%d %b %Y'))
ax.xaxis.set_minor_locator(md.DayLocator())
# 为了日期显示合理,修改dates的dtype
dates = dates.astype(md.datetime.datetime)
mp.plot(dates, closing_prices, alpha=0.3,
color='dodgerblue', linewidth=2,
linestyle='--', label='AAPL CP')
# 根据最高、最低、收盘求出趋势点
trend_points = (highest_prices + lowest_prices +
closing_prices) / 3
mp.scatter(dates, trend_points, marker='o',
s=70, color='orangered', alpha=0.6,
label='Trend Points')
# 针对趋势点执行线性拟合操作,得到k与b并绘制趋势线
# 组织A 与 B
days = dates.astype('M8[D]').astype('int32')
A = np.column_stack((days, np.ones_like(days)))
B = trend_points
x = np.linalg.lstsq(A, B)[0]
trend_line = x[0] * days + x[1]
mp.plot(dates, trend_line, linewidth=2,
color='orangered', label='Trend Line')
mp.legend()
mp.gcf().autofmt_xdate()
mp.show()
协方差可以简单反映两组统计样本的相关性,值为正,则为正相关;值为负,则为负相关,绝对值越大相关性越强。
# 均值
avg_a = np.mean(a)
avg_b = np.mean(b)
# 离差
dev_a = a-avg_a
dev_b = b-avg_b
# 协方差
cov_ab = np.mean(dev_a*dev_b)
cov_ba = np.mean(dev_b*dev_a)
cor_ab = cov_ab/(std_a * std_b)
# 相关系数矩阵
np.corrcoef(a,b)
# 协方差矩阵
np.cov(a,b)
API:
np.polyfit(X,Y,最高次幂) -> P # 拟合系数
np.polyval(P,X) -> Y # 根据系数和X求Y
np.polyder(P) -> Q # 根据系数求导函数系数
xs = np.roots(Q) # 已知多项式系数Q,求根
Q = np.polysub(P1,P2) # 两个多项式函数的差函数的系数,xs = np.roots(Q) 求出两个函数的交点。
卷积降噪
dates, bhp_closing_prices = np.loadtxt( 'bhp.csv', delimiter=',', usecols=(1,6), dtype='M8[D], f8',converters={1:dmy2ymd}, unpack=True)
vale_closing_prices = np.loadtxt( 'vale.csv', delimiter=',', usecols=(6) ,dtype='f8',converters={1:dmy2ymd}, unpack=True)
bhp_returns = np.diff(bhp_closing_prices) / bhp_closing_prices[:-1]
vale_returns = np.diff(vale_closing_prices) / vale_closing_prices[:-1]
dates = dates[:-1]
#卷积降噪
convolve_core = np.hanning(8)
convolve_core /= convolve_core.sum()
bhp_returns_convolved = np.convolve(bhp_returns, convolve_core, 'valid')
vale_returns_convolved = np.convolve(vale_returns, convolve_core,'valid')
sign函数可以把样本数组变成对应的符号数组,正数变为1,负数变为-1,0则变为0。
ary = np.sign(array)
绘制obv(On Balance Volume)能量潮柱状图
API:
dates, closing_prices, volumes = np.loadtxt(
'bhp.csv', delimiter=',',
usecols=(1, 6, 7), unpack=True,
dtype='M8[D], f8, f8', converters={1: dmy2ymd})
diff_closing_prices = np.diff(closing_prices)
sign_closing_prices = np.sign(diff_closing_prices)
obvs = volumes[1:] * sign_closing_prices
mp.figure('On-Balance Volume', facecolor='lightgray')
mp.title('On-Balance Volume', fontsize=20)
mp.xlabel('Date', fontsize=14)
mp.ylabel('OBV', fontsize=14)
ax = mp.gca()
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_minor_locator(md.DayLocator())
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y'))
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
dates = dates[1:].astype(md.datetime.datetime)
mp.bar(dates, obvs, 1.0, color='dodgerblue',
edgecolor='white', label='OBV')
mp.legend()
mp.gcf().autofmt_xdate()
mp.show()
ary = np.piecewise(源数组,条件序列,取值序列)
a = np.array([70,80,60,30,40])
d = np.piecewise(
a,
[a<60,a==60,a>60],
[-1,0,1]
)
矢量化指的是用数组代替标量来操作数组里的每个元素
import numpy as np
import math as m
a = np.array(3,9).reshape(2,3)
b = np.array(4,10).reshape(2,3)
def foo(x,y):
return m.sqrt(x**2+y**2)
print(foo(a,b)) # 会报错
foo_vec = np.vectorize(foo)
print(foo_vec(a,b)) # 不会报错
# 创建矩阵
np.matrix(
array,
copy = True
)
np.mat(iter_)
# e.g. np.mat('1 2 3;4 5 6;7 8 9')
# 逆矩阵
e = np.mat()
ei = e.I
a = np.array([[],[],[]])
k = a.dot(a) # 矩阵乘法
ai = np.linalg.inv(a) # 逆矩阵
import numpy as np
n = 35
def fibo(n):
return 1 if n<3 fibo(n-1)+fibo(n-2)
print(int((np.mat('1. 1.;1. 0.')**(n-1))[0,0]))
# 矩阵的n-1次方的(1,1)元素即为第n个斐波那契数列元素
a = np.array([10,20,30,40,50])
b = a.clip(min=15,max = 35)
c = a.compress((a>=15)&(a<=35))
d = a.prod() # 累乘
e = a.cumprod
# a: [10 20 30 40 50]
# b: [15 20 30 35 35] 将小于下限的和大于上限的替换为下限和上限
# c: [20 30]
# d: 12000000
# e:
a = np.arange(1,7)
b = np.add(a,a)
c = np.add.reduce(a)
d = np.add.accumulate(a)
e = np.add.outer([10,20,30],a)
f = np.outer([10,20,30],a)
'''
a: [1 2 3 4 5 6]
b: [ 2 4 6 8 10 12]
c: 21
d: [ 1 3 6 10 15 21]
e: [[11 12 13 14 15 16]
[21 22 23 24 25 26]
[31 32 33 34 35 36]]
f: [[ 10 20 30 40 50 60]
[ 20 40 60 80 100 120]
[ 30 60 90 120 150 180]]
'''
a = np.array([20,20,-20,-20])
b = np.array([3,-3,6,-6])
c = np.true_divide(a,b)
d = np.divide(a,b)
e = np.floor(a/b)
f = np.ceil(a/b)
g = np.trunc(a/b)
h = np.around(a/b)
'''
a: [ 20 20 -20 -20]
b: [ 3 -3 6 -6]
c: [ 6.66666667 -6.66666667 -3.33333333 3.33333333]
d: [ 6.66666667 -6.66666667 -3.33333333 3.33333333]
e: [ 6. -7. -4. 3.]
f: [ 7. -6. -3. 4.]
g: [ 6. -6. -3. 3.]
h: [ 7. -7. -3. 3.]
'''
# 合成方波
x = np.linspace(-2*np.pi, 2*np.pi, 1000)
y = np.zeros(1000)
n = 1000
for i in range(1, n+1):
y += 4 / ((2 * i - 1) * np.pi) * np.sin((2 * i - 1) * x)
mp.plot(x, y, label='n=1000')
mp.legend()
mp.show()
对于n阶方阵A,如果存在数a和非零n维列向量x,使得Ax=ax,则称a是矩阵A的一个特征值,x是矩阵A属于特征值a的特征向量
eigvals,eigvecs = np.linalg.eig(A)
A = np.mat(eigvecs)*np.mat(np.diag(eigvals))*np.mat(eigvecs.I)
有一个矩阵M,可以分解为3个矩阵U、S、V,使得U x S x V等于M。U与V都是正交矩阵(乘以自身的转置矩阵结果为单位矩阵)。那么S矩阵主对角线上的元素称为矩阵M的奇异值,其它元素均为0。
M = np.mat('4 11 14;8 7 -2')
U,sv,V = np.lialg.svd(M,full_matrices = False)
S = np.diag(sv)
print(M = U*S*V)
什么是傅里叶变换?
法国科学家傅里叶提出,任何一条周期曲线,无论多么跳跃或不规则,都能表示成一组光滑正弦曲线叠加之和。
傅里叶变换的目的是可将时域(即时间域)上的信号转变为频域(即频率域)上的信号,随着域的不同,对同一个事物的了解角度也就随之改变,因此在时域中某些不好处理的地方,在频域就可以较为简单的处理。这就可以大量减少处理信号存储量。
import numpy.fft as nf
freqs = nf.fftfreq(采样数量,采样周期) 频率序列
nf.fft(原函数值序列) -> 目标函数值序列(复数)
nf.ifft(目标函数值序列(复数))->原函数值序列
案例
import numpy as np
import matplotlib.pyplot as mp
import numpy.fft as nf
x = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
y = np.zeros(1000)
n = 1000
for i in range(1, n + 1):
y_ = 4 / ((2 * i - 1) * np.pi) * np.sin((2 * i - 1) * x)
y += y_
# 针对这组曲线数据,执行fft操作
complex_array = nf.fft(y)
y_ = nf.ifft(complex_array)
mp.subplot(121)
mp.plot(x, y, label='n=1000')
mp.plot(x, y_, label='ifft', linewidth=7,
color='orangered', alpha=0.5)
# 绘制频域图像 水平轴表示fft后所有正弦曲线的频率
# 垂直轴表示fft后所有正弦曲线的能量
# fftfreq(采样数量, 采样周期)
freqs = nf.fftfreq(y.size, x[1] - x[0])
pows = np.abs(complex_array)
mp.subplot(122)
mp.plot(freqs[freqs > 0], pows[freqs > 0],
color='orangered')
mp.legend()
mp.show()
from __future__ import unicode_literals
import numpy as np
import numpy.fft as nf
import matplotlib.pyplot as mp
import scipy.io.wavfile as wf
# 采样率(每秒采样个数) 每个采样位移值
sample_rate, sigs = wf.read('noised.wav')
sigs = sigs / (2**15)
print(sample_rate, sigs.shape)
# 绘制音频时域的:时间/位移图像。
times = np.arange(len(sigs)) / sample_rate
mp.figure('Filter', facecolor='lightgray')
mp.subplot(221)
mp.title('Time Domain', fontsize=16)
mp.ylabel('Signal', fontsize=12)
mp.grid(linestyle=':')
mp.plot(times[:178], sigs[:178],
color='dodgerblue', label='Noised Signal')
mp.legend()
# 基于傅里叶变换,获取音频频域信息,
# 绘制音频频域的:频率/能量图像。
freqs = nf.fftfreq(sigs.size, 1 / sample_rate)
complex_array = nf.fft(sigs)
pows = np.abs(complex_array) # 把负的变正
mp.subplot(222)
mp.title('Frequence Domain', fontsize=16)
mp.ylabel('pow', fontsize=12)
mp.grid(linestyle=':')
mp.semilogy(freqs[freqs > 0], pows[freqs > 0],
color='orangered', label='Noised Freq')
mp.legend()
# 将低能噪声去除后绘制音频频域的:频率/能量图像。
fun_freq = freqs[pows.argmax()] #1000
# 拿到所有噪声的索引
noised_indices = np.where(freqs != fun_freq)[0]
ca = complex_array.copy()
ca[noised_indices] = 0
filter_pows = np.abs(ca)
mp.subplot(224)
mp.ylabel('pow', fontsize=12)
mp.grid(linestyle=':')
mp.plot(freqs[freqs > 0], filter_pows[freqs > 0],
color='orangered', label='Filter Freq')
mp.legend()
# 基于逆向傅里叶变换,生成新的音频信号,
# 绘制音频时域的:时间/位移图像
filter_sigs = nf.ifft(ca)
mp.subplot(223)
mp.ylabel('Signal', fontsize=12)
mp.grid(linestyle=':')
mp.plot(times[:178], filter_sigs[:178],
color='dodgerblue', label='Filter Signal')
mp.legend()
# 重新生成音频文件。
filter_sigs = (filter_sigs * (2**15)).astype('i2')
wf.write('filter.wav', sample_rate,
filter_sigs)
mp.tight_layout()
mp.show()
二项分布
np.random.binomial(n,p,size) # n为尝试n次,p为成功概率,size个随机数
a = np.random.binomial(10,0.3,2000000) == 3
print(len(a))
print(len(a)/2000000)
print(sum(a) / 2000000)
'''
2000000
1.0
0.2671815
'''
超几何分布hypergeometric
np.random.hypergeometric(ngood,nbad,nsample,size)
# 产生size个随机数,每个随机数为在总样本中随机抽取nsample个样本后好样本的个数,总样本由ngood个好样本和nbad个坏样本组成
正态分布
np.random.normal(size)
np.random.normal(loc = 1,scale = 10, size) # 均值为1,标准差为10
import numpy as np
prices = np.array([92,83,71,92,40,12,64])
volumes = np.array([100,251,4,12,709,34,75])
names =
['Product1','Product2','Product3','Product4','Product5','Product6','Product7']
ind = np.lexsort((volumes*-1, prices)) # 先按价格,再按销量
print(ind)
for i in ind:
print(names[i], end=' ')
a = np.array([1, 2, 4, 5, 6, 8, 9])
b = np.array([7, 3])
c = np.searchsorted(a, b)
print(c)
# [5 2]
d = np.insert(a, c, b)
print(d)
# [1 2 3 4 5 6 7 8 9]
import numpy as np
import scipy.interpolate as si
import matplotlib.pyplot as mp
# 找一组散列点坐标
min_x = -50
max_x = 50
dis_x = np.linspace(min_x, max_x, 15)
dis_y = np.sinc(dis_x)
mp.scatter(dis_x, dis_y, marker='D', s=60)
# 使用插值,使散列的点连续化
linear = si.interp1d(dis_x, dis_y, kind='linear')
x = np.linspace(min_x, max_x, 1000)
y = linear(x)
mp.plot(x, y, label='linear', alpha=0.3)
# 三次样条插值
cubic = si.interp1d(dis_x, dis_y, kind='cubic')
x = np.linspace(min_x, max_x, 1000)
y = cubic(x)
mp.plot(x, y, label='cubic')
mp.show()
def f(x):
return 2 * x ** 2 + 3 * x + 4
a, b = -5, 5
import scipy.integrate as si
# 利用quad求积分 给出函数f,积分下限与积分上限[a, b] 返回(积分值,最大误差)
area = si.quad(f, a, b)[0]
print(area)
import scipy.ndimage as sn
import scipy.misc as sm
# 读图片
original = sm.imread('',True)
# 高斯模糊
median = sn.median_filter(original,21)
# 角度旋转
rotate = sn.rotate(original,45)
# 边缘识别
prewitt = sn.prewitt(original)
import numpy as np
# 终值 = np.fv(利率, 期数, 每期支付, 现值)
# 将1000元以1%的年利率存入银行5年,每年加存100元,
# 到期后本息合计多少钱?
fv = np.fv(0.01, 5, -100, -1000)
print(round(fv, 2))
# 现值 = np.pv(利率, 期数, 每期支付, 终值)
# 将多少钱以1%的年利率存入银行5年,每年加存100元,
# 到期后本息合计fv元?
pv = np.pv(0.01, 5, -100, fv)
print(pv)
# 净现值 = np.npv(利率, 现金流)
# 将1000元以1%的年利率存入银行5年,每年加存100元,
# 相当于一次性存入多少钱?
npv = np.npv(0.01, [
-1000, -100, -100, -100, -100, -100])
print(round(npv, 2))
fv = np.fv(0.01, 5, 0, npv)
print(round(fv, 2))
# 内部收益率 = np.irr(现金流)
# 将1000元存入银行5年,以后逐年提现100元、200元、
# 300元、400元、500元,银行利率达到多少,可在最后
# 一次提现后偿清全部本息,即净现值为0元?
irr = np.irr([-1000, 100, 200, 300, 400, 500])
print(round(irr, 2))
npv = np.npv(irr, [-1000, 100, 200, 300, 400, 500])
print(npv)
# 每期支付 = np.pmt(利率, 期数, 现值)
# 以1%的年利率从银行贷款1000元,分5年还清,
# 平均每年还多少钱?
pmt = np.pmt(0.01, 5, 1000)
print(round(pmt, 2))
# 期数 = np.nper(利率, 每期支付, 现值)
# 以1%的年利率从银行贷款1000元,平均每年还pmt元,
# 多少年还清?
nper = np.nper(0.01, pmt, 1000)
print(int(nper))
# 利率 = np.rate(期数, 每期支付, 现值, 终值)
# 从银行贷款1000元,平均每年还pmt元,nper年还清,
# 年利率多少?
rate = np.rate(nper, pmt, 1000, 0)
print(round(rate, 2))