Package com.ib.controller

Source Code of com.ib.controller.ApiController

/* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved.  This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */

package com.ib.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.StringTokenizer;

import com.ib.client.CommissionReport;
import com.ib.client.Contract;
import com.ib.client.ContractDetails;
import com.ib.client.EWrapper;
import com.ib.client.Execution;
import com.ib.client.ExecutionFilter;
import com.ib.client.Order;
import com.ib.client.OrderState;
import com.ib.client.ScannerSubscription;
import com.ib.client.UnderComp;
import com.ib.controller.ApiConnection.ILogger;
import com.ib.controller.Types.BarSize;
import com.ib.controller.Types.DeepSide;
import com.ib.controller.Types.DeepType;
import com.ib.controller.Types.DurationUnit;
import com.ib.controller.Types.ExerciseType;
import com.ib.controller.Types.FADataType;
import com.ib.controller.Types.FundamentalType;
import com.ib.controller.Types.MktDataType;
import com.ib.controller.Types.NewsType;
import com.ib.controller.Types.WhatToShow;

public class ApiController implements EWrapper {
  private ApiConnection m_client;
  private final ILogger m_outLogger;
  private final ILogger m_inLogger;
  private int m_reqId;  // used for all requests except orders; designed not to conflict with m_orderId
  private int m_orderId;

  private final IConnectionHandler m_connectionHandler;
  private ITradeReportHandler m_tradeReportHandler;
  private IAdvisorHandler m_advisorHandler;
  private IScannerHandler m_scannerHandler;
  private ITimeHandler m_timeHandler;
  private IBulletinHandler m_bulletinHandler;
  private final HashMap<Integer,IInternalHandler> m_contractDetailsMap = new HashMap<Integer,IInternalHandler>();
  private final HashMap<Integer,IOptHandler> m_optionCompMap = new HashMap<Integer,IOptHandler>();
  private final HashMap<Integer,IEfpHandler> m_efpMap = new HashMap<Integer,IEfpHandler>();
  private final HashMap<Integer,ITopMktDataHandler> m_topMktDataMap = new HashMap<Integer,ITopMktDataHandler>();
  private final HashMap<Integer,IDeepMktDataHandler> m_deepMktDataMap = new HashMap<Integer,IDeepMktDataHandler>();
  private final HashMap<Integer, IScannerHandler> m_scannerMap = new HashMap<Integer, IScannerHandler>();
  private final HashMap<Integer, IRealTimeBarHandler> m_realTimeBarMap = new HashMap<Integer, IRealTimeBarHandler>();
  private final HashMap<Integer, IHistoricalDataHandler> m_historicalDataMap = new HashMap<Integer, IHistoricalDataHandler>();
  private final HashMap<Integer, IFundamentalsHandler> m_fundMap = new HashMap<Integer, IFundamentalsHandler>();
  private final HashMap<Integer, IOrderHandler> m_orderHandlers = new HashMap<Integer, IOrderHandler>();
  private final HashMap<Integer,IAccountSummaryHandler> m_acctSummaryHandlers = new HashMap<Integer,IAccountSummaryHandler>();
  private final HashMap<Integer,IMarketValueSummaryHandler> m_mktValSummaryHandlers = new HashMap<Integer,IMarketValueSummaryHandler>();
  private final ConcurrentHashSet<IPositionHandler> m_positionHandlers = new ConcurrentHashSet<IPositionHandler>();
  private final ConcurrentHashSet<IAccountHandler> m_accountHandlers = new ConcurrentHashSet<IAccountHandler>();
  private final ConcurrentHashSet<ILiveOrderHandler> m_liveOrderHandlers = new ConcurrentHashSet<ILiveOrderHandler>();

  // ---------------------------------------- Constructor and Connection handling ----------------------------------------
  public interface IConnectionHandler {
    void connected();
    void disconnected();
    void accountList(ArrayList<String> list);
    void error(Exception e);
    void message(int id, int errorCode, String errorMsg);
    void show(String string);
  }

  public ApiController( IConnectionHandler handler, ILogger inLogger, ILogger outLogger) {
    m_connectionHandler = handler;
    m_client = new ApiConnection( this, inLogger, outLogger);
    m_inLogger = inLogger;
    m_outLogger = outLogger;
  }

  public void connect( String host, int port, int clientId) {
    m_client.eConnect(host, port, clientId);
    sendEOM();
  }

