扫单说明
用户可以在不重写原有策略的前提下,把策略生成的委托信号以 SQLite DB文件作为中转,不需要接口,不限编程语言,不限策略平台,直接接入掘金做仿真和实盘交易。
工作流程

① 扫单策略将数据写入到 in.db 里面
② 扫单程序按照指定扫描频率扫描 in.db 读取委托信号数据
③ 扫单程序读取到委托信号数据之后,即发起委托请求到仿真/实盘
④ 仿真柜台或实盘柜台处理委托并将结果推送到扫单程序
⑤ 扫单程序按照指定回写频率往 out.db 回写推送回来的委托、持仓、资金等相关数据
⑥ 扫单策略按照一定频率扫描读取 out.db 的数据
扫单策略与掘金扫单程序使用sqlite做为数据交换形式。扫单策略对 in.db 读写,对 out.db 只读;掘金扫单程序对 out.db 读写,对 in.db 只读。
快速上手
第一步:新建扫单策略
打开掘金终端界面,我们以仿真交易为例演示创建扫单策略的过程。如果您想创建实盘扫单策略,也可以直接点击实盘扫单,操作过程基本是是同样的。在这里,我们点击仿真扫单。

第二步:设置扫单参数
在弹出的界面选择策略类型为扫单策略,设置 扫单路径(扫单数据库文件和策略存放的位置)、扫描频率(扫描 in.db 的时间间隔)和回写频率(持仓、委托、成交、资金等数据回写到 out.db 的时间间隔),选择想要用于交易的资金账户, 填写策略名称,然后点击确认。

第三步:查看策略监控界面
如果您要查看策略的运行情况,点击策略列表中新建的策略,即可进入策略监控界面。

第四步:编写策略
在策略监控界面点击右下角的小齿轮,在弹出界面的上方有策略目录,点击即可快速打开策略目录。

