交易命令系统2.0


数据库

1. 股票账户表

tbl_stockaccount

字段 类型 默认值 说明
uuid varchar(36) 主键
aliasname varchar(255) 别名
accountcode varchar(36) 交易用户ID
password varchar(36) 交易用户密码
brokerage varchar(36) virtual 券商 fake:假的 virtual:虚拟的
type varchar(36) normal 类型 normal:普通 try:试练操盘手 trade:操盘手
exchangerate double(11,2) 0 交易手续费
followid varchar(36) 跟随交易用户ID
status int(3) 0 当前状态 0:正常 2:异常

2. 交易命令历史表 每日一张表

tbl_commandhistoryYYYYMMDD

字段 类型 默认值 说明
uuid varchar(36) 主键
stockaccountid varchar(36) 账户ID
stockcode varchar(6) 股票代码
type varchar(20) 类型 buy:买入 sell:卖出
scale double(11,9) 0 比例 买入交易金额占余额比例 卖出股票数量占持仓比例
balance double(11,3) 0 交易前余额
holdcount int(11) 0 交易前持仓
count int(11) 0 交易数量
status int(3) 0 当前状态 0:正常 2:异常
pid varchar(36) 父命令ID
dir varchar(36) 所在文件夹 组ID
error varchar(255) 错误信息
starttime varchar(20) 操作开始时间
endtime varchar(20) 操作结束时间
operatetime varchar(20) 开始执行时间
operateduration int(11) 0 执行时长
totalduration int(11) 0 执行总时长

接口

Servlet

1. 开启股票账户

/servlet/openstockaccount
此接口需要先到虚拟交易所开户,才可以使用

Request:
{
        "aliasname":"lichen",         //别名 英文中文手机号
        "password":"12345678",        //密码 6~20位 任意
        "accountcode":"qwertyuioasdfghjkzxcvbnm",  //交易所用户ID
        "brokerage":"virtual",        //券商
        "type":"normal",              //类型    normal:普通  try:试练  trade:操盘手
        "exchangerate":"2.5"          //交易费率
}
Response:
{
        "statusCode":"000000",
        "result":{
            "uuid":"dsaf6d87sfa89sdf7asdfhasdilfakds",
            "aliasname":"lichen",
            "password":"1a2bc3d4e5f6g7h8i9j0k",
            "accountcode":"qwertyuioasdfghjkzxcvbnm",
            "brokerage":"virtual",
            "exchangerate":"2.5",
            "type":"normal",
            "status":"0",
            "followid":""
         }
}

2. 关闭股票账户

/servlet/closestockaccount

Request:
{
        "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds", //账户ID
}
Response:
{
        "statusCode":"000000",
        "result":"ok"
}

3. 修改密码

/servlet/changepassword
此接口 需要先到虚拟交易所修改后,这里才能生效

Request:
{
        "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds", //账户ID
        "password":"12345678",        //密码 6~20位 任意
}
Response:
{
        "statusCode":"000000",
        "result":{
            "uuid":"dsaf6d87sfa89sdf7asdfhasdilfakds",
            "aliasname":"lichen",
            "password":"1a2bc3d4e5f6g7h8i9j0k",
            "accountcode":"qwertyuioasdfghjkzxcvbnm",
            "brokerage":"virtual",
            "exchangerate":"2.5",
            "type":"normal",
            "status":"0",
            "followid":""
         }
}

4. 修改类型

/servlet/changetype

Request:
{
        "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds", //账户ID
        "type":"try",              //类型    normal:普通  try:试练  trade:操盘手
}
Response:
{
        "statusCode":"000000",
        "result":{
            "uuid":"dsaf6d87sfa89sdf7asdfhasdilfakds",
            "aliasname":"lichen",
            "password":"1a2bc3d4e5f6g7h8i9j0k",
            "accountcode":"qwertyuioasdfghjkzxcvbnm",
            "brokerage":"virtual",
            "exchangerate":"2.5",
            "type":"try",
            "status":"0",
            "followid":""
         }
}

5. 跟随操盘手

/servlet/followtrader
此账户需要是 普通账户,并且跟随的操盘账户需要是试练或者操盘手

Request:
{
        "stockaccountid":"234jk32khi2u4wejfq432nrkew23jknk", //账户ID
        "password":"12345678",                               //密码 6~20位 任意
        "followid":"dsaf6d87sfa89sdf7asdfhasdilfakds",       //跟随操盘账户ID
}
Response:
{
        "statusCode":"000000",
        "result":{
            "uuid":"234jk32khi2u4wejfq432nrkew23jknk",
            "aliasname":"xiaoming",
            "password":"1a2bc3d4e5f6g7h8i9j0k",
            "accountcode":"kmfjo3m2f98dsn4iund8s4nijruvh2",
            "brokerage":"virtual",
            "exchangerate":"2.5",
            "type":"normal",
            "status":"0",
            "followid":"dsaf6d87sfa89sdf7asdfhasdilfakds"
         }
}

