网站开发 验收模板/电商网站制作
Backtrader 数据篇
本系列是使用Backtrader在量化领域的学习与实践,着重介绍Backtrader的使用。Backtrader 中几个核心组件:
- Cerebro:BackTrader的基石,所有的操作都是基于Cerebro的。
- Feed:将运行策略所需的基础数据加载到Cerebro中,一般为K线数据。
- Indicator:BackTader自带的指标,并集成了talib中的指标。我们也可以选择继承一个Indicator实现自己的指标。
- Strategy:交易策略。这里是整个过程中最复杂的部分,需要我们计算买入/卖出信号。
- Analyzer:分析器,以图形和风险收益等指标对交易策略的回测结果进行分析评价。
- Order:订单,记录了与当前订单相关的所有数据。
- Trader:交易,记录了与当前交易相关的所有数据。
- Position:持仓,记录了与当前持仓相关的所有数据。
- Broker:可以理解成经纪人,整个策略的初始资金、交易费率、滑点等参数需要通过Broker进行设置。
- Observer:观察者,对数据进行监控观察,比如资金曲线等等。
- Plotting:可视化组件
本次介绍Backtrader中DataFeeds模块,DataFeeds模块是Backtrader核心模块之一,其提供多数据加载途径,同时提供数据的前期处理。
在使用Backtrader时,结合量化策略编写过程通常会考虑:
- backtrader如何加载数据?可以加载哪些数据?
- 编写策略时,如何访问标的数据(行、列、单元)?
- backtrader是否可以自定义数据内容?
…
import backtrader as bt
import pandas as pd
import numpy as np
import datetimedaily_price = pd.read_csv("./data/daily_price.csv", parse_dates=['datetime'])# 筛选 600466.SH 和 603228.SH 2只股票的数据集
data1 = daily_price.query(f"sec_code=='600466.SH'").set_index('datetime').drop(columns=['sec_code'])
data2 = daily_price.query(f"sec_code=='603228.SH'").set_index('datetime').drop(columns=['sec_code'])
0 Backtrader中的数据结构
在Backtrader,可将单个或多个标的数据导入到“数据表”中,数据可通过self.datas(插入顺序)、self.dataX方式进行获取。
- self.data 和 self.data0 指向第一个元素
- self.dataX 指向数组中索引为 X 的元素
class TestStrategy(bt.Strategy):def __init__(self):print('--- self.datas ---')print(self.datas)print('--- self.data ---')print(self.data._name,self.data)print('--- self.data0 ---')print(self.data0._name, self.data0)print('--- self.datas[0] ---')print(self.datas[0]._name, self.datas[0])print('--- self.datas[1] ---')print(self.datas[1]._name, self.datas[1])print('--- self.datas[-1] ---')print(self.datas[-1]._name, self.datas[-1])def next(self):pass#print('---next: 索引为6的线 ---')#print(bt.num2date(self.datas[0].lines[6][0]))#print(bt.num2date(self.datas[0].lines[6][0]))cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)
datafeed1 = bt.feeds.PandasData(dataname=data1,fromdate=st_date,todate = ed_date)
cerebro.adddata(data=datafeed1,name='600466.SH')datafeed2 = bt.feeds.PandasData(dataname=data2,fromdate=st_date,todate=ed_date)
cerebro.adddata(data=datafeed2,name='603228.SH')cerebro.addstrategy(TestStrategy)
result = cerebro.run()
1 如何添加数据源
Backtrader 支持导入各式各样的数据:
- 第三方网站加载数据(Yahoo、VisualChart、Sierra Chart、Interactive Brokers 盈透、OANDA、Quandl)
- CSV 文件
- Pandas DataFrame
- InfluxDB、MT4CSV 等
最基础或最常见的就是导入 CSV 和导入 DataFrame了。
默认的导入方式: Backtrader 中的数据表格默认情况下包含7列,这7列的位置也是固定的,依次为 (‘close’, ‘low’, ‘high’, ‘open’, ‘volume’, ‘openinterest’, ‘datetime’)
导入的数据表格必须包含这 7 个指标吗?指标的排列顺序也必须一致吗?
- 当然不是!可以通过 GenericCSVData、PandasData 、PandasDirectData 这 7 个指标在数据源中位于第几列,如果没有这个指标,那就将位置设置为 -1。
data1
open | high | low | close | volume | openinterest | |
---|---|---|---|---|---|---|
datetime | ||||||
2019-01-02 | 33.064891 | 33.496709 | 31.954503 | 32.386321 | 10629352 | 0 |
2019-01-03 | 32.262944 | 32.941515 | 31.399309 | 31.831127 | 8602646 | 0 |
2019-01-04 | 31.399309 | 33.558397 | 31.337621 | 33.496709 | 12768116 | 0 |
2019-01-07 | 33.496709 | 34.360344 | 33.373332 | 33.620085 | 10584321 | 0 |
2019-01-08 | 33.311644 | 34.113591 | 32.694762 | 33.743462 | 10012902 | 0 |
... | ... | ... | ... | ... | ... | ... |
2021-01-22 | 30.245430 | 30.312942 | 29.502796 | 29.772845 | 17184055 | 0 |
2021-01-25 | 29.570309 | 29.570309 | 28.827675 | 28.962699 | 23646174 | 0 |
2021-01-26 | 28.962699 | 29.232748 | 28.692651 | 28.760163 | 9963442 | 0 |
2021-01-27 | 28.760163 | 29.232748 | 28.692651 | 28.895187 | 12929331 | 0 |
2021-01-28 | 28.827675 | 28.827675 | 28.557627 | 28.760163 | 12826007 | 0 |
506 rows × 6 columns
2 如何访问和获取数据
获取 line 数据
Backtrader中,列是“lines”:一列 → 一个指标 → 该指标的时间序列 → 一条线 line
Backtrader中每一个Data Feed对象都含有lines属性。将 lines 属性看作是 line 的集合,所以想要调用具体的某一条线,就通过 lines 属性来调用:
-
- 通过 lines 属性访问。例如xxx.lines, 可简写为xxx.l
-
- 通过 lines 属性中具体“线”访问。 例如:xxx.lines.close, 或写成 xxx.lines_close
-
- “先调用某张数据表格,再调用这张表格中具体的某根 line”的逻辑依次编写代码。 例如xxx.datas[0].lines[6][0]
在Backtrader的lines中,对于 datetime 线:
1、datetime 线中的时间点存的是数字形式的时间,可以通过 bt.num2date() 方法将其转为“xxxx-xx-xx xx:xx:xx”这种形式;
2、对 datetime 线进行索引时,xxx.date(X) 可以直接以“xxxx-xx-xx xx:xx:xx”的形式返回,X 就是索引位置,可以看做是传统 [X] 索引方式的改进版 。
class TestStrategy(bt.Strategy):def __init__(self):print('---打印 self 策略本身的lines ---')print(self.lines.getlinealiases())print('--- 打印 self.datas 第一个数据表格的 lines ---')print(self.datas[0]._name,self.datas[0].lines.getlinealiases())print(self.datas[0]._name,self.datas[0].lines[5][0])print('--- 打印 self.datas 第二个数据表格的 lines ---')print(self.datas[1]._name, self.datas[1].lines.getlinealiases())def next(self):print('---next: 索引为6的线 ---')print(self.datas[0]._name,bt.num2date(self.datas[0].lines[6][0]))print(self.datas[1]._name,bt.num2date(self.datas[1].lines[6][0]))cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)
datafeed1 = bt.feeds.PandasData(dataname=data1,fromdate=st_date,todate = ed_date)
cerebro.adddata(data=datafeed1,name='600466.SH')datafeed2 = bt.feeds.PandasData(dataname=data2,fromdate=st_date,todate=ed_date)
cerebro.adddata(data=datafeed2,name='603228.SH')cerebro.addstrategy(TestStrategy)
result = cerebro.run()
获取 line 上的数据点
Backtrader 提供了 索引规则 和 切片方法 get() 获取数据节点数据:
- 1、索引规则:索引位置编号结合了时间信息,0 号位置指向当前时间点的数据,-1 号位置指向前一个时间点的数据,然后依次回退 (backwards)-2、-3、-4、-5、…;1 号位置指向下一天的数据,然后依次向前(forwards)2、3、4、…;
-
2、切片方法:get(ago=0, size=1) 函数,其中 ago 对应数据点的索引位置,即从 ago 时间点开始往前取 size 个数据点。默认情况下是取当前最新时点(ago=0)的那一个数据(size=1);
-
3、在编写策略时,上面提到的对数据点的索引切片操作一般在 next() 函数中涉及较多,而 init() 中涉及较少,因为__init__() 中一般是对 一整条 line 进行操作(运算)。
class TestStrategy(bt.Strategy):def __init__(self):self.count = 0 # 用于计算 next 的循环次数# 打印数据集和数据集对应的名称print("------------- init 中的索引位置-------------")print("0 索引:",'datetime',self.data1.lines.datetime.date(0), 'close',self.data1.lines.close[0])print("-1 索引:",'datetime',self.data1.lines.datetime.date(-1),'close', self.data1.lines.close[-1])print("-2 索引",'datetime', self.data1.lines.datetime.date(-2),'close', self.data1.lines.close[-2])print("1 索引:",'datetime',self.data1.lines.datetime.date(1),'close', self.data1.lines.close[1])print("2 索引",'datetime', self.data1.lines.datetime.date(2),'close', self.data1.lines.close[2])print("从 0 开始往前取3天的收盘价:", self.data1.lines.close.get(ago=0, size=3))print("从-1开始往前取3天的收盘价:", self.data1.lines.close.get(ago=-1, size=3))print("从-2开始往前取3天的收盘价:", self.data1.lines.close.get(ago=-2, size=3))print("line的总长度:", self.data1.buflen())def next(self):print(f"------------- next 的第{self.count+1}次循环 --------------")print("当前时点(今日):",'datetime',self.data1.lines.datetime.date(0),'close', self.data1.lines.close[0])print("往前推1天(昨日):",'datetime',self.data1.lines.datetime.date(-1),'close', self.data1.lines.close[-1])print("往前推2天(前日)", 'datetime',self.data1.lines.datetime.date(-2),'close', self.data1.lines.close[-2])print("前日、昨日、今日的收盘价:", self.data1.lines.close.get(ago=0, size=3))print("往后推1天(明日):",'datetime',self.data1.lines.datetime.date(1),'close', self.data1.lines.close[1])print("往后推2天(明后日)", 'datetime',self.data1.lines.datetime.date(2),'close', self.data1.lines.close[2])print("已处理的数据点:", len(self.data1))print("line的总长度:", self.data1.buflen())self.count += 1cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)
datafeed1 = bt.feeds.PandasData(dataname=data1,fromdate=st_date,todate = ed_date)
cerebro.adddata(data=datafeed1,name='600466.SH')datafeed2 = bt.feeds.PandasData(dataname=data2,fromdate=st_date,todate=ed_date)
cerebro.adddata(data=datafeed2,name='603228.SH')cerebro.addstrategy(TestStrategy)
result = cerebro.run()
3 自定义读取函数
重新自定义数据读取函数,自定义的方式就是继承数据加载类 GenericCSVData、PandasData 再构建一个新的类,然后在新的类里统一设置参数。
在Backtrader中,默认列对应的索引值 open (default: 1) , high (default: 2), low (default: 3), close (default: 4), volume (default: 5), openinterest (default: 6),自定义数据读取函数,需要注意:
- 如果传递负值(例如:-1),则表示 CSV 数据中不存在该字段
- 自定义的函数,不会修改 Backtrader 底层的数据表格内 lines 的排列规则。
daily_price.head(10)
datetime | sec_code | open | high | low | close | volume | openinterest | |
---|---|---|---|---|---|---|---|---|
0 | 2019-01-02 | 600466.SH | 33.064891 | 33.496709 | 31.954503 | 32.386321 | 10629352 | 0 |
1 | 2019-01-02 | 603228.SH | 50.660230 | 51.458513 | 50.394136 | 51.120778 | 426147 | 0 |
2 | 2019-01-02 | 600315.SH | 148.258423 | 150.480132 | 148.258423 | 149.558935 | 2138556 | 0 |
3 | 2019-01-02 | 000750.SZ | 49.512579 | 53.154883 | 48.715825 | 51.561375 | 227557612 | 0 |
4 | 2019-01-02 | 002588.SZ | 36.608672 | 36.608672 | 35.669988 | 35.763857 | 2841517 | 0 |
5 | 2019-01-02 | 002926.SZ | 8.405656 | 8.475954 | 8.335358 | 8.435784 | 5534055 | 0 |
6 | 2019-01-02 | 603816.SH | 46.480518 | 46.480518 | 44.110319 | 45.013252 | 1864419 | 0 |
7 | 2019-01-02 | 002517.SZ | 23.626701 | 23.626701 | 23.252663 | 23.315003 | 9767171 | 0 |
8 | 2019-01-02 | 600366.SH | 56.675032 | 58.756972 | 56.675032 | 57.600338 | 5504462 | 0 |
9 | 2019-01-02 | 001914.SZ | 60.604621 | 61.414843 | 60.118487 | 60.280532 | 1484088 | 0 |
示例说明:
- 定义读取数据时间范围:20190102 - 20210128
- 缺失值设置为0.0
- 日期格式定义为YYYY-MM-DD
- 定义openinterest 为不存在列
class My_CSVData(bt.feeds.GenericCSVData):params = (('fromdate', datetime.datetime(2019,1,2)),('todate', datetime.datetime(2021,1,28)),('nullvalue', 0.0),('dtformat', ('%Y-%m-%d')),('datetime', 0),('time', -1),('high', 3),('low', 4),('open', 2),('close', 5),('volume', 6),('openinterest', -1)
)class TestStrategy(bt.Strategy):def __init__(self):self.count = 0 # 用于计算 next 的循环次数# 打印数据集和数据集对应的名称print("------------- init 中的索引位置-------------")print('--- 打印 self.datas 第一个数据表格的 lines ---')print(self.datas[0]._name,self.datas[0].lines.getlinealiases())cerebro = bt.Cerebro()
data = My_CSVData(dataname='./data/daily_price.csv')
cerebro.adddata(data, name='600466.SH')
cerebro.addstrategy(TestStrategy)
rasult = cerebro.run()
4 新增指标
往 Backtrader 的数据表格里添加指标,就是给数据表格新增列,也就是给数据表格新增 line。
在继承原始的数据读取类 GenericCSVData 或 bt.feeds.PandasData 的基础上,设置 lines 属性和 params 属性,新的 line 会按其在 lines 属性中的顺序依次添加进数据表格中。
示例说明:
- 本次增加PE、PB信息;
- 继承bt.feeds.PandasData类;
- 在现有的数据上追加PB、PE列数据;
class PandasData_more(bt.feeds.PandasData):# 要添加的线lines = ('pe','pb',)# -1表示自动按列明匹配数据,也可以设置为线在数据源中列的位置索引 (('pe',6),('pb',7),)params=(('pe',-1),('pb',-1),)class TestStrategy(bt.Strategy):def __init__(self):print('---第一个数据表格 lines---')print(self.data0.lines.getlinealiases())print('pe line:', self.data0.lines.pe)print('pb line:', self.data0.lines.pb)data1['pe'] = 2
data1['pb'] = 3cerebro = bt.Cerebro()
st_date = datetime.datetime(2019,1,2)
ed_date = datetime.datetime(2021,1,28)# 调用PandasData_more,导入Data1数据
datafeed1 = PandasData_more(dataname=data1,fromdate=st_date,todate = ed_date)
cerebro.adddata(data=datafeed1,name='600466.SH')cerebro.addstrategy(TestStrategy)
result = cerebro.run()
---第一个数据表格 lines---
('close', 'low', 'high', 'open', 'volume', 'openinterest', 'datetime', 'pe', 'pb')
pe line: <backtrader.linebuffer.LineBuffer object at 0x133edfc40>
pb line: <backtrader.linebuffer.LineBuffer object at 0x133edf9d0>
在继承原始的数据读取类 GenericCSVData 的基础上,设置 lines 属性和 params 属性,新的 line 会按其在 lines 属性中的顺序依次添加进数据表格中。
示例说明:
- 本次增加PE、PB信息;
- 继承GenericCSVData类;
- 在现有的数据上追加PB、PE列数据;
from backtrader.feeds import GenericCSVDataclass GenericCSV_PE(GenericCSVData):# 在从基类继承的行中添加一个'pe'行lines = ('pe',)# openinterest in GenericCSVData has index 7 ... add 1# add the parameter to the parameters inherited from the base classparams = (('pe', 7),('fromdate', datetime.datetime(2019,1,2)),('todate', datetime.datetime(2021,1,28)),('nullvalue', 0.0),('dtformat', ('%Y-%m-%d')),('datetime', 0),('time', -1),('high', 3),('low', 4),('open', 2),('close', 5),('volume', 6),('openinterest', -1))class TestStrategy(bt.Strategy):def __init__(self):print('---第一个数据表格 lines---')print(self.data0.lines.getlinealiases())print('pe line:', self.data0.lines.pe)#print('pb line:', self.data0.lines.pb)data1['pe'] = 2cerebro = bt.Cerebro()
# 调用PandasData_more,导入Data1数据
datafeed1 = GenericCSV_PE(dataname='./data/daily_price.csv')
print(type(datafeed1))
cerebro.adddata(data=datafeed1,name='600466.SH')cerebro.addstrategy(TestStrategy)
result = cerebro.run()
相关文章:

