Python—看我分析下已经退市的 可转债 都有什么特点

news2025/1/24 17:32:29

分析

需求分析

  • 可转债退市原因的种类与占比是多少

  • 强赎非强赎导致的退市可转债 存续时间 维度占比

  • 强赎非强赎导致的退市可转债 发行资金 规模占比

  • 强赎非强赎导致的退市可转债 各个评级 的占比

  • 强赎非强赎导致的退市可转债 各个行业(一级行业) 的占比

程序环境分析

  • 需要依赖的三方代码库:  

    • requests(处理http请求)

    • pyecharts(图表显示)

    • pandas(数据表处理)

    • BeautifulSoup(html文件解析)

  • 抓取数据的网站

    • 集思录(www.jisilu.cn/)

程序逻辑分析

  • 通过 http请求 抓取已退市可转债的列表

  • 获取列表中的每个转债代码,通过 http请求 访问转债详情页面,通过BeautifulSoup库提供的方法 获取到债券评级与行业

  • 获取列表中的(转债代码、转债名称、发行规模、存续年限、退市原因、债券评级、行业)字段,存入到csv文件中

    • 存入到csv文件是因为后面要做各个维度的数据分析,如果不存到文件中,后面数据分析中一但出现一点错误,就又得重新去网站抓取数据,比较麻烦

  • 读取csv文件中的数据,用pandas转成表格,按退市原因分组计数,用pyecharts做成饼图展示

  • 读取csv文件中的数据,用pandas转成表格,按强赎与非强赎中的存续时间分组计数,用pyecharts做成饼图

  • 读取csv文件中的数据,用pandas转成表格,按强赎与非强赎中的发行资金规模分组计数(从大到小排序,取前15),用pyecharts做成柱形图

  • 读取csv文件中的数据,用pandas转成表格,按强赎与非强赎中的债券评级分组计数,用pyecharts做成饼图

  • 读取csv文件中的数据,用pandas转成表格,按强赎与非强赎中的债券行业分组计数,用pyecharts做成柱状图

实现代码

编写http请求方法

import pandas as pd
from bs4 import BeautifulSoup
from pyecharts.charts import Bar, Pie
from pyecharts import options as opts


def get_request(url):
    # 设置请求头,防止部分网站对请求头做拦截 
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36"
    }
    try:
        resp = requests.get(url, headers=headers)
        resp.encoding="utf-8"
        if resp.status_code == 200:
            return resp.text
    except Exception as e:
        print("http请求出错:",e)
        return None
 

爬取债券详情页,取 债券评级与行业 (列表页面中没有这两个)

def assemble_grade(resp):
    resp_json=json.loads(resp)
    datas=resp_json["rows"]
    if datas is None:
        return None

    dataList=[]
    for data in datas:
        # 转债代码、转债名称、发行规模、存续年限、退市原因、债券评级
        bond_id=data["cell"]["bond_id"]
        bond_nm=data["cell"]["bond_nm"]
        orig_iss_amt=data["cell"]["orig_iss_amt"]
        listed_years=data["cell"]["listed_years"]
        delist_notes=data["cell"]["delist_notes"]

        #获取详情
        grade,indusity=parse_html("https://www.jisilu.cn/data/convert_bond_detail/%s" %bond_id)
        print("当前可转债是:%s,评级是:%s,行业是:%s" %(bond_nm,grade,indusity))

        dataList.append(",".join([bond_id,bond_nm,orig_iss_amt,listed_years,delist_notes,grade,indusity]))

        #防止访问过快,网站拦截,睡5秒
        time.sleep(2)

    return dataList
 

将抓取的数据存入csv文件中

def write_csv(data):
    if not data:
        print("当前要写入的数据为空")
    with open("bonds.csv", "w", encoding="utf-8") as f:
        f.write("\n".join(data))
 

读取csv文件的数据,用做分析

'''
type 1全部  2强赎  3非强赎
'''
def read_csv(type):
    dataList=[]
    with open("bonds.csv", "r", encoding="utf-8") as f:
        lines=f.readlines()
        for line in lines:
            line=line.replace("\\n","")
            data=line.split(",")

            # 排除可交换债
            if data[1].endswith("EB"):
                continue

            industry=data[6].split("-")[0]
            year=assemble_year(data[3])

            if type==1:
                dataList.append([data[2], year, data[4],data[5],industry])
            elif type==2:
                if data[4]=="强赎":
                    dataList.append([data[2], year, data[4],data[5],industry])
            elif type==3:
                if data[4] != "强赎":
                    dataList.append([data[2],year,data[4],data[5],industry])
    return dataList
 