在弹出的文件管理器界面里面有6个文件:
- in.db- out.db- scanner_roll.log- 两融交易示例策略.py- 普通交易示例策略.py- 说明.pdf
其中:
in.db 和 out.db:是用来和掘金终端交互的数据库文件。外部策略对in.db 只写,对out.db 只读。外部策略写入挂单,撤单等信息到in.db, 从out.db 读取账户的资金,持仓,委托,成交等各种信息。
两个示例策略:示例策略提供了简单的委托和撤单操作,以及从数据库读取委托、持仓、资金、成交等数据的简单示例。示例策略可以直接运行起来,但是需要注意的是,示例策略仅供参考,请勿用于实盘交易场景。用户可自行参考以实现自己的策略逻辑。
说明.pdf: 关于扫单的具体细节以及数据库的各字段的详细含义。scanner_roll.log: 扫单过程中的日志记录
扫单性能
测试环境和参数
- 掘金仿真柜台
- 操作系统:Windows 10,64位,SSD 固态硬盘
- 掘金版本:3.11.9
- 硬件配置:4核8G
- 扫描频率:10ms
- 回写频率:10ms
委托场景
- 场景1:空库,委托1000笔,每次一笔,收到确认后委托下一笔
- 场景2:库中已有5000笔委托,委托1000笔,每次一笔,收到确认后委托下一笔
- 场景3:库中已有10000笔委托,委托1000笔,每次一笔,收到确认后委托下一笔
测试结果
各测试场景下委托耗时,时间单位为毫秒.
| 场景 | 最小值 | 中位数 | 平均值 |
|---|---|---|---|
| 场景1 | 16.954 | 28.424 | 47.991 |
| 场景2 | 20.944 | 37.899 | 57.171 |
| 场景3 | 26.927 | 46.873 | 60.938 |
测试脚本使用(附代码)
- 登录扫单版终端
- 新建一个全新的仿真账户
- 新建一个扫单策略,扫单路径放在SSD固态硬盘
- 将
test_spend_time.py放到策略所在同级目录 编辑该脚本,修改
if __name__ == '__main__':下的代码,如下:# 下1000笔,每笔委托间隔0秒perf_order(place_total=1000, place_interval=0)# 批量委托# perf_orders(place_total=1000)
- 点击终端扫单策略上的
启动按钮启动扫单程序 在Python3下执行如下命令运行脚本报单脚本,测试每个报单过程
python test_spend_time.py
附测试脚本:test_spend_time.py
最佳实践
- 应使用SSD存放扫单文件。使用机械硬盘性能会下降一个数量级。
- 应尽可能用批量方式插入委托到扫单文件,而不是逐笔的方式插入委托。尽可能减少读写库请求次数。
- 扫单文件中的存量记录增长会影响读写性能,最好每天备份后使用新的扫单文件。
- 设置合理的扫单频率,扫单频率最低可以设置为10ms。
注意事项
- 新建扫单策略完成之后,会在策略所在文件夹生成相关数据库文件和Python3的示例代码
- 在
策略详情-> 右下角设置图标 展开可以看到当前扫单策略文件存放路径 - 启动扫单之后,扫单程序会扫描
in.db中一个小时内的委托信号,并对未执行过下单操作的委托发起委托交易请求 - 扫单策略只能运行于仿真和实盘模式,启停、增删和量化策略一致
- 新建扫单策略的时候,
扫描频率和回写频率设定之后不可再更改 - 尽可能将扫单策略放在SSD固态硬盘,相比机械硬盘,能得到一个量级以上的性能提升
- 请勿使用如网络位置的硬盘、WSL(windows虚拟的linux环境)等较为小众环境,在一定情况下会因磁盘读写不稳定造成数据丢失
数据库操作流程
扫描in.db的完整流程
从out.db读取adim_run_info表scan_sorder_id, scan_scancel_order_id 字段, 做为扫描开始的id
读取 in.db 的in_place_order表, 限制参数为id > scan_sorder_id(步骤1读取的值)且ctime > (当前时间 - preSeconds(默认为3600s))的订单, 也就是说在当前时间一个小时之前的单不会被扫描到. 把扫描的订单集合做为一个整体下单. 注意: 这里不管下单是否成功. 完成下单会更新out.db的 admin_order_map 表, 记录外部策略的订单与掘金系统的订单之前的关系, 其中ctime记录读取时间, send_time 记录发送给终端服务的时间
读取 in.db 的in_cancel_order表, 限制参数为id > scan_scancel_order_id(步骤1读取的值)且ctime > (当前时间 - preSeconds(默认为3600s))的订单,
也就是说在当前时间一个小时之前的单不会被扫描到. 把扫描的订单一条条的执行撤单操作. 注意: 这里不管撤单是否成功更新 admin_run_info表的scan_sorder_id, scan_scancel_order_id 字段值
如果b,c阶段有订单被执行, 则立即转入步骤b操作. 反之,则扫单程序暂停扫单频率设置的时间, 然后继续执行步骤b
out.db写入的完整流程
扫单程序接收终端服务推送过来的资金、持仓、委托流水、成交流水、账户状态变化等数据信息, 然后以指定的回写频率以队列的形式先后写入out.db
in.db 数据库说明
in.db 是用户的策略写入下单/撤单信息的数据库, 这个库由用户策略负责写入, 扫单程序只是读取
in_place_order 表
下单表, 用户策略对这个表只能是增加记录,写就是只能insert, 不能update跟delete
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 (用户策略不需要提供这个值) |
| sid | text | 用户自行维护的下单表示,唯一索引,不能重复 |
| account_id | text | 账号id。默认为空,表示使用默认的账号来下单,否则使用指定的account_id账号下单 |
| symbol | text | 证券代码(市场.代码)如:SZSE.000001 |
| volume | int | 委托量 |
| price | float64 | 委托价格 |
| side | int | 买卖方向 参见 |
| position_effect | int | 开平标志 参见 |
| position_src | int | 头寸来源: 0,unknown;1,普通券;2,专项券 |
| order_type | int | 委托类型 参见 |
| order_duration | int | 委托时间属性 参见 |
| order_qualifier | int | 委托成交属性 参见 |
| order_business | int | 委托业务属性 参见 |
| ctime | datetime | 创建时间.utc时间 (用户策略不需要提供这个值) |
in_cancel_order 表
撤单表, 外部策略对这个表只能是增加记录,写就是只能insert, 不能update跟delete
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 (外部策略不需要提供这个值) |
| sid | text | 用户策略维护的orderId |
| ctime | datetime | 创建时间.utc时间 (外部策略不需要提供这个值) |
in_raw_func 表
功能号数据表,外部策略对这个表只能是增加记录,写就是只能insert, 不能执行update和delete操作。
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键,系统生成。 (外部策略不需要提供这个值) |
| rid | text | request id,即请求ID,用于与返回结果(位于out_raw_func表)数据进行关联。用户需要维护的功能码请求标识。每个值唯一 |
| account_id | text | 资金账户id |
| func_id | text | 功能号ID |
| func_args | longtext | 功能号参数json字符串,形如{"param1": "value1", "param2":"value2"} |
| ctime | datetime | 创建时间.utc时间,系统生成。(外部策略不需要提供这个值) |
out.db 数据库说明
out.db 是扫单程序把从掘金系统返回的资金/成本回报/持仓等流水信息写入, 用户策略负责读取
admin_order_map 表
维护用户的orderId与掘金系统的clOrdId的关系.
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| sid | text | 用户策略维护的orderId |
| cl_ord_id | text | 掘金系统维护的orderId |
| ctime | datetime | 创建时间. utc时间(也是读取in.db里in_place_order表 记录的时间) |
| send_time | datetime | 发送in.db里 in_place_order表下单记录及 in_cancel_order 表撤单记录的时间. utc时间 |
admin_run_info 表
扫描程序运行时信息表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| scan_sorder_id | int | 对in.db的 sorder 表扫描的最大id |
| scan_scancel_order_id | int | 对in.db的 scancel_order 表扫描的最大id |
| scan_sraw_func_id | int | 对in.db的 sraw_func 表上次扫描的最大的id |
out_account_status 表
资金帐号状态变化流水表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| octime | datetime | 记录入库时间 |
| account_id | text | 账号ID |
| account_name | text | 账户登录名 |
| status | int | 参见 |
out_cash 表
资金表, 记录当前策略关联帐号的资金信息
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| octime | datetime | 记录入库时间.utc时间 |
| account_id | text | 账号ID |
| account_name | text | 账户登录名 |
| currency | int | 币种 |
| market_value | real | 市值 |
| nav | real | 净值(cum_inout + cum_pnl + fpnl - cum_commission) |
| pnl | real | 净收益(nav-cum_inout) |
| fpnl | real | 浮动盈亏(sum(each position fpnl)) |
| frozen | real | 持仓占用资金 |
| order_frozen | real | 挂单冻结资金 |
| available | real | 可用资金 |
| balance | real | 资金余额 |
| cum_inout | real | 累计出入金 |
| cum_trade | real | 累计交易额 |
| cum_pnl | real | 累计平仓收益(没扣除手续费) |
| cum_commission | real | 累计手续费 |
| last_trade | real | 上一次交易额 |
| last_pnl | real | 上一次收益 |
| last_commission | real | 上一次手续费 |
| last_inout | real | 上一次出入金 |
| change_reason | int | 资金变更原因 参见 |
| change_event_id | text | 触发资金变更事件的ID |
| created_at | datetime | 资金初始时间 |
| update_at | datetime | 资金变更时间 |
out_execrpt 表
执行回报 变化流水表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| octime | datetime | 记录入库时间.utc时间 |
| strategy_id | text | 策略ID |
| account_id | text | 账号ID |
| account_name | text | 账户登录名 |
| sid | text | 用户策略维护的orderId |
| cl_ord_id | text | 委托客户端ID |
| order_id | text | 委托柜台ID |
| exec_id | text | 委托回报ID |
| symbol | text | 证券代码(市场.代码)如:SZSE.000001 |
| order_business | int | 委托业务属性 参见 |
| position_effect | int | 开平标志 参见 |
| side | int | 买卖方向 参见 |
| ord_rej_reason | int | 委托拒绝原因 参见 |
| ord_rej_reason_detail | text | 委托拒绝原因描述 |
| exec_type | int | 执行回报类型 参见 |
| price | real | 委托成交价格 |
| volume | int | 委托成交量 |
| amount | real | 委托成交金额 |
| commission | real | 委托成交手续费 |
| cost | real | 委托成交成本金额 |
| created_at | datetime | 回报创建时间 |
out_order 表
order 状态变化流水表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| octime | datetime | 记录入库时间.utc时间 |
| sid | text | 用户策略维护的orderId |
| strategy_id | text | 策略ID |
| account_id | text | 账号ID |
| algo_order_id | text | 算法单ID |
| account_name | text | 账户登录名 |
| cl_ord_id | text | 委托客户端ID |
| order_id | text | 委托柜台ID |
| ex_ord_id | text | 委托交易所ID |
| symbol | text | 证券代码(市场.代码)如:SZSE.000001 |
| side | int | 买卖方向 参见 |
| position_effect | int | 开平标志 参见 |
| position_side | int | 持仓方向 参见 |
| position_src | int | 头寸来源: 0,unknown;1,普通券;2,专项券 |
| order_type | int | 委托类型 参见 |
| order_duration | int | 委托时间属性 参见 |
| order_qualifier | int | 委托成交属性 参见 |
| order_business | int | 委托业务属性 参见 |
| order_src | int | 委托来源 参见 |
| status | int | 委托状态 参见 |
| ord_rej_reason | int | 委托拒绝原因 参见 |
| ord_rej_reason_detail | text | 委托拒绝原因描述 |
| price | real | 委托价格 |
| stop_price | real | 委托止损/止盈触发价格 |
| order_style | int | 委托风格 参见 |
| volume | real | 委托量 |
| value | real | 委托额 |
| percent | real | 委托百分比 |
| target_volume | int | 委托目标量 |
| target_value | real | 委托目标额 |
| target_percent | real | 委托目标百分比 |
| filled_volume | int | 已成量 |
| filled_vwap | real | 已成均价 |
| filled_amount | real | 已成金额 |
| filled_commission | real | 已成手续费 |
| created_at | datetime | 委托创建时间 |
| updated_at | datetime | 委托更新时间 |
out_position 表
持仓表, 记录当前策略的持仓信息. 其中 account_id, symbol, side 联合做为主键
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| octime | datetime | 记录入库时间. utc时间 |
| account_id | text | 账号ID |
| account_name | text | 账户登录名 |
| symbol | text | 证券代码(市场.代码)如:SZSE.000001 |
| side | int | 持仓方向 参见 |
| volume | real | 总持仓量; 昨持仓量(volume-volume_today) |
| volume_today | real | 今日持仓量 |
| vwap | real | 持仓均价 |
| vwap_diluted | real | 摊薄持仓均价 |
| amount | real | 持仓额(volume*vwap*multiplier) |
| market_value | real | 持仓市值 |
| price | real | 当前行情价格 |
| fpnl | real | 持仓浮动盈亏((price-vwap)*volume*multiplier) |
| cost | real | 持仓成本(vwap*volume*multiplier*margin_ratio) |
| order_frozen | int | 挂单冻结仓位 |
| order_frozen_today | int | 挂单冻结今仓仓位 |
| available | int | 可平总仓位(volume-order_frozen); 可平昨仓位(available-available_today) |
| available_today | int | 可平今仓位(volume_today-order_frozen_today) |
| available_now | int | 当前可平仓位(根据标的的T+N属性计算) |
| last_price | real | 上一次成交价 |
| last_volume | int | 上一次成交量 |
| last_inout | int | 上一次出入持仓量 |
| change_reason | int | 仓位变更原因 参见 |
| change_event_id | text | 触发资金变更事件的ID |
| has_dividend | int | 是否除权除息 |
| created_at | datetime | 建仓时间 |
| update_at | datetime | 仓位变更时间 |
out_raw_func 表
功能号扫单结果数据表
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 自增,主键 |
| rid | text | 请求ID,与in_raw_func表中的rid对应。 |
| account_id | text | 资金账户ID |
| account_name | text | 资金账户名 |
| data | longtext | 功能号扫单结果,json字符串 |
| error_code | text | 错误编码 |
| error_info | text | 错误信息 |
| octime | datetime | 创建时间 |