下单设计概要

 

1.1.1    普通、高级单本地下单

对应功能号:854002

详细逻辑

  1. 调用get_variety_info,取得品种和交割期。
  2. 如果传入的[席位号]是空,则根据传入的[交易所],取到一个可用的席位。
  3. 如果传入的[交易编码]是空,则根据传入的[客户号]和[席位号],取到一个可用的交易编码。
  4. 调用verify_order_type,对定单类型和成交属性关系进行校验。该校验依赖的是系统表order_type_rule的定义。
  5. 调用single_entrust_verify,进行委托下单校验。

1)   到交易所信息表,校验交易所的状态是否正常,如果停用了就不允许下单了。

2)   到席位信息表,校验席位的状态是否正常,如果出于非“正常”状态,就不允许下单了。

3)   如果委托单类型不是预埋类型,则调用SettleTradePara取得该席位的交易状态(交易参数STATUS),如果非“开盘”状态则不允许下单。

4)   根据交易所代码、品种代码和交割期、席位号,来检查合约是否存在;并且检查合约状态是否已经过期、是否只允许平仓。

5)   如果委托价是0且非预埋单,则判断该席位是否允许下市价单(即ZC_SJD参数),如果不支持则直接报错不允许下单。

6)   如果委托价不是0且不是-1,则判断该席位是否要判断涨跌停板价格(即PDZDT参数),如果要判断,则看委托价是否超过了涨跌停板的价格范围。

7)   如果为平今委托单,查找该席位号是否允许下平今委托单(即SUPPORTPJD参数)

8)   调用verify_oper_trade_restricted进行操作员交易限制的校验。

  1. 取得本次委托需要使用的本地委托号。
  2. 调用single_entrust_deal,进行本地下单处理。

1)   如果不是平仓,则直接调用single_entrust进行本地下单处理。

2)   如果是平仓,则调用split_close_today判断是否需要拆分平今单。该判断的结果有一下几种:拆分标记为0表示不拆分,直接调用single_entrust进行本地下单处理;拆分标记为1表示拆分的,所以会分两次调用single_entrust,分别处理平仓和拆分后的平今;拆分标记为2表示全部转化为平今单,也是直接调用single_entrust进行本地下单处理。另外,如果拆分标记是1,还要插一笔记录到原始委托表。

3)   Single_entrust的逻辑:

a)   调用verify_oper_cust校验操作员客户对应关系。

b)   校验客户状态:销户否?冻结否?只可平仓否?其他异常?

c)   如果交易编码为空,则根据客户号和席位号找到一个可用的;如果非空,则校验一下交易编码表中是否存在。

d)   如果是开仓,则校验最大、最小下单手数、最大持仓手数,校验保值额度。

e)   如果是市价委托,则取一个冻结手续费和保证金的时候的基准价格(显然不能用0嘛,用0就变成一分钱都不冻结了),取这个冻结价的逻辑是:市价买则取涨停价,市价卖则取跌停价,如果涨跌停价取不到则取昨结算价,昨结算价也取不到就不允许下单了。另外,由于中金所最后交易日不限价格,因此当卖开时,需要将取得的这个冻结价与买价比较,取值大的那个作为冻结价。

f)   调用get_commi_fee计算需要冻结的手续费。

g)   调用verify_share_money取得是否资金共享。

h)   开仓分支:

ü  调用get_cust_margin计算需要冻结的保证金。

ü  锁资金表。

ü  根据是否资金共享,取得该客户的可用和动态权益。

ü  满仓权限处理:如果需要冻结的保证金和手续费超过了其可用的数额,且委托单类型是是“批量下单”或者“预埋批量委托”,则判断该客户是否有满仓权限(权限位第220位),如果没有满仓权限,则报资金不够的错;如果有满仓权限,则以该客户目前可用最多可开的手数作为实际下单的手数,重新冻结手续费和保证金。

ü  判断资金占用率是否超标(即ZJZYL参数)。

i)   平仓分支:

ü  锁资金表。

ü  调用close_amt查询可平量,如果可平量小于委托量,则报错。注意这里没有判断满仓权限的逻辑,不知道为什么呵呵,历史上就是这么下来的。