按退市原因进行分析,生成饼图

def craete_notes_pie(pf):
    data = pf.groupby(by=["delist_notes"]).size()
    notesList=list(data.index)
    notesCount=list(data)

    c=(
        Pie()
        .add("",[list(z) for z in zip(notesList,notesCount)])
        .set_global_opts(title_opts=opts.TitleOpts(title="退市原因统计"))
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}个  ,占比:{d}%"))
        .render("notes.html")
    )

按强赎与非强赎中的存续时间分组计数,用pyecharts做成饼图

def craete_years_pie(pf,name,title):
    data = pf.groupby(by=["listed_years"]).size()
    notesList = list(data.index)
    notesCount = list(data)

    c = (
        Pie()
            .add("", [list(z) for z in zip(notesList, notesCount)])
            .set_global_opts(title_opts=opts.TitleOpts(title=title),legend_opts=opts.LegendOpts(pos_left="20%"))
            .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}个  ,占比:{d}%"))
            .render(name)
    )
 

强赎与非强赎中的发行资金规模分组计数(从大到小排序,取前15),用pyecharts做成柱形图

def craete_amt_bar(pf,name,title):
    data = pf.groupby(by=["orig_iss_amt"]).size().reset_index(name="size").sort_values("size",ascending=False).head(15)
    print(data)
    notesList=list(data["orig_iss_amt"])
    notesCount=list(data["size"])

    c=(
        Bar()
        .add_xaxis(notesList)
        .add_yaxis("发行规模",notesCount)
        .set_global_opts(title_opts=opts.TitleOpts(title=title),xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-20)))
        .render(name)
    )
 

按强赎与非强赎中的债券评级分组计数,用pyecharts做成饼图

def craete_grade_pie(pf,name,title):
    data = pf.groupby(by=["grade"]).size()
    notesList=list(data.index)
    notesCount=list(data)

    c=(
        Pie()
        .add("",[list(z) for z in zip(notesList,notesCount)])
        .set_global_opts(title_opts=opts.TitleOpts(title=title))
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}个  ,占比:{d}%"))
        .render(name)
    )
 

按强赎与非强赎中的债券行业分组计数,用pyecharts做成柱状图

def craete_industry_bar(pf,name,title):
    # 按行业分组,排序,取前30位
    data = pf.groupby(by=["industry"]).size().reset_index(name="size").sort_values("size",ascending=False).head(30)
    print(data)
    notesList=list(data["industry"])
    notesCount=list(data["size"])

    c=(
        Bar()
        .add_xaxis(notesList)
        .add_yaxis("行业",notesCount)
        .set_global_opts(title_opts=opts.TitleOpts(title=title),xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)))
        .render(name)
    )
 

最终调用 主方法

def main():
    #生成动太时间戳
    rTime=str(round(time.time()*1000))
    #获取退市可转债列表
    resp=get_request("https://www.jisilu.cn/data/cbnew/delisted/?___jsl=LST___t="+rTime)

    #组装每个可转债的评级
    dataList=assemble_grade(resp)

    #将数据写入csv
    write_csv(dataList)

    #读取csv文件中的数据,并制成表格(发行规模,存续时间,退市原因)
    dfData = read_csv(1)
    pf = pd.DataFrame(dfData, columns=["orig_iss_amt", "listed_years", "delist_notes", "grade", "industry"])

    dfData=read_csv(2)
    pf2=pd.DataFrame(dfData, columns=["orig_iss_amt", "listed_years", "delist_notes","grade","industry"])

    dfData = read_csv(3)
    pf3 = pd.DataFrame(dfData, columns=["orig_iss_amt", "listed_years", "delist_notes", "grade","industry"])

    #按退市原因分组计数,用pyecharts做成饼图
    craete_notes_pie(pf)

    #存续时间维度占比
    craete_years_pie(pf2,"qs_years.html","强赎存续年限统计")
    craete_years_pie(pf3,"years.html","非强赎存续年限统计")

    # 强赎与非强赎发行资金规模占比
    craete_amt_bar(pf2,"qs_amt.html","强赎发行规模统计")
    craete_amt_bar(pf3, "amt.html","非强赎发行规模统计")

    # 强赎与非强赎各个评级的占比
    craete_grade_pie(pf,"qs_grade.html","强赎评级统计")
    craete_grade_pie(pf, "grade.html", "非强赎评级统计")

    # 强赎与非强赎行业占比
    craete_industry_bar(pf2,"qs_industry.html","强赎行业统计")
    craete_industry_bar(pf3, "industry.html", "非强赎行业统计")

