我曾经花了一周时间开发了一个股票模拟交易后台程序,使用Node.js。代码量很少,能完成基本功能。下面给大家介绍一下其实现步骤。
查询
其中模拟交易和真实交易最大的不同是,真实交易采用撮合制,逻辑较为复杂。模拟交易采用更简单的即时成交机制,只要符合条件,订单立即成交。
这个后台程序一共就两个js文件,一个用于处理成交,即判断成交条件,写数据库。另一个处理其他逻辑。当然这里面没有提到获取股票实时价格的问题,这是另一个系统完成,我们通过消息队列实时获取我们所关心的股票的价格,这是另一个话题了。
这个后台程序以一个node.js进程的方式运行,一个10秒一次的定时器执行成交判断。(真实交易所的撮合器也是10秒钟一次)
此外有一个WebAPI Server接受来自客户端的请求。所以总体架构,可以看成是一个微服务组成的系统。
`Id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模拟账户',
`MemberCode` varchar(20) DEFAULT '' COMMENT '用户编号',
`AccountNo` varchar(255) DEFAULT NULL COMMENT '账号',
`TranAmount` int(11) DEFAULT NULL COMMENT '模拟账户入资金额',
`CommissionLimit` decimal(20,4) DEFAULT '2.9900' COMMENT '最低佣金',
`CommissionRate` decimal(20,4) DEFAULT '0.0125' COMMENT '佣金比例',
`Cash` decimal(20,4) DEFAULT '0.0000' COMMENT '现金',
`UsableCash` decimal(20,4) DEFAULT '0.0000' COMMENT '可用资金',
`Status` tinyint(4) DEFAULT '1' COMMENT '账号状态:1正常',
`AccountType` tinyint(4) DEFAULT '1' COMMENT '账号类型:1现金账号,2保证金账号',
`CreateTime` datetime DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`Id`)
其中一个用户可以对应多个账户,所以有一个AccountNo作为区分。 TranAmount为初始资金,用于重置账户。佣金字段用于模拟交易的手续费和税费。可用资金字段是,当用户挂单的时候有一部分资金处于冻结状态,可用资金就是去除冻结资金的金额。
`Id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模拟交易订单表',
`MemberCode` varchar(20) DEFAULT '' COMMENT '用户编号',
`AccountNo` varchar(20) DEFAULT '' COMMENT '模拟账号',
`SecuritiesType` varchar(10) DEFAULT '' COMMENT '股票类型:us,hk,sh,sz',
`SecuritiesNo` varchar(20) DEFAULT '' COMMENT '股票编号',
`CPrice` decimal(20,4) DEFAULT '0.0000' COMMENT '委托价',
`Price` decimal(20,4) DEFAULT '0.0000' COMMENT '价格',
`OrderQty` decimal(20,4) DEFAULT '0.0000' COMMENT '股票数据量',
`Side` char(1) DEFAULT '' COMMENT '交易类型:B买、S卖',
`OrdType` tinyint(4) DEFAULT '1' COMMENT '订单类型:1市场订单、2限价订单、3止损订单、4做空市场订单、5做空限价订单、6做空止损订单',
`execType` tinyint(4) DEFAULT '1' COMMENT '执行类型:0新的,1成交、2取消、3拒绝',
`Commission` decimal(20,4) DEFAULT '2.9900' COMMENT '佣金',
`Reason` tinyint(4) DEFAULT '0' COMMENT '订单拒绝理由:0正常、1资金不足、2仓位不足、3超时失效',
`Amount` decimal(20,4) DEFAULT '0.0000' COMMENT '金额',
`EndTime` datetime DEFAULT NULL COMMENT '订单截止时间',
`CreateTime` datetime DEFAULT NULL COMMENT '订单时间',
`TurnoverTime` datetime DEFAULT NULL COMMENT '成交时间',
PRIMARY KEY (`Id`)
这是最重要的两张表,其他几张表就不罗列详细的内容,只做简单说明
挂单的核心就是向数据库插入一条记录,不过即便是简洁的js代码,也差不多写了80行代码。 首先就是一系列的判断,是否可以创建订单。
撤单比挂单简单许多。主要步骤就是先判断订单是否存在,然后修改订单状态,同时修改可交易仓位或者可用资金。
系统每隔10秒执行一次逻辑。
如果每隔10秒钟从数据库读取所有订单的话,效率会很低,而且过多占用数据库IO资源。所以订单数据都缓存在成交判断的进程内存中。将来也可以升级为使用redis等内存数据库来存储。 当有订单创建的时候,通过消息队列通知进程。当进程重启的时候,从数据库读取数据进行初始化。
有些订单一直没有满足成交条件,但已经超过交易时间,所以要进行处理。(订单状态设置为拒绝)
未开盘则跳过。 根据订单类型判断是否达到成交条件
'订单类型:1市场订单、2限价订单、3止损订单、4做空市场订单、5做空限价订单、6做空止损订单' Price:订单设置的价格 price:当前股价 B:买入 S:卖出
let trigge = false
switch (OrdType) {
case 1:
trigge = true;
break;
case 2:
case 3:
trigge = Side == "BS" [OrdType - 2] ? (Price >= price) : (Price <= price)
break;
case 4:
trigge = true;
break;
case 5:
case 6:
trigge = Side == "BS" [6 - OrdType] ? (Price >= price) : (Price <= price)
break;
}
最初是用程序执行的,后来为了执行效率和数据一致性,采用存储过程。 首先,我们需要查询出账户的现金和可用资金,以及仓位信息。 如果是卖多或者买空(减少持仓,增加现金),我们计算出此时需要增加的金额,当然这个时候可能出现仓位不够的情况,就拒绝订单。 如果是买多或者卖空(增加持仓,减少现金),我们就需要计算此时需要扣除的金额,如果出现可用金额不足,就拒绝订单。 最后,我们修改账户的实际金额和可用金额,写入持仓记录和现金变化记录,修改订单状态为已成交状态。
普通数据库查询,这里不多赘述了。
由于模拟交易系统无法第一时间自动得到除权和除息的消息,所以当需要进行除权和除息的操作的时候,可能用户已经发生成交的订单。这时候需要根据持仓记录变更表进行一些计算,恢复正确的持仓,如果是除息就是根据现金记录变更表,进行资金重新计算。最后我们把这次操作的日志记录下来。
原网址: 访问
创建于: 2018-11-07 02:17:56
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论