j)   平今分支:

ü  调用close_today_amt查询可平今量,如果可平今量小于委托量,且委托单类型是“批量委托”或者“批量预埋委托”,则还要判断满仓权限,如果有满仓权限,则以该客户可平今的最大量作为委托量,重新冻结手续费。

k)   插一条记录到委托表。

l)   如果私有标识和私有流水号不为空,则调用insert_private_info写入私有流水表。

m)   更新实时资金表,需要更新的字段是:冻结手续费、买/卖冻结保证金、总冻结、可用。

n)   如果是强平委托单,则插一条记录到强平委托表cust_force_offset_entrust

  1. 调用push_entrust,进行推送处理。推送的对象,是某个报盘机的登录操作员。
  2. 如果有接口登录,则将该笔委托单的状态更新为s单。
  3. 记录日志。

1.1.2    普通、高级单的委托回报

对应功能号:854020

详细逻辑:

  1. 如果传入的委托号是0,则调用get_max_no取得一个委托号,以备后用。
  2. 根据委托号从普通委托表cust_entrust中找该笔委托单,如果没有找到,再根据系统号找一遍。找委托单的目的,是为了取得该笔委托的客户号、买卖、开平、委托量。如果找到了,且传入的[委托号]是0,则不使用找到的这个委托号;如果没有找到,且传入的[委托号]是0,则使用第一步中找到的委托号。
  3. 校验传入的[买卖][投保][开平]和表中取得的,如果都是空,则报错;否则就使用有值的那个。校验[委托量]和表中取得的,如果都是0,则报错。
  4. 如果委托表中没有找到客户且传入的[客户号]也是空,则根据交易编码找客户号。
  5. 调用verify_share_money,得到该客户是否资金共享。并取得客户简称。
  6. 锁资金表。
  7. 如果传入的[修改批次]不为0,则和表中的修改批次比较,如果不一致则报错。
  8. 根据传入的[错误标记]进行分支。

1)   成功分支:

a)   为防止收到多条委托回报,看一下该交易所该系统号下的委托单的申报时间是否存在(申报时间就是委托回报的时间),如果存在,那么再看其触发时间是否已经有了,如果也有了那么肯定是重复发的,报错丢弃;如果触发时间没有,说明是触发回报晚回来了,把触发时间更新。

b)   根据客户实时成交表cust_real_done中是否存在传入系统号的成交记录,分分支去更新普通实时委托表cust_entrust的相应字段(释放的冻结、成交手数等都会不同,所以要分支处理):如果该笔委托不存在,则说明非本系统单,那么补单。补单的逻辑大致同下单逻辑,不同之处在于,补单不会判断资金是否足够、资金占用率是否超标(如果是开仓),也不会判断持仓是否足够(如果是平仓),因为非本系统单有可能也不判断的,补单的目的只是为了将委托单补到本地系统而已。

2)   失败分支:

a)   在实时委托表cust_entrust中,根据传入的[委托号]搜索该笔委托,如果找不到则直接报错。

b)   修改客户实时资金表cust_real_fund。

c)   修改客户实时委托表cust_entrust(由于撤单回报交易所没有传交易编码,因此补委托单时客户号、买卖、开平、投保不准确,找到委托记录时更新这些字段)。

  1. 调用push_entrust_return,进行推送处理。
  2. 输出结果集。
  3. 记录日志。

1.1.3    普通、高级单的撤单

对应功能号:854018

详细逻辑

  1. 直接调用公共函数withdraw_entrust进行撤单处理。withdraw_entrust的逻辑:

1)   找到交易所代码。如果[下单席位]是空则肯定是本系统单,到交易所席位对应关系表中找;如果[下单席位]非空则到普通委托表中查找。

2)   调用verify_oper_cust校验操作员客户对应关系。

3)   锁资金表。

4)   校验:如果下单人为客户并且强平标记为1,则不允许撤单。

5)   如果[强平标志]为'1' , 则校验撤单操作员是否有强平的权限,若有,继续,若没有报错退出。

6)   若该笔委托单当前状态非等待发出、非已经报入、非部分成交,则不允许撤销。

7)   如果该笔委托单当前状态是等待发出:

a)   更新普通委托表信息。

b)   调用verify_share_money,看该客户是否资金共享,并依此更新实时资金表(因为单子还在本地,所以不需要等撤单回报的时候再更新资金,且撤单回报也无需发往报盘机了)。

c)   调用push_withdraw_entrust,进行撤消委托的推送处理(无需发往报盘机)。

8)   如果该笔委托单当前状态不是等待发出:

a)   校验席位号是否在开盘状态,如果不是则报错。

b)   更新普通委托表。

c)   调用push_withdraw_entrust,进行撤消委托的推送处理(这个分支里面,推送是要发往报盘机的)。

9)   根据上层sp的接口定义,输出结果集。

10)  记录一条日志到操作日志。因为本公共函数还会被批量撤单接口调用,所以虽然上层sp854018已经记录日志了,内层也需要记录。而在热备恢复的时候,同一比单子撤两次是没有关系的。

  1. 记录到操作日志。

1.1.4    普通、高级单的撤单回报

对应功能号:854021

详细逻辑

  1. 对委托回报,交易所给的[委托号]是0的处理。
  2. 如果输入参数[修改批次]不为0,表示是手工报单调用,则根据系统号查询对应的委托号、交易所代码和下单席位,然后跟传入的委托号、交易所代码和下单席位进行比较,如果不一致则报错(手工报单一定会传这3个字段,但如果是交易所调用,则不一定会给这3个字段了)。
  3. 根据[成功标志]分支处理:

1)   成功分支:

a)   找到对应客户:先找普通委托表――先根据系统号找,找不到的话根据委托号找;如果普通委托表找不到,再根据系统号去成交表找。如果依然找不到,且传入交易编码非空,则根据交易编码找。如果找不到,则跳过下面锁定资金表的步骤。虽然仍然存在委托回报与撤单回报并发性问题(也就是非本系统单子撤单回报先回,本地什么信息都没有的情况),但是暂时不进行处理,用手工报单去解决。

b)   调用verify_share_money,判断客户是否类内资金共享,依此锁住资金表。如果找到了,则锁定资金表;如果不是根据交易编码找到的客户号,则重取该笔委托单的信息(锁完资金后的数据,才是保证正确的数据)

c)   如果传入的[修改批次]不为0,则和表中的修改批次比较,如果不一致则报错。

d)   如果前面找要撤的那笔单的时候找不到,则补单,补一笔委托到普通委托表。

e)   更新实时资金表。

f)   更新实时委托表。

2)   失败分支:

a)   找到要撤的那笔单:先根据委托号找,再根据系统号找,如果都找不到则报错。

b)   判断当前委托状态是否已经是最终态了,是的话直接跳出,不需要进行后续处理喽。

c)   调用verify_share_money,判断客户是否类内资金共享,依此锁住资金表。

d)   如果传入的修改批次不为0,则和表中的修改批次比较,如果不一致则报错。

e)   确定该笔委托当前应该是什么状态(因为撤单的时候,委托状态会变成等待撤除,所以在撤单失败的时候需要恢复回来)。

f)   更新委托表。

  1. 调用push_withdraw_return,进行推送处理。
  2. 根据外层接口约定,输出结果集。
  3. 记录一条日志到操作日志表。

1.1.5    组合本地下单

对应功能号:854300

详细逻辑

  1. 如果[席位号]为空的情况下,需要根据交易所代码找出可交易的席位号,如果存在多个,任意选择一个席位号填入。
  2. 如果交易编码为空,根据客户号、席位号找到对应的交易编码,如果有多个交易编码,取主交易编码;如果交易编码不为空,根据根据客户号,席位号,交易编码查找对应的记录,如果查找到的记录数不为1,则报错。
  3. 调用verify_oper_cust校验操作员对该客户是否有操作权限。
  4. 调用verify_combination_entrust校验组合委托下单前提条件:

1)   校验交易所的状态是否正常。

2)   校验席位的状态是否正常。

3)   判断组合买卖、组合开平是否是有效值。

4)   判断组合开平,如果为3平今则报错。

5)   判断组合投保标记,如果是1保值则报错。

6)   判断强平标志,如果是1强平则报错。

