/*
* Copyright (c) 2012 Jeremy Goetsch
*
* 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 com.jgoetsch.ib.handlers;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import com.jgoetsch.ib.TWSUtils;
import com.jgoetsch.tradeframework.Contract;
import com.jgoetsch.tradeframework.account.AccountData;
import com.jgoetsch.tradeframework.account.Position;
import com.jgoetsch.tradeframework.account.PresetPosition;
/**
* Handler that will wait for the specified account value to be returned and
* store it.
*
* @author jgoetsch
*
*/
public class AccountDataHandler extends BaseHandler implements AccountData {
private String accountCode;
private Map<String, Object> accountValues;
private Map<Contract, Position> positions;
private String updatedTimestampValue;
private long timestamp;
private boolean isDone = false;
public AccountDataHandler() {
this.accountValues = new TreeMap<String, Object>();
this.positions = new HashMap<Contract, Position>();
}
public AccountDataHandler(String accountCode) {
this();
this.accountCode = accountCode;
}
@Override
public synchronized void updateAccountValue(String key, String value, String currency, String accountName) {
if (accountCode == null || accountCode.equals(accountName)) {
try {
accountValues.put(key, Double.valueOf(value));
} catch (NumberFormatException ex) {
accountValues.put(key, value);
}
}
}
@Override
public synchronized void updatePortfolio(com.ib.client.Contract contract, int position,
double marketPrice, double marketValue, double averageCost,
double unrealizedPNL, double realizedPNL, String accountName)
{
if (accountCode == null || accountCode.equals(accountName)) {
positions.put(TWSUtils.fromTWSContract(contract), new PresetPosition(position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL));
}
}
@Override
public synchronized void updateAccountTime(String timeStamp) {
updatedTimestampValue = timeStamp;
timestamp = System.currentTimeMillis();
}
@Override
public synchronized void accountDownloadEnd(String accountName) {
if (accountCode == null || accountCode.equals(accountName)) {
isDone = true;
this.notifyAll();
}
}
@Override
public int getStatus() {
if (isDone)
return STATUS_SUCCESS;
else
return super.getStatus();
}
public double getCashBalance() {
Double value = (Double)accountValues.get("CashBalance");
return value == null ? 0 : value.doubleValue();
}
public double getNetLiquidationValue() {
Double value = (Double)accountValues.get("NetLiquidation");
return value == null ? 0 : value.doubleValue();
}
public Map<Contract, Position> getPositions() {
return positions;
}
public double getValue(String valueType) {
if (accountValues.containsKey(valueType))
return (Double)accountValues.get(valueType);
else
return 0;
}
@Override
public String toString() {
return "[AccountValueHandler net liq value = " + getNetLiquidationValue() + "]";
}
public String getSummaryText() {
NumberFormat df = new DecimalFormat("$#,###,##0;($#,###,##0)");
NumberFormat price = new DecimalFormat("0.###");
StringBuilder sb = new StringBuilder();
//sb.append("\nProfit(Loss)\t\t").append(df.format(accountValues.get("PNL")));
//sb.append("\t").append(pcnt.format(accountValues.get("PNL") / (getNetLiquidationValue() - accountValues.get("PNL"))));
for (Map.Entry<String, Object> e: accountValues.entrySet()) {
sb.append("\n").append(e.getKey());
for (int i=0; i < 4 - e.getKey().length() / 8; i++)
sb.append('\t');
sb.append(e.getValue());
}
sb.append("\n\nNet Liquidation Value\t\t").append(df.format(getNetLiquidationValue()));
sb.append("\nLast Updated Time\t\t").append(updatedTimestampValue).append("\t").append(DateFormat.getDateTimeInstance().format(new Date(timestamp)));
sb.append("\nOpen Positions:");
for (Map.Entry<Contract, ? extends Position> posEntry : positions.entrySet()) {
String contractTitle = posEntry.getKey().toString();
sb.append("\n\t").append(posEntry.getValue().getQuantity()).append("\t").append(contractTitle);
for (int i=0; i < 2 - contractTitle.length() / 8; i++)
sb.append('\t');
sb.append(price.format(posEntry.getValue().getAvgPrice()));
sb.append("\t").append(price.format(posEntry.getValue().getMarketPrice()));
sb.append("\t").append(df.format(posEntry.getValue().getUnrealizedProfitLoss()));
sb.append("\t").append(df.format(posEntry.getValue().getRealizedProfitLoss()));
}
return sb.toString();
}
public long getTimestamp() {
return timestamp;
}
}