跳到主要内容

· 3 分钟阅读
Allen Ma

发现问题

当我在写文章金融数据分析(一)python预热中的项目二:计算手机销量年增长率的时候,出现过如下报错:在这里插入图片描述 看着结果是已经跑出来了,但是前面那一长串着实然人看着不舒心。再加上==Process finished with exit code 1==让我更加确信这里面有喵腻。

如图所示,错误提示为

Traceback (most recent call last):
IndexError: list index out of range

查找原因

经过查找相关资料我知道了list index out of range错误出现的原因主要有两个。

一个可能是下标超出范围, 一个可能是list是空的,没有一个元素

接下来我来用一个例子来说明一下这个抽象的说法: 打开idle输入以下代码

>>> li = [1,2,3,4,5,6,7,8,9,10]
>>> #索引[0,1,2,3,4,5,6,7,8,9 ]
>>> li[8]
9
>>> li[10]
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
li[10]
IndexError: list index out of range
>>> # 像这样,索引值超出了循环,也叫越界

尝试解决

尝试第一次解决: 加上try...except模块

for s in linestr:
try:
L = s.split('\t')
print(L[0], end=" ")
print(isBigGrowth(L, 0.3))
except:
print('运行失败')

运行结果: 在这里插入图片描述可以看到,让人头疼的红色错误提示已经没有了,而且==Process finished with exit code 0== 问题看起来已经解决了,但是我们自己知道,这只是表面现象,刚才的问题其实并没有解决,而是我们选择不显示了。 治标不治本!

尝试第二次解决: 我注意到,程序是在最后一条抛异常了。手机公司是能够全部分析判断完的,那会不会是第二个错误原因呢?有为空的list。 所以我对源文档进行了检查,发现在末尾果然存在一行空行。 在这里插入图片描述 在删除末尾的空行之后再运行程序: 在这里插入图片描述 这下完美了! 舒服=。=

总结

在处理数据之前,检查所分析的数据格式是非常重要的!

· 6 分钟阅读
Allen Ma

关于修改win10非家庭版系统cmd中用户名方法的实践

相信很少有朋友和我一样 在购买一台新电脑或者重装系统后 心中的激动之情溢于言表 控制不住想给新宝贝起一个全世界独一无二的名字 不幸的是 我们所谓得到的欣喜 只不过是大脑为了说服我们通过一段时间的努力去获得回报的机制 这种回报让我们感到欣喜(爱情来的猛烈) 但是它会悄悄地溜走 把我们留在电脑前面对那个“不可描述”的用户名QAQ 在这里插入图片描述

正文

为了解决我曾经犯下的错误,在网络上向各路大佬求助,但弟子愚钝,犯下不少错误,特地在此记录,为有同样需求的朋友避避坑。

方法

更改==win10非家庭版==中==cmd==中用户名的方法:

我们注册原始账号时win10系统会替我们创建一个新账户,我们可以在C:\Users这个路径下看到一个熟悉的名字(那个你做梦都想换掉的名字)。 在这里插入图片描述

好的,现在我们找到源头了。 然后我尝试了右键点击原始名字文件夹,寻找“重命名”选项。 如果你和我一样尝试了,很遗憾,此路不通。 系统好像不打算给你改正错误的机会,“重命名”不存在。

遇到困难,奥利给!找原因! 由于我们采用的就是这个用户名登录的系统,系统为了避免混乱,才触发了这个保护机制。 这时我们需要一个新的用户来替我们完成这项操作,理由如下:

我认为可以简化为一个经典的篮子问题: 现在有两个篮子,篮子A里放的小球1,篮子B里放的小球2。现在我们想把这两个篮子你的小球互换,需要怎样操作? 第一步,取一个新空篮子C。 第二步,将小球1移动到篮子C中。 第三步,将小球2移动到空出来的篮子A中。 最后,将小球1移动到篮子B中。