7)   调用verify_order_type校验定单类型规则是否正确。

8)   判断席位状态,是否处于未开盘状态,如果是的话,只有预埋单才可以下,其它类型的委托全部报错拒绝。(以后可能会有未开盘委托,那么这里的判断逻辑就需要改造)

  1. 调用verify_combination_contract校验组合合约合法性:

1)   根据输入参数在组合合约表ca_contract中查询是否有对应的组合合约存在。

2)   校验组合合约的状态:如果该组合合约的状态是只可平仓,那么校验当前[开平标记]是否是平仓;如果该组合合约的状态是停用,那么也不允许委托下单。

3)   调用get_combination_strategy得到策略各腿的计算规则,该子过程的信息是取自策略规则表combination_strategy_rule。目前的交易代码中,一个组合策略的策略规则,完全是依赖这张策略规则表的,所以后期如果要新增或者修改现有规则,那么只需要改这个表的基础数据即可。

4)   判断调用get_combination_strategy后得到的腿数量,是否和输入参数合约代码1、合约代码2、合约代码3、合约代码4不为’’的单腿合约的数量相同。

5)   调用get_comb_vari_info得到各腿合约对应的品种、交割期。

6)   判断各个单腿合约的合法性和状态,是否允许下单。

7)   调用verify_oper_trade_restricted,对各个单腿合约进行操作员交易限制的校验。

  1. 调用get_max_no取得当前最大的委托号。
  2. 调用组合下单公共函数combination_entrust_deal进行组合下单:

1)   取得客户状态,判断该状态在当前情况下是否允许下单。

2)   调用verify_share_money判断是否是类内资金共享客户。

3)   查询交易合约表trade_contract,判断各单腿合约的最大、最小手数是否超限。

4)   锁资金表。

5)   调用ca_max_eo_hands,取得最大可开可平手数,如果申报手数不符合可开/可平手数的限制,则报错。

6)   如果是组合开仓,则判断资金占用率是否超标。

7)   将委托记录插入组合委托表,其中系统号填'',各腿的成交量、成交价填0,总的成交量、成交价填0,申报时间、撤单时间、撤单操作员填'',委托状态填'n',处理接口名填'',修改批次填1,本地标志填'0',下单席位填''。

8)   如果私有标识和私有流水号不为空,则调用insert_private_info写入私有流水表。

9)   处理客户实时资金表。

  1. 调用push_entrust进行推送处理。
  2. 按照本接口约定,输出结果集。
  3. 记录操作日志。
  4. 错误分支:

1)   调用insert_error_combination插入组合错误委托表。

2)   记录日志。

3)   输出错误代码和错误信息。

1.1.6    组合单委托回报

对应功能号:854320

详细逻辑

  1. 判断传入的[修改批次]是否和组合委托表中修改批次一致,不一致报错。
  2. 根据[委托号],在组合委托表中查询客户号,如果没有找到,则根据交易编码找客户号,如果还找不到就报错。
  3. 调用verify_share_money,判断客户是否类内资金共享,根据是否是共享资金客户,来锁定客户实时资金表。
  4. 根据[是否成功]标志进行分支处理:

1)   成功分支:

a)   首先需要注意的一点是:组合委托不补单,如果找不到委托就报错了。

b)   为了防止收到多条委托回报,到组合委托表中查询该笔委托的申报时间,如果申报时间非空,则说明收到过该笔委托的委托回报了,报错。

c)   根据实时成交表中是否存在该[系统号]的成交记录,去更新组合委托表。

2)   失败分支:

a)   从组合委托表中查询对应的委托信息,如果不存在则报错。

b)   从策略规则表中取得对应各腿的买卖方向,依此计算买卖冻结保证金,从而去更新实时资金表。

c)   修改组合委托表的相应记录,将冻结的保证金和手续费都释放。

  1. 调用push_entrust_return进行推送处理。
  2. 根据接口要求输出结果集。
  3. 记录到操作日志。

1.1.7    组合单的撤单

对应功能号:854301

详细逻辑