6. 解除跟随操盘手

/servlet/unfollowtrader

Request:
{
        "stockaccountid":"234jk32khi2u4wejfq432nrkew23jknk", //账户ID
        "password":"12345678",                               //密码 6~20位 任意
}
Response:
{
        "statusCode":"000000",
        "result":{
            "uuid":"234jk32khi2u4wejfq432nrkew23jknk",
            "aliasname":"xiaoming",
            "password":"1a2bc3d4e5f6g7h8i9j0k",
            "accountcode":"kmfjo3m2f98dsn4iund8s4nijruvh2",
            "brokerage":"virtual",
            "exchangerate":"2.5",
            "type":"normal",
            "status":"0",
            "followid":""
         }
}

7. 买入股票

/servlet/buystock

Request:
{
        "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds", //账户ID
        "password":"12345678",                        //密码 6~20位
        "stockcode":"601988",                         //股票代码
        "count":"1000"                                //买入数量
        "execute":"true",                             //是否真实执行
}
Response:
{
        "statusCode":"000000",
        "result":{
            "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds"
            "stockcode":"601988",
            "type":"buy",
            "price":"7.12",
            "count":"1000",
            "holdstockbefore":"0",
            "holdstockafter":"1000",
            "balancebefore":"46000",
            "balanceafter":"38862.2",
            "exchangeamount":"17.8",
            "stockamount":"7120",
            "totalamount":"7137.8"
        }
}

8. 买出股票

/servlet/sellstock

Request:
{
        "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds", //账户ID
        "password":"12345678",                        //密码 6~20位
        "stockcode":"601988",                         //股票代码
        "count":"1000"                                //买入数量
        "execute":"true",                             //是否真实执行
}
Response:
{
        "statusCode":"000000",
        "result":{
            "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds"
            "stockcode":"601988",
            "type":"sell",
            "price":"7.12",
            "count":"1000",
            "holdstockbefore":"0",
            "holdstockafter":"1000",
            "balancebefore":"38862.2",
            "balanceafter":"45964.4",
            "exchangeamount":"17.8",
            "stockamount":"7120",
            "totalamount":"7102.2",
            "createtime":"2017-06-13 15:18:32"
        }
}

9. 统计数据

/servlet/commandcount

Request:
{
        "duration":"100",                         //间隔时间
        "samplerate":"2",                         //采样率
}
Response:
{
        "statusCode":"000000",
        "result":{
            "stockaccountid":"dsaf6d87sfa89sdf7asdfhasdilfakds"
            "stockcode":"601988",
            "type":"sell",
            "price":"7.12",
            "count":"1000",
            "holdstockbefore":"0",
            "holdstockafter":"1000",
            "balancebefore":"38862.2",
            "balanceafter":"45964.4",
            "exchangeamount":"17.8",
            "stockamount":"7120",
            "totalamount":"7102.2",
            "createtime":"2017-06-13 15:18:32"
        }
}

Cache存储结构

|名称|说明|结构|
|:--|:--:|
|cachekey_stockaccount_uuid|账户集合|Map<uuid,StockAccountMap>|
|cachekey_stockaccount_accountcode|账户名集合|Map<accountcodeid, StockAccountMap >|
| cachekey_stockaccount_followid|跟随账户集合|Map<followid, List<StockAccountMap>>|
|cachekey_stockdata_600189|股票信息|JSON|

数据算法

配置文件

配置项 默认值 说明
TASK_THREADPOOL_SIZE 100 任务执行者数量
REQUEST_TRADE_THREADPOOL_SIZE 10 http请求线程数量
REQUEST_TRADE_MAXCOUNT 100 单词请求最大命令数量
IS_FAKE_TRADE false 是否使用假交易所
MAX_NEW_COMMAND_COUNT 最大新指令数量
TRADE_VIRTUAL_BASEURL 虚拟交易所地址
COMMAND_FILE_ROOT 指令文件夹

文件夹

hero 为父命令文件夹
每一个父命令均创建一个命令组文件夹,组文件夹名是每个小时做一个基础名,后面跟着自增数列,每个文件夹中只有一个文件,就是操盘手的指令文件。
new 为命令文件夹
hero文件夹里面将父指令拷贝到new文件夹中,并通过查询跟随账户,为每一个跟随账户创建指令文件。最后将hero中的父命令文件删除。
这是一个命令放大器,如果被放大的命令太多,会导致inodes过大,所以在配置文件中指定了一个最大新指令数量。
dispatched 为分发文件夹
分发任务从new文件夹里获得任务,并移动到dispatched文件夹中,这些待执行命令按照账户分别分配给了每个账户的执行者,有单独线程驱动执行中进行一步一步执行。
执行者总共有6步:

