/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.aggregation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.threeten.bp.LocalDate;
import com.opengamma.core.historicaltimeseries.HistoricalTimeSeriesSource;
import com.opengamma.core.position.Position;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.financial.security.FinancialSecurity;
import com.opengamma.financial.security.FinancialSecurityVisitor;
import com.opengamma.financial.security.FinancialSecurityVisitorAdapter;
import com.opengamma.financial.security.equity.EquitySecurity;
import com.opengamma.financial.security.option.EquityOptionSecurity;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.UniqueId;
import com.opengamma.util.CompareUtils;
import com.opengamma.util.tuple.Pair;
/**
* Function to classify positions by Currency.
*
*/
public class CurrentMarketCapAggregationFunction implements AggregationFunction<String> {
private boolean _useAttributes;
private static final String NAME = "Market Cap";
private static final String FIELD = "CUR_MKT_CAP";
private static final String RESOLUTION_KEY = "DEFAULT_TSS_CONFIG";
private static final String NO_CUR_MKT_CAP = "N/A";
private static final double NANO_CAP_UPPER_THRESHOLD = 10;
private static final double MICRO_CAP_UPPER_THRESHOLD = 100;
private static final double SMALL_CAP_UPPER_THRESHOLD = 1000;
private static final double MID_CAP_UPPER_THRESHOLD = 10E3;
//private static final double LARGE_CAP_UPPER_THRESHOLD = 100E3;
private static final String NANO_CAP = "Nano Cap";
private static final String MICRO_CAP = "Micro Cap";
private static final String SMALL_CAP = "Small Cap";
private static final String MID_CAP = "Mid Cap";
private static final String LARGE_CAP = "Large Cap";
private static final List<String> REQUIRED = Arrays.asList(LARGE_CAP, MID_CAP, SMALL_CAP, MICRO_CAP, NANO_CAP, NO_CUR_MKT_CAP);
private HistoricalTimeSeriesSource _htsSource;
private SecuritySource _secSource;
private boolean _caching = true;
private Map<UniqueId, Double> _currMktCapCache = new HashMap<UniqueId, Double>();
public CurrentMarketCapAggregationFunction(SecuritySource secSource, HistoricalTimeSeriesSource htsSource, boolean useAttributes) {
_secSource = secSource;
_htsSource = htsSource;
_useAttributes = useAttributes;
}
public CurrentMarketCapAggregationFunction(SecuritySource secSource, HistoricalTimeSeriesSource htsSource) {
this(secSource, htsSource, false);
}
private FinancialSecurityVisitor<Double> _equitySecurityVisitor = new FinancialSecurityVisitorAdapter<Double>() {
@Override
public Double visitEquitySecurity(EquitySecurity security) {
return getCurrentMarketCap(security);
}
};
private FinancialSecurityVisitor<Double> _equityOptionSecurityVisitor = new FinancialSecurityVisitorAdapter<Double>() {
@Override
public Double visitEquityOptionSecurity(EquityOptionSecurity security) {
EquitySecurity underlying = (EquitySecurity) _secSource.get(ExternalIdBundle.of(security.getUnderlyingId()));
return getCurrentMarketCap(underlying);
}
};
protected Double getCurrentMarketCap(Security security) {
try {
if (_caching && security.getUniqueId() != null) {
if (_currMktCapCache.containsKey(security.getUniqueId())) {
return _currMktCapCache.get(security.getUniqueId());
}
}
ExternalIdBundle externalIdBundle = security.getExternalIdBundle();
Pair<LocalDate, Double> latest = _htsSource.getLatestDataPoint(FIELD, externalIdBundle, RESOLUTION_KEY);
if (latest != null && latest.getSecond() != null) {
_currMktCapCache.put(security.getUniqueId(), latest.getSecond());
return latest.getSecond();
} else {
_currMktCapCache.put(security.getUniqueId(), null);
return null;
}
} catch (UnsupportedOperationException ex) {
return null;
}
}
private String getCurrentMarketCapCategory(Double currentMarketCap) {
if (currentMarketCap != null) {
if (currentMarketCap < NANO_CAP_UPPER_THRESHOLD) {
return NANO_CAP;
} else if (currentMarketCap < MICRO_CAP_UPPER_THRESHOLD) {
return MICRO_CAP;
} else if (currentMarketCap < SMALL_CAP_UPPER_THRESHOLD) {
return SMALL_CAP;
} else if (currentMarketCap < MID_CAP_UPPER_THRESHOLD) {
return MID_CAP;
} else {
return LARGE_CAP;
}
} else {
return NO_CUR_MKT_CAP;
}
}
@Override
public String classifyPosition(Position position) {
if (_useAttributes) {
Map<String, String> attributes = position.getAttributes();
if (attributes.containsKey(getName())) {
return attributes.get(getName());
} else {
return NO_CUR_MKT_CAP;
}
} else {
FinancialSecurityVisitor<Double> visitorAdapter = FinancialSecurityVisitorAdapter.<Double>builder()
.equitySecurityVisitor(_equitySecurityVisitor)
.equityOptionVisitor(_equityOptionSecurityVisitor)
.create();
FinancialSecurity security = (FinancialSecurity) position.getSecurityLink().resolve(_secSource);
Double currMarketCap = security.accept(visitorAdapter);
String classification = getCurrentMarketCapCategory(currMarketCap);
return classification == null ? NO_CUR_MKT_CAP : classification;
}
}
public String getName() {
return NAME;
}
@Override
public Collection<String> getRequiredEntries() {
return REQUIRED;
}
@Override
public int compare(String marketCapBucket1, String marketCapBucket2) {
return CompareUtils.compareByList(REQUIRED, marketCapBucket1, marketCapBucket2);
}
private class PositionComparator implements Comparator<Position> {
@Override
public int compare(Position position1, Position position2) {
FinancialSecurityVisitor<Double> visitorAdapter = FinancialSecurityVisitorAdapter.<Double>builder()
.equitySecurityVisitor(_equitySecurityVisitor)
.equityOptionVisitor(_equityOptionSecurityVisitor)
.create();
FinancialSecurity security1 = (FinancialSecurity) position1.getSecurityLink().resolve(_secSource);
FinancialSecurity security2 = (FinancialSecurity) position2.getSecurityLink().resolve(_secSource);
Double currMktCap1 = security1.accept(visitorAdapter);
Double currMktCap2 = security2.accept(visitorAdapter);
return CompareUtils.compareWithNullLow(currMktCap1, currMktCap2);
}
}
@Override
public Comparator<Position> getPositionComparator() {
return new PositionComparator();
}
}