if __name__ == '__main__':
    main()
 

结果展示图

退市原因分析:总135个已退市可转债中,127个都是 强赎导致的,占比是94.08%;8个是因为到期或者资产不足导致,占比5.92%

存续时间分析:

强赎的可转债中,按存续时间分析,1年以内被强赎的最多,有53个,占比 41.73%,其次是 大于1年,小于等于2年的,有46个,占比 36.22%, 其次是 大于2年,小于等于3年的,有 14个,占比11.02% ....    ,从分析结果中可得知 可转债发行后,短时间内被赎回的概率比较大存续时间越长,赎回概率则越小

发行规模分析:

强赎的可转债中,按资金规模划分 发行10亿的有6个,4.2亿的3个,25亿的3个...

按债券评级分析:

强赎的可转债中,按评级划分 占比最多的是AA级,有61个,占比 45.18%,其次是 AA+ 有25个,占比18.52, 第三是 AAA有22个,占比16.3%...   

总结:最好买AA- 级或以上的,被强赎的概率最高

按债券行业分析:

强赎的可转债中,按一级行业划分,取排名靠前的30个,占比最多的是 电子行业,其次是医药生物、化工、机械设备

总结:

  • 岂今为止,在已退市的可转债中,94%以上都是被强赎的

  • 可转债发行后,1年以内被强赎的概率最高,存续时间越往后,则概率越低

  • 从债券评级上看,AA- 或以上,被强赎的概率最高,AAA级债券暂还没出现被回售的

  • 从行业上看,电气、医药生物、化工、机械设备、电气设备等都是被强赎比较高的行业

注:此历史数据只供参考,具体投资还需要独立思考,且近两年,可转债的发行数量增加很多,质量更是参差不齐,选择时还需要谨慎。 如果能抱着持有到期的心态,买上价格在100以内AA级及以上的债券,相信亏本的可能性及小,且收益不会太差,此乃保守投资者投资的一种方式

程序猿与投资生活实录已改名为  程序猿知秋,WX同款,欢迎关注!   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/396823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

互相关延时估计 Matlab仿真

文章目录互相关延时估计什么是互相关延时估计?原理代码实现总结互相关延时估计 互相关延时估计是一种信号处理技术,用于计算两个信号之间的时间延迟。在本篇博客中,我们将使用MATLAB来实现互相关延时估计,并提供多个例子和代码&a…

TypeScript深度剖析: TypeScript 中函数的理解?与 JavaScript 函数的区别?

一、是什么 函数是 JavaScript 应用程序的基础,帮助我们实现抽象层、模拟类、信息隐藏和模块 在 TypeScript 里,虽然已经支持类、命名空间和模块,但函数仍然是主要定义行为的方式,TypeScript 为 JavaScript 函数添加了额外的功能…

English Learning - L2-5 英音地道语音语调 弹力双元音 [ɪə] [ʊə] [eə] 2023.03.6 周一