  public void disconnect() {
    m_client.eDisconnect();
    m_connectionHandler.disconnected();
    sendEOM();
  }

  @Override public void managedAccounts(String accounts) {
    ArrayList<String> list = new ArrayList<String>();
    for( StringTokenizer st = new StringTokenizer( accounts, ","); st.hasMoreTokens(); ) {
      list.add( st.nextToken() );
    }
    m_connectionHandler.accountList( list);
    recEOM();
  }

  @Override public void nextValidId(int orderId) {
    m_orderId = orderId;
    m_reqId = m_orderId + 10000000; // let order id's not collide with other request id's
    if (m_connectionHandler != null) {
      m_connectionHandler.connected();
    }
    recEOM();
  }

  @Override public void error(Exception e) {
    m_connectionHandler.error( e);
  }

  @Override public void error(int id, int errorCode, String errorMsg) {
    IOrderHandler handler = m_orderHandlers.get( id);
    if (handler != null) {
      handler.handle( errorCode, errorMsg);
    }

    for (ILiveOrderHandler liveHandler : m_liveOrderHandlers) {
      liveHandler.handle( id, errorCode, errorMsg);
    }

    // "no sec def found" response?
    if (errorCode == 200) {
      IInternalHandler hand = m_contractDetailsMap.remove( id);
      if (hand != null) {
        hand.contractDetailsEnd();
      }
    }

    m_connectionHandler.message( id, errorCode, errorMsg);
    recEOM();
  }

  @Override public void connectionClosed() {
    m_connectionHandler.disconnected();
  }


  // ---------------------------------------- Account and portfolio updates ----------------------------------------
  public interface IAccountHandler {
    public void accountValue(String account, String key, String value, String currency);
    public void accountTime(String timeStamp);
    public void accountDownloadEnd(String account);
    public void updatePortfolio(Position position);
  }

    public void reqAccountUpdates(boolean subscribe, String acctCode, IAccountHandler handler) {
      m_accountHandlers.add( handler);
      m_client.reqAccountUpdates(subscribe, acctCode);
    sendEOM();
    }

  @Override public void updateAccountValue(String tag, String value, String currency, String account) {
    if (tag.equals( "Currency") ) { // ignore this, it is useless
      return;
    }

    for( IAccountHandler handler : m_accountHandlers) {
      handler.accountValue( account, tag, value, currency);
    }
    recEOM();
  }

  @Override public void updateAccountTime(String timeStamp) {
    for( IAccountHandler handler : m_accountHandlers) {
      handler.accountTime( timeStamp);
    }
    recEOM();
  }

  @Override public void accountDownloadEnd(String account) {
    for( IAccountHandler handler : m_accountHandlers) {
      handler.accountDownloadEnd( account);
    }
    recEOM();
  }

  @Override public void updatePortfolio(Contract contractIn, int positionIn, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, String account) {
    NewContract contract = new NewContract( contractIn);
    contract.exchange( contractIn.m_primaryExch);

    Position position = new Position( contract, account, positionIn, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL);
    for( IAccountHandler handler : m_accountHandlers) {
      handler.updatePortfolio( position);
    }
    recEOM();
  }

  // ---------------------------------------- Account Summary handling ----------------------------------------
  public interface IAccountSummaryHandler {
    void accountSummary( String account, AccountSummaryTag tag, String value, String currency);
    void accountSummaryEnd();
  }

  public interface IMarketValueSummaryHandler {
    void marketValueSummary( String account, MarketValueTag tag, String value, String currency);
    void marketValueSummaryEnd();
  }

  /** @param group pass "All" to get data for all accounts */
  public void reqAccountSummary(String group, AccountSummaryTag[] tags, IAccountSummaryHandler handler) {
    StringBuilder sb = new StringBuilder();
    for (AccountSummaryTag tag : tags) {
      if (sb.length() > 0) {
        sb.append( ',');
      }
      sb.append( tag);
    }

    int reqId = m_reqId++;
    m_acctSummaryHandlers.put( reqId, handler);
    m_client.reqAccountSummary( reqId, group, sb.toString() );
    sendEOM();
  }

  public void cancelAccountSummary(IAccountSummaryHandler handler) {
    Integer reqId = getAndRemoveKey( m_acctSummaryHandlers, handler);
    if (reqId != null) {
      m_client.cancelAccountSummary( reqId);
      sendEOM();
    }
  }

