def top_n_orders(message, n): stock_id = getValue(message, 55) dict_list = give_top_n(stock_id, n) ret_message = fix44.MarketDataSnapshotFullRefresh() group = fix44.MarketDataSnapshotFullRefresh().NoMDEntries() for Dict in dict_list: group.setField(fix.MDEntryType(Dict["Type"])) group.setField(fix.MDEntryPx(Dict["Price"])) group.setField(fix.MDEntrySize(Dict["Quantity"])) group.setField(fix.OrderID(Dict["Order ID"])) ret_message.addGroup(group) ret_message.setField(55, stock_id) return ret_message
def publishMarketData(self): self.logger.info("FixServer: publishMarketData %s", self.subscriptions) for subscription in self.subscriptions: if not subscription.hasSessions(): self.logger.info( "FixServer:No session subscribed, skip publish symbol %s", subscription.symbol) continue message = self.fixVersion.MarketDataSnapshotFullRefresh() message.setField(quickfix.Symbol(subscription.symbol)) message.setField(quickfix.MDReqID(self.idGen.reqID())) group = self.fixVersion.MarketDataSnapshotFullRefresh( ).NoMDEntries() subscription.createOrderBook() for quote in subscription.orderbook: self.logger.info('FixServer:add quote to fix message %s', str(quote)) group.setField(quickfix.MDEntryType(quote.side)) group.setField(quickfix.MDEntryPx(quote.price)) group.setField(quickfix.MDEntrySize(quote.size)) group.setField(quickfix.QuoteEntryID(quote.id)) group.setField(quickfix.Currency(subscription.currency)) group.setField( quickfix.QuoteCondition( quickfix.QuoteCondition_OPEN_ACTIVE)) message.addGroup(group) for sessionID in subscription: self.sendToTarget(message, sessionID)
def __init__(self, reference_data, market_data): self.reference_data = reference_data self.market_data = market_data self.symbol_field = quickfix.Symbol() self.security_exchange_field = quickfix.SecurityExchange() self.no_md_entries = quickfix.NoMDEntries() self.md_entry_type = quickfix.MDEntryType() self.md_entry_price = quickfix.MDEntryPx() self.md_entry_size = quickfix.MDEntrySize()
def fromApp(self, message, sessionID): msg_type = message.getHeader().getField(fix.MsgType()).getString() depth = {} if msg_type == fix.MsgType_MarketDataSnapshotFullRefresh: group = fixMsg.MarketDataSnapshotFullRefresh.NoMDEntries() nb_entries = int(message.getField(fix.NoMDEntries()).getString()) for i in range(1, nb_entries + 1): message.getGroup(i, group) md_type = group.getField(fix.MDEntryType()).getString() md_price = group.getField(fix.MDEntryPx()).getString() md_amount = group.getField(fix.MDEntrySize()).getString() if not md_amount: md_amount = 0 order = {'price': float(md_price), 'amount': float(md_amount)} if md_type == fix.MDEntryType_OFFER: if 'asks' not in depth: depth['asks'] = [] depth['asks'].append(order) if md_type == fix.MDEntryType_BID: if 'bids' not in depth: depth['bids'] = [] depth['bids'].append(order) print("Received a full market data snapshot: %s" % (depth)) elif msg_type == fix.MsgType_MarketDataIncrementalRefresh: group = fixMsg.MarketDataIncrementalRefresh.NoMDEntries() nb_entries = int(message.getField(fix.NoMDEntries()).getString()) for i in range(1, nb_entries + 1): message.getGroup(i, group) md_type = group.getField(fix.MDEntryType()).getString() md_price = group.getField(fix.MDEntryPx()).getString() md_amount = group.getField(fix.MDEntrySize()).getString() if not md_amount: md_amount = 0 order = {'price': float(md_price), 'amount': float(md_amount)} if md_type == fix.MDEntryType_OFFER: if 'asks' not in depth: depth['asks'] = [] depth['asks'].append(order) if md_type == fix.MDEntryType_BID: if 'bids' not in depth: depth['bids'] = [] depth['bids'].append(order) print("Received an incremental market data update: %s" % (depth))
def handle_market_data_respond(self, message): """Handles market data respond Args: message (FIX::Message): Market data message to be handled. Returns: TODO how does the return value look like """ # Retrieve Market Data Response Type Full Refresh/Snapshot md_req_id_fix = fix.MDReqID() no_md_entries_fix = fix.NoMDEntries() symbol_fix = fix.Symbol() total_volume_traded_fix = fix.TotalVolumeTraded() md_entry_type_fix = fix.MDEntryType() md_entry_px_fix = fix.MDEntryPx() md_entry_size_fix = fix.MDEntrySize() md_entry_date_fix = fix.MDEntryDate() md_entry_time_fix = fix.MDEntryTime() md_entry_type_list = [] md_entry_px_list = [] md_entry_size_list = [] md_entry_date_list = [] md_entry_time_list = [] message.getField(md_req_id_fix) message.getField(no_md_entries_fix) message.getField(symbol_fix) message.getField(total_volume_traded_fix) groupMD = fix42.MarketDataSnapshotFullRefresh.NoMDEntries() for MDIndex in range(no_md_entries_fix.getValue()): message.getGroup(MDIndex + 1, groupMD) groupMD.getField(md_entry_type_fix) groupMD.getField(md_entry_px_fix) groupMD.getField(md_entry_size_fix) groupMD.getField(md_entry_date_fix) groupMD.getField(md_entry_time_fix) md_entry_type_list.append(md_entry_type_fix.getValue()) md_entry_px_list.append(md_entry_px_fix.getValue()) md_entry_size_list.append(md_entry_size_fix.getValue()) md_entry_date_list.append(TradingClass.FIXDate.from_fix_date_stamp_string(md_entry_date_fix.getString())) md_entry_time_list.append(TradingClass.FIXTime.from_fix_time_stamp_string(md_entry_time_fix.getString())) # Encapsulate data into market data response object market_data = TradingClass.MarketDataResponse(md_req_id_fix.getValue(), no_md_entries_fix.getValue(), symbol_fix.getValue() , md_entry_type_list, md_entry_px_list, md_entry_size_list, md_entry_date_list, md_entry_time_list, total_volume_traded_fix.getValue()) self.client_logic.process_market_data_respond(market_data) pass
def dispatch(self, book): symbol = book.symbol bids = book.bids asks = book.asks trades = book.trades message = fix44.MarketDataSnapshotFullRefresh() message.setField(fix.Symbol(symbol)) group = fix44.MarketDataSnapshotFullRefresh().NoMDEntries() if bids: for i in range(len(bids)): group.setField(fix.MDEntryType(fix.MDEntryType_BID)) group.setField(fix.MDEntryPx(float(bids[i][0]))) group.setField(fix.MDEntrySize(float(bids[i][1]))) message.addGroup(group) if asks: for i in range(len(asks)): group.setField(fix.MDEntryType(fix.MDEntryType_OFFER)) group.setField(fix.MDEntryPx(float(asks[i][0]))) group.setField(fix.MDEntrySize(float(asks[i][1]))) message.addGroup(group) if trades: for i in range(len(trades)): group.setField(fix.MDEntryType(fix.MDEntryType_TRADE)) group.setField(fix.MDEntryPx(float(trades[i][0]))) group.setField(fix.MDEntrySize(float(trades[i][1]))) message.addGroup(group) self.logger.debug(f"Clients {self.clients}") print(message.__str__().replace("\x01", "|")) if symbol in self.clients: for session in self.clients[symbol]: fix.Session.sendToTarget(message, session)
def parse_MarketDataSnapshotFullRefresh(self, message, sending_time): if self.verbose: print(self._server_str + ' {MD} Full refresh!') symbol = extract_message_field_value(fix.Symbol(), message) if symbol in self.history_dict: num_entries = extract_message_field_value(fix.NoMDEntries(), message, 'int') # 268 # MarketDataSnapshotFullRefresh message contains multiple NoQuoteSets group # Groups have indexes in FIX messages starting at 1 NoMDEntries_Group = fix44.MarketDataSnapshotFullRefresh.NoMDEntries( ) # NoMDEntries_Group = fix44.MarketDataIncrementalRefresh.NoMDEntries() for i in range(num_entries): message.getGroup(i + 1, NoMDEntries_Group) bid, ask, bid_size, ask_size = None, None, None, None _type = extract_message_field_value( fix.MDEntryType(), NoMDEntries_Group, 'str') # 269 (0: bid, 1: ask) price = extract_message_field_value(fix.MDEntryPx(), NoMDEntries_Group, 'float') # 270 size = extract_message_field_value(fix.MDEntrySize(), NoMDEntries_Group, 'float') # 271 depth = extract_message_field_value(fix.QuoteEntryID(), NoMDEntries_Group, 'int') # 299 if _type == '0': bid = price bid_size = size elif _type == '1': ask = price ask_size = size if self.verbose: print( f'symbol: {symbol} | bid: {bid} | ask: {ask} | bid_size: {bid_size} | ask_size: {ask_size}' ) self.update_asset(sending_time, symbol, depth, bid, ask, bid_size, ask_size)
def onMarketDataSnapshotFullRefresh(self, message, sessionID): skip_chance = random.choice(range(1, 101)) if self.skipSnapshotChance > skip_chance: self.logger.info( "FIXSIM-CLIENT onMarketDataSnapshotFullRefresh skip making trade with random choice %d", skip_chance) return fix_symbol = quickfix.Symbol() message.getField(fix_symbol) symbol = fix_symbol.getValue() snapshot = Snapshot(symbol) group = self.fixVersion.MarketDataSnapshotFullRefresh.NoMDEntries() fix_no_entries = quickfix.NoMDEntries() message.getField(fix_no_entries) no_entries = fix_no_entries.getValue() for i in range(1, no_entries + 1): message.getGroup(i, group) price = quickfix.MDEntryPx() size = quickfix.MDEntrySize() currency = quickfix.Currency() quote_id = quickfix.QuoteEntryID() group.getField(quote_id) group.getField(currency) group.getField(price) group.getField(size) quote = Quote() quote.price = price.getValue() quote.size = size.getValue() quote.currency = currency.getValue() quote.id = quote_id.getValue() fix_entry_type = quickfix.MDEntryType() group.getField(fix_entry_type) entry_type = fix_entry_type.getValue() if entry_type == quickfix.MDEntryType_BID: snapshot.addBid(quote) elif entry_type == quickfix.MDEntryType_OFFER: snapshot.addAsk(quote) else: raise RuntimeError("Unknown entry type %s" % str(entry_type)) self.makeOrder(snapshot)
def show(self, message): msgtype = fix.MsgType() message.getHeader().getField(msgtype) print(message.__str__().replace("\x01", "|")) _bids = [] _asks = [] _trades = [] if msgtype.getValue() == "W": symbol = fix.Symbol() message.getField(symbol) instrument = symbol.getValue() entry_type = fix.MDEntryType() entry_px = fix.MDEntryPx() entry_size = fix.MDEntrySize() entries = fix.NoMDEntries() message.getField(entries) group = fix44.MarketDataSnapshotFullRefresh().NoMDEntries() for i in range(entries.getValue()): message.getGroup(i + 1, group) group.getField(entry_type) group.getField(entry_px) group.getField(entry_size) if entry_type.getValue() == "0": _bids.append((entry_px.getValue(), entry_size.getValue())) elif entry_type.getValue() == "1": _asks.append((entry_px.getValue(), entry_size.getValue())) elif entry_type.getValue() == "2": _trades.append( (entry_px.getValue(), entry_size.getValue())) book = Book(instrument, _bids, _asks, _trades) print(book)
def onMessage(self, message, sessionID): print("OnMessage %s" % message) msgType = fix.MsgType() message.getHeader().getField(msgType) if (msgType.getValue() == "X"): print("MarketDataIncrementalRefresh %s" % message) noMDEntries = fix.NoMDEntries() message.getField(noMDEntries) if (noMDEntries.getValue() != 1): print("NoMDEntries in MarketDataIncrementalRefresh is not 1!") return group = fix44.MarketDataIncrementalRefresh.NoMDEntries() message.getGroup(1, group) entryID = fix.MDEntryID() group.getField(entryID) action = fix.MDUpdateAction() group.getField(action) actionvalue = action.getValue() # 0=New, 1=Update, 2=Delete) if (actionvalue == '2'): # delete if entryID.getValue() in securities: del securities[entryID.getValue()] return security = SECURITY() security.MDEntryID = entryID.getValue() security.MDUpdateAction = action.getValue() symbol = fix.Symbol() if (group.isSetField(symbol)): group.getField(symbol) security.Symbol = symbol.getValue() entryType = fix.MDEntryType() if (group.isSetField(entryType)): group.getField(entryType) security.MDEntryType = entryType.getValue() price = fix.MDEntryPx() if (group.isSetField(price)): group.getField(price) security.MDEntryPx = price.getValue() size = fix.MDEntrySize() if (group.isSetField(size)): group.getField(size) security.MDEntrySize = size.getValue() qty = fix.MinQty() if (group.isSetField(qty)): group.getField(qty) security.MinQty = qty.getValue() inc = MinInc() if (message.isSetField(inc)): message.getField(inc) security.MinInc = inc.getValue() br = MinBr() if (message.isSetField(br)): message.getField(br) security.MinBR = br.getValue() ytm = YTM() if (message.isSetField(ytm)): message.getField(ytm) security.YTM = ytm.getValue() ytw = YTW() if (message.isSetField(ytw)): message.getField(ytw) security.YTW = ytw.getValue() print(security) securities[entryID.getValue()] = security
def onMessage_MarketDataSnapshotFullRefresh(self): """ onMessage - Market Data - Snapshot / Full Refresh Message Type = 'W'. The Market Data Snapshot/Full Refresh messages are sent as the response to a Market Data Request message. The message refers to only one Market Data Request. It will contain the appropiate MDReqID tag value to correlate the request with the response. Fields: - (35) MsgType = W - (262) MDReqID = (string) - Block Instrument: - (55) Symbol = (string - Ticker) - Block MDfullGrp: - (268) NoMDEntries = (Int - number of Entries) - (269) MDEntryType = 0 (Bid) / 1 (Offer) / 2 (Trade) / 4 (Opening price) / 5 (Closing Price) / 6 (Settlement Price) / 7 (Trading Session High Price) / 8 (Trading Session Low Price) / B (Trade Volume) / C (Open Interest) / x (Nominal Volume) / w (Cash Volume) - (270) MDEntryPx = (float - Conditional field when MDEntryType is 0-1-2-4-5-6-7-8-w) - (271) MDEntrySize = (int - Conditional field when MDEntryType is 0-1-2-B-C-x) - (290) MDEntryPositionNo = (int) """ data = {} ## Number of entries following (Bid, Offer, etc) noMDEntries = self.getValue(fix.NoMDEntries()) symbol = self.getValue(fix.Symbol()) ## Market ID (ROFX, BYMA) marketId = self.getValue(fix.SecurityExchange()) instrumentId = {"symbol": symbol, "marketId": marketId} data["instrumentId"] = instrumentId data["marketData"] = {"BI": [], "OF": []} group = fix50.MarketDataSnapshotFullRefresh().NoMDEntries() MDEntryType = fix.MDEntryType( ) # Identifies the type of entry (Bid, Offer, etc) MDEntryPx = fix.MDEntryPx() MDEntrySize = fix.MDEntrySize() MDEntryPositionNo = fix.MDEntryPositionNo( ) # Display position of a bid or offer, numbered from most competitive to least competitive """ table = texttable.Texttable() table.set_deco(texttable.Texttable.BORDER|texttable.Texttable.HEADER) table.header(['Ticker','Tipo','Precio','Size','Posicion']) table.set_cols_width([12,20,8,8,8]) table.set_cols_align(['c','c','c','c','c']) """ for entry in range(1, int(noMDEntries) + 1): try: md = {} price, size, position = None, None, None self.message.getGroup(entry, group) entry_type = group.getField(MDEntryType).getString() if entry_type in list('01245678w'): # campos que tienen precio price = group.getField(MDEntryPx).getString() md['price'] = float(price) if entry_type in list('012BCx'): # campos que tienen size size = group.getField(MDEntrySize).getString() md['size'] = int(size) if entry_type in list('01'): # campos que tienen orden position = group.getField(MDEntryPositionNo).getString() md['position'] = int(position) if entry_type == '0': data["marketData"]["BI"].append(md) tipo = 'BID' elif entry_type == '1': data["marketData"]["OF"].append(md) tipo = 'OFFER' elif entry_type == 'B': data["marketData"]["TV"] = md tipo = 'TRADE VOLUME' else: tipo = entry_type # table.add_row([symbol, tipo, price, size, position]) except: pass # Aca antes de devolver se puede mandar a una cola o algo return data
def run(self): message = fix44.MarketDataSnapshotFullRefresh() group = fix44.MarketDataSnapshotFullRefresh().NoMDEntries() group.setField(fix.MDEntryType('0')) group.setField(fix.MDEntryPx(12.32)) group.setField(fix.MDEntrySize(100)) group.setField(fix.OrderID("ORDERID")) group.setField(fix.NumberOfOrders(1000)) group.setField(fix.MDEntrySeller('RIL')) group.setField(fix.MDMkt('BSE')) #group.setField(fix.MDEntryTime(20200723)) message.addGroup(group) group.setField(fix.MDEntryType('0')) group.setField(fix.MDEntryPx(12.32)) group.setField(fix.MDEntrySize(100)) group.setField(fix.OrderID("ORDERID")) group.setField(fix.NumberOfOrders(1000)) group.setField(fix.MDEntrySeller('RIL')) group.setField(fix.MDMkt('BSE')) # group.setField(fix.MDEntryTime(20200723)) message.addGroup(group) group.setField(fix.MDEntryType('1')) group.setField(fix.MDEntryPx(12.34)) group.setField(fix.MDEntrySize(104)) group.setField(fix.OrderID("ORDERID2")) group.setField(fix.NumberOfOrders(9087)) group.setField(fix.MDEntrySeller('BHEL')) group.setField(fix.MDMkt('NSE')) # group.setField(fix.MDEntryTime(20200429)) message.addGroup(group) group.setField(fix.MDEntryType('1')) group.setField(fix.MDEntryPx(12.34)) group.setField(fix.MDEntrySize(104)) group.setField(fix.OrderID("ORDERID2")) group.setField(fix.NumberOfOrders(9087)) group.setField(fix.MDEntrySeller('BHEL')) group.setField(fix.MDMkt('NSE')) # group.setField(fix.MDEntryTime(20200429)) message.addGroup(group) group.setField(fix.MDEntryType('0')) group.setField(fix.MDEntryPx(18.92)) group.setField(fix.MDEntrySize(2000)) group.setField(fix.OrderID("ORDERID3")) group.setField(fix.NumberOfOrders(10050)) group.setField(fix.MDEntrySeller('TCS')) group.setField(fix.MDMkt('BSE')) # group.setField(fix.MDEntryTime(20200723)) message.addGroup(group) group.setField(fix.MDEntryType('0')) group.setField(fix.MDEntryPx(200.32)) group.setField(fix.MDEntrySize(1006)) group.setField(fix.OrderID("ORDERID4")) group.setField(fix.NumberOfOrders(1000)) group.setField(fix.MDEntrySeller('Credit Suisse')) group.setField(fix.MDMkt('BSE')) # group.setField(fix.MDEntryTime(20200723)) message.addGroup(group) group.setField(fix.MDEntryType('0')) group.setField(fix.MDEntryPx(1000)) group.setField(fix.MDEntrySize(100)) group.setField(fix.OrderID("ORDERID6")) group.setField(fix.NumberOfOrders(1000)) group.setField(fix.MDEntrySeller('Aramco')) group.setField(fix.MDMkt('BSE')) # group.setField(fix.MDEntryTime(20200723)) message.addGroup(group) group.setField(fix.MDEntryType('1')) group.setField(fix.MDEntryPx(12.67)) group.setField(fix.MDEntrySize(1045)) group.setField(fix.OrderID("ORDERID7")) group.setField(fix.NumberOfOrders(8960)) group.setField(fix.MDEntrySeller('Zomato')) group.setField(fix.MDMkt('NSE')) # group.setField(fix.MDEntryTime(20200429)) message.addGroup(group) group.setField(fix.MDEntryType('1')) group.setField(fix.MDEntryPx(129)) group.setField(fix.MDEntrySize(10894)) group.setField(fix.OrderID("ORDERID8")) group.setField(fix.NumberOfOrders(9076)) group.setField(fix.MDEntrySeller('Gilbarco')) group.setField(fix.MDMkt('NSE')) # group.setField(fix.MDEntryTime(20200429)) message.addGroup(group) group.setField(fix.MDEntryType('1')) group.setField(fix.MDEntryPx(198)) group.setField(fix.MDEntrySize(1034)) group.setField(fix.OrderID("ORDERID9")) group.setField(fix.NumberOfOrders(9087)) group.setField(fix.MDEntrySeller('Huwawei')) group.setField(fix.MDMkt('NSE')) # group.setField(fix.MDEntryTime(20200429)) message.addGroup(group) fix.Session_sendToTarget(message, self.sessionID) return
def onMessage(self, message, sessionID): # print("OnMessage %s" % message) msgType = fix.MsgType() message.getHeader().getField(msgType) if msgType.getValue() == "X": # print("MarketDataIncrementalRefresh %s" % message) noMDEntries = fix.NoMDEntries() message.getField(noMDEntries) if (noMDEntries.getValue() != 1): # print("NoMDEntries in MarketDataIncrementalRefresh is not 1!") return group = fix44.MarketDataIncrementalRefresh.NoMDEntries() message.getGroup(1, group) entryID = fix.MDEntryID() group.getField(entryID) action = fix.MDUpdateAction() group.getField(action) security = LAST_TRADE() security.MDEntryID = entryID.getValue() security.MDUpdateAction = action.getValue() symbol = fix.Symbol() if (group.isSetField(symbol)): group.getField(symbol) security.Symbol = symbol.getValue() entryType = fix.MDEntryType() if (group.isSetField(entryType)): group.getField(entryType) security.MDEntryType = entryType.getValue() price = fix.MDEntryPx() if (group.isSetField(price)): group.getField(price) security.MDEntryPx = price.getValue() size = fix.MDEntrySize() if (group.isSetField(size)): group.getField(size) security.MDEntrySize = size.getValue() qty = fix.MinQty() if (group.isSetField(qty)): group.getField(qty) security.MinQty = qty.getValue() fire(self.callback, "OnTradeUpdated", **{"trade": security}) if msgType.getValue() == 'W': book = BOOK() Symbol = fix.Symbol() message.getField(Symbol) book.symbol = Symbol.getValue() noMDEntries = fix.NoMDEntries() message.getField(noMDEntries) group = fix44.MarketDataSnapshotFullRefresh.NoMDEntries() MDEntryType = fix.MDEntryType() MDEntryPx = fix.MDEntryPx() MDEntrySize = fix.MDEntrySize() for i in range(1, noMDEntries.getValue()): message.getGroup(i, group) group.getField(MDEntryType) group.getField(MDEntryPx) group.getField(MDEntrySize) if MDEntryType.getValue() == '0': book.bid.append(MDEntryPx.getValue()) book.bid_size.append(MDEntrySize.getValue()) if MDEntryType.getValue() == '1': book.ask.append(MDEntryPx.getValue()) book.ask_size.append(MDEntrySize.getValue()) fire(self.callback, "OnBookUpdated", **{"book": book})