1. 获取一个命令,并按照账户写入命令文件(每天一个),将文件从`dispatched`移动到`process`中
2. 发送查询请求,等待响应
3. 获得查询结果,将查询结果保存到命令对象中
4. 发送交易请求,等待响应
5. 获得交易结果,将交易结果保存到命令对象中
6. 事后处理,补写账户命令文件,将文件写入到`finished`中,并删除`process`中的文件

database 为数据库文件夹
将完成的命令,写入到入库文件中new.db,此文件所在的文件夹为每分钟一个。当数据库准备执行时,将此文件改名为process.db
history 为数据库历史文件夹
入库完成后,将process.db文件内容写入到历史文件中,此文件每小时一个,并删除process.db文件

new 为命令文件夹
dispatched 为分发文件夹
process 为执行文件夹
finished 为完成文件夹
这4个文件夹结构完全一致,分别代表任务所处阶段。

文件夹示例

[-]/CacheFile/SyncCommand
    [-]hero
         [-]GID20160814165223_00000000009.cmd   #组ID
             [+]a1s23d3d4f5g6h76j87jk90.cmd       #操盘手命令
    [-]new
             [-]GID20160814165223_00000000007.cmd   #组ID
                   [+]a1s23d3d4f5g6h76j87jk90.cmd       #操盘手命令
                   [+]s23d4f5g6h7j8k9k8j7h6g5.cmd      #跟随命令
                   [+]z12x3c4v5b6n78m8mn7b6.cmd      #跟随命令
                   [+]4c3xz28u7y6t5r4e3w2q3e.cmd      #跟随命令
             [-]GID20160814165223_00000000008.cmd   #组ID
                   [+]a1s23d3d4f5g6h76j87jk90.cmd       #操盘手命令
                   [+]s23d4f5g6h7j8k9k8j7h6g5.cmd      #跟随命令
                   [+]z12x3c4v5b6n78m8mn7b6.cmd      #跟随命令
                   [+]4c3xz28u7y6t5r4e3w2q3e.cmd      #跟随命令
    [-]dispatched
             [-]GID20160814165223_00000000005.cmd   #组ID
                   [+]z12x3c4v5b6n78m8mn7b6.cmd      #跟随命令
                   [+]4c3xz28u7y6t5r4e3w2q3e.cmd      #跟随命令
            [-]GID20160814165223_00000000006.cmd   #组ID
                   [+]a1s23d3d4f5g6h76j87jk90.cmd       #操盘手命令
                   [+]s23d4f5g6h7j8k9k8j7h6g5.cmd      #跟随命令
                   [+]z12x3c4v5b6n78m8mn7b6.cmd      #跟随命令
    [-]process
            [-]GID20160814165223_00000000005.cmd   #组ID
                   [+]a1s23d3d4f5g6h76j87jk90.cmd       #操盘手命令
                   [+]s23d4f5g6h7j8k9k8j7h6g5.cmd      #跟随命令
            [-]GID20160814165223_00000000006.cmd   #组ID
                   [+]4c3xz28u7y6t5r4e3w2q3e.cmd      #跟随命令
    [-]database
            [-]201608141622.cmd       #每分钟一个文件夹
                  [+]process.db        #正在入库的文件
            [-]201608141623.cmd       #每分钟一个文件夹
                   [+]new.db      #待入库的文件
            [-]201608141624.cmd       #每分钟一个文件夹
                   [+]new.db      #待入库的文件
    [-]history
            [+]2016081415.cmd       #每小时一个文件
            [+]2016081416.cmd       #每小时一个文件

技巧

线程使用技巧

当处于高频HTTP发送的时候,有两种解决方案:

1.使用单线程异步请求
做一个任务队列,和请求类列表(回调使用),然后单线程来获得队列中任务,制作成请求,调用异步请求,并将请求ID作为Attribute传出,在异步获得结果后,取出请求ID以及结果,在请求类列表中找到指定的请求,将结果作为参数去调用回调方法。

此方案优点: 写法简单明了 缺点:单线程调用
注意: 异步请求

2.使用多线程同步请求
做指定线程数量的线程池,和任务执行实例,做一个请求任务队列,然后单线程来获得一个执行类,判断是否是空闲,并让线程池启动执行类,执行类启动后,从任务列表中获取任务,制作成请求,调用同步请求,获得结果后,将结果作为参数去调用请求的回调方法。

此方案优点: 多线程调用 可以指定若干执行实例,由线程池控制执行线程数 缺点:结构复杂,不便于维护
注意:在线程池执行任务前,需要先判断线程是否运行,这里防止多任务进入单线程,将前任务覆盖。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容