Backtrader 数据篇 02
Backtrader 数据篇 本系列是使用Backtrader在量化领域的学习与实践,着重介绍Backtrader的使用。Backtrader 中几个核心组件: Cerebro:BackTrader的基石,所有的操作都是基于Cerebro的。Feed:将运行策略所需的基础数据…...

视频转场素材资源网站分享
视频剪辑者常常为找不到合适的转场素材而苦恼。合适的转场素材能让视频更流畅,给观众带来惊喜。下面就为大家介绍几个宝藏网站,提供丰富的转场剪辑素材,让你的视频瞬间高大上。 蛙学网 首先重磅推荐蛙学网,堪称视频素材界的“翘楚…...

二十二、MySQL 8.0 主从复制原理分析与实战
文章目录 一、复制(Replication)1、什么是复制2、复制的方式3、复制的数据同步类型3.1、异步复制3.2、半同步复制3.3、设计理念:复制状态机——几乎所有的分布式存储都是这么复制数据的 4、基于binlog位点同步的主从复制原理4.1、异步复制示例…...

基于OSS搭建在线教育视频课程分享网站
OSS对象存储服务是海量、安全、低成本、高持久的存储服务。适合于存储大规模非结构化数据,如图片、视频、备份文件和容器/虚拟机镜像等。 安装nginx wget https://nginx.org/download/nginx-1.20.2.tar.gz yum -y install zlib zlib-devel gcc-c pcre-devel open…...

