一. 前言
闲聊一下
这段时间发文频率会明显变少 , 一个是年底了要赶紧加班赶项目了 ,年终行不行就看这项目了。
再一个是 Java 在沉淀更深层次的一些东西 ,Python 在陆陆续续的学习 , 所以很难有比较好的产出。
回到正文
前段时间就聊过 ,最近在基于 Python 实现一个 股票监控系统 , 其核心是进行 仓位控制 + 风险告警。
老股民应该很有理解 ,股票赚钱不难 ,难的是赚的怎么落袋,怎么避免亏回去。
其实这个也不是一直在做 ,也就是 每被割一次 ,亏一次钱 ,就会捡起来写一点。
- 坏消息 : cao ,上一周亏得有点多
- 好消息 : 动力够了 ,东西基本成型了`。
二. 关于花了多久
整个开发时间其实不多 ,大多数时间都在 发呆
+ 学习 Python 基础知识
。
真正高质量写代码的时间 , 可以说也就十几个小时 ,算一天不过分吧。
整个功能我其实已经完成了3个模块 :
-
- 整体大盘可视化
-
- 个股日线走势
-
- 策略及评分模块 (包括个股打分 ,个股推荐 ,个股报警 ,整体风险等)
但是整个应用还要修饰 ,所以这一篇不推出了 ,只是介绍一下其中的技术概念 ,帮大家捋一下 ,一个简单的小项目需要什么。
三. 关于使用的工具
3.1 图形界面
整体是基于 QFluentWidgets 实现的 , 这个组件是对 QT 的封装 ,其开源版本中支持 : C++ Qt/PyQt/PySide
大家如果要用 ,可以在其 Git 上下载源码或者直接安装依赖使用 : github.com/zhiyiYo/PyQ...
使用评价 :
- 这是一个非常优秀的脚手架 ,可以节约百分之70的重复造轮子的时间
- 界面非常美观 ,开源的工具足够日常开发的使用 ,更复杂的自己扩展一下源码也能实现
- 拥有功能更加丰富的高级版,很多功能开箱即用,如果是打工人 ,给老板申请一下 ,完全没负担
使用经历 :
- 大部分的用法在源码的 Demo 里面都能找到案例
- 多数场景下使用内置的 Card (卡片模板)就能快速开发 ,复杂场景可以像我一样自己封一些组件进去
- Echats 开源版本是不集成的 ,但是提供了 FramelessWebEngineView 的工具 ,自己找找案例也能用
- 底层逻辑还没看完 ,但是
用到的一些比较复杂的操作都能从源码里面找到解法
总的来说方向用,强烈推荐哦!!!
3.2 图表工具
图表使用的是 EChats ,这个在前面文章里面也提到过。
这段时间在 HTML 和 Python 的聚合上面花了不少时间 ,也踩了不少坑。
使用评价 :
- 开箱即用 ,真的是开箱即用,所有的样式都基于一个 Option 传入就行了
- 参数有点多 ,但是特点是 Demo 特别全 ,你能看到的案例都能查到 Demo 源码
- 性能很快 ,在做几千条数据的 K线图的时候 ,都没感觉到卡顿
3.3 量化组件
量化工具用的是 Tushare ,这个也提到过很多次了 ,也有几篇文章来说。
具体就不说了 , 用它就完事了 ,我这里用的是120积分的基础款,免费。 更高级的功能我暂时没场景 ,大家后面有需要开源赞助 ,一年200 能接受。
四. 一些代码的难点和设计过程
下面回到代码方面 ,整体的难点主要有以下几个 :
- 很多页面相同 , 功能类似, 不想重复写代码
- echats 其实是 HTML 代码 ,兼容起来有问题
- Tushare 其实没有太多难点,因为需要的工具不多
4.1 关于重复代码 -- 那就写个公共类给子类集成吧
具体的样式参考 Home 页
- 整体基于公共父类开发后 ,
代码可以说精简到了极点
❗❗❗ - 如果想要特殊的布局 ,通过 自己建 QHBoxLayout 就可以进行配置
- 通过 addEchatTemplate , addTableTemplate , addFromTemplate 添加图表 ,表单 ,表格
- 可以自己传回调方法进去 ,所以可以任意的组合模块 👉
CallBack
python
from typing import Dict
from common.utils.JsonReplace import JsonPlaceholderReplacer
from views.common.translator import Translator
from views.template_page_view import BasePageTemplateView, FormItemDto, TableDataDto
from PyQt6.QtWidgets import (
QHBoxLayout,
)
class HomeView(BasePageTemplateView):
def __init__(self, parent=None):
t = Translator()
super().__init__("HomeView", parent=parent)
def doInitAndUpdate(self):
# 水平视图 : Chat 默认以水平试图分为左右两个部分
level1_HLayout = QHBoxLayout()
# 先返回一个当前持股信息 Echat
self.addEchatTemplate(
"持股比例",
"home_current_stock",
self.exhcangeStockChatInfo,
self.getBaseParam,
1,
level1_HLayout,
)
# 再返回一个当前持股信息 Table
self.addTableTemplate(
"当前持股", self.getStockTableInfo, self.getBaseParam, 1, level1_HLayout
)
# 添加外部组件
self.addOutLayout(level1_HLayout)
# 再返回一个当前持股信息 Table
self.addTableTemplate(
"当前持股", self.getStockTableInfo, self.getBaseParam, 1
)
# 用于返回当前的报表数据
def exhcangeStockChatInfo(self, jsonData: str, params: Dict[str, str]) -> str:
print(f"exhcangeStockChatInfo 传入查询的对象信息{params}")
replacer = JsonPlaceholderReplacer(jsonData)
return replacer.get_modified_json()
# 用于标记当前的查询对象
def getBaseParam(self) -> Dict[str, str]:
return {"stockCode": "100001"}
# 用于返回当前的报表数据
def getStockTableInfo(self, params: Dict[str, str]) -> str:
print(f"getStockTableInfo 传入查询的对象信息{params}")
return TableDataDto(
table_header=[
"股票代码",
"股票名称",
"股票当前价",
"当前盈亏比例",
"当前风险等级",
],
table_data=[
["600519", "贵州茅台", "1800.00", "+5.32%", "低风险"],
["000858", "五粮液", "120.00", "-2.15%", "中风险"],
["002304", "洋河股份", "95.50", "+1.25%", "高风险"],
],
table_item_fun=[{"查看详情": self.showTableDatail}],
)
def showTableDatail(self, stock_code: str) -> str:
return f"当前操作者的对象信息: {stock_code}"
4.2 关于 Echat 的集成
这个花的时间比较多 ,主要是 Option 的传递问题。解决方案如下 :
- 我会在一个默认文件夹下面存放 .html + .json 两个文件 ,默认将这两个文件取出来
通过变量替换 ,把.json 里面的一些配置变量替换成我应用里面的实际值
- 转换成 JS 代码后 ,通过
self.webView.page().runJavaScript(js_code, self.echat_callback)
调用前端
小难点 :
有一些变量替换的时候 ,会把一些方法引用转换成字符串 ,到了前端就不好执行了 ,所以前端 JS 里面要进行一次转换
js
function executeMethodInJson(json) {
// 遍历 JSON 数据
for (let key in json) {
if (typeof json[key] === 'string') {
// 检查是否是方法调用
const match = json[key].match(/^(\w+)\(\)$/);
if (match && typeof window[match[1]] === 'function') {
// 调用对应的函数
json[key] = window[match[1]]();
} else {
const match = json[key].match(/(\w+customFun)$/); // 正则匹配
if (match && typeof window[match[1]] === 'function') {
// 调用对应的函数
json[key] = window[match[1]];
}
}
} else if (typeof json[key] === 'object') {
// 如果是对象,递归调用
executeMethodInJson(json[key]);
}
}
}
总结
如果搭建好了上面的脚手架体系 ,估计后续页面平均1小时可以出一个。 一个开源的小应用 ,基本上也是5个页面就能成型。
所以 ,只要你有想法,花一天时间搞一个开源项目出来真的不难。 难的是基础的学习和想法的产生。
而更难的是能不能找到盈利的点 ,当然,这个组件的目的是为了自己服务 ,只要我股票不亏钱 ,我就盈利了 ,Nice.
源码发一下 :
AntMonitor: 交易市场量化工具 - Gitee.com
后续进度 :
现阶段已经开发完了页面和主逻辑 ,后续预计1个月会出一个以下3个功能的发行版 ,欢迎大家 star!!
最后的最后 ❤️❤️❤️👇👇👇
- 👈 欢迎关注 ,超200篇优质文章,未来持续高质量输出 🎉🎉
- 🔥🔥🔥 系列文章集合,高并发,源码应有尽有 👍👍
- 走过路过不要错过 ,知识无价还不收钱 ❗❗