  public void reqMarketValueSummary(String group, IMarketValueSummaryHandler handler) {
    int reqId = m_reqId++;
    m_mktValSummaryHandlers.put( reqId, handler);
    m_client.reqAccountSummary( reqId, group, "$LEDGER");
    sendEOM();
  }

  public void cancelMarketValueSummary(IMarketValueSummaryHandler handler) {
    Integer reqId = getAndRemoveKey( m_mktValSummaryHandlers, handler);
    if (reqId != null) {
      m_client.cancelAccountSummary( reqId);
      sendEOM();
    }
  }

  @Override public void accountSummary( int reqId, String account, String tag, String value, String currency) {
    if (tag.equals( "Currency") ) { // ignore this, it is useless
      return;
    }

    IAccountSummaryHandler handler = m_acctSummaryHandlers.get( reqId);
    if (handler != null) {
      handler.accountSummary(account, AccountSummaryTag.valueOf( tag), value, currency);
    }

    IMarketValueSummaryHandler handler2 = m_mktValSummaryHandlers.get( reqId);
    if (handler2 != null) {
      handler2.marketValueSummary(account, MarketValueTag.valueOf( tag), value, currency);
    }

    recEOM();
  }

  @Override public void accountSummaryEnd( int reqId) {
    IAccountSummaryHandler handler = m_acctSummaryHandlers.get( reqId);
    if (handler != null) {
      handler.accountSummaryEnd();
    }

    IMarketValueSummaryHandler handler2 = m_mktValSummaryHandlers.get( reqId);
    if (handler2 != null) {
      handler2.marketValueSummaryEnd();
    }

    recEOM();
  }

  // ---------------------------------------- Position handling ----------------------------------------
  public interface IPositionHandler {
    void position( String account, NewContract contract, int position, double avgCost);
    void positionEnd();
  }

  public void reqPositions( IPositionHandler handler) {
    m_positionHandlers.add( handler);
    m_client.reqPositions();
    sendEOM();
  }

  public void cancelPositions( IPositionHandler handler) {
    m_positionHandlers.add( handler);
    m_client.cancelPositions();
    sendEOM();
  }

  @Override public void position(String account, Contract contractIn, int pos, double avgCost) {
    NewContract contract = new NewContract( contractIn);
    for (IPositionHandler handler : m_positionHandlers) {
      handler.position( account, contract, pos, avgCost);
    }
    recEOM();
  }

  @Override public void positionEnd() {
    for (IPositionHandler handler : m_positionHandlers) {
      handler.positionEnd();
    }
    recEOM();
  }

  // ---------------------------------------- Contract Details ----------------------------------------
  public interface IContractDetailsHandler {
    void contractDetails(ArrayList<NewContractDetails> list);
  }

  public void reqContractDetails( NewContract contract, final IContractDetailsHandler processor) {
    final ArrayList<NewContractDetails> list = new ArrayList<NewContractDetails>();
    internalReqContractDetails( contract, new IInternalHandler() {
      @Override public void contractDetails(NewContractDetails data) {
        list.add( data);
      }
      @Override public void contractDetailsEnd() {
        processor.contractDetails( list);
      }
    });
    sendEOM();
  }

  private interface IInternalHandler {
    void contractDetails(NewContractDetails data);
    void contractDetailsEnd();
  }

  private void internalReqContractDetails( NewContract contract, IInternalHandler processor) {
    int reqId = m_reqId++;
    m_contractDetailsMap.put( reqId, processor);
    m_client.reqContractDetails(reqId, contract.getContract() );
    sendEOM();
  }

  @Override public void contractDetails(int reqId, ContractDetails contractDetails) {
    IInternalHandler handler = m_contractDetailsMap.get( reqId);
    if (handler != null) {
      handler.contractDetails( new NewContractDetails( contractDetails) );
    }
    else {
      show( "Error: no contract details handler for reqId " + reqId);
    }
    recEOM();
  }

  @Override public void bondContractDetails(int reqId, ContractDetails contractDetails) {
    IInternalHandler handler = m_contractDetailsMap.get( reqId);
    if (handler != null) {
      handler.contractDetails(new NewContractDetails( contractDetails) );
    }
    else {
      show( "Error: no bond contract details handler for reqId " + reqId);
    }
    recEOM();
  }