CentOS 7 下升级 OpenSSL
升级openssh,下载:https://download.csdn.net/download/weimeilayer/89935114 上传到服务器,然后执行命令 rpm -Uvh *.rpm --nodeps --force安装依赖 yum -y install gcc perl make zlib-devel perl-CPAN下载安装包:https://github.com/ope…...

线上 Dump
优质博文:IT-BLOG-CN 一、简介 机器宕机或者请求很慢最常出现的几种问题:针对代码bug或者qps过高造成的。 【1】cpu过高致内存耗尽OOM,堆区对象回收不及时cpu被打满 【2】死锁抢用资源导致cpu过高致耗尽 【3】内存泄漏: 堆内存由…...
AcWing 1303:斐波那契前 n 项和 ← 矩阵快速幂加速递推
【题目来源】https://www.acwing.com/problem/content/1305/http://poj.org/problem?id3070【题目描述】 大家都知道 数列吧,。现在问题很简单,输入 和 ,求 的前 项和 。【输入格式】 共一行,包含两个整数 和 。【输出格式】…...

2024 Rust现代实用教程:1.2编译器与包管理工具以及开发环境搭建
文章目录 一、Rust的编译器rustc二、开发环境搭建三、Rust的包管理工具Cargo四、项目结构1.Cargo.toml文件2.创建一个可执行文件项目3.创建一个库项目 参考 一、Rust的编译器rustc 查看版本 rustc-version编译生成二进制文件 rustc -o output filename filename.rs编译生成库…...

