python:将指数ETF基金数据转换为 midi 文件

ops/2025/4/2 15:28:36/

这是一个将指数ETF基金数据转换为 MIDI音乐的 python程序示例。程序使用 Tushare 获取股票数据,将收盘价映射为 MIDI音符的音高,并且根据交易量控制音量的大小
pip install tushare
python 3.7  tushare==1.2.89
pip install midiutil>midiutil
  MIDIUtil==1.2.1

编写 stock2mid.py  如下

python"># -*- coding: utf-8 -*-
"""使用 Tushare 获取股票数据并转换为 MIDI文件需要先安装依赖:pip install tushare midiutil>midiutil
"""
import sys
import tushare as ts
from midiutil>midiutil import MIDIFileif len(sys.argv) ==2:code = sys.argv[1]
else:print('usage: python stock2mid.py stockcode ')sys.exit(1)if len(code) !=6:print('stock code length: 6')sys.exit(2)df = ts.get_k_data(code)
if df.empty is True:print(" df is empty ")sys.exit(2)df = df[ df['date'] > '2024-01-01']
if len(df) <60:print(len(df)," < 60")sys.exit(2)
print('len(df)=', len(df))
# DataFrame 重建索引
df = df.reset_index(drop=True)# 提取收盘价序列
prices = df['close'].astype(float).tolist()
# 提取交易量序列
volumes = df['volume'].astype(int).tolist()
max_vol = max(volumes)
# 根据交易量控制音量的大小:将交易量转为音量
vols = [ int(100*i/max_vol)+20 for i in volumes ]
# 使用 zip 函数组合 prices 和 vols 列表
combined = list(zip(prices, vols))
print(combined[0:5])# 数据归一化处理
min_price = min(prices)
max_price = max(prices)
price_range = max_price - min_price
print(f"{code}: max={max_price}, min={min_price}, range={price_range}")
print('max/min:', max_price/min_price)# MIDI参数配置
# C3(MIDI音符范围最小值=48)
min_note = 48
# C5(MIDI音符范围最大值=84)
max_note = 84
if (max_price/min_price) < (84/48):max_note = int(50 * max_price/min_price)
if max_note %2 ==1:max_note += 1
print(f"max_note={max_note}, min_note={min_note} ")
print('max_note/50=', max_note/50)track = 0
channel = 0
tempo = 120    # BPM
volume = 100   # 音量(0-127)# 创建MIDI文件
midi = MIDIFile(1) # 单音轨
midi.addTrackName(track, 0, f"Stock {code}")
midi.addTempo(track, 0, tempo)# 生成音符序列
time_counter = 0  # 时间指针(单位:拍)
for price,vol in combined:if price_range < 0.01:  # 处理价格无波动的情况pitch = (max_note + min_note) // 2else:normalized = (price - min_price) / price_rangepitch = min_note + int(normalized * (max_note - min_note))# 添加音符(每个音符持续1拍,间隔1拍)midi.addNote(track, channel, pitch, time_counter, 1, vol)time_counter += 1# 保存MIDI文件
output_file =f"melo_{code}.mid"
with open(output_file, 'wb') as f:midi.writeFile(f)
print(f" 生成:{output_file}")

以 华泰柏瑞--沪深300ETF (510300)为示例:
运行 python stock2mid.py 510300
生成 melo_510300.mid

编写 play_mid.py 如下

