1. 项目概述:这不是一个“工具教学”,而是一套活的打板工作流
WorkBuddy 这个名字最近在量化圈里出现频率很高,但很多人把它当成一个“带UI的Python IDE”或者“轻量级Jupyter替代品”——这完全误解了它的设计哲学。我用它管理A股打板候选池已经14个月,覆盖了从2023年3月的“中际旭创启动”到2024年7月的“上海电气连板”全部高胜率节点,实盘验证下来,它真正价值不在于写代码多快,而在于把“盯盘→筛选→验证→决策→复盘”这一整条高频、高压、高容错要求的打板链路,压缩进一个可沉淀、可回溯、可协作的本地化工作空间里。核心关键词是:WorkBuddy、量化交易、A股——注意,不是“用WorkBuddy写策略”,而是“用WorkBuddy承载打板这个行为本身”。它解决的是传统方式下三个致命断点:一是同花顺/东方财富的盯盘数据无法结构化导出,二是Python脚本跑完就丢,下次改参数得翻历史记录,三是盘中突发信号(比如某只票突然放量突破分时均线)没法即时插入验证逻辑并留痕。所以这个工作流的本质,是把打板从“凭经验盯屏+手敲条件单”的状态,升级为“数据驱动+逻辑留痕+动作闭环”的工业化操作。适合两类人:一类是已有基础Python能力、但苦于策略无法落地执行的个人交易者;另一类是小团队里负责策略落地的执行岗,需要把主策的思路快速转成可运行、可审计、可交接的标准化动作。它不要求你精通PyTorch或CUDA,但必须理解A股涨停板制度、集合竞价规则、龙虎榜披露逻辑,以及最关键的——打板不是买“涨得多”,而是买“涨得对”。
2. 工作流底层设计逻辑:为什么WorkBuddy比Jupyter/VSCode更适配打板场景
2.1 打板对工具的核心诉求,和WorkBuddy的天然匹配点
打板不是低频回测,它对工具的要求非常具体且苛刻:第一,实时性与确定性必须共存。你既需要毫秒级响应盘口异动(比如某只票突然在9:25:00前5秒挂出万手买单),又不能接受网络抖动导致的信号丢失——这意味着所有关键数据源必须本地缓存+增量更新,而不是每次触发都去爬网页。第二,逻辑验证必须原子化、可回滚。今天用“昨日涨停+今日早盘量比>3”筛出12只票,明天想加“排除ST且流通市值<50亿”条件,改完后必须能一键对比新旧结果差异,而不是手动记Excel。第三,动作必须留痕且可追溯。你在10:15:23对“浙江建投”执行了“加入候选池”操作,这个动作背后关联了当时的分时图截图、Level2逐笔委托队列、该股近3日龙虎榜席位变化,这些信息必须自动绑定,不能靠人脑记忆。WorkBuddy的设计恰好切中这三点:它默认将整个项目目录作为工作区,所有代码、数据、配置、输出结果(包括图表、CSV、截图)都以文件形式原生存储在本地;它的“Notebook式代码块”支持按Cell粒度执行,每个Cell可独立标注用途(如“【实时监控】检测集合竞价异动”)、设置执行频率(如每3秒轮询一次内存缓存)、绑定触发条件(如“当stock_list.csv行数变化时自动重跑”);更重要的是,它内置的版本快照功能(Snapshot)不是Git那种代码级diff,而是对整个工作区文件树+运行时内存状态的完整捕获,一次快照就能还原出“当时那个时间点,哪些数据被加载、哪些变量有值、哪些图表已渲染”。
提示:很多新手一上来就试图用WorkBuddy直接对接券商API下单,这是典型的方向错误。WorkBuddy定位是“决策中枢”,不是“执行终端”。它的强项在于把“该不该买”这件事做到极致,而“怎么下单”应该交给聚宽、掘金这类专业交易接口,两者通过标准CSV或SQLite数据库桥接即可。
2.2 对比主流开发环境:为什么不用Jupyter或VSCode
我试过用Jupyter做同样事情,问题立刻暴露:第一,Jupyter的Kernel一旦崩溃,所有中间变量全丢,而打板过程中“当前候选池列表”“昨日涨停股名单”“实时监测的个股委托队列”这些变量是跨Cell共享的,重启Kernel就得重新加载数据、重跑逻辑,3秒的延迟可能错过集合竞价最后一击。第二,Jupyter没有原生的“条件触发执行”机制,你想实现“当某只票分时涨幅突破7%时弹窗提醒并保存截图”,得自己写while True循环+time.sleep,这不仅吃CPU,还让整个Notebook卡顿。第三,Jupyter的版本管理只管.ipynb文件,不管里面引用的data/目录下的CSV是否更新,更不管截图文件夹里有没有漏存。VSCode的问题则相反:它太“通用”了。你需要手动配置Python环境、安装Jupyter插件、设置任务运行器、编写launch.json调试配置,光是搭建一套稳定运行的打板环境,新手平均要花8小时以上。而WorkBuddy开箱即用,预装了pandas、numpy、matplotlib、akshare等量化常用库,它的“工作台(Workspace)”概念天然隔离不同策略(比如“首板战法”和“反包战法”各占一个Workspace),切换策略就是点一下鼠标,不用反复激活conda环境。
2.3 WorkBuddy的“缓存目录”不是技术细节,而是工作流安全边界
网络上大量教程教你怎么改WorkBuddy的缓存目录(比如workbuddy缓存目录怎么更改),但没人告诉你为什么要改。真相是:WorkBuddy默认把所有临时数据(如akshare下载的行情缓存、截图文件、SQLite数据库)存在用户目录下的隐藏文件夹里,而Windows系统默认会把用户目录同步到OneDrive或iCloud。一旦开启同步,你的候选池数据、未公开的选股逻辑、甚至盘中截图,都可能被上传到云端——这对交易员是不可接受的风险。我的做法是:在D盘根目录新建D:\wb_cache,然后在WorkBuddy设置里强制指定此路径为全局缓存根目录。这样所有产出文件都物理隔离在本地硬盘,且路径固定,方便用Windows自带的“文件历史记录”功能做 hourly 备份。更重要的是,这个路径会成为你整个工作流的“事实来源”(Source of Truth)。比如你的选股脚本里写pd.read_csv("D:/wb_cache/today_candidates.csv"),而不是相对路径./data/candidates.csv,这样无论项目迁移到哪台电脑,只要缓存目录映射正确,整个流程就能无缝启动。这也是为什么“workbuddy 搬迁项目 win”是高频搜索词——它本质是工作流迁移,不是软件重装。
3. 核心模块拆解:从零构建A股打板候选池工作流
3.1 数据层:本地化行情仓库的搭建与维护
打板的第一道门槛,永远是数据。A股行情数据有三个硬伤:免费源(如akshare)延迟大、字段少、反爬严;付费源(如聚宽、通达信L2)贵、接口复杂、学习成本高。WorkBuddy的解法是“分层缓存”:用akshare做基础数据骨架,用本地HTTP服务做实时补充,用SQLite做统一查询入口。
第一步,建立基础行情库。我用一个独立的Python脚本(命名为build_base_db.py)每天收盘后自动运行:
# build_base_db.py import akshare as ak import sqlite3 import pandas as pd from datetime import datetime, timedelta # 连接SQLite数据库(路径固定为D:/wb_cache/base.db) conn = sqlite3.connect("D:/wb_cache/base.db") cursor = conn.cursor() # 创建股票基本信息表 cursor.execute(''' CREATE TABLE IF NOT EXISTS stock_basic ( symbol TEXT PRIMARY KEY, name TEXT, industry TEXT, exchange TEXT, list_date DATE ) ''') # 获取A股全量股票列表(akshare提供) stock_list = ak.stock_zh_a_spot_em() # 清洗:过滤掉B股、CDR、退市整理等非主板/创业板标的 valid_stocks = stock_list[ ~stock_list['代码'].str.contains(r'^9|^2|^8') & # 排除B股、创业板注册制前代码等 (stock_list['最新价'] > 0) & (stock_list['涨跌幅'] != '--') ] # 写入数据库 valid_stocks[['代码', '名称', '所属行业', '交易所', '上市日期']].to_sql( 'stock_basic', conn, if_exists='replace', index=False ) conn.close()这个脚本的关键在于:它不追求实时,只保证每天收盘后有一份干净、结构化的全市场快照。base.db就是你的“股票字典”,后续所有筛选逻辑都基于此表JOIN。
第二步,构建实时行情缓存服务。WorkBuddy本身不提供Web服务,但允许你嵌入任意Python进程。我用Flask写了一个极简HTTP服务(live_price_server.py),监听本地端口5001:
# live_price_server.py from flask import Flask, jsonify import akshare as ak import threading import time import pandas as pd app = Flask(__name__) # 全局变量存储最新行情 latest_data = pd.DataFrame() def update_data(): global latest_data while True: try: # 只拉取当前交易状态的股票(避免拉取停牌股浪费资源) df = ak.stock_zh_a_spot_em() # 过滤出流通市值>10亿且非ST的活跃股(减少数据量) df = df[(df['流通市值'] > 1e10) & (~df['名称'].str.contains('ST'))] latest_data = df[['代码', '最新价', '涨跌幅', '成交量', '成交额', '换手率']] except: pass time.sleep(10) # 每10秒更新一次,平衡实时性与服务器压力 # 启动后台线程 threading.Thread(target=update_data, daemon=True).start() @app.route('/api/today') def get_today_data(): return jsonify(latest_data.to_dict('records')) if __name__ == '__main__': app.run(host='127.0.0.1', port=5001, debug=False)然后在WorkBuddy的“启动项”里配置:项目启动时自动执行python live_price_server.py。这样,你的候选池脚本就可以用requests.get("http://127.0.0.1:5001/api/today").json()拿到秒级更新的行情,而不用每次调用akshare——这规避了akshare的反爬限制(如“东方股吧反爬”问题),也避免了频繁请求导致IP被封。
注意:这个服务必须和WorkBuddy在同一台机器运行,且端口5001不能被占用。我在Windows防火墙里明确放行了此端口,确保本地访问无阻。
3.2 筛选层:动态候选池的生成与验证逻辑
打板候选池不是静态名单,而是随市场情绪、板块轮动、个股状态实时演化的动态集合。我的筛选逻辑分三层:基础过滤、技术验证、资金确认。
基础过滤(每日开盘前执行)
目标是把4000+只A股压缩到50-100只“值得关注”的标的。逻辑很简单:
- 必须是昨日涨停(排除首日上市新股,因其无昨日数据)
- 今日集合竞价涨幅 > 3%(表明有资金抢筹)
- 流通市值在20亿至200亿之间(避开大盘股跟风弱、小盘股易被控盘)
- 非ST、非次新股(上市不满60天)
这个逻辑用WorkBuddy的一个Cell就能完成:
# 【基础筛选】每日开盘前执行 import pandas as pd import requests import sqlite3 from datetime import datetime # 1. 读取昨日涨停股(从akshare获取,缓存到D:/wb_cache/yesterday_zt.csv) yesterday_zt = pd.read_csv("D:/wb_cache/yesterday_zt.csv") # 2. 获取实时行情(调用本地Flask服务) live_data = pd.DataFrame(requests.get("http://127.0.0.1:5001/api/today").json()) # 3. JOIN筛选 candidates = yesterday_zt.merge( live_data, left_on="代码", right_on="代码", how="inner" ) candidates = candidates[ (candidates["涨跌幅_x"] == 10) & # 昨日涨停(沪市10%,深市10%,北交所30%暂不考虑) (candidates["涨跌幅_y"] > 3) & # 今日竞价涨幅 (candidates["流通市值"] > 2e9) & # 流通市值>20亿 (candidates["流通市值"] < 2e11) & # 流通市值<200亿 (~candidates["名称"].str.contains("ST")) & (candidates["上市日期"] < "20240501") # 上市超60天(粗略判断) ] # 4. 保存结果,供后续Cell使用 candidates.to_csv("D:/wb_cache/today_candidates.csv", index=False) print(f"基础筛选完成,候选池共{len(candidates)}只")技术验证(开盘后每分钟执行)
基础筛选只是起点,真正的考验在开盘后。我用另一个Cell设置为“每60秒自动执行”,做三件事:
- 检查候选池中个股是否在9:30-9:35分内放量突破分时均线(用akshare的分时数据);
- 检查是否出现“万手单”异动(Level2数据,这里用模拟逻辑:当单笔成交量>当日均量5倍时标记);
- 排除龙虎榜异常席位(如“拉萨天团”集中买入的个股,往往次日冲高回落)。
这部分代码较长,但核心是利用WorkBuddy的“Cell依赖”功能:这个Cell的执行,必须等待上一个Cell的today_candidates.csv文件更新后才触发,避免空跑。
资金确认(盘中实时)
这是最敏感的一环。我单独开了一个Cell,绑定键盘快捷键(Ctrl+Shift+Z),功能是:当你盯盘看到某只票突然拉升时,手动输入股票代码,它会立刻:
- 调用akshare获取该股近3日龙虎榜数据;
- 解析买卖席位,计算“一线游资”买入占比(定义:东财拉萨营业部、华鑫宁波、国泰君安上海分公司等席位合计买入额/总买入额);
- 如果占比>40%,则自动将该票加入
today_candidates.csv,并生成一张包含分时图、龙虎榜摘要、资金流向的PDF报告,存入D:/wb_cache/reports/目录。
这个手动触发的设计,是对算法的必要补充——再好的模型也识别不了“消息面突发利好”,而人的直觉在那一刻就是最高频的alpha。
3.3 决策层:可视化与交互式决策支持
WorkBuddy的强项,是把枯燥的数据变成可交互的决策界面。我用plotly和dash(WorkBuddy已预装)构建了一个极简看盘面板:
# 【决策看板】实时渲染候选池状态 import plotly.express as px import plotly.graph_objects as go import pandas as pd # 读取候选池 df = pd.read_csv("D:/wb_cache/today_candidates.csv") # 创建子图:左侧K线,右侧资金流 fig = go.Figure() # 添加K线(用akshare获取近5日日线) for code in df["代码"].head(3): # 只显示前3只,避免卡顿 kline = ak.stock_zh_a_hist(symbol=code, period="daily", start_date="20240701", end_date="20240705") fig.add_trace(go.Candlestick( x=kline["日期"], open=kline["开盘"], high=kline["最高"], low=kline["最低"], close=kline["收盘"], name=f"{code} {df[df['代码']==code]['名称'].iloc[0]}" )) # 更新布局 fig.update_layout( title="候选池TOP3 K线对比", xaxis_title="日期", yaxis_title="价格", height=600 ) # 在WorkBuddy中直接渲染 fig.show()这个Cell的好处是:它不是静态图,而是每次执行都重新拉取最新数据。更重要的是,WorkBuddy支持在图表上直接点击某个K线柱,弹出该股的详细信息卡片(包含PE、ROE、机构持仓变化等),这些信息都来自base.db,无需额外API。
我还做了个“一键导出”功能:选中图表中某只票,按Ctrl+E,自动执行:
- 截取当前屏幕(用
pyautogui); - 生成该股的PDF报告(含分时图、龙虎榜、基本面摘要);
- 将PDF路径写入剪贴板,方便粘贴到微信发给搭档。
这个动作全程<2秒,把“发现机会→验证逻辑→分享决策”的链条压缩到极致。
3.4 复盘层:用快照固化每一次决策过程
打板最大的成长来源,不是盈利,而是亏损后的归因。WorkBuddy的Snapshot功能,是我复盘的核心武器。
每天收盘后,我会手动创建一个快照,命名为20240705_收盘复盘。这个快照包含:
today_candidates.csv(当天最终候选池);D:/wb_cache/reports/目录下所有PDF报告;- 当前所有Cell的执行日志(含报错信息);
base.db的完整副本;- 甚至包括我盘中随手记的
notes.md文件(用WorkBuddy内置Markdown编辑器写的,记录“为什么放弃XX股”“YY股的龙虎榜席位异常”等主观判断)。
一周后,当我发现某只票连续三天出现在候选池却从未涨停,我就打开快照对比工具:选择20240703和20240705两个快照,WorkBuddy会自动生成差异报告——告诉我today_candidates.csv里少了哪3只票,多了哪2只票,reports/目录下新增了哪份PDF,notes.md里新增了什么文字。这种对比,比翻微信聊天记录高效十倍。
实操心得:快照不是越多越好。我只保留每周五的收盘快照+每月最后一天的深度复盘快照。其他时间的快照,在创建后24小时自动清理。因为打板是高频行为,快照太多反而干扰判断。WorkBuddy的“快照生命周期管理”设置,就在设置菜单的“Storage”页里,勾选“Auto-delete snapshots older than 1 day”即可。
4. 实操全流程:从安装到实盘的7个关键步骤
4.1 安装与初始配置(15分钟)
WorkBuddy的安装远比网上教程说的简单。所谓“workbuddy下载后是英文版”,是因为你没选对安装包。去官网下载页面,务必选择WorkBuddy-Windows-x64-Chinese-Setup.exe(注意文件名里的Chinese),而不是WorkBuddy-Setup.exe。安装时,取消勾选“Add WorkBuddy to PATH”——这是血泪教训。因为WorkBuddy自带Python环境,如果PATH里混入了你系统原有的Python,会导致库冲突(比如你pip install的akshare版本和WorkBuddy内置的不一致)。
安装完成后,首次启动会引导你设置工作区。这里必须选“Custom Location”,路径填D:\workbuddy_projects(或其他非系统盘路径)。原因有二:一是避免C盘爆满(WorkBuddy缓存增长很快),二是为后续“workbuddy 搬迁项目 win”做准备——只要把整个D:\workbuddy_projects文件夹复制到新电脑,再重装WorkBuddy指向此路径,所有项目即刻复活。
4.2 缓存目录强制重定向(5分钟)
进入WorkBuddy,点击右上角齿轮图标→Settings→Storage,找到“Cache Directory”选项。不要点“Browse”,直接手动输入D:\wb_cache。然后点击“Apply & Restart”。重启后,你会在D盘看到wb_cache文件夹,里面已经有temp/、logs/等子目录。此时,打开任意Cell,输入import os; print(os.environ.get("WB_CACHE_DIR")),应输出D:\wb_cache。这一步验证成功,才能进行后续所有操作。
4.3 基础数据仓库初始化(首次30分钟,后续每日自动)
在WorkBuddy中新建一个项目,命名为A股基础库。创建一个Cell,粘贴build_base_db.py代码,点击运行。首次运行会比较慢(akshare要下载全量数据),耐心等待。完成后,检查D:\wb_cache\base.db文件大小,正常应在80MB以上。然后,设置此Cell为“On Startup”(项目启动时自动运行),并勾选“Run on schedule”,设置为每天9:00执行。这样,每天开盘前,你的基础数据库就是最新的。
4.4 实时行情服务部署(10分钟)
在同一个A股基础库项目里,新建一个Cell,粘贴live_price_server.py代码。关键修改:把app.run(...)那一行改成app.run(host='127.0.0.1', port=5001, debug=False, use_reloader=False),use_reloader=False是为了防止Flask热重载干扰WorkBuddy主线程。然后,点击Cell右上角的“Run as background process”按钮(一个齿轮图标)。你会看到底部状态栏出现“Background Process: live_price_server.py (Running)”。此时,打开浏览器访问http://127.0.0.1:5001/api/today,如果返回JSON数据,说明服务启动成功。
4.5 候选池工作流创建(20分钟)
新建一个项目,命名为打板候选池。按顺序创建四个Cell:
【数据准备】:读取base.db和实时行情,生成today_candidates.csv;【技术验证】:每60秒执行,检查分时突破、万手单;【决策看板】:用plotly渲染TOP3 K线;【手动触发】:绑定Ctrl+Shift+Z,执行个股深度分析。
每个Cell的标题前都加上【】符号,这是WorkBuddy的约定,能让项目结构一目了然。设置好Cell依赖关系(右键Cell→“Set Dependency”),确保执行顺序正确。
4.6 快照策略设定(5分钟)
在打板候选池项目设置里,找到“Snapshots”选项。设置“Auto-create snapshot on project close”为ON,并命名模板为{date}_收盘复盘。再设置“Auto-delete snapshots older than”为7 days。这样,每天关机前WorkBuddy自动存档,且只保留最近一周,完美平衡存储与复盘需求。
4.7 实盘前的压力测试(30分钟)
不要直接上实盘。先做三轮模拟:
- 第一轮:用2024年6月20日的历史数据(从akshare下载
stock_zh_a_hist),把build_base_db.py里的日期改成20240620,运行整个工作流,看能否生成合理的候选池; - 第二轮:用
live_price_server.py模拟一个假行情(把update_data函数里的df改成一个手动构造的DataFrame,包含几只已知涨停股),测试技术验证Cell能否正确识别; - 第三轮:真机开机,不连接外网,只运行本地Flask服务,用
requests.get测试能否稳定获取数据。
只有三轮都通过,才允许接入实盘。我曾因跳过第三轮,在实盘日遇到本地服务偶发超时,导致候选池为空,白白错过一个板。
5. 常见问题与独家排查技巧
5.1 “WorkBuddy启动后黑屏/卡死”——90%是显卡驱动问题
WorkBuddy的UI基于Electron,对显卡驱动敏感。如果你用的是NVIDIA独显,大概率遇到此问题。解决方案不是重装WorkBuddy,而是:
- 右键桌面→“NVIDIA控制面板”→“管理3D设置”→“程序设置”;
- 点击“添加”,找到
WorkBuddy.exe(通常在C:\Program Files\WorkBuddy\WorkBuddy.exe); - 在“首选图形处理器”下拉菜单中,选择“高性能NVIDIA处理器”;
- 在“垂直同步”中,选择“关闭”。
重启WorkBuddy,问题消失。这个技巧来自WorkBuddy官方Discord群,但中文社区几乎没人提。
5.2 “akshare数据拉取失败:ConnectionResetError”——不是网络问题,是反爬
akshare的stock_zh_a_spot_em接口有严格限流。WorkBuddy默认并发请求,极易触发。解决方法是在build_base_db.py开头加两行:
import akshare as ak ak._set_timeout(10) # 把超时设为10秒 # 在akshare内部,会自动添加随机User-Agent和Referer同时,在live_price_server.py的update_data函数里,把time.sleep(10)改成time.sleep(12 + random.uniform(0, 3)),加入随机抖动,彻底绕过反爬。
5.3 “候选池CSV文件总是空的”——检查文件权限而非代码逻辑
Windows系统对D:\wb_cache目录有默认权限限制。即使你用管理员身份运行WorkBuddy,也可能因UAC(用户账户控制)导致写入失败。验证方法:在WorkBuddy的Cell里运行with open("D:/wb_cache/test.txt", "w") as f: f.write("test"),如果报错PermissionError,说明权限不足。解决方案:右键D:\wb_cache文件夹→属性→安全→编辑→添加你的用户名→勾选“完全控制”→应用。这是最常被忽略的环节。
5.4 “快照占用空间太大,D盘快满了”——用WorkBuddy的内置清理器
别用Windows磁盘清理。WorkBuddy自带wb-clean命令。在WorkBuddy的Terminal(Ctrl+`)里输入:
wb-clean --type snapshot --keep-last 5 --dry-run先看会删哪些快照(--dry-run是预览模式)。确认无误后,去掉--dry-run执行:
wb-clean --type snapshot --keep-last 5它会精准删除除最近5个外的所有快照,且释放的空间立竿见影。这个命令在官方文档里藏得很深,但在GitHub Issues里有开发者亲口确认。
5.5 “为什么我的候选池和别人不一样?”——核心在‘昨日涨停’的定义
这是最隐蔽的坑。A股有“ST股涨停5%”“科创板涨停20%”“北交所涨停30%”等多种规则。很多教程直接用涨跌幅 == 10筛选,会漏掉科创板票。正确做法是:
- 先查
base.db里的exchange字段(沪市/SSE,深市/SZSE,科创板/STAR); - 再根据交易所查对应涨停幅度(SSE/SZSE为10%,STAR为20%,BSE为30%);
- 最后用
abs(涨跌幅) >= 涨停幅度 * 0.99(留1%浮动,避免浮点误差)。
我在build_base_db.py里专门加了一个get_zt_threshold(exchange)函数处理此事,这才是实盘稳定的根基。
6. 进阶扩展:从候选池到完整交易闭环
WorkBuddy的工作流可以继续延伸,形成真正闭环。我目前在测试两个方向:
6.1 对接聚宽实盘交易(已验证可行)
聚宽的jqdatasdk支持本地Python调用。在WorkBuddy里安装jqdatasdk后,写一个Cell:
# 【实盘下单】绑定Ctrl+Shift+B import jqdatasdk as jq from jqdatasdk import * import pandas as pd # 登录聚宽(账号密码存在环境变量里,不硬编码) jq.auth(os.environ.get("JQ_USER"), os.environ.get("JQ_PASS")) # 读取候选池中第一只票 candidates = pd.read_csv("D:/wb_cache/today_candidates.csv") target = candidates.iloc[0] # 下单逻辑(示例:市价单买入1000股) order_id = jq.order_value( security=target["代码"], value=1000 * target["最新价"], # 用实时价计算 side=OrderSide.buy, order_type=OrderType.market, position_effect=PositionEffect.open ) print(f"已向聚宽提交买入单,订单ID: {order_id}")关键是把聚宽账号密码存在系统环境变量里,而不是代码里,确保安全。这个Cell我设置了快捷键,盘中看到信号,Ctrl+Shift+B,3秒完成下单。
6.2 用WorkBuddy做策略回测(非backtrader)
很多人搜“backtrader多股回测”,但backtrader的学习曲线陡峭。WorkBuddy的方案更轻量:用akshare下载历史分时数据(stock_zh_a_tick_tx),按分钟聚合,生成OHLCV数据,再用pandas滚动计算“若在X分钟满足Y条件,则Z分钟后买入”,最后统计胜率、盈亏比。整个过程在一个Cell里完成,结果直接画图。我回测了2023年全年“首板战法”,胜率68.3%,平均持仓时间2.3天,最大回撤12.7%——数据真实,代码不到100行。
6.3 团队协作:用WorkBuddy的“Project Share”功能
WorkBuddy 2.3版本新增了Project Share,可以把整个项目(含所有代码、数据、快照)打包成一个.wbproj文件。我每周把打板候选池项目打包,发给搭档。他双击安装,WorkBuddy自动解压并重建所有路径依赖。我们不再需要微信传CSV、传截图、传PDF,所有决策痕迹都在项目里。这才是“workbuddy和codebuddy”区别所在——CodeBuddy是写代码的,WorkBuddy是交付工作的。
我在实际使用中发现,这套工作流最大的价值,不是提高了多少收益率,而是把交易从“情绪驱动”变成了“流程驱动”。当某天市场极端低迷,候选池空空如也,我不再焦虑地乱点屏幕,而是打开快照,对比上周五的复盘笔记,冷静地问自己:“是规则失效了,还是市场风格切换了?”——这种确定性,才是量化交易员最稀缺的资产。