  @Override public void contractDetailsEnd(int reqId) {
    IInternalHandler handler = m_contractDetailsMap.remove( reqId);
    if (handler != null) {
      handler.contractDetailsEnd();
    }
    else {
      show( "Error: no contract details handler for reqId " + reqId);
    }
    recEOM();
  }

  // ---------------------------------------- Top Market Data handling ----------------------------------------
  public interface ITopMktDataHandler {
    void tickPrice(NewTickType tickType, double price, int canAutoExecute);
    void tickSize(NewTickType tickType, int size);
    void tickString(NewTickType tickType, String value);
    void tickSnapshotEnd();
    void marketDataType(MktDataType marketDataType);
  }

  public interface IEfpHandler extends ITopMktDataHandler {
    void tickEFP(int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureExpiry, double dividendImpact, double dividendsToExpiry);
  }

  public interface IOptHandler extends ITopMktDataHandler {
    void tickOptionComputation( NewTickType tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice);
  }

  public static class TopMktDataAdapter implements ITopMktDataHandler {
    @Override public void tickPrice(NewTickType tickType, double price, int canAutoExecute) {
    }
    @Override public void tickSize(NewTickType tickType, int size) {
    }
    @Override public void tickString(NewTickType tickType, String value) {
    }
    @Override public void tickSnapshotEnd() {
    }
    @Override public void marketDataType(MktDataType marketDataType) {
    }
  }

    public void reqTopMktData(NewContract contract, String genericTickList, boolean snapshot, ITopMktDataHandler handler) {
      int reqId = m_reqId++;
      m_topMktDataMap.put( reqId, handler);
      m_client.reqMktData( reqId, contract.getContract(), genericTickList, snapshot);
    sendEOM();
    }

    public void reqOptionMktData(NewContract contract, String genericTickList, boolean snapshot, IOptHandler handler) {
      int reqId = m_reqId++;
      m_topMktDataMap.put( reqId, handler);
      m_optionCompMap.put( reqId, handler);
      m_client.reqMktData( reqId, contract.getContract(), genericTickList, snapshot);
    sendEOM();
    }

    public void reqEfpMktData(NewContract contract, String genericTickList, boolean snapshot, IEfpHandler handler) {
      int reqId = m_reqId++;
      m_topMktDataMap.put( reqId, handler);
      m_efpMap.put( reqId, handler);
      m_client.reqMktData( reqId, contract.getContract(), genericTickList, snapshot);
    sendEOM();
    }

    public void cancelTopMktData( ITopMktDataHandler handler) {
      Integer reqId = getAndRemoveKey( m_topMktDataMap, handler);
      if (reqId != null) {
        m_client.cancelMktData( reqId);
      }
      else {
        show( "Error: could not cancel top market data");
      }
    sendEOM();
    }

    public void cancelOptionMktData( IOptHandler handler) {
      cancelTopMktData( handler);
      getAndRemoveKey( m_optionCompMap, handler);
    }

    public void cancelEfpMktData( IEfpHandler handler) {
      cancelTopMktData( handler);
      getAndRemoveKey( m_efpMap, handler);
    }

  public void reqMktDataType( MktDataType type) {
    m_client.reqMarketDataType( type.ordinal() );
    sendEOM();
  }

  @Override public void tickPrice(int reqId, int tickType, double price, int canAutoExecute) {
    ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
    if (handler != null) {
      handler.tickPrice( NewTickType.get( tickType), price, canAutoExecute);
    }
    recEOM();
  }

  @Override public void tickGeneric(int reqId, int tickType, double value) {
    ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
    if (handler != null) {
      handler.tickPrice( NewTickType.get( tickType), value, 0);
    }
    recEOM();
  }

  @Override public void tickSize(int reqId, int tickType, int size) {
    ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
    if (handler != null) {
      handler.tickSize( NewTickType.get( tickType), size);
    }
    recEOM();
  }

  @Override public void tickString(int reqId, int tickType, String value) {
    ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
    if (handler != null) {
      handler.tickString( NewTickType.get( tickType), value);
    }
    recEOM();
  }

