简介一套面向Python股票量化初学者的完整系统源码与配套教程围绕MySQL数据存储、Python环境配置及策略回测流程展开适合希望系统掌握量化选股与交易逻辑的投资者。压缩包共244个文件包体3.53MB主要包含71个Python脚本、80个编译生成的pyc文件、38个图表png、20个策略参数json及若干界面ui、前端css/html和说明txt覆盖从数据管理、策略编写到结果可视化的主要环节。该系统需在安装MySQL并配置root用户后通过命令行一键安装依赖库并启动主程序教程会逐步讲解各脚本功能和量化概念帮助用户建立自己的投资分析框架。目前已有38人浏览学习对于想快速接触量化系统开发实战的入门者是性价比高的参考素材。1. 一套能跑的 Python 股票量化系统先看它长什么样打开这套“Python股票量化系统源码及教程”的压缩包第一眼看到的是 layer.css、setting.html、demo.html 这类偏前端的资源而不是满屏的 .py 文件很多人会愣一下。实际上这就是一套带 Web 操作界面的本地量化系统前端负责策略参数设置与数据展示后端由win_main.py统一调度数据落在 MySQL 里。它的定位很明确——给想从零搭起量化框架的人一套能改能跑的底子不是那种装完就跑个 K 线图的玩具。适合两类人一类是刚学完 Python 语法、想看看真实项目长什么样的新手另一类是已经在用聚宽或掘金做策略验证、想把本地化回测和数据管理接回自己电脑的熟手。本篇会从环境搭建讲到策略改造把参数、坑和边界都摊开说。2. 环境装配MySQL、Python 与 requirement.txt 的落地顺序2.1 为什么这套系统绑定了 MySQL数据落地的核心角色这套量化系统的策略计算、回测结果、历史行情缓存都依赖 MySQL而不是 SQLite 或 CSV 文件。原因很实际量化回测通常要反复读取同一批历史数据MySQL 的索引查询效率远高于逐行扫描 CSV更重要的是MySQL 的事务机制能保证写入行情数据时的一致性避免半截写入导致回测结果错乱。按照摘要说明安装完 MySQL 后建议直接创建一个用户名为 root、密码为 88888888 的账户。很多人不理解“建议”是什么意思——实际上这套系统的数据库连接配置里默认就是写死这两个值如果你不按这个来后面启动时会在数据库连接阶段直接报错。先确认 MySQL 服务已经启动# 检查 MySQL 服务状态 sudo systemctl status mysql # 如果没启动先启动再设置开机自启Windows 在服务管理器里操作 sudo systemctl start mysql sudo systemctl enable mysqlMySQL 服务正常后打开命令行进入 MySQL 客户端确认或修改 root 密码-- 用 root 登录 MySQL mysql -u root -p -- 查看当前用户与主机信息 SELECT user, host, plugin FROM mysql.user WHERE user root; -- 如果密码不是 88888888执行修改本机使用 ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 88888888; FLUSH PRIVILEGES;这里有两个容易忽略的点。第一mysql_native_password是旧版认证插件如果 MySQL 版本是 8.0 以上默认的 caching_sha2_password 可能导致一些老版本数据库驱动连接失败建议显式指定。第二别在 NAS 或 Docker 容器里跑这套系统还想着远程连数据库——它的连接地址默认是 127.0.0.1改起来牵一发动全身。2.2 requirement.txt 批量安装库命令背后的版本陷阱项目根目录下应该有requirement.txt文件里面列了运行所需的全部 Python 库及版本号。对应的安装命令很简单# 在项目根目录下执行 pip install -r requirement.txt如果觉得安装速度太慢可以加-i参数切换镜像源# 使用清华镜像源加速下载 pip install -r requirement.txt -i https://pypi.tuna.tsinghua.edu.cn/simple-i后面的地址可以换阿里云或中科大镜像选哪个取决于你所在网络的连通性。需要留意的不是命令本身而是不要用sudo pip直接装到系统全局环境——尤其是电脑里已经装过 Anaconda 或其它 Python 环境的情况下容易把系统 Python 搞乱。常见做法是在虚拟环境里装# 创建虚拟环境 python -m venv quan_env # Windows 激活虚拟环境 quan_env\Scripts\activate.bat # Linux/macOS 激活 source quan_env/bin/activate # 激活后再安装依赖库 pip install -r requirement.txt如果requirement.txt里的某个版本号已经下架或被新版本替代pip install会报“找不到满足要求的版本”。遇到这种情况不要擅自把版本号改成最新版——量化库之间的版本依赖很强比如 pandas 2.x 和旧版 numpy 混用会直接报二进制不兼容。只改动冲突的那个版本号并做好记录。2.3 setting.html 与数据库配置前端页面和数据的握手逻辑这套系统的 Web 界面里setting.html承担的是“参数设置中心”的角色数据库连接信息就是在这个页面里配置的。它本质上就是把前端表单数据提交给后端脚本再由后端写入配置文件或直接连库操作。在浏览器里打开setting.html你会看到数据库地址、端口、用户名、密码这几个输入框。这里的输入值会对应以下标准配置[database] host 127.0.0.1 port 3306 user root password 88888888 database quan_sys charset utf8mb4重点说明一下charset utf8mb4。这套系统里存储的 A 股股票名称、板块名含有中文如果沿用默认的 latin1 或 utf8写入数据库时会报 “Incorrect string value” 错误。utf8mb4 是 UTF-8 的完整实现能覆盖所有中文和特殊符号。在 MySQL 里创建数据库时要保持字符集一致-- 建库语法适配这套系统的数据表 CREATE DATABASE IF NOT EXISTS quan_sys DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;utf8mb4_unicode_ci在排序上比默认的utf8mb4_general_ci更精确虽然性能略低一些但作为本地量化系统这点开销完全可以忽略。3. 跑通主程序win_main.py 的启动过程与前端资源分工3.1 启动入口脚本python win_main.py 执行后发生了什么依赖库装完、数据库建好之后就该启动系统了# 在项目根目录执行 python win_main.py首次执行时脚本会依次做这几件事读取配置文件里的数据库连接参数调用连接池接口初始化 MySQL 连接检查系统所需的几张核心数据表是否存在不存在则自动建表加载策略配置并把 Web 服务跑起来监听在某个本地端口上。执行成功后终端会输出监听地址通常是http://127.0.0.1:5000或http://127.0.0.1:8000用浏览器打开这个地址就能看到系统主界面。用 Flask 这类轻量框架做本地工具是极常见的做法——不需要额外的 Node 或 Nginx 服务Python 自己就把 Web 服务和策略计算都包了。win_main.py里的几个全局参数值得关注# win_main.py 中常见的全局配置段 HOST 127.0.0.1 # 监听地址改成 0.0.0.0 可允许局域网访问 PORT 8000 # 服务端口被占用时改成 8001 等 DB_NAME quan_sys # 数据库名需与 2.3 节建库名一致 DEBUG False # 生产/学习环境建议保持 False排错时改 True注意HOST参数。如果你在虚拟机里跑这套系统宿主机的浏览器想直接访问HOST需要改成0.0.0.0同时防火墙放行对应端口否则宿主机访问不到。如果只在本地用127.0.0.1就好没必要改。3.2 前端资源分工laydate、layer、code.css 在系统里干什么项目资源目录里的laydate.css、layui.css、layer.css、code.css、table.css和几个 loading 动图文件来自一套名为 layui 的前端 UI 框架。在系统里它们的分工很清楚laydate.css处理日期选择器样式——回测时你需要设定回测起止日期这个组件就是那个日历弹层layer.css与layer.js配合弹窗组件数据导入完成、策略执行结束等操作都会有弹窗提示table.css表格样式行情数据展示与回测结果列表都靠它loading-0.gif等加载动画在系统请求数据或执行长时间策略运算时显示你去改代码时大概率不会碰这些文件但要明白它们的存在是为了让demo.html和setting.html的页面结构不会错乱。最常见的翻车现场是有人为了“优化样式”删了某个 CSS 文件结果整个页面布局崩了策略配置表单显示成竖排。这些静态资源是按依赖关系互相引用的删之前想清楚。3.3 demo.html 的使用价值从演示页面理解系统运行逻辑demo.html是整套系统的演示与功能首页。打开它你能直观看到行情数据加载、策略运行、回测结果展示这一整条链路。对于新手这个页面的意义在于“先看效果再学代码”——你不需要一开始就去追源码里每个变量怎么传值先在这个页面上操作一遍理解系统输入什么、输出什么再回头翻代码就会有方向感。实操路径是这样在demo.html页面里选择某只股票的代码和日期区间点击数据加载表格区域会展示从 MySQL 读取到的历史行情再选择一个策略模板点击回测页面会显示收益曲线图和策略评价指标。这些操作本质上是调用了后端写好的接口demo.html只负责把数据渲染到页面上。这个环节最常见的问题就是点击按钮后页面一直转圈最后弹窗报超时。原因通常不是前端而是后端在查数据库时卡住了。排查思路是去终端看win_main.py的运行日志——如果日志停留在 “Fetching data from database” 之类的输出说明 SQL 查询没走完重点检查数据表里是否真的有数据、查询语句是否扫了全表。换句话说前端页面只是表象真正的故障点几乎都在数据查询效率上。4. 策略与回测链路从数据获取到结果评估的实战理解4.1 历史行情数据入库避免数据抓取与存储的常见误区运行量化系统的头号难点其实是数据。本地部署的挑战在于没有现成的数据接口需要自己解决行情来源。作者提供的教程里推荐的方案是从公开数据接口下载历史日线数据然后导入 MySQL。实际执行时我一般会先手动导少量数据验证表结构再写批量导入脚本import pymysql import pandas as pd # 建立数据库连接 conn pymysql.connect( host127.0.0.1, port3306, userroot, password88888888, databasequan_sys, charsetutf8mb4 ) # 读取待导入的日线数据data 列对应日期/开盘/收盘/最高/最低/成交量 df pd.read_csv(stock_data_000001.csv) cursor conn.cursor() for _, row in df.iterrows(): sql INSERT INTO daily_kline (stock_code, trade_date, open, high, low, close, volume) VALUES (%s, %s, %s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE close VALUES(close), volume VALUES(volume) cursor.execute(sql, ( 000001, row[trade_date], row[open], row[high], row[low], row[close], row[volume] )) conn.commit() cursor.close() conn.close()逻辑说明ON DUPLICATE KEY UPDATE这段是防重复导入的后悔药——同一支股票同一交易日的数据重复导入时不会报主键冲突而是直接更新收盘价和成交量字段。这个写法在重复跑脚本时会省掉大量去重烦恼。参数说明trade_date字段建议存成DATE类型回测时按日期做区间过滤性能最好volume的单位要与数据源保持一致有的接口返回的是“股”有的是“手”混用会导致换手率计算失真。建议导入完成后执行SELECT COUNT(*) FROM daily_kline WHERE stock_code000001核对行数这个习惯能发现遗漏和重复。4.2 策略编写与信号生成以双均线策略为例教程里花了不少篇幅讲策略怎么写核心思路其实不复杂给定一组行情数据策略逻辑输出一组买卖信号系统再根据信号去模拟成交。以最经典的双均线策略来说import pandas as pd def generate_signal(df, short_window5, long_window20): 双均线策略信号生成器 df 包含 close 列索引为交易日 df df.copy() # 计算短期和长期均线 df[short_ma] df[close].rolling(windowshort_window).mean() df[long_ma] df[close].rolling(windowlong_window).mean() # 生成信号短线上穿长线记 1买入下穿记 -1卖出 df[signal] 0 df.loc[df[short_ma] df[long_ma], signal] 1 df.loc[df[short_ma] df[long_ma], signal] -1 # 去掉没有均线值的前 N 行避免信号误判 df df.dropna() return df逻辑说明rolling(windowshort_window).mean()生成的是滚动均值窗口大小决定了均线对价格变化的敏感度。5 日均线贴近价格、反应快但噪声大20 日均线更平滑但滞后明显。signal列里的 1 和 -1 不是实时买卖命令只是“当前持仓倾向”的状态标记真实的回测引擎会在此基础上做成交撮合。策略逻辑里最关键的是dropna()前几行没有均线的数据不处理的话会把 0 当信号参与回测导致开仓位置完全错误。4.3 回测结果评估不能只看收益率曲线教程里涉及回测结果评估的部分是整份资料中信息密度最高的地方。新手习惯盯着“累计收益率”看但一个策略是否靠谱至少要同时看这几个维度指标含义合格参考范围个股日线级别年化收益率策略全年的复合收益与基准对比跑赢才算有效最大回撤从峰值到谷底的最大亏损幅度个股策略尽量控制在 20% 以内夏普比率单位风险对应多少超额收益大于 1 说明风险收益比可接受胜率盈利交易笔数占总交易笔数的比例单独看意义有限需结合盈亏比回测结果出来之后第一步不是看赚了多少而是看交易次数。一个在 3 年日线数据上只产生 4 次信号的策略统计意义很弱——样本量太少任何结论都不可靠。反过来如果产生了 200 次交易但胜率只有 30%那大概率是策略在频繁止损需要检查是不是信号参数周期太短导致噪声触发。这里插入一条血泪经验看到回测曲线漂亮不要高兴太早。先确认回测起始日期的前一天有没有“未来函数”——也就是策略在 T 日计算信号时是否无意中用了 T1 日的数据。常见做法是检查数据对齐方式shift(1)表示信号发出后次日成交如果策略在信号当天就以收盘价成交实盘中是做不到的。5. 避坑指南环境、数据与运行时的常见问题排查5.1 现象运行python win_main.py直接报Access denied for user rootlocalhost这个报错几乎 90% 的新手都会遇到。根本原因是数据库连接密码与系统配置不一致。前面 2.1 节特意强调把 MySQL 的 root 密码设成 88888888就是为了避免这个错。解决方法是先确认密码是否真的是 88888888 而不是 8888888少一位是常见手误。如果确认密码没问题就检查 MySQL 的认证插件——MySQL 8.0 默认用的 caching_sha2_password 会拒绝部分旧驱动执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 88888888;手动改掉。5.2 现象pip install -r requirement.txt时报错Failed to build numpynumpy 和 pandas 的源码编译失败通常发生在 Python 3.12 环境下——这些库对旧版本 Python 的预编译 wheel 没有覆盖到新版本。解决思路是装 Python 3.9 或 3.10 的低版本环境重来或者在requirement.txt里把冲突库的版本号往后调整到支持当前 Python 的版本。另一个更省事的路是在 Anaconda 里新建一个 Python 3.10 环境conda 会自己匹配好编译好的二进制包不折腾源码编译。5.3 现象导入 CSV 文件时所有中文列显示为乱码CSV 文件编码不是 UTF-8。多数行情数据下载网站默认用 UTF-8 或 GBK 导出如果下载源编码是 GBK而导入脚本按 UTF-8 解析就必然乱码。解决方法是在pd.read_csv()里显式指定编码# 指定 GBK 编码读取国产行情软件导出的文件 df pd.read_csv(stock_data.csv, encodinggbk)如果还报编码错误就用encodinggb18030这个编码集覆盖更广。拿不准编码时用记事本打开 CSV 文件另存为 UTF-8 再导入是最后兜底的方案。5.4 现象系统启动成功页面也能打开但所有股票列表都是空的MySQL 里quan_sys库中缺少数据表或表内无数据。win_main.py启动时会自动建表但自动建表只建结构、不负责填充行情数据数据导入需要运行另写的数据采集脚本。解决方法是在浏览器里确认数据库连接状态显示正常再用命令行检查表内数据量USE quan_sys; SHOW TABLES; SELECT COUNT(*) FROM daily_kline;如果表不存在检查win_main.py中DB_NAME设置是否和建库语句里的quan_sys一致如果表为空参考 4.1 节的数据入库步骤补齐。5.5 现象回测结果和教程截图对不上教程截图里的结果是用特定参数跑出来的比如双均线5, 20对应的收益曲线你换成10, 60当然对不上。另一个原因是数据范围不同——教程用了某个 5 年区间你用同一支股票但换了时间段结果必然不同。解决方法是先按照教程里明确给出的参数、股票代码、时间范围做一次完全一致的复现确认输出一致后再改动任何变量。确认系统本身没问题再开始自己的策略实验这条顺序非常关键。6. 进阶把内置策略改成你自己的交易逻辑系统跑通之后就该考虑动手改策略了。最值得改的地方是信号生成逻辑——把单纯的均线交叉升级成多条件共振。比如加一个成交量过滤条件只在放量上穿均线时买入缩量上穿时观望。这样可以过滤掉一部分假突破信号# 在原双均线信号基础上增加成交量确认 df[vol_ma] df[volume].rolling(window10).mean() df[volume_confirm] df[volume] 1.2 * df[vol_ma] # 只有均线金叉 且 放量时才触发买入信号 df[final_signal] 0 df.loc[(df[signal] 1) (df[volume_confirm]), final_signal] 1注意这里用了1.2这个倍数作为放量阈值它是经验值。改参数时不要一次只改一个逐个扫参才会理解参数间的耦合关系。实操中常用的做法是跑一个两层循环分别测试short_window和long_window的不同组合再把每个组合的回测结果存入 MySQL 的param_results表做成参数热力图。策略改造验证通过后把那套原始参数和结果单独归档——记录策略演进过程的习惯能省去大量重复试错的成本从那以后我每改一版策略都会强制走一遍“原始参数复现 → 新参数对比 → 结果归档”的流程这个习惯帮我躲过了不少改崩的尴尬希望帮到你。本文还有配套的精品资源点击获取