所以,我们首先需要一个第三方账户。这也是为什么是==win10非家庭版==的原因,据我所知这个版没有本地用户和组这个功能,节哀。

第一步,找到一个新账户,人性化的win给我们内置了一些,比如我打算用的Administrator,但是这些账户默认是禁用的,我们需要手动启用。 Administrator账户启用方法: 右击此电脑,然后找到管理并点击,找到本地用户和组,依次点开用户Administrator,查看它的属性,就会出现个小框,可以看到,账户已禁用那个划了√,去掉这个√,点击确定,就可在开机时选择使用Administrator登录了。

在这里插入图片描述

退出当前账号,这个通过开始里的注销可以做到。

在这里插入图片描述 注销后在次开机时选择使用Administrator登录,登陆后进入路径:C:\Users 再次右键想改掉的用户名,会惊奇的发现重命名出现了!那就改成心仪的名字吧。(由于我改过,就不示范了) 在这里插入图片描述

然后回到桌面,按win+R调出运行窗口,输入regedit搜索,就可打开注册表编辑器,然后在搜索框输入:

    计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersio\ProfileList

找到ProfileList文件夹其中最长的一个包,然后右键其中的ProfileImagePath,选择修改,如图所示

在这里插入图片描述

然后在编辑字符串里将名字改成C盘那个重命名的名字确定就可以了。

在这里插入图片描述 最后,换回我们以前的账户,注销Administrator之后开机选择登陆我们自己的那个账户就可以了。

在cmd中查看成果: 在这里插入图片描述

==在更改用户名之后,我们以前设置的环境变量和系统变量需要手动更新,不然会出现程序无反应或者文件无法打开的情况。请一定注意!!!==

· 3 分钟阅读
Allen Ma

项目二:计算股票的超额收益率

设计一个程序,计算股票的季收益率和年收益率,并计算单支股票收益率相对同一时期股票市场平均收益率的超额收益率(即相对收益率)。

本项目采用tushare的Python SDK 获取数据 具体方法另开新篇。

# -*- coding: utf-8 -*-
"""
Created on Sat Sept 19 9:30:36 2020

@author: mly
"""
import tushare as ts
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import ticker

plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签

startday = '2015-01-01'
endday = '2020-04-01'
tscode = '600519'
tsindx = 'sh'
df1 = ts.get_k_data(tscode, start = startday, end = endday, ktype = 'M')
df2 = ts.get_k_data(tsindx, start = startday, end = endday, ktype = 'M')
df1.to_excel('600519.xlsx',index=False)
df2.to_excel('sh.xlsx',index=False)
df1=pd.read_excel('600519.xlsx',dtype={'code':'str'})
df2=pd.read_excel('sh.xlsx',dtype={'code':'str'})
df = df2[['date', 'close']].copy()
df.rename(columns={'close': 'indclose'}, inplace = True)
df = pd.merge(df[['date', 'indclose']],
df1[['date', 'close']], on = 'date', how = 'left')
df.fillna(method = 'ffill',inplace=True) #先后向填充
df.fillna(method = 'bfill',inplace=True) # 再前向填充
# 计算月收益率和累计收益率
df['stk_log_ret'] = np.round(np.log(df['close']/df['close'].shift(1)), 4)
df['ind_log_ret'] = np.round(np.log(df['indclose']/df['indclose'].shift(1)), 4)
df['stk_log_ret'].fillna(method = 'bfill',inplace=True) # 再前向填充
df['ind_log_ret'].fillna(method = 'bfill',inplace=True) # 再前向填充
df['xd_ret']=df['stk_log_ret']-df['ind_log_ret']
df['xd_ret'].fillna(method = 'bfill',inplace=True) # 再前向填充

df_list=list(df['stk_log_ret'].values)
print(df['stk_log_ret'].values)

