diff --git a/ib/.classpath b/ib/.classpath new file mode 100644 index 00000000..df370c06 --- /dev/null +++ b/ib/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ib/.project b/ib/.project new file mode 100644 index 00000000..440434d1 --- /dev/null +++ b/ib/.project @@ -0,0 +1,23 @@ + + + ib + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + diff --git a/ib/.settings/org.eclipse.jdt.core.prefs b/ib/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..86260262 --- /dev/null +++ b/ib/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/ib/.settings/org.maven.ide.eclipse.prefs b/ib/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 00000000..3c757a28 --- /dev/null +++ b/ib/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,7 @@ +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/ib/pom.xml b/ib/pom.xml new file mode 100644 index 00000000..33d0be56 --- /dev/null +++ b/ib/pom.xml @@ -0,0 +1,25 @@ + + 4.0.0 + + com.uims.bst + ib + 0.0.1-SNAPSHOT + jar + + ib + http://maven.apache.org + + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + diff --git a/ib/src/main/java/TestJavaClient/AccountDlg.java b/ib/src/main/java/TestJavaClient/AccountDlg.java new file mode 100644 index 00000000..290b57b1 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/AccountDlg.java @@ -0,0 +1,372 @@ +/* + * AccountDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Vector; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.AbstractTableModel; + +import com.ib.client.Contract; +import com.ib.client.Util; + +public class AccountDlg extends JDialog { + private JTextField m_updateTime = new JTextField(); + private JLabel m_timeLabel = new JLabel("Update time:"); + private JButton m_close = new JButton( "Close"); + private PortfolioTable m_portfolioModel = new PortfolioTable(); + private AcctValueModel m_acctValueModel = new AcctValueModel(); + private boolean m_rc; + + private String m_accountName; + private boolean m_complete; + + boolean rc() { return m_rc; } + + public AccountDlg(JFrame parent) { + super(parent, true); + + JScrollPane acctPane = new JScrollPane(new JTable(m_acctValueModel)); + JScrollPane portPane = new JScrollPane(new JTable(m_portfolioModel)); + + acctPane.setBorder(BorderFactory.createTitledBorder( "Key, Value, Currency, and Account") ); + portPane.setBorder(BorderFactory.createTitledBorder( "Portfolio Entries") ); + + JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, acctPane, portPane); + splitPane.setOneTouchExpandable(true); + splitPane.setDividerLocation(240); + + splitPane.setPreferredSize(new Dimension(600, 350)); + + JPanel timePanel = new JPanel(); + timePanel.add(m_timeLabel); + timePanel.add(m_updateTime); + timePanel.add(m_close); + + m_updateTime.setEditable(false); + m_updateTime.setHorizontalAlignment(JTextField.CENTER); + m_updateTime.setPreferredSize(new Dimension(80, 26)); + m_close.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onClose(); + } + }); + + getContentPane().add( splitPane, BorderLayout.CENTER); + getContentPane().add( timePanel, BorderLayout.SOUTH); + setLocation(20, 20); + pack(); + reset(); + } + + void updateAccountValue(String key, String value, String currency, String accountName) { + m_acctValueModel.updateAccountValue(key, value, currency, accountName); + } + + void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, + double averageCost, double unrealizedPNL, double realizedPNL, String accountName) { + m_portfolioModel.updatePortfolio(contract, position, marketPrice, marketValue, + averageCost, unrealizedPNL, realizedPNL, accountName); + } + + void reset() { + m_acctValueModel.reset(); + m_portfolioModel.reset(); + m_updateTime.setText(""); + } + + void onClose() { + setVisible( false); + } + + void updateAccountTime(String timeStamp) { + m_updateTime.setText(timeStamp); + } + + void accountDownloadBegin(String accountName) { + m_accountName = accountName; + m_complete = false; + + updateTitle(); + } + + + + void accountDownloadEnd(String accountName) { + + if ( !Util.StringIsEmpty( m_accountName) && + !m_accountName.equals( accountName)) { + return; + } + + m_complete = true; + updateTitle(); + } + + private void updateTitle() { + + String title = new String(); + + if (!Util.StringIsEmpty( m_accountName)) { + title += m_accountName; + } + if (m_complete) { + if (title.length() != 0) { + title += ' '; + } + title += "[complete]"; + } + + setTitle(title); + } +} + + +class PortfolioTable extends AbstractTableModel { + Vector m_allData = new Vector(); + + void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, + double averageCost, double unrealizedPNL, double realizedPNL, String accountName) { + PortfolioTableRow newData = + new PortfolioTableRow(contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName); + int size = m_allData.size(); + for ( int i = 0; i < size; i++ ) { + PortfolioTableRow test = (PortfolioTableRow)m_allData.get(i); + if ( test.m_contract.equals(newData.m_contract) ) { + if ( newData.m_position == 0 ) + m_allData.remove(i); + else + m_allData.set(i, newData); + + fireTableDataChanged(); + return; + } + } + + m_allData.add(newData); + fireTableDataChanged(); + } + + void reset() { + m_allData.clear(); + } + + public int getRowCount() { + return m_allData.size(); + } + + public int getColumnCount() { + return 13; + } + + public Object getValueAt(int r, int c) { + return ((PortfolioTableRow) m_allData.get(r)).getValue(c); + } + + public boolean isCellEditable(int r, int c) { + return false; + } + + public String getColumnName(int c) { + switch(c) { + case 0: + return "Symbol"; + case 1: + return "SecType"; + case 2: + return "Expiry"; + case 3: + return "Strike"; + case 4: + return "Right"; + case 5: + return "Multiplier"; + case 6: + return "Exchange"; + case 7: + return "Currency"; + case 8: + return "Position"; + case 9: + return "Market Price"; + case 10: + return "Market Value"; + case 11: + return "Average Cost"; + case 12: + return "Unrealized P&L"; + case 13: + return "Realized P&L"; + case 14: + return "Account Name"; + default: + return null; + } + } + + class PortfolioTableRow { + Contract m_contract; + int m_position; + double m_marketPrice; + double m_marketValue; + double m_averageCost; + double m_unrealizedPNL; + double m_realizedPNL; + String m_accountName; + + PortfolioTableRow( Contract contract, int position, double marketPrice, + double marketValue, double averageCost, double unrealizedPNL, + double realizedPNL, String accountName) { + m_contract = contract; + m_position = position; + m_marketPrice = marketPrice; + m_marketValue = marketValue; + m_averageCost = averageCost; + m_unrealizedPNL = unrealizedPNL; + m_realizedPNL = realizedPNL; + m_accountName = accountName; + } + + Object getValue(int c) { + switch(c) { + case 0: + return m_contract.m_symbol; + case 1: + return m_contract.m_secType; + case 2: + return m_contract.m_expiry; + case 3: + return m_contract.m_expiry == null ? null : "" + m_contract.m_strike; + case 4: + return (m_contract.m_right != null && m_contract.m_right.equals("???")) ? null : m_contract.m_right; + case 5: + return m_contract.m_multiplier; + case 6: + return (m_contract.m_primaryExch != null ? m_contract.m_primaryExch : ""); + case 7: + return m_contract.m_currency; + case 8: + return "" + m_position; + case 9: + return "" + m_marketPrice; + case 10: + return "" + m_marketValue; + case 11: + return "" + m_averageCost; + case 12: + return "" + m_unrealizedPNL; + case 13: + return "" + m_realizedPNL; + case 14: + return m_accountName; + default: + return null; + } + } + } +} + +class AcctValueModel extends AbstractTableModel { + Vector m_allData = new Vector(); + + void updateAccountValue(String key, String val, String currency, String accountName) { + AccountTableRow newData = new AccountTableRow(key, val, currency, accountName); + int size = m_allData.size(); + for ( int i = 0; i < size; i++ ) { + AccountTableRow test = (AccountTableRow)m_allData.get(i); + if (test.m_key != null && + test.m_key.equals(newData.m_key) && + test.m_currency != null && + test.m_currency.equals(newData.m_currency)) { + test.m_value = newData.m_value; + fireTableDataChanged(); + return; + } + } + + m_allData.add(newData); + fireTableDataChanged(); + } + + void reset() { + m_allData.clear(); + } + + public int getRowCount() { + return m_allData.size(); + } + + public int getColumnCount() { + return 4; + } + + public Object getValueAt(int r, int c) { + return ((AccountTableRow)m_allData.get(r)).getValue(c); + } + + + public boolean isCellEditable(int r, int c) { + return false; + } + + public String getColumnName(int c) { + switch (c) { + case 0: + return "Key"; + case 1: + return "Value"; + case 2: + return "Currency"; + case 3: + return "Account Name"; + + default: + return null; + } + } + + class AccountTableRow { + String m_key; + String m_value; + String m_currency; + String m_accountName; + + AccountTableRow(String key, String val, String cur, String accountName) { + m_key = key; + m_value = val; + m_currency = cur; + m_accountName = accountName ; + } + + Object getValue(int c) { + switch (c) { + case 0: + return m_key; + case 1: + return m_value; + case 2: + return m_currency; + case 3: + return m_accountName ; + + default: + return null; + } + } + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/AcctUpdatesDlg.java b/ib/src/main/java/TestJavaClient/AcctUpdatesDlg.java new file mode 100644 index 00000000..a63be920 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/AcctUpdatesDlg.java @@ -0,0 +1,117 @@ + +/* + * AcctUpdatesDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +public class AcctUpdatesDlg extends JDialog { + JTextField m_txtAcctCode = new JTextField(10); + JButton m_btnSubscribe = new JButton("Subscribe"); + JButton m_btnUnSubscribe = new JButton("UnSubscribe"); + JButton m_btnClose = new JButton( "Close"); + SampleFrame m_parent; + String m_acctCode; + boolean m_subscribe = false; + boolean m_rc; + + public AcctUpdatesDlg( SampleFrame owner) { + super( owner, true); + + m_parent = owner; + + setTitle("Account Updates (FA Customers only)"); + setSize(200,300); + + m_txtAcctCode.setMaximumSize( m_txtAcctCode.getPreferredSize()); + + + Box row1 = Box.createHorizontalBox(); + row1.add( new JLabel( " Enter the account code for the FA managed \n account you wish to receive updates for :")); + + Box row2 = Box.createHorizontalBox(); + row2.add( new JLabel( "Account Code :")); + row2.add( Box.createHorizontalStrut(10)); + row2.add( m_txtAcctCode); + + Box row3 = Box.createHorizontalBox(); + row3.add( m_btnSubscribe); + row3.add( Box.createHorizontalStrut(10)); + row3.add( m_btnUnSubscribe); + + + Box vbox = Box.createVerticalBox(); + vbox.add( Box.createVerticalStrut(10)); + vbox.add( row1); + vbox.add( Box.createVerticalStrut(10)); + vbox.add( row2); + vbox.add( Box.createVerticalStrut(10)); + vbox.add( row3); + vbox.add( Box.createVerticalStrut(10)); + + // create accoun chooser panel + JPanel acctChooserPanel = new JPanel(); + acctChooserPanel.setBorder( BorderFactory.createTitledBorder( "")); + acctChooserPanel.add(vbox); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_btnClose); + + // create action listeners + m_btnSubscribe.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onSubscribe(); + } + }); + m_btnUnSubscribe.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onUnSubscribe(); + } + }); + m_btnClose.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onClose(); + } + }); + + // create dlg box + getContentPane().add( acctChooserPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + pack(); + } + + void onSubscribe() { + m_subscribe = true; + m_acctCode = m_txtAcctCode.getText(); + + m_rc = true; + setVisible( false); + } + + void onUnSubscribe() { + m_subscribe = false; + m_acctCode = m_txtAcctCode.getText(); + + m_rc = true; + setVisible( false); + } + + void onClose() { + m_acctCode = ""; + m_rc = false; + setVisible( false); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/AlgoParamsDlg.java b/ib/src/main/java/TestJavaClient/AlgoParamsDlg.java new file mode 100644 index 00000000..c146ff80 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/AlgoParamsDlg.java @@ -0,0 +1,248 @@ +/* + * + * AlgoDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Vector; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.AbstractTableModel; + +import com.ib.client.Order; +import com.ib.client.TagValue; + +public class AlgoParamsDlg extends JDialog { + + private Order m_order; + + private JTextField m_algoStrategy = new JTextField( ""); + + private Vector m_algoParams; + + private JTextField m_tag = new JTextField( ""); + private JTextField m_value = new JTextField( ""); + + private JButton m_addParam = new JButton( "Add"); + private JButton m_removeParam = new JButton( "Remove"); + + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + + private AlgoParamModel m_paramModel = new AlgoParamModel(); + private JTable m_paramTable = new JTable(m_paramModel); + private JScrollPane m_paramPane = new JScrollPane(m_paramTable); + + public AlgoParamModel paramModel() { return m_paramModel; } + + public AlgoParamsDlg( Order order, JDialog owner) { + super( owner, true); + + m_order = order; + + setTitle( "Algo Order Parameters"); + + JPanel pAlgoPanel = new JPanel( new GridLayout( 0, 2, 10, 10) ); + pAlgoPanel.setBorder( BorderFactory.createTitledBorder( "Algorithm") ); + pAlgoPanel.add( new JLabel( "Strategy:") ); + m_algoStrategy.setText(m_order.m_algoStrategy); + pAlgoPanel.add(m_algoStrategy); + + // create algo params panel + JPanel pParamList = new JPanel( new GridLayout( 0, 1, 10, 10) ); + pParamList.setBorder( BorderFactory.createTitledBorder( "Parameters") ); + + Vector algoParams = m_order.m_algoParams; + if (algoParams != null) { + m_paramModel.algoParams().addAll(algoParams); + } + pParamList.add( m_paramPane); + + // create combo details panel + JPanel pParamListControl = new JPanel( new GridLayout( 0, 2, 10, 10) ); + pParamListControl.setBorder( BorderFactory.createTitledBorder( "Add / Remove") ); + pParamListControl.add( new JLabel( "Param:") ); + pParamListControl.add( m_tag); + pParamListControl.add( new JLabel( "Value:") ); + pParamListControl.add( m_value); + pParamListControl.add( m_addParam); + pParamListControl.add( m_removeParam); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create wrapper panel + JPanel topPanel = new JPanel(); + topPanel.setLayout( new BoxLayout( topPanel, BoxLayout.Y_AXIS) ); + topPanel.add( pAlgoPanel); + topPanel.add( pParamList); + topPanel.add( pParamListControl); + + // create dlg box + getContentPane().add( topPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + + // create action listeners + m_addParam.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onAddParam(); + } + }); + m_removeParam.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onRemoveParam(); + } + }); + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + setSize(250, 600); + centerOnOwner( this); + } + + public void onAddParam() { + try { + String tag = m_tag.getText(); + String value = m_value.getText(); + + m_paramModel.addParam( new TagValue(tag, value)); + } + catch( Exception e) { + reportError( "Error - ", e); + return; + } + } + + public void onRemoveParam() { + try { + if ( m_paramTable.getSelectedRowCount() != 0 ) { + int[] rows = m_paramTable.getSelectedRows(); + for ( int i=rows.length -1; i>=0 ; i-- ) { + m_paramModel.removeParam( rows[i]); + } + } + } + catch( Exception e) { + reportError( "Error - ", e); + return; + } + } + + void onOk() { + + m_order.m_algoStrategy = m_algoStrategy.getText(); + + Vector algoParams = m_paramModel.algoParams(); + m_order.m_algoParams = algoParams.isEmpty() ? null : algoParams; + + setVisible( false); + } + + void onCancel() { + setVisible( false); + } + + + void reportError( String msg, Exception e) { + Main.inform( this, msg + " --" + e); + } + + private void centerOnOwner( Window window) { + Window owner = window.getOwner(); + if( owner == null) { + return; + } + int x = owner.getX() + ((owner.getWidth() - window.getWidth()) / 2); + int y = owner.getY() + ((owner.getHeight() - window.getHeight()) / 2); + if( x < 0) x = 0; + if( y < 0) y = 0; + window.setLocation( x, y); + } +} + +class AlgoParamModel extends AbstractTableModel { + + private Vector m_allData = new Vector(); + + synchronized public void addParam( TagValue tagValue) + { + m_allData.add( tagValue); + fireTableDataChanged(); + } + + synchronized public void removeParam( int index) + { + m_allData.remove( index); + fireTableDataChanged(); + } + + synchronized public void reset() { + m_allData.removeAllElements(); + fireTableDataChanged(); + } + + synchronized public int getRowCount() { + return m_allData.size(); + } + + synchronized public int getColumnCount() { + return 2; + } + + synchronized public Object getValueAt(int r, int c) { + TagValue tagValue = (TagValue)m_allData.get(r); + + switch (c) { + case 0: + return tagValue.m_tag; + case 1: + return tagValue.m_value; + default: + return ""; + } + + } + + public boolean isCellEditable(int r, int c) { + return false; + } + + public String getColumnName(int c) { + switch (c) { + case 0: + return "Param"; + case 1: + return "Value"; + default: + return null; + } + } + + public Vector algoParams() { + return m_allData; + } +} diff --git a/ib/src/main/java/TestJavaClient/ComboLegDlg.java b/ib/src/main/java/TestJavaClient/ComboLegDlg.java new file mode 100644 index 00000000..4fe2f117 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/ComboLegDlg.java @@ -0,0 +1,292 @@ +/* + * + * ComboLegDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Vector; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.AbstractTableModel; + +import com.ib.client.ComboLeg; +import com.ib.client.Contract; + +public class ComboLegDlg extends JDialog { + + //private static String BUY = "BUY"; + //private static String SELL = "SELL"; + //private static String SSHORT = "SSHORT"; + + private Vector m_comboLegs; + + private JTextField m_conId = new JTextField( "0"); + private JTextField m_ratio = new JTextField( "0"); + private JTextField m_action = new JTextField( "BUY"); + private JTextField m_exchange = new JTextField( ""); + private JTextField m_openClose = new JTextField( "0"); + private JTextField m_shortSaleSlot = new JTextField( "0"); + private JTextField m_designatedLocation = new JTextField( ""); + private JTextField m_exemptCode = new JTextField( "-1"); + + private JButton m_addLeg = new JButton( "Add"); + private JButton m_removeLeg = new JButton( "Remove"); + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + + private ComboLegModel m_comboLegsModel = new ComboLegModel(); + private JTable m_comboTable = new JTable(m_comboLegsModel); + private JScrollPane m_comboLegsPane = new JScrollPane(m_comboTable); + + public ComboLegModel comboLegModel() { return m_comboLegsModel; } + + public ComboLegDlg( Vector comboLegs, String orderExchange, JDialog owner) { + super( owner, true); + + m_comboLegs = comboLegs; + + setTitle( "Combination Legs"); + + // create combos list panel + JPanel pLegList = new JPanel( new GridLayout( 0, 1, 10, 10) ); + pLegList.setBorder( BorderFactory.createTitledBorder( "Combination Order legs:") ); + m_comboLegsModel.comboLegModel().addAll(comboLegs); + pLegList.add( m_comboLegsPane); + + if (orderExchange != null && orderExchange.length() > 0) { + m_exchange.setText(orderExchange); + } + + // create combo details panel + JPanel pComboDetails = new JPanel( new GridLayout( 0, 2, 10, 10) ); + pComboDetails.setBorder( BorderFactory.createTitledBorder( "Combo Leg Details:") ); + pComboDetails.add( new JLabel( "ConId:") ); + pComboDetails.add( m_conId); + pComboDetails.add( new JLabel( "Ratio:") ); + pComboDetails.add( m_ratio); + pComboDetails.add( new JLabel( "Side:") ); + pComboDetails.add( m_action); + pComboDetails.add( new JLabel( "Exchange:") ); + pComboDetails.add( m_exchange); + pComboDetails.add( new JLabel( "Open/Close:") ); + pComboDetails.add( m_openClose); + pComboDetails.add( new JLabel( "Short Sale Slot:") ); + pComboDetails.add( m_shortSaleSlot); + pComboDetails.add( new JLabel( "Designated Location:") ); + pComboDetails.add( m_designatedLocation); + pComboDetails.add( new JLabel( "Exempt Code:") ); + pComboDetails.add( m_exemptCode); + pComboDetails.add( m_addLeg); + pComboDetails.add( m_removeLeg); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create wrapper panel + JPanel topPanel = new JPanel(); + topPanel.setLayout( new BoxLayout( topPanel, BoxLayout.Y_AXIS) ); + topPanel.add( pLegList); + topPanel.add( pComboDetails); + + // create dlg box + getContentPane().add( topPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + + // create action listeners + m_addLeg.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onAddLeg(); + } + }); + m_removeLeg.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onRemoveLeg(); + } + }); + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + setSize(250, 600); + centerOnOwner( this); + } + + public void onAddLeg() { + try { + int conId = Integer.parseInt( m_conId.getText()); + int ratio = Integer.parseInt( m_ratio.getText()); + int openClose = Integer.parseInt( m_openClose.getText()); + int shortSaleSlot = Integer.parseInt(m_shortSaleSlot.getText()); + int exemptCode = Integer.parseInt(m_exemptCode.getText().length() != 0 ? m_exemptCode.getText() : "-1"); + m_comboLegsModel.addComboLeg( new ComboLeg(conId, ratio, + m_action.getText(), m_exchange.getText(), openClose, + shortSaleSlot, m_designatedLocation.getText(), exemptCode) ); + } + catch( Exception e) { + reportError( "Error - ", e); + return; + } + } + + public void onRemoveLeg() { + try { + if ( m_comboTable.getSelectedRowCount() != 0 ) { + int[] rows = m_comboTable.getSelectedRows(); + for ( int i=rows.length -1; i>=0 ; i-- ) { + m_comboLegsModel.removeComboLeg( rows[i]); + } + } + } + catch( Exception e) { + reportError( "Error - ", e); + return; + } + } + + void onOk() { + m_comboLegs.clear(); + m_comboLegs.addAll( m_comboLegsModel.comboLegModel()); + setVisible( false); + } + + void onCancel() { + setVisible( false); + } + + + void reportError( String msg, Exception e) { + Main.inform( this, msg + " --" + e); + } + + private void centerOnOwner( Window window) { + Window owner = window.getOwner(); + if( owner == null) { + return; + } + int x = owner.getX() + ((owner.getWidth() - window.getWidth()) / 2); + int y = owner.getY() + ((owner.getHeight() - window.getHeight()) / 2); + if( x < 0) x = 0; + if( y < 0) y = 0; + window.setLocation( x, y); + } +} + +class ComboLegModel extends AbstractTableModel { + private Vector m_allData = new Vector(); + + synchronized public void addComboLeg( ComboLeg leg) + { + m_allData.add( leg); + fireTableDataChanged(); + } + + synchronized public void removeComboLeg( int index) + { + m_allData.remove(index); + fireTableDataChanged(); + } + + synchronized public void removeComboLeg( ComboLeg leg) + { + for ( int i=0; i < m_allData.size(); i++ ) { + if ( leg.equals( (ComboLeg)m_allData.get(i)) ) { + m_allData.remove(i); + break; + } + } + fireTableDataChanged(); + } + + synchronized public void reset() { + m_allData.removeAllElements(); + fireTableDataChanged(); + } + + synchronized public int getRowCount() { + return m_allData.size(); + } + + synchronized public int getColumnCount() { + return 8; + } + + synchronized public Object getValueAt(int r, int c) { + ComboLeg leg = (ComboLeg)m_allData.get(r); + + switch (c) { + case 0: + return Integer.toString(leg.m_conId); + case 1: + return Integer.toString(leg.m_ratio); + case 2: + return leg.m_action; + case 3: + return leg.m_exchange; + case 4: + return Integer.toString(leg.m_openClose); + case 5: + return Integer.toString(leg.m_shortSaleSlot); + case 6: + return leg.m_designatedLocation; + case 7: + return Integer.toString(leg.m_exemptCode); + default: + return ""; + } + + } + + public boolean isCellEditable(int r, int c) { + return false; + } + + public String getColumnName(int c) { + switch (c) { + case 0: + return "ConId"; + case 1: + return "Ratio"; + case 2: + return "Side"; + case 3: + return "Exchange"; + case 4: + return "Open/Close"; + case 5: + return "Short Sale Slot"; + case 6: + return "Designated Location"; + case 7: + return "Exempt Code"; + default: + return null; + } + } + + public Vector comboLegModel() { + return m_allData; + } +} diff --git a/ib/src/main/java/TestJavaClient/ConnectDlg.java b/ib/src/main/java/TestJavaClient/ConnectDlg.java new file mode 100644 index 00000000..c8040466 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/ConnectDlg.java @@ -0,0 +1,95 @@ +/* + * ConnectDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +public class ConnectDlg extends JDialog { + public static int LAST_CLIENT_ID = 0; + + JTextField m_ipAddress = new JTextField(); + JTextField m_port = new JTextField( "7496"); + JTextField m_clientId = new JTextField(); + JButton m_ok = new JButton( "OK"); + JButton m_cancel = new JButton( "Cancel"); + String m_retIpAddress; + int m_retPort; + int m_retClientId; + boolean m_rc; + + public ConnectDlg( Frame owner) { + super( owner, true); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create action listeners + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + // create mid panel + JPanel midPanel = new JPanel(); + midPanel.setLayout( new GridLayout( 0, 1, 5, 5) ); + midPanel.add( new JLabel( "IP Address (leave blank for local host)") ); + midPanel.add( m_ipAddress); + midPanel.add( new JLabel( "Port") ); + midPanel.add( m_port); + midPanel.add( new JLabel( "Client ID") ); + midPanel.add( m_clientId); + m_clientId.setText( Integer.toString(LAST_CLIENT_ID) ); + + // create dlg box + getContentPane().add( midPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + setTitle( "Connect"); + pack(); + } + + void onOk() { + m_rc = false; + + try { + // set id + m_retIpAddress = m_ipAddress.getText(); + m_retPort = Integer.parseInt( m_port.getText() ); + m_retClientId = Integer.parseInt( m_clientId.getText() ); + LAST_CLIENT_ID = m_retClientId; + } + catch( Exception e) { + Main.inform( this, "Error - " + e); + return; + } + + m_rc = true; + setVisible( false); + } + + void onCancel() { + LAST_CLIENT_ID = Integer.parseInt( m_clientId.getText() ); + + m_rc = false; + setVisible( false); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/ExecFilterDlg.java b/ib/src/main/java/TestJavaClient/ExecFilterDlg.java new file mode 100644 index 00000000..de4772ab --- /dev/null +++ b/ib/src/main/java/TestJavaClient/ExecFilterDlg.java @@ -0,0 +1,122 @@ + /** + * + * ExtFilterDlg.java + * + */ + +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import com.ib.client.ExecutionFilter; + +public class ExecFilterDlg extends JDialog { + + public int m_reqId; + public ExecutionFilter m_execFilter = new ExecutionFilter(); + public boolean m_rc; + + private JTextField m_reqIdTxt = new JTextField("0"); + private JTextField m_clientID = new JTextField("0"); + private JTextField m_acctCode = new JTextField(); + private JTextField m_time = new JTextField(); + private JTextField m_symbol = new JTextField(); + private JTextField m_secType = new JTextField(); + private JTextField m_exchange = new JTextField(); + private JTextField m_action = new JTextField(); + + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + + public ExecFilterDlg( JFrame owner) { + super( owner, true); + + setTitle( "Execution Report Filter"); + + // create extended order attributes panel + JPanel execRptFilterPanel = new JPanel( new GridLayout( 0, 2, 7, 7) ); + execRptFilterPanel.setBorder( BorderFactory.createTitledBorder( "Filter Criteria") ); + execRptFilterPanel.add( new JLabel( "Request ID:") ); + execRptFilterPanel.add( m_reqIdTxt); + execRptFilterPanel.add( new JLabel( "Client ID:") ); + execRptFilterPanel.add( m_clientID); + execRptFilterPanel.add( new JLabel( "Account Code:") ); + execRptFilterPanel.add( m_acctCode); + execRptFilterPanel.add( new JLabel( "Time :") ); + execRptFilterPanel.add( m_time); + execRptFilterPanel.add( new JLabel( "Symbol :") ); + execRptFilterPanel.add( m_symbol); + execRptFilterPanel.add( new JLabel( "SecType :") ); + execRptFilterPanel.add( m_secType); + execRptFilterPanel.add( new JLabel( "Exchange :") ); + execRptFilterPanel.add( m_exchange); + execRptFilterPanel.add( new JLabel( "Action :") ); + execRptFilterPanel.add( m_action); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create action listeners + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + // create dlg box + getContentPane().add( execRptFilterPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + pack(); + } + + void onOk() { + m_rc = false; + + try { + + m_reqId = Integer.parseInt( m_reqIdTxt.getText()); + + // set extended order fields + String clientId = m_clientID.getText().toString(); + m_execFilter.m_clientId = clientId != "" + ? Integer.parseInt( m_clientID.getText()) + : 0; + m_execFilter.m_acctCode = m_acctCode.getText(); + m_execFilter.m_time = m_time.getText(); + m_execFilter.m_symbol = m_symbol.getText(); + m_execFilter.m_secType = m_secType.getText(); + m_execFilter.m_exchange = m_exchange.getText(); + m_execFilter.m_side = m_action.getText(); + } + catch( Exception e) { + Main.inform( this, "Error - " + e); + return; + } + + m_rc = true; + setVisible( false); + } + + void onCancel() { + m_rc = false; + setVisible( false); + } +} diff --git a/ib/src/main/java/TestJavaClient/ExtOrdDlg.java b/ib/src/main/java/TestJavaClient/ExtOrdDlg.java new file mode 100644 index 00000000..9dcbf41a --- /dev/null +++ b/ib/src/main/java/TestJavaClient/ExtOrdDlg.java @@ -0,0 +1,355 @@ + /** + * + * ExtOrdDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; + +import com.ib.client.Order; + +public class ExtOrdDlg extends JDialog { + public Order m_order = new Order(); + public boolean m_rc; + + private JTextField m_tif = new JTextField( "DAY"); + private JTextField m_ocaGroup = new JTextField(); + private JTextField m_ocaType = new JTextField("0"); + + private JTextField m_account = new JTextField(); + private JTextField m_settlingFirm = new JTextField(); + private JTextField m_clearingAccount = new JTextField(); + private JTextField m_clearingIntent = new JTextField(); + + private JTextField m_openClose = new JTextField( "O"); + private JTextField m_origin = new JTextField( "1"); + private JTextField m_orderRef = new JTextField(); + private JTextField m_parentId = new JTextField( "0"); + private JTextField m_transmit = new JTextField( "1"); + private JTextField m_blockOrder = new JTextField( "0"); + private JTextField m_sweepToFill = new JTextField( "0"); + private JTextField m_displaySize = new JTextField( "0"); + private JTextField m_triggerMethod = new JTextField( "0"); + private JTextField m_outsideRth = new JTextField( "0"); + private JTextField m_hidden = new JTextField( "0"); + private JTextField m_discretionaryAmt = new JTextField( "0"); + private JTextField m_shortSaleSlot = new JTextField( "0"); + private JTextField m_designatedLocation = new JTextField(); + private JTextField m_exemptCode = new JTextField( "-1"); + private JTextField m_rule80A = new JTextField(); + private JTextField m_allOrNone = new JTextField(); + private JTextField m_overridePercentageConstraints = new JTextField(); + private JTextField m_minQty = new JTextField(); + private JTextField m_percentOffset = new JTextField(); + private JTextField m_eTradeOnly = new JTextField(); + private JTextField m_firmQuoteOnly = new JTextField(); + private JTextField m_nbboPriceCap = new JTextField(); + private JTextField m_auctionStrategy = new JTextField("0"); + private JTextField m_startingPrice = new JTextField(); + private JTextField m_stockRefPrice = new JTextField(); + private JTextField m_delta = new JTextField(); + private JTextField m_BOXstockRangeLower = new JTextField(); + private JTextField m_BOXstockRangeUpper = new JTextField(); + + private JTextField m_VOLVolatility = new JTextField(); + private JTextField m_VOLVolatilityType = new JTextField(); + private JTextField m_VOLDeltaNeutralOrderType = new JTextField(); + private JTextField m_VOLDeltaNeutralAuxPrice = new JTextField(); + private JTextField m_VOLDeltaNeutralConId = new JTextField(); + private JTextField m_VOLDeltaNeutralSettlingFirm = new JTextField(); + private JTextField m_VOLDeltaNeutralClearingAccount = new JTextField(); + private JTextField m_VOLDeltaNeutralClearingIntent = new JTextField(); + private JTextField m_VOLContinuousUpdate = new JTextField(); + private JTextField m_VOLReferencePriceType = new JTextField(); + private JTextField m_trailStopPrice = new JTextField(); + + private JTextField m_scaleInitLevelSize = new JTextField(); + private JTextField m_scaleSubsLevelSize = new JTextField(); + private JTextField m_scalePriceIncrement = new JTextField(); + + private JTextField m_hedgeType = new JTextField(); + private JTextField m_hedgeParam = new JTextField(); + private JCheckBox m_optOutSmartRoutingCheckBox = new JCheckBox("Opting out of SMART routing", false); + + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + + public ExtOrdDlg( OrderDlg owner) { + super( owner, true); + + setTitle( "Sample"); + + // create extended order attributes panel + JPanel extOrderDetailsPanel = new JPanel( new GridLayout( 0, 4, 10, 10) ); + extOrderDetailsPanel.setBorder( BorderFactory.createTitledBorder( "Extended Order Info") ); + extOrderDetailsPanel.add( new JLabel( "TIF") ); + extOrderDetailsPanel.add( m_tif); + extOrderDetailsPanel.add( new JLabel( "OCA Group") ); + extOrderDetailsPanel.add( m_ocaGroup); + extOrderDetailsPanel.add( new JLabel( "OCA Type") ); + extOrderDetailsPanel.add( m_ocaType); + + extOrderDetailsPanel.add( new JLabel( "Account") ); + extOrderDetailsPanel.add( m_account); + extOrderDetailsPanel.add(new JLabel("Settling Firm")); + extOrderDetailsPanel.add(m_settlingFirm); + extOrderDetailsPanel.add(new JLabel("Clearing Account")); + extOrderDetailsPanel.add(m_clearingAccount); + extOrderDetailsPanel.add(new JLabel("Clearing Intent")); + extOrderDetailsPanel.add(m_clearingIntent); + + extOrderDetailsPanel.add( new JLabel( "Open/Close") ); + extOrderDetailsPanel.add( m_openClose); + extOrderDetailsPanel.add( new JLabel( "Origin") ); + extOrderDetailsPanel.add( m_origin); + extOrderDetailsPanel.add( new JLabel( "OrderRef") ); + extOrderDetailsPanel.add( m_orderRef); + extOrderDetailsPanel.add( new JLabel( "Parent Id") ); + extOrderDetailsPanel.add( m_parentId); + extOrderDetailsPanel.add( new JLabel( "Transmit") ); + extOrderDetailsPanel.add( m_transmit); + extOrderDetailsPanel.add( new JLabel( "Block Order") ); + extOrderDetailsPanel.add( m_blockOrder); + extOrderDetailsPanel.add( new JLabel( "Sweep To Fill") ); + extOrderDetailsPanel.add( m_sweepToFill); + extOrderDetailsPanel.add( new JLabel( "Display Size") ); + extOrderDetailsPanel.add( m_displaySize); + extOrderDetailsPanel.add( new JLabel( "Trigger Method") ); + extOrderDetailsPanel.add( m_triggerMethod); + extOrderDetailsPanel.add( new JLabel( "Outside Regular Trading Hours") ); + extOrderDetailsPanel.add( m_outsideRth); + extOrderDetailsPanel.add( new JLabel( "Hidden") ); + extOrderDetailsPanel.add( m_hidden); + extOrderDetailsPanel.add( new JLabel( "Discretionary Amt") ); + extOrderDetailsPanel.add( m_discretionaryAmt); + extOrderDetailsPanel.add( new JLabel( "Trail Stop Price") ); + extOrderDetailsPanel.add( m_trailStopPrice); + extOrderDetailsPanel.add( new JLabel( "Institutional Short Sale Slot") ); + extOrderDetailsPanel.add( m_shortSaleSlot); + extOrderDetailsPanel.add( new JLabel( "Institutional Designated Location") ); + extOrderDetailsPanel.add( m_designatedLocation); + extOrderDetailsPanel.add( new JLabel( "Exempt Code") ); + extOrderDetailsPanel.add( m_exemptCode); + extOrderDetailsPanel.add( new JLabel( "Rule 80 A") ); + extOrderDetailsPanel.add(m_rule80A); + + extOrderDetailsPanel.add(new JLabel("All or None")); + extOrderDetailsPanel.add(m_allOrNone); + extOrderDetailsPanel.add(new JLabel("Override Percentage Constraints")); + extOrderDetailsPanel.add(m_overridePercentageConstraints); + extOrderDetailsPanel.add(new JLabel("Minimum Quantity")); + extOrderDetailsPanel.add(m_minQty); + extOrderDetailsPanel.add(new JLabel("Percent Offset")); + extOrderDetailsPanel.add(m_percentOffset); + extOrderDetailsPanel.add(new JLabel("Electronic Exchange Only")); + extOrderDetailsPanel.add(m_eTradeOnly); + extOrderDetailsPanel.add(new JLabel("Firm Quote Only")); + extOrderDetailsPanel.add(m_firmQuoteOnly); + extOrderDetailsPanel.add(new JLabel("NBBO Price Cap")); + extOrderDetailsPanel.add(m_nbboPriceCap); + extOrderDetailsPanel.add( new JLabel( "") ); + extOrderDetailsPanel.add( new JLabel("")); + extOrderDetailsPanel.add(new JLabel("BOX: Auction Strategy")); + extOrderDetailsPanel.add(m_auctionStrategy); + extOrderDetailsPanel.add(new JLabel("BOX: Starting Price")); + extOrderDetailsPanel.add(m_startingPrice); + extOrderDetailsPanel.add(new JLabel("BOX: Stock Reference Price")); + extOrderDetailsPanel.add(m_stockRefPrice); + extOrderDetailsPanel.add(new JLabel("BOX: Delta")); + extOrderDetailsPanel.add(m_delta); + extOrderDetailsPanel.add(new JLabel("BOX or VOL: Stock Range Lower")); + extOrderDetailsPanel.add(m_BOXstockRangeLower); + extOrderDetailsPanel.add(new JLabel("BOX or VOL: Stock Range Upper")); + extOrderDetailsPanel.add(m_BOXstockRangeUpper); + + extOrderDetailsPanel.add(new JLabel("VOL: Volatility")); + extOrderDetailsPanel.add(m_VOLVolatility); + extOrderDetailsPanel.add(new JLabel("VOL: Volatility Type (1 or 2)")); + extOrderDetailsPanel.add(m_VOLVolatilityType); + extOrderDetailsPanel.add(new JLabel("VOL: Hedge Delta Order Type")); + extOrderDetailsPanel.add(m_VOLDeltaNeutralOrderType); + extOrderDetailsPanel.add(new JLabel("VOL: Hedge Delta Aux Price")); + extOrderDetailsPanel.add(m_VOLDeltaNeutralAuxPrice); + extOrderDetailsPanel.add(new JLabel("VOL: Hedge Delta Contract Id")); + extOrderDetailsPanel.add(m_VOLDeltaNeutralConId); + extOrderDetailsPanel.add(new JLabel("VOL: Hedge Delta Settling Firm")); + extOrderDetailsPanel.add(m_VOLDeltaNeutralSettlingFirm); + extOrderDetailsPanel.add(new JLabel("VOL: Hedge Delta Clearing Account")); + extOrderDetailsPanel.add(m_VOLDeltaNeutralClearingAccount); + extOrderDetailsPanel.add(new JLabel("VOL: Hedge Delta Clearing Intent")); + extOrderDetailsPanel.add(m_VOLDeltaNeutralClearingIntent); + extOrderDetailsPanel.add(new JLabel("VOL: Continuously Update Price (0 or 1)")); + extOrderDetailsPanel.add(m_VOLContinuousUpdate); + extOrderDetailsPanel.add(new JLabel("VOL: Reference Price Type (1 or 2)")); + extOrderDetailsPanel.add(m_VOLReferencePriceType); + + extOrderDetailsPanel.add(new JLabel("SCALE: Scale Init Level Size")); + extOrderDetailsPanel.add(m_scaleInitLevelSize); + extOrderDetailsPanel.add(new JLabel("SCALE: Scale Subs Level Size")); + extOrderDetailsPanel.add(m_scaleSubsLevelSize); + extOrderDetailsPanel.add(new JLabel("SCALE: Scale Price Increment")); + extOrderDetailsPanel.add(m_scalePriceIncrement); + + extOrderDetailsPanel.add(new JLabel("HEDGE: Type")); + extOrderDetailsPanel.add(m_hedgeType); + extOrderDetailsPanel.add(new JLabel("HEDGE: Param")); + extOrderDetailsPanel.add(m_hedgeParam); + extOrderDetailsPanel.add(m_optOutSmartRoutingCheckBox) ; + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create action listeners + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + // create dlg box + getContentPane().add( extOrderDetailsPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + + JScrollPane scroller = new JScrollPane(extOrderDetailsPanel); + this.add( scroller, BorderLayout.CENTER); + + pack(); + } + + void onOk() { + m_rc = false; + + try { + // set extended order fields + m_order.m_tif = m_tif.getText().trim(); + m_order.m_ocaGroup = m_ocaGroup.getText().trim(); + m_order.m_ocaType = parseInt( m_ocaType); + + m_order.m_account = m_account.getText().trim(); + m_order.m_settlingFirm = m_settlingFirm.getText().trim(); + m_order.m_clearingAccount = m_clearingAccount.getText().trim(); + m_order.m_clearingIntent = m_clearingIntent.getText().trim(); + + m_order.m_openClose = m_openClose.getText().trim(); + m_order.m_origin = parseInt( m_origin ); + m_order.m_orderRef = m_orderRef.getText().trim(); + m_order.m_parentId = parseInt( m_parentId); + m_order.m_transmit = parseInt(m_transmit) != 0; + m_order.m_blockOrder = parseInt(m_blockOrder) != 0; + m_order.m_sweepToFill = parseInt(m_sweepToFill) != 0; + m_order.m_displaySize = parseInt( m_displaySize); + m_order.m_triggerMethod = parseInt( m_triggerMethod); + m_order.m_outsideRth = parseInt(m_outsideRth) != 0; + m_order.m_hidden = parseInt(m_hidden) != 0; + m_order.m_discretionaryAmt = parseDouble( m_discretionaryAmt); + m_order.m_shortSaleSlot = parseInt( m_shortSaleSlot ); + m_order.m_designatedLocation = m_designatedLocation.getText().trim(); + m_order.m_exemptCode = Integer.parseInt(m_exemptCode.getText().length() != 0 ? m_exemptCode.getText() : "-1"); + m_order.m_rule80A = m_rule80A.getText().trim(); + m_order.m_allOrNone = parseInt(m_allOrNone) != 0; + m_order.m_minQty = parseMaxInt(m_minQty); + m_order.m_overridePercentageConstraints = + parseInt(m_overridePercentageConstraints) != 0; + m_order.m_percentOffset = parseMaxDouble(m_percentOffset); + m_order.m_eTradeOnly = parseInt(m_eTradeOnly) != 0; + m_order.m_firmQuoteOnly = parseInt(m_firmQuoteOnly) != 0; + m_order.m_nbboPriceCap = parseMaxDouble(m_nbboPriceCap); + m_order.m_optOutSmartRouting = m_optOutSmartRoutingCheckBox.isSelected(); + m_order.m_auctionStrategy = parseInt(m_auctionStrategy); + m_order.m_startingPrice = parseMaxDouble(m_startingPrice); + m_order.m_stockRefPrice = parseMaxDouble(m_stockRefPrice); + m_order.m_delta = parseMaxDouble(m_delta); + m_order.m_stockRangeLower = parseMaxDouble(m_BOXstockRangeLower); + m_order.m_stockRangeUpper = parseMaxDouble(m_BOXstockRangeUpper); + m_order.m_volatility = parseMaxDouble(m_VOLVolatility); + m_order.m_volatilityType = parseMaxInt(m_VOLVolatilityType); + m_order.m_deltaNeutralOrderType = m_VOLDeltaNeutralOrderType.getText().trim(); + m_order.m_deltaNeutralAuxPrice = parseMaxDouble(m_VOLDeltaNeutralAuxPrice); + m_order.m_deltaNeutralConId = parseInt(m_VOLDeltaNeutralConId); + m_order.m_deltaNeutralSettlingFirm = m_VOLDeltaNeutralSettlingFirm.getText().trim(); + m_order.m_deltaNeutralClearingAccount = m_VOLDeltaNeutralClearingAccount.getText().trim(); + m_order.m_deltaNeutralClearingIntent = m_VOLDeltaNeutralClearingIntent.getText().trim(); + m_order.m_continuousUpdate = parseInt(m_VOLContinuousUpdate); + m_order.m_referencePriceType = parseMaxInt(m_VOLReferencePriceType); + m_order.m_trailStopPrice = parseMaxDouble(m_trailStopPrice); + + m_order.m_scaleInitLevelSize = parseMaxInt(m_scaleInitLevelSize); + m_order.m_scaleSubsLevelSize = parseMaxInt(m_scaleSubsLevelSize); + m_order.m_scalePriceIncrement = parseMaxDouble(m_scalePriceIncrement); + m_order.m_hedgeType = m_hedgeType.getText().trim(); + m_order.m_hedgeParam = m_hedgeParam.getText().trim(); + } + catch( Exception e) { + Main.inform( this, "Error - " + e); + return; + } + + m_rc = true; + setVisible( false); + } + + private int parseMaxInt(JTextField textField) { + String text = textField.getText().trim(); + if (text.length() == 0) { + return Integer.MAX_VALUE; + } + else { + return Integer.parseInt(text); + } + } + + private double parseMaxDouble(JTextField textField) { + String text = textField.getText().trim(); + if (text.length() == 0) { + return Double.MAX_VALUE; + } + else { + return Double.parseDouble(text); + } + } + + private int parseInt(JTextField textField) { + String text = textField.getText().trim(); + if (text.length() == 0) { + return 0; + } + else { + return Integer.parseInt(text); + } + } + + private double parseDouble(JTextField textField) { + String text = textField.getText().trim(); + if (text.length() == 0) { + return 0; + } + else { + return Double.parseDouble(text); + } + } + + void onCancel() { + m_rc = false; + setVisible( false); + } +} diff --git a/ib/src/main/java/TestJavaClient/FAAllocationInfoDlg.java b/ib/src/main/java/TestJavaClient/FAAllocationInfoDlg.java new file mode 100644 index 00000000..105626cd --- /dev/null +++ b/ib/src/main/java/TestJavaClient/FAAllocationInfoDlg.java @@ -0,0 +1,104 @@ +/** + * + * FAAllocationInfoDlg.java + * + */ + +package TestJavaClient; + +import java.awt.Color; +import java.awt.event.ActionEvent; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.border.Border; +import javax.swing.border.TitledBorder; + +public class FAAllocationInfoDlg extends JDialog { + IBGridBagPanel mainJPanel = new IBGridBagPanel(); + IBGridBagPanel faGroupJPanel = new IBGridBagPanel(); + IBGridBagPanel faProfileJPanel = new IBGridBagPanel(); + + JLabel m_groupLabel = new JLabel("Group"); + JLabel m_methodLabel = new JLabel("Method"); + JLabel m_percentageLabel = new JLabel("Percentage"); + JLabel m_profileLabel = new JLabel("Profile"); + + JTextField m_groupTextField = new JTextField(20); + JTextField m_methodTextField = new JTextField(20); + JTextField m_percentageTextField = new JTextField(20); + JTextField m_profileTextField = new JTextField(20); + + JButton m_okButton = new JButton("OK"); + JButton m_closeButton = new JButton("Close"); + + private OrderDlg m_parent; + + public FAAllocationInfoDlg(OrderDlg dlg) { + super(dlg, false); + m_parent = dlg; + try { + jbInit(); + pack(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + void jbInit() throws Exception { + Color etchedColor = new Color(148, 145, 140); + Border border1 = BorderFactory.createEtchedBorder(Color.white, etchedColor); + Border border2 = BorderFactory.createEtchedBorder(Color.white, etchedColor); + TitledBorder titledBorder1 = new TitledBorder(border1, "Group"); + TitledBorder titledBorder2 = new TitledBorder(border2, "Profile"); + + faGroupJPanel.setBorder(titledBorder1); + faProfileJPanel.setBorder(titledBorder2); + + faGroupJPanel.SetObjectPlacement(m_groupLabel, 0, 0); + faGroupJPanel.SetObjectPlacement(m_groupTextField, 1, 0); + faGroupJPanel.SetObjectPlacement(m_methodLabel, 0, 1); + faGroupJPanel.SetObjectPlacement(m_methodTextField, 1, 1); + faGroupJPanel.SetObjectPlacement(m_percentageLabel, 0, 2); + faGroupJPanel.SetObjectPlacement(m_percentageTextField, 1, 2); + + faProfileJPanel.SetObjectPlacement(m_profileLabel, 0, 0); + faProfileJPanel.SetObjectPlacement(m_profileTextField, 1, 0); + + mainJPanel.SetObjectPlacement(faProfileJPanel, 0, 0, 4, 1); + mainJPanel.SetObjectPlacement(faGroupJPanel, 0, 1, 4, 1); + mainJPanel.SetObjectPlacement(m_okButton, 1, 2, 1, 1); + mainJPanel.SetObjectPlacement(m_closeButton, 2, 2, 1, 1); + + setTitle("FA Allocation Info"); + getContentPane().add(mainJPanel); + setSize( 600, 300); + + + m_okButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + onOk(); + } + }); + m_closeButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(ActionEvent e) { + onClose(); + } + }); + } + + void onOk() { + m_parent.faGroup(m_groupTextField.getText().trim()); + m_parent.faMethod(m_methodTextField.getText().trim()); + m_parent.faPercentage(m_percentageTextField.getText().trim()); + m_parent.faProfile(m_profileTextField.getText().trim()); + dispose(); + } + + void onClose() { + dispose(); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/FinancialAdvisorDlg.java b/ib/src/main/java/TestJavaClient/FinancialAdvisorDlg.java new file mode 100644 index 00000000..24725f3d --- /dev/null +++ b/ib/src/main/java/TestJavaClient/FinancialAdvisorDlg.java @@ -0,0 +1,83 @@ +/* + * FinancialAdvisorDlg.java + * + */ + +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JDialog; + +public class FinancialAdvisorDlg extends JDialog { + private int DIALOG_WIDTH = 500; + private int EDITOR_HEIGHT = 240; + private int BUTTON_PANEL_HEIGHT = 60; + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + private IBTextPanel groupTextEditor = new IBTextPanel("Groups", true) ; + private IBTextPanel profileTextEditor = new IBTextPanel("Allocation Profiles", true) ; + private IBTextPanel aliasTextEditor = new IBTextPanel("Aliases", true) ; + String groupsXML ; + String profilesXML ; + String aliasesXML ; + boolean m_rc = false; + + public FinancialAdvisorDlg( Frame owner) { + super( owner, "Financial Advisor", true); + + IBGridBagPanel editPanel = new IBGridBagPanel(); + + editPanel.SetObjectPlacement( groupTextEditor, 0, 0 ) ; + editPanel.SetObjectPlacement( profileTextEditor, 0, 1 ) ; + editPanel.SetObjectPlacement( aliasTextEditor, 0, 2 ) ; + Dimension editPanelSizeDimension = + new Dimension(DIALOG_WIDTH, 3 * EDITOR_HEIGHT); + editPanel.setPreferredSize(editPanelSizeDimension) ; + + IBGridBagPanel buttonPanel = new IBGridBagPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create action listeners + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + //setTitle( "Financial Advisor"); + getContentPane().add( editPanel, BorderLayout.NORTH); + getContentPane().add( buttonPanel, BorderLayout.CENTER); + pack(); + } + + void receiveInitialXML(String p_groupsXML, String p_profilesXML, String p_aliasesXML) { + groupTextEditor.setTextDetabbed(p_groupsXML); + profileTextEditor.setTextDetabbed(p_profilesXML); + aliasTextEditor.setTextDetabbed(p_aliasesXML); + } + + void onOk() { + m_rc = true; + groupsXML = groupTextEditor.getText(); + profilesXML = profileTextEditor.getText(); + aliasesXML = aliasTextEditor.getText(); + setVisible( false); + } + + void onCancel() { + m_rc = false; + setVisible( false); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/IBGridBagPanel.java b/ib/src/main/java/TestJavaClient/IBGridBagPanel.java new file mode 100644 index 00000000..7835e422 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/IBGridBagPanel.java @@ -0,0 +1,86 @@ +/* + * IBGridBagPanel.java + * + */ + +package TestJavaClient ; + +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; + +import javax.swing.JPanel; + +class IBGridBagPanel extends JPanel { + private static final Insets oneInsets = new Insets(1, 1, 1, 1); + private GridBagLayout m_layout = new GridBagLayout(); + + IBGridBagPanel() { + setLayout(m_layout); + } + + public void setConstraints(Component comp, GridBagConstraints constraints) { + m_layout.setConstraints(comp, constraints); + } + + public void SetObjectPlacement(Component c, int x, int y) { + addToPane(c, x, y, 1, 1, 100, 100, oneInsets) ; + } + + public void SetObjectPlacement(Component c, int x, int y, int w, int h) { + addToPane(c, x, y, w, h, 100, 100, oneInsets) ; + } + + public void SetObjectPlacement(Component c, int x, int y, int w, int h, int xGrow, int yGrow) { + addToPane(c, x, y, w, h, xGrow, yGrow, oneInsets) ; + } + + public void SetObjectPlacement(Component c, int x, int y, int w, int h, int xGrow, int yGrow, int fill) { + addToPane(c, x, y, w, h, xGrow, yGrow, GridBagConstraints.WEST, fill, oneInsets) ; + } + + public void SetObjectPlacement(Component c, int x, int y, int w, int h, int xGrow, int yGrow, int anchor, int fill) { + addToPane(c, x, y, w, h, xGrow, yGrow, anchor, fill, oneInsets) ; + } + + public void SetObjectPlacement(Component c, int x, int y, int w, int h, int xGrow, int yGrow, Insets insets) { + addToPane(c, x, y, w, h, xGrow, yGrow, insets) ; + } + + private void addToPane(Component c, int x, int y, int w, int h, + int xGrow, int yGrow, Insets insets) { + addToPane(c, x, y, w, h, xGrow, yGrow, GridBagConstraints.WEST, GridBagConstraints.BOTH, insets) ; + } + + private void addToPane(Component c, int x, int y, int w, int h, int xGrow, + int yGrow, int anchor, int fill, Insets insets) { + GridBagConstraints gbc = new GridBagConstraints(); + + // the coordinates of the cell in the layout that contains + // the upper-left corner of the component + gbc.gridx = x; + gbc.gridy = y; + + // the number of cells that this entry is going to take up + gbc.gridwidth = w; + gbc.gridheight = h; + + // drive how extra space is distributed among components. + gbc.weightx = xGrow; + gbc.weighty = yGrow; + + // drive how component is made larger if extra space is available for it + gbc.fill = fill; + + // drive where, within the display area, to place the component when it + // is larger than its display area. + gbc.anchor = anchor; + + // drive the minimum amount of space between the component and the edges + // of its display area + gbc.insets = insets; + + add(c, gbc); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/IBTextPanel.java b/ib/src/main/java/TestJavaClient/IBTextPanel.java new file mode 100644 index 00000000..97a775a0 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/IBTextPanel.java @@ -0,0 +1,112 @@ +/* + * IBTextPanel.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.StringTokenizer; + +import javax.swing.BorderFactory; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.border.Border; + +class IBTextPanel extends JPanel { + public static final Color textBackgroundColor = new Color(5, 5, 5); + public static final Color textForegroundColor = new Color(0, 245, 0); + public static final Font textComponentFont = new JList().getFont(); + public static final Color textCaretColor = Color.WHITE; + public static final String lineSeparator = System.getProperty("line.separator"); + + private JTextArea m_textArea = new JTextArea(); + private JScrollPane m_scrollPane = new JScrollPane(m_textArea); + private final static String CRLF = "\r\n" ; + private final static String LF = "\n" ; + private final static String TAB = "\t" ; + private final static String EIGHT_SPACES = " "; + private final static String EMPTY_STRING = ""; + + IBTextPanel() { + this(null, false); + } + + IBTextPanel(String title, boolean editable) { + super(new BorderLayout()); + if (title != null) { + Border border = BorderFactory.createTitledBorder( title); + setBorder(border); + } + m_textArea.setBackground(textBackgroundColor); + m_textArea.setForeground(textForegroundColor); + m_textArea.setFont(textComponentFont); + m_textArea.setCaretColor(textCaretColor); + m_textArea.setEditable(editable); + add(m_scrollPane); + } + + public void clear() { + m_textArea.setText(EMPTY_STRING); + } + + public void setText(String text) { + m_textArea.setText(text); + if (m_textArea.isEditable()) { + moveCursorToBeginning(); + } else { + moveCursorToEnd(); + } + } + + public void setTextDetabbed(String text) { + m_textArea.setText(detabbed(text)); + } + + public String getText() { + return m_textArea.getText(); + } + + public void add(String line) { + m_textArea.append(line + lineSeparator); + moveCursorToEnd(); + } + + public void moveCursorToEnd() { + m_textArea.setCaretPosition(m_textArea.getText().length()); + } + + public void moveCursorToBeginning() { + m_textArea.setCaretPosition(0); + } + + public void add(Collection lines) { + for (Iterator iter = lines.iterator(); iter.hasNext(); ) { + add((String)iter.next()); + } + } + + public void addText(String text) { + add(tokenizedIntoArrayList(detabbed(text), LF)); + } + + public static ArrayList tokenizedIntoArrayList(String source, String delimiter) { + ArrayList list = new ArrayList(); + StringTokenizer st = new StringTokenizer(source, delimiter); + while (st.hasMoreTokens()) { + String temp = st.nextToken(); + list.add(temp); + } + return list; + } + + private String detabbed(String text) { + return text.replaceAll(TAB, EIGHT_SPACES); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/LogConfigDlg.java b/ib/src/main/java/TestJavaClient/LogConfigDlg.java new file mode 100644 index 00000000..3a6dee26 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/LogConfigDlg.java @@ -0,0 +1,82 @@ +/* + * LogConfigDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; + +public class LogConfigDlg extends JDialog { + public static int SYSTEM_LOG = 1; + public static int ERROR_LOG = 2; + public static int WARN_LOG = 3; + public static int INFO_LOG = 4; + public static int DETAIL_LOG = 5; + + JComboBox m_cmbServerLogLevels = new JComboBox(); + JButton m_ok = new JButton( "OK"); + JButton m_cancel = new JButton( "Cancel"); + int m_serverLogLevel; + boolean m_rc; + + public LogConfigDlg( Frame owner) { + super( owner, true); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create action listeners + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + // create mid panel + m_cmbServerLogLevels.addItem("System"); + m_cmbServerLogLevels.addItem("Error"); + m_cmbServerLogLevels.addItem("Warning"); + m_cmbServerLogLevels.addItem("Information"); + m_cmbServerLogLevels.addItem("Detail"); + + JPanel midPanel = new JPanel(); + midPanel.setLayout( new GridLayout( 0, 2, 5, 5) ); + midPanel.add( new JLabel( "Log Level :") ); + midPanel.add( m_cmbServerLogLevels); + + // create dlg box + getContentPane().add( midPanel, BorderLayout.NORTH); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + setTitle( "Log Configuration"); + pack(); + } + + void onOk() { + // set server log Level + m_serverLogLevel = m_cmbServerLogLevels.getSelectedIndex() + 1; + m_rc = true; + setVisible( false); + } + + void onCancel() { + m_rc = false; + setVisible( false); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/Main.java b/ib/src/main/java/TestJavaClient/Main.java new file mode 100644 index 00000000..8a3d68f8 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/Main.java @@ -0,0 +1,37 @@ +/* + * Main.java + * + */ +package TestJavaClient; + +import java.awt.Component; + +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +public class Main { + + // This method is called to start the application + public static void main (String args[]) { + SampleFrame sampleFrame = new SampleFrame(); + sampleFrame.setVisible(true); + } + + static public void inform( final Component parent, final String str) { + if( SwingUtilities.isEventDispatchThread() ) { + showMsg( parent, str, JOptionPane.INFORMATION_MESSAGE); + } + else { + SwingUtilities.invokeLater( new Runnable() { + public void run() { + showMsg( parent, str, JOptionPane.INFORMATION_MESSAGE); + } + }); + } + } + + static private void showMsg( Component parent, String str, int type) { + // this function pops up a dlg box displaying a message + JOptionPane.showMessageDialog( parent, str, "IB Java Test Client", type); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/MktDepthDlg.java b/ib/src/main/java/TestJavaClient/MktDepthDlg.java new file mode 100644 index 00000000..f886956c --- /dev/null +++ b/ib/src/main/java/TestJavaClient/MktDepthDlg.java @@ -0,0 +1,276 @@ +/* + * MktDepthDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.LinkedList; +import java.util.ListIterator; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; + +import com.ib.client.EClientSocket; + +public class MktDepthDlg extends JDialog { + final static int OPERATION_INSERT = 0; + final static int OPERATION_UPDATE = 1; + final static int OPERATION_DELETE = 2; + + final static int SIDE_ASK = 0; + final static int SIDE_BID = 1; + final static int MKT_DEPTH_DATA_RESET = 317; + + private JButton m_close = new JButton( "Close"); + private MktDepthModel m_bidModel = new MktDepthModel(); + private MktDepthModel m_askModel = new MktDepthModel(); + private EClientSocket m_client; + private int m_id; + + public MktDepthDlg(String title, JFrame parent) { + super(parent, title, false); + + JScrollPane bidPane = new JScrollPane(new JTable(m_bidModel)); + JScrollPane askPane = new JScrollPane(new JTable(m_askModel)); + + bidPane.setBorder(BorderFactory.createTitledBorder( "Bid") ); + askPane.setBorder(BorderFactory.createTitledBorder( "Ask") ); + + JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, bidPane, askPane); + splitPane.setOneTouchExpandable(true); + splitPane.setDividerLocation(300); + splitPane.setPreferredSize(new Dimension(600, 380)); + + JPanel closePanel = new JPanel(); + closePanel.add(m_close); + m_close.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onClose(); + } + }); + + this.addWindowListener( new WindowAdapter() { + public void windowClosing(WindowEvent e) { + onClose(); + } + }); + + + getContentPane().add( splitPane, BorderLayout.CENTER); + getContentPane().add( closePanel, BorderLayout.SOUTH); + setLocation(20, 20); + pack(); + reset(); + } + + void setParams( EClientSocket client, int id) { + m_client = client; + m_id = id; + reset(); + } + + void updateMktDepth( int tickerId, int position, String marketMaker, + int operation, int side, double price, int size) { + try { + MktDepthModel.MktDepthTableRow tmpRow = null; + + if (operation == OPERATION_INSERT ) + { + if ( side == SIDE_BID ) { + m_bidModel.addOrderAt(position, marketMaker, price, size); + } + else { + m_askModel.addOrderAt(position, marketMaker, price, size); + } + } + else if (operation == OPERATION_UPDATE ) + { + if ( side == SIDE_BID ) { + tmpRow = m_bidModel.getOrderAt(position); + if ( tmpRow != null ) { + tmpRow.m_marketMaker = marketMaker; + tmpRow.m_price = price; + tmpRow.m_size = size; + } + m_bidModel.fireTableRowsUpdated(position, position); + } + else { + tmpRow = m_askModel.getOrderAt(position); + if ( tmpRow != null ) { + tmpRow.m_marketMaker = marketMaker; + tmpRow.m_price = price; + tmpRow.m_size = size; + } + m_askModel.fireTableRowsUpdated(position, position); + } + + } + else if (operation == OPERATION_DELETE) + { + if ( side == SIDE_BID ) { + m_bidModel.removeOrderAt(position); + } + else { + m_askModel.removeOrderAt(position); + } + } + + if ( side == SIDE_BID ) { + m_bidModel.updateCumSizesAndAvgPrices(position); + } + else { + m_askModel.updateCumSizesAndAvgPrices(position); + } + } + catch( Exception e) { + System.out.println("Exception: " + e.getMessage()); + } + } + + void reset() { + m_bidModel.reset(); + m_askModel.reset(); + } + + void onClose() { + m_client.cancelMktDepth( m_id ); + setVisible( false); + } +} + +class MktDepthModel extends AbstractTableModel { + private LinkedList m_allData = new LinkedList(); + + synchronized public void addOrderAt(int position, String marketMaker, double price, int size) + { + MktDepthTableRow newData = new MktDepthTableRow(marketMaker, price, size); + m_allData.add(position, newData); + fireTableRowsInserted(position, position); + } + + synchronized public void removeOrderAt(int position) + { + m_allData.remove(position); + fireTableRowsDeleted(position, position); + } + + synchronized public MktDepthTableRow getOrderAt(int orderPosition) { + return (MktDepthTableRow)getIteratorAt(orderPosition).next(); + } + + synchronized public ListIterator getIteratorAt(int orderPosition) { + return m_allData.listIterator(orderPosition); + } + + synchronized public void updateCumSizesAndAvgPrices(int baseRow) + { + int cumSize = 0; + double totalPrice = 0.0; + MktDepthTableRow tmpRow = null; + + if (baseRow > 0) { + tmpRow = (MktDepthTableRow)m_allData.get(baseRow - 1); + cumSize = tmpRow.m_cumSize; + totalPrice = tmpRow.m_price * cumSize; + } + + for (int ctr = baseRow ; ctr < m_allData.size() ; ctr++) + { + tmpRow = (MktDepthTableRow) m_allData.get(ctr); + cumSize += tmpRow.m_size; + totalPrice += (tmpRow.m_price * tmpRow.m_size); + tmpRow.m_cumSize = cumSize; + tmpRow.m_avgPrice = (totalPrice / cumSize); + fireTableCellUpdated(ctr, 3); + fireTableCellUpdated(ctr, 4); + } + } + + synchronized public void reset() { + m_allData.clear(); + fireTableDataChanged(); + } + + synchronized public int getRowCount() { + return m_allData.size(); + } + + synchronized public int getColumnCount() { + return 5; + } + + synchronized public Object getValueAt(int r, int c) { + if (r >= m_allData.size()) { + return null; + } + return ((MktDepthTableRow)m_allData.get(r)).getValue(c); + } + + public boolean isCellEditable(int r, int c) { + return false; + } + + public String getColumnName(int c) { + switch (c) { + case 0: + return "MM"; + case 1: + return "Price"; + case 2: + return "Size"; + case 3: + return "Cum Size"; + case 4: + return "Avg Price"; + default: + return null; + } + } + + class MktDepthTableRow { + public String m_marketMaker; + public double m_price; + public int m_size; + public int m_cumSize; + public double m_avgPrice; + + MktDepthTableRow(String marketMaker, double price,int size) { + m_marketMaker = marketMaker; + m_price = price; + m_size = size; + m_cumSize = 0; + m_avgPrice = 0.0; + } + + Object getValue(int c) { + switch (c) + { + case 0: + return m_marketMaker; + case 1: + return "" + m_price; + case 2: + return "" + m_size; + case 3: + return "" + m_cumSize; + case 4: + return "" + m_avgPrice; + default: + return null; + } + } + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/NewsBulletinDlg.java b/ib/src/main/java/TestJavaClient/NewsBulletinDlg.java new file mode 100644 index 00000000..0991134c --- /dev/null +++ b/ib/src/main/java/TestJavaClient/NewsBulletinDlg.java @@ -0,0 +1,92 @@ +/* + * NewsBulletinDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JRadioButton; + +public class NewsBulletinDlg extends JDialog { + private IBGridBagPanel m_subscriptionTypePanel = new IBGridBagPanel(); + private IBGridBagPanel m_mainPanel = new IBGridBagPanel(); + + private JButton m_btnSubscribe = new JButton( "Subscribe"); + private JButton m_btnUnsubscribe = new JButton( "Unsubscribe"); + private JButton m_btnClose = new JButton( "Close"); + + private ButtonGroup m_btnGroup = new ButtonGroup(); + private JRadioButton m_btnNewMsgs = new JRadioButton( "receive new messages only."); + private JRadioButton m_btnAllMsgs = new JRadioButton( "receive all the current day's messages and any new messages."); + + public boolean m_rc; + public boolean m_subscribe; + public boolean m_allMsgs; + + public NewsBulletinDlg(SampleFrame parent) { + super(parent, "IB News Bulletin Subscription", true); + + m_btnGroup.add( m_btnNewMsgs); + m_btnGroup.add( m_btnAllMsgs); + m_btnNewMsgs.setSelected( true); + + // register button listeners + m_btnSubscribe.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onSubscribe(); + } + }); + m_btnUnsubscribe.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onUnSubscribe(); + } + }); + m_btnClose.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onClose(); + } + }); + + m_subscriptionTypePanel.setBorder( BorderFactory.createLineBorder( Color.BLACK)); + JLabel optionTypeLabel = new JLabel("When subscribing to IB news bulletins you have 2 options:"); + m_subscriptionTypePanel.SetObjectPlacement(optionTypeLabel, 0, 0); + m_subscriptionTypePanel.SetObjectPlacement(m_btnNewMsgs, 0, 1); + m_subscriptionTypePanel.SetObjectPlacement(m_btnAllMsgs, 0, 2); + + m_mainPanel.SetObjectPlacement(m_subscriptionTypePanel, 0, 0, 4, 1); + m_mainPanel.SetObjectPlacement(m_btnSubscribe, 0, 1); + m_mainPanel.SetObjectPlacement(m_btnUnsubscribe, 1, 1); + m_mainPanel.SetObjectPlacement(m_btnClose, 3, 1); + + getContentPane().add(m_mainPanel, BorderLayout.CENTER); + setSize( 460, 160); + } + + private void onSubscribe() { + m_rc = true; + m_subscribe = true; + m_allMsgs = m_btnAllMsgs.isSelected(); + setVisible( false); + } + + private void onUnSubscribe() { + m_rc = true; + m_subscribe = false; + m_allMsgs = false; + setVisible( false); + } + + private void onClose() { + m_rc = false; + setVisible( false); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/OrderDlg.java b/ib/src/main/java/TestJavaClient/OrderDlg.java new file mode 100644 index 00000000..6198aa48 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/OrderDlg.java @@ -0,0 +1,498 @@ +/* + * OrderDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.JComboBox; + +import com.ib.client.Contract; +import com.ib.client.Order; +import com.ib.client.UnderComp; +import com.ib.client.MarketDataType; + +public class OrderDlg extends JDialog { + final static String ALL_GENERIC_TICK_TAGS = "100,101,104,105,106,107,165,221,225,233,236,258,293,294,295,318"; + final static int OPERATION_INSERT = 0; + final static int OPERATION_UPDATE = 1; + final static int OPERATION_DELETE = 2; + + final static int SIDE_ASK = 0; + final static int SIDE_BID = 1; + + public boolean m_rc; + public int m_id; + public String m_backfillEndTime; + public String m_backfillDuration; + public String m_barSizeSetting; + public int m_useRTH; + public int m_formatDate; + public int m_marketDepthRows; + public String m_whatToShow; + public Contract m_contract = new Contract(); + public Order m_order = new Order(); + public UnderComp m_underComp = new UnderComp(); + public int m_exerciseAction; + public int m_exerciseQuantity; + public int m_override; + public int m_marketDataType; + + private JTextField m_Id = new JTextField( "0"); + private JTextField m_BackfillEndTime = new JTextField(22); + private JTextField m_BackfillDuration = new JTextField( "1 M"); + private JTextField m_BarSizeSetting = new JTextField("1 day"); + private JTextField m_UseRTH = new JTextField( "1"); + private JTextField m_FormatDate = new JTextField( "1"); + private JTextField m_WhatToShow = new JTextField( "TRADES"); + private JTextField m_conId = new JTextField(); + private JTextField m_symbol = new JTextField( "QQQQ"); + private JTextField m_secType = new JTextField( "STK"); + private JTextField m_expiry = new JTextField(); + private JTextField m_strike = new JTextField( "0"); + private JTextField m_right = new JTextField(); + private JTextField m_multiplier = new JTextField(""); + private JTextField m_exchange = new JTextField( "SMART"); + private JTextField m_primaryExch = new JTextField( "ISLAND" ); + private JTextField m_currency = new JTextField("USD"); + private JTextField m_localSymbol = new JTextField(); + private JTextField m_includeExpired = new JTextField("0"); + private JTextField m_secIdType = new JTextField(); + private JTextField m_secId = new JTextField(); + private JTextField m_action = new JTextField( "BUY"); + private JTextField m_totalQuantity = new JTextField( "10"); + private JTextField m_orderType = new JTextField( "LMT"); + private JTextField m_lmtPrice = new JTextField( "40"); + private JTextField m_auxPrice = new JTextField( "0"); + private JTextField m_goodAfterTime = new JTextField(); + private JTextField m_goodTillDate = new JTextField(); + private JTextField m_marketDepthRowTextField = new JTextField( "20"); + private JTextField m_genericTicksTextField = new JTextField(ALL_GENERIC_TICK_TAGS); + private JCheckBox m_snapshotMktDataTextField = new JCheckBox("Snapshot", false); + private JTextField m_exerciseActionTextField = new JTextField("1"); + private JTextField m_exerciseQuantityTextField = new JTextField("1"); + private JTextField m_overrideTextField = new JTextField("0"); + private JComboBox m_marketDataTypeCombo = new JComboBox(MarketDataType.getFields()); + + private JButton m_sharesAlloc = new JButton("FA Allocation Info..."); + private JButton m_comboLegs = new JButton( "Combo Legs"); + private JButton m_btnUnderComp = new JButton( "Delta Neutral"); + private JButton m_btnAlgoParams = new JButton( "Algo Params"); + private JButton m_btnSmartComboRoutingParams = new JButton( "Smart Combo Routing Params"); + + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + private SampleFrame m_parent; + + private String m_faGroup; + private String m_faProfile; + private String m_faMethod; + private String m_faPercentage; + public String m_genericTicks; + public boolean m_snapshotMktData; + + private static final int COL1_WIDTH = 30 ; + private static final int COL2_WIDTH = 100 - COL1_WIDTH ; + public void faGroup(String s) { m_faGroup = s;} + public void faProfile(String s) { m_faProfile = s;} + public void faMethod(String s) { m_faMethod = s;} + public void faPercentage(String s) { m_faPercentage = s; } + + private static void addGBComponent(IBGridBagPanel panel, Component comp, + GridBagConstraints gbc, int weightx, int gridwidth) + { + gbc.weightx = weightx; + gbc.gridwidth = gridwidth; + panel.setConstraints(comp, gbc); + panel.add(comp, gbc); + } + + public OrderDlg( SampleFrame owner) { + super( owner, true); + + m_parent = owner; + setTitle( "Sample"); + + java.awt.GridBagConstraints gbc = new java.awt.GridBagConstraints() ; + gbc.fill = GridBagConstraints.BOTH ; + gbc.anchor = GridBagConstraints.CENTER ; + gbc.weighty = 100 ; + gbc.fill = GridBagConstraints.BOTH ; + gbc.gridheight = 1 ; + // create id panel + IBGridBagPanel pId = new IBGridBagPanel(); + pId.setBorder( BorderFactory.createTitledBorder( "Message Id") ); + + addGBComponent(pId, new JLabel( "Id"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pId, m_Id, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + // create contract panel + IBGridBagPanel pContractDetails = new IBGridBagPanel(); + pContractDetails.setBorder( BorderFactory.createTitledBorder( "Contract Info") ); + addGBComponent(pContractDetails, new JLabel( "Contract Id"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_conId, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Symbol"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_symbol, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Security Type"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_secType, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Expiry"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_expiry, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Strike"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_strike, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Put/Call"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_right, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Option Multiplier"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_multiplier, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Exchange"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_exchange, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Primary Exchange"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_primaryExch, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Currency"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_currency, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Local Symbol"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_localSymbol, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Include Expired"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_includeExpired, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Sec Id Type"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_secIdType, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pContractDetails, new JLabel( "Sec Id"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pContractDetails, m_secId, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + + // create order panel + IBGridBagPanel pOrderDetails = new IBGridBagPanel(); + pOrderDetails.setBorder( BorderFactory.createTitledBorder( "Order Info") ); + addGBComponent(pOrderDetails, new JLabel( "Action"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_action, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pOrderDetails, new JLabel( "Total Order Size"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_totalQuantity, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pOrderDetails, new JLabel( "Order Type"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_orderType, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pOrderDetails, new JLabel( "Lmt Price / Option Price / Volatility"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_lmtPrice, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pOrderDetails, new JLabel( "Aux Price / Underlying Price"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_auxPrice, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pOrderDetails, new JLabel( "Good After Time"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_goodAfterTime, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pOrderDetails, new JLabel( "Good Till Date"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pOrderDetails, m_goodTillDate, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + + // create marketDepth panel + IBGridBagPanel pMarketDepth = new IBGridBagPanel(); + pMarketDepth.setBorder( BorderFactory.createTitledBorder( "Market Depth") ); + addGBComponent(pMarketDepth, new JLabel( "Number of Rows"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pMarketDepth, m_marketDepthRowTextField, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + // create marketData panel + IBGridBagPanel pMarketData = new IBGridBagPanel(); + pMarketData.setBorder( BorderFactory.createTitledBorder( "Market Data") ); + addGBComponent(pMarketData, new JLabel( "Generic Tick Tags"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pMarketData, m_genericTicksTextField, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pMarketData, m_snapshotMktDataTextField, gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + + // create options exercise panel + IBGridBagPanel pOptionsExercise= new IBGridBagPanel(); + pOptionsExercise.setBorder( BorderFactory.createTitledBorder( "Options Exercise") ); + addGBComponent(pOptionsExercise, new JLabel( "Action (1 or 2)"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pOptionsExercise, m_exerciseActionTextField, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pOptionsExercise, new JLabel( "Number of Contracts"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pOptionsExercise, m_exerciseQuantityTextField, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pOptionsExercise, new JLabel( "Override (0 or 1)"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pOptionsExercise, m_overrideTextField, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + // create historical data panel + IBGridBagPanel pBackfill = new IBGridBagPanel(); + pBackfill.setBorder( BorderFactory.createTitledBorder( "Historical Data Query") ); + GregorianCalendar gc = new GregorianCalendar(); + gc.setTimeZone(TimeZone.getTimeZone("GMT")); + String dateTime = "" + + gc.get(Calendar.YEAR) + + pad(gc.get(Calendar.MONTH) + 1) + + pad(gc.get(Calendar.DAY_OF_MONTH)) + " " + + pad(gc.get(Calendar.HOUR_OF_DAY)) + ":" + + pad(gc.get(Calendar.MINUTE)) + ":" + + pad(gc.get(Calendar.SECOND)) + " " + + gc.getTimeZone().getDisplayName( false, TimeZone.SHORT); + + m_BackfillEndTime.setText(dateTime); + addGBComponent(pBackfill, new JLabel( "End Date/Time"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pBackfill, m_BackfillEndTime, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pBackfill, new JLabel( "Duration"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pBackfill, m_BackfillDuration, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pBackfill, new JLabel( "Bar Size Setting (1 to 11)"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pBackfill, m_BarSizeSetting, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pBackfill, new JLabel( "What to Show"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pBackfill, m_WhatToShow, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pBackfill, new JLabel( "Regular Trading Hours (1 or 0)"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pBackfill, m_UseRTH, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(pBackfill, new JLabel( "Date Format Style (1 or 2)"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pBackfill, m_FormatDate, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + // create marketDataType panel + IBGridBagPanel pMarketDataType = new IBGridBagPanel(); + pMarketDataType.setBorder( BorderFactory.createTitledBorder( "Market Data Type") ); + addGBComponent(pMarketDataType, new JLabel( "Market Data Type"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pMarketDataType, m_marketDataTypeCombo, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + // create mid Panel + JPanel pMidPanel = new JPanel(); + pMidPanel.setLayout( new BoxLayout( pMidPanel, BoxLayout.Y_AXIS) ); + pMidPanel.add( pContractDetails, BorderLayout.CENTER); + pMidPanel.add( pOrderDetails, BorderLayout.CENTER); + pMidPanel.add( pMarketDepth, BorderLayout.CENTER); + pMidPanel.add( pMarketData, BorderLayout.CENTER); + pMidPanel.add( pOptionsExercise, BorderLayout.CENTER); + pMidPanel.add( pBackfill, BorderLayout.CENTER); + pMidPanel.add( pMarketDataType, BorderLayout.CENTER); + + // create order button panel + JPanel pOrderButtonPanel = new JPanel(); + pOrderButtonPanel.add( m_sharesAlloc); + pOrderButtonPanel.add( m_comboLegs); + pOrderButtonPanel.add( m_btnUnderComp); + pOrderButtonPanel.add( m_btnAlgoParams); + pOrderButtonPanel.add( m_btnSmartComboRoutingParams); + + pMidPanel.add( pOrderButtonPanel, BorderLayout.CENTER); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create action listeners + m_sharesAlloc.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onSharesAlloc(); + } + }); + + m_comboLegs.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onAddComboLegs(); + } + }); + m_btnUnderComp.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onBtnUnderComp(); + } + }); + m_btnAlgoParams.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onBtnAlgoParams(); + } + }); + m_btnSmartComboRoutingParams.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onBtnSmartComboRoutingParams(); + } + }); + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + // create top panel + JPanel topPanel = new JPanel(); + topPanel.setLayout( new BoxLayout( topPanel, BoxLayout.Y_AXIS) ); + topPanel.add( pId); + topPanel.add( pMidPanel); + + // create dlg box + getContentPane().add( topPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + + JScrollPane scroller = new JScrollPane(topPanel); + this.add( scroller, BorderLayout.CENTER); + + pack(); + } + + private static String pad( int val) { + return val < 10 ? "0" + val : "" + val; + } + + void onSharesAlloc() { + if ( !m_parent.m_bIsFAAccount ) { + return; + } + + FAAllocationInfoDlg dlg = new FAAllocationInfoDlg(this); + + // show the combo leg dialog + dlg.setVisible(true); + } + + void onAddComboLegs() { + + ComboLegDlg comboLegDlg = new ComboLegDlg( + m_contract.m_comboLegs, m_exchange.getText(), this); + + // show the combo leg dialog + comboLegDlg.setVisible( true); + } + + void onBtnUnderComp() { + + UnderCompDlg underCompDlg = new UnderCompDlg(m_underComp, this); + + // show delta neutral dialog + underCompDlg.setVisible( true); + if (underCompDlg.ok()) { + m_contract.m_underComp = m_underComp; + } + else if (underCompDlg.reset()) { + m_contract.m_underComp = null; + } + } + + void onBtnAlgoParams() { + + AlgoParamsDlg algoParamsDlg = new AlgoParamsDlg(m_order, this); + + // show delta neutral dialog + algoParamsDlg.setVisible( true); + } + + void onBtnSmartComboRoutingParams() { + + SmartComboRoutingParamsDlg smartComboRoutingParamsDlg = new SmartComboRoutingParamsDlg(m_order, this); + + // show smart combo routing params dialog + smartComboRoutingParamsDlg.setVisible( true); + } + + void onOk() { + m_rc = false; + + try { + // set id + m_id = Integer.parseInt( m_Id.getText() ); + + // set contract fields + m_contract.m_conId = ParseInt(m_conId.getText(), 0); + m_contract.m_symbol = m_symbol.getText(); + m_contract.m_secType = m_secType.getText(); + m_contract.m_expiry = m_expiry.getText(); + m_contract.m_strike = ParseDouble(m_strike.getText(), 0.0); + m_contract.m_right = m_right.getText(); + m_contract.m_multiplier = m_multiplier.getText(); + m_contract.m_exchange = m_exchange.getText(); + m_contract.m_primaryExch = m_primaryExch.getText(); + m_contract.m_currency = m_currency.getText(); + m_contract.m_localSymbol = m_localSymbol.getText(); + try { + int includeExpired = Integer.parseInt(m_includeExpired.getText()); + m_contract.m_includeExpired = (includeExpired == 1); + } + catch (NumberFormatException ex) { + m_contract.m_includeExpired = false; + } + m_contract.m_secIdType = m_secIdType.getText(); + m_contract.m_secId = m_secId.getText(); + + // set order fields + m_order.m_action = m_action.getText(); + m_order.m_totalQuantity = Integer.parseInt( m_totalQuantity.getText() ); + m_order.m_orderType = m_orderType.getText(); + m_order.m_lmtPrice = Double.parseDouble( m_lmtPrice.getText() ); + m_order.m_auxPrice = Double.parseDouble( m_auxPrice.getText() ); + m_order.m_goodAfterTime = m_goodAfterTime.getText(); + m_order.m_goodTillDate = m_goodTillDate.getText(); + + m_order.m_faGroup = m_faGroup; + m_order.m_faProfile = m_faProfile; + m_order.m_faMethod = m_faMethod; + m_order.m_faPercentage = m_faPercentage; + + // set historical data fields + m_backfillEndTime = m_BackfillEndTime.getText(); + m_backfillDuration = m_BackfillDuration.getText(); + m_barSizeSetting = m_BarSizeSetting.getText(); + m_useRTH = Integer.parseInt( m_UseRTH.getText() ); + m_whatToShow = m_WhatToShow.getText(); + m_formatDate = Integer.parseInt( m_FormatDate.getText() ); + m_exerciseAction = Integer.parseInt( m_exerciseActionTextField.getText() ); + m_exerciseQuantity = Integer.parseInt( m_exerciseQuantityTextField.getText() ); + m_override = Integer.parseInt( m_overrideTextField.getText() );; + + // set market depth rows + m_marketDepthRows = Integer.parseInt( m_marketDepthRowTextField.getText() ); + m_genericTicks = m_genericTicksTextField.getText(); + m_snapshotMktData = m_snapshotMktDataTextField.isSelected(); + + m_marketDataType = m_marketDataTypeCombo.getSelectedIndex() + 1; + } + catch( Exception e) { + Main.inform( this, "Error - " + e); + return; + } + + m_rc = true; + setVisible( false); + } + + void onCancel() { + m_rc = false; + setVisible( false); + } + + public void show() { + m_rc = false; + super.show(); + } + + void setIdAtLeast( int id) { + try { + // set id field to at least id + int curId = Integer.parseInt( m_Id.getText() ); + if( curId < id) { + m_Id.setText( String.valueOf( id) ); + } + } + catch( Exception e) { + Main.inform( this, "Error - " + e); + } + } + + private static int ParseInt(String text, int defValue) { + try { + return Integer.parseInt(text); + } + catch (NumberFormatException e) { + return defValue; + } + } + + private static double ParseDouble(String text, double defValue) { + try { + return Double.parseDouble(text); + } + catch (NumberFormatException e) { + return defValue; + } + } +} diff --git a/ib/src/main/java/TestJavaClient/SampleFrame.java b/ib/src/main/java/TestJavaClient/SampleFrame.java new file mode 100644 index 00000000..e7baa894 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/SampleFrame.java @@ -0,0 +1,1060 @@ +/* + * SampleFrame.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.HashMap; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; + +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.EClientSocket; +import com.ib.client.EWrapper; +import com.ib.client.EWrapperMsgGenerator; +import com.ib.client.Execution; +import com.ib.client.Order; +import com.ib.client.OrderState; +import com.ib.client.UnderComp; +import com.ib.client.Util; + +class SampleFrame extends JFrame implements EWrapper { + private static final int NOT_AN_FA_ACCOUNT_ERROR = 321 ; + private int faErrorCodes[] = { 503, 504, 505, 522, 1100, NOT_AN_FA_ACCOUNT_ERROR } ; + private boolean faError ; + + private EClientSocket m_client = new EClientSocket( this); + private IBTextPanel m_tickers = new IBTextPanel("Market and Historical Data", false); + private IBTextPanel m_TWS = new IBTextPanel("TWS Server Responses", false); + private IBTextPanel m_errors = new IBTextPanel("Errors and Messages", false); + private OrderDlg m_orderDlg = new OrderDlg( this); + private ExtOrdDlg m_extOrdDlg = new ExtOrdDlg( m_orderDlg); + private AccountDlg m_acctDlg = new AccountDlg(this); + private HashMap m_mapRequestToMktDepthDlg = new HashMap(); + private NewsBulletinDlg m_newsBulletinDlg = new NewsBulletinDlg(this); + private ScannerDlg m_scannerDlg = new ScannerDlg(this); + + String faGroupXML ; + String faProfilesXML ; + String faAliasesXML ; + public String m_FAAcctCodes; + public boolean m_bIsFAAccount = false; + + private boolean m_disconnectInProgress = false; + + SampleFrame() { + JPanel scrollingWindowDisplayPanel = new JPanel( new GridLayout( 0, 1) ); + scrollingWindowDisplayPanel.add( m_tickers); + scrollingWindowDisplayPanel.add( m_TWS); + scrollingWindowDisplayPanel.add( m_errors); + + JPanel buttonPanel = createButtonPanel(); + + getContentPane().add( scrollingWindowDisplayPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.EAST); + setSize( 600, 700); + setTitle( "Sample"); + setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE); + } + + private JPanel createButtonPanel() { + JPanel buttonPanel = new JPanel( new GridLayout( 0, 1) ); + JButton butConnect = new JButton( "Connect"); + butConnect.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onConnect(); + } + }); + JButton butDisconnect = new JButton( "Disconnect"); + butDisconnect.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onDisconnect(); + } + }); + JButton butMktData = new JButton( "Req Mkt Data"); + butMktData.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqMktData(); + } + }); + JButton butCancelMktData = new JButton( "Cancel Mkt Data"); + butCancelMktData.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelMktData(); + } + }); + JButton butMktDepth = new JButton( "Req Mkt Depth"); + butMktDepth.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqMktDepth(); + } + }); + JButton butCancelMktDepth = new JButton( "Cancel Mkt Depth"); + butCancelMktDepth.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelMktDepth(); + } + }); + JButton butHistoricalData = new JButton( "Historical Data"); + butHistoricalData.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onHistoricalData(); + } + }); + JButton butCancelHistoricalData = new JButton( "Cancel Hist. Data"); + butCancelHistoricalData.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelHistoricalData(); + } + }); + JButton butRealTimeBars = new JButton( "Req Real Time Bars"); + butRealTimeBars.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqRealTimeBars(); + } + }); + JButton butCancelRealTimeBars = new JButton( "Cancel Real Time Bars"); + butCancelRealTimeBars.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelRealTimeBars(); + } + }); + JButton butCurrentTime = new JButton( "Req Current Time"); + butCurrentTime.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqCurrentTime(); + } + }); + JButton butScanner = new JButton( "Market Scanner"); + butScanner.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onScanner(); + } + }); + JButton butOpenOrders = new JButton( "Req Open Orders"); + butOpenOrders.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqOpenOrders(); + } + }); + JButton butCalculateImpliedVolatility = new JButton( "Calculate Implied Volatility"); + butCalculateImpliedVolatility.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCalculateImpliedVolatility(); + } + }); + JButton butCancelCalculateImpliedVolatility = new JButton( "Cancel Calc Impl Volatility"); + butCancelCalculateImpliedVolatility.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelCalculateImpliedVolatility(); + } + }); + JButton butCalculateOptionPrice = new JButton( "Calculate Option Price"); + butCalculateOptionPrice.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCalculateOptionPrice(); + } + }); + JButton butCancelCalculateOptionPrice = new JButton( "Cancel Calc Opt Price"); + butCancelCalculateOptionPrice.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelCalculateOptionPrice(); + } + }); + JButton butWhatIfOrder = new JButton( "What If"); + butWhatIfOrder.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onWhatIfOrder(); + } + }); + JButton butPlaceOrder = new JButton( "Place Order"); + butPlaceOrder.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onPlaceOrder(); + } + }); + JButton butCancelOrder = new JButton( "Cancel Order"); + butCancelOrder.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelOrder(); + } + }); + JButton butExerciseOptions = new JButton( "Exercise Options"); + butExerciseOptions.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onExerciseOptions(); + } + }); + JButton butExtendedOrder = new JButton( "Extended"); + butExtendedOrder.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onExtendedOrder(); + } + }); + JButton butAcctData = new JButton( "Req Acct Data"); + butAcctData.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqAcctData(); + } + }); + JButton butContractData = new JButton( "Req Contract Data"); + butContractData.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqContractData(); + } + }); + JButton butExecutions = new JButton( "Req Executions"); + butExecutions.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqExecutions(); + } + }); + JButton butNewsBulletins = new JButton( "Req News Bulletins"); + butNewsBulletins.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqNewsBulletins(); + } + }); + JButton butServerLogging = new JButton( "Server Logging"); + butServerLogging.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onServerLogging(); + } + }); + JButton butAllOpenOrders = new JButton( "Req All Open Orders"); + butAllOpenOrders.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqAllOpenOrders(); + } + }); + JButton butAutoOpenOrders = new JButton( "Req Auto Open Orders"); + butAutoOpenOrders.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqAutoOpenOrders(); + } + }); + JButton butManagedAccts = new JButton( "Req Accounts"); + butManagedAccts.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqManagedAccts(); + } + }); + JButton butFinancialAdvisor = new JButton( "Financial Advisor"); + butFinancialAdvisor.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onFinancialAdvisor(); + } + }); + JButton butGlobalCancel = new JButton( "Global Cancel"); + butGlobalCancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onGlobalCancel(); + } + }); + JButton butReqMarketDataType = new JButton( "Req Market Data Type"); + butReqMarketDataType.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReqMarketDataType(); + } + }); + + JButton butClear = new JButton( "Clear"); + butClear.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onClear(); + } + }); + JButton butClose = new JButton( "Close"); + butClose.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onClose(); + } + }); + + + buttonPanel.add( new JPanel() ); + buttonPanel.add( butConnect); + buttonPanel.add( butDisconnect); + + buttonPanel.add( new JPanel() ); + buttonPanel.add( butMktData); + buttonPanel.add( butCancelMktData); + buttonPanel.add( butMktDepth); + buttonPanel.add( butCancelMktDepth); + buttonPanel.add( butHistoricalData); + buttonPanel.add( butCancelHistoricalData); + buttonPanel.add( butRealTimeBars); + buttonPanel.add( butCancelRealTimeBars); + buttonPanel.add( butScanner); + buttonPanel.add( butCurrentTime); + buttonPanel.add( butCalculateImpliedVolatility); + buttonPanel.add( butCancelCalculateImpliedVolatility); + buttonPanel.add( butCalculateOptionPrice); + buttonPanel.add( butCancelCalculateOptionPrice); + + buttonPanel.add( new JPanel() ); + buttonPanel.add( butWhatIfOrder); + buttonPanel.add( butPlaceOrder); + buttonPanel.add( butCancelOrder); + buttonPanel.add( butExerciseOptions); + buttonPanel.add( butExtendedOrder); + + buttonPanel.add( new JPanel() ); + buttonPanel.add( butContractData ); + buttonPanel.add( butOpenOrders); + buttonPanel.add( butAllOpenOrders); + buttonPanel.add( butAutoOpenOrders); + buttonPanel.add( butAcctData ); + buttonPanel.add( butExecutions ); + buttonPanel.add( butNewsBulletins ); + buttonPanel.add( butServerLogging ); + buttonPanel.add( butManagedAccts ); + buttonPanel.add( butFinancialAdvisor ) ; + buttonPanel.add( butGlobalCancel ) ; + buttonPanel.add( butReqMarketDataType ) ; + + buttonPanel.add( new JPanel() ); + buttonPanel.add( butClear ); + buttonPanel.add( butClose ); + + return buttonPanel; + } + + void onConnect() { + m_bIsFAAccount = false; + // get connection parameters + ConnectDlg dlg = new ConnectDlg( this); + dlg.setVisible(true); + if( !dlg.m_rc) { + return; + } + + // connect to TWS + m_disconnectInProgress = false; + + m_client.eConnect( dlg.m_retIpAddress, dlg.m_retPort, dlg.m_retClientId); + if (m_client.isConnected()) { + m_TWS.add("Connected to Tws server version " + + m_client.serverVersion() + " at " + + m_client.TwsConnectionTime()); + } + } + + void onDisconnect() { + // disconnect from TWS + m_disconnectInProgress = true; + m_client.eDisconnect(); + } + + void onReqMktData() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // req mkt data + m_client.reqMktData( m_orderDlg.m_id, m_orderDlg.m_contract, + m_orderDlg.m_genericTicks, m_orderDlg.m_snapshotMktData); + } + + void onReqRealTimeBars() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + // req mkt data + m_client.reqRealTimeBars( m_orderDlg.m_id, m_orderDlg.m_contract, + 5 /* TODO: parse and use m_orderDlg.m_barSizeSetting */, + m_orderDlg.m_whatToShow, m_orderDlg.m_useRTH > 0); + } + + void onCancelRealTimeBars() { + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + // cancel market data + m_client.cancelRealTimeBars( m_orderDlg.m_id ); + } + + void onScanner() { + m_scannerDlg.show(); + if (m_scannerDlg.m_userSelection == ScannerDlg.CANCEL_SELECTION) { + m_client.cancelScannerSubscription(m_scannerDlg.m_id); + } + else if (m_scannerDlg.m_userSelection == ScannerDlg.SUBSCRIBE_SELECTION) { + m_client.reqScannerSubscription(m_scannerDlg.m_id, + m_scannerDlg.m_subscription); + } + else if (m_scannerDlg.m_userSelection == ScannerDlg.REQUEST_PARAMETERS_SELECTION) { + m_client.reqScannerParameters(); + } + } + + void onReqCurrentTime() { + m_client.reqCurrentTime(); + } + + void onHistoricalData() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + if( Util.StringCompare( m_orderDlg.m_whatToShow, "estimates" ) == 0 || + Util.StringCompare( m_orderDlg.m_whatToShow, "finstat" ) == 0 || + Util.StringCompare( m_orderDlg.m_whatToShow, "snapshot" ) == 0 ) { + + m_client.reqFundamentalData(m_orderDlg.m_id, m_orderDlg.m_contract, + /* reportType */ m_orderDlg.m_whatToShow); + return; + } + + // req historical data + m_client.reqHistoricalData( m_orderDlg.m_id, m_orderDlg.m_contract, + m_orderDlg.m_backfillEndTime, m_orderDlg.m_backfillDuration, + m_orderDlg.m_barSizeSetting, m_orderDlg.m_whatToShow, + m_orderDlg.m_useRTH, m_orderDlg.m_formatDate ); + } + + void onCancelHistoricalData() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + if( Util.StringCompare( m_orderDlg.m_whatToShow, "estimates" ) == 0 || + Util.StringCompare( m_orderDlg.m_whatToShow, "finstat" ) == 0 || + Util.StringCompare( m_orderDlg.m_whatToShow, "snapshot" ) == 0 ) { + + m_client.cancelFundamentalData(m_orderDlg.m_id); + return; + } + + // cancel historical data + m_client.cancelHistoricalData( m_orderDlg.m_id ); + } + + void onReqContractData() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // req mkt data + m_client.reqContractDetails( m_orderDlg.m_id, m_orderDlg.m_contract ); + } + + void onReqMktDepth() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + final Integer dialogId = m_orderDlg.m_id; + MktDepthDlg depthDialog = m_mapRequestToMktDepthDlg.get(dialogId); + if ( depthDialog == null ) { + depthDialog = new MktDepthDlg("Market Depth ID ["+dialogId+"]", this); + m_mapRequestToMktDepthDlg.put(dialogId, depthDialog); + + // cleanup the map after depth dialog is closed so it does not linger or leak memory + depthDialog.addWindowListener(new WindowAdapter() { + @Override public void windowClosed(WindowEvent e) { + m_mapRequestToMktDepthDlg.remove(dialogId); + } + }); + } + + depthDialog.setParams( m_client, dialogId); + + // req mkt data + m_client.reqMktDepth( dialogId, m_orderDlg.m_contract, m_orderDlg.m_marketDepthRows ); + depthDialog.setVisible(true); + } + + void onCancelMktData() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // cancel market data + m_client.cancelMktData( m_orderDlg.m_id ); + } + + void onCancelMktDepth() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // cancel market data + m_client.cancelMktDepth( m_orderDlg.m_id ); + } + + void onReqOpenOrders() { + m_client.reqOpenOrders(); + } + + void onWhatIfOrder() { + placeOrder(true); + } + + void onPlaceOrder() { + placeOrder(false); + } + + void placeOrder(boolean whatIf) { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + Order order = m_orderDlg.m_order; + + // save old and set new value of whatIf attribute + boolean savedWhatIf = order.m_whatIf; + order.m_whatIf = whatIf; + + // place order + m_client.placeOrder( m_orderDlg.m_id, m_orderDlg.m_contract, order ); + + // restore whatIf attribute + order.m_whatIf = savedWhatIf; + } + + void onExerciseOptions() { + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // cancel order + m_client.exerciseOptions( m_orderDlg.m_id, m_orderDlg.m_contract, + m_orderDlg.m_exerciseAction, m_orderDlg.m_exerciseQuantity, + m_orderDlg.m_order.m_account, m_orderDlg.m_override); + } + + void onCancelOrder() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // cancel order + m_client.cancelOrder( m_orderDlg.m_id ); + } + + void onExtendedOrder() { + //Show the extended order attributes dialog + m_extOrdDlg.setVisible(true); + if( !m_extOrdDlg.m_rc ) { + return; + } + + // Copy over the extended order details + copyExtendedOrderDetails( m_orderDlg.m_order, m_extOrdDlg.m_order); + } + + void onReqAcctData() { + AcctUpdatesDlg dlg = new AcctUpdatesDlg(this); + + dlg.setVisible(true); + + if ( dlg.m_subscribe) { + m_acctDlg.accountDownloadBegin(dlg.m_acctCode); + } + + m_client.reqAccountUpdates( dlg.m_subscribe, dlg.m_acctCode); + + if ( m_client.isConnected() && dlg.m_subscribe) { + m_acctDlg.reset(); + m_acctDlg.setVisible(true); + } + } + + void onFinancialAdvisor() { + faGroupXML = faProfilesXML = faAliasesXML = null ; + faError = false ; + m_client.requestFA(EClientSocket.GROUPS) ; + m_client.requestFA(EClientSocket.PROFILES) ; + m_client.requestFA(EClientSocket.ALIASES) ; + } + + void onServerLogging() { + // get server logging level + LogConfigDlg dlg = new LogConfigDlg( this); + dlg.setVisible(true); + if( !dlg.m_rc) { + return; + } + + // connect to TWS + m_client.setServerLogLevel( dlg.m_serverLogLevel); + } + + void onReqAllOpenOrders() { + // request list of all open orders + m_client.reqAllOpenOrders(); + } + + void onReqAutoOpenOrders() { + // request to automatically bind any newly entered TWS orders + // to this API client. NOTE: TWS orders can only be bound to + // client's with clientId=0. + m_client.reqAutoOpenOrders( true); + } + + void onReqManagedAccts() { + // request the list of managed accounts + m_client.reqManagedAccts(); + } + + void onClear() { + m_tickers.clear(); + m_TWS.clear(); + m_errors.clear(); + } + + void onClose() { + System.exit(1); + } + + void onReqExecutions() { + ExecFilterDlg dlg = new ExecFilterDlg(this); + + dlg.setVisible(true); + if ( dlg.m_rc ) { + // request execution reports based on the supplied filter criteria + m_client.reqExecutions( dlg.m_reqId, dlg.m_execFilter); + } + } + + void onReqNewsBulletins() { + // run m_newsBulletinDlg + m_newsBulletinDlg.setVisible(true); + if( !m_newsBulletinDlg.m_rc ) { + return; + } + + if ( m_newsBulletinDlg.m_subscribe ) { + m_client.reqNewsBulletins( m_newsBulletinDlg.m_allMsgs); + } + else { + m_client.cancelNewsBulletins(); + } + } + + void onCalculateImpliedVolatility() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + m_client.calculateImpliedVolatility( m_orderDlg.m_id, m_orderDlg.m_contract, + m_orderDlg.m_order.m_lmtPrice, m_orderDlg.m_order.m_auxPrice); + } + + void onCancelCalculateImpliedVolatility() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + m_client.cancelCalculateImpliedVolatility( m_orderDlg.m_id); + } + + void onCalculateOptionPrice() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + m_client.calculateOptionPrice( m_orderDlg.m_id, m_orderDlg.m_contract, + m_orderDlg.m_order.m_lmtPrice, m_orderDlg.m_order.m_auxPrice); + } + + void onCancelCalculateOptionPrice() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + m_client.cancelCalculateOptionPrice( m_orderDlg.m_id); + } + + void onGlobalCancel() { + m_client.reqGlobalCancel(); + } + + void onReqMarketDataType() { + // run m_orderDlg + m_orderDlg.show(); + if( !m_orderDlg.m_rc ) { + return; + } + + // req mkt data type + m_client.reqMarketDataType( m_orderDlg.m_marketDataType); + } + + public void tickPrice( int tickerId, int field, double price, int canAutoExecute) { + // received price tick + String msg = EWrapperMsgGenerator.tickPrice( tickerId, field, price, canAutoExecute); + m_tickers.add( msg ); + } + + public void tickOptionComputation( int tickerId, int field, double impliedVol, double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + // received computation tick + String msg = EWrapperMsgGenerator.tickOptionComputation( tickerId, field, impliedVol, delta, optPrice, pvDividend, + gamma, vega, theta, undPrice); + m_tickers.add( msg ); + } + + public void tickSize( int tickerId, int field, int size) { + // received size tick + String msg = EWrapperMsgGenerator.tickSize( tickerId, field, size); + m_tickers.add( msg); + } + + public void tickGeneric( int tickerId, int tickType, double value) { + // received generic tick + String msg = EWrapperMsgGenerator.tickGeneric(tickerId, tickType, value); + m_tickers.add( msg); + } + + public void tickString( int tickerId, int tickType, String value) { + // received String tick + String msg = EWrapperMsgGenerator.tickString(tickerId, tickType, value); + m_tickers.add( msg); + } + + public void tickSnapshotEnd(int tickerId) { + String msg = EWrapperMsgGenerator.tickSnapshotEnd(tickerId); + m_tickers.add( msg) ; + } + + public void tickEFP(int tickerId, int tickType, double basisPoints, String formattedBasisPoints, + double impliedFuture, int holdDays, String futureExpiry, double dividendImpact, + double dividendsToExpiry) { + // received EFP tick + String msg = EWrapperMsgGenerator.tickEFP(tickerId, tickType, basisPoints, formattedBasisPoints, + impliedFuture, holdDays, futureExpiry, dividendImpact, dividendsToExpiry); + m_tickers.add(msg); + } + + public void orderStatus( int orderId, String status, int filled, int remaining, + double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + // received order status + String msg = EWrapperMsgGenerator.orderStatus( orderId, status, filled, remaining, + avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld); + m_TWS.add( msg); + + // make sure id for next order is at least orderId+1 + m_orderDlg.setIdAtLeast( orderId + 1); + } + + public void openOrder( int orderId, Contract contract, Order order, OrderState orderState) { + // received open order + String msg = EWrapperMsgGenerator.openOrder( orderId, contract, order, orderState); + m_TWS.add( msg) ; + } + + public void openOrderEnd() { + // received open order end + String msg = EWrapperMsgGenerator.openOrderEnd(); + m_TWS.add( msg) ; + } + + public void contractDetails(int reqId, ContractDetails contractDetails) { + String msg = EWrapperMsgGenerator.contractDetails( reqId, contractDetails); + m_TWS.add(msg); + } + + public void contractDetailsEnd(int reqId) { + String msg = EWrapperMsgGenerator.contractDetailsEnd(reqId); + m_TWS.add(msg); + } + + public void scannerData(int reqId, int rank, ContractDetails contractDetails, + String distance, String benchmark, String projection, String legsStr) { + String msg = EWrapperMsgGenerator.scannerData(reqId, rank, contractDetails, distance, + benchmark, projection, legsStr); + m_tickers.add(msg); + } + + public void scannerDataEnd(int reqId) { + String msg = EWrapperMsgGenerator.scannerDataEnd(reqId); + m_tickers.add(msg); + } + + public void bondContractDetails(int reqId, ContractDetails contractDetails) + { + String msg = EWrapperMsgGenerator.bondContractDetails( reqId, contractDetails); + m_TWS.add(msg); + } + + public void execDetails(int reqId, Contract contract, Execution execution) + { + String msg = EWrapperMsgGenerator.execDetails(reqId, contract, execution); + m_TWS.add(msg); + } + + public void execDetailsEnd(int reqId) + { + String msg = EWrapperMsgGenerator.execDetailsEnd(reqId); + m_TWS.add(msg); + } + + public void updateMktDepth( int tickerId, int position, int operation, + int side, double price, int size) { + + MktDepthDlg depthDialog = m_mapRequestToMktDepthDlg.get(tickerId); + if ( depthDialog != null ) { + depthDialog.updateMktDepth( tickerId, position, "", operation, side, price, size); + } else { + System.err.println("cannot find dialog that corresponds to request id ["+tickerId+"]"); + } + + + } + + public void updateMktDepthL2( int tickerId, int position, String marketMaker, + int operation, int side, double price, int size) { + MktDepthDlg depthDialog = m_mapRequestToMktDepthDlg.get(tickerId); + if ( depthDialog != null ) { + depthDialog.updateMktDepth( tickerId, position, marketMaker, operation, side, price, size); + } else { + System.err.println("cannot find dialog that corresponds to request id ["+tickerId+"]"); + } + } + + public void nextValidId( int orderId) { + // received next valid order id + String msg = EWrapperMsgGenerator.nextValidId( orderId); + m_TWS.add(msg) ; + m_orderDlg.setIdAtLeast( orderId); + } + + public void error(Exception ex) { + // do not report exceptions if we initiated disconnect + if (!m_disconnectInProgress) { + String msg = EWrapperMsgGenerator.error(ex); + Main.inform( this, msg); + } + } + + public void error( String str) { + String msg = EWrapperMsgGenerator.error(str); + m_errors.add( msg); + } + + public void error( int id, int errorCode, String errorMsg) { + // received error + String msg = EWrapperMsgGenerator.error(id, errorCode, errorMsg); + m_errors.add( msg); + for (int ctr=0; ctr < faErrorCodes.length; ctr++) { + faError |= (errorCode == faErrorCodes[ctr]); + } + if (errorCode == MktDepthDlg.MKT_DEPTH_DATA_RESET) { + + MktDepthDlg depthDialog = m_mapRequestToMktDepthDlg.get(id); + if ( depthDialog != null ) { + depthDialog.reset(); + } else { + System.err.println("cannot find dialog that corresponds to request id ["+id+"]"); + } + } + } + + public void connectionClosed() { + String msg = EWrapperMsgGenerator.connectionClosed(); + Main.inform( this, msg); + } + + public void updateAccountValue(String key, String value, + String currency, String accountName) { + m_acctDlg.updateAccountValue(key, value, currency, accountName); + } + + public void updatePortfolio(Contract contract, int position, double marketPrice, + double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, + String accountName) { + m_acctDlg.updatePortfolio(contract, position, marketPrice, marketValue, + averageCost, unrealizedPNL, realizedPNL, accountName); + } + + public void updateAccountTime(String timeStamp) { + m_acctDlg.updateAccountTime(timeStamp); + } + + public void accountDownloadEnd(String accountName) { + m_acctDlg.accountDownloadEnd( accountName); + + String msg = EWrapperMsgGenerator.accountDownloadEnd( accountName); + m_TWS.add( msg); + } + + public void updateNewsBulletin( int msgId, int msgType, String message, String origExchange) { + String msg = EWrapperMsgGenerator.updateNewsBulletin(msgId, msgType, message, origExchange); + JOptionPane.showMessageDialog(this, msg, "IB News Bulletin", JOptionPane.INFORMATION_MESSAGE); + } + + public void managedAccounts( String accountsList) { + m_bIsFAAccount = true; + m_FAAcctCodes = accountsList; + String msg = EWrapperMsgGenerator.managedAccounts(accountsList); + m_TWS.add( msg); + } + + public void historicalData(int reqId, String date, double open, double high, double low, + double close, int volume, int count, double WAP, boolean hasGaps) { + String msg = EWrapperMsgGenerator.historicalData(reqId, date, open, high, low, close, volume, count, WAP, hasGaps); + m_tickers.add( msg ); + } + public void realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count) { + String msg = EWrapperMsgGenerator.realtimeBar(reqId, time, open, high, low, close, volume, wap, count); + m_tickers.add( msg ); + } + public void scannerParameters(String xml) { + displayXML(EWrapperMsgGenerator.SCANNER_PARAMETERS, xml); + } + + public void currentTime(long time) { + String msg = EWrapperMsgGenerator.currentTime(time); + m_TWS.add(msg); + } + public void fundamentalData(int reqId, String data) { + String msg = EWrapperMsgGenerator.fundamentalData(reqId, data); + m_tickers.add(msg); + } + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + String msg = EWrapperMsgGenerator.deltaNeutralValidation(reqId, underComp); + m_TWS.add(msg); + } + + void displayXML(String title, String xml) { + m_TWS.add(title); + m_TWS.addText(xml); + } + + public void receiveFA(int faDataType, String xml) { + displayXML(EWrapperMsgGenerator.FINANCIAL_ADVISOR + " " + EClientSocket.faMsgTypeName(faDataType), xml); + switch (faDataType) { + case EClientSocket.GROUPS: + faGroupXML = xml ; + break ; + case EClientSocket.PROFILES: + faProfilesXML = xml ; + break ; + case EClientSocket.ALIASES: + faAliasesXML = xml ; + break ; + } + + if (!faError && + !(faGroupXML == null || faProfilesXML == null || faAliasesXML == null)) { + FinancialAdvisorDlg dlg = new FinancialAdvisorDlg(this); + dlg.receiveInitialXML(faGroupXML, faProfilesXML, faAliasesXML); + dlg.setVisible(true); + + if (!dlg.m_rc) { + return; + } + + m_client.replaceFA( EClientSocket.GROUPS, dlg.groupsXML ); + m_client.replaceFA( EClientSocket.PROFILES, dlg.profilesXML ); + m_client.replaceFA( EClientSocket.ALIASES, dlg.aliasesXML ); + + } + } + + public void marketDataType(int reqId, int marketDataType) { + String msg = EWrapperMsgGenerator.marketDataType(reqId, marketDataType); + m_tickers.add(msg); + } + + private void copyExtendedOrderDetails( Order destOrder, Order srcOrder) { + destOrder.m_tif = srcOrder.m_tif; + destOrder.m_ocaGroup = srcOrder.m_ocaGroup; + destOrder.m_ocaType = srcOrder.m_ocaType; + destOrder.m_openClose = srcOrder.m_openClose; + destOrder.m_origin = srcOrder.m_origin; + destOrder.m_orderRef = srcOrder.m_orderRef; + destOrder.m_transmit = srcOrder.m_transmit; + destOrder.m_parentId = srcOrder.m_parentId; + destOrder.m_blockOrder = srcOrder.m_blockOrder; + destOrder.m_sweepToFill = srcOrder.m_sweepToFill; + destOrder.m_displaySize = srcOrder.m_displaySize; + destOrder.m_triggerMethod = srcOrder.m_triggerMethod; + destOrder.m_outsideRth = srcOrder.m_outsideRth; + destOrder.m_hidden = srcOrder.m_hidden; + destOrder.m_discretionaryAmt = srcOrder.m_discretionaryAmt; + destOrder.m_goodAfterTime = srcOrder.m_goodAfterTime; + destOrder.m_shortSaleSlot = srcOrder.m_shortSaleSlot; + destOrder.m_designatedLocation = srcOrder.m_designatedLocation; + destOrder.m_exemptCode = srcOrder.m_exemptCode; + destOrder.m_ocaType = srcOrder.m_ocaType; + destOrder.m_rule80A = srcOrder.m_rule80A; + destOrder.m_allOrNone = srcOrder.m_allOrNone; + destOrder.m_minQty = srcOrder.m_minQty; + destOrder.m_percentOffset = srcOrder.m_percentOffset; + destOrder.m_eTradeOnly = srcOrder.m_eTradeOnly; + destOrder.m_firmQuoteOnly = srcOrder.m_firmQuoteOnly; + destOrder.m_nbboPriceCap = srcOrder.m_nbboPriceCap; + destOrder.m_optOutSmartRouting = srcOrder.m_optOutSmartRouting; + destOrder.m_auctionStrategy = srcOrder.m_auctionStrategy; + destOrder.m_startingPrice = srcOrder.m_startingPrice; + destOrder.m_stockRefPrice = srcOrder.m_stockRefPrice; + destOrder.m_delta = srcOrder.m_delta; + destOrder.m_stockRangeLower = srcOrder.m_stockRangeLower; + destOrder.m_stockRangeUpper = srcOrder.m_stockRangeUpper; + destOrder.m_overridePercentageConstraints = srcOrder.m_overridePercentageConstraints; + destOrder.m_volatility = srcOrder.m_volatility; + destOrder.m_volatilityType = srcOrder.m_volatilityType; + destOrder.m_deltaNeutralOrderType = srcOrder.m_deltaNeutralOrderType; + destOrder.m_deltaNeutralAuxPrice = srcOrder.m_deltaNeutralAuxPrice; + destOrder.m_deltaNeutralConId = srcOrder.m_deltaNeutralConId; + destOrder.m_deltaNeutralSettlingFirm = srcOrder.m_deltaNeutralSettlingFirm; + destOrder.m_deltaNeutralClearingAccount = srcOrder.m_deltaNeutralClearingAccount; + destOrder.m_deltaNeutralClearingIntent = srcOrder.m_deltaNeutralClearingIntent; + destOrder.m_continuousUpdate = srcOrder.m_continuousUpdate; + destOrder.m_referencePriceType = srcOrder.m_referencePriceType; + destOrder.m_trailStopPrice = srcOrder.m_trailStopPrice; + destOrder.m_scaleInitLevelSize = srcOrder.m_scaleInitLevelSize; + destOrder.m_scaleSubsLevelSize = srcOrder.m_scaleSubsLevelSize; + destOrder.m_scalePriceIncrement = srcOrder.m_scalePriceIncrement; + destOrder.m_hedgeType = srcOrder.m_hedgeType; + destOrder.m_hedgeParam = srcOrder.m_hedgeParam; + destOrder.m_account = srcOrder.m_account; + destOrder.m_settlingFirm = srcOrder.m_settlingFirm; + destOrder.m_clearingAccount = srcOrder.m_clearingAccount; + destOrder.m_clearingIntent = srcOrder.m_clearingIntent; + } +} diff --git a/ib/src/main/java/TestJavaClient/ScannerDlg.java b/ib/src/main/java/TestJavaClient/ScannerDlg.java new file mode 100644 index 00000000..99f59dc2 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/ScannerDlg.java @@ -0,0 +1,250 @@ +/* + * ScannerDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import com.ib.client.ScannerSubscription; + +public class ScannerDlg extends JDialog { + public static final int NO_SELECTION = 0; + public static final int SUBSCRIBE_SELECTION = 1; + public static final int CANCEL_SELECTION = 2; + public static final int REQUEST_PARAMETERS_SELECTION = 3; + + public int m_userSelection = NO_SELECTION; + public int m_id; + public ScannerSubscription m_subscription = new ScannerSubscription(); + + private JTextField m_Id = new JTextField( "0"); + private JTextField m_numberOfRows = new JTextField("10"); + private JTextField m_instrument = new JTextField("STK"); + private JTextField m_locationCode = new JTextField("STK.US.MAJOR"); + private JTextField m_scanCode = new JTextField("HIGH_OPT_VOLUME_PUT_CALL_RATIO"); + private JTextField m_abovePrice = new JTextField("3"); + private JTextField m_belowPrice = new JTextField(); + private JTextField m_aboveVolume = new JTextField("0"); + private JTextField m_averageOptionVolumeAbove = new JTextField("0"); + private JTextField m_marketCapAbove = new JTextField("100000000"); + private JTextField m_marketCapBelow = new JTextField(); + private JTextField m_moodyRatingAbove = new JTextField(); + private JTextField m_moodyRatingBelow = new JTextField(); + private JTextField m_spRatingAbove = new JTextField(); + private JTextField m_spRatingBelow = new JTextField(); + private JTextField m_maturityDateAbove = new JTextField(); + private JTextField m_maturityDateBelow = new JTextField(); + private JTextField m_couponRateAbove = new JTextField(); + private JTextField m_couponRateBelow = new JTextField(); + private JTextField m_excludeConvertible = new JTextField("0"); + private JTextField m_scannerSettingPairs = new JTextField("Annual,true"); + private JTextField m_stockTypeFilter = new JTextField("ALL"); + + private JButton m_requestParameters = new JButton( "Request Parameters"); + private JButton m_subscribe = new JButton( "Subscribe"); + private JButton m_cancel = new JButton( "Cancel Subscription"); + private SampleFrame m_parent; + + private static final int COL1_WIDTH = 30 ; + private static final int COL2_WIDTH = 100 - COL1_WIDTH ; + + private static void addGBComponent(IBGridBagPanel panel, Component comp, + GridBagConstraints gbc, int weightx, int gridwidth) + { + gbc.weightx = weightx; + gbc.gridwidth = gridwidth; + panel.setConstraints(comp, gbc); + panel.add(comp, gbc); + } + + public ScannerDlg( SampleFrame owner) { + super( owner, true); + + m_parent = owner; + setTitle( "Sample"); + + java.awt.GridBagConstraints gbc = new java.awt.GridBagConstraints() ; + gbc.fill = gbc.BOTH ; + gbc.anchor = gbc.CENTER ; + gbc.weighty = 100 ; + gbc.fill = GridBagConstraints.BOTH ; + gbc.gridheight = 1 ; + // create id panel + IBGridBagPanel pId = new IBGridBagPanel(); + pId.setBorder( BorderFactory.createTitledBorder( "Message Id") ); + + addGBComponent(pId, new JLabel( "Id"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(pId, m_Id, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + // create contract panel + IBGridBagPanel pSubscriptionDetails = new IBGridBagPanel(); + pSubscriptionDetails.setBorder( BorderFactory.createTitledBorder( "Subscription Info") ); + addGBComponent(pSubscriptionDetails, new JLabel( "Number of Rows"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_numberOfRows, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Instrument"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_instrument, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Location Code"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_locationCode, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Scan Code"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_scanCode , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Above Price"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_abovePrice , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Below Price"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_belowPrice , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Above Volume"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_aboveVolume , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Avg Option Volume Above"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_averageOptionVolumeAbove, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Market Cap Above"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_marketCapAbove , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Market Cap Below"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_marketCapBelow , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Moody Rating Above"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_moodyRatingAbove , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Moody Rating Below"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_moodyRatingBelow , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "S & P Rating Above"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_spRatingAbove , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "S & P Rating Below"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_spRatingBelow , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Maturity Date Above"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_maturityDateAbove , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Maturity Date Below"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_maturityDateBelow , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Coupon Rate Above"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_couponRateAbove , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Coupon Rate Below"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_couponRateBelow , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Exclude Convertible"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_excludeConvertible , gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Scanner Setting Pairs"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_scannerSettingPairs, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + addGBComponent(pSubscriptionDetails, new JLabel( "Stock Type Filter"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE ); + addGBComponent(pSubscriptionDetails, m_stockTypeFilter, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_requestParameters); + buttonPanel.add( m_subscribe); + buttonPanel.add( m_cancel); + + m_requestParameters.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onRequestParameters(); + } + }); + m_subscribe.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onSubscribe(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancelSubscription(); + } + }); + + // create top panel + JPanel topPanel = new JPanel(); + topPanel.setLayout( new BoxLayout( topPanel, BoxLayout.Y_AXIS) ); + topPanel.add( pId); + topPanel.add( pSubscriptionDetails); + + // create dlg box + getContentPane().add( topPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + + pack(); + } + + private static String pad( int val) { + return val < 10 ? "0" + val : "" + val; + } + + private double parseDouble(JTextField textfield) { + try { + return Double.parseDouble(textfield.getText().trim()); + } + catch (Exception ex) { + return Double.MAX_VALUE; + } + } + + private int parseInt(JTextField textfield) { + try { + return Integer.parseInt(textfield.getText().trim()); + } + catch (Exception ex) { + return Integer.MAX_VALUE; + } + } + + + void onSubscribe() { + m_userSelection = NO_SELECTION; + + try { + // set id + m_id = Integer.parseInt( m_Id.getText().trim() ); + m_subscription.numberOfRows(parseInt(m_numberOfRows)); + m_subscription.instrument(m_instrument.getText().trim()); + m_subscription.locationCode(m_locationCode.getText().trim() ); + m_subscription.scanCode(m_scanCode.getText().trim() ); + m_subscription.abovePrice(parseDouble(m_abovePrice)); + m_subscription.belowPrice(parseDouble(m_belowPrice)); + m_subscription.aboveVolume(parseInt(m_aboveVolume)); + int avgOptVolume = parseInt(m_averageOptionVolumeAbove); + // with Integer.MAX_VALUE creates filter in TWS + m_subscription.averageOptionVolumeAbove(avgOptVolume!= Integer.MAX_VALUE ? avgOptVolume : Integer.MIN_VALUE); + m_subscription.marketCapAbove(parseDouble(m_marketCapAbove)); + m_subscription.marketCapBelow(parseDouble(m_marketCapBelow)); + m_subscription.moodyRatingAbove(m_moodyRatingAbove.getText().trim()); + m_subscription.moodyRatingBelow(m_moodyRatingBelow.getText().trim()); + m_subscription.spRatingAbove(m_spRatingAbove.getText().trim()); + m_subscription.spRatingBelow(m_spRatingBelow.getText().trim()); + m_subscription.maturityDateAbove(m_maturityDateAbove.getText().trim()); + m_subscription.maturityDateBelow(m_maturityDateBelow.getText().trim()); + m_subscription.couponRateAbove(parseDouble(m_couponRateAbove)); + m_subscription.couponRateBelow(parseDouble(m_couponRateBelow)); + m_subscription.excludeConvertible(m_excludeConvertible.getText().trim()); + m_subscription.scannerSettingPairs(m_scannerSettingPairs.getText().trim()); + // m_subscription.stockTypeFilter(m_stockTypeFilter.getText().trim()); Peter ??? + } + catch( Exception e) { + Main.inform( this, "Error - " + e); + return; + } + + m_userSelection = SUBSCRIBE_SELECTION; + setVisible( false); + } + + void onRequestParameters() { + m_userSelection = REQUEST_PARAMETERS_SELECTION; + setVisible( false); + } + + void onCancelSubscription() { + m_userSelection = CANCEL_SELECTION; + m_id = Integer.parseInt( m_Id.getText().trim() ); + setVisible( false); + } + + public void show() { + m_userSelection = NO_SELECTION; + super.show(); + } +} \ No newline at end of file diff --git a/ib/src/main/java/TestJavaClient/SmartComboRoutingParamsDlg.java b/ib/src/main/java/TestJavaClient/SmartComboRoutingParamsDlg.java new file mode 100644 index 00000000..d9ed5453 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/SmartComboRoutingParamsDlg.java @@ -0,0 +1,236 @@ +/* + * + * SmartComboRoutingParamsDlg.java + * + */ +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.GridLayout; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Vector; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.table.AbstractTableModel; + +import com.ib.client.Order; +import com.ib.client.TagValue; + +public class SmartComboRoutingParamsDlg extends JDialog { + + private Order m_order; + + private Vector m_smartComboRoutingParams; + + private JTextField m_tag = new JTextField( ""); + private JTextField m_value = new JTextField( ""); + + private JButton m_addParam = new JButton( "Add"); + private JButton m_removeParam = new JButton( "Remove"); + + private JButton m_ok = new JButton( "OK"); + private JButton m_cancel = new JButton( "Cancel"); + + private SmartComboRoutingParamModel m_paramModel = new SmartComboRoutingParamModel(); + private JTable m_paramTable = new JTable(m_paramModel); + private JScrollPane m_paramPane = new JScrollPane(m_paramTable); + + public SmartComboRoutingParamModel paramModel() { return m_paramModel; } + + public SmartComboRoutingParamsDlg( Order order, JDialog owner) { + super( owner, true); + + m_order = order; + + setTitle( "Smart Combo Routing Parameters"); + + // create smart combo routing params panel + JPanel pParamList = new JPanel( new GridLayout( 0, 1, 10, 10) ); + pParamList.setBorder( BorderFactory.createTitledBorder( "Smart Combo Routing Parameters") ); + + Vector smartComboRoutingParams = m_order.m_smartComboRoutingParams; + if (smartComboRoutingParams != null) { + m_paramModel.smartComboRoutingParams().addAll(smartComboRoutingParams); + } + pParamList.add( m_paramPane); + + // create add/remove panel + JPanel pParamListControl = new JPanel( new GridLayout( 0, 2, 10, 10) ); + pParamListControl.setBorder( BorderFactory.createTitledBorder( "Add / Remove") ); + pParamListControl.add( new JLabel( "Param:") ); + pParamListControl.add( m_tag); + pParamListControl.add( new JLabel( "Value:") ); + pParamListControl.add( m_value); + pParamListControl.add( m_addParam); + pParamListControl.add( m_removeParam); + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_ok); + buttonPanel.add( m_cancel); + + // create wrapper panel + JPanel topPanel = new JPanel(); + topPanel.setLayout( new BoxLayout( topPanel, BoxLayout.Y_AXIS) ); + topPanel.add( pParamList); + topPanel.add( pParamListControl); + + // create dlg box + getContentPane().add( topPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + + // create action listeners + m_addParam.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onAddParam(); + } + }); + m_removeParam.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onRemoveParam(); + } + }); + m_ok.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_cancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + setSize(250, 600); + centerOnOwner( this); + } + + public void onAddParam() { + try { + String tag = m_tag.getText(); + String value = m_value.getText(); + + m_paramModel.addParam( new TagValue(tag, value)); + } + catch( Exception e) { + reportError( "Error - ", e); + return; + } + } + + public void onRemoveParam() { + try { + if ( m_paramTable.getSelectedRowCount() != 0 ) { + int[] rows = m_paramTable.getSelectedRows(); + for ( int i=rows.length -1; i>=0 ; i-- ) { + m_paramModel.removeParam( rows[i]); + } + } + } + catch( Exception e) { + reportError( "Error - ", e); + return; + } + } + + void onOk() { + Vector smartComboRoutingParams = m_paramModel.smartComboRoutingParams(); + m_order.m_smartComboRoutingParams = smartComboRoutingParams.isEmpty() ? null : smartComboRoutingParams; + + setVisible( false); + } + + void onCancel() { + setVisible( false); + } + + + void reportError( String msg, Exception e) { + Main.inform( this, msg + " --" + e); + } + + private void centerOnOwner( Window window) { + Window owner = window.getOwner(); + if( owner == null) { + return; + } + int x = owner.getX() + ((owner.getWidth() - window.getWidth()) / 2); + int y = owner.getY() + ((owner.getHeight() - window.getHeight()) / 2); + if( x < 0) x = 0; + if( y < 0) y = 0; + window.setLocation( x, y); + } +} + +class SmartComboRoutingParamModel extends AbstractTableModel { + + private Vector m_allData = new Vector(); + + synchronized public void addParam( TagValue tagValue) + { + m_allData.add( tagValue); + fireTableDataChanged(); + } + + synchronized public void removeParam( int index) + { + m_allData.remove( index); + fireTableDataChanged(); + } + + synchronized public void reset() { + m_allData.removeAllElements(); + fireTableDataChanged(); + } + + synchronized public int getRowCount() { + return m_allData.size(); + } + + synchronized public int getColumnCount() { + return 2; + } + + synchronized public Object getValueAt(int r, int c) { + TagValue tagValue = (TagValue)m_allData.get(r); + + switch (c) { + case 0: + return tagValue.m_tag; + case 1: + return tagValue.m_value; + default: + return ""; + } + + } + + public boolean isCellEditable(int r, int c) { + return false; + } + + public String getColumnName(int c) { + switch (c) { + case 0: + return "Param"; + case 1: + return "Value"; + default: + return null; + } + } + + public Vector smartComboRoutingParams() { + return m_allData; + } +} diff --git a/ib/src/main/java/TestJavaClient/UnderCompDlg.java b/ib/src/main/java/TestJavaClient/UnderCompDlg.java new file mode 100644 index 00000000..60cb7333 --- /dev/null +++ b/ib/src/main/java/TestJavaClient/UnderCompDlg.java @@ -0,0 +1,146 @@ +/* + * UnderCompDlg.java + * + */ + +package TestJavaClient; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.GridBagConstraints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import com.ib.client.UnderComp; + +public class UnderCompDlg extends JDialog { + + private UnderComp m_underComp; + + private JTextField m_txtConId = new JTextField(); + private JTextField m_txtDelta = new JTextField(); + private JTextField m_txtPrice = new JTextField(); + + private JButton m_btnOk = new JButton( "OK"); + private JButton m_btnReset = new JButton( "Reset"); + private JButton m_btnCancel = new JButton( "Cancel"); + + private boolean m_ok = false; + private boolean m_reset = false; + + private static final int COL1_WIDTH = 30 ; + private static final int COL2_WIDTH = 100 - COL1_WIDTH ; + + public UnderCompDlg(UnderComp underComp, JDialog owner) { + super( owner, true); + + m_underComp = underComp; + + // create button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.add( m_btnOk); + buttonPanel.add( m_btnReset); + buttonPanel.add( m_btnCancel); + + // create action listeners + m_btnOk.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onOk(); + } + }); + m_btnReset.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onReset(); + } + }); + m_btnCancel.addActionListener( new ActionListener() { + public void actionPerformed( ActionEvent e) { + onCancel(); + } + }); + + java.awt.GridBagConstraints gbc = new java.awt.GridBagConstraints() ; + gbc.fill = GridBagConstraints.BOTH ; + gbc.anchor = GridBagConstraints.CENTER ; + gbc.weighty = 100 ; + gbc.fill = GridBagConstraints.BOTH ; + gbc.gridheight = 1 ; + + // create mid panel + IBGridBagPanel midPanel = new IBGridBagPanel(); + midPanel.setBorder(BorderFactory.createTitledBorder( "Under Comp")); + addGBComponent(midPanel, new JLabel( "Contract Id"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(midPanel, m_txtConId, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(midPanel, new JLabel( "Delta"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(midPanel, m_txtDelta, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + addGBComponent(midPanel, new JLabel( "Price"), gbc, COL1_WIDTH, GridBagConstraints.RELATIVE) ; + addGBComponent(midPanel, m_txtPrice, gbc, COL2_WIDTH, GridBagConstraints.REMAINDER) ; + + + m_txtConId.setText(Integer.toString(m_underComp.m_conId)); + m_txtDelta.setText(Double.toString(m_underComp.m_delta)); + m_txtPrice.setText(Double.toString(m_underComp.m_price)); + + // create dlg box + getContentPane().add( midPanel, BorderLayout.CENTER); + getContentPane().add( buttonPanel, BorderLayout.SOUTH); + setTitle( "Delta Neutral"); + pack(); + } + + + private void onOk() { + + try { + int conId = Integer.parseInt(m_txtConId.getText()); + double delta = Double.parseDouble(m_txtDelta.getText()); + double price = Double.parseDouble(m_txtPrice.getText()); + + m_underComp.m_conId = conId; + m_underComp.m_delta = delta; + m_underComp.m_price = price; + m_ok = true; + setVisible( false); + } + catch ( Exception e) { + Main.inform( this, "Error - " + e); + } + } + + private void onReset() { + m_underComp.m_conId = 0; + m_underComp.m_delta = 0; + m_underComp.m_price = 0; + m_reset = true; + setVisible( false); + } + + private void onCancel() { + setVisible( false); + } + + public boolean ok() { + return m_ok; + } + + public boolean reset() { + return m_reset; + } + + private static void addGBComponent(IBGridBagPanel panel, Component comp, + GridBagConstraints gbc, int weightx, int gridwidth) + { + gbc.weightx = weightx; + gbc.gridwidth = gridwidth; + panel.setConstraints(comp, gbc); + panel.add(comp, gbc); + } + +} diff --git a/ib/src/main/java/com/ib/client/AnyWrapper.java b/ib/src/main/java/com/ib/client/AnyWrapper.java new file mode 100644 index 00000000..c0380bec --- /dev/null +++ b/ib/src/main/java/com/ib/client/AnyWrapper.java @@ -0,0 +1,14 @@ +/* + * AnyWrapper.java + * + */ +package com.ib.client; + + +public interface AnyWrapper { + void error( Exception e); + void error( String str); + void error(int id, int errorCode, String errorMsg); + void connectionClosed(); +} + diff --git a/ib/src/main/java/com/ib/client/AnyWrapperMsgGenerator.java b/ib/src/main/java/com/ib/client/AnyWrapperMsgGenerator.java new file mode 100644 index 00000000..dac517d2 --- /dev/null +++ b/ib/src/main/java/com/ib/client/AnyWrapperMsgGenerator.java @@ -0,0 +1,19 @@ +package com.ib.client; + +public class AnyWrapperMsgGenerator { + public static String error( Exception ex) { return "Error - " + ex;} + public static String error( String str) { return str;} + + public static String error(int id, int errorCode, String errorMsg) { + String err = Integer.toString(id); + err += " | "; + err += Integer.toString(errorCode); + err += " | "; + err += errorMsg; + return err; + } + + public static String connectionClosed() { + return "Connection Closed"; + } +} diff --git a/ib/src/main/java/com/ib/client/ComboLeg.java b/ib/src/main/java/com/ib/client/ComboLeg.java new file mode 100644 index 00000000..e4464618 --- /dev/null +++ b/ib/src/main/java/com/ib/client/ComboLeg.java @@ -0,0 +1,82 @@ +/* + * ComboLeg.java + * + */ +package com.ib.client; + + +public class ComboLeg { + public final static int SAME = 0; // open/close leg value is same as combo + public final static int OPEN = 1; + public final static int CLOSE = 2; + public final static int UNKNOWN = 3; + + public int m_conId; + public int m_ratio; + public String m_action; // BUY/SELL/SSHORT/SSHORTX + public String m_exchange; + public int m_openClose; + + // for stock legs when doing short sale + public int m_shortSaleSlot; // 1 = clearing broker, 2 = third party + public String m_designatedLocation; + public int m_exemptCode; + + public ComboLeg() { + this(/* conId */ 0, /* ratio */ 0, /* action */ null, + /* exchange */ null, /* openClose */ 0, + /* shortSaleSlot */ 0, /* designatedLocation*/ null, /* exemptCode */ -1); + } + + public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, int p_openClose) { + this(p_conId, p_ratio, p_action, p_exchange, p_openClose, + /* shortSaleSlot */ 0, /* designatedLocation*/ null, /* exemptCode */ -1); + + } + + public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, + int p_openClose, int p_shortSaleSlot, String p_designatedLocation) { + this(p_conId, p_ratio, p_action, p_exchange, p_openClose, p_shortSaleSlot, p_designatedLocation, + /* exemptCode */ -1); + + } + + public ComboLeg(int p_conId, int p_ratio, String p_action, String p_exchange, + int p_openClose, int p_shortSaleSlot, String p_designatedLocation, int p_exemptCode) { + m_conId = p_conId; + m_ratio = p_ratio; + m_action = p_action; + m_exchange = p_exchange; + m_openClose = p_openClose; + m_shortSaleSlot = p_shortSaleSlot; + m_designatedLocation = p_designatedLocation; + m_exemptCode = p_exemptCode; + } + + public boolean equals(Object p_other) { + if ( this == p_other ) { + return true; + } + else if ( p_other == null ) { + return false; + } + + ComboLeg l_theOther = (ComboLeg)p_other; + + if (m_conId != l_theOther.m_conId || + m_ratio != l_theOther.m_ratio || + m_openClose != l_theOther.m_openClose || + m_shortSaleSlot != l_theOther.m_shortSaleSlot || + m_exemptCode != l_theOther.m_exemptCode) { + return false; + } + + if (Util.StringCompareIgnCase(m_action, l_theOther.m_action) != 0 || + Util.StringCompareIgnCase(m_exchange, l_theOther.m_exchange) != 0 || + Util.StringCompareIgnCase(m_designatedLocation, l_theOther.m_designatedLocation) != 0) { + return false; + } + + return true; + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/Contract.java b/ib/src/main/java/com/ib/client/Contract.java new file mode 100644 index 00000000..8eab7dc5 --- /dev/null +++ b/ib/src/main/java/com/ib/client/Contract.java @@ -0,0 +1,134 @@ +/* + * Contract.java + * + */ +package com.ib.client; + +import java.util.Vector; + +public class Contract implements Cloneable { + + public int m_conId; + public String m_symbol; + public String m_secType; + public String m_expiry; + public double m_strike; + public String m_right; + public String m_multiplier; + public String m_exchange; + + public String m_currency; + public String m_localSymbol; + public String m_primaryExch; // pick a non-aggregate (ie not the SMART exchange) exchange that the contract trades on. DO NOT SET TO SMART. + public boolean m_includeExpired; // can not be set to true for orders. + + public String m_secIdType; // CUSIP;SEDOL;ISIN;RIC + public String m_secId; + + // COMBOS + public String m_comboLegsDescrip; // received in open order version 14 and up for all combos + public Vector m_comboLegs = new Vector(); + + // delta neutral + public UnderComp m_underComp; + + public Contract() { + m_conId = 0; + m_strike = 0; + m_includeExpired = false; + } + + public Object clone() throws CloneNotSupportedException { + Contract retval = (Contract)super.clone(); + retval.m_comboLegs = (Vector)retval.m_comboLegs.clone(); + return retval; + } + + public Contract(int p_conId, String p_symbol, String p_secType, String p_expiry, + double p_strike, String p_right, String p_multiplier, + String p_exchange, String p_currency, String p_localSymbol, + Vector p_comboLegs, String p_primaryExch, boolean p_includeExpired, + String p_secIdType, String p_secId) { + m_conId = p_conId; + m_symbol = p_symbol; + m_secType = p_secType; + m_expiry = p_expiry; + m_strike = p_strike; + m_right = p_right; + m_multiplier = p_multiplier; + m_exchange = p_exchange; + m_currency = p_currency; + m_includeExpired = p_includeExpired; + m_localSymbol = p_localSymbol; + m_comboLegs = p_comboLegs; + m_primaryExch = p_primaryExch; + m_secIdType = p_secIdType; + m_secId = p_secId ; + } + + public boolean equals(Object p_other) { + + if (this == p_other) { + return true; + } + + if (p_other == null || !(p_other instanceof Contract)) { + return false; + } + + Contract l_theOther = (Contract)p_other; + + if (m_conId != l_theOther.m_conId) { + return false; + } + + if (Util.StringCompare(m_secType, l_theOther.m_secType) != 0) { + return false; + } + + if (Util.StringCompare(m_symbol, l_theOther.m_symbol) != 0 || + Util.StringCompare(m_exchange, l_theOther.m_exchange) != 0 || + Util.StringCompare(m_primaryExch, l_theOther.m_primaryExch) != 0 || + Util.StringCompare(m_currency, l_theOther.m_currency) != 0) { + return false; + } + + if (!Util.NormalizeString(m_secType).equals("BOND")) { + + if (m_strike != l_theOther.m_strike) { + return false; + } + + if (Util.StringCompare(m_expiry, l_theOther.m_expiry) != 0 || + Util.StringCompare(m_right, l_theOther.m_right) != 0 || + Util.StringCompare(m_multiplier, l_theOther.m_multiplier) != 0 || + Util.StringCompare(m_localSymbol, l_theOther.m_localSymbol) != 0) { + return false; + } + } + + if (Util.StringCompare(m_secIdType, l_theOther.m_secIdType) != 0) { + return false; + } + + if (Util.StringCompare(m_secId, l_theOther.m_secId) != 0) { + return false; + } + + // compare combo legs + if (!Util.VectorEqualsUnordered(m_comboLegs, l_theOther.m_comboLegs)) { + return false; + } + + if (m_underComp != l_theOther.m_underComp) { + if (m_underComp == null || l_theOther.m_underComp == null) { + return false; + } + if (!m_underComp.equals(l_theOther.m_underComp)) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/ContractDetails.java b/ib/src/main/java/com/ib/client/ContractDetails.java new file mode 100644 index 00000000..99cb4db4 --- /dev/null +++ b/ib/src/main/java/com/ib/client/ContractDetails.java @@ -0,0 +1,68 @@ +/* + * ContractDetails.java + * + */ +package com.ib.client; + +public class ContractDetails { + public Contract m_summary; + public String m_marketName; + public String m_tradingClass; + public double m_minTick; + public int m_priceMagnifier; + public String m_orderTypes; + public String m_validExchanges; + public int m_underConId; + public String m_longName; + public String m_contractMonth; + public String m_industry; + public String m_category; + public String m_subcategory; + public String m_timeZoneId; + public String m_tradingHours; + public String m_liquidHours; + + // BOND values + public String m_cusip; + public String m_ratings; + public String m_descAppend; + public String m_bondType; + public String m_couponType; + public boolean m_callable = false; + public boolean m_putable = false; + public double m_coupon = 0; + public boolean m_convertible = false; + public String m_maturity; + public String m_issueDate; + public String m_nextOptionDate; + public String m_nextOptionType; + public boolean m_nextOptionPartial = false; + public String m_notes; + + public ContractDetails() { + m_summary = new Contract(); + m_minTick = 0; + m_underConId = 0; + } + + public ContractDetails( Contract p_summary, String p_marketName, String p_tradingClass, + double p_minTick, String p_orderTypes, String p_validExchanges, int p_underConId, String p_longName, + String p_contractMonth, String p_industry, String p_category, String p_subcategory, + String p_timeZoneId, String p_tradingHours, String p_liquidHours) { + m_summary = p_summary; + m_marketName = p_marketName; + m_tradingClass = p_tradingClass; + m_minTick = p_minTick; + m_orderTypes = p_orderTypes; + m_validExchanges = p_validExchanges; + m_underConId = p_underConId; + m_longName = p_longName; + m_contractMonth = p_contractMonth; + m_industry = p_industry; + m_category = p_category; + m_subcategory = p_subcategory; + m_timeZoneId = p_timeZoneId; + m_tradingHours = p_tradingHours; + m_liquidHours = p_liquidHours; + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/EClientErrors.java b/ib/src/main/java/com/ib/client/EClientErrors.java new file mode 100644 index 00000000..52b00368 --- /dev/null +++ b/ib/src/main/java/com/ib/client/EClientErrors.java @@ -0,0 +1,75 @@ +/* + * EClientErrors.java + * + */ +package com.ib.client; + + +public class EClientErrors { + static final int NO_VALID_ID = -1; + + static final CodeMsgPair ALREADY_CONNECTED = new CodeMsgPair(501, "Already connected."); + static final CodeMsgPair CONNECT_FAIL = new CodeMsgPair(502, "Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket Clients\" is enabled on the TWS \"Configure->API\" menu."); + static final CodeMsgPair UPDATE_TWS = new CodeMsgPair(503, "The TWS is out of date and must be upgraded."); + static final CodeMsgPair NOT_CONNECTED = new CodeMsgPair(504, "Not connected"); + static final CodeMsgPair UNKNOWN_ID = new CodeMsgPair(505, "Fatal Error: Unknown message id."); + static final CodeMsgPair FAIL_SEND_REQMKT = new CodeMsgPair(510, "Request Market Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANMKT = new CodeMsgPair(511, "Cancel Market Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_ORDER = new CodeMsgPair(512, "Order Sending Error - "); + static final CodeMsgPair FAIL_SEND_ACCT = new CodeMsgPair(513, "Account Update Request Sending Error -"); + static final CodeMsgPair FAIL_SEND_EXEC = new CodeMsgPair(514, "Request For Executions Sending Error -"); + static final CodeMsgPair FAIL_SEND_CORDER = new CodeMsgPair(515, "Cancel Order Sending Error -"); + static final CodeMsgPair FAIL_SEND_OORDER = new CodeMsgPair(516, "Request Open Order Sending Error -"); + static final CodeMsgPair UNKNOWN_CONTRACT = new CodeMsgPair(517, "Unknown contract. Verify the contract details supplied."); + static final CodeMsgPair FAIL_SEND_REQCONTRACT = new CodeMsgPair(518, "Request Contract Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQMKTDEPTH = new CodeMsgPair(519, "Request Market Depth Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANMKTDEPTH = new CodeMsgPair(520, "Cancel Market Depth Sending Error - "); + static final CodeMsgPair FAIL_SEND_SERVER_LOG_LEVEL = new CodeMsgPair(521, "Set Server Log Level Sending Error - "); + static final CodeMsgPair FAIL_SEND_FA_REQUEST = new CodeMsgPair(522, "FA Information Request Sending Error - "); + static final CodeMsgPair FAIL_SEND_FA_REPLACE = new CodeMsgPair(523, "FA Information Replace Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQSCANNER = new CodeMsgPair(524, "Request Scanner Subscription Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANSCANNER = new CodeMsgPair(525, "Cancel Scanner Subscription Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQSCANNERPARAMETERS = new CodeMsgPair(526, "Request Scanner Parameter Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQHISTDATA = new CodeMsgPair(527, "Request Historical Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANHISTDATA = new CodeMsgPair(528, "Request Historical Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQRTBARS = new CodeMsgPair(529, "Request Real-time Bar Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANRTBARS = new CodeMsgPair(530, "Cancel Real-time Bar Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQCURRTIME = new CodeMsgPair(531, "Request Current Time Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQFUNDDATA = new CodeMsgPair(532, "Request Fundamental Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANFUNDDATA = new CodeMsgPair(533, "Cancel Fundamental Data Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQCALCIMPLIEDVOLAT = new CodeMsgPair(534, "Request Calculate Implied Volatility Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQCALCOPTIONPRICE = new CodeMsgPair(535, "Request Calculate Option Price Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANCALCIMPLIEDVOLAT = new CodeMsgPair(536, "Cancel Calculate Implied Volatility Sending Error - "); + static final CodeMsgPair FAIL_SEND_CANCALCOPTIONPRICE = new CodeMsgPair(537, "Cancel Calculate Option Price Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQGLOBALCANCEL = new CodeMsgPair(538, "Request Global Cancel Sending Error - "); + static final CodeMsgPair FAIL_SEND_REQMARKETDATATYPE = new CodeMsgPair(539, "Request Market Data Type Sending Error - "); + + public EClientErrors() { + } + + static public class CodeMsgPair { + + /////////////////////////////////////////////////////////////////// + // Public members + /////////////////////////////////////////////////////////////////// + int m_errorCode; + String m_errorMsg; + + /////////////////////////////////////////////////////////////////// + // Get/Set methods + /////////////////////////////////////////////////////////////////// + public int code() { return m_errorCode; } + public String msg() { return m_errorMsg; } + + /////////////////////////////////////////////////////////////////// + // Constructors + /////////////////////////////////////////////////////////////////// + /** + * + */ + public CodeMsgPair(int i, String errString) { + m_errorCode = i; + m_errorMsg = errString; + } + } +} diff --git a/ib/src/main/java/com/ib/client/EClientSocket.java b/ib/src/main/java/com/ib/client/EClientSocket.java new file mode 100644 index 00000000..e4bd91a2 --- /dev/null +++ b/ib/src/main/java/com/ib/client/EClientSocket.java @@ -0,0 +1,1968 @@ +/* + * EClientSocket.java + * + */ +package com.ib.client; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +public class EClientSocket { + + // Client version history + // + // 6 = Added parentId to orderStatus + // 7 = The new execDetails event returned for an order filled status and reqExecDetails + // Also market depth is available. + // 8 = Added lastFillPrice to orderStatus() event and permId to execution details + // 9 = Added 'averageCost', 'unrealizedPNL', and 'unrealizedPNL' to updatePortfolio event + // 10 = Added 'serverId' to the 'open order' & 'order status' events. + // We send back all the API open orders upon connection. + // Added new methods reqAllOpenOrders, reqAutoOpenOrders() + // Added FA support - reqExecution has filter. + // - reqAccountUpdates takes acct code. + // 11 = Added permId to openOrder event. + // 12 = requsting open order attributes ignoreRth, hidden, and discretionary + // 13 = added goodAfterTime + // 14 = always send size on bid/ask/last tick + // 15 = send allocation description string on openOrder + // 16 = can receive account name in account and portfolio updates, and fa params in openOrder + // 17 = can receive liquidation field in exec reports, and notAutoAvailable field in mkt data + // 18 = can receive good till date field in open order messages, and request intraday backfill + // 19 = can receive rthOnly flag in ORDER_STATUS + // 20 = expects TWS time string on connection after server version >= 20. + // 21 = can receive bond contract details. + // 22 = can receive price magnifier in version 2 contract details message + // 23 = support for scanner + // 24 = can receive volatility order parameters in open order messages + // 25 = can receive HMDS query start and end times + // 26 = can receive option vols in option market data messages + // 27 = can receive delta neutral order type and delta neutral aux price in place order version 20: API 8.85 + // 28 = can receive option model computation ticks: API 8.9 + // 29 = can receive trail stop limit price in open order and can place them: API 8.91 + // 30 = can receive extended bond contract def, new ticks, and trade count in bars + // 31 = can receive EFP extensions to scanner and market data, and combo legs on open orders + // ; can receive RT bars + // 32 = can receive TickType.LAST_TIMESTAMP + // ; can receive "whyHeld" in order status messages + // 33 = can receive ScaleNumComponents and ScaleComponentSize is open order messages + // 34 = can receive whatIf orders / order state + // 35 = can receive contId field for Contract objects + // 36 = can receive outsideRth field for Order objects + // 37 = can receive clearingAccount and clearingIntent for Order objects + // 38 = can receive multiplier and primaryExchange in portfolio updates + // ; can receive cumQty and avgPrice in execution + // ; can receive fundamental data + // ; can receive underComp for Contract objects + // ; can receive reqId and end marker in contractDetails/bondContractDetails + // ; can receive ScaleInitComponentSize and ScaleSubsComponentSize for Order objects + // 39 = can receive underConId in contractDetails + // 40 = can receive algoStrategy/algoParams in openOrder + // 41 = can receive end marker for openOrder + // ; can receive end marker for account download + // ; can receive end marker for executions download + // 42 = can receive deltaNeutralValidation + // 43 = can receive longName(companyName) + // ; can receive listingExchange + // ; can receive RTVolume tick + // 44 = can receive end market for ticker snapshot + // 45 = can receive notHeld field in openOrder + // 46 = can receive contractMonth, industry, category, subcategory fields in contractDetails + // ; can receive timeZoneId, tradingHours, liquidHours fields in contractDetails + // 47 = can receive gamma, vega, theta, undPrice fields in TICK_OPTION_COMPUTATION + // 48 = can receive exemptCode in openOrder + // 49 = can receive hedgeType and hedgeParam in openOrder + // 50 = can receive optOutSmartRouting field in openOrder + // 51 = can receive smartComboRoutingParams in openOrder + // 52 = can receive deltaNeutralConId, deltaNeutralSettlingFirm, deltaNeutralClearingAccount and deltaNeutralClearingIntent in openOrder + // 53 = can receive orderRef in execution + + private static final int CLIENT_VERSION = 53; + private static final int SERVER_VERSION = 38; + private static final byte[] EOL = {0}; + private static final String BAG_SEC_TYPE = "BAG"; + + // FA msg data types + public static final int GROUPS = 1; + public static final int PROFILES = 2; + public static final int ALIASES = 3; + + public static String faMsgTypeName(int faDataType) { + switch (faDataType) { + case GROUPS: + return "GROUPS"; + case PROFILES: + return "PROFILES"; + case ALIASES: + return "ALIASES"; + } + return null; + } + + // outgoing msg id's + private static final int REQ_MKT_DATA = 1; + private static final int CANCEL_MKT_DATA = 2; + private static final int PLACE_ORDER = 3; + private static final int CANCEL_ORDER = 4; + private static final int REQ_OPEN_ORDERS = 5; + private static final int REQ_ACCOUNT_DATA = 6; + private static final int REQ_EXECUTIONS = 7; + private static final int REQ_IDS = 8; + private static final int REQ_CONTRACT_DATA = 9; + private static final int REQ_MKT_DEPTH = 10; + private static final int CANCEL_MKT_DEPTH = 11; + private static final int REQ_NEWS_BULLETINS = 12; + private static final int CANCEL_NEWS_BULLETINS = 13; + private static final int SET_SERVER_LOGLEVEL = 14; + private static final int REQ_AUTO_OPEN_ORDERS = 15; + private static final int REQ_ALL_OPEN_ORDERS = 16; + private static final int REQ_MANAGED_ACCTS = 17; + private static final int REQ_FA = 18; + private static final int REPLACE_FA = 19; + private static final int REQ_HISTORICAL_DATA = 20; + private static final int EXERCISE_OPTIONS = 21; + private static final int REQ_SCANNER_SUBSCRIPTION = 22; + private static final int CANCEL_SCANNER_SUBSCRIPTION = 23; + private static final int REQ_SCANNER_PARAMETERS = 24; + private static final int CANCEL_HISTORICAL_DATA = 25; + private static final int REQ_CURRENT_TIME = 49; + private static final int REQ_REAL_TIME_BARS = 50; + private static final int CANCEL_REAL_TIME_BARS = 51; + private static final int REQ_FUNDAMENTAL_DATA = 52; + private static final int CANCEL_FUNDAMENTAL_DATA = 53; + private static final int REQ_CALC_IMPLIED_VOLAT = 54; + private static final int REQ_CALC_OPTION_PRICE = 55; + private static final int CANCEL_CALC_IMPLIED_VOLAT = 56; + private static final int CANCEL_CALC_OPTION_PRICE = 57; + private static final int REQ_GLOBAL_CANCEL = 58; + private static final int REQ_MARKET_DATA_TYPE = 59; + + private static final int MIN_SERVER_VER_REAL_TIME_BARS = 34; + private static final int MIN_SERVER_VER_SCALE_ORDERS = 35; + private static final int MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35; + private static final int MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35; + private static final int MIN_SERVER_VER_WHAT_IF_ORDERS = 36; + private static final int MIN_SERVER_VER_CONTRACT_CONID = 37; + private static final int MIN_SERVER_VER_PTA_ORDERS = 39; + private static final int MIN_SERVER_VER_FUNDAMENTAL_DATA = 40; + private static final int MIN_SERVER_VER_UNDER_COMP = 40; + private static final int MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40; + private static final int MIN_SERVER_VER_SCALE_ORDERS2 = 40; + private static final int MIN_SERVER_VER_ALGO_ORDERS = 41; + private static final int MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42; + private static final int MIN_SERVER_VER_NOT_HELD = 44; + private static final int MIN_SERVER_VER_SEC_ID_TYPE = 45; + private static final int MIN_SERVER_VER_PLACE_ORDER_CONID = 46; + private static final int MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47; + private static final int MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49; + private static final int MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50; + private static final int MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT = 50; + private static final int MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE = 50; + private static final int MIN_SERVER_VER_SSHORTX_OLD = 51; + private static final int MIN_SERVER_VER_SSHORTX = 52; + private static final int MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53; + private static final int MIN_SERVER_VER_HEDGE_ORDERS = 54; + private static final int MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55; + private static final int MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56; + private static final int MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57; + private static final int MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58; + + private AnyWrapper m_anyWrapper; // msg handler + private DataOutputStream m_dos; // the socket output stream + private boolean m_connected;// true if we are connected + private EReader m_reader; // thread which reads msgs from socket + private int m_serverVersion = 0; + private String m_TwsTime; + + public int serverVersion() { return m_serverVersion; } + public String TwsConnectionTime() { return m_TwsTime; } + public AnyWrapper wrapper() { return m_anyWrapper; } + public EReader reader() { return m_reader; } + + + public EClientSocket( AnyWrapper anyWrapper) { + m_anyWrapper = anyWrapper; + } + + public boolean isConnected() { + return m_connected; + } + + public synchronized void eConnect( String host, int port, int clientId) { + // already connected? + host = checkConnected(host); + if(host == null){ + return; + } + try{ + Socket socket = new Socket( host, port); + eConnect(socket, clientId); + } + catch( Exception e) { + eDisconnect(); + connectionError(); + } + } + + protected void connectionError() { + m_anyWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.CONNECT_FAIL.code(), + EClientErrors.CONNECT_FAIL.msg()); + m_reader = null; + } + + protected String checkConnected(String host) { + if( m_connected) { + m_anyWrapper.error(EClientErrors.NO_VALID_ID, EClientErrors.ALREADY_CONNECTED.code(), + EClientErrors.ALREADY_CONNECTED.msg()); + return null; + } + if( isNull( host) ) { + host = "127.0.0.1"; + } + return host; + } + + public EReader createReader(EClientSocket socket, DataInputStream dis) { + return new EReader(socket, dis); + } + + public synchronized void eConnect(Socket socket, int clientId) throws IOException { + + // create io streams + m_dos = new DataOutputStream( socket.getOutputStream() ); + + // set client version + send( CLIENT_VERSION); + + // start reader thread + m_reader = createReader(this, new DataInputStream( + socket.getInputStream())); + + // check server version + m_serverVersion = m_reader.readInt(); + System.out.println("Server Version:" + m_serverVersion); + if ( m_serverVersion >= 20 ){ + m_TwsTime = m_reader.readStr(); + System.out.println("TWS Time at connection:" + m_TwsTime); + } + if( m_serverVersion < SERVER_VERSION) { + eDisconnect(); + m_anyWrapper.error( EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), EClientErrors.UPDATE_TWS.msg()); + return; + } + + // Send the client id + if ( m_serverVersion >= 3 ){ + send( clientId); + } + + m_reader.start(); + + // set connected flag + m_connected = true; + } + + public synchronized void eDisconnect() { + // not connected? + if( m_dos == null) { + return; + } + + m_connected = false; + m_serverVersion = 0; + m_TwsTime = ""; + + DataOutputStream dos = m_dos; + m_dos = null; + + EReader reader = m_reader; + m_reader = null; + + try { + // stop reader thread + if( reader != null) { + reader.interrupt(); + } + } + catch( Exception e) { + } + + try { + // close socket + if( dos != null) { + dos.close(); + } + } + catch( Exception e) { + } + } + + public synchronized void cancelScannerSubscription( int tickerId) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support API scanner subscription."); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + send( CANCEL_SCANNER_SUBSCRIPTION); + send( VERSION); + send( tickerId); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANSCANNER, "" + e); + close(); + } + } + + public synchronized void reqScannerParameters() { + // not connected? + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support API scanner subscription."); + return; + } + + final int VERSION = 1; + + try { + send(REQ_SCANNER_PARAMETERS); + send(VERSION); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, + EClientErrors.FAIL_SEND_REQSCANNERPARAMETERS, "" + e); + close(); + } + } + + public synchronized void reqScannerSubscription( int tickerId, + ScannerSubscription subscription) { + // not connected? + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support API scanner subscription."); + return; + } + + final int VERSION = 3; + + try { + send(REQ_SCANNER_SUBSCRIPTION); + send(VERSION); + send(tickerId); + sendMax(subscription.numberOfRows()); + send(subscription.instrument()); + send(subscription.locationCode()); + send(subscription.scanCode()); + sendMax(subscription.abovePrice()); + sendMax(subscription.belowPrice()); + sendMax(subscription.aboveVolume()); + sendMax(subscription.marketCapAbove()); + sendMax(subscription.marketCapBelow()); + send(subscription.moodyRatingAbove()); + send(subscription.moodyRatingBelow()); + send(subscription.spRatingAbove()); + send(subscription.spRatingBelow()); + send(subscription.maturityDateAbove()); + send(subscription.maturityDateBelow()); + sendMax(subscription.couponRateAbove()); + sendMax(subscription.couponRateBelow()); + send(subscription.excludeConvertible()); + if (m_serverVersion >= 25) { + send(subscription.averageOptionVolumeAbove()); + send(subscription.scannerSettingPairs()); + } + if (m_serverVersion >= 27) { + send(subscription.stockTypeFilter()); + } + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQSCANNER, "" + e); + close(); + } + } + + public synchronized void reqMktData(int tickerId, Contract contract, + String genericTickList, boolean snapshot) { + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_SNAPSHOT_MKT_DATA && snapshot) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support snapshot market data requests."); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { + if (contract.m_underComp != null) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support delta-neutral orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_MKT_DATA_CONID) { + if (contract.m_conId > 0) { + error(tickerId, EClientErrors.UPDATE_TWS, + " It does not support conId parameter."); + return; + } + } + + final int VERSION = 9; + + try { + // send req mkt data msg + send(REQ_MKT_DATA); + send(VERSION); + send(tickerId); + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_REQ_MKT_DATA_CONID) { + send(contract.m_conId); + } + send(contract.m_symbol); + send(contract.m_secType); + send(contract.m_expiry); + send(contract.m_strike); + send(contract.m_right); + if (m_serverVersion >= 15) { + send(contract.m_multiplier); + } + send(contract.m_exchange); + if (m_serverVersion >= 14) { + send(contract.m_primaryExch); + } + send(contract.m_currency); + if(m_serverVersion >= 2) { + send( contract.m_localSymbol); + } + if(m_serverVersion >= 8 && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { + if ( contract.m_comboLegs == null ) { + send( 0); + } + else { + send( contract.m_comboLegs.size()); + + ComboLeg comboLeg; + for (int i=0; i < contract.m_comboLegs.size(); i ++) { + comboLeg = (ComboLeg)contract.m_comboLegs.get(i); + send( comboLeg.m_conId); + send( comboLeg.m_ratio); + send( comboLeg.m_action); + send( comboLeg.m_exchange); + } + } + } + + if (m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { + if (contract.m_underComp != null) { + UnderComp underComp = contract.m_underComp; + send( true); + send( underComp.m_conId); + send( underComp.m_delta); + send( underComp.m_price); + } + else { + send( false); + } + } + + if (m_serverVersion >= 31) { + /* + * Note: Even though SHORTABLE tick type supported only + * starting server version 33 it would be relatively + * expensive to expose this restriction here. + * + * Therefore we are relying on TWS doing validation. + */ + send( genericTickList); + } + if (m_serverVersion >= MIN_SERVER_VER_SNAPSHOT_MKT_DATA) { + send (snapshot); + } + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQMKT, "" + e); + close(); + } + } + + public synchronized void cancelHistoricalData( int tickerId ) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < 24) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support historical data query cancellation."); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + send( CANCEL_HISTORICAL_DATA); + send( VERSION); + send( tickerId); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANHISTDATA, "" + e); + close(); + } + } + + public void cancelRealTimeBars(int tickerId) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support realtime bar data query cancellation."); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + send( CANCEL_REAL_TIME_BARS); + send( VERSION); + send( tickerId); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANRTBARS, "" + e); + close(); + } + } + + public synchronized void reqHistoricalData( int tickerId, Contract contract, + String endDateTime, String durationStr, + String barSizeSetting, String whatToShow, + int useRTH, int formatDate) { + // not connected? + if( !m_connected) { + error( tickerId, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 4; + + try { + if (m_serverVersion < 16) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support historical data backfill."); + return; + } + + send(REQ_HISTORICAL_DATA); + send(VERSION); + send(tickerId); + + // send contract fields + send(contract.m_symbol); + send(contract.m_secType); + send(contract.m_expiry); + send(contract.m_strike); + send(contract.m_right); + send(contract.m_multiplier); + send(contract.m_exchange); + send(contract.m_primaryExch); + send(contract.m_currency); + send(contract.m_localSymbol); + if (m_serverVersion >= 31) { + send(contract.m_includeExpired ? 1 : 0); + } + if (m_serverVersion >= 20) { + send(endDateTime); + send(barSizeSetting); + } + send(durationStr); + send(useRTH); + send(whatToShow); + if (m_serverVersion > 16) { + send(formatDate); + } + if (BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { + if (contract.m_comboLegs == null) { + send(0); + } + else { + send(contract.m_comboLegs.size()); + + ComboLeg comboLeg; + for (int i = 0; i < contract.m_comboLegs.size(); i++) { + comboLeg = (ComboLeg) contract.m_comboLegs.get(i); + send(comboLeg.m_conId); + send(comboLeg.m_ratio); + send(comboLeg.m_action); + send(comboLeg.m_exchange); + } + } + } + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_REQHISTDATA, "" + e); + close(); + } + } + + public synchronized void reqRealTimeBars(int tickerId, Contract contract, int barSize, String whatToShow, boolean useRTH) { + // not connected? + if (!m_connected ) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + if (m_serverVersion < MIN_SERVER_VER_REAL_TIME_BARS) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support real time bars."); + return; + } + + final int VERSION = 1; + + try { + // send req mkt data msg + send(REQ_REAL_TIME_BARS); + send(VERSION); + send(tickerId); + + // send contract fields + send(contract.m_symbol); + send(contract.m_secType); + send(contract.m_expiry); + send(contract.m_strike); + send(contract.m_right); + send(contract.m_multiplier); + send(contract.m_exchange); + send(contract.m_primaryExch); + send(contract.m_currency); + send(contract.m_localSymbol); + send(barSize); + send(whatToShow); + send(useRTH); + + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQRTBARS, "" + e); + close(); + } + + } + + public synchronized void reqContractDetails(int reqId, Contract contract) + { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + // This feature is only available for versions of TWS >=4 + if( m_serverVersion < 4) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { + if (!IsEmpty(contract.m_secIdType) || !IsEmpty(contract.m_secId)) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support secIdType and secId parameters."); + return; + } + } + + final int VERSION = 6; + + try { + // send req mkt data msg + send( REQ_CONTRACT_DATA); + send( VERSION); + + if (m_serverVersion >= MIN_SERVER_VER_CONTRACT_DATA_CHAIN) { + send( reqId); + } + + // send contract fields + if (m_serverVersion >= MIN_SERVER_VER_CONTRACT_CONID) { + send(contract.m_conId); + } + send( contract.m_symbol); + send( contract.m_secType); + send( contract.m_expiry); + send( contract.m_strike); + send( contract.m_right); + if (m_serverVersion >= 15) { + send(contract.m_multiplier); + } + send( contract.m_exchange); + send( contract.m_currency); + send( contract.m_localSymbol); + if (m_serverVersion >= 31) { + send(contract.m_includeExpired); + } + if (m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE) { + send( contract.m_secIdType); + send( contract.m_secId); + } + + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQCONTRACT, "" + e); + close(); + } + } + + public synchronized void reqMktDepth( int tickerId, Contract contract, int numRows) + { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + // This feature is only available for versions of TWS >=6 + if( m_serverVersion < 6) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 3; + + try { + // send req mkt data msg + send( REQ_MKT_DEPTH); + send( VERSION); + send( tickerId); + + // send contract fields + send( contract.m_symbol); + send( contract.m_secType); + send( contract.m_expiry); + send( contract.m_strike); + send( contract.m_right); + if (m_serverVersion >= 15) { + send(contract.m_multiplier); + } + send( contract.m_exchange); + send( contract.m_currency); + send( contract.m_localSymbol); + if (m_serverVersion >= 19) { + send( numRows); + } + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_REQMKTDEPTH, "" + e); + close(); + } + } + + public synchronized void cancelMktData( int tickerId) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + send( CANCEL_MKT_DATA); + send( VERSION); + send( tickerId); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANMKT, "" + e); + close(); + } + } + + public synchronized void cancelMktDepth( int tickerId) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + // This feature is only available for versions of TWS >=6 + if( m_serverVersion < 6) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 1; + + // send cancel mkt data msg + try { + send( CANCEL_MKT_DEPTH); + send( VERSION); + send( tickerId); + } + catch( Exception e) { + error( tickerId, EClientErrors.FAIL_SEND_CANMKTDEPTH, "" + e); + close(); + } + } + + public synchronized void exerciseOptions( int tickerId, Contract contract, + int exerciseAction, int exerciseQuantity, + String account, int override) { + // not connected? + if( !m_connected) { + error( tickerId, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + try { + if (m_serverVersion < 21) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support options exercise from the API."); + return; + } + + send(EXERCISE_OPTIONS); + send(VERSION); + send(tickerId); + + // send contract fields + send(contract.m_symbol); + send(contract.m_secType); + send(contract.m_expiry); + send(contract.m_strike); + send(contract.m_right); + send(contract.m_multiplier); + send(contract.m_exchange); + send(contract.m_currency); + send(contract.m_localSymbol); + send(exerciseAction); + send(exerciseQuantity); + send(account); + send(override); + } + catch (Exception e) { + error(tickerId, EClientErrors.FAIL_SEND_REQMKT, "" + e); + close(); + } + } + + public synchronized void placeOrder( int id, Contract contract, Order order) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS) { + if (order.m_scaleInitLevelSize != Integer.MAX_VALUE || + order.m_scalePriceIncrement != Double.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support Scale orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SSHORT_COMBO_LEGS) { + if (!contract.m_comboLegs.isEmpty()) { + ComboLeg comboLeg; + for (int i = 0; i < contract.m_comboLegs.size(); ++i) { + comboLeg = (ComboLeg)contract.m_comboLegs.get(i); + if (comboLeg.m_shortSaleSlot != 0 || + !IsEmpty(comboLeg.m_designatedLocation)) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support SSHORT flag for combo legs."); + return; + } + } + } + } + + if (m_serverVersion < MIN_SERVER_VER_WHAT_IF_ORDERS) { + if (order.m_whatIf) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support what-if orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_UNDER_COMP) { + if (contract.m_underComp != null) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support delta-neutral orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS2) { + if (order.m_scaleSubsLevelSize != Integer.MAX_VALUE) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support Subsequent Level Size for Scale orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_ALGO_ORDERS) { + if (!IsEmpty(order.m_algoStrategy)) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support algo orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_NOT_HELD) { + if (order.m_notHeld) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support notHeld parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SEC_ID_TYPE) { + if (!IsEmpty(contract.m_secIdType) || !IsEmpty(contract.m_secId)) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support secIdType and secId parameters."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_PLACE_ORDER_CONID) { + if (contract.m_conId > 0) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support conId parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { + if (order.m_exemptCode != -1) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support exemptCode parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_SSHORTX) { + if (!contract.m_comboLegs.isEmpty()) { + ComboLeg comboLeg; + for (int i = 0; i < contract.m_comboLegs.size(); ++i) { + comboLeg = (ComboLeg)contract.m_comboLegs.get(i); + if (comboLeg.m_exemptCode != -1) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support exemptCode parameter."); + return; + } + } + } + } + + if (m_serverVersion < MIN_SERVER_VER_HEDGE_ORDERS) { + if (!IsEmpty(order.m_hedgeType)) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support hedge orders."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { + if (order.m_optOutSmartRouting) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support optOutSmartRouting parameter."); + return; + } + } + + if (m_serverVersion < MIN_SERVER_VER_DELTA_NEUTRAL_CONID) { + if (order.m_deltaNeutralConId > 0 + || !IsEmpty(order.m_deltaNeutralSettlingFirm) + || !IsEmpty(order.m_deltaNeutralClearingAccount) + || !IsEmpty(order.m_deltaNeutralClearingIntent) + ) { + error(id, EClientErrors.UPDATE_TWS, + " It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent"); + return; + } + } + + + int VERSION = (m_serverVersion < MIN_SERVER_VER_NOT_HELD) ? 27 : 35; + + // send place order msg + try { + send( PLACE_ORDER); + send( VERSION); + send( id); + + // send contract fields + if( m_serverVersion >= MIN_SERVER_VER_PLACE_ORDER_CONID) { + send(contract.m_conId); + } + send( contract.m_symbol); + send( contract.m_secType); + send( contract.m_expiry); + send( contract.m_strike); + send( contract.m_right); + if (m_serverVersion >= 15) { + send(contract.m_multiplier); + } + send( contract.m_exchange); + if( m_serverVersion >= 14) { + send(contract.m_primaryExch); + } + send( contract.m_currency); + if( m_serverVersion >= 2) { + send (contract.m_localSymbol); + } + if( m_serverVersion >= MIN_SERVER_VER_SEC_ID_TYPE){ + send( contract.m_secIdType); + send( contract.m_secId); + } + + // send main order fields + send( order.m_action); + send( order.m_totalQuantity); + send( order.m_orderType); + send( order.m_lmtPrice); + send( order.m_auxPrice); + + // send extended order fields + send( order.m_tif); + send( order.m_ocaGroup); + send( order.m_account); + send( order.m_openClose); + send( order.m_origin); + send( order.m_orderRef); + send( order.m_transmit); + if( m_serverVersion >= 4 ) { + send (order.m_parentId); + } + + if( m_serverVersion >= 5 ) { + send (order.m_blockOrder); + send (order.m_sweepToFill); + send (order.m_displaySize); + send (order.m_triggerMethod); + if (m_serverVersion < 38) { + // will never happen + send(/* order.m_ignoreRth */ false); + } + else { + send (order.m_outsideRth); + } + } + + if(m_serverVersion >= 7 ) { + send(order.m_hidden); + } + + // Send combo legs for BAG requests + if(m_serverVersion >= 8 && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { + if ( contract.m_comboLegs == null ) { + send( 0); + } + else { + send( contract.m_comboLegs.size()); + + ComboLeg comboLeg; + for (int i=0; i < contract.m_comboLegs.size(); i ++) { + comboLeg = (ComboLeg)contract.m_comboLegs.get(i); + send( comboLeg.m_conId); + send( comboLeg.m_ratio); + send( comboLeg.m_action); + send( comboLeg.m_exchange); + send( comboLeg.m_openClose); + + if (m_serverVersion >= MIN_SERVER_VER_SSHORT_COMBO_LEGS) { + send( comboLeg.m_shortSaleSlot); + send( comboLeg.m_designatedLocation); + } + if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { + send( comboLeg.m_exemptCode); + } + } + } + } + + if(m_serverVersion >= MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS && BAG_SEC_TYPE.equalsIgnoreCase(contract.m_secType)) { + java.util.Vector smartComboRoutingParams = order.m_smartComboRoutingParams; + int smartComboRoutingParamsCount = smartComboRoutingParams == null ? 0 : smartComboRoutingParams.size(); + send( smartComboRoutingParamsCount); + if( smartComboRoutingParamsCount > 0) { + for( int i = 0; i < smartComboRoutingParamsCount; ++i) { + TagValue tagValue = (TagValue)smartComboRoutingParams.get(i); + send( tagValue.m_tag); + send( tagValue.m_value); + } + } + } + + if ( m_serverVersion >= 9 ) { + // send deprecated sharesAllocation field + send( ""); + } + + if ( m_serverVersion >= 10 ) { + send( order.m_discretionaryAmt); + } + + if ( m_serverVersion >= 11 ) { + send( order.m_goodAfterTime); + } + + if ( m_serverVersion >= 12 ) { + send( order.m_goodTillDate); + } + + if ( m_serverVersion >= 13 ) { + send( order.m_faGroup); + send( order.m_faMethod); + send( order.m_faPercentage); + send( order.m_faProfile); + } + if (m_serverVersion >= 18) { // institutional short sale slot fields. + send( order.m_shortSaleSlot); // 0 only for retail, 1 or 2 only for institution. + send( order.m_designatedLocation); // only populate when order.m_shortSaleSlot = 2. + } + if (m_serverVersion >= MIN_SERVER_VER_SSHORTX_OLD) { + send( order.m_exemptCode); + } + if (m_serverVersion >= 19) { + send( order.m_ocaType); + if (m_serverVersion < 38) { + // will never happen + send( /* order.m_rthOnly */ false); + } + send( order.m_rule80A); + send( order.m_settlingFirm); + send( order.m_allOrNone); + sendMax( order.m_minQty); + sendMax( order.m_percentOffset); + send( order.m_eTradeOnly); + send( order.m_firmQuoteOnly); + sendMax( order.m_nbboPriceCap); + sendMax( order.m_auctionStrategy); + sendMax( order.m_startingPrice); + sendMax( order.m_stockRefPrice); + sendMax( order.m_delta); + // Volatility orders had specific watermark price attribs in server version 26 + double lower = (m_serverVersion == 26 && order.m_orderType.equals("VOL")) + ? Double.MAX_VALUE + : order.m_stockRangeLower; + double upper = (m_serverVersion == 26 && order.m_orderType.equals("VOL")) + ? Double.MAX_VALUE + : order.m_stockRangeUpper; + sendMax( lower); + sendMax( upper); + } + + if (m_serverVersion >= 22) { + send( order.m_overridePercentageConstraints); + } + + if (m_serverVersion >= 26) { // Volatility orders + sendMax( order.m_volatility); + sendMax( order.m_volatilityType); + if (m_serverVersion < 28) { + send( order.m_deltaNeutralOrderType.equalsIgnoreCase("MKT")); + } else { + send( order.m_deltaNeutralOrderType); + sendMax( order.m_deltaNeutralAuxPrice); + + if (m_serverVersion >= MIN_SERVER_VER_DELTA_NEUTRAL_CONID && !IsEmpty(order.m_deltaNeutralOrderType)){ + send( order.m_deltaNeutralConId); + send( order.m_deltaNeutralSettlingFirm); + send( order.m_deltaNeutralClearingAccount); + send( order.m_deltaNeutralClearingIntent); + } + } + send( order.m_continuousUpdate); + if (m_serverVersion == 26) { + // Volatility orders had specific watermark price attribs in server version 26 + double lower = order.m_orderType.equals("VOL") ? order.m_stockRangeLower : Double.MAX_VALUE; + double upper = order.m_orderType.equals("VOL") ? order.m_stockRangeUpper : Double.MAX_VALUE; + sendMax( lower); + sendMax( upper); + } + sendMax( order.m_referencePriceType); + } + + if (m_serverVersion >= 30) { // TRAIL_STOP_LIMIT stop price + sendMax( order.m_trailStopPrice); + } + + if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS) { + if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS2) { + sendMax (order.m_scaleInitLevelSize); + sendMax (order.m_scaleSubsLevelSize); + } + else { + send (""); + sendMax (order.m_scaleInitLevelSize); + + } + sendMax (order.m_scalePriceIncrement); + } + + if (m_serverVersion >= MIN_SERVER_VER_HEDGE_ORDERS) { + send (order.m_hedgeType); + if (!IsEmpty(order.m_hedgeType)) { + send (order.m_hedgeParam); + } + } + + if (m_serverVersion >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) { + send (order.m_optOutSmartRouting); + } + + if (m_serverVersion >= MIN_SERVER_VER_PTA_ORDERS) { + send (order.m_clearingAccount); + send (order.m_clearingIntent); + } + + if (m_serverVersion >= MIN_SERVER_VER_NOT_HELD) { + send (order.m_notHeld); + } + + if (m_serverVersion >= MIN_SERVER_VER_UNDER_COMP) { + if (contract.m_underComp != null) { + UnderComp underComp = contract.m_underComp; + send( true); + send( underComp.m_conId); + send( underComp.m_delta); + send( underComp.m_price); + } + else { + send( false); + } + } + + if (m_serverVersion >= MIN_SERVER_VER_ALGO_ORDERS) { + send( order.m_algoStrategy); + if( !IsEmpty(order.m_algoStrategy)) { + java.util.Vector algoParams = order.m_algoParams; + int algoParamsCount = algoParams == null ? 0 : algoParams.size(); + send( algoParamsCount); + if( algoParamsCount > 0) { + for( int i = 0; i < algoParamsCount; ++i) { + TagValue tagValue = (TagValue)algoParams.get(i); + send( tagValue.m_tag); + send( tagValue.m_value); + } + } + } + } + + if (m_serverVersion >= MIN_SERVER_VER_WHAT_IF_ORDERS) { + send (order.m_whatIf); + } + } + catch( Exception e) { + error( id, EClientErrors.FAIL_SEND_ORDER, "" + e); + close(); + } + } + + public synchronized void reqAccountUpdates(boolean subscribe, String acctCode) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 2; + + // send cancel order msg + try { + send( REQ_ACCOUNT_DATA ); + send( VERSION); + send( subscribe); + + // Send the account code. This will only be used for FA clients + if ( m_serverVersion >= 9 ) { + send( acctCode); + } + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_ACCT, "" + e); + close(); + } + } + + public synchronized void reqExecutions(int reqId, ExecutionFilter filter) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 3; + + // send cancel order msg + try { + send( REQ_EXECUTIONS); + send( VERSION); + + if (m_serverVersion >= MIN_SERVER_VER_EXECUTION_DATA_CHAIN) { + send( reqId); + } + + // Send the execution rpt filter data + if ( m_serverVersion >= 9 ) { + send( filter.m_clientId); + send( filter.m_acctCode); + + // Note that the valid format for m_time is "yyyymmdd-hh:mm:ss" + send( filter.m_time); + send( filter.m_symbol); + send( filter.m_secType); + send( filter.m_exchange); + send( filter.m_side); + } + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_EXEC, "" + e); + close(); + } + } + + public synchronized void cancelOrder( int id) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send cancel order msg + try { + send( CANCEL_ORDER); + send( VERSION); + send( id); + } + catch( Exception e) { + error( id, EClientErrors.FAIL_SEND_CORDER, "" + e); + close(); + } + } + + public synchronized void reqOpenOrders() { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send cancel order msg + try { + send( REQ_OPEN_ORDERS); + send( VERSION); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); + close(); + } + } + + public synchronized void reqIds( int numIds) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + try { + send( REQ_IDS); + send( VERSION); + send( numIds); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, "" + e); + close(); + } + } + + public synchronized void reqNewsBulletins( boolean allMsgs) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + try { + send( REQ_NEWS_BULLETINS); + send( VERSION); + send( allMsgs); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, "" + e); + close(); + } + } + + public synchronized void cancelNewsBulletins() { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send cancel order msg + try { + send( CANCEL_NEWS_BULLETINS); + send( VERSION); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_CORDER, "" + e); + close(); + } + } + + public synchronized void setServerLogLevel(int logLevel) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send the set server logging level message + try { + send( SET_SERVER_LOGLEVEL); + send( VERSION); + send( logLevel); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_SERVER_LOG_LEVEL, "" + e); + close(); + } + } + + public synchronized void reqAutoOpenOrders(boolean bAutoBind) + { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send req open orders msg + try { + send( REQ_AUTO_OPEN_ORDERS); + send( VERSION); + send( bAutoBind); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); + close(); + } + } + + public synchronized void reqAllOpenOrders() { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send req all open orders msg + try { + send( REQ_ALL_OPEN_ORDERS); + send( VERSION); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); + close(); + } + } + + public synchronized void reqManagedAccts() { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + final int VERSION = 1; + + // send req FA managed accounts msg + try { + send( REQ_MANAGED_ACCTS); + send( VERSION); + } + catch( Exception e) { + error(EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_OORDER, "" + e); + close(); + } + } + + public synchronized void requestFA( int faDataType ) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + // This feature is only available for versions of TWS >= 13 + if( m_serverVersion < 13) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 1; + + try { + send( REQ_FA ); + send( VERSION); + send( faDataType); + } + catch( Exception e) { + error( faDataType, EClientErrors.FAIL_SEND_FA_REQUEST, "" + e); + close(); + } + } + + public synchronized void replaceFA( int faDataType, String xml ) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + // This feature is only available for versions of TWS >= 13 + if( m_serverVersion < 13) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS.code(), + EClientErrors.UPDATE_TWS.msg()); + return; + } + + final int VERSION = 1; + + try { + send( REPLACE_FA ); + send( VERSION); + send( faDataType); + send( xml); + } + catch( Exception e) { + error( faDataType, EClientErrors.FAIL_SEND_FA_REPLACE, "" + e); + close(); + } + } + + public synchronized void reqCurrentTime() { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + // This feature is only available for versions of TWS >= 33 + if( m_serverVersion < 33) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support current time requests."); + return; + } + + final int VERSION = 1; + + try { + send( REQ_CURRENT_TIME ); + send( VERSION); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQCURRTIME, "" + e); + close(); + } + } + + public synchronized void reqFundamentalData(int reqId, Contract contract, + String reportType) { + if( !m_connected) { + error( reqId, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { + error( reqId, EClientErrors.UPDATE_TWS, + " It does not support fundamental data requests."); + return; + } + + final int VERSION = 1; + + try { + // send req fund data msg + send( REQ_FUNDAMENTAL_DATA); + send( VERSION); + send( reqId); + + // send contract fields + send( contract.m_symbol); + send( contract.m_secType); + send( contract.m_exchange); + send( contract.m_primaryExch); + send( contract.m_currency); + send( contract.m_localSymbol); + + send( reportType); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_REQFUNDDATA, "" + e); + close(); + } + } + + public synchronized void cancelFundamentalData(int reqId) { + if( !m_connected) { + error( reqId, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if( m_serverVersion < MIN_SERVER_VER_FUNDAMENTAL_DATA) { + error( reqId, EClientErrors.UPDATE_TWS, + " It does not support fundamental data requests."); + return; + } + + final int VERSION = 1; + + try { + // send req mkt data msg + send( CANCEL_FUNDAMENTAL_DATA); + send( VERSION); + send( reqId); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_CANFUNDDATA, "" + e); + close(); + } + } + + public synchronized void calculateImpliedVolatility(int reqId, Contract contract, + double optionPrice, double underPrice) { + + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate implied volatility requests."); + return; + } + + final int VERSION = 1; + + try { + // send calculate implied volatility msg + send( REQ_CALC_IMPLIED_VOLAT); + send( VERSION); + send( reqId); + + // send contract fields + send( contract.m_conId); + send( contract.m_symbol); + send( contract.m_secType); + send( contract.m_expiry); + send( contract.m_strike); + send( contract.m_right); + send( contract.m_multiplier); + send( contract.m_exchange); + send( contract.m_primaryExch); + send( contract.m_currency); + send( contract.m_localSymbol); + + send( optionPrice); + send( underPrice); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_REQCALCIMPLIEDVOLAT, "" + e); + close(); + } + } + + public synchronized void cancelCalculateImpliedVolatility(int reqId) { + + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_IMPLIED_VOLAT) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate implied volatility cancellation."); + return; + } + + final int VERSION = 1; + + try { + // send cancel calculate implied volatility msg + send( CANCEL_CALC_IMPLIED_VOLAT); + send( VERSION); + send( reqId); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_CANCALCIMPLIEDVOLAT, "" + e); + close(); + } + } + + public synchronized void calculateOptionPrice(int reqId, Contract contract, + double volatility, double underPrice) { + + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_CALC_OPTION_PRICE) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate option price requests."); + return; + } + + final int VERSION = 1; + + try { + // send calculate option price msg + send( REQ_CALC_OPTION_PRICE); + send( VERSION); + send( reqId); + + // send contract fields + send( contract.m_conId); + send( contract.m_symbol); + send( contract.m_secType); + send( contract.m_expiry); + send( contract.m_strike); + send( contract.m_right); + send( contract.m_multiplier); + send( contract.m_exchange); + send( contract.m_primaryExch); + send( contract.m_currency); + send( contract.m_localSymbol); + + send( volatility); + send( underPrice); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_REQCALCOPTIONPRICE, "" + e); + close(); + } + } + + public synchronized void cancelCalculateOptionPrice(int reqId) { + + if (!m_connected) { + error(EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_CANCEL_CALC_OPTION_PRICE) { + error(reqId, EClientErrors.UPDATE_TWS, + " It does not support calculate option price cancellation."); + return; + } + + final int VERSION = 1; + + try { + // send cancel calculate option price msg + send( CANCEL_CALC_OPTION_PRICE); + send( VERSION); + send( reqId); + } + catch( Exception e) { + error( reqId, EClientErrors.FAIL_SEND_CANCALCOPTIONPRICE, "" + e); + close(); + } + } + + public synchronized void reqGlobalCancel() { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_GLOBAL_CANCEL) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support globalCancel requests."); + return; + } + + final int VERSION = 1; + + // send request global cancel msg + try { + send( REQ_GLOBAL_CANCEL); + send( VERSION); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQGLOBALCANCEL, "" + e); + close(); + } + } + + public synchronized void reqMarketDataType(int marketDataType) { + // not connected? + if( !m_connected) { + error( EClientErrors.NO_VALID_ID, EClientErrors.NOT_CONNECTED, ""); + return; + } + + if (m_serverVersion < MIN_SERVER_VER_REQ_MARKET_DATA_TYPE) { + error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS, + " It does not support marketDataType requests."); + return; + } + + final int VERSION = 1; + + // send the reqMarketDataType message + try { + send( REQ_MARKET_DATA_TYPE); + send( VERSION); + send( marketDataType); + } + catch( Exception e) { + error( EClientErrors.NO_VALID_ID, EClientErrors.FAIL_SEND_REQMARKETDATATYPE, "" + e); + close(); + } + } + + protected synchronized void error( String err) { + m_anyWrapper.error( err); + } + + protected synchronized void error( int id, int errorCode, String errorMsg) { + m_anyWrapper.error( id, errorCode, errorMsg); + } + + protected void close() { + eDisconnect(); + wrapper().connectionClosed(); + } + + private static boolean is( String str) { + // return true if the string is not empty + return str != null && str.length() > 0; + } + + private static boolean isNull( String str) { + // return true if the string is null or empty + return !is( str); + } + + private void error(int id, EClientErrors.CodeMsgPair pair, String tail) { + error(id, pair.code(), pair.msg() + tail); + } + + protected void send( String str) throws IOException { + // write string to data buffer; writer thread will + // write it to socket + if( !IsEmpty(str)) { + m_dos.write( str.getBytes() ); + } + sendEOL(); + } + + private void sendEOL() throws IOException { + m_dos.write( EOL); + } + + protected void send( int val) throws IOException { + send( String.valueOf( val) ); + } + + protected void send( char val) throws IOException { + m_dos.write( val); + sendEOL(); + } + + protected void send( double val) throws IOException { + send( String.valueOf( val) ); + } + + protected void send( long val) throws IOException { + send( String.valueOf( val) ); + } + + private void sendMax( double val) throws IOException { + if (val == Double.MAX_VALUE) { + sendEOL(); + } + else { + send(String.valueOf(val)); + } + } + + private void sendMax( int val) throws IOException { + if (val == Integer.MAX_VALUE) { + sendEOL(); + } + else { + send(String.valueOf(val)); + } + } + + protected void send( boolean val) throws IOException { + send( val ? 1 : 0); + } + + private static boolean IsEmpty(String str) { + return Util.StringIsEmpty(str); + } + +} diff --git a/ib/src/main/java/com/ib/client/EReader.java b/ib/src/main/java/com/ib/client/EReader.java new file mode 100644 index 00000000..8f16681d --- /dev/null +++ b/ib/src/main/java/com/ib/client/EReader.java @@ -0,0 +1,983 @@ +/* + * EReader.java + * + */ + +package com.ib.client; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.Vector; + +public class EReader extends Thread { + + // incoming msg id's + static final int TICK_PRICE = 1; + static final int TICK_SIZE = 2; + static final int ORDER_STATUS = 3; + static final int ERR_MSG = 4; + static final int OPEN_ORDER = 5; + static final int ACCT_VALUE = 6; + static final int PORTFOLIO_VALUE = 7; + static final int ACCT_UPDATE_TIME = 8; + static final int NEXT_VALID_ID = 9; + static final int CONTRACT_DATA = 10; + static final int EXECUTION_DATA = 11; + static final int MARKET_DEPTH = 12; + static final int MARKET_DEPTH_L2 = 13; + static final int NEWS_BULLETINS = 14; + static final int MANAGED_ACCTS = 15; + static final int RECEIVE_FA = 16; + static final int HISTORICAL_DATA = 17; + static final int BOND_CONTRACT_DATA = 18; + static final int SCANNER_PARAMETERS = 19; + static final int SCANNER_DATA = 20; + static final int TICK_OPTION_COMPUTATION = 21; + static final int TICK_GENERIC = 45; + static final int TICK_STRING = 46; + static final int TICK_EFP = 47; + static final int CURRENT_TIME = 49; + static final int REAL_TIME_BARS = 50; + static final int FUNDAMENTAL_DATA = 51; + static final int CONTRACT_DATA_END = 52; + static final int OPEN_ORDER_END = 53; + static final int ACCT_DOWNLOAD_END = 54; + static final int EXECUTION_DATA_END = 55; + static final int DELTA_NEUTRAL_VALIDATION = 56; + static final int TICK_SNAPSHOT_END = 57; + static final int MARKET_DATA_TYPE = 58; + + private EClientSocket m_parent; + private DataInputStream m_dis; + + protected EClientSocket parent() { return m_parent; } + private EWrapper eWrapper() { return (EWrapper)parent().wrapper(); } + + public EReader( EClientSocket parent, DataInputStream dis) { + this("EReader", parent, dis); + } + + protected EReader( String name, EClientSocket parent, DataInputStream dis) { + setName( name); + m_parent = parent; + m_dis = dis; + } + + public void run() { + try { + // loop until thread is terminated + while( !isInterrupted() && processMsg(readInt())); + } + catch ( Exception ex ) { + if (parent().isConnected()) { + eWrapper().error( ex); + } + } + if (parent().isConnected()) { + m_parent.close(); + } + } + + /** Overridden in subclass. */ + protected boolean processMsg(int msgId) throws IOException{ + if( msgId == -1) return false; + + switch( msgId) { + case TICK_PRICE: { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double price = readDouble(); + int size = 0; + if( version >= 2) { + size = readInt(); + } + int canAutoExecute = 0; + if (version >= 3) { + canAutoExecute = readInt(); + } + eWrapper().tickPrice( tickerId, tickType, price, canAutoExecute); + + if( version >= 2) { + int sizeTickType = -1 ; // not a tick + switch (tickType) { + case 1: // BID + sizeTickType = 0 ; // BID_SIZE + break ; + case 2: // ASK + sizeTickType = 3 ; // ASK_SIZE + break ; + case 4: // LAST + sizeTickType = 5 ; // LAST_SIZE + break ; + } + if (sizeTickType != -1) { + eWrapper().tickSize( tickerId, sizeTickType, size); + } + } + break; + } + case TICK_SIZE: { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + int size = readInt(); + + eWrapper().tickSize( tickerId, tickType, size); + break; + } + + case TICK_OPTION_COMPUTATION: { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double impliedVol = readDouble(); + if (impliedVol < 0) { // -1 is the "not yet computed" indicator + impliedVol = Double.MAX_VALUE; + } + double delta = readDouble(); + if (Math.abs(delta) > 1) { // -2 is the "not yet computed" indicator + delta = Double.MAX_VALUE; + } + double optPrice = Double.MAX_VALUE; + double pvDividend = Double.MAX_VALUE; + double gamma = Double.MAX_VALUE; + double vega = Double.MAX_VALUE; + double theta = Double.MAX_VALUE; + double undPrice = Double.MAX_VALUE; + if (version >= 6 || tickType == TickType.MODEL_OPTION) { // introduced in version == 5 + optPrice = readDouble(); + if (optPrice < 0) { // -1 is the "not yet computed" indicator + optPrice = Double.MAX_VALUE; + } + pvDividend = readDouble(); + if (pvDividend < 0) { // -1 is the "not yet computed" indicator + pvDividend = Double.MAX_VALUE; + } + } + if (version >= 6) { + gamma = readDouble(); + if (Math.abs(gamma) > 1) { // -2 is the "not yet computed" indicator + gamma = Double.MAX_VALUE; + } + vega = readDouble(); + if (Math.abs(vega) > 1) { // -2 is the "not yet computed" indicator + vega = Double.MAX_VALUE; + } + theta = readDouble(); + if (Math.abs(theta) > 1) { // -2 is the "not yet computed" indicator + theta = Double.MAX_VALUE; + } + undPrice = readDouble(); + if (undPrice < 0) { // -1 is the "not yet computed" indicator + undPrice = Double.MAX_VALUE; + } + } + + eWrapper().tickOptionComputation( tickerId, tickType, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice); + break; + } + + case TICK_GENERIC: { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double value = readDouble(); + + eWrapper().tickGeneric( tickerId, tickType, value); + break; + } + + case TICK_STRING: { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + String value = readStr(); + + eWrapper().tickString( tickerId, tickType, value); + break; + } + + case TICK_EFP: { + int version = readInt(); + int tickerId = readInt(); + int tickType = readInt(); + double basisPoints = readDouble(); + String formattedBasisPoints = readStr(); + double impliedFuturesPrice = readDouble(); + int holdDays = readInt(); + String futureExpiry = readStr(); + double dividendImpact = readDouble(); + double dividendsToExpiry = readDouble(); + eWrapper().tickEFP( tickerId, tickType, basisPoints, formattedBasisPoints, + impliedFuturesPrice, holdDays, futureExpiry, dividendImpact, dividendsToExpiry); + break; + } + + case ORDER_STATUS: { + int version = readInt(); + int id = readInt(); + String status = readStr(); + int filled = readInt(); + int remaining = readInt(); + double avgFillPrice = readDouble(); + + int permId = 0; + if( version >= 2) { + permId = readInt(); + } + + int parentId = 0; + if( version >= 3) { + parentId = readInt(); + } + + double lastFillPrice = 0; + if( version >= 4) { + lastFillPrice = readDouble(); + } + + int clientId = 0; + if( version >= 5) { + clientId = readInt(); + } + + String whyHeld = null; + if( version >= 6) { + whyHeld = readStr(); + } + + eWrapper().orderStatus( id, status, filled, remaining, avgFillPrice, + permId, parentId, lastFillPrice, clientId, whyHeld); + break; + } + + case ACCT_VALUE: { + int version = readInt(); + String key = readStr(); + String val = readStr(); + String cur = readStr(); + String accountName = null ; + if( version >= 2) { + accountName = readStr(); + } + eWrapper().updateAccountValue(key, val, cur, accountName); + break; + } + + case PORTFOLIO_VALUE: { + int version = readInt(); + Contract contract = new Contract(); + if (version >= 6) { + contract.m_conId = readInt(); + } + contract.m_symbol = readStr(); + contract.m_secType = readStr(); + contract.m_expiry = readStr(); + contract.m_strike = readDouble(); + contract.m_right = readStr(); + if (version >= 7) { + contract.m_multiplier = readStr(); + contract.m_primaryExch = readStr(); + } + contract.m_currency = readStr(); + if ( version >= 2 ) { + contract.m_localSymbol = readStr(); + } + + int position = readInt(); + double marketPrice = readDouble(); + double marketValue = readDouble(); + double averageCost = 0.0; + double unrealizedPNL = 0.0; + double realizedPNL = 0.0; + if (version >=3 ) { + averageCost = readDouble(); + unrealizedPNL = readDouble(); + realizedPNL = readDouble(); + } + + String accountName = null ; + if( version >= 4) { + accountName = readStr(); + } + + if(version == 6 && m_parent.serverVersion() == 39) { + contract.m_primaryExch = readStr(); + } + + eWrapper().updatePortfolio(contract, position, marketPrice, marketValue, + averageCost, unrealizedPNL, realizedPNL, accountName); + + break; + } + + case ACCT_UPDATE_TIME: { + int version = readInt(); + String timeStamp = readStr(); + eWrapper().updateAccountTime(timeStamp); + break; + } + + case ERR_MSG: { + int version = readInt(); + if(version < 2) { + String msg = readStr(); + m_parent.error( msg); + } else { + int id = readInt(); + int errorCode = readInt(); + String errorMsg = readStr(); + m_parent.error(id, errorCode, errorMsg); + } + break; + } + + case OPEN_ORDER: { + // read version + int version = readInt(); + + // read order id + Order order = new Order(); + order.m_orderId = readInt(); + + // read contract fields + Contract contract = new Contract(); + if (version >= 17) { + contract.m_conId = readInt(); + } + contract.m_symbol = readStr(); + contract.m_secType = readStr(); + contract.m_expiry = readStr(); + contract.m_strike = readDouble(); + contract.m_right = readStr(); + contract.m_exchange = readStr(); + contract.m_currency = readStr(); + if ( version >= 2 ) { + contract.m_localSymbol = readStr(); + } + + // read order fields + order.m_action = readStr(); + order.m_totalQuantity = readInt(); + order.m_orderType = readStr(); + order.m_lmtPrice = readDouble(); + order.m_auxPrice = readDouble(); + order.m_tif = readStr(); + order.m_ocaGroup = readStr(); + order.m_account = readStr(); + order.m_openClose = readStr(); + order.m_origin = readInt(); + order.m_orderRef = readStr(); + + if(version >= 3) { + order.m_clientId = readInt(); + } + + if( version >= 4 ) { + order.m_permId = readInt(); + if ( version < 18) { + // will never happen + /* order.m_ignoreRth = */ readBoolFromInt(); + } + else { + order.m_outsideRth = readBoolFromInt(); + } + order.m_hidden = readInt() == 1; + order.m_discretionaryAmt = readDouble(); + } + + if ( version >= 5 ) { + order.m_goodAfterTime = readStr(); + } + + if ( version >= 6 ) { + // skip deprecated sharesAllocation field + readStr(); + } + + if ( version >= 7 ) { + order.m_faGroup = readStr(); + order.m_faMethod = readStr(); + order.m_faPercentage = readStr(); + order.m_faProfile = readStr(); + } + + if ( version >= 8 ) { + order.m_goodTillDate = readStr(); + } + + if ( version >= 9) { + order.m_rule80A = readStr(); + order.m_percentOffset = readDouble(); + order.m_settlingFirm = readStr(); + order.m_shortSaleSlot = readInt(); + order.m_designatedLocation = readStr(); + if ( m_parent.serverVersion() == 51){ + readInt(); // exemptCode + } + else if ( version >= 23){ + order.m_exemptCode = readInt(); + } + order.m_auctionStrategy = readInt(); + order.m_startingPrice = readDouble(); + order.m_stockRefPrice = readDouble(); + order.m_delta = readDouble(); + order.m_stockRangeLower = readDouble(); + order.m_stockRangeUpper = readDouble(); + order.m_displaySize = readInt(); + if ( version < 18) { + // will never happen + /* order.m_rthOnly = */ readBoolFromInt(); + } + order.m_blockOrder = readBoolFromInt(); + order.m_sweepToFill = readBoolFromInt(); + order.m_allOrNone = readBoolFromInt(); + order.m_minQty = readInt(); + order.m_ocaType = readInt(); + order.m_eTradeOnly = readBoolFromInt(); + order.m_firmQuoteOnly = readBoolFromInt(); + order.m_nbboPriceCap = readDouble(); + } + + if ( version >= 10) { + order.m_parentId = readInt(); + order.m_triggerMethod = readInt(); + } + + if (version >= 11) { + order.m_volatility = readDouble(); + order.m_volatilityType = readInt(); + if (version == 11) { + int receivedInt = readInt(); + order.m_deltaNeutralOrderType = ( (receivedInt == 0) ? "NONE" : "MKT" ); + } else { // version 12 and up + order.m_deltaNeutralOrderType = readStr(); + order.m_deltaNeutralAuxPrice = readDouble(); + + if (version >= 27 && !Util.StringIsEmpty(order.m_deltaNeutralOrderType)) { + order.m_deltaNeutralConId = readInt(); + order.m_deltaNeutralSettlingFirm = readStr(); + order.m_deltaNeutralClearingAccount = readStr(); + order.m_deltaNeutralClearingIntent = readStr(); + } + } + order.m_continuousUpdate = readInt(); + if (m_parent.serverVersion() == 26) { + order.m_stockRangeLower = readDouble(); + order.m_stockRangeUpper = readDouble(); + } + order.m_referencePriceType = readInt(); + } + + if (version >= 13) { + order.m_trailStopPrice = readDouble(); + } + + if (version >= 14) { + order.m_basisPoints = readDouble(); + order.m_basisPointsType = readInt(); + contract.m_comboLegsDescrip = readStr(); + } + + if (version >= 26) { + int smartComboRoutingParamsCount = readInt(); + if (smartComboRoutingParamsCount > 0) { + order.m_smartComboRoutingParams = new Vector(smartComboRoutingParamsCount); + for (int i = 0; i < smartComboRoutingParamsCount; ++i) { + TagValue tagValue = new TagValue(); + tagValue.m_tag = readStr(); + tagValue.m_value = readStr(); + order.m_smartComboRoutingParams.add(tagValue); + } + } + } + + if (version >= 15) { + if (version >= 20) { + order.m_scaleInitLevelSize = readIntMax(); + order.m_scaleSubsLevelSize = readIntMax(); + } + else { + /* int notSuppScaleNumComponents = */ readIntMax(); + order.m_scaleInitLevelSize = readIntMax(); + } + order.m_scalePriceIncrement = readDoubleMax(); + } + + if (version >= 24) { + order.m_hedgeType = readStr(); + if (!Util.StringIsEmpty(order.m_hedgeType)) { + order.m_hedgeParam = readStr(); + } + } + + if (version >= 25) { + order.m_optOutSmartRouting = readBoolFromInt(); + } + + if (version >= 19) { + order.m_clearingAccount = readStr(); + order.m_clearingIntent = readStr(); + } + + if (version >= 22) { + order.m_notHeld = readBoolFromInt(); + } + + if (version >= 20) { + if (readBoolFromInt()) { + UnderComp underComp = new UnderComp(); + underComp.m_conId = readInt(); + underComp.m_delta = readDouble(); + underComp.m_price = readDouble(); + contract.m_underComp = underComp; + } + } + + if (version >= 21) { + order.m_algoStrategy = readStr(); + if (!Util.StringIsEmpty(order.m_algoStrategy)) { + int algoParamsCount = readInt(); + if (algoParamsCount > 0) { + order.m_algoParams = new Vector(algoParamsCount); + for (int i = 0; i < algoParamsCount; ++i) { + TagValue tagValue = new TagValue(); + tagValue.m_tag = readStr(); + tagValue.m_value = readStr(); + order.m_algoParams.add(tagValue); + } + } + } + } + + OrderState orderState = new OrderState(); + + if (version >= 16) { + + order.m_whatIf = readBoolFromInt(); + + orderState.m_status = readStr(); + orderState.m_initMargin = readStr(); + orderState.m_maintMargin = readStr(); + orderState.m_equityWithLoan = readStr(); + orderState.m_commission = readDoubleMax(); + orderState.m_minCommission = readDoubleMax(); + orderState.m_maxCommission = readDoubleMax(); + orderState.m_commissionCurrency = readStr(); + orderState.m_warningText = readStr(); + } + + eWrapper().openOrder( order.m_orderId, contract, order, orderState); + break; + } + + case NEXT_VALID_ID: { + int version = readInt(); + int orderId = readInt(); + eWrapper().nextValidId( orderId); + break; + } + + case SCANNER_DATA: { + ContractDetails contract = new ContractDetails(); + int version = readInt(); + int tickerId = readInt(); + int numberOfElements = readInt(); + for (int ctr=0; ctr < numberOfElements; ctr++) { + int rank = readInt(); + if (version >= 3) { + contract.m_summary.m_conId = readInt(); + } + contract.m_summary.m_symbol = readStr(); + contract.m_summary.m_secType = readStr(); + contract.m_summary.m_expiry = readStr(); + contract.m_summary.m_strike = readDouble(); + contract.m_summary.m_right = readStr(); + contract.m_summary.m_exchange = readStr(); + contract.m_summary.m_currency = readStr(); + contract.m_summary.m_localSymbol = readStr(); + contract.m_marketName = readStr(); + contract.m_tradingClass = readStr(); + String distance = readStr(); + String benchmark = readStr(); + String projection = readStr(); + String legsStr = null; + if (version >= 2) { + legsStr = readStr(); + } + eWrapper().scannerData(tickerId, rank, contract, distance, + benchmark, projection, legsStr); + } + eWrapper().scannerDataEnd(tickerId); + break; + } + + case CONTRACT_DATA: { + int version = readInt(); + + int reqId = -1; + if (version >= 3) { + reqId = readInt(); + } + + ContractDetails contract = new ContractDetails(); + contract.m_summary.m_symbol = readStr(); + contract.m_summary.m_secType = readStr(); + contract.m_summary.m_expiry = readStr(); + contract.m_summary.m_strike = readDouble(); + contract.m_summary.m_right = readStr(); + contract.m_summary.m_exchange = readStr(); + contract.m_summary.m_currency = readStr(); + contract.m_summary.m_localSymbol = readStr(); + contract.m_marketName = readStr(); + contract.m_tradingClass = readStr(); + contract.m_summary.m_conId = readInt(); + contract.m_minTick = readDouble(); + contract.m_summary.m_multiplier = readStr(); + contract.m_orderTypes = readStr(); + contract.m_validExchanges = readStr(); + if (version >= 2) { + contract.m_priceMagnifier = readInt(); + } + if (version >= 4) { + contract.m_underConId = readInt(); + } + if( version >= 5) { + contract.m_longName = readStr(); + contract.m_summary.m_primaryExch = readStr(); + } + if( version >= 6) { + contract.m_contractMonth = readStr(); + contract.m_industry = readStr(); + contract.m_category = readStr(); + contract.m_subcategory = readStr(); + contract.m_timeZoneId = readStr(); + contract.m_tradingHours = readStr(); + contract.m_liquidHours = readStr(); + } + eWrapper().contractDetails( reqId, contract); + break; + } + case BOND_CONTRACT_DATA: { + int version = readInt(); + + int reqId = -1; + if (version >= 3) { + reqId = readInt(); + } + + ContractDetails contract = new ContractDetails(); + + contract.m_summary.m_symbol = readStr(); + contract.m_summary.m_secType = readStr(); + contract.m_cusip = readStr(); + contract.m_coupon = readDouble(); + contract.m_maturity = readStr(); + contract.m_issueDate = readStr(); + contract.m_ratings = readStr(); + contract.m_bondType = readStr(); + contract.m_couponType = readStr(); + contract.m_convertible = readBoolFromInt(); + contract.m_callable = readBoolFromInt(); + contract.m_putable = readBoolFromInt(); + contract.m_descAppend = readStr(); + contract.m_summary.m_exchange = readStr(); + contract.m_summary.m_currency = readStr(); + contract.m_marketName = readStr(); + contract.m_tradingClass = readStr(); + contract.m_summary.m_conId = readInt(); + contract.m_minTick = readDouble(); + contract.m_orderTypes = readStr(); + contract.m_validExchanges = readStr(); + if (version >= 2) { + contract.m_nextOptionDate = readStr(); + contract.m_nextOptionType = readStr(); + contract.m_nextOptionPartial = readBoolFromInt(); + contract.m_notes = readStr(); + } + if( version >= 4) { + contract.m_longName = readStr(); + } + eWrapper().bondContractDetails( reqId, contract); + break; + } + case EXECUTION_DATA: { + int version = readInt(); + + int reqId = -1; + if (version >= 7) { + reqId = readInt(); + } + + int orderId = readInt(); + + // read contract fields + Contract contract = new Contract(); + if (version >= 5) { + contract.m_conId = readInt(); + } + contract.m_symbol = readStr(); + contract.m_secType = readStr(); + contract.m_expiry = readStr(); + contract.m_strike = readDouble(); + contract.m_right = readStr(); + contract.m_exchange = readStr(); + contract.m_currency = readStr(); + contract.m_localSymbol = readStr(); + + Execution exec = new Execution(); + exec.m_orderId = orderId; + exec.m_execId = readStr(); + exec.m_time = readStr(); + exec.m_acctNumber = readStr(); + exec.m_exchange = readStr(); + exec.m_side = readStr(); + exec.m_shares = readInt(); + exec.m_price = readDouble(); + if ( version >= 2 ) { + exec.m_permId = readInt(); + } + if ( version >= 3) { + exec.m_clientId = readInt(); + } + if ( version >= 4) { + exec.m_liquidation = readInt(); + } + if (version >= 6) { + exec.m_cumQty = readInt(); + exec.m_avgPrice = readDouble(); + } + if (version >= 8) { + exec.m_orderRef = readStr(); + } + eWrapper().execDetails( reqId, contract, exec); + break; + } + case MARKET_DEPTH: { + int version = readInt(); + int id = readInt(); + + int position = readInt(); + int operation = readInt(); + int side = readInt(); + double price = readDouble(); + int size = readInt(); + + eWrapper().updateMktDepth(id, position, operation, + side, price, size); + break; + } + case MARKET_DEPTH_L2: { + int version = readInt(); + int id = readInt(); + + int position = readInt(); + String marketMaker = readStr(); + int operation = readInt(); + int side = readInt(); + double price = readDouble(); + int size = readInt(); + + eWrapper().updateMktDepthL2(id, position, marketMaker, + operation, side, price, size); + break; + } + case NEWS_BULLETINS: { + int version = readInt(); + int newsMsgId = readInt(); + int newsMsgType = readInt(); + String newsMessage = readStr(); + String originatingExch = readStr(); + + eWrapper().updateNewsBulletin( newsMsgId, newsMsgType, newsMessage, originatingExch); + break; + } + case MANAGED_ACCTS: { + int version = readInt(); + String accountsList = readStr(); + + eWrapper().managedAccounts( accountsList); + break; + } + case RECEIVE_FA: { + int version = readInt(); + int faDataType = readInt(); + String xml = readStr(); + + eWrapper().receiveFA(faDataType, xml); + break; + } + case HISTORICAL_DATA: { + int version = readInt(); + int reqId = readInt(); + String startDateStr; + String endDateStr; + String completedIndicator = "finished"; + if (version >= 2) { + startDateStr = readStr(); + endDateStr = readStr(); + completedIndicator += "-" + startDateStr + "-" + endDateStr; + } + int itemCount = readInt(); + for (int ctr = 0; ctr < itemCount; ctr++) { + String date = readStr(); + double open = readDouble(); + double high = readDouble(); + double low = readDouble(); + double close = readDouble(); + int volume = readInt(); + double WAP = readDouble(); + String hasGaps = readStr(); + int barCount = -1; + if (version >= 3) { + barCount = readInt(); + } + eWrapper().historicalData(reqId, date, open, high, low, + close, volume, barCount, WAP, + Boolean.valueOf(hasGaps).booleanValue()); + } + // send end of dataset marker + eWrapper().historicalData(reqId, completedIndicator, -1, -1, -1, -1, -1, -1, -1, false); + break; + } + case SCANNER_PARAMETERS: { + int version = readInt(); + String xml = readStr(); + eWrapper().scannerParameters(xml); + break; + } + case CURRENT_TIME: { + /*int version =*/ readInt(); + long time = readLong(); + eWrapper().currentTime(time); + break; + } + case REAL_TIME_BARS: { + /*int version =*/ readInt(); + int reqId = readInt(); + long time = readLong(); + double open = readDouble(); + double high = readDouble(); + double low = readDouble(); + double close = readDouble(); + long volume = readLong(); + double wap = readDouble(); + int count = readInt(); + eWrapper().realtimeBar(reqId, time, open, high, low, close, volume, wap, count); + break; + } + case FUNDAMENTAL_DATA: { + /*int version =*/ readInt(); + int reqId = readInt(); + String data = readStr(); + eWrapper().fundamentalData(reqId, data); + break; + } + case CONTRACT_DATA_END: { + /*int version =*/ readInt(); + int reqId = readInt(); + eWrapper().contractDetailsEnd(reqId); + break; + } + case OPEN_ORDER_END: { + /*int version =*/ readInt(); + eWrapper().openOrderEnd(); + break; + } + case ACCT_DOWNLOAD_END: { + /*int version =*/ readInt(); + String accountName = readStr(); + eWrapper().accountDownloadEnd( accountName); + break; + } + case EXECUTION_DATA_END: { + /*int version =*/ readInt(); + int reqId = readInt(); + eWrapper().execDetailsEnd( reqId); + break; + } + case DELTA_NEUTRAL_VALIDATION: { + /*int version =*/ readInt(); + int reqId = readInt(); + + UnderComp underComp = new UnderComp(); + underComp.m_conId = readInt(); + underComp.m_delta = readDouble(); + underComp.m_price = readDouble(); + + eWrapper().deltaNeutralValidation( reqId, underComp); + break; + } + case TICK_SNAPSHOT_END: { + /*int version =*/ readInt(); + int reqId = readInt(); + + eWrapper().tickSnapshotEnd( reqId); + break; + } + case MARKET_DATA_TYPE: { + /*int version =*/ readInt(); + int reqId = readInt(); + int marketDataType = readInt(); + + eWrapper().marketDataType( reqId, marketDataType); + break; + } + + default: { + m_parent.error( EClientErrors.NO_VALID_ID, EClientErrors.UNKNOWN_ID.code(), EClientErrors.UNKNOWN_ID.msg()); + return false; + } + } + return true; + } + + + protected String readStr() throws IOException { + StringBuffer buf = new StringBuffer(); + while( true) { + byte c = m_dis.readByte(); + if( c == 0) { + break; + } + buf.append( (char)c); + } + + String str = buf.toString(); + return str.length() == 0 ? null : str; + } + + + boolean readBoolFromInt() throws IOException { + String str = readStr(); + return str == null ? false : (Integer.parseInt( str) != 0); + } + + protected int readInt() throws IOException { + String str = readStr(); + return str == null ? 0 : Integer.parseInt( str); + } + + protected int readIntMax() throws IOException { + String str = readStr(); + return (str == null || str.length() == 0) ? Integer.MAX_VALUE + : Integer.parseInt( str); + } + + protected long readLong() throws IOException { + String str = readStr(); + return str == null ? 0l : Long.parseLong(str); + } + + protected double readDouble() throws IOException { + String str = readStr(); + return str == null ? 0 : Double.parseDouble( str); + } + + protected double readDoubleMax() throws IOException { + String str = readStr(); + return (str == null || str.length() == 0) ? Double.MAX_VALUE + : Double.parseDouble( str); + } +} diff --git a/ib/src/main/java/com/ib/client/EWrapper.java b/ib/src/main/java/com/ib/client/EWrapper.java new file mode 100644 index 00000000..30aafbcf --- /dev/null +++ b/ib/src/main/java/com/ib/client/EWrapper.java @@ -0,0 +1,56 @@ +/* + * EWrapper.java + * + */ +package com.ib.client; + +public interface EWrapper extends AnyWrapper { + + /////////////////////////////////////////////////////////////////////// + // Interface methods + /////////////////////////////////////////////////////////////////////// + void tickPrice( int tickerId, int field, double price, int canAutoExecute); + void tickSize( int tickerId, int field, int size); + void tickOptionComputation( int tickerId, int field, double impliedVol, + double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice); + void tickGeneric(int tickerId, int tickType, double value); + void tickString(int tickerId, int tickType, String value); + void tickEFP(int tickerId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry); + void orderStatus( int orderId, String status, int filled, int remaining, + double avgFillPrice, int permId, int parentId, double lastFillPrice, + int clientId, String whyHeld); + void openOrder( int orderId, Contract contract, Order order, OrderState orderState); + void openOrderEnd(); + void updateAccountValue(String key, String value, String currency, String accountName); + void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, + double averageCost, double unrealizedPNL, double realizedPNL, String accountName); + void updateAccountTime(String timeStamp); + void accountDownloadEnd(String accountName); + void nextValidId( int orderId); + void contractDetails(int reqId, ContractDetails contractDetails); + void bondContractDetails(int reqId, ContractDetails contractDetails); + void contractDetailsEnd(int reqId); + void execDetails( int reqId, Contract contract, Execution execution); + void execDetailsEnd( int reqId); + void updateMktDepth( int tickerId, int position, int operation, int side, double price, int size); + void updateMktDepthL2( int tickerId, int position, String marketMaker, int operation, + int side, double price, int size); + void updateNewsBulletin( int msgId, int msgType, String message, String origExchange); + void managedAccounts( String accountsList); + void receiveFA(int faDataType, String xml); + void historicalData(int reqId, String date, double open, double high, double low, + double close, int volume, int count, double WAP, boolean hasGaps); + void scannerParameters(String xml); + void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, + String benchmark, String projection, String legsStr); + void scannerDataEnd(int reqId); + void realtimeBar(int reqId, long time, double open, double high, double low, double close, long volume, double wap, int count); + void currentTime(long time); + void fundamentalData(int reqId, String data); + void deltaNeutralValidation(int reqId, UnderComp underComp); + void tickSnapshotEnd(int reqId); + void marketDataType(int reqId, int marketDataType); +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/EWrapperMsgGenerator.java b/ib/src/main/java/com/ib/client/EWrapperMsgGenerator.java new file mode 100644 index 00000000..41b775e3 --- /dev/null +++ b/ib/src/main/java/com/ib/client/EWrapperMsgGenerator.java @@ -0,0 +1,437 @@ +package com.ib.client; + +import java.text.DateFormat; +import java.util.Date; +import java.util.Vector; + +public class EWrapperMsgGenerator extends AnyWrapperMsgGenerator { + public static final String SCANNER_PARAMETERS = "SCANNER PARAMETERS:"; + public static final String FINANCIAL_ADVISOR = "FA:"; + + static public String tickPrice( int tickerId, int field, double price, int canAutoExecute) { + return "id=" + tickerId + " " + TickType.getField( field) + "=" + price + " " + + ((canAutoExecute != 0) ? " canAutoExecute" : " noAutoExecute"); + } + + static public String tickSize( int tickerId, int field, int size) { + return "id=" + tickerId + " " + TickType.getField( field) + "=" + size; + } + + static public String tickOptionComputation( int tickerId, int field, double impliedVol, + double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + String toAdd = "id=" + tickerId + " " + TickType.getField( field) + + ": vol = " + ((impliedVol >= 0 && impliedVol != Double.MAX_VALUE) ? Double.toString(impliedVol) : "N/A") + + " delta = " + ((Math.abs(delta) <= 1) ? Double.toString(delta) : "N/A") + + " gamma = " + ((Math.abs(gamma) <= 1) ? Double.toString(gamma) : "N/A") + + " vega = " + ((Math.abs(vega) <= 1) ? Double.toString(vega) : "N/A") + + " theta = " + ((Math.abs(theta) <= 1) ? Double.toString(theta) : "N/A") + + " optPrice = " + ((optPrice >= 0 && optPrice != Double.MAX_VALUE) ? Double.toString(optPrice) : "N/A") + + " pvDividend = " + ((pvDividend >= 0 && pvDividend != Double.MAX_VALUE) ? Double.toString(pvDividend) : "N/A") + + " undPrice = " + ((undPrice >= 0 && undPrice != Double.MAX_VALUE) ? Double.toString(undPrice) : "N/A"); + return toAdd; + } + + static public String tickGeneric(int tickerId, int tickType, double value) { + return "id=" + tickerId + " " + TickType.getField( tickType) + "=" + value; + } + + static public String tickString(int tickerId, int tickType, String value) { + return "id=" + tickerId + " " + TickType.getField( tickType) + "=" + value; + } + + static public String tickEFP(int tickerId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry) { + return "id=" + tickerId + " " + TickType.getField(tickType) + + ": basisPoints = " + basisPoints + "/" + formattedBasisPoints + + " impliedFuture = " + impliedFuture + " holdDays = " + holdDays + + " futureExpiry = " + futureExpiry + " dividendImpact = " + dividendImpact + + " dividends to expiry = " + dividendsToExpiry; + } + + static public String orderStatus( int orderId, String status, int filled, int remaining, + double avgFillPrice, int permId, int parentId, double lastFillPrice, + int clientId, String whyHeld) { + return "order status: orderId=" + orderId + " clientId=" + clientId + " permId=" + permId + + " status=" + status + " filled=" + filled + " remaining=" + remaining + + " avgFillPrice=" + avgFillPrice + " lastFillPrice=" + lastFillPrice + + " parent Id=" + parentId + " whyHeld=" + whyHeld; + } + + static public String openOrder( int orderId, Contract contract, Order order, OrderState orderState) { + String msg = "open order: orderId=" + orderId + + " action=" + order.m_action + + " quantity=" + order.m_totalQuantity + + " symbol=" + contract.m_symbol + + " exchange=" + contract.m_exchange + + " secType=" + contract.m_secType + + " type=" + order.m_orderType + + " lmtPrice=" + order.m_lmtPrice + + " auxPrice=" + order.m_auxPrice + + " TIF=" + order.m_tif + + " localSymbol=" + contract.m_localSymbol + + " client Id=" + order.m_clientId + + " parent Id=" + order.m_parentId + + " permId=" + order.m_permId + + " outsideRth=" + order.m_outsideRth + + " hidden=" + order.m_hidden + + " discretionaryAmt=" + order.m_discretionaryAmt + + " triggerMethod=" + order.m_triggerMethod + + " goodAfterTime=" + order.m_goodAfterTime + + " goodTillDate=" + order.m_goodTillDate + + " faGroup=" + order.m_faGroup + + " faMethod=" + order.m_faMethod + + " faPercentage=" + order.m_faPercentage + + " faProfile=" + order.m_faProfile + + " shortSaleSlot=" + order.m_shortSaleSlot + + " designatedLocation=" + order.m_designatedLocation + + " exemptCode=" + order.m_exemptCode + + " ocaGroup=" + order.m_ocaGroup + + " ocaType=" + order.m_ocaType + + " rule80A=" + order.m_rule80A + + " allOrNone=" + order.m_allOrNone + + " minQty=" + order.m_minQty + + " percentOffset=" + order.m_percentOffset + + " eTradeOnly=" + order.m_eTradeOnly + + " firmQuoteOnly=" + order.m_firmQuoteOnly + + " nbboPriceCap=" + order.m_nbboPriceCap + + " optOutSmartRouting=" + order.m_optOutSmartRouting + + " auctionStrategy=" + order.m_auctionStrategy + + " startingPrice=" + order.m_startingPrice + + " stockRefPrice=" + order.m_stockRefPrice + + " delta=" + order.m_delta + + " stockRangeLower=" + order.m_stockRangeLower + + " stockRangeUpper=" + order.m_stockRangeUpper + + " volatility=" + order.m_volatility + + " volatilityType=" + order.m_volatilityType + + " deltaNeutralOrderType=" + order.m_deltaNeutralOrderType + + " deltaNeutralAuxPrice=" + order.m_deltaNeutralAuxPrice + + " deltaNeutralConId=" + order.m_deltaNeutralConId + + " deltaNeutralSettlingFirm=" + order.m_deltaNeutralSettlingFirm + + " deltaNeutralClearingAccount=" + order.m_deltaNeutralClearingAccount + + " deltaNeutralClearingIntent=" + order.m_deltaNeutralClearingIntent + + " continuousUpdate=" + order.m_continuousUpdate + + " referencePriceType=" + order.m_referencePriceType + + " trailStopPrice=" + order.m_trailStopPrice + + " scaleInitLevelSize=" + Util.IntMaxString(order.m_scaleInitLevelSize) + + " scaleSubsLevelSize=" + Util.IntMaxString(order.m_scaleSubsLevelSize) + + " scalePriceIncrement=" + Util.DoubleMaxString(order.m_scalePriceIncrement) + + " hedgeType=" + order.m_hedgeType + + " hedgeParam=" + order.m_hedgeParam + + " account=" + order.m_account + + " settlingFirm=" + order.m_settlingFirm + + " clearingAccount=" + order.m_clearingAccount + + " clearingIntent=" + order.m_clearingIntent + + " notHeld=" + order.m_notHeld + + " whatIf=" + order.m_whatIf + ; + + if ("BAG".equals(contract.m_secType)) { + if (contract.m_comboLegsDescrip != null) { + msg += " comboLegsDescrip=" + contract.m_comboLegsDescrip; + } + if (order.m_basisPoints != Double.MAX_VALUE) { + msg += " basisPoints=" + order.m_basisPoints; + msg += " basisPointsType=" + order.m_basisPointsType; + } + } + + if (contract.m_underComp != null) { + UnderComp underComp = contract.m_underComp; + msg += + " underComp.conId =" + underComp.m_conId + + " underComp.delta =" + underComp.m_delta + + " underComp.price =" + underComp.m_price ; + } + + if (!Util.StringIsEmpty(order.m_algoStrategy)) { + msg += " algoStrategy=" + order.m_algoStrategy; + msg += " algoParams={"; + if (order.m_algoParams != null) { + Vector algoParams = order.m_algoParams; + for (int i = 0; i < algoParams.size(); ++i) { + TagValue param = (TagValue)algoParams.elementAt(i); + if (i > 0) { + msg += ","; + } + msg += param.m_tag + "=" + param.m_value; + } + } + msg += "}"; + } + + if ("BAG".equals(contract.m_secType)) { + msg += " smartComboRoutingParams={"; + if (order.m_smartComboRoutingParams != null) { + Vector smartComboRoutingParams = order.m_smartComboRoutingParams; + for (int i = 0; i < smartComboRoutingParams.size(); ++i) { + TagValue param = (TagValue)smartComboRoutingParams.elementAt(i); + if (i > 0) { + msg += ","; + } + msg += param.m_tag + "=" + param.m_value; + } + } + msg += "}"; + } + + String orderStateMsg = + " status=" + orderState.m_status + + " initMargin=" + orderState.m_initMargin + + " maintMargin=" + orderState.m_maintMargin + + " equityWithLoan=" + orderState.m_equityWithLoan + + " commission=" + Util.DoubleMaxString(orderState.m_commission) + + " minCommission=" + Util.DoubleMaxString(orderState.m_minCommission) + + " maxCommission=" + Util.DoubleMaxString(orderState.m_maxCommission) + + " commissionCurrency=" + orderState.m_commissionCurrency + + " warningText=" + orderState.m_warningText + ; + + return msg + orderStateMsg; + } + + static public String openOrderEnd() { + return " =============== end ==============="; + } + + static public String updateAccountValue(String key, String value, String currency, String accountName) { + return "updateAccountValue: " + key + " " + value + " " + currency + " " + accountName; + } + + static public String updatePortfolio(Contract contract, int position, double marketPrice, + double marketValue, double averageCost, double unrealizedPNL, + double realizedPNL, String accountName) { + String msg = "updatePortfolio: " + + contractMsg(contract) + + position + " " + marketPrice + " " + marketValue + " " + averageCost + " " + unrealizedPNL + " " + realizedPNL + " " + accountName; + return msg; + } + + static public String updateAccountTime(String timeStamp) { + return "updateAccountTime: " + timeStamp; + } + + static public String accountDownloadEnd(String accountName) { + return "accountDownloadEnd: " + accountName; + } + + static public String nextValidId( int orderId) { + return "Next Valid Order ID: " + orderId; + } + + static public String contractDetails(int reqId, ContractDetails contractDetails) { + Contract contract = contractDetails.m_summary; + String msg = "reqId = " + reqId + " ===================================\n" + + " ---- Contract Details begin ----\n" + + contractMsg(contract) + contractDetailsMsg(contractDetails) + + " ---- Contract Details End ----\n"; + return msg; + } + + private static String contractDetailsMsg(ContractDetails contractDetails) { + String msg = "marketName = " + contractDetails.m_marketName + "\n" + + "tradingClass = " + contractDetails.m_tradingClass + "\n" + + "minTick = " + contractDetails.m_minTick + "\n" + + "price magnifier = " + contractDetails.m_priceMagnifier + "\n" + + "orderTypes = " + contractDetails.m_orderTypes + "\n" + + "validExchanges = " + contractDetails.m_validExchanges + "\n" + + "underConId = " + contractDetails.m_underConId + "\n" + + "longName = " + contractDetails.m_longName + "\n" + + "contractMonth = " + contractDetails.m_contractMonth + "\n" + + "industry = " + contractDetails.m_industry + "\n" + + "category = " + contractDetails.m_category + "\n" + + "subcategory = " + contractDetails.m_subcategory + "\n" + + "timeZoneId = " + contractDetails.m_timeZoneId + "\n" + + "tradingHours = " + contractDetails.m_tradingHours + "\n" + + "liquidHours = " + contractDetails.m_liquidHours + "\n"; + return msg; + } + + static public String contractMsg(Contract contract) { + String msg = "conid = " + contract.m_conId + "\n" + + "symbol = " + contract.m_symbol + "\n" + + "secType = " + contract.m_secType + "\n" + + "expiry = " + contract.m_expiry + "\n" + + "strike = " + contract.m_strike + "\n" + + "right = " + contract.m_right + "\n" + + "multiplier = " + contract.m_multiplier + "\n" + + "exchange = " + contract.m_exchange + "\n" + + "primaryExch = " + contract.m_primaryExch + "\n" + + "currency = " + contract.m_currency + "\n" + + "localSymbol = " + contract.m_localSymbol + "\n"; + return msg; + } + + static public String bondContractDetails(int reqId, ContractDetails contractDetails) { + Contract contract = contractDetails.m_summary; + String msg = "reqId = " + reqId + " ===================================\n" + + " ---- Bond Contract Details begin ----\n" + + "symbol = " + contract.m_symbol + "\n" + + "secType = " + contract.m_secType + "\n" + + "cusip = " + contractDetails.m_cusip + "\n" + + "coupon = " + contractDetails.m_coupon + "\n" + + "maturity = " + contractDetails.m_maturity + "\n" + + "issueDate = " + contractDetails.m_issueDate + "\n" + + "ratings = " + contractDetails.m_ratings + "\n" + + "bondType = " + contractDetails.m_bondType + "\n" + + "couponType = " + contractDetails.m_couponType + "\n" + + "convertible = " + contractDetails.m_convertible + "\n" + + "callable = " + contractDetails.m_callable + "\n" + + "putable = " + contractDetails.m_putable + "\n" + + "descAppend = " + contractDetails.m_descAppend + "\n" + + "exchange = " + contract.m_exchange + "\n" + + "currency = " + contract.m_currency + "\n" + + "marketName = " + contractDetails.m_marketName + "\n" + + "tradingClass = " + contractDetails.m_tradingClass + "\n" + + "conid = " + contract.m_conId + "\n" + + "minTick = " + contractDetails.m_minTick + "\n" + + "orderTypes = " + contractDetails.m_orderTypes + "\n" + + "validExchanges = " + contractDetails.m_validExchanges + "\n" + + "nextOptionDate = " + contractDetails.m_nextOptionDate + "\n" + + "nextOptionType = " + contractDetails.m_nextOptionType + "\n" + + "nextOptionPartial = " + contractDetails.m_nextOptionPartial + "\n" + + "notes = " + contractDetails.m_notes + "\n" + + "longName = " + contractDetails.m_longName + "\n" + + " ---- Bond Contract Details End ----\n"; + return msg; + } + + static public String contractDetailsEnd(int reqId) { + return "reqId = " + reqId + " =============== end ==============="; + } + + static public String execDetails( int reqId, Contract contract, Execution execution) { + String msg = " ---- Execution Details begin ----\n" + + "reqId = " + reqId + "\n" + + "orderId = " + execution.m_orderId + "\n" + + "clientId = " + execution.m_clientId + "\n" + + "symbol = " + contract.m_symbol + "\n" + + "secType = " + contract.m_secType + "\n" + + "expiry = " + contract.m_expiry + "\n" + + "strike = " + contract.m_strike + "\n" + + "right = " + contract.m_right + "\n" + + "contractExchange = " + contract.m_exchange + "\n" + + "currency = " + contract.m_currency + "\n" + + "localSymbol = " + contract.m_localSymbol + "\n" + + "execId = " + execution.m_execId + "\n" + + "time = " + execution.m_time + "\n" + + "acctNumber = " + execution.m_acctNumber + "\n" + + "executionExchange = " + execution.m_exchange + "\n" + + "side = " + execution.m_side + "\n" + + "shares = " + execution.m_shares + "\n" + + "price = " + execution.m_price + "\n" + + "permId = " + execution.m_permId + "\n" + + "liquidation = " + execution.m_liquidation + "\n" + + "cumQty = " + execution.m_cumQty + "\n" + + "avgPrice = " + execution.m_avgPrice + "\n" + + "orderRef = " + execution.m_orderRef + "\n" + + " ---- Execution Details end ----\n"; + return msg; + } + + static public String execDetailsEnd(int reqId) { + return "reqId = " + reqId + " =============== end ==============="; + } + + static public String updateMktDepth( int tickerId, int position, int operation, int side, + double price, int size) { + return "updateMktDepth: " + tickerId + " " + position + " " + operation + " " + side + " " + price + " " + size; + } + + static public String updateMktDepthL2( int tickerId, int position, String marketMaker, + int operation, int side, double price, int size) { + return "updateMktDepth: " + tickerId + " " + position + " " + marketMaker + " " + operation + " " + side + " " + price + " " + size; + } + + static public String updateNewsBulletin( int msgId, int msgType, String message, String origExchange) { + return "MsgId=" + msgId + " :: MsgType=" + msgType + " :: Origin=" + origExchange + " :: Message=" + message; + } + + static public String managedAccounts( String accountsList) { + return "Connected : The list of managed accounts are : [" + accountsList + "]"; + } + + static public String receiveFA(int faDataType, String xml) { + return FINANCIAL_ADVISOR + " " + EClientSocket.faMsgTypeName(faDataType) + " " + xml; + } + + static public String historicalData(int reqId, String date, double open, double high, double low, + double close, int volume, int count, double WAP, boolean hasGaps) { + return "id=" + reqId + + " date = " + date + + " open=" + open + + " high=" + high + + " low=" + low + + " close=" + close + + " volume=" + volume + + " count=" + count + + " WAP=" + WAP + + " hasGaps=" + hasGaps; + } + public static String realtimeBar(int reqId, long time, double open, + double high, double low, double close, long volume, double wap, int count) { + return "id=" + reqId + + " time = " + time + + " open=" + open + + " high=" + high + + " low=" + low + + " close=" + close + + " volume=" + volume + + " count=" + count + + " WAP=" + wap; + } + + static public String scannerParameters(String xml) { + return SCANNER_PARAMETERS + "\n" + xml; + } + + static public String scannerData(int reqId, int rank, ContractDetails contractDetails, + String distance, String benchmark, String projection, + String legsStr) { + Contract contract = contractDetails.m_summary; + return "id = " + reqId + + " rank=" + rank + + " symbol=" + contract.m_symbol + + " secType=" + contract.m_secType + + " expiry=" + contract.m_expiry + + " strike=" + contract.m_strike + + " right=" + contract.m_right + + " exchange=" + contract.m_exchange + + " currency=" + contract.m_currency + + " localSymbol=" + contract.m_localSymbol + + " marketName=" + contractDetails.m_marketName + + " tradingClass=" + contractDetails.m_tradingClass + + " distance=" + distance + + " benchmark=" + benchmark + + " projection=" + projection + + " legsStr=" + legsStr; + } + + static public String scannerDataEnd(int reqId) { + return "id = " + reqId + " =============== end ==============="; + } + + static public String currentTime(long time) { + return "current time = " + time + + " (" + DateFormat.getDateTimeInstance().format(new Date(time * 1000)) + ")"; + } + + static public String fundamentalData(int reqId, String data) { + return "id = " + reqId + " len = " + data.length() + '\n' + data; + } + + static public String deltaNeutralValidation(int reqId, UnderComp underComp) { + return "id = " + reqId + + " underComp.conId =" + underComp.m_conId + + " underComp.delta =" + underComp.m_delta + + " underComp.price =" + underComp.m_price; + } + static public String tickSnapshotEnd(int tickerId) { + return "id=" + tickerId + " =============== end ==============="; + } + + static public String marketDataType(int reqId, int marketDataType){ + return "id=" + reqId + " marketDataType = " + MarketDataType.getField(marketDataType); + } +} diff --git a/ib/src/main/java/com/ib/client/Execution.java b/ib/src/main/java/com/ib/client/Execution.java new file mode 100644 index 00000000..9cffb7f4 --- /dev/null +++ b/ib/src/main/java/com/ib/client/Execution.java @@ -0,0 +1,69 @@ +/* + * Execution.java + * + */ +package com.ib.client; + +public class Execution { + public int m_orderId; + public int m_clientId; + public String m_execId; + public String m_time; + public String m_acctNumber; + public String m_exchange; + public String m_side; + public int m_shares; + public double m_price; + public int m_permId; + public int m_liquidation; + public int m_cumQty; + public double m_avgPrice; + public String m_orderRef; + + public Execution() { + m_orderId = 0; + m_clientId = 0; + m_shares = 0; + m_price = 0; + m_permId = 0; + m_liquidation = 0; + m_cumQty = 0; + m_avgPrice = 0; + } + + public Execution( int p_orderId, int p_clientId, String p_execId, String p_time, + String p_acctNumber, String p_exchange, String p_side, int p_shares, + double p_price, int p_permId, int p_liquidation, int p_cumQty, + double p_avgPrice, String p_orderRef) { + m_orderId = p_orderId; + m_clientId = p_clientId; + m_execId = p_execId; + m_time = p_time; + m_acctNumber = p_acctNumber; + m_exchange = p_exchange; + m_side = p_side; + m_shares = p_shares; + m_price = p_price; + m_permId = p_permId; + m_liquidation = p_liquidation; + m_cumQty = p_cumQty; + m_avgPrice = p_avgPrice; + m_orderRef = p_orderRef; + } + + public boolean equals(Object p_other) { + boolean l_bRetVal = false; + + if ( p_other == null ) { + l_bRetVal = false; + } + else if ( this == p_other ) { + l_bRetVal = true; + } + else { + Execution l_theOther = (Execution)p_other; + l_bRetVal = m_execId.equals( l_theOther.m_execId); + } + return l_bRetVal; + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/ExecutionFilter.java b/ib/src/main/java/com/ib/client/ExecutionFilter.java new file mode 100644 index 00000000..3cfad9ea --- /dev/null +++ b/ib/src/main/java/com/ib/client/ExecutionFilter.java @@ -0,0 +1,52 @@ +/* + * ExecutionFilter.java + * + */ +package com.ib.client; + +public class ExecutionFilter{ + public int m_clientId; + public String m_acctCode; + public String m_time; + public String m_symbol; + public String m_secType; + public String m_exchange; + public String m_side; + + public ExecutionFilter() { + m_clientId = 0; + } + + public ExecutionFilter( int p_clientId, String p_acctCode, String p_time, + String p_symbol, String p_secType, String p_exchange, String p_side) { + m_clientId = p_clientId; + m_acctCode = p_acctCode; + m_time = p_time; + m_symbol = p_symbol; + m_secType = p_secType; + m_exchange = p_exchange; + m_side = p_side; + } + + public boolean equals(Object p_other) { + boolean l_bRetVal = false; + + if ( p_other == null ) { + l_bRetVal = false; + } + else if ( this == p_other ) { + l_bRetVal = true; + } + else { + ExecutionFilter l_theOther = (ExecutionFilter)p_other; + l_bRetVal = (m_clientId == l_theOther.m_clientId && + m_acctCode.equalsIgnoreCase( l_theOther.m_acctCode) && + m_time.equalsIgnoreCase( l_theOther.m_time) && + m_symbol.equalsIgnoreCase( l_theOther.m_symbol) && + m_secType.equalsIgnoreCase( l_theOther.m_secType) && + m_exchange.equalsIgnoreCase( l_theOther.m_exchange) && + m_side.equalsIgnoreCase( l_theOther.m_side) ); + } + return l_bRetVal; + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/MarketDataType.java b/ib/src/main/java/com/ib/client/MarketDataType.java new file mode 100644 index 00000000..354fc9e9 --- /dev/null +++ b/ib/src/main/java/com/ib/client/MarketDataType.java @@ -0,0 +1,29 @@ +/* + * MarketDataType.java + * + */ +package com.ib.client; + +public class MarketDataType { + // constants - market data types + public static final int REALTIME = 1; + public static final int FROZEN = 2; + + public static String getField( int marketDataType) { + switch( marketDataType) { + case REALTIME: return "Real-Time"; + case FROZEN: return "Frozen"; + + default: return "Unknown"; + } + } + + public static String[] getFields(){ + int totalFields = MarketDataType.class.getFields().length; + String [] fields = new String[totalFields]; + for (int i = 0; i < totalFields; i++){ + fields[i] = MarketDataType.getField(i + 1); + } + return fields; + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/Order.java b/ib/src/main/java/com/ib/client/Order.java new file mode 100644 index 00000000..bbe28202 --- /dev/null +++ b/ib/src/main/java/com/ib/client/Order.java @@ -0,0 +1,268 @@ +/* + * Order.java + * + */ +package com.ib.client; + +import java.util.Vector; + +public class Order { + final public static int CUSTOMER = 0; + final public static int FIRM = 1; + final public static char OPT_UNKNOWN='?'; + final public static char OPT_BROKER_DEALER='b'; + final public static char OPT_CUSTOMER ='c'; + final public static char OPT_FIRM='f'; + final public static char OPT_ISEMM='m'; + final public static char OPT_FARMM='n'; + final public static char OPT_SPECIALIST='y'; + final public static int AUCTION_MATCH = 1; + final public static int AUCTION_IMPROVEMENT = 2; + final public static int AUCTION_TRANSPARENT = 3; + final public static String EMPTY_STR = ""; + + // main order fields + public int m_orderId; + public int m_clientId; + public int m_permId; + public String m_action; + public int m_totalQuantity; + public String m_orderType; + public double m_lmtPrice; + public double m_auxPrice; + + // extended order fields + public String m_tif; // "Time in Force" - DAY, GTC, etc. + public String m_ocaGroup; // one cancels all group name + public int m_ocaType; // 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK + public String m_orderRef; + public boolean m_transmit; // if false, order will be created but not transmited + public int m_parentId; // Parent order Id, to associate Auto STP or TRAIL orders with the original order. + public boolean m_blockOrder; + public boolean m_sweepToFill; + public int m_displaySize; + public int m_triggerMethod; // 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point + public boolean m_outsideRth; + public boolean m_hidden; + public String m_goodAfterTime; // FORMAT: 20060505 08:00:00 {time zone} + public String m_goodTillDate; // FORMAT: 20060505 08:00:00 {time zone} + public boolean m_overridePercentageConstraints; + public String m_rule80A; // Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N' + public boolean m_allOrNone; + public int m_minQty; + public double m_percentOffset; // REL orders only + public double m_trailStopPrice; // for TRAILLIMIT orders only + + // Financial advisors only + public String m_faGroup; + public String m_faProfile; + public String m_faMethod; + public String m_faPercentage; + + // Institutional orders only + public String m_openClose; // O=Open, C=Close + public int m_origin; // 0=Customer, 1=Firm + public int m_shortSaleSlot; // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action="SSHORT + public String m_designatedLocation; // set when slot=2 only. + public int m_exemptCode; + + // SMART routing only + public double m_discretionaryAmt; + public boolean m_eTradeOnly; + public boolean m_firmQuoteOnly; + public double m_nbboPriceCap; + public boolean m_optOutSmartRouting; + + // BOX or VOL ORDERS ONLY + public int m_auctionStrategy; // 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT + + // BOX ORDERS ONLY + public double m_startingPrice; + public double m_stockRefPrice; + public double m_delta; + + // pegged to stock or VOL orders + public double m_stockRangeLower; + public double m_stockRangeUpper; + + // VOLATILITY ORDERS ONLY + public double m_volatility; + public int m_volatilityType; // 1=daily, 2=annual + public int m_continuousUpdate; + public int m_referencePriceType; // 1=Average, 2 = BidOrAsk + public String m_deltaNeutralOrderType; + public double m_deltaNeutralAuxPrice; + public int m_deltaNeutralConId; + public String m_deltaNeutralSettlingFirm; + public String m_deltaNeutralClearingAccount; + public String m_deltaNeutralClearingIntent; + + // COMBO ORDERS ONLY + public double m_basisPoints; // EFP orders only + public int m_basisPointsType; // EFP orders only + + // SCALE ORDERS ONLY + public int m_scaleInitLevelSize; + public int m_scaleSubsLevelSize; + public double m_scalePriceIncrement; + + // HEDGE ORDERS ONLY + public String m_hedgeType; // 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair + public String m_hedgeParam; // beta value for beta hedge, ratio for pair hedge + + // Clearing info + public String m_account; // IB account + public String m_settlingFirm; + public String m_clearingAccount; // True beneficiary of the order + public String m_clearingIntent; // "" (Default), "IB", "Away", "PTA" (PostTrade) + + // ALGO ORDERS ONLY + public String m_algoStrategy; + public Vector m_algoParams; + + // What-if + public boolean m_whatIf; + + // Not Held + public boolean m_notHeld; + + // Smart combo routing params + public Vector m_smartComboRoutingParams; + + public Order() { + m_outsideRth = false; + m_openClose = "O"; + m_origin = CUSTOMER; + m_transmit = true; + m_designatedLocation = EMPTY_STR; + m_exemptCode = -1; + m_minQty = Integer.MAX_VALUE; + m_percentOffset = Double.MAX_VALUE; + m_nbboPriceCap = Double.MAX_VALUE; + m_optOutSmartRouting = false; + m_startingPrice = Double.MAX_VALUE; + m_stockRefPrice = Double.MAX_VALUE; + m_delta = Double.MAX_VALUE; + m_stockRangeLower = Double.MAX_VALUE; + m_stockRangeUpper = Double.MAX_VALUE; + m_volatility = Double.MAX_VALUE; + m_volatilityType = Integer.MAX_VALUE; + m_deltaNeutralOrderType = EMPTY_STR; + m_deltaNeutralAuxPrice = Double.MAX_VALUE; + m_deltaNeutralConId = 0; + m_deltaNeutralSettlingFirm = EMPTY_STR; + m_deltaNeutralClearingAccount = EMPTY_STR; + m_deltaNeutralClearingIntent = EMPTY_STR; + m_referencePriceType = Integer.MAX_VALUE; + m_trailStopPrice = Double.MAX_VALUE; + m_basisPoints = Double.MAX_VALUE; + m_basisPointsType = Integer.MAX_VALUE; + m_scaleInitLevelSize = Integer.MAX_VALUE; + m_scaleSubsLevelSize = Integer.MAX_VALUE; + m_scalePriceIncrement = Double.MAX_VALUE; + m_whatIf = false; + m_notHeld = false; + } + + public boolean equals(Object p_other) { + + if ( this == p_other ) + return true; + + if ( p_other == null ) + return false; + + Order l_theOther = (Order)p_other; + + if ( m_permId == l_theOther.m_permId ) { + return true; + } + + if (m_orderId != l_theOther.m_orderId || + m_clientId != l_theOther.m_clientId || + m_totalQuantity != l_theOther.m_totalQuantity || + m_lmtPrice != l_theOther.m_lmtPrice || + m_auxPrice != l_theOther.m_auxPrice || + m_ocaType != l_theOther.m_ocaType || + m_transmit != l_theOther.m_transmit || + m_parentId != l_theOther.m_parentId || + m_blockOrder != l_theOther.m_blockOrder || + m_sweepToFill != l_theOther.m_sweepToFill || + m_displaySize != l_theOther.m_displaySize || + m_triggerMethod != l_theOther.m_triggerMethod || + m_outsideRth != l_theOther.m_outsideRth || + m_hidden != l_theOther.m_hidden || + m_overridePercentageConstraints != l_theOther.m_overridePercentageConstraints || + m_allOrNone != l_theOther.m_allOrNone || + m_minQty != l_theOther.m_minQty || + m_percentOffset != l_theOther.m_percentOffset || + m_trailStopPrice != l_theOther.m_trailStopPrice || + m_origin != l_theOther.m_origin || + m_shortSaleSlot != l_theOther.m_shortSaleSlot || + m_discretionaryAmt != l_theOther.m_discretionaryAmt || + m_eTradeOnly != l_theOther.m_eTradeOnly || + m_firmQuoteOnly != l_theOther.m_firmQuoteOnly || + m_nbboPriceCap != l_theOther.m_nbboPriceCap || + m_optOutSmartRouting != l_theOther.m_optOutSmartRouting || + m_auctionStrategy != l_theOther.m_auctionStrategy || + m_startingPrice != l_theOther.m_startingPrice || + m_stockRefPrice != l_theOther.m_stockRefPrice || + m_delta != l_theOther.m_delta || + m_stockRangeLower != l_theOther.m_stockRangeLower || + m_stockRangeUpper != l_theOther.m_stockRangeUpper || + m_volatility != l_theOther.m_volatility || + m_volatilityType != l_theOther.m_volatilityType || + m_continuousUpdate != l_theOther.m_continuousUpdate || + m_referencePriceType != l_theOther.m_referencePriceType || + m_deltaNeutralAuxPrice != l_theOther.m_deltaNeutralAuxPrice || + m_deltaNeutralConId != l_theOther.m_deltaNeutralConId || + m_basisPoints != l_theOther.m_basisPoints || + m_basisPointsType != l_theOther.m_basisPointsType || + m_scaleInitLevelSize != l_theOther.m_scaleInitLevelSize || + m_scaleSubsLevelSize != l_theOther.m_scaleSubsLevelSize || + m_scalePriceIncrement != l_theOther.m_scalePriceIncrement || + m_whatIf != l_theOther.m_whatIf || + m_notHeld != l_theOther.m_notHeld || + m_exemptCode != l_theOther.m_exemptCode) { + return false; + } + + if (Util.StringCompare(m_action, l_theOther.m_action) != 0 || + Util.StringCompare(m_orderType, l_theOther.m_orderType) != 0 || + Util.StringCompare(m_tif, l_theOther.m_tif) != 0 || + Util.StringCompare(m_ocaGroup, l_theOther.m_ocaGroup) != 0 || + Util.StringCompare(m_orderRef,l_theOther.m_orderRef) != 0 || + Util.StringCompare(m_goodAfterTime, l_theOther.m_goodAfterTime) != 0 || + Util.StringCompare(m_goodTillDate, l_theOther.m_goodTillDate) != 0 || + Util.StringCompare(m_rule80A, l_theOther.m_rule80A) != 0 || + Util.StringCompare(m_faGroup, l_theOther.m_faGroup) != 0 || + Util.StringCompare(m_faProfile, l_theOther.m_faProfile) != 0 || + Util.StringCompare(m_faMethod, l_theOther.m_faMethod) != 0 || + Util.StringCompare(m_faPercentage, l_theOther.m_faPercentage) != 0 || + Util.StringCompare(m_openClose, l_theOther.m_openClose) != 0 || + Util.StringCompare(m_designatedLocation, l_theOther.m_designatedLocation) != 0 || + Util.StringCompare(m_deltaNeutralOrderType, l_theOther.m_deltaNeutralOrderType) != 0 || + Util.StringCompare(m_deltaNeutralSettlingFirm, l_theOther.m_deltaNeutralSettlingFirm) != 0 || + Util.StringCompare(m_deltaNeutralClearingAccount, l_theOther.m_deltaNeutralClearingAccount) != 0 || + Util.StringCompare(m_deltaNeutralClearingIntent, l_theOther.m_deltaNeutralClearingIntent) != 0 || + Util.StringCompare(m_hedgeType, l_theOther.m_hedgeType) != 0 || + Util.StringCompare(m_hedgeParam, l_theOther.m_hedgeParam) != 0 || + Util.StringCompare(m_account, l_theOther.m_account) != 0 || + Util.StringCompare(m_settlingFirm, l_theOther.m_settlingFirm) != 0 || + Util.StringCompare(m_clearingAccount, l_theOther.m_clearingAccount) != 0 || + Util.StringCompare(m_clearingIntent, l_theOther.m_clearingIntent) != 0 || + Util.StringCompare(m_algoStrategy, l_theOther.m_algoStrategy) != 0) { + return false; + } + + if (!Util.VectorEqualsUnordered(m_algoParams, l_theOther.m_algoParams)) { + return false; + } + + if (!Util.VectorEqualsUnordered(m_smartComboRoutingParams, l_theOther.m_smartComboRoutingParams)) { + return false; + } + + return true; + } +} diff --git a/ib/src/main/java/com/ib/client/OrderState.java b/ib/src/main/java/com/ib/client/OrderState.java new file mode 100644 index 00000000..fde2984d --- /dev/null +++ b/ib/src/main/java/com/ib/client/OrderState.java @@ -0,0 +1,65 @@ +/* + * OrderState.java + */ +package com.ib.client; + +public class OrderState { + + public String m_status; + + public String m_initMargin; + public String m_maintMargin; + public String m_equityWithLoan; + + public double m_commission; + public double m_minCommission; + public double m_maxCommission; + public String m_commissionCurrency; + + public String m_warningText; + + OrderState() { + this (null, null, null, null, 0.0, 0.0, 0.0, null, null); + } + + OrderState(String status, String initMargin, String maintMargin, + String equityWithLoan, double commission, double minCommission, + double maxCommission, String commissionCurrency, String warningText) { + + m_initMargin = initMargin; + m_maintMargin = maintMargin; + m_equityWithLoan = equityWithLoan; + m_commission = commission; + m_minCommission = minCommission; + m_maxCommission = maxCommission; + m_commissionCurrency = commissionCurrency; + m_warningText = warningText; + } + + public boolean equals(Object other) { + + if (this == other) + return true; + + if (other == null) + return false; + + OrderState state = (OrderState)other; + + if (m_commission != state.m_commission || + m_minCommission != state.m_minCommission || + m_maxCommission != state.m_maxCommission) { + return false; + } + + if (Util.StringCompare(m_status, state.m_status) != 0 || + Util.StringCompare(m_initMargin, state.m_initMargin) != 0 || + Util.StringCompare(m_maintMargin, state.m_maintMargin) != 0 || + Util.StringCompare(m_equityWithLoan, state.m_equityWithLoan) != 0 || + Util.StringCompare(m_commissionCurrency, state.m_commissionCurrency) != 0) { + return false; + } + + return true; + } +} diff --git a/ib/src/main/java/com/ib/client/ScannerSubscription.java b/ib/src/main/java/com/ib/client/ScannerSubscription.java new file mode 100644 index 00000000..03631ca6 --- /dev/null +++ b/ib/src/main/java/com/ib/client/ScannerSubscription.java @@ -0,0 +1,73 @@ +package com.ib.client; + +public class ScannerSubscription { + public final static int NO_ROW_NUMBER_SPECIFIED = -1; + + private int m_numberOfRows = NO_ROW_NUMBER_SPECIFIED; + private String m_instrument; + private String m_locationCode; + private String m_scanCode; + private double m_abovePrice = Double.MAX_VALUE; + private double m_belowPrice = Double.MAX_VALUE; + private int m_aboveVolume = Integer.MAX_VALUE; + private int m_averageOptionVolumeAbove = Integer.MAX_VALUE; + private double m_marketCapAbove = Double.MAX_VALUE; + private double m_marketCapBelow = Double.MAX_VALUE; + private String m_moodyRatingAbove; + private String m_moodyRatingBelow; + private String m_spRatingAbove; + private String m_spRatingBelow; + private String m_maturityDateAbove; + private String m_maturityDateBelow; + private double m_couponRateAbove = Double.MAX_VALUE; + private double m_couponRateBelow = Double.MAX_VALUE; + private String m_excludeConvertible; + private String m_scannerSettingPairs; + private String m_stockTypeFilter; + + // Get + public int numberOfRows() { return m_numberOfRows; } + public String instrument() { return m_instrument; } + public String locationCode() { return m_locationCode; } + public String scanCode() { return m_scanCode; } + public double abovePrice() { return m_abovePrice; } + public double belowPrice() { return m_belowPrice; } + public int aboveVolume() { return m_aboveVolume; } + public int averageOptionVolumeAbove() { return m_averageOptionVolumeAbove; } + public double marketCapAbove() { return m_marketCapAbove; } + public double marketCapBelow() { return m_marketCapBelow; } + public String moodyRatingAbove() { return m_moodyRatingAbove; } + public String moodyRatingBelow() { return m_moodyRatingBelow; } + public String spRatingAbove() { return m_spRatingAbove; } + public String spRatingBelow() { return m_spRatingBelow; } + public String maturityDateAbove() { return m_maturityDateAbove; } + public String maturityDateBelow() { return m_maturityDateBelow; } + public double couponRateAbove() { return m_couponRateAbove; } + public double couponRateBelow() { return m_couponRateBelow; } + public String excludeConvertible() { return m_excludeConvertible; } + public String scannerSettingPairs() { return m_scannerSettingPairs; } + public String stockTypeFilter() { return m_stockTypeFilter; } + + // Set + public void numberOfRows(int num) { m_numberOfRows = num; } + public void instrument(String txt) { m_instrument = txt; } + public void locationCode(String txt) { m_locationCode = txt; } + public void scanCode(String txt) { m_scanCode = txt; } + public void abovePrice(double price) { m_abovePrice = price; } + public void belowPrice(double price) { m_belowPrice = price; } + public void aboveVolume(int volume) { m_aboveVolume = volume; } + public void averageOptionVolumeAbove(int volume) { m_averageOptionVolumeAbove = volume; } + public void marketCapAbove(double cap) { m_marketCapAbove = cap; } + public void marketCapBelow(double cap) { m_marketCapBelow = cap; } + public void moodyRatingAbove(String r) { m_moodyRatingAbove = r; } + public void moodyRatingBelow(String r) { m_moodyRatingBelow = r; } + public void spRatingAbove(String r) { m_spRatingAbove = r; } + public void spRatingBelow(String r) { m_spRatingBelow = r; } + public void maturityDateAbove(String d) { m_maturityDateAbove = d; } + public void maturityDateBelow(String d) { m_maturityDateBelow = d; } + public void couponRateAbove(double r) { m_couponRateAbove = r; } + public void couponRateBelow(double r) { m_couponRateBelow = r; } + public void excludeConvertible(String c) { m_excludeConvertible = c; } + public void scannerSettingPairs(String val) { m_scannerSettingPairs = val; } + public void stockTypeFilter(String val) { m_stockTypeFilter = val; } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/TagValue.java b/ib/src/main/java/com/ib/client/TagValue.java new file mode 100644 index 00000000..0b2adeff --- /dev/null +++ b/ib/src/main/java/com/ib/client/TagValue.java @@ -0,0 +1,38 @@ +/* + * UnderComp.java + * + */ + +package com.ib.client; + +public class TagValue { + + public String m_tag; + public String m_value; + + public TagValue() { + } + + public TagValue(String p_tag, String p_value) { + m_tag = p_tag; + m_value = p_value; + } + + public boolean equals(Object p_other) { + + if( this == p_other) + return true; + + if( p_other == null) + return false; + + TagValue l_theOther = (TagValue)p_other; + + if( Util.StringCompare(m_tag, l_theOther.m_tag) != 0 || + Util.StringCompare(m_value, l_theOther.m_value) != 0) { + return false; + } + + return true; + } +} diff --git a/ib/src/main/java/com/ib/client/TickType.java b/ib/src/main/java/com/ib/client/TickType.java new file mode 100644 index 00000000..d2bd6afc --- /dev/null +++ b/ib/src/main/java/com/ib/client/TickType.java @@ -0,0 +1,131 @@ +/* + * TickType.java + * + */ +package com.ib.client; + +public class TickType { + // constants - tick types + public static final int BID_SIZE = 0; + public static final int BID = 1; + public static final int ASK = 2; + public static final int ASK_SIZE = 3; + public static final int LAST = 4; + public static final int LAST_SIZE = 5; + public static final int HIGH = 6; + public static final int LOW = 7; + public static final int VOLUME = 8; + public static final int CLOSE = 9; + public static final int BID_OPTION = 10; + public static final int ASK_OPTION = 11; + public static final int LAST_OPTION = 12; + public static final int MODEL_OPTION = 13; + public static final int OPEN = 14; + public static final int LOW_13_WEEK = 15; + public static final int HIGH_13_WEEK = 16; + public static final int LOW_26_WEEK = 17; + public static final int HIGH_26_WEEK = 18; + public static final int LOW_52_WEEK = 19; + public static final int HIGH_52_WEEK = 20; + public static final int AVG_VOLUME = 21; + public static final int OPEN_INTEREST = 22; + public static final int OPTION_HISTORICAL_VOL = 23; + public static final int OPTION_IMPLIED_VOL = 24; + public static final int OPTION_BID_EXCH = 25; + public static final int OPTION_ASK_EXCH = 26; + public static final int OPTION_CALL_OPEN_INTEREST = 27; + public static final int OPTION_PUT_OPEN_INTEREST = 28; + public static final int OPTION_CALL_VOLUME = 29; + public static final int OPTION_PUT_VOLUME = 30; + public static final int INDEX_FUTURE_PREMIUM = 31; + public static final int BID_EXCH = 32; + public static final int ASK_EXCH = 33; + public static final int AUCTION_VOLUME = 34; + public static final int AUCTION_PRICE = 35; + public static final int AUCTION_IMBALANCE = 36; + public static final int MARK_PRICE = 37; + public static final int BID_EFP_COMPUTATION = 38; + public static final int ASK_EFP_COMPUTATION = 39; + public static final int LAST_EFP_COMPUTATION = 40; + public static final int OPEN_EFP_COMPUTATION = 41; + public static final int HIGH_EFP_COMPUTATION = 42; + public static final int LOW_EFP_COMPUTATION = 43; + public static final int CLOSE_EFP_COMPUTATION = 44; + public static final int LAST_TIMESTAMP = 45; + public static final int SHORTABLE = 46; + public static final int FUNDAMENTAL_RATIOS = 47; + public static final int RT_VOLUME = 48; + public static final int HALTED = 49; + public static final int BID_YIELD = 50; + public static final int ASK_YIELD = 51; + public static final int LAST_YIELD = 52; + public static final int CUST_OPTION_COMPUTATION = 53; + public static final int TRADE_COUNT = 54; + public static final int TRADE_RATE = 55; + public static final int VOLUME_RATE = 56; + public static final int LAST_RTH_TRADE = 57; + + public static String getField( int tickType) { + switch( tickType) { + case BID_SIZE: return "bidSize"; + case BID: return "bidPrice"; + case ASK: return "askPrice"; + case ASK_SIZE: return "askSize"; + case LAST: return "lastPrice"; + case LAST_SIZE: return "lastSize"; + case HIGH: return "high"; + case LOW: return "low"; + case VOLUME: return "volume"; + case CLOSE: return "close"; + case BID_OPTION: return "bidOptComp"; + case ASK_OPTION: return "askOptComp"; + case LAST_OPTION: return "lastOptComp"; + case MODEL_OPTION: return "modelOptComp"; + case OPEN: return "open"; + case LOW_13_WEEK: return "13WeekLow"; + case HIGH_13_WEEK: return "13WeekHigh"; + case LOW_26_WEEK: return "26WeekLow"; + case HIGH_26_WEEK: return "26WeekHigh"; + case LOW_52_WEEK: return "52WeekLow"; + case HIGH_52_WEEK: return "52WeekHigh"; + case AVG_VOLUME: return "AvgVolume"; + case OPEN_INTEREST: return "OpenInterest"; + case OPTION_HISTORICAL_VOL: return "OptionHistoricalVolatility"; + case OPTION_IMPLIED_VOL: return "OptionImpliedVolatility"; + case OPTION_BID_EXCH: return "OptionBidExchStr"; + case OPTION_ASK_EXCH: return "OptionAskExchStr"; + case OPTION_CALL_OPEN_INTEREST: return "OptionCallOpenInterest"; + case OPTION_PUT_OPEN_INTEREST: return "OptionPutOpenInterest"; + case OPTION_CALL_VOLUME: return "OptionCallVolume"; + case OPTION_PUT_VOLUME: return "OptionPutVolume"; + case INDEX_FUTURE_PREMIUM: return "IndexFuturePremium"; + case BID_EXCH: return "bidExch"; + case ASK_EXCH: return "askExch"; + case AUCTION_VOLUME: return "auctionVolume"; + case AUCTION_PRICE: return "auctionPrice"; + case AUCTION_IMBALANCE: return "auctionImbalance"; + case MARK_PRICE: return "markPrice"; + case BID_EFP_COMPUTATION: return "bidEFP"; + case ASK_EFP_COMPUTATION: return "askEFP"; + case LAST_EFP_COMPUTATION: return "lastEFP"; + case OPEN_EFP_COMPUTATION: return "openEFP"; + case HIGH_EFP_COMPUTATION: return "highEFP"; + case LOW_EFP_COMPUTATION: return "lowEFP"; + case CLOSE_EFP_COMPUTATION: return "closeEFP"; + case LAST_TIMESTAMP: return "lastTimestamp"; + case SHORTABLE: return "shortable"; + case FUNDAMENTAL_RATIOS: return "fundamentals"; + case RT_VOLUME: return "RTVolume"; + case HALTED: return "halted"; + case BID_YIELD: return "bidYield"; + case ASK_YIELD: return "askYield"; + case LAST_YIELD: return "lastYield"; + case CUST_OPTION_COMPUTATION: return "custOptComp"; + case TRADE_COUNT: return "trades"; + case TRADE_RATE: return "trades/min"; + case VOLUME_RATE: return "volume/min"; + case LAST_RTH_TRADE: return "lastRTHTrade"; + default: return "unknown"; + } + } +} \ No newline at end of file diff --git a/ib/src/main/java/com/ib/client/UnderComp.java b/ib/src/main/java/com/ib/client/UnderComp.java new file mode 100644 index 00000000..9e0b7358 --- /dev/null +++ b/ib/src/main/java/com/ib/client/UnderComp.java @@ -0,0 +1,44 @@ +/* + * UnderComp.java + * + */ + +package com.ib.client; + +public class UnderComp { + + public int m_conId; + public double m_delta; + public double m_price; + + public UnderComp() { + m_conId = 0; + m_delta = 0; + m_price = 0; + } + + public boolean equals(Object p_other) { + + if (this == p_other) { + return true; + } + + if (p_other == null || !(p_other instanceof UnderComp)) { + return false; + } + + UnderComp l_theOther = (UnderComp)p_other; + + if (m_conId != l_theOther.m_conId) { + return false; + } + if (m_delta != l_theOther.m_delta) { + return false; + } + if (m_price != l_theOther.m_price) { + return false; + } + + return true; + } +} diff --git a/ib/src/main/java/com/ib/client/Util.java b/ib/src/main/java/com/ib/client/Util.java new file mode 100644 index 00000000..a8d90ef5 --- /dev/null +++ b/ib/src/main/java/com/ib/client/Util.java @@ -0,0 +1,71 @@ +/* + * Util.java + */ +package com.ib.client; + +import java.util.Vector; + +public class Util { + + public static boolean StringIsEmpty(String str) { + return str == null || str.length() == 0; + } + + public static String NormalizeString(String str) { + return str != null ? str : ""; + } + + public static int StringCompare(String lhs, String rhs) { + return NormalizeString(lhs).compareTo(NormalizeString(rhs)); + } + + public static int StringCompareIgnCase(String lhs, String rhs) { + return NormalizeString(lhs).compareToIgnoreCase(NormalizeString(rhs)); + } + + public static boolean VectorEqualsUnordered(Vector lhs, Vector rhs) { + + if (lhs == rhs) + return true; + + int lhsCount = lhs == null ? 0 : lhs.size(); + int rhsCount = rhs == null ? 0 : rhs.size(); + + if (lhsCount != rhsCount) + return false; + + if (lhsCount == 0) + return true; + + boolean[] matchedRhsElems = new boolean[rhsCount]; + + for (int lhsIdx = 0; lhsIdx < lhsCount; ++lhsIdx) { + Object lhsElem = lhs.get(lhsIdx); + int rhsIdx = 0; + for (; rhsIdx < rhsCount; ++rhsIdx) { + if (matchedRhsElems[rhsIdx]) { + continue; + } + if (lhsElem.equals(rhs.get(rhsIdx))) { + matchedRhsElems[rhsIdx] = true; + break; + } + } + if (rhsIdx >= rhsCount) { + // no matching elem found + return false; + } + } + + return true; + } + + public static String IntMaxString(int value) { + return (value == Integer.MAX_VALUE) ? "" : "" + value; + } + + public static String DoubleMaxString(double value) { + return (value == Double.MAX_VALUE) ? "" : "" + value; + } + +} diff --git a/ib/src/main/java/samples/base/ComboContract.java b/ib/src/main/java/samples/base/ComboContract.java new file mode 100644 index 00000000..a46afe17 --- /dev/null +++ b/ib/src/main/java/samples/base/ComboContract.java @@ -0,0 +1,32 @@ +/* + * ComboContract.java + */ +package samples.base; + +import com.ib.client.Contract; + +public class ComboContract extends Contract { + + public ComboContract(String symbol) { + m_symbol = symbol; + m_secType = "BAG"; + m_currency = "USD"; + m_exchange = "SMART"; + } + + public ComboContract(String symbol, String currency) { + m_symbol = symbol; + m_secType = "BAG"; + m_currency = currency; + m_exchange = "SMART"; + } + + public ComboContract(String symbol, String currency, String exchange) { + m_symbol = symbol; + m_secType = "BAG"; + m_currency = currency; + m_exchange = exchange; + } +} + + diff --git a/ib/src/main/java/samples/base/FutContract.java b/ib/src/main/java/samples/base/FutContract.java new file mode 100644 index 00000000..cec333a5 --- /dev/null +++ b/ib/src/main/java/samples/base/FutContract.java @@ -0,0 +1,25 @@ +/* + * FutContract.java + */ +package samples.base; + +import com.ib.client.Contract; + +public class FutContract extends Contract { + + public FutContract(String symbol, String expiry) { + m_symbol = symbol; + m_secType = "FUT"; + m_exchange = "ONE"; + m_currency = "USD"; + m_expiry = expiry; + } + + public FutContract(String symbol, String expiry, String currency) { + m_symbol = symbol; + m_secType = "FUT"; + m_currency = currency; + m_expiry = expiry; + } +} + diff --git a/ib/src/main/java/samples/base/OptContract.java b/ib/src/main/java/samples/base/OptContract.java new file mode 100644 index 00000000..dbc11174 --- /dev/null +++ b/ib/src/main/java/samples/base/OptContract.java @@ -0,0 +1,33 @@ +/* + * OptContract.java + */ +package samples.base; + +import com.ib.client.Contract; + +public class OptContract extends Contract { + + public OptContract(String symbol, String expiry, double strike, + String right) { + m_symbol = symbol; + m_secType = "OPT"; + m_exchange = "SMART"; + m_currency = "USD"; + m_expiry = expiry; + m_strike = strike; + m_right = right; + } + + public OptContract(String symbol, String exchange, + String expiry, double strike, String right) { + m_symbol = symbol; + m_secType = "OPT"; + m_exchange = exchange; + m_currency = "USD"; + m_expiry = expiry; + m_strike = strike; + m_right = right; + } + +} + diff --git a/ib/src/main/java/samples/base/SimpleWrapper.java b/ib/src/main/java/samples/base/SimpleWrapper.java new file mode 100644 index 00000000..957ce234 --- /dev/null +++ b/ib/src/main/java/samples/base/SimpleWrapper.java @@ -0,0 +1,284 @@ +package samples.base; + +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.EClientSocket; +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; + +public class SimpleWrapper implements EWrapper { + + private static final int MAX_MESSAGES = 1000000; + + // main client + private EClientSocket m_client = new EClientSocket(this); + + // utils + private long ts; + private PrintStream m_output; + private int m_outputCounter = 0; + private int m_messageCounter; + private final SimpleDateFormat m_df = new SimpleDateFormat("HH:mm:ss"); + + protected EClientSocket client() { return m_client; } + + protected SimpleWrapper() { + /* */ + initNextOutput(); + attachDisconnectHook(this); + } + + public void connect() { + connect(1); + } + + public void connect(int clientId) { + String host = System.getProperty("jts.host"); + host = host != null ? host : ""; + m_client.eConnect(host, 7496, clientId); + } + + public void disconnect() { + m_client.eDisconnect(); + } + + /* *************************************************************** + * AnyWrapper + *****************************************************************/ + + public void error(Exception e) { + e.printStackTrace(m_output); + } + + public void error(String str) { + m_output.println(str); + } + + public void error(int id, int errorCode, String errorMsg) { + logIn("Error id=" + id + " code=" + errorCode + " msg=" + errorMsg); + } + + public void connectionClosed() { + m_output.println("--------------------- CLOSED ---------------------"); + } + + /* *************************************************************** + * EWrapper + *****************************************************************/ + + public void tickPrice(int tickerId, int field, double price, int canAutoExecute) { + logIn("tickPrice"); + } + + public void tickSize(int tickerId, int field, int size) { + logIn("tickSize"); + } + + public void tickGeneric(int tickerId, int tickType, double value) { + logIn("tickGeneric"); + } + + public void tickString(int tickerId, int tickType, String value) { + logIn("tickString"); + } + + public void tickSnapshotEnd(int tickerId) { + logIn("tickSnapshotEnd"); + } + + public void tickOptionComputation(int tickerId, int field, double impliedVol, + double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + logIn("tickOptionComputation"); + } + + public void tickEFP(int tickerId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry) { + logIn("tickEFP"); + } + + public void orderStatus(int orderId, String status, int filled, int remaining, + double avgFillPrice, int permId, int parentId, double lastFillPrice, + int clientId, String whyHeld) { + logIn("orderStatus"); + } + + public void openOrder(int orderId, Contract contract, Order order, OrderState orderState) { + logIn("openOrder"); + } + + public void openOrderEnd() { + logIn("openOrderEnd"); + } + + public void updateAccountValue(String key, String value, String currency, String accountName) { + logIn("updateAccountValue"); + } + + public void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, + double averageCost, double unrealizedPNL, double realizedPNL, String accountName) { + logIn("updatePortfolio"); + } + + public void updateAccountTime(String timeStamp) { + logIn("updateAccountTime"); + } + + public void accountDownloadEnd(String accountName) { + logIn("accountDownloadEnd"); + } + + public void nextValidId(int orderId) { + logIn("nextValidId"); + } + + public void contractDetails(int reqId, ContractDetails contractDetails) { + logIn("contractDetails"); + } + + public void contractDetailsEnd(int reqId) { + logIn("contractDetailsEnd"); + } + + public void bondContractDetails(int reqId, ContractDetails contractDetails) { + logIn("bondContractDetails"); + } + + public void execDetails(int reqId, Contract contract, Execution execution) { + logIn("execDetails"); + } + + public void execDetailsEnd(int reqId) { + logIn("execDetailsEnd"); + } + + public void updateMktDepth(int tickerId, int position, int operation, int side, double price, int size) { + logIn("updateMktDepth"); + } + + public void updateMktDepthL2(int tickerId, int position, String marketMaker, int operation, + int side, double price, int size) { + logIn("updateMktDepthL2"); + } + + public void updateNewsBulletin(int msgId, int msgType, String message, String origExchange) { + logIn("updateNewsBulletin"); + } + + public void managedAccounts(String accountsList) { + logIn("managedAccounts"); + } + + public void receiveFA(int faDataType, String xml) { + logIn("receiveFA"); + } + + public void historicalData(int reqId, String date, double open, double high, double low, + double close, int volume, int count, double WAP, boolean hasGaps) { + logIn("historicalData"); + } + + public void scannerParameters(String xml) { + logIn("scannerParameters"); + } + + public void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, + String benchmark, String projection, String legsStr) { + logIn("scannerData"); + } + + public void scannerDataEnd(int reqId) { + logIn("scannerDataEnd"); + } + + public void realtimeBar(int reqId, long time, double open, double high, double low, double close, + long volume, double wap, int count) { + logIn("realtimeBar"); + } + + public void currentTime(long millis) { + logIn("currentTime"); + } + + public void fundamentalData(int reqId, String data) { + logIn("fundamentalData"); + } + + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + logIn("deltaNeutralValidation"); + } + + public void marketDataType(int reqId, int marketDataType) { + logIn("marketDataType"); + } + + /* *************************************************************** + * Helpers + *****************************************************************/ + + protected void logIn(String method) { + m_messageCounter++; + if (m_messageCounter == MAX_MESSAGES) { + m_output.close(); + initNextOutput(); + m_messageCounter = 0; + } + m_output.println("[W] > " + method); + } + + protected void consoleMsg(String str) { + System.out.println(Thread.currentThread().getName() + " (" + tsStr() + "): " + str); + } + + protected String tsStr() { + synchronized (m_df) { + return m_df.format(new Date()); + } + } + + protected void sleepSec(int sec) { + sleep(sec * 1000); + } + + protected void sleep(int msec) { + try { + Thread.sleep(msec); + } catch (Exception e) { /* noop */ } + } + + protected void swStart() { + ts = System.currentTimeMillis(); + } + + protected void swStop() { + long dt = System.currentTimeMillis() - ts; + m_output.println("[API]" + " Time=" + dt); + } + + private void initNextOutput() { + try { + m_output = new PrintStream(new File("sysout_" + (++m_outputCounter) + ".log")); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + private static void attachDisconnectHook(final SimpleWrapper ut) { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + ut.disconnect(); + } + }); + } +} + diff --git a/ib/src/main/java/samples/base/StkContract.java b/ib/src/main/java/samples/base/StkContract.java new file mode 100644 index 00000000..bf9ef783 --- /dev/null +++ b/ib/src/main/java/samples/base/StkContract.java @@ -0,0 +1,17 @@ +/* + * StkContract.java + */ +package samples.base; + +import com.ib.client.Contract; + +public class StkContract extends Contract { + + public StkContract(String symbol) { + m_symbol = symbol; + m_secType = "STK"; + m_exchange = "SMART"; + m_currency = "USD"; + } +} + diff --git a/ib/src/main/java/samples/rfq/RfqOrder.java b/ib/src/main/java/samples/rfq/RfqOrder.java new file mode 100644 index 00000000..22b92fcb --- /dev/null +++ b/ib/src/main/java/samples/rfq/RfqOrder.java @@ -0,0 +1,26 @@ +/* + * RfqOrder.java + */ +package samples.rfq; + +import com.ib.client.Order; + +public class RfqOrder extends Order { + + public RfqOrder(int clientId, int id, int size) { + + m_clientId = clientId; + m_orderId = id; + m_permId = id; + m_totalQuantity = size; + m_orderType = "QUOTE"; + + /* + * Note: this will be overridden by the backend + * because it could not keep such order + * (and it does not make too much sence) + */ + m_transmit = false; + } +} + diff --git a/ib/src/main/java/samples/rfq/SampleRfq.java b/ib/src/main/java/samples/rfq/SampleRfq.java new file mode 100644 index 00000000..23b91d3a --- /dev/null +++ b/ib/src/main/java/samples/rfq/SampleRfq.java @@ -0,0 +1,521 @@ +package samples.rfq; + +import samples.base.ComboContract; +import samples.base.FutContract; +import samples.base.OptContract; +import samples.base.StkContract; +import samples.base.SimpleWrapper; + +import com.ib.client.ComboLeg; +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.TickType; +import com.ib.client.UnderComp; + +import java.util.Vector; + + +public class SampleRfq extends SimpleWrapper { + + private enum Status { None, SecDef, SecDefFMF, Rfq, Ticks, Done, Error }; + + private static final int MaskBidPrice = 1; + private static final int MaskAskPrice = 2; + private static final int MaskBidSize = 4; + private static final int MaskAskSize = 8; + + private static final int MaskRecvAll = MaskBidPrice | MaskBidSize | + MaskAskPrice | MaskAskSize ; + + private Object m_mutex = new Object(); + private Status m_status = Status.None; + + private int m_clientId; + private int m_rfqId; + private int m_mode; + + private Contract m_contract = null; + + private int m_underConId = 0; + + private boolean m_needFrontMonthFuture = false; + private Contract m_frontMonthFuture = null; + private int m_frontMonthFutureExpiry = 0; + private int m_frontMonthFutureMult = 0; + + private double m_bidPrice = 0; + private double m_askPrice = 0; + + private int m_bidSize = 0; + private int m_askSize = 0; + + private int m_receivedTicks = 0; + + public SampleRfq(int clientId, int rfqId, int mode) { + m_clientId = clientId; + m_rfqId = rfqId; + m_mode = mode; + } + + public void testOrder() throws Exception { + + int clientId = 2; + connect(clientId); + + if (client() != null && client().isConnected()) { + + try { + + synchronized (m_mutex) { + + if (client().serverVersion() < 42) { + error ("Sample will not work with TWS older that 877"); + } + + while (m_status != Status.Done && + m_status != Status.Error) { + + if (m_status == Status.None) { + obtainContract(); + if (m_status != Status.Error && + m_status != Status.SecDef) { + submitRfq(); + } + } + m_mutex.wait(); + } + } + } + + finally { + disconnect(); + } + + if (m_status == Status.Done) { + + String msg = "Done, bid=" + m_bidSize + "@" + m_bidPrice + + " ask=" + m_askSize + "@" + m_askPrice; + + UnderComp underComp = m_contract.m_underComp; + if (underComp != null) { + msg += " DN: conId=" + underComp.m_conId + + " price=" + underComp.m_price + + " delta=" + underComp.m_delta; + } + + consoleMsg(msg); + } + } + } + + private void obtainContract() { + + switch (m_mode) { + case 0: + { + m_contract = new StkContract("IBM"); + m_contract.m_currency = "EUR"; + break; + } + case 1: + { + m_contract = new FutContract("IBM", "200809"); + break; + } + case 2: + { + m_contract = new OptContract("IBM", "200809", 120, "CALL"); + break; + } + case 3: + { + m_contract = new OptContract("Z", "LIFFE", "200809", 54.75, "CALL"); + m_contract.m_currency = "GBP"; + break; + } + case 4: + { + m_contract = new ComboContract("Z", "GBP", "LIFFE"); + m_contract.m_comboLegs = new Vector(2); + m_contract.m_comboLegs.setSize(2); + + { + Contract l1 = new OptContract( + "Z", "LIFFE", "200809", 54.75, "CALL"); + l1.m_currency = "GBP"; + submitSecDef(1, l1); + } + + { + Contract l2 = new OptContract( + "Z", "LIFFE", "200810", 55.00, "CALL"); + l2.m_currency = "GBP"; + submitSecDef(2, l2); + } + + m_status = Status.SecDef; + break; + } + case 5: + { + m_contract = new ComboContract("IBM"); + m_contract.m_comboLegs = new Vector(1); + m_contract.m_comboLegs.setSize(1); + + m_contract.m_underComp = new UnderComp(); + //m_contract.m_underComp.m_delta = 0.8; + //m_contract.m_underComp.m_price = 120; + + { + Contract l1 = new OptContract("IBM", "200809", 120, "CALL"); + submitSecDef(1, l1); + } + + m_status = Status.SecDef; + break; + } + case 6: + { + m_contract = new ComboContract("RUT"); + m_contract.m_comboLegs = new Vector(1); + m_contract.m_comboLegs.setSize(1); + + m_contract.m_underComp = new UnderComp(); + m_needFrontMonthFuture = true; + + { + Contract l1 = new OptContract("RUT", "200809", 740, "CALL"); + submitSecDef(1, l1); + } + + m_status = Status.SecDef; + break; + } + case 7: + { + m_contract = new ComboContract("Z", "GBP", "LIFFE"); + m_contract.m_comboLegs = new Vector(1); + m_contract.m_comboLegs.setSize(1); + + m_contract.m_underComp = new UnderComp(); + + m_needFrontMonthFuture = true; + + { + Contract l1 = new OptContract( + "Z", "LIFFE", "200808", 55.00, "CALL"); + l1.m_currency = "GBP"; + submitSecDef(1, l1); + } + + m_status = Status.SecDef; + break; + } + } + } + + private void submitSecDef(int reqId, Contract contract) { + + consoleMsg("REQ: secDef " + reqId); + + client().reqContractDetails(reqId, contract); + } + + private void submitRfq() { + + consoleMsg("REQ: rfq " + m_rfqId); + + m_status = m_contract.m_underComp != null ? Status.Rfq : Status.Ticks; + + client().placeOrder(m_rfqId, m_contract, + new RfqOrder(m_clientId, m_rfqId, 1)); + } + + private void checkReceivedAllTicks() { + + if ((m_receivedTicks & MaskRecvAll) == MaskRecvAll) { + m_status = Status.Done; + m_mutex.notify(); + } + } + + public void contractDetails(int reqId, ContractDetails contractDetails) { + + consoleMsg("contractDetails: " + reqId); + + try { + + synchronized (m_mutex) { + + if (m_status == Status.SecDef) { + /* + * Note: we are requesting SecDefs only if we need Combo's + */ + + int legId = reqId - 1; + + ComboLeg comboLeg = new ComboLeg( + contractDetails.m_summary.m_conId, /* ratio */ 1, + (reqId == 1 ? "BUY" : "SELL"), m_contract.m_exchange, 0); + + m_contract.m_comboLegs.set(legId, comboLeg); + + /* + * Do we have all legs? + */ + for (int i = 0; i < m_contract.m_comboLegs.size(); ++i) { + if (i == legId) + continue; + if (m_contract.m_comboLegs.get(i) == null) + return; + } + + if (m_contract.m_underComp != null) { + /* + * Store underConId if needed + */ + if (m_underConId == 0) { + m_underConId = contractDetails.m_underConId; + } + + /* + * Do we need to request front month future for hedging? + */ + + if (m_needFrontMonthFuture) { + m_status = Status.SecDefFMF; + + Contract futContract = new FutContract( + contractDetails.m_summary.m_symbol, + /* all expirations */ "", + contractDetails.m_summary.m_currency); + + submitSecDef(0, futContract); + return; + } + + consoleMsg("using " + m_underConId + " for hedging"); + m_contract.m_underComp.m_conId = m_underConId; + } + + /* + * And finally submit RFQ + */ + submitRfq(); + } + else if (m_status == Status.SecDefFMF) { + + /* + * Ignore unknown reqId's + */ + + if (reqId != 0) { + return; + } + + /* + * Ignore secDefs with different underConId + */ + if (contractDetails.m_underConId != m_underConId) { + return; + } + + Contract contract = contractDetails.m_summary; + + /* + * Check if we have a better match + */ + + int contractExpiry = Integer.parseInt(contract.m_expiry); + int contractMult = Integer.parseInt(contract.m_multiplier); + + if (m_frontMonthFuture != null) { + if (m_frontMonthFutureExpiry <= contractExpiry) { + return; + } + if (m_frontMonthFutureExpiry == contractExpiry && + m_frontMonthFutureMult <= contractMult) { + return; + } + } + + m_frontMonthFuture = contract; + m_frontMonthFutureExpiry = contractExpiry; + m_frontMonthFutureMult = contractMult; + } + } + } + catch (Exception e) { + // will update status and notify main thread + error (e.toString()); + } + } + + public void contractDetailsEnd(int reqId) { + + consoleMsg("contractDetailsEnd: " + reqId); + + try { + + synchronized (m_mutex) { + + if (m_status == Status.SecDefFMF) { + + if (reqId != 0) { + // ignore details end for leg requests + return; + } + + if (m_frontMonthFuture == null) { + error ("Could not find front month future for hedging"); + return; + } + + consoleMsg("using " + m_frontMonthFuture.m_conId + + " for hedging"); + + m_contract.m_underComp.m_conId = + m_frontMonthFuture.m_conId; + + /* + * And finally submit RFQ + */ + submitRfq(); + } + } + } + catch (Exception e) { + // will update status and notify main thread + error (e.toString()); + } + } + + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + + consoleMsg("deltaNeutralValidation:" + reqId); + + synchronized (m_mutex) { + + if (m_status == Status.Rfq) { + + if (reqId != m_rfqId) { + // unexpected dn validation + return; + } + + // update underComp + m_contract.m_underComp = underComp; + m_status = Status.Ticks; + } + } + } + public void orderStatus(int orderId, String status, int filled, + int remaining, double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + + consoleMsg("orderStatus:" + orderId + " status=" + status); + + synchronized (m_mutex) { + if (status.equals("Cancelled")) { + m_status = Status.Error; + m_mutex.notify(); + } + } + } + + public void tickPrice(int tickerId, int field, double price, + int canAutoExecute) { + + consoleMsg("tickPrice:" + tickerId + " field:" + field + + " (" + TickType.getField(field) + ") value:" + price); + + synchronized (m_mutex) { + + if (m_status == Status.Ticks) { + + switch (field) { + case TickType.BID: + { + m_bidPrice = price; + m_receivedTicks |= MaskBidPrice; + break; + } + case TickType.ASK: + { + m_askPrice = price; + m_receivedTicks |= MaskAskPrice; + break; + } + } + checkReceivedAllTicks(); + } + } + } + + public void tickSize(int tickerId, int field, int size) { + + consoleMsg("tickSize:" + tickerId + " field:" + field + + " (" + TickType.getField(field) + ") value:" + size); + + synchronized (m_mutex) { + + if (m_status == Status.Ticks) { + + switch (field) { + case TickType.BID_SIZE: + { + m_bidSize = size; + if (!(m_bidSize == 0 && m_bidPrice == -1)) { + m_receivedTicks |= MaskBidSize; + } + break; + } + case TickType.ASK_SIZE: + { + m_askSize = size; + if (!(m_askSize == 0 && m_askPrice == -1)) { + m_receivedTicks |= MaskAskSize; + } + break; + } + } + checkReceivedAllTicks(); + } + } + } + + public void error(String str) { + consoleMsg("Error=" + str); + synchronized (m_mutex) { + m_status = Status.Error; + m_mutex.notify(); + } + } + + public void error(int id, int errorCode, String errorMsg) { + consoleMsg("Error id=" + id + " code=" + errorCode + " msg=" + errorMsg); + if (errorCode >= 2100 && errorCode < 2200) { + return; + } + synchronized (m_mutex) { + m_status = Status.Error; + m_mutex.notify(); + } + } + + /* *************************************************************** + * Main Method + *****************************************************************/ + + public static void main(String[] args) { + try { + int rfqId = (int) (System.currentTimeMillis() / 1000); + int mode = (args.length > 0) ? Integer.parseInt(args[0]) : 0; + SampleRfq ut = new SampleRfq(/* clientId */ 2, rfqId, mode); + ut.testOrder(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} +