Package com.quantcomponents.algo.service

Source Code of com.quantcomponents.algo.service.PositionCalculator

/*******************************************************************************
* Copyright (c) 2013 Luigi Sgro. 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:
*     Luigi Sgro - initial API and implementation
******************************************************************************/
package com.quantcomponents.algo.service;

import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.quantcomponents.algo.IPosition;
import com.quantcomponents.algo.ITrade;
import com.quantcomponents.algo.ITradingListener;
import com.quantcomponents.algo.PositionBean;
import com.quantcomponents.core.model.IContract;
import com.quantcomponents.core.model.ISeriesPoint;
import com.quantcomponents.core.model.OrderSide;
import com.quantcomponents.core.model.beans.ContractBean;

public class PositionCalculator implements ITradingListener {
  private final Map<IContract, PositionBean> positions = new ConcurrentHashMap<IContract, PositionBean>();
  private final Map<IContract, PositionBean> readonlyPositions = Collections.unmodifiableMap(positions);
 
  public Map<IContract, ? extends IPosition> getPositions() {
    return readonlyPositions;
  }
 
  public synchronized void reset() {
    positions.clear();
  }
 
  @Override
  public synchronized void onTrade(ITrade trade) {
    IContract contract = trade.getOrder().getContract();
    IContract currency = ContractBean.cash(contract.getCurrency());
    PositionBean contractPosition = positions.get(contract);
    if (contractPosition == null) {
      contractPosition = new PositionBean();
      positions.put(contract, contractPosition);
    }
    PositionBean cashPosition = positions.get(currency);
    if (cashPosition == null) {
      cashPosition = new PositionBean();
      cashPosition.setAveragePrice(1.0);
      cashPosition.setMarketPrice(1.0);
      positions.put(currency, cashPosition);
    }
    Integer contractMultiplier = contract.getMultiplier();
    if (contractMultiplier == null || contractMultiplier == 0) {
      contractMultiplier = 1;
    }
    contractPosition.setMarketPrice(trade.getExecutionPrice());
    contractPosition.setTimestamp(trade.getExecutionTime());
    cashPosition.setTimestamp(trade.getExecutionTime());
    double residueSignedPositionAmount = contractPosition.getSignedAmount();
    int residueTradeAmount = trade.getAmount();
    // reducing position
    if (residueSignedPositionAmount != 0) {
      if (residueSignedPositionAmount > 0 && trade.getOrder().getSide() == OrderSide.SELL) { // reducing long position
        double positionReduction = Math.min(residueSignedPositionAmount, residueTradeAmount);
        contractPosition.setRealizedPnl(contractPosition.getRealizedPnl() + (trade.getAveragePrice() - contractPosition.getAveragePrice()) * contractMultiplier * positionReduction);
        residueSignedPositionAmount -= positionReduction;
        residueTradeAmount -= positionReduction;
      } else if (residueSignedPositionAmount < 0 && trade.getOrder().getSide() == OrderSide.BUY) { // reducing short position
        double positionReduction = Math.min(-residueSignedPositionAmount, residueTradeAmount);
        contractPosition.setRealizedPnl(contractPosition.getRealizedPnl() + (contractPosition.getAveragePrice() - trade.getAveragePrice()) * contractMultiplier * positionReduction);
        residueSignedPositionAmount += positionReduction;
        residueTradeAmount -= positionReduction;
      }
    }
    double newSignedPositionAmount = residueSignedPositionAmount;
    if (newSignedPositionAmount == 0) {
      contractPosition.setAveragePrice(0.0);
    }
    // building position
    if (residueTradeAmount > 0) {
      if (trade.getOrder().getSide() == OrderSide.BUY) { // building long position from 0 or more
        newSignedPositionAmount = residueSignedPositionAmount + residueTradeAmount;
        contractPosition.setAveragePrice((contractPosition.getAveragePrice() * residueSignedPositionAmount + trade.getAveragePrice() * residueTradeAmount) / newSignedPositionAmount);
      } else { // building long position from 0 or less
        newSignedPositionAmount = residueSignedPositionAmount - residueTradeAmount;
        contractPosition.setAveragePrice((contractPosition.getAveragePrice() * residueSignedPositionAmount - trade.getAveragePrice() * residueTradeAmount) / newSignedPositionAmount);
      }
    }
    contractPosition.setSignedAmount(newSignedPositionAmount);
    double cashChange = trade.getAveragePrice() * trade.getAmount() * contractMultiplier * (trade.getOrder().getSide() == OrderSide.BUY ? -1 : 1);;
    cashPosition.setSignedAmount(cashPosition.getSignedAmount() + cashChange);
    recalculateMarketValueAndUPnl();
  }

  @Override
  public void onPriceUpdate(IContract contract, ISeriesPoint<Date, Double> price) {
    updateMarketPrice(contract, price.getIndex(), price.getValue());
  }
 
  private void updateMarketPrice(IContract contract, Date timestamp, double price) {
    PositionBean position = positions.get(contract);
    if (position != null) {
      if (price != position.getMarketPrice()) {
        position.setMarketPrice(price);
        position.setTimestamp(timestamp);
        recalculateMarketValueAndUPnl();
      }
    }
  }

  private void recalculateMarketValueAndUPnl() {
    for (Map.Entry<IContract, PositionBean> entry : positions.entrySet()) {
      Integer contractMultiplier = entry.getKey().getMultiplier();
      if (contractMultiplier == null || contractMultiplier == 0) {
        contractMultiplier = 1;
      }
      PositionBean position = entry.getValue();
      position.setMarketValue(position.getMarketPrice() * position.getSignedAmount() * contractMultiplier);
      position.setUnrealizedPnl(position.getMarketValue() - position.getAveragePrice() * position.getSignedAmount() * contractMultiplier);
    }
  }
TOP

Related Classes of com.quantcomponents.algo.service.PositionCalculator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.