直接调用cancel_combination_entrust,进行组合单的撤单:

  1. 找到需要撤单的那笔委托单,首先找到交易所代码。如果找到的委托单不是1条,则报错。
  2. 调用verify_oper_cust,判断操作员是否对此客户有操作权限。
  3. 调用verify_share_money,判断是否是类内资金共享客户,据此锁定资金表。
  4. 根据委托号、交易所代码、下单席位,去组合委托表取得该笔委托单的详细信息,比如:下单操作员、委托单状态、组合买卖方向、币种、冻结保证金、冻结手续费、指令编码(为以后批量改价撤单使用)、合约1、合约2、合约3、合约4、策略代码、组合类型、组合开平。
  5. 调用get_combination_strategy,得到该笔委托的腿数量、各腿的买卖、开平、投保。
  6. 判断委托单状态是否可以撤单。
  7. 如果委托单状态是等待发出,说明该笔委托尚未发往接口,则直接更新组合委托表中的委托单状态为已经撤销;同时,将该笔委托单占用的资金释放(即同时更新实时资金表),并且调用push_withdraw_entrust进行推送数据的准备。
  8. 如果委托单状态是已经报入或者部分成交,首先需要校验当前席位是否处于开盘状态;如果通过校验,则更新委托状态为等待撤销,并且调用push_withdraw_entrust进行推送数据的准备。
  9. 根据854301的接口约定,输出推送结果集。
  10. 记录一条日志到操作日志表。
  11. Return 0。
  12. 错误分支:

1)   更新组合委托表对应记录的备注和修改批次,也就是将错误信息更新到委托记录上。

2)   将错误信息拼接输入参数后作为报错信息。

3)   记录一条日志到操作日志表。

1.1.8    组合单撤单回报

对应功能号:854321

详细逻辑

  1. 首先查找需要撤单的那笔组合委托单,如果根据系统号找和根据委托号找都没有找到,则报错。组合委托不补单。
  2. 如果是手工报单调用,则需要校验传入的[修改批次]和表中的是否一致,如果不一致则报错。
  3. 调用verify_share_money判断客户是否类内资金共享,据此锁资金表。
  4. 根据撤单的成功失败进行分支处理:

1)   成功分支:

a)   重新取得该笔组合委托的信息,然后计算得到以下值:剩余的总冻结保证金和剩余总冻结手续费、剩余的各腿的冻结保证金和剩余的各腿的冻结手续费;并根据该笔委托的策略,计算其买卖冻结保证金。把这部分计算得到的数据更新到实时资金表。

b)   更新组合委托表:如果成交手数不为0,修改委托单状态为部成部撤;否则修改委托状态为已经撤消。并且更新撤单时间。

2)   失败分支:

a)   找到该笔组合委托单,取得其委托单信息。

b)   校验取得的委托状态,如果是最终状态了,则报错退出,将本次撤单回报丢弃。

c)   确定委托状态,逻辑依次如下:如果取得的系统号是空,则委托状态是“等待发出”;如果成交量是0,则委托状态是“已经报入”;如果剩余量不为0,则委托状态是“部分成交”;以上都不是则委托状态是“全部成交”。

d)   更新组合委托表。

  1. 调用push_withdraw_return进行推送数据准备。根据接口约定输出推送结果集。
  2. 记录一条日志到操作日志表。

1.1.9    成交回报

对应功能号:854024

详细逻辑

  1. 校验:

1)   如果传入的[交易所成交号]是AUTO,则说明是手工报单调用,于是自动生成一个交易所成交号。

2)   如果输入合约号不为空,调用get_variety_info拆分品种代码和交割期。

3)   根据传入的[品种代码]、[交割期],从交易合约表中查找该合约的信息;找不到或者找到多条都报错。

4)   根据交易编码和席位号找到客户号;如果查询出来的客户号不为1则去委托表中查询出对应的客户号,还找不到则报错。

  1. 公共业务处理:

1)   调用verify_share_money判断该客户是否类内资金共享,据此锁定资金表。

2)   调用get_commi_fee取得成交手续费。

3)   如果是开仓,则分别调用get_cust_marginget_exch_margin计算优惠前的成交保证金和成交交易所保证金。

4)   从委托表查找该笔委托单的信息,先根据委托号找,再根据系统号找;先找普通委托表再找组合委托表。

