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 getOrderCancelReject(self, message): beginString = fix.BeginString() message.getHeader().getField(beginString) clOrdID = fix.ClOrdID() orderID = fix.OrderID() origClOrdID = fix.OrigClOrdID() message.getField(clOrdID) message.getField(orderID) message.getField(origClOrdID) orderCancelReject = fix.Message() orderCancelReject.getHeader().setField(beginString) orderCancelReject.getHeader().setField( fix.MsgType(fix.MsgType_OrderCancelReject)) orderCancelReject.setField(clOrdID) orderCancelReject.setField(orderID) orderCancelReject.setField(origClOrdID) 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 return orderCancelReject
def cancel(self, message, sessionID): symbol = fix.Symbol() side = fix.Side() orderQty = fix.OrderQty() clOrdID = fix.ClOrdID() org = fix.OrigClOrdID() message.getField(symbol) message.getField(side) message.getField(orderQty) message.getField(clOrdID) message.getField(org) log.info("cancel:\nsymbol:{},side:{},orderQty:{},clOrdID:{},org:{} -----"\ .format(symbol, side, orderQty, clOrdID, org)) cancel = fix44.OrderCancelReject() cancel.setField(clOrdID) cancel.setField(fix.OrderID(self.genOrderID())) cancel.setField(fix.OrdStatus(fix.OrdStatus_NEW)) cancel.setField(fix.OrigClOrdID(org.getValue())) cancel.setField(fix.Text('order completed')) cancel.setField(fix.TransactTime()) cancel.setField(fix.CxlRejReason(fix.CxlRejReason_BROKER)) cancel.setField( fix.CxlRejResponseTo(fix.CxlRejResponseTo_ORDER_CANCEL_REQUEST)) fix.Session.sendToTarget(cancel, sessionID)
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 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 sendFill(self, orderID, quantity): message = self.startFIXString(orderID) if self.orders[orderID]['leaves'] <= quantity: message.setField(quickfix.OrdStatus(quickfix.OrdStatus_FILLED)) message.setField(quickfix.ExecType(quickfix.ExecType_FILL)) else: message.setField(quickfix.OrdStatus(quickfix.OrdStatus_PARTIALLY_FILLED)) message.setField(quickfix.ExecType(quickfix.ExecType_PARTIAL_FILL)) message.setField(quickfix.LastShares(quantity)) if 'price' in self.orders[orderID]: message.setField(quickfix.LastPx(self.orders[orderID]['price'])) else: message.setField(quickfix.LastPx(1.00)) quickfix.Session.sendToTarget(message, self.orders[orderID]['session']) self.orders[orderID]['leaves'] -= quantity if self.orders[orderID]['leaves'] < 1: self.orders[orderID]['state'] = 'Filled'
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 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 __get_attributes(self, message): price = fix.LastPx() quantity = fix.LastQty() symbol = fix.Symbol() side = fix.Side() client_order_id = fix.ClOrdID() exec_id = fix.ExecID() order_status = fix.OrdStatus() message.getField(client_order_id) message.getField(side) message.getField(symbol) message.getField(price) message.getField(quantity) message.getField(order_status) message.getField(exec_id) return (symbol, price, quantity, side, client_order_id, exec_id, order_status)
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 fromApp(self, message, sessionID): logger.info("fromApp:" + message.__str__()) #print "fromApp...", sessionID, message msgType = fix.MsgType() clOrdID = fix.ClOrdID() orderStatus = fix.OrdStatus() message.getHeader().getField(msgType) if (msgType.getValue() == fix.MsgType_ExecutionReport): echo = fix.Message(message) message.getField(orderStatus) if (orderStatus.getString() == "8"): print "reject" elif (orderStatus.getString() == "0"): print "new" elif (msgType.getValue() == "UAP"): PosReqType = fix.PosReqType() message.getField(PosReqType) logger.info("PosReqType.getValue():" + PosReqType.getString()) if (PosReqType.getValue() == 0): self.OnNoPositions(message) elif (PosReqType.getValue() == 9): self.OnNoPosAmt(message)
def cancel_child_order(self, message: fix.Message): """""" cl_ord_id = get_field_value(message, fix.OrigClOrdID()) vt_orderid = self.genus_vt_map.get(cl_ord_id, "") if vt_orderid: child_order = self.child_orders[vt_orderid] if child_order.ord_status not in {"2", "8", "4"}: self.client.cancel_order(vt_orderid) return # Reject cancel request self.exec_id += 1 message = new_message(fix.MsgType_OrderCancelReject) message.setField(fix.ClOrdID(cl_ord_id)) message.setField(fix.OrigClOrdID(cl_ord_id)) message.setField(fix.OrdStatus("8")) message.setField(fix.ExecID(str(self.exec_id))) message.setField(434, "1") fix.Session.sendToTarget(message, self.session_id)
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 __unpackMessage(self, message): msgType = fix.MsgType() message.getHeader().getField(msgType) if msgType.getValue() == fix.MsgType_RequestForPositionsAck: account = fix.Account() message.getField(account) posId = fix.PosReqID() message.getField(posId) self.Notifier.notifyMsgHandlers( Notify.Account, Account=account.getValue(), PosReqID=posId.getValue(), Symbol=None, Maturity=None, NoPositions=0, LongQty=0, ShortQty=0, PosAmt=0, SettlPrice=0, NoPosAmt=0, ClearingBusinessDate=None, AccountInquiry=AccountInquiry.RequestForPositions) elif msgType.getValue() == fix.MsgType_PositionReport: account = fix.Account() message.getField(account) posId = fix.PosReqID() message.getField(posId) symbol = fix.Symbol() message.getField(symbol) maturity = fix.MaturityMonthYear() message.getField(maturity) noPositions = fix.NoPositions() message.getField(noPositions) longQty = fix.LongQty() message.getField(longQty) shortQty = fix.ShortQty() message.getField(shortQty) posAmt = fix.PosAmt() message.getField(posAmt) cBusDate = fix.ClearingBusinessDate() message.getField(cBusDate) settlePrice = fix.SettlPrice() message.getField(settlePrice) noPosAmt = fix.NoPosAmt() message.getField(noPosAmt) self.Notifier.notifyMsgHandlers( Notify.Account, Account=account.getValue(), PosReqID=posId.getValue(), Symbol=symbol.getValue(), Maturity=maturity.getValue(), NoPositions=noPositions.getValue(), LongQty=longQty.getValue(), ShortQty=shortQty.getValue(), PosAmt=posAmt.getValue(), SettlPrice=settlePrice.getValue(), NoPosAmt=noPosAmt.getValue(), ClearingBusinessDate=cBusDate.getValue(), AccountInquiry=AccountInquiry.RequestForPositions) elif msgType.getValue() == fix.MsgType_CollateralReport: account = fix.Account() message.getField(account) ccy = fix.Currency() message.getField(ccy) csh = fix.CashOutstanding() message.getField(csh) colId = fix.CollInquiryID() message.getField(colId) self.Notifier.notifyMsgHandlers( Notify.Account, Account=account.getValue(), Currency=ccy.getValue(), Balance=csh.getValue(), CollInquiryID=colId.getValue(), AccountInquiry=AccountInquiry.CollateralInquiry) elif msgType.getValue() == fix.MsgType_OrderCancelReject: cId = fix.ClOrdID() message.getField(cId) origClOrdID = fix.OrigClOrdID() message.getField(origClOrdID) self.Notifier.notifyMsgHandlers(Notify.Order, ClientOrderId=cId.getValue(), Symbol=None, AvgPx=None, Quantity=None, Side=None, Status=OrderStatus.CancelRejected, OrigClOrdID=origClOrdID.getValue(), Sender=self.FixClientRef) elif msgType.getValue() == fix.MsgType_ExecutionReport: cId = fix.ClOrdID() message.getField(cId) fixStatus = fix.OrdStatus() message.getField(fixStatus) price = fix.AvgPx() message.getField(price) qty = fix.OrderQty() message.getField(qty) side = fix.Side() message.getField(side) symbol = fix.Symbol() message.getField(symbol) orderSide = None origOrderId = None if side.getValue() == fix.Side_BUY: orderSide = OrderSide.Buy elif side.getValue() == fix.Side_SELL: orderSide = OrderSide.Sell status = None if fixStatus.getValue() == fix.OrdStatus_NEW: status = OrderStatus.New elif fixStatus.getValue() == fix.OrdStatus_CANCELED: status = OrderStatus.Cancelled origClOrdID = fix.OrigClOrdID() message.getField(origClOrdID) origOrderId = origClOrdID.getValue() elif fixStatus.getValue() == fix.OrdStatus_FILLED: status = OrderStatus.Filled elif fixStatus.getValue() == fix.OrdStatus_REJECTED: status = OrderStatus.Rejected if status is not None: self.Notifier.notifyMsgHandlers(Notify.Order, ClientOrderId=cId.getValue(), Symbol=symbol.getValue(), AvgPx=price.getValue(), Quantity=qty.getValue(), Side=orderSide, Status=status, OrigClOrdID=origOrderId, Sender=self.FixClientRef)
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): order_status_field = quickfix.OrdStatus() message.getField(order_status_field) return order_status_field
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