  @Override public void tickEFP(int reqId, int tickType, double basisPoints, String formattedBasisPoints, double impliedFuture, int holdDays, String futureExpiry, double dividendImpact, double dividendsToExpiry) {
    IEfpHandler handler = m_efpMap.get( reqId);
    if (handler != null) {
      handler.tickEFP( tickType, basisPoints, formattedBasisPoints, impliedFuture, holdDays, futureExpiry, dividendImpact, dividendsToExpiry);
    }
    recEOM();
  }

  @Override public void tickSnapshotEnd(int reqId) {
    ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
    if (handler != null) {
      handler.tickSnapshotEnd();
    }
    recEOM();
  }

  @Override public void marketDataType(int reqId, int marketDataType) {
    ITopMktDataHandler handler = m_topMktDataMap.get( reqId);
    if (handler != null) {
      handler.marketDataType( MktDataType.get( marketDataType) );
    }
    recEOM();
  }


  // ---------------------------------------- Deep Market Data handling ----------------------------------------
  public interface IDeepMktDataHandler {
    void updateMktDepth(int position, String marketMaker, DeepType operation, DeepSide side, double price, int size);
  }

    public void reqDeepMktData( NewContract contract, int numRows, IDeepMktDataHandler handler) {
      int reqId = m_reqId++;
      m_deepMktDataMap.put( reqId, handler);
      m_client.reqMktDepth( reqId, contract.getContract(), numRows);
    sendEOM();
    }

    public void cancelDeepMktData( IDeepMktDataHandler handler) {
      Integer reqId = getAndRemoveKey( m_deepMktDataMap, handler);
      if (reqId != null) {
        m_client.cancelMktDepth( reqId);
        sendEOM();
      }
    }

  @Override public void updateMktDepth(int reqId, int position, int operation, int side, double price, int size) {
    IDeepMktDataHandler handler = m_deepMktDataMap.get( reqId);
    if (handler != null) {
      handler.updateMktDepth( position, null, DeepType.get( operation), DeepSide.get( side), price, size);
    }
    recEOM();
  }

  @Override public void updateMktDepthL2(int reqId, int position, String marketMaker, int operation, int side, double price, int size) {
    IDeepMktDataHandler handler = m_deepMktDataMap.get( reqId);
    if (handler != null) {
      handler.updateMktDepth( position, marketMaker, DeepType.get( operation), DeepSide.get( side), price, size);
    }
    recEOM();
  }

  // ---------------------------------------- Option computations ----------------------------------------
  public void reqOptionVolatility(NewContract c, double optPrice, double underPrice, IOptHandler handler) {
    int reqId = m_reqId++;
    m_optionCompMap.put( reqId, handler);
    m_client.calculateImpliedVolatility( reqId, c.getContract(), optPrice, underPrice);
    sendEOM();
  }

  public void reqOptionComputation( NewContract c, double vol, double underPrice, IOptHandler handler) {
    int reqId = m_reqId++;
    m_optionCompMap.put( reqId, handler);
    m_client.calculateOptionPrice(reqId, c.getContract(), vol, underPrice);
    sendEOM();
  }

  void cancelOptionComp( IOptHandler handler) {
    Integer reqId = getAndRemoveKey( m_optionCompMap, handler);
    if (reqId != null) {
      m_client.cancelCalculateOptionPrice( reqId);
      sendEOM();
    }
  }

  @Override public void tickOptionComputation(int reqId, int tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) {
    IOptHandler handler = m_optionCompMap.get( reqId);
    if (handler != null) {
      handler.tickOptionComputation( NewTickType.get( tickType), impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice);
    }
    else {
      System.out.println( String.format( "not handled %s %s %s %s %s %s %s %s %s", tickType, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice) );
    }
    recEOM();
  }


  // ---------------------------------------- Trade reports ----------------------------------------
  public interface ITradeReportHandler {
    void tradeReport(String tradeKey, NewContract contract, Execution execution);
    void tradeReportEnd();
    void commissionReport(String tradeKey, CommissionReport commissionReport);
  }

    public void reqExecutions( ExecutionFilter filter, ITradeReportHandler handler) {
      m_tradeReportHandler = handler;
      m_client.reqExecutions( m_reqId++, filter);
    sendEOM();
    }

  @Override public void execDetails(int reqId, Contract contract, Execution execution) {
    if (m_tradeReportHandler != null) {
      int i = execution.m_execId.lastIndexOf( '.');
      String tradeKey = execution.m_execId.substring( 0, i);
      m_tradeReportHandler.tradeReport( tradeKey, new NewContract( contract), execution);
    }
    recEOM();
  }

