/*
* 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 com.ib.client.Contract;
import com.ib.client.ContractDetails;
import com.ib.client.EWrapper;
import com.ib.client.Execution;
import com.ib.client.Order;
import com.ib.client.OrderState;
import com.ib.client.UnderComp;
/**
* Base implementation of the EWrapper interface with empty handlers for every event
* and common handling of error and closed connection conditions.
* Extending classes need override only the events they want to handle.
*
* @author jgoetsch
*
*/
public class BaseHandler implements EWrapper {
private boolean closedConnection;
private int errorCode;
private String errorMsg;
public static final int STATUS_WORKING = 0;
public static final int STATUS_SUCCESS = 1;
public static final int STATUS_FAILED = 2;
protected final static int MAX_WAIT_COUNT = 2; // 5 secs
protected final static int WAIT_TIME = 2500;
public int getErrorCode() {
return errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public boolean isClosedConnection() {
return closedConnection;
}
/**
* Should be overridden to return success when the conditions that the handler must
* wait for to be considered complete are satisfied. The default implementation returns
* failed status on closed connection or error or working otherwise.
*
* @return STATUS_WORKING, STATUS_SUCCESS, or STATUS_FAILED
*/
public int getStatus() {
if (isClosedConnection())
return STATUS_FAILED;
else
return STATUS_WORKING;
}
/**
* Puts the current thread into a wait state until the handler reports
* either success or failure or a timeout is reached.
*
* @return true if handler reported success, false if failed or timed out
*/
public final boolean block() {
int waitCount = 0;
while (getStatus() == BaseHandler.STATUS_WORKING && (++waitCount) <= MAX_WAIT_COUNT) {
try {
this.wait(WAIT_TIME);
} catch (InterruptedException e) {}
}
return (getStatus() == STATUS_SUCCESS);
}
/**
* Handle connection closed event. Mark closed and wake up threads waiting on this handler.
*/
public synchronized void connectionClosed() {
this.closedConnection = true;
this.notifyAll();
}
/**
* Handle error event. Record error and wake up threads waiting on this handler.
*/
public synchronized void error(int id, int errorCode, String errorMsg) {
this.errorCode = errorCode;
this.errorMsg = errorMsg;
this.notifyAll();
}
public void error(Exception e) {
}
public void error(String str) {
}
/*
* empty EWrapper event method implementations to be overridden
*/
public void bondContractDetails(int reqId, ContractDetails contractDetails) {
}
public void contractDetails(int reqId, ContractDetails contractDetails) {
}
public void contractDetailsEnd(int reqId) {
}
public void currentTime(long time) {
}
public void execDetails(int orderId, Contract contract, Execution execution) {
}
public void fundamentalData(int reqId, String data) {
}
public void historicalData(int reqId, String date, double open,
double high, double low, double close, int volume, int count,
double WAP, boolean hasGaps) {
}
public void managedAccounts(String accountsList) {
}
public void nextValidId(int orderId) {
}
public void openOrder(int orderId, Contract contract, Order order,
OrderState orderState) {
}
public void orderStatus(int orderId, String status, int filled,
int remaining, double avgFillPrice, int permId, int parentId,
double lastFillPrice, int clientId, String whyHeld) {
}
public void realtimeBar(int reqId, long time, double open, double high,
double low, double close, long volume, double wap, int count) {
}
public void receiveFA(int faDataType, String xml) {
}
public void scannerData(int reqId, int rank,
ContractDetails contractDetails, String distance, String benchmark,
String projection, String legsStr) {
}
public void scannerDataEnd(int reqId) {
}
public void scannerParameters(String xml) {
}
public void tickEFP(int tickerId, int tickType, double basisPoints,
String formattedBasisPoints, double impliedFuture, int holdDays,
String futureExpiry, double dividendImpact, double dividendsToExpiry) {
}
public void tickGeneric(int tickerId, int tickType, double value) {
}
public void tickOptionComputation(int tickerId, int field,
double impliedVol, double delta, double modelPrice,
double pvDividend) {
}
public void tickPrice(int tickerId, int field, double price,
int canAutoExecute) {
}
public void tickSize(int tickerId, int field, int size) {
}
public void tickString(int tickerId, int tickType, String value) {
}
public void updateAccountTime(String timeStamp) {
}
public void updateAccountValue(String key, String value, String currency,
String accountName){
}
public void updateMktDepth(int tickerId, int position, int operation,
int side, double price, int size) {
}
public void updateMktDepthL2(int tickerId, int position,
String marketMaker, int operation, int side, double price, int size) {
}
public void updateNewsBulletin(int msgId, int msgType, String message,
String origExchange) {
}
public void updatePortfolio(Contract contract, int position,
double marketPrice, double marketValue, double averageCost,
double unrealizedPNL, double realizedPNL, String accountName) {
}
public void accountDownloadEnd(String accountName) {
}
public void deltaNeutralValidation(int reqId, UnderComp underComp) {
}
public void execDetailsEnd(int reqId) {
}
public void openOrderEnd() {
}
public void tickSnapshotEnd(int reqId) {
}
}