扫单说明
用户可以在不重写原有策略的前提下,把策略生成的委托信号以 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 | 创建时间 |