  @Override public void execDetailsEnd(int reqId) {
    if (m_tradeReportHandler != null) {
      m_tradeReportHandler.tradeReportEnd();
    }
    recEOM();
  }

  @Override public void commissionReport(CommissionReport commissionReport) {
    if (m_tradeReportHandler != null) {
      int i = commissionReport.m_execId.lastIndexOf( '.');
      String tradeKey = commissionReport.m_execId.substring( 0, i);
      m_tradeReportHandler.commissionReport( tradeKey, commissionReport);
    }
    recEOM();
  }

  // ---------------------------------------- Advisor info ----------------------------------------
  public interface IAdvisorHandler {
    void groups(ArrayList<Group> groups);
    void profiles(ArrayList<Profile> profiles);
    void aliases(ArrayList<Alias> aliases);
  }

  public void reqAdvisorData( FADataType type, IAdvisorHandler handler) {
    m_advisorHandler = handler;
    m_client.requestFA( type.ordinal() );
    sendEOM();
  }

  public void updateGroups( ArrayList<Group> groups) {
    m_client.replaceFA( FADataType.GROUPS.ordinal(), AdvisorUtil.getGroupsXml( groups) );
    sendEOM();
  }

  public void updateProfiles(ArrayList<Profile> profiles) {
    m_client.replaceFA( FADataType.PROFILES.ordinal(), AdvisorUtil.getProfilesXml( profiles) );
    sendEOM();
  }

  @Override public final void receiveFA(int faDataType, String xml) {
    if (m_advisorHandler == null) {
      return;
    }

    FADataType type = FADataType.get( faDataType);

    switch( type) {
      case GROUPS:
        ArrayList<Group> groups = AdvisorUtil.getGroups( xml);
        m_advisorHandler.groups(groups);
        break;

      case PROFILES:
        ArrayList<Profile> profiles = AdvisorUtil.getProfiles( xml);
        m_advisorHandler.profiles(profiles);
        break;

      case ALIASES:
        ArrayList<Alias> aliases = AdvisorUtil.getAliases( xml);
        m_advisorHandler.aliases(aliases);
        break;
    }
    recEOM();
  }

  // ---------------------------------------- Trading and Option Exercise ----------------------------------------
  public interface IOrderHandler {
    void orderState(NewOrderState orderState);
    void handle(int errorCode, String errorMsg);
  }

  public void placeOrModifyOrder(NewContract contract, final NewOrder order, final IOrderHandler handler) {
    // when placing new order, assign new order id
    if (order.orderId() == 0) {
      order.orderId( m_orderId++);
      if (handler != null) {
        m_orderHandlers.put( order.orderId(), handler);
      }
    }

    m_client.placeOrder( contract, order);
    sendEOM();
  }

  public void cancelOrder(int orderId) {
    m_client.cancelOrder( orderId);
    sendEOM();
  }

  public void cancelAllOrders() {
    m_client.reqGlobalCancel();
    sendEOM();
  }

  public void exerciseOption( String account, NewContract contract, ExerciseType type, int quantity, boolean override) {
    m_client.exerciseOptions( m_reqId++, contract.getContract(), type.ordinal(), quantity, account, override ? 1 : 0);
    sendEOM();
  }

  public void removeOrderHandler( IOrderHandler handler) {
    getAndRemoveKey(m_orderHandlers, handler);
  }


  // ---------------------------------------- Live order handling ----------------------------------------
  public interface ILiveOrderHandler {
    void openOrder(NewContract contract, NewOrder order, NewOrderState orderState);
    void openOrderEnd();
    void orderStatus(int orderId, OrderStatus status, int filled, int remaining, double avgFillPrice, long permId, int parentId, double lastFillPrice, int clientId, String whyHeld);
    void handle(int orderId, int errorCode, String errorMsg)// add permId?
  }

  public void reqLiveOrders( ILiveOrderHandler handler) {
    m_liveOrderHandlers.add( handler);
    m_client.reqAllOpenOrders();
    sendEOM();
  }

  public void takeTwsOrders( ILiveOrderHandler handler) {
    m_liveOrderHandlers.add( handler);
    m_client.reqOpenOrders();
    sendEOM();
  }

