一、前言
上篇文章提到要做一个工具,实现:监控即将涨停的股票数据,只提醒,辅助我做交易。
上篇文章解决高延迟问题,但还遗留了 音声提醒 会显著阻碍策略运行,所以本篇文章继续解决这个问题。
上篇文章链接:涨停股监控,设计程序时遇到行情堵塞该怎么办?-CSDN博客
二、声音提醒的方法
之所以要增加声音提醒,是因为如果只有文字提醒的话,那要是没看电脑,就很容易错过,我也不可能一直看着电脑屏幕吧;那如果有声音提醒的话,即使我在忙其他事情,但听到声音也能立刻知道出现信号了。
所以,以下测试了三种声音提醒的方式
1、语音播报
第一种方式是采用了语音播报的方式,当股票触发了监控条件,就自动告诉我是哪只股票,涨速是多少?
import pyttsx3
def init(context):
# 初始话语音插件
context.ppttsx_engine = pyttsx3.init()
context.ppttsx_engine.setProperty('rate', 240) # 语速,默认值为 240
context.ppttsx_engine.setProperty('volume', 1.0) # 音量,范围为 0.0 到 1.0
def on_tick(context,tick):
text = '{},涨速 {:.1%}'.format( ' '.join(symbol[5:]),current_rate)
context.ppttsx_engine.say(text)
# 启动语音并等待完成
context.ppttsx_engine.runAndWait()
2、蜂鸣声提示音
测试一段时间后发现,这个语音辨识度不够高,有时候环境比较嘈杂,容易忽略掉,所以又尝试了其他提示音,例如这种蜂鸣声。
import winsound
def on_tick(context,tick):
# 播放“叮咚”声音(频率和持续时间)
winsound.Beep(1000, 500) # 1000 Hz, 500 ms
3、播放本地音频
蜂鸣声感觉太单调了,辨识度还是不够高,最终想能否用播放本地音频的方式,毕竟不同客户喜欢不同的声音,客户想用什么声音就用什么声音!
PS:本地音频需要用wav格式,放在同级目录下,或者在程序中指定目录。
import pygame
def on_tick(context,tick):
play_sound()
def play_sound():
# 初始化 pygame
pygame.mixer.init()
# 加载音频文件
pygame.mixer.music.load('提示音.wav')
# 播放音频
pygame.mixer.music.play()
三、声音阻碍程序运行
提示音找到了满意的方式,但是测试下来,发现一个很严重的问题:行情堵塞!
这里的主要原因是掘金量化的程序都是单线程模式,要处理一个行情事件后,才能进一步处理下一个行情事件。
我这一个提示音就有5秒左右了,严重阻碍程序的运行。
那用更短的提示音可以嘛?比如1秒的,或者0.5秒的。测试下来,也不行,因为早上刚开盘那会,涨停信号是比较多的,即使0.5秒,10个信号也需要5秒钟了。
思来想去可能用多线程的方式应该能够解决。
最终测试下来也确实可行。不过中间也遇到很多问题,比如短时间内信号多的时候,线程一下占满了,这个时候就容易造成新信号的初始化错误,最后是采用单例模式解决了该问题。
import pygame
import threading
def init(context):
# 创建 SoundPlayer 实例
context.sound_player = SoundPlayer()
def on_tick(context,tick):
# 创建一个新的线程来播放音频,并设置为 daemon 线程
sound_thread = threading.Thread(target=context.sound_player.play_sound, args=('提示音.wav',), daemon=True)
sound_thread.start()
class SoundPlayer:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(SoundPlayer, cls).__new__(cls, *args, **kwargs)
cls._instance.init_mixer()
return cls._instance
def init_mixer(self):
pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.mixer.init()
def play_sound(self, sound_file):
try:
sound = pygame.mixer.Sound(sound_file)
sound.play()
except pygame.error as e:
print(f"Error: {e}")
def quit_mixer(self):
pygame.mixer.quit()
四、测试结果
完美,撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。
看下测试结果:
涨停股监控
ps:大家有什么建议或者需求,可以私聊我~