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 * Derived from code developed by Opentick Corporation, http://www.opentick.com.
018 */
019
020 package org.otfeed.event;
021
022 import static org.otfeed.event.IdentityUtil.equalsTo;
023 import static org.otfeed.event.IdentityUtil.safeCompare;
024 import static org.otfeed.event.IdentityUtil.safeHashCode;
025 import static org.otfeed.event.IdentityUtil.enumSetHashCode;
026 import static org.otfeed.event.IdentityUtil.compareEnumSet;
027
028 import java.io.Serializable;
029 import java.util.Date;
030 import java.util.HashSet;
031 import java.util.Set;
032
033
034 /**
035 * Provides either real-time or historical trade information.
036 * This event indicates that shares were sold and purchased
037 * (excepting some tracing messages).
038 * OTTrade stores price, size and other information about the deal.
039 */
040 public final class OTTrade implements Comparable<OTTrade>, Serializable {
041
042 private static final long serialVersionUID = -4048718961928459556L;
043
044 private Date timestamp;
045 private int size;
046 private double price;
047 private long volume;
048 private int sequenceNumber;
049 private char indicator;
050 private char tickIndicator;
051 private Set<TradePropertyEnum> properties = new HashSet<TradePropertyEnum>();
052 private String exchange;
053 private String symbol;
054
055 /**
056 * Default constructor.
057 */
058 public OTTrade() { }
059
060 /**
061 * Constructor.
062 * @param timestamp Time when the event occurred.
063 * @param size Number of shares traded in this transaction.
064 * @param price Trade price.
065 * @param volume Accumulated volume for the trading day.
066 * @param sequenceNumber Sequence number of trade.
067 * @param indicator Indicator.
068 * @param tickIndicator Tick indicator: D - Down, U - Up, N - Not provided.
069 * @param properties Trade properties.
070 * @param exchange Exchange code.
071 * @param symbol Symbol code.
072 */
073 public OTTrade(Date timestamp, int size, double price,
074 long volume, int sequenceNumber,
075 char indicator, char tickIndicator,
076 Set<TradePropertyEnum> properties,
077 String exchange, String symbol) {
078 this.timestamp = timestamp;
079 this.size = size;
080 this.price = price;
081 this.volume = volume;
082 this.sequenceNumber = sequenceNumber;
083 this.indicator = indicator;
084 this.tickIndicator = tickIndicator;
085 this.exchange = exchange;
086 this.symbol = symbol;
087 this.properties = properties;
088 }
089
090 /**
091 *
092 * @return Time when the event occurred.
093 */
094 public Date getTimestamp() {
095 return timestamp;
096 }
097
098 /**
099 * Sets time of the event.
100 * @param timestamp Time when the event occurred.
101 */
102 public void setTimestamp(Date timestamp) {
103 this.timestamp = timestamp;
104 }
105
106 /**
107 *
108 * @return Number of shares traded in this transaction.
109 */
110 public int getSize() {
111 return size;
112 }
113
114 /**
115 * Sets number of shares traded in this transaction.
116 * @param size Number of shares traded in this transaction.
117 */
118 public void setSize(int size) {
119 this.size = size;
120 }
121
122 /**
123 *
124 * @return Trade price.
125 */
126 public double getPrice() {
127 return price;
128 }
129
130 /**
131 * Sets trade price.
132 * @param price Trade price.
133 */
134 public void setPrice(double price) {
135 this.price = price;
136 }
137
138 /**
139 *
140 * @return Accumulated volume for the trading day.
141 */
142 public long getVolume() {
143 return volume;
144 }
145
146 /**
147 * Sets accumulated volume for the trading day.
148 * @param volume Accumulated volume for the trading day.
149 */
150 public void setVolume(long volume) {
151 this.volume = volume;
152 }
153
154 /**
155 *
156 * @return Sequence number of trade; used to correct trades in cancellations.
157 */
158 public int getSequenceNumber() {
159 return sequenceNumber;
160 }
161
162 /**
163 * Sets sequence number of trade.
164 * @param sequenceNumber Sequence number of trade.
165 */
166 public void setSequenceNumber(int sequenceNumber) {
167 this.sequenceNumber = sequenceNumber;
168 }
169
170 /**
171 *
172 * @return Indicator: See the Trade Indicators section for details.
173 */
174 public char getIndicator() {
175 return indicator;
176 }
177
178 /**
179 * Sets indicator.
180 * @param indicator Indicator.
181 */
182 public void setIndicator(char indicator) {
183 this.indicator = indicator;
184 }
185
186 /**
187 *
188 * @return Tick indicator: D - Down, U - Up, N - Not provided.
189 */
190 public char getTickIndicator() {
191 return tickIndicator;
192 }
193
194 /**
195 * Sets tick indicator: D - Down, U - Up, N - Not provided.
196 * @param tickIndicator Sets tick indicator: D - Down, U - Up, N - Not provided.
197 */
198 public void setTickIndicator(char tickIndicator) {
199 this.tickIndicator = tickIndicator;
200 }
201
202 /**
203 *
204 * @return Notes whether the trade provides the opening price for the day.
205 */
206 public boolean isOpen() {
207 return properties.contains(TradePropertyEnum.OPEN);
208 }
209
210 /**
211 *
212 * @return Notes whether the trade provides the high price for the day.
213 */
214 public boolean isHigh() {
215 return properties.contains(TradePropertyEnum.HIGH);
216 }
217
218 /**
219 * Returns set of boolean properties of this trade.
220 * One can check these properties individually by
221 * calling one of <code>isXXX</code> methods of this calsss.
222 *
223 */
224 public Set<TradePropertyEnum> getTradeProperties() {
225 return properties;
226 }
227
228 public void setTradeProperties(Set<TradePropertyEnum> p) {
229 properties = p;
230 }
231
232 /**
233 *
234 * @return Notes whether the trade provides the low price for the day.
235 */
236 public boolean isLow() {
237 return properties.contains(TradePropertyEnum.LOW);
238 }
239
240 /**
241 *
242 * @return Notes whether the trade provides the closing price for the day.
243 */
244 public boolean isClose() {
245 return properties.contains(TradePropertyEnum.CLOSE);
246 }
247
248 /**
249 *
250 * @return Notes whether the trade updates the last trade price.
251 */
252 public boolean isUpdateLast() {
253 return properties.contains(TradePropertyEnum.UPDATE_LAST);
254 }
255
256 /**
257 *
258 * @return Notes whether the volume is a replacement consolidated volume.
259 */
260 public boolean isUpdateVolume() {
261 return properties.contains(TradePropertyEnum.UPDATE_VOLUME);
262 }
263
264 /**
265 *
266 * @return Notes whether the trade is a cancel for a previous trade.
267 */
268 public boolean isCancel() {
269 return properties.contains(TradePropertyEnum.CANCEL);
270 }
271
272 /**
273 *
274 * @return Notes whether the trade is from an ECN book.
275 */
276 public boolean isFromBook() {
277 return properties.contains(TradePropertyEnum.FROM_BOOK);
278 }
279
280 /**
281 *
282 * @return Exchange code.
283 */
284 public String getExchange() {
285 return exchange;
286 }
287
288 /**
289 * Sets exchange code.
290 * @param exchange Exchange code.
291 */
292 public void setExchange(String exchange) {
293 this.exchange = exchange;
294 }
295
296 /**
297 *
298 * @return Symbol code; this field is provided for option chains only, because there can be more than one symbol appropriate to the requested underlyer and expiry date.
299 */
300 public String getSymbol() {
301 return symbol;
302 }
303
304 /**
305 * Sets symbol code.
306 * @param symbol Symbol code.
307 */
308 public void setSymbol(String symbol) {
309 this.symbol = symbol;
310 }
311
312 @Override
313 public String toString() {
314 String out = "OTTrade: timestamp="
315 + timestamp + ", price=" + price
316 + ", size=" + size + ", volume=" + volume
317 + ", sequencenumber=" + sequenceNumber
318 + ", indicator=" + indicator
319 + ", tickindicator=" + tickIndicator
320 + ", isopen=" + isOpen()
321 + ", ishigh=" + isHigh()
322 + ", islow=" + isLow()
323 + ", isclose=" + isClose()
324 + ", isupdatelast=" + isUpdateLast()
325 + ", isupdatevolume=" + isUpdateVolume()
326 + ", iscancel=" + isCancel()
327 + ", isfrombook=" + isFromBook()
328 + ", exchange=" + exchange
329 + ", symbol=" + symbol;
330 out += ", properties=";
331
332 boolean first = true;
333 for(TradePropertyEnum p : properties) {
334 if(first) { first = false; }
335 else { out += "|"; }
336 out += p;
337 }
338 return out;
339 }
340
341 @Override
342 public int hashCode() {
343 return safeHashCode(timestamp)
344 + 3 * safeHashCode(size)
345 + 5 * safeHashCode(price)
346 + 7 * safeHashCode(volume)
347 + 11 * safeHashCode(sequenceNumber)
348 + 17 * safeHashCode(indicator)
349 + 19 * safeHashCode(tickIndicator)
350 + 23 * enumSetHashCode(properties)
351 + 29 * safeHashCode(exchange)
352 + 31 * safeHashCode(symbol);
353 }
354
355 @Override
356 public boolean equals(Object o) {
357 return equalsTo(this, o);
358 }
359
360 public int compareTo(OTTrade other) {
361 int rc;
362
363 if((rc = safeCompare(timestamp, other.timestamp)) != 0) {
364 return rc;
365 }
366
367 if((rc = safeCompare(size, other.size)) != 0) {
368 return rc;
369 }
370
371 if((rc = safeCompare(price, other.price)) != 0) {
372 return rc;
373 }
374
375 if((rc = safeCompare(volume, other.volume)) != 0) {
376 return rc;
377 }
378
379 if((rc = safeCompare(sequenceNumber, other.sequenceNumber)) != 0) {
380 return rc;
381 }
382
383 if((rc = safeCompare(indicator, other.indicator)) != 0) {
384 return rc;
385 }
386
387 if((rc = safeCompare(tickIndicator, other.tickIndicator)) != 0) {
388 return rc;
389 }
390
391 if((rc = compareEnumSet(TradePropertyEnum.class, properties, other.properties)) != 0) {
392 return rc;
393 }
394
395 if((rc = safeCompare(exchange, other.exchange)) != 0) {
396 return rc;
397 }
398
399 if((rc = safeCompare(symbol, other.symbol)) != 0) {
400 return rc;
401 }
402
403 return 0;
404 }
405 }