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    }