def report_child_order(self, child_order: GenusChildOrder, trade: TradeData = None): """""" self.exec_id += 1 message = new_message(fix.MsgType_ExecutionReport) message.setField(fix.ClOrdID(child_order.cl_ord_id)) message.setField(fix.OrderID(child_order.order_id)) message.setField(fix.ExecID(str(self.exec_id))) message.setField(fix.OrdStatus(child_order.ord_status)) message.setField(fix.ExecType(child_order.ord_status)) message.setField(fix.Symbol(child_order.symbol)) message.setField(fix.Side(child_order.side)) message.setField(fix.OrderQty(child_order.order_qty)) message.setField(fix.CumQty(child_order.cum_qty)) message.setField( fix.LeavesQty(child_order.order_qty - child_order.cum_qty)) message.setField(fix.AvgPx(child_order.avg_px)) if trade: message.setField(fix.LastShares(trade.volume)) message.setField(fix.LastPx(trade.price)) fix.Session.sendToTarget(message, self.session_id)
def getExecutionReportForNewOrder(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) symbol = fix.Symbol() side = fix.Side() ordType = fix.OrdType() orderQty = fix.OrderQty() price = fix.Price() clOrdID = fix.ClOrdID() message.getField(ordType) if ordType.getValue() != fix.OrdType_LIMIT: raise fix.IncorrectTagValue(ordType.getField()) message.getField(symbol) message.getField(side) message.getField(orderQty) message.getField(price) message.getField(clOrdID) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) executionReport.setField(fix.OrderID(self.genOrderID())) executionReport.setField(fix.ExecID(self.genExecID())) executionReport.setField(fix.OrdStatus(fix.OrdStatus_FILLED)) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(fix.CumQty(orderQty.getValue())) executionReport.setField(fix.AvgPx(price.getValue())) executionReport.setField(fix.LastShares(orderQty.getValue())) executionReport.setField(fix.LastPx(price.getValue())) executionReport.setField(clOrdID) executionReport.setField(orderQty) executionReport.setField(fix.Text("New order accepted!")) # Since FIX 4.3, ExecTransType is killed and the values are moved to ExecType if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField(fix.ExecTransType(fix.ExecTransType_NEW)) # ExecType and LeavesQty fields only existsince FIX 4.1 if beginString.getValue() >= fix.BeginString_FIX41: if beginString.getValue() <= fix.BeginString_FIX42: executionReport.setField(fix.ExecType( fix.ExecType_FILL)) #150=2 FILL (or 1 PARTIAL_FILL) else: # FILL and PARTIAL_FILL are removed and replaced by TRADE (F) since FIX 4.3 as these info can be retrieved from OrdStatus field executionReport.setField(fix.ExecType( fix.ExecType_TRADE)) #150=F TRADE executionReport.setField(fix.LeavesQty(0)) return executionReport
def fromApp(self, message, sessionID): beginString = fix.BeginString() msgType = fix.MsgType() message.getHeader().getField(beginString) message.getHeader().getField(msgType) symbol = fix.Symbol() side = fix.Side() ordType = fix.OrdType() orderQty = fix.OrderQty() price = fix.Price() clOrdID = fix.ClOrdID() message.getField(ordType) print(ordType) if ordType.getValue() != fix.OrdType_LIMIT: raise fix.IncorrectTagValue(ordType.getField()) message.getField(symbol) message.getField(side) message.getField(orderQty) message.getField(price) message.getField(clOrdID) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) executionReport.setField(fix.OrderID(self.genOrderID())) executionReport.setField(fix.ExecID(self.genExecID())) executionReport.setField(fix.OrdStatus(fix.OrdStatus_FILLED)) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(fix.CumQty(orderQty.getValue())) executionReport.setField(fix.AvgPx(price.getValue())) executionReport.setField(fix.LastShares(orderQty.getValue())) executionReport.setField(fix.LastPx(price.getValue())) executionReport.setField(clOrdID) executionReport.setField(orderQty) if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField(fix.ExecTransType(fix.ExecTransType_NEW)) if beginString.getValue() >= fix.BeginString_FIX41: executionReport.setField(fix.ExecType(fix.ExecType_FILL)) executionReport.setField(fix.LeavesQty(0)) try: fix.Session.sendToTarget(executionReport, sessionID) except (SessionNotFound, e): return
def _create_execution_report( self, symbol, side, client_order_id, price=None, quantity=None, order_status=fix.OrdStatus_NEW, exec_trans_type=fix.ExecTransType_NEW, exec_type=fix.ExecType_NEW, text=None, reject_reason=None, orig_client_order_id=None, ): # defaults execution_report = Message() execution_report.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) execution_report.setField( fix.OrderID(self.generate_order_id(symbol.getValue()))) execution_report.setField( fix.ExecID(self.generate_execution_id(symbol.getValue()))) execution_report.setField(fix.OrdStatus(order_status)) execution_report.setField(symbol) execution_report.setField(side) execution_report.setField(client_order_id) execution_report.setField(fix.ExecTransType(exec_trans_type)) execution_report.setField(fix.ExecType(exec_type)) execution_report.setField(fix.LeavesQty(0)) if price: execution_report.setField(fix.AvgPx(price.getValue())) execution_report.setField(fix.LastPx(price.getValue())) if quantity: execution_report.setField(fix.CumQty(quantity.getValue())) execution_report.setField(fix.LastShares(quantity.getValue())) execution_report.setField(quantity) if orig_client_order_id: execution_report.setField( fix.OrigClOrdID(orig_client_order_id.getValue())) if text: execution_report.setField(fix.Text(text)) if exec_type == fix.ExecType_REJECTED: execution_report.setField(fix.OrdRejReason(reject_reason)) self.logger.debug( f"Created execution report {execution_report.__str__()}") return execution_report
def fromApp(self, message, sessionID): beginString = fix.BeginString() msgType = fix.MsgType() message.getHeader().getField( beginString ) message.getHeader().getField( msgType ) if msgType.getValue() == 'F': print 'Cancel Request' symbol = fix.Symbol() side = fix.Side() clOrdID = fix.ClOrdID() origClOrdID = fix.OrigClOrdID() orderQty = fix.OrderQty() message.getField( orderQty ) message.getField( clOrdID ) message.getField( origClOrdID ) message.getField( symbol ) message.getField( side ) executionReport = fix.Message() executionReport.getHeader().setField( beginString ) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport) ) executionReport.setField( symbol ) executionReport.setField( side ) executionReport.setField( clOrdID ) executionReport.setField( origClOrdID ) executionReport.setField( fix.ExecID(self.genExecID()) ) executionReport.setField( fix.OrderID(self.genOrderID()) ) executionReport.setField( fix.AvgPx(0)) executionReport.setField( fix.LastShares(0)) executionReport.setField( fix.CumQty(0)) if beginString.getValue() == fix.BeginString_FIX40 or beginString.getValue() == fix.BeginString_FIX41 or beginString.getValue() == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_CANCEL) ) executionReport.setField( fix.OrdStatus(fix.OrdStatus_CANCELED) ) if beginString.getValue() >= fix.BeginString_FIX41: executionReport.setField( fix.ExecType(fix.ExecType_CANCELED) ) executionReport.setField( fix.LeavesQty(0) ) else: executionReport.setField( fix.ExecType(fix.ExecType_CANCELED) ) executionReport.setField( fix.LeavesQty(0) ) try: print executionReport fix.Session.sendToTarget( executionReport, sessionID ) except SessionNotFound, e: return
def new_order(self, message, beginString, sessionID): symbol = fix.Symbol() side = fix.Side() ordType = fix.OrdType() orderQty = fix.OrderQty() price = fix.Price(50) clOrdID = fix.ClOrdID() message.getField(ordType) message.getField(symbol) message.getField(side) message.getField(orderQty) message.getField(price) message.getField(clOrdID) log.info("new_order:\nordType:{},symbol:{},side:{},orderQty:{},price:{},clOrdID:{} -----"\ .format(ordType, symbol, side, orderQty, price, clOrdID)) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) executionReport.setField(fix.TransactTime()) executionReport.setField(fix.OrderID(self.genOrderID())) executionReport.setField(fix.ExecID(self.genExecID())) executionReport.setField(fix.OrdStatus(fix.OrdStatus_NEW)) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(fix.CumQty(orderQty.getValue())) executionReport.setField(fix.AvgPx(price.getValue())) executionReport.setField(fix.LastShares(orderQty.getValue())) executionReport.setField(fix.LastPx(price.getValue())) executionReport.setField(clOrdID) executionReport.setField(orderQty) executionReport.setField(fix.ExecType(fix.ExecType_NEW)) executionReport.setField(fix.LeavesQty(orderQty.getValue())) try: fix.Session.sendToTarget(executionReport, sessionID) time.sleep(1) if ordType.getValue() == fix.OrdType_MARKET: executionReport.setField(fix.OrdStatus(fix.OrdStatus_FILLED)) executionReport.setField(fix.ExecType(fix.ExecType_TRADE)) fix.Session.sendToTarget(executionReport, sessionID) except fix.SessionNotFound as e: return
def getExecutionReportForCancelOrder(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) symbol = fix.Symbol() side = fix.Side() clOrdID = fix.ClOrdID() message.getField(symbol) message.getField(side) message.getField(clOrdID) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) executionReport.setField(fix.OrderID(self.genOrderID())) executionReport.setField(fix.ExecID(self.genExecID())) executionReport.setField(fix.OrdType( fix.OrdType_LIMIT)) #40=2 Limit order executionReport.setField(fix.OrderQty(100)) #38=100 executionReport.setField(fix.Price(10)) #44=10 executionReport.setField(fix.OrdStatus(fix.OrdStatus_FILLED)) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(fix.AvgPx(10)) #6=10 executionReport.setField(fix.CumQty(100)) #14=100 executionReport.setField(clOrdID) executionReport.setField(fix.Text("Order cancelled!")) # Since FIX 4.3, ExecTransType values are moved to ExecType if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_CANCEL)) # ExecType and LeavesQty fields only existsince FIX 4.1 if beginString.getValue() >= fix.BeginString_FIX41: executionReport.setField(fix.ExecType( fix.ExecType_CANCELED)) #150=4 CANCELED executionReport.setField(fix.LeavesQty(0)) #151=0 return executionReport
def getExecutionReportForStatusRequest(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) clOrdID = fix.ClOrdID() message.getField(clOrdID) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) executionReport.setField(fix.Symbol("ABCD")) executionReport.setField(fix.Side(fix.Side_BUY)) #43=1 Buy executionReport.setField(fix.OrderID(self.genOrderID())) executionReport.setField(fix.ExecID(self.genExecID())) executionReport.setField(fix.OrdType( fix.OrdType_LIMIT)) #40=2 Limit order executionReport.setField(fix.OrderQty(100)) #38=100 executionReport.setField(fix.Price(10)) #44=10 executionReport.setField(fix.OrdStatus(fix.OrdStatus_FILLED)) executionReport.setField(fix.AvgPx(10)) #6=10 executionReport.setField(fix.CumQty(100)) #14=100 executionReport.setField(clOrdID) executionReport.setField(fix.Text("Order status retrieved!")) # Since FIX 4.3, ExecTransType values are moved to ExecType if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_STATUS)) # ExecType and LeavesQty fields only existsince FIX 4.1 if beginString.getValue() >= fix.BeginString_FIX41: if beginString.getValue() <= fix.BeginString_FIX42: executionReport.setField(fix.ExecType( fix.ExecType_FILL)) #150=2 FILL (or 1 PARTIAL_FILL) else: # FILL and PARTIAL_FILL are removed and replaced by TRADE (F) since FIX 4.3 as these info can be retrieved from OrdStatus field executionReport.setField(fix.ExecType( fix.ExecType_TRADE)) #150=F TRADE executionReport.setField(fix.LeavesQty(0)) return executionReport
def handle_execution_report(self, message): order_id = TradingClass.FIXHandlerUtils.get_field_value(fix.OrderID(), message) cl_ord_id = TradingClass.FIXHandlerUtils.get_field_value(fix.ClOrdID(), message) orig_cl_ord_id = TradingClass.FIXHandlerUtils.get_field_value(fix.OrigClOrdID(), message) exec_id = TradingClass.FIXHandlerUtils.get_field_value(fix.ExecID(), message) exec_trans_type = TradingClass.FIXHandlerUtils.get_field_value(fix.ExecTransType(), message) exec_type = TradingClass.FIXHandlerUtils.get_field_value(fix.ExecType(), message) ord_status = TradingClass.FIXHandlerUtils.get_field_value(fix.OrdStatus(), message) symbol = TradingClass.FIXHandlerUtils.get_field_value(fix.Symbol(), message) side = TradingClass.FIXHandlerUtils.get_field_value(fix.Side(), message) leaves_qty = TradingClass.FIXHandlerUtils.get_field_value(fix.LeavesQty(), message) price = TradingClass.FIXHandlerUtils.get_field_value(fix.Price(), message) cum_qty = TradingClass.FIXHandlerUtils.get_field_value(fix.CumQty(), message) avg_px = TradingClass.FIXHandlerUtils.get_field_value(fix.AvgPx(), message) order_execution = TradingClass.ExecutionReport(order_id, cl_ord_id, exec_id, exec_trans_type, exec_type, ord_status, symbol, side, leaves_qty, cum_qty, avg_px, price, orig_cl_ord_id) self.client_logic.process_order_execution_respond(order_execution) return
def on_parent_order(self, message: fix.Message): """""" parent_orderid = get_field_value(message, fix.ClOrdID()) # Get parent orderid of cancel request if parent_orderid.startswith("Cancel"): parent_orderid = get_field_value(message, fix.OrigClOrdID()) # If this parent order is from previous session if parent_orderid not in self.algo_settings: # Cancel it to avoid future update self.cancel_parent_order(parent_orderid) return tradeid = get_field_value(message, fix.ExecID()) status = get_field_value(message, fix.OrdStatus()) side = get_field_value(message, fix.Side()) genus_symbol = get_field_value(message, fix.Symbol()) order_traded = get_field_value(message, fix.CumQty()) text = get_field_value(message, fix.Text()) algo_type = get_field_value(message, fix.StringField(847)) variables = {"推送编号": tradeid, "已成交": order_traded, "算法信息": text} self.algo_settings[parent_orderid] = { "symbol": genus_symbol, "side": side, "algo_type": algo_type } # Add algo active status if status in {"0", "1", "5", "6", "A", "D", "E"}: variables["active"] = True else: variables["active"] = False if status == "C": self.client.write_log("执行时间已结束,停止算法", parent_orderid) self.client.put_variables_event(parent_orderid, variables)
def onNewOrderSingle(self, message, beginString, sessionID): symbol = quickfix.Symbol() side = quickfix.Side() ordType = quickfix.OrdType() orderQty = quickfix.OrderQty() price = quickfix.Price() clOrdID = quickfix.ClOrdID() quoteID = quickfix.QuoteID() currency = quickfix.Currency() message.getField(ordType) if ordType.getValue() != quickfix.OrdType_PREVIOUSLY_QUOTED: raise quickfix.IncorrectTagValue(ordType.getField()) message.getField(symbol) message.getField(side) message.getField(orderQty) message.getField(price) message.getField(clOrdID) message.getField(quoteID) message.getField(currency) executionReport = quickfix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( quickfix.MsgType(quickfix.MsgType_ExecutionReport)) executionReport.setField(quickfix.OrderID(self.idGen.orderID())) executionReport.setField(quickfix.ExecID(self.idGen.execID())) try: reject_chance = random.choice(range(1, 101)) if self.rejectRate > reject_chance: raise FixSimError("Rejected by cruel destiny %s" % str( (reject_chance, self.rejectRate))) subscription = self.subscriptions.get(symbol.getValue()) quote = subscription.orderbook.get(quoteID.getValue()) execPrice = price.getValue() execSize = orderQty.getValue() if execSize > quote.size: raise FixSimError("size to large for quote") if abs(execPrice - quote.price) > 0.0000001: raise FixSimError("Trade price not equal to quote") executionReport.setField( quickfix.SettlDate(self.getSettlementDate())) executionReport.setField(quickfix.Currency(subscription.currency)) executionReport.setField( quickfix.OrdStatus(quickfix.OrdStatus_FILLED)) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(clOrdID) executionReport.setField(quickfix.Price(price.getValue())) executionReport.setField(quickfix.AvgPx(execPrice)) executionReport.setField(quickfix.LastPx(execPrice)) executionReport.setField(quickfix.LastShares(execSize)) executionReport.setField(quickfix.CumQty(execSize)) executionReport.setField(quickfix.OrderQty(execSize)) executionReport.setField(quickfix.ExecType(quickfix.ExecType_FILL)) executionReport.setField(quickfix.LeavesQty(0)) except Exception as e: self.logger.exception("FixServer:Close order error") executionReport.setField(quickfix.SettlDate('')) executionReport.setField(currency) executionReport.setField( quickfix.OrdStatus(quickfix.OrdStatus_REJECTED)) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(clOrdID) executionReport.setField(quickfix.Price(0)) executionReport.setField(quickfix.AvgPx(0)) executionReport.setField(quickfix.LastPx(0)) executionReport.setField(quickfix.LastShares(0)) executionReport.setField(quickfix.CumQty(0)) executionReport.setField(quickfix.OrderQty(0)) executionReport.setField( quickfix.ExecType(quickfix.ExecType_REJECTED)) executionReport.setField(quickfix.LeavesQty(0)) self.sendToTarget(executionReport, sessionID)
def parse_ExecutionReport(self, message, sending_time): # Extract fields from the message here and pass to an upper layer if self.verbose: print('[fromApp] Execution Report received!') print(f'[fromApp] {read_FIX_message(message)}') # Tag 11 (client order ID, the one we sent) # must be the same type (int) as in open_orders. ClOrdID = extract_message_field_value(fix.ClOrdID(), message, 'int') # print('ClOrdID:', ClOrdID) # Tag 15 # _Currency = extract_message_field_value(fix.Currency(), message) # print('_Currency:', _Currency) # Tag 17 # _ExecID = extract_message_field_value(fix.ExecID(), message) # print('_ExecID:', _ExecID) # Tag 37 # _OrderID = extract_message_field_value(fix.OrderID(), message) # print('_OrderID:', _OrderID) # Tag 39 OrderStatus: 0 = New, 1 = Partially filled, 2 = Filled, 3 = Done for day, 4 = Canceled, # 6 = Pending Cancel (e.g. result of Order Cancel Request <F>), 7 = Stopped, # 8 = Rejected, 9 = Suspended, A = Pending New, B = Calculated, C = Expired, # D = Accepted for bidding, E = Pending Replace (e.g. result of Order Cancel/Replace Request <G>) # maybe also check 3=Done for day, 7=Stopped, 9=Suspended, B=Calculated and C=Expired, but it seems that Stopped means it can still be filled? # https://www.onixs.biz/fix-dictionary/4.4/tagNum_39.html ordStatus = extract_message_field_value(fix.OrdStatus(), message, 'str') # print('ordStatus:', ordStatus) # Tag 150 Execution type # 0 = New, 4 = Canceled, F = Trade (partial fill or fill), I = Order Status, ... _ExecType = extract_message_field_value(fix.ExecType(), message) # print('_ExecType:', _ExecType) # if the exection report is a response to an OrderStatusRequest, # fields other than OrdStatus might not be set. if _ExecType == 'I': if ClOrdID in self.open_orders.keys(): self.open_orders[ClOrdID].status = ordStatus else: print(f'Order {ClOrdID} not found! Order status: {ordStatus}') return # Tag 40 OrderType: 1 = Market, 2 = Limit, 3 = Stop ordType = extract_message_field_value(fix.OrdType(), message, 'str') # print('ordType:', ordType) # Tag 44 price = extract_message_field_value(fix.Price(), message, 'float') # print('price:', price) # Tag 54 side = extract_message_field_value(fix.Side(), message, 'str') # print('side:', side) # Tag 55 symbol = extract_message_field_value(fix.Symbol(), message, 'str') # print('symbol:', symbol) # canceled or rejected: here a few fields are not defined, which would # prevent further parsing of the message. therefore, exiting earlier. # https://www.onixs.biz/fix-dictionary/4.4/tagNum_39.html # tags not defined: 60, 18, 100 # [fromApp] 8=FIX.4.4, 9=164, 35=8, 34=33, 49=XCD17, 52=20201020-10:04:25.518, # 56=T008, 11=51515, 14=0.0, 17=0, 37=0, 38=1000, 39=8, 40=2, 44=1.17, 54=1, # 55=EUR/USD, 58=reject: duplicate clOrdID, 150=8, 151=0.0, 10=073 if ordStatus == '4' or ordStatus == '6' or ordStatus == '8': action = 'canceled' if ordStatus == '8': action = 'rejected' if ClOrdID in self.open_orders.keys( ): # the report might be sent after restarting the FIX algo. if ordStatus == '4' or ordStatus == '6': if self.verbose: print(f'Order {action}: {self.open_orders[ClOrdID]}') if ordStatus == '8': if self.verbose: print(f'Order {action}: {self.open_orders[ClOrdID]}') del self.open_orders[ClOrdID] elif self.verbose: print(f'Order {action}, but not found in open_orders.') report = execution_report(ClOrdID, symbol, side, price, ordType, ordStatus, 0, 0, 0, 0) self.execution_history.append(report) if self.verbose: print(report) transactTime = datetime_to_str(datetime.datetime.utcnow()) log( self.execution_logger, '{},{},{},{},{},{},{},{},{},{},{}'.format( transactTime, ClOrdID, symbol, side, price, ordType, ordStatus, 0, 0, 0, 0)) if self.read_positions_from_file: self.save_positions_to_file() self.lock.acquire() self.tick_processor.on_execution_report(report, self) self.lock.release() return # Tag 60 (how to make it a datetime object?) # here without extract_message_field_value() because we want to call getString() and not getValue(). transactTime = fix.TransactTime() message.getField(transactTime) transactTime = transactTime.getString() # print('transactTime:', transactTime) # Tag 18 orderQty = extract_message_field_value(fix.OrderQty(), message, 'int') # print('orderQty:', orderQty) # Tag 110 minQty = extract_message_field_value(fix.MinQty(), message, 'int') # print('minQty:', minQty) # Tag 14 CumQty: Total quantity filled. cumQty = extract_message_field_value(fix.CumQty(), message, 'int') # print('cumQty:', cumQty) # Tag 151 LeavesQty: Quantity open for further execution. 0 if 'Canceled', 'DoneForTheDay', # 'Expired', 'Calculated', or' Rejected', else LeavesQty <151> = OrderQty <38> - CumQty <14>. leavesQty = extract_message_field_value(fix.LeavesQty(), message, 'int') # print('leavesQty:', leavesQty) if not ClOrdID in self.open_orders.keys(): log(self.execution_logger, f'[ERROR] ClOrdID {ClOrdID} not found in open_orders:', True) for o in self.open_orders: log(self.execution_logger, o) report = execution_report(ClOrdID, symbol, side, price, ordType, ordStatus, orderQty, minQty, cumQty, leavesQty) self.execution_history.append(report) print(report) # maybe better exit if the ID was not found? # but it could happen on the start of a session with PersistMessages=Y. return self.open_orders[ClOrdID].status = ordStatus if ordStatus == '0': # new self.open_orders[ClOrdID].openTime = transactTime elif ordStatus == '1' and leavesQty > 0: # partially filled if leavesQty == 0: if ClOrdID in self.open_orders.keys(): del self.open_orders[ClOrdID] else: self.open_orders[ClOrdID].leaves_quantity = leavesQty # orderQty is the ordered quantity, cumQty the one filled. self.add_position(symbol, side, cumQty) # for consistency check. canceled quantity is orderQty-cumQty. self.add_canceled_quantity(symbol, side, orderQty - cumQty) elif ordStatus == '2': # filled if ClOrdID in self.open_orders.keys(): del self.open_orders[ClOrdID] self.add_position(symbol, side, cumQty) # if there was a partial fill before, a following canceled order can have a non-zero cumQty. elif ordStatus == '3': if ClOrdID in self.open_orders.keys(): del self.open_orders[ClOrdID] report = execution_report(ClOrdID, symbol, side, price, ordType, ordStatus, orderQty, minQty, cumQty, leavesQty) self.execution_history.append(report) if self.verbose: print(report) log( self.execution_logger, '{},{},{},{},{},{},{},{},{},{},{}'.format( transactTime, ClOrdID, symbol, side, price, ordType, ordStatus, orderQty, minQty, cumQty, leavesQty)) if self.read_positions_from_file: self.save_positions_to_file() self.lock.acquire() self.tick_processor.on_execution_report(report, self) self.lock.release()
def _process_execution_report(self, message): cl_ord_id = self._extract_field(fix.ClOrdID(), message) exec_type = self._extract_field(fix.ExecType(), message) market_order_id = self._extract_optional_field(fix.OrderID(), message) order = self.order_store.find_order(cl_ord_id, market_order_id) # We only update the market order if it's changed self.order_store.store_market_order_id(market_order_id, order.order_id) order.order_id = self.order_store.find_order_id(cl_ord_id) if exec_type == fix.ExecType_NEW: order.status = OrdStatus.NEW self.order_handler.on_new_ack(order) elif exec_type == fix.ExecType_DONE_FOR_DAY: pass elif exec_type == fix.ExecType_CANCELED: order.status = OrdStatus.CANCELED self.order_handler.on_cancel_ack(order) elif exec_type == fix.ExecType_REPLACE: order.status = OrdStatus.REPLACED self.order_handler.on_replace_ack(order) elif exec_type == fix.ExecType_PENDING_CANCEL: self.log.info( 'Received pending cancel for order [order id: {}]'.format( order.order_id)) elif exec_type == fix.ExecType_STOPPED: pass elif exec_type == fix.ExecType_REJECTED: ord_rej_reason = self._extract_field(fix.OrdRejReason(), message) self.log.error('Submission rejected, ({}) {}'.format( OrdRejReason[ord_rej_reason], ord_rej_reason)) order.status = OrdStatus.NEW_REJECT self.order_handler.on_new_rej(order) elif exec_type == fix.ExecType_SUSPENDED: pass elif exec_type == fix.ExecType_PENDING_NEW: self.log.info( 'Received pending new for order [order id: {}]'.format( order.order_id)) elif exec_type == fix.ExecType_CALCULATED: pass elif exec_type == fix.ExecType_EXPIRED: pass elif exec_type == fix.ExecType_RESTATED: pass elif exec_type == fix.ExecType_PENDING_REPLACE: self.log.info( 'Received pending replace for order [order id: {}]'.format( order.order_id)) elif exec_type == fix.ExecType_TRADE: exec_id = self._extract_field(fix.ExecID(), message) transact_time = self._extract_date_field(fix.TransactTime(), message) remaining_qty = self._extract_field(fix.LeavesQty(), message) executed_qty = self._extract_field(fix.CumQty(), message) last_qty = self._extract_field(fix.LastQty(), message) last_px = self._extract_field(fix.LastPx(), message) order.executed_qty = executed_qty execution = Execution(order.order_id) execution.exec_id = exec_id execution.transact_time = transact_time execution.last_price = last_px execution.last_qty = last_qty if remaining_qty == 0: order.status = OrdStatus.FULLY_FILLED else: order.status = OrdStatus.PARTIALLY_FILLED self.order_store.store_exec_id(exec_id, execution) self.order_handler.on_execution(order, execution) elif exec_type == fix.ExecType_TRADE_CORRECT: pass elif exec_type == fix.ExecType_TRADE_CANCEL: pass elif exec_type == fix.ExecType_ORDER_STATUS: pass else: self.log.error('Unknown execType: {}'.format(exec_type))
def getExecutionReportForStatusRequest2(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) clOrdID = fix.ClOrdID() orderID = fix.OrderID() message.getField(clOrdID) message.getField(orderID) response = getOrder(self.accessKey, self.secretKey, orderID.getValue()) jResponse = json.loads(response) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) executionReport.setField(fix.ExecID(self.genExecID())) # todo get client order id executionReport.setField(clOrdID) if 'error' in jResponse and jResponse['error']: executionReport.setField(fix.OrderID(orderID.getValue())) executionReport.setField(fix.OrdStatus(fix.OrdStatus_REJECTED)) executionReport.setField(fix.Text(jResponse['error']['message'])) # todo Reject reason for each case executionReport.setField( fix.OrdRejReason(fix.OrdRejReason_UNKNOWN_ORDER)) else: executionReport.setField(fix.OrderID(str(jResponse['id']))) # todo check trades_count from json response and set FILL status? executionReport.setField(fix.OrdStatus(fix.OrdStatus_NEW)) executionReport.setField( fix.Side(fix.Side_BUY if jResponse['side'] == 'buy' else fix.Side_SELL)) executionReport.setField( fix.OrdType( fix.OrdType_LIMIT if jResponse['ord_type'] == 'limit' else fix.OrdType_MARKET)) #40=2 Limit order executionReport.setField(fix.Symbol(jResponse['market'])) executionReport.setField(fix.Price(float(jResponse['price']))) #44 executionReport.setField(fix.OrderQty(float( jResponse['volume']))) #38 executionReport.setField( fix.CumQty(float(jResponse['executed_volume']))) #14=100 executionReport.setField(fix.AvgPx(float( jResponse['avg_price']))) #6 executionReport.setField(fix.Text('Order status retrieved!')) # Since FIX 4.3, ExecTransType values are moved to ExecType if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_STATUS)) # ExecType and LeavesQty fields only existsince FIX 4.1 if beginString.getValue() >= fix.BeginString_FIX41: if beginString.getValue() <= fix.BeginString_FIX42: executionReport.setField(fix.ExecType( fix.ExecType_FILL)) #150=2 FILL (or 1 PARTIAL_FILL) else: # FILL and PARTIAL_FILL are removed and replaced by TRADE (F) since FIX 4.3 as these info can be retrieved from OrdStatus field executionReport.setField(fix.ExecType( fix.ExecType_TRADE)) #150=F TRADE executionReport.setField(fix.LeavesQty(0)) return executionReport
def getExecutionReportForCancelOrder2(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) symbol = fix.Symbol() side = fix.Side() clOrdID = fix.ClOrdID() orderID = fix.OrderID() origClOrdID = fix.OrigClOrdID() message.getField(symbol) message.getField(side) message.getField(clOrdID) message.getField(orderID) message.getField(origClOrdID) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) data = {} data['id'] = orderID.getValue() response = cancelOrder(self.accessKey, self.secretKey, orderID.getValue()) jResponse = json.loads(response) executionReport.setField(fix.OrderID(orderID.getValue())) # todo get client order id executionReport.setField(clOrdID) executionReport.setField(fix.ExecID(self.genExecID())) if 'error' in jResponse and jResponse['error']: orderCancelReject = fix.Message() orderCancelReject.getHeader().setField(beginString) orderCancelReject.getHeader().setField( fix.MsgType(fix.MsgType_OrderCancelReject)) orderCancelReject.setField(clOrdID) orderCancelReject.setField(orderID) orderCancelReject.setField(origClOrdID) # todo reject reason orderCancelReject.setField(fix.OrdStatus( fix.OrdStatus_FILLED)) #39 = 2 FILLED orderCancelReject.setField( fix.CxlRejReason(0)) #102=0 TOO_LATE_TO_CANCEL orderCancelReject.setField( fix.CxlRejResponseTo(1)) #434=1 ORDER_CANCEL_REQUEST orderCancelReject.setField(fix.Text(jResponse['error']['message'])) return orderCancelReject else: executionReport.setField(fix.OrderID(str(jResponse['id']))) # todo check trades_count from json response and set FILL status? executionReport.setField(fix.OrdStatus(fix.OrdStatus_CANCELED)) executionReport.setField( fix.Side(fix.Side_BUY if jResponse['side'] == 'buy' else fix.Side_SELL)) executionReport.setField( fix.OrdType( fix.OrdType_LIMIT if jResponse['ord_type'] == 'limit' else fix.OrdType_MARKET)) #40=2 Limit order executionReport.setField(fix.Symbol(jResponse['market'])) executionReport.setField(fix.Price(float(jResponse['price']))) #44 executionReport.setField(fix.OrderQty(float( jResponse['volume']))) #38 executionReport.setField( fix.CumQty(float(jResponse['executed_volume']))) #14=100 executionReport.setField(fix.AvgPx(float( jResponse['avg_price']))) #6 executionReport.setField(fix.Text("Order cancelled!")) # Since FIX 4.3, ExecTransType values are moved to ExecType if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_CANCEL)) # ExecType and LeavesQty fields only existsince FIX 4.1 if beginString.getValue() >= fix.BeginString_FIX41: executionReport.setField(fix.ExecType( fix.ExecType_CANCELED)) #150=4 CANCELED executionReport.setField(fix.LeavesQty(0)) #151=0 return executionReport
class Application(fix.Application): orderID = 0 execID = 0 bids = {} asks = {} #creates empty dictionaries loc = ("C:\\Bloomberg\\SampleMarketData.xlsx") wb = xlrd.open_workbook(loc) sheetMSFT = wb.sheet_by_index(0) sheetNFLX = wb.sheet_by_index(1) sheetNames = wb.sheet_names() xl_sheet1 = wb.sheet_by_index(0) xl_sheet2 = wb.sheet_by_index(1) sheet1Name = xl_sheet1.name.encode("utf-8") sheet2Name = xl_sheet2.name.encode("utf-8") excelbids = {} excelbids['BATS'] = {} excelbids['BATS'][sheet1Name] = {} excelbids['BATS'][sheet2Name] = {} excelbids['NASD'] = {} excelbids['NASD'][sheet1Name] = {} excelbids['NASD'][sheet2Name] = {} excelasks = {} excelasks['BATS'] = {} excelasks['BATS'][sheet1Name] = {} excelasks['BATS'][sheet2Name] = {} excelasks['NASD'] = {} excelasks['NASD'][sheet1Name] = {} excelasks['NASD'][sheet2Name] = {} for i in range (2, 7): for j in range (0, 1): excelbids['NASD'][sheet1Name][sheetMSFT.cell_value(i, j)] = sheetMSFT.cell_value(i, j+1) for i in range (2, 7): for j in range (2, 3): excelasks['NASD'][sheet1Name][sheetMSFT.cell_value(i, j)] = sheetMSFT.cell_value(i, j+1) for i in range (9, 14): for j in range (0, 1): excelbids['BATS'][sheet1Name][sheetMSFT.cell_value(i, j)] = sheetMSFT.cell_value(i, j+1) for i in range (9, 14): for j in range (2, 3): excelasks['BATS'][sheet1Name][sheetMSFT.cell_value(i, j)] = sheetMSFT.cell_value(i, j+1) for i in range (2, 7): for j in range (0, 1): excelbids['NASD'][sheet2Name][sheetNFLX.cell_value(i, j)] = sheetNFLX.cell_value(i, j+1) for i in range (2, 7): for j in range (2, 3): excelasks['NASD'][sheet2Name][sheetNFLX.cell_value(i, j)] = sheetNFLX.cell_value(i, j+1) for i in range (9, 14): for j in range (0, 1): excelbids['BATS'][sheet2Name][sheetNFLX.cell_value(i, j)] = sheetNFLX.cell_value(i, j+1) for i in range (9, 14): for j in range (2, 3): excelasks['BATS'][sheet2Name][sheetNFLX.cell_value(i, j)] = sheetNFLX.cell_value(i, j+1) #reads excel files, inputs data into nested dictionaries @echo def onCreate(self, sessionID): return @echo def onLogon(self, sessionID): return @echo def onLogout(self, sessionID): return @echo def toAdmin(self, sessionID, message): return @echo def fromAdmin(self, sessionID, message): return @echo def toApp(self, sessionID, message): return @echo def fromApp(self, message, sessionID): beginString = fix.BeginString() msgType = fix.MsgType() message.getHeader().getField( beginString ) message.getHeader().getField( msgType ) if msgType.getValue() == 'F': print 'Cancel Request' symbol = fix.Symbol() side = fix.Side() clOrdID = fix.ClOrdID() origClOrdID = fix.OrigClOrdID() orderQty = fix.OrderQty() message.getField( orderQty ) message.getField( clOrdID ) message.getField( origClOrdID ) message.getField( symbol ) message.getField( side ) executionReport = fix.Message() executionReport.getHeader().setField( beginString ) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport) ) executionReport.setField( symbol ) executionReport.setField( side ) executionReport.setField( clOrdID ) executionReport.setField( origClOrdID ) executionReport.setField( fix.ExecID(self.genExecID()) ) executionReport.setField( fix.OrderID(self.genOrderID()) ) executionReport.setField( fix.AvgPx(0)) executionReport.setField( fix.LastShares(0)) executionReport.setField( fix.CumQty(0)) if beginString.getValue() == fix.BeginString_FIX40 or beginString.getValue() == fix.BeginString_FIX41 or beginString.getValue() == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_CANCEL) ) executionReport.setField( fix.OrdStatus(fix.OrdStatus_CANCELED) ) if beginString.getValue() >= fix.BeginString_FIX41: executionReport.setField( fix.ExecType(fix.ExecType_CANCELED) ) executionReport.setField( fix.LeavesQty(0) ) else: executionReport.setField( fix.ExecType(fix.ExecType_CANCELED) ) executionReport.setField( fix.LeavesQty(0) ) try: print executionReport fix.Session.sendToTarget( executionReport, sessionID ) except SessionNotFound, e: return if msgType.getValue() == 'D': print 'New Order Single' symbol = fix.Symbol() side = fix.Side() ordType = fix.OrdType() orderQty = fix.OrderQty() price = fix.Price() timeInForce = fix.TimeInForce() clOrdID = fix.ClOrdID() message.getField( ordType ) print message if ordType.getValue() == fix.OrdType_LIMIT: message.getField( price ) price = round(float(price.getValue()),2) message.getField( symbol ) message.getField( side ) message.getField( orderQty ) message.getField( clOrdID ) message.getField( timeInForce ) executionReport = fix.Message() executionReport.getHeader().setField( beginString ) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport) ) availableQty = 0 if side.getValue() == '2': #check the bids sym = symbol.getValue() mergedDict = sorted(set(self.excelbids['BATS'][sym].keys()) | set(self.excelbids['NASD'][sym].keys()), reverse = True) orderMergedDict = OrderedDict() for pricelevel in mergedDict: orderMergedDict[pricelevel] = OrderedDict() if pricelevel in self.excelbids['BATS'][sym].keys(): orderMergedDict[pricelevel]['BATS'] = self.excelbids['BATS'][sym][pricelevel] if pricelevel in self.excelbids['NASD'][sym].keys(): orderMergedDict[pricelevel]['NASD'] = self.excelbids['NASD'][sym][pricelevel] print '-------------Sell Order - Checking available Bids-------------' qty = orderQty.getValue() orderToSend = {} for bid_price, exch in orderMergedDict.iteritems(): if price <= bid_price or ordType.getValue() == fix.OrdType_MARKET : for exchange,bid_qty in exch.iteritems(): if exchange not in orderToSend: orderToSend[exchange] = {} if bid_qty >= qty and qty > 0: orderToSend[exchange][bid_price] = qty qty = 0 elif qty > 0: orderToSend[exchange][bid_price] = bid_qty qty = qty - bid_qty availableQty += bid_qty else: #check the asks sym = symbol.getValue() mergedDict = sorted(set(self.excelasks['BATS'][sym].keys()) | set(self.excelasks['NASD'][sym].keys())) orderMergedDict = OrderedDict() for pricelevel in mergedDict: orderMergedDict[pricelevel] = OrderedDict() if pricelevel in self.excelasks['BATS'][sym].keys(): orderMergedDict[pricelevel]['BATS'] = self.excelasks['BATS'][sym][pricelevel] if pricelevel in self.excelasks['NASD'][sym].keys(): orderMergedDict[pricelevel]['NASD'] = self.excelasks['NASD'][sym][pricelevel] print '--------------Buy Order - Checking available Asks-------------' qty = orderQty.getValue() orderToSend = {} for ask_price, exch in orderMergedDict.iteritems(): #if ask_price <= round(float(price.getValue()),2): if ask_price <= price or ordType.getValue() == fix.OrdType_MARKET: for exchange,ask_qty in exch.iteritems(): if exchange not in orderToSend: orderToSend[exchange] = {} if ask_qty >= qty and qty > 0: orderToSend[exchange][ask_price] = qty qty = 0 elif qty > 0: orderToSend[exchange][ask_price] = ask_qty qty = qty - ask_qty availableQty += ask_qty filledQty = 0 if len(orderToSend) > 0: for exchange, detailsOfOrders in orderToSend.iteritems(): for price, qty in detailsOfOrders.iteritems(): filledQty = filledQty + qty executionReport.setField( fix.OrderID(self.genOrderID()) ) executionReport.setField( fix.ExecID(self.genExecID()) ) if filledQty >= orderQty.getValue(): executionReport.setField( fix.OrdStatus(fix.OrdStatus_FILLED) ) else: executionReport.setField( fix.OrdStatus(fix.OrdStatus_PARTIALLY_FILLED) ) executionReport.setField( symbol ) executionReport.setField( side ) executionReport.setField( fix.CumQty(filledQty)) executionReport.setField( fix.AvgPx(price )) # to do - need to properly calculate average price executionReport.setField( fix.LastShares(qty)) executionReport.setField( fix.LastPx(price)) executionReport.setField( clOrdID ) executionReport.setField( orderQty ) executionReport.setField( fix.LastMkt(exchange)) if beginString.getValue() == fix.BeginString_FIX40 or beginString.getValue() == fix.BeginString_FIX41 or beginString.getValue() == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_NEW) ) if beginString.getValue() >= fix.BeginString_FIX41: if filledQty >=0 : executionReport.setField( fix.ExecType(fix.ExecType_FILL) ) executionReport.setField( fix.LeavesQty(0) ) else: executionReport.setField( fix.ExecType(fix.ExecType_PARTIAL_FILL) ) executionReport.setField( fix.LeavesQty(orderQty.getValue() - filledQty) ) try: print executionReport fix.Session.sendToTarget( executionReport, sessionID ) except SessionNotFound, e: return if timeInForce.getValue() == fix.TimeInForce_IMMEDIATE_OR_CANCEL: print "TimeInForce is IOC - need to cancel the remaining balance" executionReport = fix.Message() executionReport.getHeader().setField( beginString ) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport) ) executionReport.setField( symbol ) executionReport.setField( side ) executionReport.setField( clOrdID ) executionReport.setField( fix.ExecID(self.genExecID()) ) executionReport.setField( fix.OrderID(self.genOrderID()) ) executionReport.setField( fix.AvgPx(price)) executionReport.setField( fix.LastShares(0)) executionReport.setField( fix.CumQty(filledQty)) executionReport.setField( fix.LastPx(price)) executionReport.setField( orderQty ) if beginString.getValue() == fix.BeginString_FIX40 or beginString.getValue() == fix.BeginString_FIX41 or beginString.getValue() == fix.BeginString_FIX42: executionReport.setField( fix.ExecTransType(fix.ExecTransType_CANCEL) ) executionReport.setField( fix.OrdStatus(fix.OrdStatus_CANCELED) ) if beginString.getValue() >= fix.BeginString_FIX41: executionReport.setField( fix.ExecType(fix.ExecType_CANCELED) ) executionReport.setField( fix.LeavesQty(0) ) else: executionReport.setField( fix.ExecType(fix.ExecType_CANCELED) ) executionReport.setField( fix.LeavesQty(0) ) try: print executionReport fix.Session.sendToTarget( executionReport, sessionID ) except SessionNotFound, e: return
def getExecutionReportForNewOrder2(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) msgSeqNum = fix.MsgSeqNum() message.getHeader().getField(msgSeqNum) symbol = fix.Symbol() side = fix.Side() ordType = fix.OrdType() orderQty = fix.OrderQty() price = fix.Price() clOrdID = fix.ClOrdID() message.getField(ordType) # todo handle market order if ordType.getValue() != fix.OrdType_LIMIT: raise fix.IncorrectTagValue(ordType.getField()) message.getField(symbol) message.getField(side) message.getField(orderQty) message.getField(price) message.getField(clOrdID) data = {} data['market'] = symbol.getValue() data['price'] = price.getValue() data['side'] = 'buy' if side.getValue() == fix.Side_BUY else 'sell' data['volume'] = orderQty.getValue() response = createOrder(self.accessKey, self.secretKey, data) jResponse = json.loads(response) executionReport = fix.Message() executionReport.getHeader().setField(beginString) executionReport.getHeader().setField( fix.MsgType(fix.MsgType_ExecutionReport)) # todo exec id? executionReport.setField(fix.ExecID(self.genExecID())) executionReport.setField(symbol) executionReport.setField(side) executionReport.setField(fix.CumQty(orderQty.getValue())) executionReport.setField(fix.AvgPx(price.getValue())) executionReport.setField(fix.LastShares(orderQty.getValue())) executionReport.setField(fix.LastPx(price.getValue())) # todo save Client order id to DB? executionReport.setField(clOrdID) executionReport.setField(orderQty) if 'error' in jResponse and jResponse['error']: executionReport.setField(fix.OrderID("nil")) executionReport.setField(fix.OrdStatus(fix.OrdStatus_REJECTED)) executionReport.setField(fix.Text(jResponse['error']['message'])) # todo Reject reason for each case executionReport.setField( fix.OrdRejReason(fix.OrdRejReason_UNKNOWN_SYMBOL)) else: executionReport.setField(fix.OrderID(str(jResponse['id']))) # todo check trades_count from json response and set FILL status? executionReport.setField(fix.OrdStatus(fix.OrdStatus_NEW)) executionReport.setField(fix.Text('New order accpeted!')) # Since FIX 4.3, ExecTransType is killed and the values are moved to ExecType if beginString.getValue( ) == fix.BeginString_FIX40 or beginString.getValue( ) == fix.BeginString_FIX41 or beginString.getValue( ) == fix.BeginString_FIX42: executionReport.setField(fix.ExecTransType(fix.ExecTransType_NEW)) # todo check trades_count from json response and set FILL status? # ExecType and LeavesQty fields only existsince FIX 4.1 if beginString.getValue() >= fix.BeginString_FIX41: if beginString.getValue() <= fix.BeginString_FIX42: executionReport.setField(fix.ExecType( fix.ExecType_FILL)) #150=2 FILL (or 1 PARTIAL_FILL) else: # FILL and PARTIAL_FILL are removed and replaced by TRADE (F) since FIX 4.3 as these info can be retrieved from OrdStatus field executionReport.setField(fix.ExecType( fix.ExecType_TRADE)) #150=F TRADE executionReport.setField(fix.LeavesQty(0)) """if 'error' in jResponse and jResponse['error']: reject = fix.Message() reject.getHeader().setField(beginString) reject.getHeader().setField(fix.MsgType(fix.MsgType_Reject)) reject.setField(fix.RefMsgType(fix.MsgType_NewOrderSingle)) reject.setField(fix.RefSeqNum(msgSeqNum.getValue())) #45 = RefSeqNum reject.setField(fix.SessionRejectReason(fix.SessionRejectReason_OTHER)) #373 = 99 OTHER reject.setField(fix.Text(jResponse['message'])) return reject """ return executionReport