/*
* Copyright (c) 2004-2011 Marco Maccaferri and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marco Maccaferri - initial API and implementation
*/
package org.eclipsetrader.core.ats.simulation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Currency;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipsetrader.core.Cash;
import org.eclipsetrader.core.instruments.ISecurity;
import org.eclipsetrader.core.internal.CoreActivator;
import org.eclipsetrader.core.trading.IAccount;
import org.eclipsetrader.core.trading.IOrderSide;
import org.eclipsetrader.core.trading.IPosition;
import org.eclipsetrader.core.trading.IPositionListener;
import org.eclipsetrader.core.trading.ITransaction;
import org.eclipsetrader.core.trading.PositionEvent;
public class Account implements IAccount {
private final String id;
private Double balance = 0.0;
private final List<Transaction> transactions = new ArrayList<Transaction>();
private final Map<ISecurity, Position> positions = new HashMap<ISecurity, Position>();
private final ListenerList listeners = new ListenerList();
public Account() {
this.id = UUID.randomUUID().toString();
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#getId()
*/
@Override
public String getId() {
return id;
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#getDescription()
*/
@Override
public String getDescription() {
return "Simulated Account";
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#getBalance()
*/
@Override
public Cash getBalance() {
return new Cash(balance, Currency.getInstance(Locale.getDefault()));
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#getTransactions()
*/
@Override
public ITransaction[] getTransactions() {
return transactions.toArray(new ITransaction[transactions.size()]);
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#getPositions()
*/
@Override
public IPosition[] getPositions() {
Collection<Position> c = positions.values();
return c.toArray(new IPosition[c.size()]);
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#addPositionListener(org.eclipsetrader.core.trading.IPositionListener)
*/
@Override
public void addPositionListener(IPositionListener listener) {
listeners.add(listener);
}
/* (non-Javadoc)
* @see org.eclipsetrader.core.trading.IAccount#removePositionListener(org.eclipsetrader.core.trading.IPositionListener)
*/
@Override
public void removePositionListener(IPositionListener listener) {
listeners.remove(listener);
}
public void processCompletedOrder(OrderMonitor monitor) {
Transaction transaction = new Transaction(monitor, monitor.getOrder().getDate());
monitor.setTransaction(transaction);
transactions.add(transaction);
Long quantity = monitor.getOrder().getSide() == IOrderSide.Sell ? -monitor.getFilledQuantity() : monitor.getFilledQuantity();
double averagePrice = transaction.getAmount().getAmount() / monitor.getFilledQuantity();
balance -= quantity * averagePrice;
Position position = positions.get(monitor.getOrder().getSecurity());
if (position == null) {
position = new Position(monitor.getOrder().getSecurity(), quantity, averagePrice);
positions.put(position.getSecurity(), position);
firePositionOpenedEvent(position);
}
else {
position.add(quantity, averagePrice);
if (position.getQuantity() == 0L) {
positions.remove(position.getSecurity());
firePositionClosedEvent(position);
}
else {
firePositionChangedEvent(position);
}
}
}
protected void firePositionOpenedEvent(Position position) {
PositionEvent event = new PositionEvent(this, position);
Object[] l = listeners.getListeners();
for (int i = 0; i < l.length; i++) {
try {
((IPositionListener) l[i]).positionOpened(event);
} catch (Throwable t) {
Status status = new Status(IStatus.ERROR, CoreActivator.PLUGIN_ID, "Error notifying listeners", t);
CoreActivator.log(status);
}
}
}
protected void firePositionClosedEvent(Position position) {
PositionEvent event = new PositionEvent(this, position);
Object[] l = listeners.getListeners();
for (int i = 0; i < l.length; i++) {
try {
((IPositionListener) l[i]).positionClosed(event);
} catch (Throwable t) {
Status status = new Status(IStatus.ERROR, CoreActivator.PLUGIN_ID, "Error notifying listeners", t);
CoreActivator.log(status);
}
}
}
protected void firePositionChangedEvent(Position position) {
PositionEvent event = new PositionEvent(this, position);
Object[] l = listeners.getListeners();
for (int i = 0; i < l.length; i++) {
try {
((IPositionListener) l[i]).positionChanged(event);
} catch (Throwable t) {
Status status = new Status(IStatus.ERROR, CoreActivator.PLUGIN_ID, "Error notifying listeners", t);
CoreActivator.log(status);
}
}
}
}