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 }