數(shù)據(jù)庫
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 | 交易手續(xù)費 |
followid | varchar(36) | 跟隨交易用戶ID | |
status | int(3) | 0 | 當前狀態(tài) 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 | 比例 買入交易金額占余額比例 賣出股票數(shù)量占持倉比例 |
balance | double(11,3) | 0 | 交易前余額 |
holdcount | int(11) | 0 | 交易前持倉 |
count | int(11) | 0 | 交易數(shù)量 |
status | int(3) | 0 | 當前狀態(tài) 0:正常 2:異常 |
pid | varchar(36) | 父命令ID | |
dir | varchar(36) | 所在文件夾 組ID | |
error | varchar(255) | 錯誤信息 | |
starttime | varchar(20) | 操作開始時間 | |
endtime | varchar(20) | 操作結束時間 | |
operatetime | varchar(20) | 開始執(zhí)行時間 | |
operateduration | int(11) | 0 | 執(zhí)行時長 |
totalduration | int(11) | 0 | 執(zhí)行總時長 |
接口
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" //買入數(shù)量
"execute":"true", //是否真實執(zhí)行
}
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" //買入數(shù)量
"execute":"true", //是否真實執(zhí)行
}
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. 統(tǒng)計數(shù)據(jù)
/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|
數(shù)據(jù)算法
配置文件
配置項 | 默認值 | 說明 |
---|---|---|
TASK_THREADPOOL_SIZE | 100 | 任務執(zhí)行者數(shù)量 |
REQUEST_TRADE_THREADPOOL_SIZE | 10 | http請求線程數(shù)量 |
REQUEST_TRADE_MAXCOUNT | 100 | 單詞請求最大命令數(shù)量 |
IS_FAKE_TRADE | false | 是否使用假交易所 |
MAX_NEW_COMMAND_COUNT | 最大新指令數(shù)量 | |
TRADE_VIRTUAL_BASEURL | 虛擬交易所地址 | |
COMMAND_FILE_ROOT | 指令文件夾 |
文件夾
hero
為父命令文件夾
每一個父命令均創(chuàng)建一個命令組文件夾凰盔,組文件夾名是每個小時做一個基礎名,后面跟著自增數(shù)列,每個文件夾中只有一個文件,就是操盤手的指令文件。
new
為命令文件夾
從hero
文件夾里面將父指令拷貝到new文件夾中痪伦,并通過查詢跟隨賬戶,為每一個跟隨賬戶創(chuàng)建指令文件雹锣。最后將hero
中的父命令文件刪除网沾。
這是一個命令放大器,如果被放大的命令太多蕊爵,會導致inodes過大辉哥,所以在配置文件中指定了一個最大新指令數(shù)量。
dispatched
為分發(fā)文件夾
分發(fā)任務從new
文件夾里獲得任務,并移動到dispatched
文件夾中攒射,這些待執(zhí)行命令按照賬戶分別分配給了每個賬戶的執(zhí)行者醋旦,有單獨線程驅動執(zhí)行中進行一步一步執(zhí)行。
執(zhí)行者總共有6步:
1. 獲取一個命令会放,并按照賬戶寫入命令文件(每天一個)饲齐,將文件從`dispatched`移動到`process`中
2. 發(fā)送查詢請求,等待響應
3. 獲得查詢結果咧最,將查詢結果保存到命令對象中
4. 發(fā)送交易請求捂人,等待響應
5. 獲得交易結果,將交易結果保存到命令對象中
6. 事后處理矢沿,補寫賬戶命令文件滥搭,將文件寫入到`finished`中,并刪除`process`中的文件
database
為數(shù)據(jù)庫文件夾
將完成的命令咨察,寫入到入庫文件中new.db论熙,此文件所在的文件夾為每分鐘一個。當數(shù)據(jù)庫準備執(zhí)行時摄狱,將此文件改名為process.db
history
為數(shù)據(jù)庫歷史文件夾
入庫完成后脓诡,將process.db文件內容寫入到歷史文件中,此文件每小時一個媒役,并刪除process.db文件
new
為命令文件夾
dispatched
為分發(fā)文件夾
process
為執(zhí)行文件夾
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發(fā)送的時候酣衷,有兩種解決方案:
1.使用單線程異步請求
做一個任務隊列交惯,和請求類列表(回調使用),然后單線程來獲得隊列中任務,制作成請求,調用異步請求席爽,并將請求ID作為Attribute傳出意荤,在異步獲得結果后,取出請求ID以及結果只锻,在請求類列表中找到指定的請求玖像,將結果作為參數(shù)去調用回調方法。
此方案優(yōu)點: 寫法簡單明了 缺點:單線程調用
注意: 異步請求
2.使用多線程同步請求
做指定線程數(shù)量的線程池齐饮,和任務執(zhí)行實例捐寥,做一個請求任務隊列,然后單線程來獲得一個執(zhí)行類祖驱,判斷是否是空閑握恳,并讓線程池啟動執(zhí)行類,執(zhí)行類啟動后捺僻,從任務列表中獲取任務乡洼,制作成請求,調用同步請求陵像,獲得結果后就珠,將結果作為參數(shù)去調用請求的回調方法寇壳。
此方案優(yōu)點: 多線程調用 可以指定若干執(zhí)行實例醒颖,由線程池控制執(zhí)行線程數(shù) 缺點:結構復雜,不便于維護
注意:在線程池執(zhí)行任務前壳炎,需要先判斷線程是否運行泞歉,這里防止多任務進入單線程,將前任務覆蓋匿辩。