001    /**
002     * Copyright 2007 Mike Kroutikov.
003     *
004     * This program is free software; you can redistribute it and/or modify
005     *   it under the terms of the Lesser GNU General Public License as 
006     *   published by the Free Software Foundation; either version 3 of
007     *   the License, or (at your option) any later version.
008     *
009     *   This program is distributed in the hope that it will be useful,
010     *   but WITHOUT ANY WARRANTY; without even the implied warranty of
011     *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012     *   Lesser GNU General Public License for more details.
013     *
014     *   You should have received a copy of the Lesser GNU General Public License
015     *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
016     */
017    
018    package org.otfeed.protocol.request.quote;
019    
020    import org.otfeed.event.IDataDelegate;
021    import org.otfeed.event.OTBBO;
022    import org.otfeed.event.OTMMQuote;
023    import org.otfeed.event.OTQuote;
024    import org.otfeed.event.OTTrade;
025    import org.otfeed.event.TradePropertyEnum;
026    import org.otfeed.event.TradeSideEnum;
027    
028    import org.otfeed.protocol.DataEnum;
029    import org.otfeed.protocol.ProtocolException;
030    import org.otfeed.protocol.request.Header;
031    import org.otfeed.protocol.request.Util;
032    
033    import java.nio.ByteBuffer;
034    import java.util.Date;
035    import java.util.Set;
036    
037    /**
038     * Class that knows how to de-serialize miscellaneous Quote events.
039     */
040    public abstract class QuoteReader {
041    
042            // no subclassing
043            private QuoteReader(DataEnum type) {
044                    this.type = type;
045                    this.mask = 1 << (type.code - 1);
046            }
047    
048            public final DataEnum type;
049            public final int mask;
050    
051            /**
052             * Reads data frame, parses response from the server, and 
053             * emits events.
054             *
055             * @param h response header.
056             * @param in data frame.
057             */
058            public abstract void read(Header h, ByteBuffer in);
059    
060            /**
061             * Creates reader for the Quote event.
062             */
063            public static final QuoteReader quoteReader(
064                            final IDataDelegate<OTQuote> dataDelegate) {
065                    return new QuoteReader(DataEnum.QUOTE) {
066    
067                            @Override
068                            public void read(Header h, ByteBuffer in) {
069                                    OTQuote quote = readQuote(in);
070                                    dataDelegate.onData(quote);
071                            }
072                            
073                    };
074            }
075            
076            /**
077             * Creates reader for the Quote event.
078             */
079            public static final QuoteReader quoteReaderEx(
080                            final IDataDelegate<OTQuote> dataDelegate) {
081                    return new QuoteReader(DataEnum.QUOTE) {
082    
083                            @Override
084                            public void read(Header h, ByteBuffer in) {
085                                    OTQuote quote = readQuoteEx(in);
086                                    dataDelegate.onData(quote);
087                            }
088                            
089                    };
090            }
091    
092            /**
093             * Creates reader for the Quote event.
094             */
095            public static final QuoteReader quoteReaderExEx(
096                            final IDataDelegate<OTQuote> dataDelegate) {
097                    return new QuoteReader(DataEnum.QUOTE) {
098    
099                            @Override
100                            public void read(Header h, ByteBuffer in) {
101                                    OTQuote quote = readQuoteExEx(in);
102                                    dataDelegate.onData(quote);
103                            }
104                            
105                    };
106            }
107    
108            private final static OTQuote readQuote(ByteBuffer in) {
109                    Date quote_timestamp     = Util.readDate(in);
110                    int quote_bidSize        = in.getInt();
111                    int quote_askSize        = in.getInt();
112                    double quote_bidPrice    = in.getDouble();
113                    double quote_askPrice    = in.getDouble();
114                    String quote_askExchange = Util.readString(in, 2).trim();
115                    char quote_indicator     = (char) in.get();
116                    char quote_tickIndicator = (char) in.get();
117    
118                    return new OTQuote(quote_timestamp,
119                            quote_bidSize, quote_bidPrice, quote_askSize,
120                            quote_askPrice, quote_askExchange, quote_indicator,
121                            quote_tickIndicator, "", "", "");
122            }
123    
124            private final static OTQuote readQuoteEx(ByteBuffer in) {
125                    OTQuote quote = readQuote(in);
126    
127                    String bidExchange = Util.readString(in, 2).trim();
128                    String exchange    = Util.readString(in, 2).trim();
129                    quote.setBidExchange(bidExchange);
130                    quote.setExchange(exchange);
131    
132                    return quote;
133            }
134    
135            private final static OTQuote readQuoteExEx(ByteBuffer in) {
136                    OTQuote quote = readQuoteEx(in);
137    
138                    String symbol = Util.readString(in, 15).trim();
139                    quote.setSymbol(symbol);
140    
141                    return quote;
142            }
143                        
144            /**
145             * Creates reader for the Trade event.
146             */
147            public static final QuoteReader tradeReader(
148                            final IDataDelegate<OTTrade> dataDelegate) {
149                    return new QuoteReader(DataEnum.TRADE) {
150    
151                            @Override
152                            public void read(Header h, ByteBuffer in) {
153                                    OTTrade data = readTrade(in);
154                                    dataDelegate.onData(data);
155                            }
156                            
157                    };
158            }
159    
160            /**
161             * Creates reader for the Trade event.
162             */
163            public static final QuoteReader tradeReaderEx(
164                            final IDataDelegate<OTTrade> dataDelegate) {
165                    return new QuoteReader(DataEnum.TRADE) {
166    
167                            @Override
168                            public void read(Header h, ByteBuffer in) {
169                                    OTTrade data = readTradeEx(in);
170                                    dataDelegate.onData(data);
171                            }
172                            
173                    };
174            }
175    
176            /**
177             * Creates reader for the Trade event.
178             */
179            public static final QuoteReader tradeReaderExEx(
180                            final IDataDelegate<OTTrade> dataDelegate) {
181                    return new QuoteReader(DataEnum.TRADE) {
182    
183                            @Override
184                            public void read(Header h, ByteBuffer in) {
185                                    OTTrade data = readTradeExEx(in);
186                                    dataDelegate.onData(data);
187                            }
188                            
189                    };
190            }
191    
192            private final static OTTrade readTrade(ByteBuffer in) {
193                    Date trade_timestamp     = Util.readDate(in);
194                    double trade_price       = in.getDouble();
195                    int trade_size           = in.getInt();
196                    long trade_volume        = in.getLong();
197                    int trade_sequenceNumber = in.getInt();
198                    char trade_indicator     = (char) in.get();
199                    char trade_tickIndicator = (char) in.get();
200                    Set<TradePropertyEnum> trade_properties = Util.readTradePropertySet(in);
201                    
202                    return new OTTrade(trade_timestamp,
203                        trade_size, trade_price, trade_volume,
204                        trade_sequenceNumber, trade_indicator,
205                        trade_tickIndicator, trade_properties, "", "");
206            }
207    
208            private final static OTTrade readTradeEx(ByteBuffer in) {
209                    OTTrade trade = readTrade(in);
210    
211                    String exchange = Util.readString(in, 2).trim();
212                    trade.setExchange(exchange);
213    
214                    return trade;
215            }
216    
217            private final static OTTrade readTradeExEx(ByteBuffer in) {
218                    OTTrade trade = readTradeEx(in);
219    
220                    String trade_symbol = Util.readString(in, 15).trim();
221                    trade.setSymbol(trade_symbol);
222    
223                    return trade;
224            }
225    
226            /**
227             * Creates reader for the MMQuote event.
228             */
229            public static final QuoteReader mmQuoteReader(
230                            final IDataDelegate<OTMMQuote> dataDelegate) {
231                    return new QuoteReader(DataEnum.MMQUOTE) {
232    
233                            @Override
234                            public void read(Header h, ByteBuffer in) {
235                                    OTMMQuote data = readMMQuote(in);
236                                    dataDelegate.onData(data);
237                            }
238                            
239                    };
240            }
241    
242            /**
243             * Creates reader for the MMQuote event.
244             */
245            public static final QuoteReader mmQuoteReaderEx(
246                            final IDataDelegate<OTMMQuote> dataDelegate) {
247                    return new QuoteReader(DataEnum.MMQUOTE) {
248    
249                            @Override
250                            public void read(Header h, ByteBuffer in) {
251                                    OTMMQuote data = readMMQuoteEx(in);
252                                    dataDelegate.onData(data);
253                            }
254                            
255                    };
256            }
257    
258            /**
259             * Creates reader for the MMQuote event.
260             */
261            public static final QuoteReader mmQuoteReaderExEx(
262                            final IDataDelegate<OTMMQuote> dataDelegate) {
263                    return new QuoteReader(DataEnum.MMQUOTE) {
264    
265                            @Override
266                            public void read(Header h, ByteBuffer in) {
267                                    OTMMQuote data = readMMQuoteExEx(in);
268                                    dataDelegate.onData(data);
269                            }
270                            
271                    };
272            }
273    
274            private final static OTMMQuote readMMQuote(ByteBuffer in) {
275                    Date mm_timestamp  = Util.readDate(in);
276                    int mm_bidSize     = in.getInt();
277                    int mm_askSize     = in.getInt();
278                    double mm_bidPrice = in.getDouble();
279                    double mm_askPrice = in.getDouble();
280                    String MMID        = Util.readString(in, 4).trim();
281                    char mm_indicator  = (char) in.get();
282    
283    
284                    return new OTMMQuote(mm_timestamp,
285                            mm_bidSize, mm_bidPrice, mm_askSize, mm_askPrice,
286                            MMID, mm_indicator, "", "");
287            }
288    
289            private final static OTMMQuote readMMQuoteEx(ByteBuffer in) {
290                    OTMMQuote mmQuote = readMMQuote(in);                    
291    
292                    String exchange = Util.readString(in, 2).trim();
293                    mmQuote.setExchange(exchange);
294    
295                    return mmQuote;
296            }
297    
298            private final static OTMMQuote readMMQuoteExEx(ByteBuffer in) {
299                    OTMMQuote mmQuote = readMMQuoteEx(in);                  
300    
301                    String mm_symbol = Util.readString(in, 15).trim();
302                    mmQuote.setSymbol(mm_symbol);
303    
304                    return mmQuote;
305            }
306    
307            /**
308             * Creates reader for the BBO event.
309             */
310            public static final QuoteReader bboReader(
311                            final IDataDelegate<OTBBO> dataDelegate) {
312                    return new QuoteReader(DataEnum.BBO) {
313    
314                            @Override
315                            public void read(Header h, ByteBuffer in) {
316                                    OTBBO data = readBBO(in);
317                                    dataDelegate.onData(data);
318                            }
319                            
320                    };
321            }
322    
323            /**
324             * Creates reader for the BBO event.
325             */
326            public static final QuoteReader bboReaderEx(
327                            final IDataDelegate<OTBBO> dataDelegate) {
328                    return new QuoteReader(DataEnum.BBO) {
329    
330                            @Override
331                            public void read(Header h, ByteBuffer in) {
332                                    OTBBO data = readBBOEx(in);
333                                    dataDelegate.onData(data);
334                            }
335                            
336                    };
337            }
338    
339            /**
340             * Creates reader for the BBO event.
341             */
342            public static final QuoteReader bboReaderExEx(
343                            final IDataDelegate<OTBBO> dataDelegate) {
344                    return new QuoteReader(DataEnum.BBO) {
345    
346                            @Override
347                            public void read(Header h, ByteBuffer in) {
348                                    OTBBO data = readBBOExEx(in);
349                                    dataDelegate.onData(data);
350                            }
351                            
352                    };
353            }
354    
355            private final static OTBBO readBBO(ByteBuffer in) {
356                    Date bboTimestamp = Util.readDate(in);
357                    double bboPrice   = in.getDouble();
358                    int bboSize       = in.getInt();
359                    char sideCode = (char) in.get();
360                    TradeSideEnum side = TradeSideEnum.SELLER;
361                    if(sideCode == 'B') {
362                            side = TradeSideEnum.BUYER;
363                    } else if(sideCode == 'A') {
364                            side = TradeSideEnum.SELLER;
365                    } else {
366                            throw new ProtocolException("unexpected side code: " + sideCode, in);
367                    }
368    
369                    return new OTBBO(bboTimestamp, bboPrice,
370                                    bboSize, side, "", "");
371            }
372    
373            private final static OTBBO readBBOEx(ByteBuffer in) {
374                    OTBBO bbo = readBBO(in);                        
375    
376                    String exchange = Util.readString(in, 2).trim();
377                    bbo.setExchange(exchange);
378    
379                    return bbo;
380            }
381    
382            private final static OTBBO readBBOExEx(ByteBuffer in) {
383                    OTBBO bbo = readBBOEx(in);                      
384    
385                    String bbo_symbol = Util.readString(in, 15).trim();
386                    bbo.setSymbol(bbo_symbol);
387    
388                    return bbo;
389            }
390    }