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 parse_MassQuote(self, message, sending_time): if self.verbose: print(self._server_str + ' MassQuote!') ################################# # Enter Tick Storage Logic here. # we could have multiple QuoteSets for multiple symbols num_sets = extract_message_field_value(fix.NoQuoteSets(), message, 'int') # 296 # print('num_sets:', num_sets) for i in range(num_sets): NoQuoteSets_Group = fix44.MassQuote.NoQuoteSets() # Groups have indexes in FIX messages starting at 1 message.getGroup(i + 1, NoQuoteSets_Group) reqid = extract_message_field_value(fix.QuoteSetID(), NoQuoteSets_Group) # print(self._id_to_symbol) _symbol = self._id_to_symbol[reqid] # Bid/Offer data is inside NoQuoteEntries group, inside _NoQuoteSets group. # num_sets = extract_message_field_value(fix.NoQuoteEntries(), message, 'int') # 295, should always be 1. NoQuoteEntries_Group = fix44.MassQuote.NoQuoteSets.NoQuoteEntries() NoQuoteSets_Group.getGroup(1, NoQuoteEntries_Group) depth = extract_message_field_value(fix.QuoteEntryID(), NoQuoteEntries_Group, 'int') # 299 bid = extract_message_field_value(fix.BidSpotRate(), NoQuoteEntries_Group, 'float') # 188 ask = extract_message_field_value(fix.OfferSpotRate(), NoQuoteEntries_Group, 'float') # 190 bid_size = extract_message_field_value(fix.BidSize(), NoQuoteEntries_Group, 'int') # 134 ask_size = extract_message_field_value(fix.OfferSize(), NoQuoteEntries_Group, 'int') # 135 self.update_asset(sending_time, _symbol, depth, bid, ask, bid_size, ask_size) ################################# # If QuoteID is set the client has to respond immediately with a MassQuoteAcknowledgement. if message.isSetField(fix.QuoteID()): self.sender.send_MassQuoteAcknowledgement(message)
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)