int RecordFactory::parseServiceContracts(ifstream &stream, const char *fileName, bool printAccts, bool printRec) { int rc = 0; cout << "============================================================\n" << "Processing service contract file: " << fileName << '\n'; int InfoHeader_cnt = 0; int StmtHeader_cnt = 0; int special_cnt = 0; int Division_cnt = 0; int PostCode_cnt = 0; int ContractInfo_cnt = 0; int Statement_cnt = 0; int LineItem_cnt = 0; int TaxLineItem_cnt = 0; int ContrFlags_cnt = 0; int Trailer_cnt = 0; double please_pay_bal = 0.0; int current_rec = 0; bool done = false; InfoHeaderRec *ih = 0; DocumentHeaderRec *dh = 0; TrailerRec *tr = 0; vector<DivisionRec *> Divisions; Divisions.resize(64, 0); PcodeMap PostingCodes; ContractInfoMap ContractInfo; StatementRec *currentStatement = 0; Files++; dumpCount = 0; dump_stmt_bal = 0.0; // if (patricks_special_flag) // ReadPatricksSpecialFile(); if (opt_e) { for_each(excludeFiles.begin(), excludeFiles.end(), bind2nd(ReadAccountSet(), &SkipAccounts)); } if (opt_i) { for_each(includeFiles.begin(), includeFiles.end(), bind2nd(ReadAccountSet(), &KeepAccounts)); } bool filterCurrent = false; do { // loop increment current_rec++; // read the data char buf[2+1]; if (!stream.get(buf, sizeof(buf))) { if (stream.eof()) { done = 1; continue; } cerr << "Error: read error, record #" << current_rec << "\n"; return 1; } // Report record type Record::RecordType rt = (Record::RecordType)atoi(buf); if (opt_r) { if (rt == Record::Statement) cout << "*****************************************************************************************\n"; cout << "#### Record #" << current_rec << " Type: " << rt << " (" << Record::RT_to_String(rt) << ")\n"; } // Process records switch (rt) { case Record::InfoHeader: if (++InfoHeader_cnt > 1) { cerr << "Error: multiple InfoHeader records, record #" << current_rec << "\n"; rc++; } try { ih = new InfoHeaderRec(stream, fileName, current_rec); } catch (...) { } if (opt_d) ih->dump(dumpFile); break; case Record::DocHeader: if (++StmtHeader_cnt > 1) { cerr << "Error: multiple StatementHeader records, record #" << current_rec << "\n"; rc++; } try { dh = new DocumentHeaderRec(stream, fileName, current_rec, DocumentHeaderRec::SvcContr); } catch (...) { } if (opt_d) dh->dump(dumpFile); break; case Record::Division: Division_cnt++; try { DivisionRec *dr = new DivisionRec(stream, fileName, current_rec); Divisions[dr->getDivisionNum()] = dr; if (opt_d) dr->dump(dumpFile); } catch (...) { } break; case Record::PostCode: PostCode_cnt++; try { PostingCode *code = new PostingCode(stream, fileName, current_rec); PostingCodes.insert(PcodeMap::value_type(code->getCode(), code)); if (opt_d) code->dump(dumpFile); } catch (...) { } break; case Record::ContractInfo: ContractInfo_cnt++; try { ContractInfoRec *info = new ContractInfoRec(stream, fileName, current_rec); ContractInfo.insert(ContractInfoMap::value_type(info->getContr(), info)); if (opt_d) info->dump(dumpFile); } catch (...) { } break; case Record::Statement: Statement_cnt++; try { FinishPrevStatement(currentStatement, 0.0, 0.0, 0.0, 0.0); currentStatement = new StatementRec(stream, fileName, current_rec, true); if (opt_f && FilterOut(currentStatement)) { filterCurrent = true; } else { filterCurrent = false; if (currentStatement->specialHandling()) special_cnt++; if (!Divisions[currentStatement->getDivisionNum()]) { cerr << "Error: invalid division, record #" << current_rec << '\n'; } acct_numbers.insert(currentStatement->getAcctNum()); file_recnum_pair acctrec(fileName, current_rec); acct_map.insert(acct_mapping::value_type(currentStatement->getAcctNum(), acctrec)); } } catch (...) { } break; case Record::ContractLine: if (currentStatement == 0) { cerr << "Error: Contract line not inside a statement, record #" << current_rec << "\n"; throw; } try { ContractLineRec *li = new ContractLineRec(currentStatement, PostingCodes, ContractInfo, stream, fileName, current_rec); currentStatement->AddItem(li); LineItem_cnt++; } catch (...) { } break; case Record::ContractTaxLine: if (currentStatement == 0) { cerr << "Error: Contract tax line not inside a statement, record #" << current_rec << "\n"; throw; } try { ContractTaxLineRec *li = new ContractTaxLineRec(currentStatement, stream, fileName, current_rec); currentStatement->AddItem(li); TaxLineItem_cnt++; please_pay_bal += li->getTotal(); } catch (...) { } break; case Record::ContractFlags: { ContractFlagsRec *flgs = new ContractFlagsRec(currentStatement, stream, fileName, current_rec); currentStatement->AddItem(flgs); ContrFlags_cnt++; } break; case Record::LineItemAddr: if (file_ver <= 1) { cerr << "Error: LineItemAddrRec present in old format file, record #" << current_rec << "\n"; throw; } else { LineItemAddrRec *lia = new LineItemAddrRec(stream, fileName, current_rec); currentStatement->AddItem(lia); } break; case Record::StatementAddr: if (file_ver <= 1) { cerr << "Error: StatementAddrRec present in old format file, record #" << current_rec << "\n"; throw; } else { StatementAddrRec *sa = new StatementAddrRec(stream, fileName, current_rec); currentStatement->AddItem(sa); } break; case Record::Trailer: FinishPrevStatement(currentStatement, 0.0, 0.0, 0.0, 0.0); if (++Trailer_cnt > 1) { cerr << "Error: multiple Trailer records, record #" << current_rec << "\n"; rc++; } try { tr = new TrailerRec(stream, fileName, current_rec); if (opt_d) { tr->dumpNew(dumpFile, dumpCount, dump_stmt_bal); } } catch (...) { } break; default: cerr << "Error: invalid record type " << rt << ", record #" << current_rec << "\n"; throw; break; } CheckEndOfRec(stream, current_rec); } while (!done); // Check for missing records if (InfoHeader_cnt != 1) { cerr << "Error: missing InfoHeader\n"; rc++; } if (StmtHeader_cnt != 1) { cerr << "Error: missing StmtHeader\n"; rc++; } if (Trailer_cnt != 1) { cerr << "Error: missing Trailer\n"; rc++; } if (opt_r) cout << "\nRecord Counts:\n" << "InfoHeader: " << InfoHeader_cnt << "\n" << "StmtHeader: " << StmtHeader_cnt << "\n" << "Division: " << Division_cnt << "\n" << "PostCode: " << PostCode_cnt << "\n" << "ContrInfo: " << ContractInfo_cnt << "\n" << "Statement: " << Statement_cnt << "\n" << "LineItem: " << LineItem_cnt << "\n" << "ContrTax: " << TaxLineItem_cnt << "\n" << "ContrFlags: " << ContrFlags_cnt << "\n" << "Trailer: " << Trailer_cnt << "\n"; // Verify counts & totals if (tr->getTotalItems() != Statement_cnt) { cerr << "Error: count of statements (" << Statement_cnt << ") does not match count in trailer record (" << tr->getTotalItems() << ")\n"; rc++; } if ((tr->getTotalBilled() - please_pay_bal) >= 0.001) { cerr << "Error: total billed in trailer record ("; PrintCurrency(cerr, tr->getTotalBilled()); cerr << ") does not match total of statement balances ("; PrintCurrency(cerr, please_pay_bal); cerr << ")\n"; rc++; } cout << "Total Statements: " << Statement_cnt << '\n' << "Total Line items: " << LineItem_cnt << '\n' << "Total Contracts: " << LineItem_cnt << '\n' << "Total Special handling: " << special_cnt << '\n' << "Total Please Pay: "; PrintCurrency(cout, please_pay_bal); cout << '\n' << "============================================================\n\n"; LineItems += LineItem_cnt; SpecialCount += special_cnt; TotalPleasePay += please_pay_bal; TotalStatements += Statement_cnt; return rc; }
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; }