5)   如果传入的修改批次不为0,则和表中的修改批次比较,如果不一致则报错。

6)   如果是组合委托,还要获得对应的策略规则信息。

  1. 根据开平标记进行处理:

1)   开仓处理:

a)   如果没收到过传入[系统号]的成交单,则插一笔成交到实时成交表。

b)   插入一笔持仓,到客户实时持仓明细表。

c)   如果是组合开仓则插入组合持仓表。

d)   更新客户实时持仓汇总表信息,如果没有汇总信息则新插入一条记录到实时持仓汇总表。

e)   更新委托表的委托信息,主要更新委托状态、冻结、剩余手数、成交手数、成交均价等字段。

f)   更新客户实时资金表。

g)   调用do_single_ssfx执行试算风险。

h)   调用push_exch_trade_return进行推送处理准备。

i)   判断是否有需要处理的平仓先回的平仓的成交回报,如果有,则调用deal_trade_offset进行平仓处理(由于此处调用deal_trade_offset也是平仓业务,所以该段逻辑请参考平仓分支)。

j)   根据接口定义,产生推送结果集。

2)   平仓或平今处理:调用deal_trade_offset

a)   判断实时成交表中,是否已经收到该笔系统号的单子,如果是则拒绝。

b)   判断等待平仓表中,是否已经收到过该笔成交回报(仅当真正的平仓的时候才会校验,处理等待单的时候不需要作该校验,肯定有的,哈哈)。

c)   判断持仓总手数是否够,如果不够平,则跳转到fatal,fatal会把本次的平仓信息写入等待平仓表,待以后持仓足够后,再进行本次平仓的具体处理。

d)   如果是处理等待单,则需要重新从委托表中获取数据。

e)   插一笔成交到实时成交表。

f)   如果是组合开仓则插入组合持仓表。

g)   平仓处理,分交易所进行处理:

ü  如果是郑州交易所的平仓处理,则根据先平单腿再平组合的原则。

ü  如果是其他交易所,则先开先平,大连交易所在成交号相同情况下先平普通再平组合。

h)   平今处理:

ü  由于组合单不支持平今仓,因此平今的时候不需要考虑组合类型的平仓成交,只需要处理普通仓,如果不够且是真正的平仓分支进来的,则跳转到fatal,fatal会把本次的平仓信息写入等待平仓表,待以后持仓足够后,再进行本次平仓的具体处理。

i)   删除组合持仓表中持仓手数为0的记录。

j)   删除客户实时持仓明细表中持仓手数为0的记录

k)   更新持仓汇总表。

l)   更新委托表委托信息。

m)   更新客户实时资金信息。

n)   如果本次平仓是等待处理引起的,则在等待处理列表中,删除该笔等待处理的成交单。

  • o)   如果试算方式是数据库试算,则调用do_single_ssfx进行单客户试算风险。

p)   调用push_exch_trade_return进行推送处理准备。

q)   根据成交回报接口要求,输出推送结果集。

r)   记录日志。

s)   Return 0。

t)   错误流程:

ü  如果本次平仓是由正常平仓引起的,而非由等待平仓引起的,则在本错误分支里面,记录本次平仓的记录到等待平仓表。

  1. 如果[开平标记]是开仓的话,记录一条日志。
  2. Return 0,正常流程结束。
  3. 异常流程:

1)   如果错误码是101037,表示平仓回来时持仓不够,进入等待平仓表等待处理。严格来说,该错误码并不是一个错误,而是一个异常处理。

2)   如果[操作员]是空,表示是初始化调用,为了把该存储过程载入数据库的cache中,所以不需要报错,正常退出就好了。

3)   拼一些本次成交回报的关键信息,到本次要报的错误信息后面,方便查问题。

4)   错误流程结束。

l  委托、撤单的数据流

交易前端à应用服务器à报盘机à交易所à报盘机à应用服务器à交易前端

l  成交回报的数据流

交易所à报盘机à应用服务器à交易前端

l  行情的数据流

交易所à报盘机à行情服务器à行情转发机à交易前端

 

猜你喜欢

转载自www.cnblogs.com/xiaohengheng/p/9187193.html