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;
019
020 import org.otfeed.event.ICompletionDelegate;
021 import org.otfeed.event.IDataDelegate;
022 import org.otfeed.event.OTTodaysOHL;
023 import org.otfeed.protocol.CommandEnum;
024 import org.otfeed.protocol.DataEnum;
025 import org.otfeed.protocol.ProtocolException;
026
027 import java.nio.ByteBuffer;
028
029 /**
030 * Request to receive current OHL (open-high-low) data.
031 */
032 public class TodaysOHLRequest extends AbstractSessionRequest {
033
034 private final String exchangeCode;
035 private final String symbolCode;
036
037 private final IDataDelegate<OTTodaysOHL> dataDelegate;
038
039 public String getExchangeCode() { return exchangeCode; }
040 public String getSymbolCode() { return symbolCode; }
041
042 public TodaysOHLRequest(int requestId,
043 String exchangeCode,
044 String symbolCode,
045 IDataDelegate<OTTodaysOHL> dataDelegate,
046 ICompletionDelegate completionDelegate) {
047
048 super(CommandEnum.REQUEST_HIST_DATA,
049 requestId, completionDelegate);
050
051 Check.notNull(exchangeCode, "exchangeCode");
052 Check.notNull(symbolCode, "symbolCode");
053 Check.notNull(dataDelegate, "dataDelegate");
054
055 this.exchangeCode = exchangeCode;
056 this.symbolCode = symbolCode;
057 this.dataDelegate = dataDelegate;
058 }
059
060 @Override
061 public void writeRequest(ByteBuffer out) {
062 super.writeRequest(out);
063
064 Util.writeString(out, exchangeCode, 15);
065 Util.writeString(out, symbolCode, 15);
066 out.put((byte) 0);
067 out.put((byte) 0);
068 out.putInt(0);
069 out.putInt(0);
070 out.put((byte) 9); // special code, meaning "get ohlc"
071 out.put((byte) 0);
072 out.putShort((short) 0);
073 }
074
075 private static OTTodaysOHL readTodaysOHL(ByteBuffer in) {
076 double ohl_openPrice = in.getDouble();
077 double ohl_highPrice = in.getDouble();
078 double ohl_lowPrice = in.getDouble();
079
080 return new OTTodaysOHL(ohl_openPrice,
081 ohl_highPrice, ohl_lowPrice);
082 }
083
084 @Override
085 public JobStatus handleMessage(Header header, ByteBuffer in) {
086 super.handleMessage(header, in);
087
088 int count = in.getInt();
089
090 // to the best of my knowledge, TodaysOHL request returns only
091 // one event. Therefore, we have to return end-of data
092 // right away... Note that this is exactly what CPP driver from Opentick
093 // Corp. does (but not .NET one).
094 if(count < 0 || count > 1) {
095 throw new ProtocolException("unexpected number of todaysOHL events", in);
096 }
097
098 while(count -- > 0) {
099 int typeCode = in.get();
100
101 if(typeCode == DataEnum.EOD.code) {
102 return JobStatus.FINISHED;
103 }
104
105 if(typeCode != DataEnum.OHL_TODAY.code) {
106 throw new ProtocolException("unexpected OHL data code: " + typeCode, in);
107 }
108
109 OTTodaysOHL ohl = readTodaysOHL(in);
110 dataDelegate.onData(ohl);
111 }
112
113 return JobStatus.FINISHED; // ???
114 }
115 }