  public void takeFutureTwsOrders( ILiveOrderHandler handler) {
    m_liveOrderHandlers.add( handler);
    m_client.reqAutoOpenOrders( true);
    sendEOM();
  }

  public void removeLiveOrderHandler(ILiveOrderHandler handler) {
    m_liveOrderHandlers.remove( handler);
  }

  @Override public void openOrder(int orderId, Contract contract, Order orderIn, OrderState orderState) {
    NewOrder order = new NewOrder( orderIn);

    IOrderHandler handler = m_orderHandlers.get( orderId);
    if (handler != null) {
      handler.orderState( new NewOrderState( orderState) );
    }

    if (!order.whatIf() ) {
      for (ILiveOrderHandler liveHandler : m_liveOrderHandlers) {
        liveHandler.openOrder( new NewContract( contract), order, new NewOrderState( orderState) );
      }
    }
    recEOM();
  }

  @Override public void openOrderEnd() {
    for (ILiveOrderHandler handler : m_liveOrderHandlers) {
      handler.openOrderEnd();
    }
    recEOM();
  }

  @Override public void orderStatus(int orderId, String status, int filled, int remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld) {
    for (ILiveOrderHandler handler : m_liveOrderHandlers) {
      handler.orderStatus(orderId, OrderStatus.valueOf( status), filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld);
    }
    recEOM();
  }


  // ---------------------------------------- Market Scanners ----------------------------------------
  public interface IScannerHandler {
    void scannerParameters(String xml);
    void scannerData( int rank, NewContractDetails contractDetails, String legsStr);
    void scannerDataEnd();
  }

  public void reqScannerParameters( IScannerHandler handler) {
    m_scannerHandler = handler;
    m_client.reqScannerParameters();
    sendEOM();
  }

  public void reqScannerSubscription( ScannerSubscription sub, IScannerHandler handler) {
    int reqId = m_reqId++;
    m_scannerMap.put( reqId, handler);
    m_client.reqScannerSubscription( reqId, sub);
    sendEOM();
  }

  public void cancelScannerSubscription( IScannerHandler handler) {
    Integer reqId = getAndRemoveKey( m_scannerMap, handler);
    if (reqId != null) {
      m_client.cancelScannerSubscription( reqId);
      sendEOM();
    }
  }

  @Override public void scannerParameters(String xml) {
    m_scannerHandler.scannerParameters( xml);
    recEOM();
  }