python"># -*- coding: utf-8 -*-
import os
import sys
import time
from tkinter import filedialog
import traceback
import pygame
from pygame import mixerdef mixer_init():freq = 44100bitsize = -16channels = 2buffer = 2048mixer.init(freq, bitsize, channels, buffer)# optional volume 0 to 1.0mixer.music.set_volume(0.9)def play_mid(file):if mixer.music.get_busy():mixer.music.fadeout(1000)mixer.music.stop()clock = pygame.time.Clock()try:mixer.music.load(file)except:print(traceback.format_exc())mixer.music.play()while mixer.music.get_busy():clock.tick(30)# main()
f1 = ''
if len(sys.argv) ==1:filetypes = [('mid file','.mid'),('mp3 file','.mp3'),('wav file','.wav')]f1 = filedialog.askopenfilename(initialdir='D:/Music', filetypes=filetypes)
elif len(sys.argv) ==2:f1 = sys.argv[1]
else:print('usage: python play_mid.py file1.mid')print('usage: python play_mid.py file1.mp3')print('usage: python play_mid.py file1.wav')sys.exit(1)if not os.path.exists(f1):print(f"{f1} is not exists.")sys.exit(2)fn,ext = os.path.splitext(f1)
if ext.lower() not in ('.mid','.mp3','.wav'):print('.ext is not (.mid , .mp3','.wav')sys.exit(2)print(f1)
mixer_init()
time1 = time.time()
try:play_mid(f1)
except KeyboardInterrupt as ex:# if user hits Ctrl+C then exit# (works only in console mode)mixer.music.fadeout(1000)mixer.music.stop()raise SystemExit from ex
mixer.music.stop()
time2 = time.time()
print("run time: %.3f s" % (time2-time1))

运行 python play_mid.py  melo_510300.mid 


http://www.ppmy.cn/ops/171461.html

相关文章

自然语言处理,能否成为人工智能与人类语言完美交互的答案?

自然语言处理&#xff08;NLP&#xff09;作为人工智能关键领域&#xff0c;正深刻改变着人机交互模式。其发展历经从早期基于规则与统计&#xff0c;到如今借深度学习实现飞跃的历程。NLP 涵盖分词、词性标注、语义理解等多元基础任务&#xff0c;运用传统机器学习与前沿深度学…

mac m1/m2/m3 pyaudio的安装

google了很多方法&#xff0c;也尝试了 issue68的方法&#xff0c; 但是均失败了&#xff0c;但是问deepseek竟然成功了&#xff0c;下面是deepseek r1给出的方法。在M3 pro芯片上可以成功运行. 安装homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent…

完全背包模板

题目链接&#xff1a;【模板】完全背包 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 你有一个背包&#xff0c;最多能容纳的体积是V。 现在有n种物品&#xff0c;每种物品有任意多个&#xff0c;第i种物品的体积为vi​ ,价值为…

SpringBoot分布式项目订单管理实战:Mybatis最佳实践全解

一、架构设计与技术选型 典型分布式订单系统架构&#xff1a; [网关层] → [订单服务] ←→ [分布式缓存]↑ ↓ [用户服务] [支付服务]↓ ↓ [MySQL集群] ← [分库分表中间件]技术栈组合&#xff1a; Spring Boot 3.xMybatis-Plus 3.5.xShardingSpher…

Python贝叶斯分层模型专题|对环境健康、医学心梗患者、体育赛事数据空间异质性实证分析合集|附数据代码

全文链接&#xff1a;https://tecdat.cn/?p41267 在大数据时代&#xff0c;多水平数据结构广泛存在于环境健康、医学研究和体育赛事等领域。本专题合集聚焦贝叶斯分层模型&#xff08;Hierarchical Bayesian Model&#xff09;的创新应用&#xff0c;通过氡气污染数据与 季后…

第 五 章:优化算法_《C++性能优化指南》_notes

优化算法 第五章重难点详解与代码实战编译与测试说明第五章核心知识点整理重难点梳理 第一部分&#xff1a;多选题&#xff08;10道&#xff09;第二部分&#xff1a;设计题&#xff08;5道&#xff09;答案与详解多选题答案&#xff1a; 设计题参考实现&#xff08;以题目2为例…

【身份安全】OAuth 2.0工作原理(一)

目录 OAuth 授权框架一、OAuth 角色二、协议流程三、应用注册&#xff08;Application Registration&#xff09;用户 ID&#xff08;Client ID&#xff09; 和 用户密码&#xff08;Client Secret&#xff09; 四、权限授予1、授权码链接2、用户授权申请3、应用程序接收授权码…

OpenAI API - Concept 核心概念说明

文章目录 文本生成与提示消息角色和指令遵循选择模型我应该选择哪个模型&#xff1f; 提示工程 图像与视觉传递一个 URL 图像输入要求指定图像输入细节级别提供多个图像输入局限性计算成本成本计算示例 Audio and speech使用音频构建音频用例之旅语音代理流式音频文本转语音语音…