English Learning - L2-5 英音地道语音语调 弹力双元音 [ɪə] [ʊə] [eə] 2023.03.6 周一朗读节奏元音的长度元音发音在清辅音和浊辅音前的区别元音发音跟后面浊辅音节数的区别元音在重读音节中复习大小元音发音对比/ʌ/ 舌中音/ɒ/ 舌后音/ʊ/ 舌后音/ɪ/ 舌前音[ɑ:] VS […

Jenkins+Docker自动化部署项目

看到了一篇文章,实操一下自动部署的感觉。参看地址:原文 首先更新docker,我更新到了 [rootlocalhost springboot]# docker --version Docker version 23.0.1, build a5ee5b1跟新步骤: yum update#卸载旧版本 yum remove dock…

Nginx支持quic协议

第一种方式:Nginx官方nginx-quic搭建 通过部署Nginx官方的QUIC分支来实现的浏览器和nginx-quic服务器粗略的HTTP3通信。 1、下载BoringSSL BoringSSL 是由谷歌开发,从 OpenSSL 中分离的一个分支。BoringSSL 是 Chrome/Chromium、Android(但它不是 NDK 的…

Spark Yarn 运行环境搭建

文章目录Spark Yarn 运行环境搭建1、解压缩文件2、修改配置环境文件3、配置历史服务器Spark Yarn 运行环境搭建 1、解压缩文件 将spark3.2.3的压缩包上传到 linux /opt/software 目录下 输入命令: tar -zxvf spark-3.2.3-bin-hadoop3.2-scala2.13.tgz -C /opt/ 解…

究竟是谁负了谁,来自底层测试的2022年终总结

前言 说实话坐在椅子前,都想好了,该怎么去写,甚至感觉有好多要写的,但是当我坐在椅子上时,却不知道该怎么开头了,不知道是不是紧张?还是不舍?难道还没有跟过去挥手告别的勇气吗&…

lambda函数

Lambda(函数指针)lambda 是c11非常重要也是最常用的特性之一,他有以下优点:可以就地匿名定义目标函数或函数对象,不需要额外写一个函数lambda表达式是一个匿名的内联函数lambda表达式定义了一个匿名函数,语法如下:[cap…

Vue3手写分页在分页的基础上用到Pagination 分页组件

近期有个项目要用到分页组件,但是内容不是表格,所以自己就研究了一下在Pagination 分页组件的基础上手写了分页 效果图: 目录 一、先声明几个变量用来定义第几页,每页多少条,总页数。 二、然后封装一个函数方便以后…

学习 Python 之 Pygame 开发魂斗罗(十)

学习 Python 之 Pygame 开发魂斗罗(十)继续编写魂斗罗1. 解决敌人不开火的问题2. 创建爆炸效果类3. 为敌人跳入河中增加爆炸效果4. 玩家击中敌人继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗(九)中,…

pycharm 使用方式

提示: pycharm 是专业版; 社区版目前暂不支持调试 Jupyter; 如果你是学生, 在读期间,每一年可以申请免费一年使用专业版, 详情到Jetbrain 去申请; 在申请过程中,需要注意, 不要使用…

简单给WordPress怎么添加自定义字段面板

今天一淘模板(56admin.com)WordPress怎么添加自定义字段面板?下面本篇文章给大家介绍一下WordPress添加自定义字段面板的方法,希望对大家有所帮助! 我们在WordPress中编写文章的时候,经常会用到一些自定义字段,如网页描…

Vue3笔记01 创建项目,Composition API,新组件,其他

Vue3 创建Vue3项目 vue-cli //查看vue/cli版本,确保在4.5.0以上 vue --version //安装或升级vue/cli npm install -g vue/cli //创建项目 vue create new_project //启动 cd new_project npm run serve 也可以通过vue ui进入图形化界面进行创建 vite 新一代前端…

论文笔记:Positive-incentive Noise

2022 TNNLS 中心思想是:噪声并不一定是有害的 1 CV问题中的噪声 以图像分类为例 对图像加入适量的噪声后再训练,识别准确率反而上升了 再以目标检测为例: 从遥感影像中做飞机检测,一般都是把飞机紧紧框住,然后做…

第十四届蓝桥杯第三期模拟赛 C/C++ B组 原题与详解

文章目录 一、填空题 1、1 找最小全字母十六进制数 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 给列命名 1、2、1 题目描述 1、2、2 题解关键思路与解答 1、3 日期相等 1、3、1 题目描述 1、3、2 题解关键思路与解答 1、4 乘积方案数 1、4、1 题目描述 1、4、2 题解关…

js typeof instanceof 以及数据类型

js 的数据类型 JavaScript的数据类型分为两种:原始类型(即基本数据类型)和对象类型(即引用数据类型):基本类型:String、Number、Boolean、Null、Undefined、Symbol(es6)引用类型:Ob…

【冲刺蓝桥杯的最后30天】day5

大家好😃,我是想要慢慢变得优秀的向阳🌞同学👨‍💻,断更了整整一年,又开始恢复CSDN更新,从今天开始更新备战蓝桥30天系列,一共30天,如果对你有帮助或者正在备…

工作日志day04

再次安装虚拟机时常见的不确定点 软件选择 安装位置 点击完成 设置用户名的时候可能与数字,以及强度有关 注销以管理员身份登录填写root用户名和自己设的密码 网络设置之后可以ping通 sudo yum -y install tree python -V查看版本信息 之后是配置python3.6 http…

【C++】内联函数auto范围for循环nullptr

🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、内联函数1.1 内联函数概念1.2…

华为OD机试题,用 Java 解【数字加减游戏】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…