  @Override public void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr) {
    IScannerHandler handler = m_scannerMap.get( reqId);
    if (handler != null) {
      handler.scannerData( rank, new NewContractDetails( contractDetails), legsStr);
    }
    recEOM();
  }

  @Override public void scannerDataEnd(int reqId) {
    IScannerHandler handler = m_scannerMap.get( reqId);
    if (handler != null) {
      handler.scannerDataEnd();
    }
    recEOM();
  }


  // ----------------------------------------- Historical data handling ----------------------------------------
  public interface IHistoricalDataHandler {
    void historicalData(Bar bar, boolean hasGaps);
    void historicalDataEnd();
  }

  /** @param endDateTime format is YYYYMMDD HH:MM:SS [TMZ]
   *  @param duration is number of durationUnits */
    public void reqHistoricalData( NewContract contract, String endDateTime, int duration, DurationUnit durationUnit, BarSize barSize, WhatToShow whatToShow, boolean rthOnly, IHistoricalDataHandler handler) {
      int reqId = m_reqId++;
      m_historicalDataMap.put( reqId, handler);
      String durationStr = duration + " " + durationUnit.toString().charAt( 0);
      m_client.reqHistoricalData(reqId, contract.getContract(), endDateTime, durationStr, barSize.toString(), whatToShow.toString(), rthOnly ? 1 : 0, 2);
    sendEOM();
    }

    public void cancelHistoricalData( IHistoricalDataHandler handler) {
      Integer reqId = getAndRemoveKey( m_historicalDataMap, handler);
      if (reqId != null) {
        m_client.cancelHistoricalData( reqId);
        sendEOM();
      }
    }

  @Override public void historicalData(int reqId, String date, double open, double high, double low, double close, int volume, int count, double wap, boolean hasGaps) {
    IHistoricalDataHandler handler = m_historicalDataMap.get( reqId);
    if (handler != null) {
      if (date.startsWith( "finished")) {
        handler.historicalDataEnd();
      }
      else {
        long longDate;
        if (date.length() == 8) {
          int year = Integer.parseInt( date.substring( 0, 4) );
          int month = Integer.parseInt( date.substring( 4, 6) );
          int day = Integer.parseInt( date.substring( 6) );
          longDate = new Date( year - 1900, month - 1, day).getTime() / 1000;
        }
        else {
          longDate = Long.parseLong( date);
        }
        Bar bar = new Bar( longDate, high, low, open, close, wap, volume, count);
        handler.historicalData(bar, hasGaps);
      }
    }
    recEOM();
  }


  //----------------------------------------- Real-time bars --------------------------------------
  public interface IRealTimeBarHandler {
    void realtimeBar(Bar bar); // time is in seconds since epoch
  }

    public void reqRealTimeBars(NewContract contract, WhatToShow whatToShow, boolean rthOnly, IRealTimeBarHandler handler) {
      int reqId = m_reqId++;
      m_realTimeBarMap.put( reqId, handler);
      m_client.reqRealTimeBars(reqId, contract.getContract(), 0, whatToShow.toString(), rthOnly);
    sendEOM();
    }

    public void cancelRealtimeBars( IRealTimeBarHandler handler) {
      Integer reqId = getAndRemoveKey( m_realTimeBarMap, handler);
      if (reqId != null) {
        m_client.cancelRealTimeBars( reqId);
        sendEOM();
      }
    }

    @Override public void realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count) {
      IRealTimeBarHandler handler = m_realTimeBarMap.get( reqId);
    if (handler != null) {
      Bar bar = new Bar( time, high, low, open, close, wap, volume, count);
      handler.realtimeBar( bar);
    }
    recEOM();
  }


    // ----------------------------------------- Fundamentals handling ----------------------------------------
  public interface IFundamentalsHandler {
    void fundamentals( String str);
  }

    public void reqFundamentals( NewContract contract, FundamentalType reportType, IFundamentalsHandler handler) {
      int reqId = m_reqId++;
      m_fundMap.put( reqId, handler);
      m_client.reqFundamentalData( reqId, contract.getContract(), reportType.getApiString() );
    sendEOM();
    }

    @Override public void fundamentalData(int reqId, String data) {
    IFundamentalsHandler handler = m_fundMap.get( reqId);
    if (handler != null) {
      handler.fundamentals( data);
    }
    recEOM();
  }


  // ---------------------------------------- Time handling ----------------------------------------
  public interface ITimeHandler {
    void currentTime(long time);
  }

  public void reqCurrentTime( ITimeHandler handler) {
    m_timeHandler = handler;
    m_client.reqCurrentTime();
    sendEOM();
  }

  @Override public void currentTime(long time) {
    m_timeHandler.currentTime(time);
    recEOM();
  }


  // ---------------------------------------- Bulletins handling ----------------------------------------
  public interface IBulletinHandler {
    void bulletin(int msgId, NewsType newsType, String message, String exchange);
  }

  public void reqBulletins( boolean allMessages, IBulletinHandler handler) {
    m_bulletinHandler = handler;
    m_client.reqNewsBulletins( allMessages);
    sendEOM();
  }

  public void cancelBulletins() {
    m_client.cancelNewsBulletins();
  }

  @Override public void updateNewsBulletin(int msgId, int msgType, String message, String origExchange) {
    m_bulletinHandler.bulletin( msgId, NewsType.get( msgType), message, origExchange);
    recEOM();
  }


  // ---------------------------------------- other methods ----------------------------------------
  /** Not supported in ApiController. */
  @Override public void deltaNeutralValidation(int reqId, UnderComp underComp) {
    show( "RECEIVED DN VALIDATION");
    recEOM();
  }

  private void sendEOM() {
    m_outLogger.log( "\n");
  }

  private void recEOM() {
    m_inLogger.log( "\n");
  }

  public void show(String string) {
    m_connectionHandler.show( string);
  }

    private static <K,V> K getAndRemoveKey( HashMap<K,V> map, V value) {
      for (Entry<K,V> entry : map.entrySet() ) {
        if (entry.getValue() == value) {
          map.remove( entry.getKey() );
          return entry.getKey();
        }
      }
    return null;
    }

  /** Obsolete, never called. */
  @Override public void error(String str) {
    throw new RuntimeException();
  }
}
TOP

Related Classes of com.ib.controller.ApiController

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.