package edu.brown.benchmark.tpce.generators; import java.lang.reflect.Method; import java.util.Date; import java.util.GregorianCalendar; import java.util.LinkedList; import java.util.Queue; import edu.brown.benchmark.tpce.generators.TradeGenerator.TradeType; import edu.brown.benchmark.tpce.util.EGenMoney; import edu.brown.benchmark.tpce.util.EGenRandom; public class MEETickerTape { public long getRNGSeed(){ return( rnd.getSeed() ); } public void setRNGSeed( long RNGSeed ){ rnd.setSeed( RNGSeed ); } public void initialize(){ txnInput = new TMarketFeedTxnInput(); txnInput.StatusAndTradeType.status_submitted = new String("SBMT"); txnInput.StatusAndTradeType.type_limit_buy = new String("TLB"); txnInput.StatusAndTradeType.type_limit_sell = new String("TLS"); txnInput.StatusAndTradeType.type_stop_loss = new String("TSL"); } public MEETickerTape(MEESUTInterface sut, MEEPriceBoard priceBoard, Date baseTime, Date currentTime ){ this.sut = sut; this.priceBoard = priceBoard; batchIndex = 0; rnd = new EGenRandom( EGenRandom.RNG_SEED_BASE_MEE_TICKER_TAPE); enabled = true; this.baseTime = baseTime; this.currentTime = currentTime; inTheMoneyLimitOrderQ = new LinkedList<TTickerEntry> (); Method AddLimitTrigger = null; try{ AddLimitTrigger = MEETickerTape.class.getMethod("AddLimitTrigger", TTickerEntry.class); }catch(Exception e){ e.printStackTrace(); } limitOrderTimers = new TimerWheel(TTickerEntry.class, this, AddLimitTrigger, 900, 1000); initialize(); } public MEETickerTape(MEESUTInterface sut, MEEPriceBoard priceBoard, Date baseTime, Date currentTime, long RNGSeed ){ this.sut = sut; this.priceBoard = priceBoard; batchIndex = 0; rnd = new EGenRandom(RNGSeed); enabled = true; this.baseTime = baseTime; this.currentTime = currentTime; inTheMoneyLimitOrderQ = new LinkedList<TTickerEntry> (); initialize(); } public boolean DisableTicker(){ enabled = false; return( ! enabled ); } public boolean EnableTicker(){ enabled = true; return( enabled ); } public void AddEntry( TTickerEntry tickerEntry ){ if( enabled ){ AddToBatch( tickerEntry); AddArtificialEntries( ); } } public void PostLimitOrder( TTradeRequest tradeRequest ){ TradeType eTradeType; double CurrentPrice = -1.0; TTickerEntry pNewEntry = new TTickerEntry(); eTradeType = ConvertTradeTypeIdToEnum(tradeRequest.trade_type_id.toCharArray()); pNewEntry.price_quote = tradeRequest.price_quote; pNewEntry.symbol = new String(tradeRequest.symbol); pNewEntry.trade_qty = LIMIT_TRIGGER_TRADE_QTY; CurrentPrice = priceBoard.getCurrentPrice( tradeRequest.symbol ).getDollars(); if((( eTradeType == TradeType.eLimitBuy || eTradeType == TradeType.eStopLoss ) && CurrentPrice <= tradeRequest.price_quote ) || (( eTradeType == TradeType.eLimitSell ) && CurrentPrice >= tradeRequest.price_quote )){ pNewEntry.price_quote = CurrentPrice; limitOrderTimers.processExpiredTimers(); inTheMoneyLimitOrderQ.add(pNewEntry); } else{ pNewEntry.price_quote = tradeRequest.price_quote; double TriggerTimeDelay; GregorianCalendar currGreTime = new GregorianCalendar(); GregorianCalendar baseGreTime = new GregorianCalendar(); currGreTime.setTime(currentTime); baseGreTime.setTime(baseTime); double fCurrentTime = currGreTime.getTimeInMillis() - baseGreTime.getTimeInMillis(); //TODO the third para, compare to c++ TriggerTimeDelay = priceBoard.getSubmissionTime(pNewEntry.symbol, fCurrentTime, new EGenMoney(pNewEntry.price_quote), eTradeType) - fCurrentTime; limitOrderTimers.startTimer( TriggerTimeDelay); } } public void AddLimitTrigger( TTickerEntry tickerEntry ){ inTheMoneyLimitOrderQ.add( tickerEntry ); } public void AddArtificialEntries(){ long SecurityIndex; TTickerEntry TickerEntry = new TTickerEntry(); int TotalEntryCount = 0; final int PaddingLimit = (TxnHarnessStructs.max_feed_len / 10) - 1; final int PaddingLimitForAll = PaddingLimit; final int PaddingLimitForTriggers = PaddingLimit; while ( TotalEntryCount < PaddingLimitForTriggers && !inTheMoneyLimitOrderQ.isEmpty() ) { TTickerEntry pEntry = inTheMoneyLimitOrderQ.peek(); AddToBatch( pEntry ); inTheMoneyLimitOrderQ.poll(); TotalEntryCount++; } while ( TotalEntryCount < PaddingLimitForAll ) { TickerEntry.trade_qty = ( rnd.rndPercent( 50 )) ? RANDOM_TRADE_QTY_1 : RANDOM_TRADE_QTY_2; SecurityIndex = rnd.int64Range( 0, priceBoard.getNumOfSecurities() - 1 ); TickerEntry.price_quote = (priceBoard.getCurrentPrice( SecurityIndex )).getDollars(); priceBoard.getSymbol( SecurityIndex, TickerEntry.symbol, TickerEntry.symbol.length() ); AddToBatch( TickerEntry ); TotalEntryCount++; } } public void AddToBatch( TTickerEntry tickerEntry ){ txnInput.Entries[batchIndex++] = tickerEntry; if( TxnHarnessStructs.max_feed_len == batchIndex ){ sut.MarketFeed( txnInput ); batchIndex = 0; } } public TradeType ConvertTradeTypeIdToEnum( char[] tradeType ){ switch( tradeType[0] ){ case 'T': switch( tradeType[1] ){ case 'L': switch( tradeType[2] ){ case 'B': return( TradeType.eLimitBuy ); case 'S': return( TradeType.eLimitSell ); default: break; } break; case 'M': switch( tradeType[2] ){ case 'B': return( TradeType.eMarketBuy ); case 'S': return( TradeType.eMarketSell ); default: break; } break; case 'S': switch( tradeType[2] ){ case 'L': return( TradeType.eStopLoss ); default: break; } break; default: break; } break; default: break; } assert(false); return TradeType.eMarketBuy; } private MEESUTInterface sut; private MEEPriceBoard priceBoard; private TMarketFeedTxnInput txnInput; private int batchIndex; private EGenRandom rnd; private boolean enabled; private InputFileHandler statusType; private InputFileHandler tradeType; public final int LIMIT_TRIGGER_TRADE_QTY = 375; public final int RANDOM_TRADE_QTY_1 = 325; public final int RANDOM_TRADE_QTY_2 = 425; private TimerWheel limitOrderTimers; private Queue<TTickerEntry> inTheMoneyLimitOrderQ; private Date baseTime; private Date currentTime; }