Blankly / 三套框架

Model、Strategy、Screener:三套基类该用哪一个

Blankly 的顶层导出里有四个可以直接 import 的框架类:ModelStrategyScreener,以及期货专用的 FuturesStrategy。但 blankly init 只会问你「strategy 还是 screener」——四类框架、两类模板,这个落差就是选型时最容易踩空的地方。这一页把四者的定位与入口方法摆在一起对照。

依据:顶层导出实测依据:new_cli.py 模板表依据:frameworks 目录源码本站未实机交易
Model事件驱动基类,用 main() 自管循环
Strategy声明式注册回调,最常被模板使用
Screener横截面筛选,按标的批量评估
FuturesStrategy期货专用,杠杆与保证金相关
四类框架定位示意(依据发行版 1.18.25b0 顶层导出与 blankly/frameworks 目录结构整理)。注意 blankly init 只为 Strategy 与 Screener 提供模板,Model 与 FuturesStrategy 需要自行搭建。
逐项对照

四类框架的定位、入口与覆盖情况是什么?

判断该用哪个,只要回答两个问题:你的策略是「盯着一两个标的持续决策」,还是「在一批标的里先筛出候选」;以及你需要的是标准资产还是期货合约。

定位典型入口CLI 是否提供模板
Model最底层的事件驱动基类,你自己写 main() 循环与 event() 回调继承 blankly.Model,实现 main(self, args);用 self.sleep('1h') 控制节奏TEMPLATES 里只有 strategy 与 screener)
Strategy声明式封装,把「价格事件」「自定义事件」「定时事件」注册进去即可blankly.Strategy(exchange) + add_price_event(fn, symbol, resolution, init)(模板 none.pyrsi_bot.py
Screener面向「一批标的」的横截面评估,逐个标的产出筛选结果依赖 ScreenerState 与运行时调度器(模板 none_screener.pyrsi_screener.py
FuturesStrategy期货专用策略类,配合 BinanceFutures 等期货接口使用Strategy 同族的注册式接口,但账户/持仓语义按合约处理init 的交易所列表也不含期货交易所)
StrategyState / ScreenerState / FuturesStrategyState传入回调的状态容器,承载 variablesinterfaceresolutionbase_asset由框架构造后作为回调参数传入,不需要自己 new
为什么这件事值得单独一页:三套基类的事件模型不同,从一个换到另一个基本等于重写策略主体。而且 blankly init 只给两类模板,选 Model 或期货路线的人拿不到脚手架,只能照着仓库 examples 目录里的示例自己搭。
选型决策

按场景选:什么情况下用哪一个

下表按「你要解决的问题」组织,而不是按类名组织。每一行都给出一条能立刻验证的判断依据。

你的场景建议基类理由立刻验证的方法
单标的、按价格推进做买卖决策Strategy有官方模板,回调式接口最少样板代码跑一次 blankly init 看生成的 bot.py
需要按固定时间间隔做非价格决策(如每日再平衡)StrategyModelStrategy 可注册定时类事件;Model 自己控制 sleep 节奏更灵活看仓库 examples 里的定时相关示例
需要在多个标的上跑同一套逻辑做横截面排序Screener它的抽象就是「一批标的 → 筛选结果」blankly init 选 screener,读生成的模板
需要把外部事件(新闻、情绪、自定义数据)接进决策ModelStrategy两者都支持自定义事件;Model 在示例里示范了 event(type_, data) 写法读仓库 examples 的 custom_model.py
要做期货合约、杠杆与保证金相关逻辑FuturesStrategy只有它按合约语义处理持仓读仓库 examples 里的 futures 系列示例
只想做离线回测,不打算上实盘Strategy + KeylessExchange离线链路最短,零密钥见首个离线回测页
需要多个策略并行运行注意 BlanklyBot 与多进程示例顶层导出了 BlanklyBot,仓库 examples 里有 multicore_bot.py读该示例确认进程模型
「多策略并行」是容易被低估的一格。回测里的多标的与实盘里的多进程是两码事:回测是在一个进程里推进多个价格序列,实盘则涉及多个进程各自持有一份状态。选型时先确认你要的是哪一种,再决定是否引入进程级方案。
脚手架现状

blankly init 实际会生成什么

脚手架决定了你的起步速度。下面这张表来自 new_cli.py 的模板表与生成逻辑,是当前发行版的真实行为。

交互步骤可选值说明注意点
选择交易所alpaca / binance / coinbase_pro / ftx / oanda / kucoin / Keyless来自 deployment/exchange_data.pyEXCHANGES 列表比 README 的支持表少很多,详见交易所可用性矩阵页
选择模型类型strategy / screener来自 TEMPLATES 字典的两个键没有 model 这个选项
选择模板strategy:none / rsi_bot;screener:none / rsi_screener模板文件来自包内的 blankly/data/templates/none 就是一个空壳,需要自己填逻辑
是否添加密钥是 / 否选是会进入交互式密钥录入;Keyless 不涉及密钥可以之后用 blankly key add
生成的文件bot.pybacktest.jsonrequirements.txtkeys.jsonblankly.jsonsettings.json共 6 个文件README 只列了 5 个(漏了 requirements.txt
用指定模板初始化blankly init <model>源码里该分支会直接返回会打印 Starter models are currently disabled.
模板里的占位符是可替换的。生成的 bot.py 会把 EXCHANGE_NAMEEXCHANGE_CLASSSYMBOL_LISTSYMBOLQUOTE_ASSET 这几个标记替换成你所选交易所的真实值。也就是说你选 alpaca 时得到的默认标的与选 binance 时不同,这会影响你复制示例代码时的直觉。
取舍

声明式与自管循环:两种写法你各自会失去什么

Strategy 与 Model 的差别不只是 API 好看不好看,而是「谁控制时间推进」这件事的归属不同。

Strategy:声明式,样板代码少

你只写「当价格更新时做什么」「当某个事件到来时做什么」,时间推进由框架负责。好处是回测与实盘共用同一段回调逻辑,代码量最小。代价是你对「事件之间的相对时序」控制力更弱,复杂的状态机不好表达。

Model:自管循环,控制力强

你实现 main(),用 self.sleep(...) 自己决定节奏,也可以在循环里自由组织多步骤逻辑。好处是复杂流程好写。代价是回测路径与实盘路径的差异要你自己保证一致,框架不再帮你统一。

Screener:换的是问题形态

它回答的不是「现在买还是卖」,而是「这批标的里哪些值得进入下一步」。所以它天然是多标的批处理,产出是候选集合,后续通常还需要第二个环节来决策买卖。

FuturesStrategy:换的是账户语义

期货涉及杠杆、保证金、双向持仓,账户与持仓的读法和现货不同。前三个类处理的是现货式账户,只有它按合约语义处理——这一步不能用「继承后重写几个方法」糊过去。

维度StrategyModelScreener
时间推进由谁控制框架你的 main() 循环框架调度
每单位时间处理几个标的通常 1 到少数几个由你在循环里决定一批
产出形态下单动作下单动作候选集合
回测与实盘复用度高(同一回调)取决于你的循环写法
官方脚手架无(仅 examples 示例)
上手成本中(需理解状态对象)
迁移成本

选错之后换回来要改什么

如果一开始没判断清楚,切换基类并不是改一行 import 的事。下面按改动范围说明代价,帮你在写代码之前就把这件事决定掉。

迁移方向需要改的东西改动量可以复用的部分
Strategy → Model把注册式回调改写成一个 main() 循环;自己处理 sleep 与数据推进订单调用与指标计算逻辑可以基本照搬
Model → Strategy把循环体拆成若干回调并注册;状态从自由变量改为 state.variables同上
Strategy → Screener问题形态从「单标的时序决策」改成「多标的横截面评估」,产出从下单改成候选集很大指标计算函数可复用
现货 → 期货账户读取、下单参数、持仓语义全部改;还要处理杠杆与保证金概念很大指标与信号逻辑可复用
换交易所(同基类)通常只需改交易所构造与标的代码策略主体理论上不动
结论:交易所可以后换,基类最好先定。如果你的策略还处在「不知道要解决什么问题」的阶段,先用 Strategy 加离线数据把想法跑出形状,再决定是否迁移到 Screener 或期货语义——这样最坏情况只是丢掉回调层的胶水代码。
FAQ

关于框架选型的高频问题

回答基于发行版 1.18.25b0 的顶层导出与 CLI 源码;具体 API 行为以官方仓库实现为准。

为什么 blankly init 没有 Model 选项?

这是当前发行版的实际行为:CLI 的模板表 TEMPLATES 只有 strategyscreener 两个键。Model 仍然可以从包顶层导入并使用,只是没有脚手架。需要 Model 写法的话,可以直接读仓库 examples/ 目录里的示例作为起点。

Strategy 和 Model 能混用吗?

它们共享同一套交易所接口层,所以在同一个进程里各自构造是可行的;但两套事件推进机制同时存在会让时序难以推理。实务上更常见的做法是只选一套作为主结构,另一套只用来复用其中的工具函数(如指标计算)。

Screener 跑出来的结果能直接下单吗?

不能直接。Screener 的产出是候选集合,本质是「筛选」而不是「执行」。要真的下单,你需要再写一个消费候选集的环节。这个设计是有意的——筛选与执行是两类不同频率、不同风险特征的任务。

期货部分现在能用于实盘吗?

本站不做这个判断。可核对的官方表述是:仓库的工程文档里写明期货回测引擎「仍在 beta」,并且资金费率的下载与缓存「仍在开发中」。在没有处理资金成本的情况下,期货策略的回测和实盘之间会有系统性差异,请据此评估。

Model 写的话,回测和实盘还能复用同一份代码吗?

可以,但复用度取决于你怎么写 main()。Strategy 的复用是由框架保证的(同一份回调同时用于两种模式);Model 的复用由你保证——如果循环里写了对当前时间、当前账户的隐式假设,回测和实盘就可能走出不同路径。这也是为什么新手路径通常从 Strategy 开始。

三套框架的代码分别放在仓库哪里?

都在 blankly/frameworks/ 下:model/model.pystrategy/strategy.pyscreener/screener.py,以及 strategy/futures_strategy.py 与对应的状态类文件。想确认某个方法的行为,直接读这几个文件比看文档更准确。

下一步:怎么确认你的交易所当前能不能用?

选好基类之后,下一个问题是交易所。README 的支持表、CLI 实际可选的列表、以及接口地址的可达性,是三个不同的口径——照 README 建策略很容易选到已失效的平台。