package com.activequant.trading;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.activequant.domainmodel.ETransportType;
import com.activequant.domainmodel.TimeStamp;
import com.activequant.domainmodel.exceptions.TransportException;
import com.activequant.domainmodel.streaming.PNLChangeEvent;
import com.activequant.interfaces.trading.IRiskCalculator;
import com.activequant.interfaces.transport.IPublisher;
import com.activequant.interfaces.transport.ITransportFactory;
import com.activequant.trading.datamodel.InstrumentTable;
import com.activequant.trading.datamodel.QuoteTable;
/**
* should be decoupled from abstractTSBase.
* Should send out risk events.
* Abstract TS Base should manage risk events.
*
* @author GhostRider
*
*/
public class PositionRiskCalculator implements IRiskCalculator {
private AbstractTSBase tsBase;
private Map<String, Double> positions = new HashMap<String, Double>();
private Map<String, Double> lastValPrices = new HashMap<String, Double>();
private Map<String, Double> avgPrices = new HashMap<String, Double>();
private IPublisher riskDataPublisher = null;
private List<Long> lastEvalMinutes = new ArrayList<Long>();
//
public PositionRiskCalculator(AbstractTSBase tsBase) {
this.tsBase = tsBase;
}
@Override
public void setTransportFactory(ITransportFactory transportFactory) {
try {
riskDataPublisher = transportFactory.getPublisher(ETransportType.RISK_DATA.toString());
} catch (TransportException e) {
e.printStackTrace();
}
}
/**
* This one can be used to make the pos risk calculator recompute pnl by setting a price with zero quantity
*/
public PNLChangeEvent execution(TimeStamp ts, String tid, double price, double quantity) {
return pnl(ts, tid, price, quantity);
}
public void setPosition(String tid, double price, double quantity){
positions.put(tid, quantity);
lastValPrices.put(tid, price);
avgPrices.put(tid, price);
}
private PNLChangeEvent pnl(TimeStamp ts, String tid, double price, double posChange) {
PNLChangeEvent pce = null;
Double formerPos = positions.get(tid);
Double lastValuationPrice = lastValPrices.get(tid);
Double avgPrice = avgPrices.get(tid);
if (formerPos == null) {
formerPos = 0.0;
lastValuationPrice = 0.0;
}
Double newPos = formerPos + posChange;
if (formerPos != 0.0) {
// revalue the former position.
double pnlChange = (price - lastValuationPrice) * formerPos;
double unrealizedPnl = (price - avgPrice) * formerPos;
if(newPos==0.0)
unrealizedPnl = 0.0;
pce = new PNLChangeEvent(ts, tid, pnlChange, unrealizedPnl);
try {
riskDataPublisher.send(pce);
} catch (Exception e) {
e.printStackTrace();
}
}
if(posChange!=0.0)
positions.put(tid, newPos);
lastValPrices.put(tid, price);
return pce;
}
private boolean recalc(int rowIndex){
while(lastEvalMinutes.size()<(rowIndex+1)){
lastEvalMinutes.add(0L);
}
long lastEval = lastEvalMinutes.get(rowIndex);
long currentMinute = tsBase.getCurrentTimeSlot();
if(lastEval!=currentMinute){
lastEvalMinutes.set(rowIndex, currentMinute);
return true;
}
return false;
}
@Override
public PNLChangeEvent pricesUpdated(int rowIndex) {
PNLChangeEvent pce = null;
if (recalc(rowIndex)) {
String mdiId = (String) tsBase.getQuoteTable().getCell(rowIndex, QuoteTable.Columns.INSTRUMENTID.colIdx());
// get the tradeable ID.
int rowIndex2 = tsBase.getInstrumentTable().getRowIndexOf(mdiId);
String tid = (String) tsBase.getInstrumentTable().getCell(rowIndex2,
InstrumentTable.Columns.TRADEABLEID.colIdx());
Double position = positions.get(tid);
if (position != null && position != 0.0) {
Double valPrice = null;
if (position > 0.0)
valPrice = (Double) tsBase.getQuoteTable().getCell(rowIndex, QuoteTable.Columns.BID.colIdx());
else
valPrice = (Double) tsBase.getQuoteTable().getCell(rowIndex, QuoteTable.Columns.ASK.colIdx());
//
if (valPrice != null)
pce = pnl(tsBase.currentTime, tid, valPrice, 0.0);
}
}
return null;
}
}