人工智能原理实验一:知识的表示与推理实验
一、实验目的 本实验课程是计算机、智能、物联网等专业学生的一门专业课程,通过实验,帮助学生更好地掌握人工智能相关概念、技术、原理、应用等;通过实验提高学生编写实验报告、总结实验结果的能力;使学生对智能程序、智能算法等有…...

自学C语言——VS实用调试技巧总结
接上一篇:自学C语言——扫雷游戏(无递归) 什么是bug “bug”本意是昆虫或虫子,一般指电脑系统或程序中,隐藏着一些未被发现的缺陷或者问题,简称程序漏洞。 第一代的计算机是由许多庞大且昂贵的真空管组成&…...

VC2012创建弹出式菜单
首先为视类添加鼠标右键单击处理函数,添加如下代码, void CMFCApplication1View::OnRButtonDown(UINT nFlags, CPoint point) {// TODO: 在此添加消息处理程序代码和/或调用默认值CView::OnRButtonDown(nFlags, point);CMenu menu;menu.CreatePopupMenu…...

Google 第三季度季报出炉
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

入职总结(更新中)
【STEP 1/3】短信1之后:材料准备阶段 填写 新进教职工“入职一件事”线上办理 系统档案转递证明(需档案到校); 档案:为规范管理,请拟报到人员将个人档案寄至浙江财经大学人事处,有专职人员进行…...

@DeleteMapping和@PostMapping和@GetMapping和Content-Type使用记录
代码例子,有注释大家可以自己试一下 RestController RequestMapping(value "demo") public class TestController {//Content-Type:application/x-www-form-urlencoded;表单提交form-dataPostMapping("/demo1")public String test…...

unity 中使用zeroMq和Mqtt 进行通讯
最近我在做一个车上的HMI项目,也就是车机应用,需要与云端和域控进行通信。HMI的功能已经外包了,但消息的统一层留给我自己来做。因为项目组其他人都没有经验,所以这个任务就落到了我头上,尽管我自己也没有太多经验&…...

四、k8s快速入门之Kubernetes资源清单
kubernetes中的资源 ⭐️ k8s中所有的内容都抽象为资源,资源实列化之后,叫做对象 1️⃣名称空间级别 ⭐️ kubeadm在执行k8s的pod的时候会在kube-system这个名称空间下执行,所以说当你kubectl get pod 的时候是查看不到的查看的是默认的po…...

掌握ElasticSearch(六):分析过程
文章目录 一、什么是分析1. 字符过滤 (Character Filtering)2. 分词 (Breaking into Tokens)3. 词条过滤 (Token Filtering)4. 词条索引 (Token Indexing) 二、内置分析器分类1. 标准分析器 (Standard Analyzer)2. 简单分析器 (Simple Analyzer)3. 语言分析器 (Language Analyz…...

【设计模式】使用python 实践框架设计
单一职责原则(SRP):一个类应该只有一个职责,意味着该类只应该有一个引起变化的原因。这使得代码更易于维护和理解。 开放封闭原则(OCP):软件实体(类、模块、函数等)应该…...

Apache paimon-CDC
CDC集成 paimon支持五种方式通过模式转化数据提取到paimon表中。添加的列会实时同步到Paimon表中 MySQL同步表:将MySQL中的一张或多张表同步到一张Paimon表中。MySQL同步数据库:将MySQL的整个数据库同步到一个Paimon数据库中。API同步表:将您的自定义DataStream输入同步到一…...

如何分析算法的执行效率和资源消耗
分析算法的执行效率和资源消耗可以从以下几个方面入手: 一、时间复杂度分析 定义和概念 时间复杂度是衡量算法执行时间随输入规模增长的速度的指标。它通常用大 O 符号表示,表示算法执行时间与输入规模之间的关系。例如,一个算法的时间复杂度为 O(n),表示该算法的执行时间…...

提示工程(Prompt Engineering)指南(进阶篇)
在 Prompt Engineering 的进阶阶段,我们着重关注提示的结构化、复杂任务的分解、反馈循环以及模型的高级特性利用。随着生成式 AI 技术的快速发展,Prompt Engineering 已经从基础的单一指令优化转向了更具系统性的设计思维,并应用于多轮对话、…...

音视频入门基础:FLV专题(19)——FFmpeg源码中,解码Audio Tag的AudioTagHeader,并提取AUDIODATA的实现
一、引言 从《音视频入门基础:FLV专题(18)——Audio Tag简介》可以知道,未加密的情况下,FLV文件中的一个Audio Tag Tag header AudioTagHeader AUDIODATA。本文讲述FFmpeg源码中是怎样解码Audio Tag的AudioTagHead…...

前端零基础入门到上班:【Day3】从零开始构建网页骨架HTML
HTML 基础入门:从零开始构建网页骨架 目录 1. 什么是 HTML?HTML 的核心作用 2. HTML 基本结构2.1 DOCTYPE 声明2.2 <html> 标签2.3 <head> 标签2.4 <body> 标签 3. HTML 常用标签详解3.1 标题标签3.2 段落和文本标签3.3 链接标签3.4 图…...

字符脱敏工具类
1、字符脱敏工具类 import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils;/*** 数据脱敏工具类** date 2024/10/30 13:44*/Slf4j public class DataDesensitizationUtils {public static final String STAR_1 "*";public static final …...

【jvm】jvm对象都分配在堆上吗
目录 1. 说明2. 堆上分配3. 栈上分配(逃逸分析和标量替换)4. 方法区分配5. 直接内存(非堆内存) 1. 说明 1.JVM的对象并不总是分配在堆上。2.堆是JVM用于存储对象实例的主要内存区域,存在一些特殊情况,对象…...

@AutoWired和 @Resource原理深度分析!
嗨,你好呀,我是猿java Autowired和Resource是 Java程序员经常用来实现依赖注入的两个注解,这篇文章,我们将详细分析这两个注解的工作原理、使用示例和它们之间的对比。 依赖注入概述 依赖注入是一种常见的设计模式,…...

C++设计模式创建型模式———原型模式
文章目录 一、引言二、原型模式三、总结 一、引言 与工厂模式相同,原型模式(Prototype)也是创建型模式。原型模式通过一个对象(原型对象)克隆出多个一模一样的对象。实际上,该模式与其说是一种设计模式&am…...

重学SpringBoot3-Spring WebFlux之SSE服务器发送事件
更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ Spring WebFlux之SSE服务器发送事件 1. 什么是 SSE?2. Spring Boot 3 响应式编程与 SSE为什么选择响应式编程实现 SSE? 3. 实现 SSE 的基本步骤3.…...

YOLO即插即用模块---AgentAttention
Agent Attention: On the Integration of Softmax and Linear Attention 论文地址:https://arxiv.org/pdf/2312.08874 问题: 普遍使用的 Softmax 注意力机制在视觉 Transformer 模型中计算复杂度过高,限制了其在各种场景中的应用。 方法&a…...

探索开源语音识别的未来:高效利用先进的自动语音识别技术20241030
🚀 探索开源语音识别的未来:高效利用自动语音识别技术 🌟 引言 在数字化时代,语音识别技术正在引领人机交互的新潮流,为各行业带来了颠覆性的改变。开源的自动语音识别(ASR)系统,如…...