/** * Copyright 2011 Archfirst * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.archfirst.bfexch.spec.matchingengine; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; import javax.inject.Inject; import org.apache.commons.lang.StringUtils; import org.archfirst.bfexch.domain.marketdata.MarketDataService; import org.archfirst.bfexch.domain.marketdata.MarketPrice; import org.archfirst.bfexch.domain.trading.MatchingEngine; import org.archfirst.bfexch.domain.trading.order.ExecutionReport; import org.archfirst.bfexch.domain.trading.order.ExecutionReportType; import org.archfirst.bfexch.domain.trading.order.Order; import org.archfirst.bfexch.domain.trading.order.OrderSide; import org.archfirst.bfexch.domain.trading.order.OrderStatus; import org.archfirst.bfexch.domain.trading.order.OrderTerm; import org.archfirst.bfexch.domain.trading.order.OrderType; import org.archfirst.bfexch.spec.mocks.OrderEventRecorder; import org.archfirst.common.datetime.DateTimeUtil; import org.archfirst.common.money.Money; import org.archfirst.common.quantity.DecimalQuantity; import org.archfirst.common.springtest.AbstractTransactionalSpecTest; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.BeforeMethod; /** * MatchingEngineBaseTest * * @author Naresh Bhatia */ @ContextConfiguration(locations={"classpath:/org/archfirst/bfexch/spec/applicationContext.xml"}) public abstract class MatchingEngineBaseTest extends AbstractTransactionalSpecTest { @Inject private MarketDataService marketDataService; @Inject private MatchingEngine matchingEngine; @Inject protected OrderEventRecorder eventRecorder; @BeforeMethod public void setup() { eventRecorder.clear(); } public void setupSymbol(String symbol) { marketDataService.createMarketPrice(symbol, new Money("10.00")); } public void createMarketPrice(String symbol, String price) { marketDataService.createMarketPrice(symbol, new Money(price)); } public void placeOrder( String creationTime, String clientOrderId, String side, String symbol, BigDecimal quantity, String type, String limitPrice, String gtc, String allOrNone) { Order order = new Order( DateTimeUtil.parseDateTimeSecond(creationTime), clientOrderId, OrderSide.valueOf(side), symbol, new DecimalQuantity(quantity), OrderType.valueOf(type), (StringUtils.isEmpty(limitPrice)) ? null : new Money(limitPrice), (StringUtils.equalsIgnoreCase(gtc, "Y")) ? OrderTerm.GoodTilCanceled : OrderTerm.GoodForTheDay, (StringUtils.equalsIgnoreCase(allOrNone, "Y")) ? true : false); matchingEngine.placeOrder(order); } public void clearExecutionReports() { eventRecorder.clear(); } public List<OrderOut> getBuyStack(String symbol) { return convertOrders( matchingEngine.getOrderBook(symbol).getBuyStack()); } public List<OrderOut> getSellStack(String symbol) { return convertOrders( matchingEngine.getOrderBook(symbol).getSellStack()); } private List<OrderOut> convertOrders(SortedSet<Order> orders) { List<OrderOut> result = new ArrayList<OrderOut>(); for (Order order : orders) { result.add(new OrderOut(order)); } return result; } public List<ExecutionReportOut> getExecutionReports() { return convertExecutionReports(eventRecorder.getExecutionReports()); } private List<ExecutionReportOut> convertExecutionReports( List<ExecutionReport> executionReports) { List<ExecutionReportOut> result = new ArrayList<ExecutionReportOut>(); for (ExecutionReport executionReport : executionReports) { result.add(new ExecutionReportOut(executionReport)); } return result; } public int getNumberOfFills() { int numberOfFills = 0; List<ExecutionReport> executionReports = eventRecorder.getExecutionReports(); for (ExecutionReport executionReport : executionReports) { if (executionReport.getType() == ExecutionReportType.Trade) { if (executionReport.getOrderStatus() == OrderStatus.Filled || executionReport.getOrderStatus() == OrderStatus.PartiallyFilled) { numberOfFills++; } } } return numberOfFills; } public BigDecimal getMarketPrice(String symbol) { MarketPrice marketPrice = marketDataService.getMarketPrice(symbol); return marketPrice.getPrice().getAmount(); } public class OrderOut { private final Order order; public OrderOut(Order order) { this.order = order; } public String getCreationTime() { return DateTimeUtil.toStringDateTimeSecond(order.getCreationTime()); } public String getClientOrderId() { return order.getClientOrderId(); } public OrderSide getSide() { return order.getSide(); } public String getSymbol() { return order.getSymbol(); } public DecimalQuantity getQuantity() { return order.getQuantity(); } public OrderType getType() { return order.getType(); } public String getLimitPrice() { return (order.getLimitPrice() == null) ? "" : order.getLimitPrice().getAmount().toString(); } public String getGtc() { return (order.getTerm() == OrderTerm.GoodTilCanceled) ? "Y" : ""; } public String getAllOrNone() { return order.isAllOrNone() ? "Y" : ""; } public OrderStatus getStatus() { return order.getStatus(); } } public class ExecutionReportOut { private final ExecutionReport executionReport; public ExecutionReportOut(ExecutionReport executionReport) { this.executionReport = executionReport; } public ExecutionReportType getType() { return executionReport.getType(); } public String getOrderId() { return executionReport.getOrderId(); } public String getClientOrderId() { return executionReport.getClientOrderId(); } public OrderStatus getOrderStatus() { return executionReport.getOrderStatus(); } public OrderSide getSide() { return executionReport.getSide(); } public String getSymbol() { return executionReport.getSymbol(); } public String getLastQty() { DecimalQuantity lastQty = executionReport.getLastQty(); return (lastQty != null) ? lastQty.toString() : ""; } public DecimalQuantity getLeavesQty() { return executionReport.getLeavesQty(); } public DecimalQuantity getCumQty() { return executionReport.getCumQty(); } public String getLastPrice() { Money lastPrice = executionReport.getLastPrice(); return (lastPrice != null) ? lastPrice.getAmount().toString() : ""; } } }