/* 撤单合规检查,如果大于等于最大撤单限制数则禁止撤单 */ RESULT_TYPE COMPLIANCE_CHECK_API_CALL ComplianceCheck_TryReqOrderAction( const char * account, // account const char * code, // 证券代码 OrderRefDataType order_ref // 报单引用 ) { int ret = COMPLIANCE_CHECK_RESULT_SUCCESS; char key[64]; sprintf(key, "%s_%s", account, code); lock_guard<std::mutex> lock(check_mutex); auto acit = account_contract_infomap.find(key); if (acit != account_contract_infomap.end()) { auto oit = order_infomap.find(order_ref); if (oit != order_infomap.end()) { if (oit->second.status == PENDING) { ret = TryCancelCheck(acit); if (ret == COMPLIANCE_CHECK_RESULT_CANCEL_EXCEED_LIMIT) { return ret; } oit->second.status = PENDING_CANCEL; acit->second.cur_cancel_times++; if (acit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(acit, account, code, CONST_ENTRUST_BUY); } else if (acit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(acit, account, code, CONST_ENTRUST_BUY); } auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (cit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_BUY); } else if (cit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_SELL); } } } } } return ret; }
/* 订单已撤销,修正完撤单数后删除订单 */ void COMPLIANCE_CHECK_API_CALL ComplianceCheck_OnOrderCanceled( const char * account, // account const char * code, // 证券代码 OrderRefDataType order_ref, // 报单引用 char exchange_code, // 交易所编码 int canceled_volumn, // 撤单数量 char hedge_flag, // 投机套保类型 char open_close_flag // 开平方向 ) { lock_guard<std::mutex> lock(check_mutex); auto oit = order_infomap.find(order_ref); if (oit != order_infomap.end()) { char buy_sell_flag = oit->second.buy_sell_flag; if (oit->second.status == PENDING_CANCEL) { auto ait = account_infomap.find(account); if (ait != account_infomap.end()) { if (open_close_flag == CONST_ENTRUST_OPEN && exchange_code == CONST_EXCHCODE_CFFEX) { int index = GetCommodityIndex(code); if (index != -1) { if (hedge_flag == CONST_SHFLAG_TOU) { ait->second.cur_speculate_open_times[index] -= canceled_volumn; ait->second.cur_total_open_times[index] -= canceled_volumn; } else if (hedge_flag == CONST_SHFLAG_TAO) { ait->second.cur_arbitrage_open_times[index] -= canceled_volumn; ait->second.cur_total_open_times[index] -= canceled_volumn; } } } oit->second.status = CANCELED; order_infomap.erase(order_ref); char key[64]; sprintf(key, "%s_%s", account, code); auto acit = account_contract_infomap.find(key); if (acit != account_contract_infomap.end()) { ResetCurPriceAndOrder(acit, account, code, buy_sell_flag); } auto cit = contract_infomap.find(key); if (cit != contract_infomap.end()) { ResetCurPriceAndOrder(cit, code, buy_sell_flag); } } } } }
/* 订单成交 */ void COMPLIANCE_CHECK_API_CALL ComplianceCheck_OnOrderFilled( const char * account, // account OrderRefDataType order_ref // 报单引用 ) { lock_guard<std::mutex> lock(check_mutex); auto it = order_infomap.find(order_ref); if (it != order_infomap.end()) { string code = it->second.stock; char key[64]; sprintf(key, "%s_%s", account, it->second.stock.c_str()); auto acit = account_contract_infomap.find(key); if (acit != account_contract_infomap.end()) { //如果订单处于撤单状态,撤单数减一 if (it->second.status == PENDING_CANCEL) { acit->second.cur_cancel_times--; } it->second.status = FILLED; order_infomap.erase(order_ref); if (acit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(acit, account, it->second.stock, CONST_ENTRUST_BUY); } else if (acit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(acit, account, it->second.stock, CONST_ENTRUST_BUY); } } auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (cit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_BUY); } else if (cit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_SELL); } } } }
/* 撤单失败,修正撤单数 */ void COMPLIANCE_CHECK_API_CALL ComplianceCheck_OnOrderCancelFailed( const char * account, // account const char * code, // 证券代码 OrderRefDataType order_ref // 报单引用 ) { char key[64]; sprintf(key, "%s_%s", account, code); lock_guard<std::mutex> lock(check_mutex); auto oit = order_infomap.find(order_ref); if (oit != order_infomap.end()) { if (oit->second.status == PENDING_CANCEL) { oit->second.status = PENDING; auto acit = account_contract_infomap.find(key); if (acit != account_contract_infomap.end()) { acit->second.cur_cancel_times--; } if (acit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(acit, account, code, CONST_ENTRUST_BUY); } else if (acit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(acit, account, code, CONST_ENTRUST_BUY); } auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (cit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_BUY); } else if (cit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_SELL); } } } } }
static int SelfTradeInsertCheck(const string &account, const string &code, const char price_flag, const char buy_sell_flag, const double price, OrderRefDataType * opposite_serial_no) { int ret = COMPLIANCE_CHECK_RESULT_SUCCESS; //多账户内的自成交检查 //如果不是限价单,只要方向相反就拦截 auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (price_flag != CONST_ENTRUSTKIND_XJ) { if (buy_sell_flag == CONST_ENTRUST_BUY && cit->second.cur_sell_price != 0) { *opposite_serial_no = cit->second.cur_sell_ref; return COMPLIANCE_CHECK_RESULT_SELFTRADE; //返回自成交的错误码 } else if (buy_sell_flag == CONST_ENTRUST_SELL && cit->second.cur_buy_price != 0) { *opposite_serial_no = cit->second.cur_buy_ref; return COMPLIANCE_CHECK_RESULT_SELFTRADE; } } else { //如果是限价单,判断买卖的价格是否有冲突,有冲突则返回错误 if (buy_sell_flag == CONST_ENTRUST_BUY && cit->second.cur_sell_price != 0 && price >= cit->second.cur_sell_price) { *opposite_serial_no = cit->second.cur_sell_ref; return COMPLIANCE_CHECK_RESULT_SELFTRADE; } else if (buy_sell_flag == CONST_ENTRUST_SELL && cit->second.cur_buy_price != 0 && price <= cit->second.cur_buy_price) { *opposite_serial_no = cit->second.cur_buy_ref; return COMPLIANCE_CHECK_RESULT_SELFTRADE; } } } return ret; }
void COMPLIANCE_CHECK_API_CALL ComplianceCheck_OnOrderInsertFailed( const char * account, // account OrderRefDataType order_ref, // 报单引用 char exchange_code, // 交易所编码 const char * code, // 证券代码 int volumn, // 数量 char hedge_flag, // 投机套保类型 char open_close_flag, // 开平方向 char order_type // 报单类型 ) { char key[64]; sprintf(key, "%s_%s", account, code); lock_guard<std::mutex> lock(check_mutex); if (order_type != CONST_ENTRUSTKIND_FAK && order_type != CONST_ENTRUSTKIND_FOK) { order_infomap.erase(order_ref); } auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (cit->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_BUY); } else if (cit->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(cit, code, CONST_ENTRUST_SELL); } } auto it = account_contract_infomap.find(key); if (it != account_contract_infomap.end()) { if (exchange_code == CONST_EXCHCODE_CFFEX) { int index = GetCommodityIndex(code); if (index != -1) { auto ait = account_infomap.find(account); if (ait != account_infomap.end()) { if (hedge_flag == CONST_SHFLAG_TOU) { ait->second.cur_speculate_open_times[index] -= volumn; ait->second.cur_total_open_times[index] -= volumn; } else if (hedge_flag == CONST_SHFLAG_TAO) { ait->second.cur_arbitrage_open_times[index] -= volumn; ait->second.cur_total_open_times[index] -= volumn; } } } } if (it->second.cur_buy_ref == order_ref) { ResetCurPriceAndOrder(it, account, code, CONST_ENTRUST_BUY); } else if (it->second.cur_sell_ref == order_ref) { ResetCurPriceAndOrder(it, account, code, CONST_ENTRUST_BUY); } } }
RESULT_TYPE COMPLIANCE_CHECK_API_CALL ComplianceCheck_TryReqOrderInsert( const char * account, // account OrderRefDataType order_ref, // 报单引用 char exchange_code, // 交易所编码 const char * code, // 证券代码 int volumn, // 数量 double price, // 价格 char price_flag, // 价格类型 char hedge_flag, // 投机套保类型 char buy_sell_flag, // 买卖方向 char open_close_flag, // 开平方向 char order_type, // 报单类型 OrderRefDataType * opposite_serial_no // 【输出】导致自成交对手单的报单引用 ) { char key[64]; sprintf(key, "%s_%s", account, code); lock_guard<std::mutex> lock(check_mutex); RESULT_TYPE ret = COMPLIANCE_CHECK_RESULT_SUCCESS; auto acit = account_contract_infomap.find(key); if (acit != account_contract_infomap.end()) { //撤单数检查 ret = CancelTimesInsertCheck(acit, order_type, open_close_flag); if (ret != COMPLIANCE_CHECK_RESULT_SUCCESS && ret != COMPLIANCE_CHECK_RESULT_CANCEL_TIMES_EQUAL_WARN_THRETHOLD) { return ret; } //开仓数检查 int tmp_ret; tmp_ret = OpenTimesInsertCheck(acit, account, exchange_code, open_close_flag, hedge_flag, code, volumn); if (tmp_ret != COMPLIANCE_CHECK_RESULT_SUCCESS && tmp_ret != COMPLIANCE_CHECK_RESULT_OPEN_EQUAL_LIMIT) { return tmp_ret; } else if (ret == COMPLIANCE_CHECK_RESULT_SUCCESS && tmp_ret == COMPLIANCE_CHECK_RESULT_OPEN_EQUAL_LIMIT) { ret = tmp_ret; } //自成交检查 tmp_ret = SelfTradeInsertCheck(acit, account, code, price_flag, buy_sell_flag, price, opposite_serial_no); if (tmp_ret != COMPLIANCE_CHECK_RESULT_SUCCESS) { return tmp_ret; } //成功下单,录入操作 if (open_close_flag == CONST_ENTRUST_OPEN && exchange_code == CONST_EXCHCODE_CFFEX) { int index = GetCommodityIndex(code); if (index != -1) { auto ait = account_infomap.find(account); if (ait != account_infomap.end()) { if (hedge_flag == CONST_SHFLAG_TOU) { ait->second.cur_speculate_open_times[index] += volumn; ait->second.cur_total_open_times[index] += volumn; } else if (hedge_flag == CONST_SHFLAG_TAO) { ait->second.cur_arbitrage_open_times[index] += volumn; ait->second.cur_total_open_times[index] += volumn; } } } } if (order_type != CONST_ENTRUSTKIND_FAK && order_type != CONST_ENTRUSTKIND_FOK && order_infomap.find(order_ref) == order_infomap.end()) { auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (buy_sell_flag == CONST_ENTRUST_BUY && price >= cit->second.cur_buy_price) { cit->second.cur_buy_price = price; cit->second.cur_buy_ref = order_ref; } else if (buy_sell_flag == CONST_ENTRUST_SELL && price >= cit->second.cur_buy_price) { cit->second.cur_sell_price = price; cit->second.cur_sell_ref = order_ref; } } if (buy_sell_flag == CONST_ENTRUST_BUY && price >= acit->second.cur_buy_price) { acit->second.cur_buy_price = price; acit->second.cur_buy_ref = order_ref; } else if (buy_sell_flag == CONST_ENTRUST_SELL && price >= acit->second.cur_buy_price) { acit->second.cur_sell_price = price; acit->second.cur_sell_ref = order_ref; } OrderInfo item(account, code, order_type, buy_sell_flag, price, volumn); order_infomap.insert(make_pair(order_ref, item)); } } else { auto ait = account_infomap.find(account); if (ait != account_infomap.end()) { ret = NewOrderInsertCheck(ait, exchange_code, open_close_flag, hedge_flag, volumn); if (ret != COMPLIANCE_CHECK_RESULT_OPEN_REACH_EXCEED_LIMIT) { int tmp_ret = COMPLIANCE_CHECK_RESULT_SUCCESS; if (ait->second.self_match_check_in_all) { tmp_ret = SelfTradeInsertCheck(account, code, price_flag, buy_sell_flag, price, opposite_serial_no); } if (tmp_ret != COMPLIANCE_CHECK_RESULT_SUCCESS) { return tmp_ret; } AccountContractInfo item(ait->second); if (open_close_flag == CONST_ENTRUST_OPEN && exchange_code == CONST_EXCHCODE_CFFEX) { int index = GetCommodityIndex(code); if (index != -1) { if (hedge_flag == CONST_SHFLAG_TOU) { ait->second.cur_speculate_open_times[index] += volumn; ait->second.cur_total_open_times[index] += volumn; } else if (hedge_flag == CONST_SHFLAG_TAO) { ait->second.cur_arbitrage_open_times[index] += volumn; ait->second.cur_total_open_times[index] += volumn; } } } if (order_type != CONST_ENTRUSTKIND_FAK && order_type != CONST_ENTRUSTKIND_FOK) { auto cit = contract_infomap.find(code); if (cit != contract_infomap.end()) { if (buy_sell_flag == CONST_ENTRUST_BUY && price >= cit->second.cur_buy_price) { cit->second.cur_buy_price = price; cit->second.cur_buy_ref = order_ref; } else if (buy_sell_flag == CONST_ENTRUST_SELL && price >= cit->second.cur_buy_price) { cit->second.cur_sell_price = price; cit->second.cur_sell_ref = order_ref; } } else { ContractInfo citem; if (buy_sell_flag == CONST_ENTRUST_BUY) { citem.cur_buy_price = price; citem.cur_buy_ref = order_ref; } else if (buy_sell_flag == CONST_ENTRUST_SELL){ citem.cur_sell_price = price; citem.cur_sell_ref = order_ref; } contract_infomap.insert(make_pair(code, citem)); } if (buy_sell_flag == CONST_ENTRUST_BUY) { item.cur_buy_price = price; item.cur_buy_ref = order_ref; } else { item.cur_sell_price = price; item.cur_sell_ref = order_ref; } } account_contract_infomap.insert(make_pair(key, item)); } if (order_type != CONST_ENTRUSTKIND_FAK && order_type != CONST_ENTRUSTKIND_FOK && order_infomap.find(order_ref) == order_infomap.end()) { OrderInfo item(account, code, order_type, buy_sell_flag, price, volumn); order_infomap.insert(make_pair(order_ref, item)); } } else { return COMPLIANCE_CHECK_RESULT_FAIL; } } return ret; }