ret_year=[]
ret_quarter=[]
for i in range(len(df_list)//3):
ret_quarter.append(np.round(df_list[3*i]+df_list[3*i+1]+df_list[3*i+2],4))
ret_quarter1=pd.Series(ret_quarter)

for n in range(len(ret_quarter)//4):
ret_year.append(np.round(ret_quarter[4*n]+ret_quarter[4*n+1]+ret_quarter[4*n+2]+ret_quarter[4*n+3],4))
ret_year1=pd.Series(ret_year)

quarter_list=[]
year=[]
df_index=list(df.date)
for value in df_index:
tempvalue = value.split("-")
if tempvalue[1] in ['01','02','03']:
quarter_list.append(tempvalue[0] + "Q1")
year.append(tempvalue[0])
elif tempvalue[1] in ['04','05','06']:
quarter_list.append(tempvalue[0] + "Q2")
year.append(tempvalue[0])
elif tempvalue[1] in ['07', '08', '09']:
quarter_list.append(tempvalue[0] + "Q3")
year.append(tempvalue[0])
elif tempvalue[1] in ['10', '11', '12']:
quarter_list.append(tempvalue[0] + "Q4")
year.append(tempvalue[0])

quarter_set = set(quarter_list)
quarter_list = list(quarter_set)
quarter_list.sort()

year_set = set(year)
year = list(year_set)
year.sort()
year.pop() #由于2020还没有完整,所以删除

ymajorFormatter = ticker.FormatStrFormatter('%.2f%%') # 设置 y 轴标签文本的格式

fig = plt.figure(figsize=(14, 24))
ax1 = fig.add_subplot(3, 1, 1)
fig.subplots_adjust(bottom = 0.2)
plt.ylabel('季度收益率')
plt.xticks(rotation = 60)
ax1.yaxis.set_major_formatter(ymajorFormatter) # 显示百分比
ax1.plot(quarter_list, ret_quarter1*100, '-cs', lw = 1.5, label = tscode+' 季度收益率')
ax1.legend(loc = 'upper left')

ax2 = fig.add_subplot(3, 1, 2)
plt.ylabel('年收益率')
plt.xticks(rotation = 60)
ax2.yaxis.set_major_formatter(ymajorFormatter) # 显示百分比
ax2.plot(year, ret_year1*100, '-gp', lw = 1.5, label = tscode+' 年收益率')
ax2.legend(loc = 'upper left')

ax3 = fig.add_subplot(3, 1, 3)
plt.ylabel('相对收益率')
plt.xticks(rotation = 60)
ax3.yaxis.set_major_formatter(ymajorFormatter) # 显示百分比
ax3.plot(df.date, df['xd_ret']*100, '-rp', lw = 1.5, label = tscode+' 相对市场收益率')
ax3.legend(loc = 'upper left')
plt.show()

运行结果:

在这里插入图片描述

· 1 分钟阅读
Allen Ma

案例(一)python预热

项目三:爬取某省的大学排名

输入某省名称,从上海交通大学研发的“软科中国最好大学排名2020”(http://www.zuihaodaxue.cn/zuihaodaxuepaiming2020.html)爬取数据,输出该省2020年的大学排名。 输入: 广东 输出:在这里插入图片描述

import requests
from bs4 import BeautifulSoup
import bs4


def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""


def fillUnivList(ulist, html):
soup = BeautifulSoup(html, "html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr, bs4.element.Tag):
tds = tr('td')
ulist.append([tds[0].string, tds[1].string, tds[2].string])


def printUnivList(ulist, num, place):
tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
print("{:^10}\t{:^6}\t{:^10}".format("排名", "学校名称", "省市"))
for i in range(num):
u = ulist[i]
if u[2] == place:
print(tplt.format(u[0], u[1], u[2], chr(12288)))
# print("{:^10}\t{:^6}\t{:^10}".format(u[0], u[1], u[2]))
else:
continue

def main():
uinfo = []
url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2019.html'
html = getHTMLText(url)
fillUnivList(uinfo, html)
printUnivList(uinfo, 549, "广东") # 20 univs


main()

运行结果: 在这里插入图片描述

· 2 分钟阅读
Allen Ma

项目三:计算一年内以MACD指标买入卖出信号进行股票交易而产生的收益

设计一个程序,计算一年内以MACD指标买入卖出信号进行股票交易而产生收益。MACD交易信号为:快线从下往上穿越慢线是当天买入信号,快线从上往下穿越慢线是当天卖出。假设买入和卖出价格为发出交易信号当天的收盘价格。

# -*- coding: utf-8 -*-
"""
Created on Sun Sept 20 9:04:59 2020

@author: mly
"""
import numpy as np
import datetime
import pandas_datareader.data as web

start = datetime.datetime(2018, 6, 1)
end = datetime.datetime.today()
stock_name = '601318.ss'
df = web.DataReader(stock_name, 'yahoo', start, end)


def df_EMA(prices, N):
ema = []
k = len(prices)
if k > 0:
for i in range(k):
if i == 0:
ema.append(prices[i])
else:
ema.append((2 * prices[i] + (N - 1) * ema[i - 1]) / (N + 1))
return (ema)


def df_MACD(df, short=12, long=26, M=9):
fast = df_EMA(df['Adj Close'].values, short)
slow = df_EMA(df['Adj Close'].values, long)
if len(fast) > 0: # & len(slow)>0:
df['Fast'] = np.round(np.array(fast), 2)
df['Slow'] = np.round(np.array(slow), 2)
df['DIF'] = df['Fast'] - df['Slow']
df['DEA'] = np.round(np.array(df_EMA(df['DIF'].values, M)), 2)
df['MACD'] = 2 * (df['DIF'] - df['DEA'])
df['tim'] = df['Close'] / df['Open']
return (df)
else:
print('no data,no MACD')


times0 = 1
marker = 0
df_MACD(df, 12, 26, 9)
for i in df.itertuples(index=True, name='df'):
if getattr(i, 'DIF') > 0 and marker == 0:
times0 = times0 * getattr(i, 'tim')
marker = 1
elif getattr(i, 'DIF') > 0 and marker == 1:
times0 = times0 * getattr(i, 'tim')
marker = 1
elif getattr(i, 'DIF') == 0 and marker == 1:
times0 = times0 * getattr(i, 'tim')
marker = 0
elif getattr(i, 'DIF') < 0 and marker == 1:
times0 = times0 * getattr(i, 'tim')
marker = 0
else:
continue

print(times0)

运行结果:

在这里插入图片描述 看来历史上如果按照这个方法买股票,至少不会亏qwq,233333333...

· 2 分钟阅读
Allen Ma

项目二:亚马逊商品信息自定义获取,可自定商品名称和爬取页数

# -*- coding: utf-8 -*-
"""
Created on Thur Sept 17 15:56:36 2020

@author: mly
"""
import requests
import re
import pandas as pd

ilt = []
iltl = []


def getHTMLText(url):
try:
kv = {'user-agent': 'Mozilla/5.0',
'Cookie': 'x-wl-uid=1+EeiKz9a/J/y3g6XfXTnSbHAItJEus3oQ6Gz+T/haur7dZfkNIgoxzMGwviB+42iWIyk9LR+iHQ=;'
' session-id=457-2693740-8878563; ubid-acbcn=459-5133849-3255047; lc-acbcn=zh_CN; i18n-prefs=CNY; '
'session-token="8n/Oi/dUCiI9zc/0zDLjB9FQRC6sce2+Tl7F0oXncOcIYDK4SEJ7eek/Vs3UfwsRchW459OZni0AFjMW+'
'9xMMBPSLM8MxLNDPP1/13unryj8aiRIZAE1WAn6GaeAgauNsijuBKKUwwLh8Dba7hYEjwlI1J6xlW0LKkkyVuApjRXnOsvdYr'
'X8IURVpOxDBnuAF9r7O71d/NPkIQsHy7YCCw=="; session-id-time=2082787201l;'
' csm-hit=tb:s-85XYJNXFEJ5NBKR0JE6H|1566558845671&t:1566558845672&adb:adblk_no'}
r = requests.get(url, headers=kv, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""


def parsePage(ilt, html):
try:
plt = re.findall('<span class="a-offscreen">¥(.*?)</span>', html)
#print(plt)
tlt = re.findall('<span class="a-size-base-plus a-color-base a-text-normal" dir="auto">(.*?)</span>', html)
#print(tlt)
for i in range(len(tlt)):
ilt.append([plt[i], tlt[i]])
except:
return ""


def printGoodsList(ilt):
column = ["序号", "价格", "商品名称"]
count = 0
for g in ilt:
count = count + 1
iltl.append([count, g[0], g[1]])
test = pd.DataFrame(columns=column, data=iltl)
test.to_csv('finance.csv', encoding='utf_8_sig', index=False)


def main():
goods = input("请输入商品名称:")
depth = int(input("请输入想查看到的页码:"))
start_url = 'https://www.amazon.cn/s?k=' + goods
infoList = []
for i in range(depth):
try:
url = start_url + '&page=' + str(i + 1)
html = getHTMLText(url)
parsePage(infoList, html)
except:
continue
printGoodsList(infoList)

main()

运行时可自定义商品名称和爬取页数:

在这里插入图片描述 爬取结果:

在这里插入图片描述

· 2 分钟阅读
Allen Ma

项目一:不同按揭额度下还款总额的变化趋势

设计一个程序,比较在相同贷款额度(如100万元人民币)但不同按揭(月)额度(至少计算三种按揭额度)的情况下各自还款总额的变化趋势。

# -*- coding: utf-8 -*-
"""
Created on Fri Sept 18 9:50:37 2020

@author: mly
"""
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签

dp_rate = 0.015 # 2015 年 10 月人民银行发布的 1 年期存款利率
rates = [0.046, 0.05, 0.054] # 2、4、6年贷款利率
loan_pv = 100 # 单位:万元
loan_nper = [2, 4, 6] # 单位:年
repay_pmt = np.zeros(len(loan_nper)) # 按揭月供金额
repay_fv = np.zeros(len(loan_nper)) # 实际还款未来终值
for n in range(len(loan_nper)):
repay_pmt[n] = round(np.pmt(rates[n]/12, loan_nper[n]*12, loan_pv)*10000, 2)
repay_fv[n] = round(np.fv(dp_rate/12, loan_nper[n]*12, repay_pmt[n], 0), 2)

fig, ax = plt.subplots(figsize = (9,6))
ax.plot(loan_nper, np.round(repay_fv/10000, 2), marker= 'o', label = '不同还款年限的按揭终值')
ax.set(xticks = loan_nper, xlabel = '还款年限', ylabel = '100 万按揭终值')
for i in range(len(loan_nper)):
ax.text(loan_nper[i], np.round(repay_fv/10000, 2)[i],
np.round(repay_fv/10000, 2)[i], ha='left', fontsize=20)
ax.legend()
plt.show()

运行结果:

在这里插入图片描述

· 3 分钟阅读
Allen Ma

项目一:当当网店商品爬虫——爬虫类书籍为例

此案例是运用bs4库find方法对相关内容进行抓取。

 -*- coding: utf-8 -*-
import requests
import csv
from bs4 import BeautifulSoup as bs
#获取网页信息
def request_dandan(url):
try:
#用户代理
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36'}
r = requests.get(url,headers=headers)
if r.status_code == 200:
return r.text
except requests.RequestException:
return None

#存放列名
def write_item_to_file():
csv_file = open('dangdang.csv', 'w', newline='', encoding="utf-8")
writer = csv.writer(csv_file)
writer.writerow(['书名','购买链接','纸质书价格','电子书价格','电子书链接','书的详细介绍','书的封面地址','评论地址','作者','出版时间','出版社'])
print('列名已成功放入CSV中')
#解析网页并写入csv文件中
def parse_dangdang_write(html):
csv_file = open('dangdang.csv', 'a', newline='')
writer = csv.writer(csv_file)
#解析网页
soup = bs(html, 'html.parser')
class_tags = ['line'+str(x) for x in range(1,61)]
for class_tag in class_tags:
li = soup.find('li',class_=class_tag)
book_name = li.find('a',class_='pic').get('title') # 书名
paperbook_price = li.find('span',class_='search_now_price').text #纸质书价格
try:
ebook_price = li.find('a',class_='search_e_price').find('i').text #电子书价格
ebook_link = li.find('a',class_='search_e_price').get('href') #电子书链接
except:
ebook_price = ''
ebook_link = ''
detail = li.find('p',class_='detail').text #书的详细介绍
book_purchase_link = li.find('a',class_='pic').get('href') #每本书的详细购买链接
book_cover_link = li.find('a',class_='pic').find('img').get('src')#书的封面地址
comment_link = li.find('a',class_='search_comment_num').get('href') #评论地址
author = li.find('p',class_='search_book_author').find('span').text # 书的作者
public_time = li.find('p',class_='search_book_author').find('span').next_sibling.text[2:]#出版时间
public = li.find('p',class_='search_book_author').find('span').next_sibling.next_sibling.text[3:]#出版社
writer.writerow([book_name, book_purchase_link, paperbook_price, ebook_price, ebook_link, detail, book_cover_link, comment_link, author, public_time, public])
#writer.writerow(['书名', '购买链接', '纸质书价格', '电子书价格', '电子书链接', '书的详细介绍', '书的封面地址', '评论地址', '作者', '出版时间', '出版社'])
csv_file.close()

if __name__ == '__main__':
write_item_to_file()
for page in range(1, 10): # 爬取9页数据存入csv文件
url = 'http://search.dangdang.com/?key=python%C5%C0%B3%E6&act=input&page_index=' + str(page)
html = request_dandan(url) # 获取网页信息
parse_dangdang_write(html) # 解析网页并写入csv文件中
print('第{}页数据成功放入CSV中'.format(page))

运行结果: 在这里插入图片描述 在这里插入图片描述

· 6 分钟阅读
Allen Ma

项目一:

案例详情

王先生是一家高科技公司高级工程师,近期计划在广州购置一套总价为1000万元的住房,由于自有资金有限无法全额付款,拟向当地C银行申请住房按揭贷款。 假定你是C银行负责拓展住房按揭贷款业务的客户经理,在评估了王先生的还款能力后,制定了如下的贷款方案:贷款本金为600万元,贷款期限是30年,贷款利率是按照5年期以上贷款市场报价利率(LPR)上浮5个基点,即是贷款利率是4.9%。但是,针对该贷款有以下两种还款方式可供王先生选择: (1)等额本息还款,具体是指在贷款利率水平不变的情况下,王先生作为借款人每月还款的本金和利息之和保持不变; (2)等额本金还款,具体是指在贷款利率水平不变的情况下,王先生每月还款的本金固定不变,支付的利息则是逐月递减。 为了让王先生清楚了解这两种还款方式的差异性,并且借助图形展示贷款还款情况,你需要运用Python完成3项编程任务。

编程任务

(1)假定选择了等额本息还款,请计算王先生需要每月偿还的金额,以及每月偿还金额中的本金额和利息额,并且对相关数据可视化。 (2)为了能够让王先生知道在等额本息的规则下贷款利率变动对每月还款金额的影响,你采用了如下的敏感性分析:即是模拟出当贷款利率从2%/年增加至8%/年时,王先生每月偿还金额的变化情况,并且进行可视化展示。 (3)假定采用等额本金还款规则,贷款利率依然是4.9%/年,分别计算王先生每月偿还金额中的本金部分和利息部分,并且对结果进行可视化展示。

开始编程:

# -*- coding: utf-8 -*-
"""
Created on Tue Sept 22 8:47:37 2020

@author: mly
"""
import numpy as np
import matplotlib.pyplot as plt

# (1)
dp_rate = 0.049 # 贷款利率
loan_pv = 6000000 # 贷款本金 单位:元
loan_year = 30 # 贷款期限(年)
repay_mon = -round(np.pmt(dp_rate / 12, loan_year * 12, loan_pv)) # 每月还款额
interestList = [] # 每期利息的列表
capitalList = [] # 每期需还本金的列表
monthList = [x for x in range(loan_year * 12)] # 还款期数列表
rest = loan_pv #定义剩余代还本金
for i in range(loan_year * 12):
interest = round(rest * (dp_rate / 12)) # 每期的利息
interestList.append(interest) # 将每期的利息插入利息的列表
repay_capital = repay_mon - interest # 每期需还的本金
capitalList.append(repay_capital) # 将每期需还本金插入需还本金的列表
rest = round(rest - repay_capital) # 剩余待还本金
# 绘制堆积柱状图
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False #显示中文
plt.bar(monthList, capitalList, align="center", color="#EE9A49", label='每月本金额')
plt.bar(monthList, interestList, align="center", bottom=capitalList, color="#000000", label='每月利息额')
plt.xlabel('还款期限(月)')
plt.ylabel('每月还款额(元)')
plt.title('等额本息还款图')
plt.legend()
plt.show()

#(2)
# 年利率2%~8%的敏感性分析
rates = [x / 100 for x in range(2, 9, 1)] # 贷款年利率
repaymentNL = []
for n in range(len(rates)):
repaymentN = -round(np.pmt(rates[n] / 12, loan_year * 12, loan_pv)) # 每月还款额
repaymentNL.append(repaymentN)
plt.plot(rates, repaymentNL, lw=6,color="#EE9A49", label="每月还款额")
plt.fill_between(rates, 0, repaymentNL, facecolor="#000000", alpha=1)
plt.xlabel('年利率')
plt.ylabel('每月还款额(元)')
plt.title('年利率在2%~8%变化时每月还款额变化趋势')
plt.legend()
plt.show()

# 等额本金
repay_capitalX = loan_pv / (loan_year * 12) # 等额本金每期还款的本金额
repay_capitalXL = [repay_capitalX for i in range(loan_year * 12)]
restX = loan_pv # 初始待还本金
interestXList = [] # 每期利息的列表
repaymentXL = [] # 每期需还本金的列表
for i in range(loan_year * 12):
interestX = round(restX * (dp_rate / 12)) # 每期的利息
interestXList.append(interestX) # 将每期的利息插入利息的列表
restX = round(restX - repay_capitalX) # 剩余待还本金
repaymentX = interestX + repay_capitalX # 每期还款额
repaymentXL.append(repaymentX)
# 绘制堆积柱状图
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(monthList, repaymentXL)
plt.bar(monthList, repay_capitalXL, align="center", color="#000000", label='每期本金额')
plt.bar(monthList, interestXList, align="center", bottom=repay_capitalXL, color="#EE9A49", label='每期利息额')
plt.xlabel('还款期限(月)')
plt.ylabel('每期还款额(元)')
plt.title('等额本金还款图')
plt.legend()
plt.show()

结果展示

等额本息还款图 年利率在2%~8%变化时每月还款额变化趋势 等额本金还款图

· 5 分钟阅读
Allen Ma

项目二:

案例详情

A公司是总部位于广州的一家公募基金管理公司,在公司对外发行的全部基金产品中,有一只名为“新金融股票型基金”,该基金在投资策略上是精选具有核心竞争优势、持续增长潜力且估值水平相对合理的A股市场金融股。截止到2020年5月末,该基金重仓的股票包括浦发银行(600000)、招商银行(600036)、海通证券(600837)、华泰证券(601688)、中国平安(601318)、中国太保(601601)。 假定你是A公司的一位基金经理助理,日常的工作就是协助“新金融股票型基金”的基金经理跟踪并分析已投资的股票。根据基金经理的要求,你需要运用Python完成3项编程任务。

编程任务

(1)获取6只股票在2014年1月1日至2020年5月31日期间的收盘价,计算每只股票的日收益率、年化平均收益率、年化收益波动率,计算日收益率时需用到自然对数; (2)针对这6只股票构建投资组合,随机生成包括每只股票配置权重的一个数组(权重合计为1),并且计算以该权重配置的投资组合年化平均收益率、年化收益波动率; (3)针对6只股票,随机生成2000组不同的股票配置权重数组,以此计算出相对应的2000个不同的投资组合年化平均收益率、年化收益波动率,并且以散点图的方式绘制在横坐标为年化收益波动率、纵坐标为年化平均收益率的坐标轴中。

开始编程:

# -*- coding: utf-8 -*-
"""
Created on Wed Sept 23 8:59:40 2020

@author: mly
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['KaiTi']
mpl.rcParams['axes.unicode_minus'] = False
stock_price=pd.read_excel('期末案例二.xlsx', sheet_name= "期末案例",header=0,index_col=0) #导入外部数据
stock_price=stock_price.dropna()
#(stock_price/stock_price.iloc[0]).plot(figsize=(9,6),grid=True) #将股价按照2014年首个交易日进行归1处理并且可视化
stock_return=np.log(stock_price/stock_price.shift(1)) #计算股票的日收益率
stock_return=stock_return.dropna() #删除缺失值所在的行
return_mean=stock_return.mean()*252 #计算股票的平均年化收益率
print('2014年至2020年5月的日收益率\n',stock_return.round(6)) #保留小数点后6位
print('2014年至2020年5月的年化平均收益率\n',return_mean.round(6)) #保留小数点后6位
return_volatility=stock_return.std()*np.sqrt(252) #计算股票的年化收益波动率
print('2014年至2020年5月的年化收益波动率\n',return_volatility.round(6))

#任务2
x=np.random.random(len(return_mean.index)) #从均匀分布中随机抽取6个从0到1的随机数
w = x / np.sum(x) # 生成随机权重的一个数组
return_cov=stock_return.cov()*252 #计算每只股票收益率之间的协方差
print(return_cov)
return_corr=stock_return.corr() #计算每只股票收益率之间的相关系数
print(return_corr)
Rp=np.dot(return_mean,w) #计算投资组合的年化收益率
Vp=np.sqrt(np.dot(w,np.dot(return_cov,w.T))) #计算投资组合的年化收益波动率
print('用随机生成的权重计算得到投资组合的年化收益率',round(Rp,6))
print('用随机生成的权重计算得到投资组合的年化收益波动率',round(Vp,6))

#任务3
x_2000=np.random.random((len(return_mean.index),2000)) #从均匀分布中随机抽取6行、2000列的0到1的随机数
w_2000=x_2000/np.sum(x_2000,axis=0) #生成包含2000组随机权重的数组
Rp_2000=np.dot(return_mean,w_2000) #计算投资组合不同的2000个收益率
Vp_2000=np.zeros_like(Rp_2000) #生成存放投资组合2000个不同收益波动率的初始数组
for i in range(len(Rp_2000)):
Vp_2000[i] = np.sqrt(np.dot((w_2000.T)[i], np.dot(return_cov, w_2000[:, i])))
plt.figure(figsize=(9,6))
plt.scatter(Vp_2000,Rp_2000)
plt.xlabel(u'波动率',fontsize=13)
plt.ylabel(u'收益率',fontsize=13,rotation=90)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.title(u'投资组合收益率与波动率的关系', fontsize=13)
plt.grid('True')
plt.show()

结果展示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述