2016-08-16 107 views
1

我正在嘗試爲API創建一個程序,以一次放置多筆交易,然後獲取股票價格,然後每隔一段時間重新平衡一次。我使用了一個來自在線的教程來獲取這些代碼,並做了一些調整。Interactive Brokers API - 執行多筆交易

但是,當我運行代碼時,如果我重新啓動IB TWS,它通常會連接並下訂單。但是如果我再次運行代碼,它不起作用,或者顯示它將連接的任何指示。任何人都可以幫助我弄清楚如何保持連接,以便我可以運行main.java文件,它將執行多個交易,然後結束連接?我是否需要更改代碼或TWS設置中的客戶端ID號?

中有三個文件:

Ordermanagement.java:

package SendMarketOrder; 
//import statements// 

class OrderManagement extends Thread implements EWrapper{ 

private EClientSocket client = null; //IB API client Socket Object 
private Stock stock = new Stock(); 
private Order order = new Order(); 
private int orderId; 
private double limitprice; 
private String Ticker; 

//method to create connection class. It's the constructor 
public OrderManagement() throws InterruptedException, ClassNotFoundException, SQLException { 
    // Create a new EClientSocket object 
    System.out.println("////////////// Creating a Connection ////////////"); 
    client = new EClientSocket(this); //Creation of a socket to connect 
    //connect to the TWS Demo 
    client.eConnect(null,7497,1); 

    try { 
     Thread.sleep(3000); //waits 3 seconds for user to accept 
     while (!(client.isConnected())); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    System.out.println("/////////  Connected /////////"); 
} 
public void sendMarketOrder(String cusip, String buyorSell, int shares) throws SQLException, ClassNotFoundException{ 
    //New Order ID 
    orderId++; 
    order.m_action = buyorSell; 
    order.m_orderId = orderId; 
    order.m_orderType = "MKT"; 
    order.m_totalQuantity = shares; 
    order.m_account = "DU33xxxxx"; //write own account 
    order.m_clientId = 1; 

    //Create a new contract 
    stock.createContract(cusip); 
    client.placeOrder(orderId, stock.contract, order); 

    //Show order in console 
    SimpleDateFormat time_formatter = new SimpleDateFormat("HH:mm:ss"); 
    String current_time_str = time_formatter.format(System.currentTimeMillis()); 
    System.out.println("////////////////////////////////////////////////\n" + 
    "#Limit Price: " + order.m_lmtPrice + "///////////////////////////\n" + 
    "#Client number: " + order.m_clientId + "///////////////////////////\n" + 
    "#OrderType: " + order.m_orderType + "///////////////////////////\n" + 
    "#Order Quantity: " + order.m_totalQuantity + "///////////////////////////\n" + 
    "#Account number: " + order.m_account + "///////////////////////////\n" + 
    "#Symbol: " + stock.contract.m_secId + "///////////////////////////\n" + 
    "///////////////////////////////////////" 
    ); 
    } 

Stock.java

public class Stock{ 
private int StockId; //we can identify the stock 
private String Symbol; //Ticker 

    public Stock() { //default constructor 
    } 

    public Stock(int StockId, String Symbol) { //constructor 
     this.StockId = StockId; 
     this.Symbol = Symbol; 
    } 
    //getter and setters 
    public int getStockId() { 
     return StockId; 
    } 

    public String getSymbol() { 
     return Symbol; 
    } 

Contract contract = new Contract(); 
public void createContract(String cusip){ 
    contract.m_secId = cusip; 
    contract.m_secIdType = "CUSIP"; 
    contract.m_exchange = "SMART"; 
    contract.m_secType = "STK"; 
    contract.m_currency = "USD"; 

} 
} 

Main.java:

package SendMarketOrder; 
import java.sql.SQLException; 

public class Main { 

public static void main(String[] args) throws InterruptedException, ClassNotFoundException, SQLException { 
    OrderManagement order = new OrderManagement(); 
    order.sendMarketOrder("922908363","BUY", 100); 
    order.sendMarketOrder("92204A504","BUY", 50); 
    order.sendMarketOrder("92204A702","BUY", 100); 
    System.exit(0); 
} 
} 

這是我的當前設置TWS setti NGS是否有幫助:

IB TWS Api Settings

在此先感謝您的幫助!

+0

你的程序在冗餘行'System.exit(0);'退出。當main完成時,程序仍然退出。如果你想讓程序繼續運行,你需要一個主循環,或者做一個gui。如果這是一個控制檯應用程序,那麼我會繼續檢查市場數據以便重新平衡,直到東部時間下午4點之前的某個時間。 – brian

+0

如果TWS認爲客戶端ID已被使用,它可能不會重新連接。這就是重新啓動交易平臺允許建立新連接的原因。你想多次運行這個程序還是讓它在白天運行? – brian

+0

我只想每隔一段時間運行一次程序,以便在更改股票的權重時進行自動重新平衡。它不必經常運行 – user3628240

回答

0

我在代碼中改變了一些東西並添加了評論。

package sendmarketorder;//usually lower case pkg names 

public class Main { 

    //you throw a bunch of exceptions that are never encountered 
    public static void main(String[] args) { 
     //since there's a Thread.sleep in this class 
     //it will block until ready 
     OrderManagement order = new OrderManagement(); 

     //obviously you need some logic to buy/sell 
     //you can use command line args here if you want 
     order.sendMarketOrder("922908363", "BUY", 100); 
     order.sendMarketOrder("92204A504", "BUY", 50); 
     order.sendMarketOrder("92204A702", "BUY", 100); 

     //the socket creates a reader thread so this will stop it. 
     //if you didn't have this line the non-daemon thread would keep a 
     //connection to TWS and that's why you couldn't reconnect 
     //System.exit(0);//use better exit logic 
    } 
} 

package sendmarketorder; 

import com.ib.client.*; 
import java.text.SimpleDateFormat; 
import java.util.HashMap; 
import java.util.Map; 

//doesn't extend thread and if you implement EWrapper you have to implement all methods 
//in API 9.72 you can extend DefaultWrapper and just override the methods you need 
public class OrderManagement implements EWrapper{ 

    private EClientSocket client = null; //IB API client Socket Object 
    private int orderId = -1;//use as flag to send orders 
    //private double limitprice; 
    //private String Ticker; 

    //keep track of all working orders 
    private Map<Integer, Order> workingOrders = new HashMap<>(); 

    //method to create connection class. It's the constructor 
    public OrderManagement(){ 
     // Create a new EClientSocket object 
     System.out.println("////////////// Creating a Connection ////////////"); 
     client = new EClientSocket(this); //Creation of a socket to connect 
     //connect to the TWS Demo 
     client.eConnect(null, 7497, 123);//starts reader thread 

     try { 
      while (orderId < 0){ //not best practice but it works 
       System.out.println("waiting for orderId"); 
       Thread.sleep(1000); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     System.out.println("/////////  Connected /////////"); 
    } 

    public void sendMarketOrder(String cusip, String buyorSell, int shares) { 
     //make new stock and order for each stock 
     Stock stock = new Stock(); 
     Order order = new Order(); 
     //New Order ID, but get from API as you have to increment on every run for life 
     orderId++; 
     order.m_action = buyorSell; 
     order.m_orderId = orderId; 
     order.m_orderType = "MKT"; 
     order.m_totalQuantity = shares; 
     //I don't think you're supposed to use these fields 
     //order.m_account = "DU33xxxxx"; //write own account 
     //order.m_clientId = 1; 

     //Create a new contract 
     stock.createContract(cusip); 

     //remember which orders are working 
     workingOrders.put(orderId, order); 
     client.placeOrder(orderId, stock.contract, order); 

     //Show order in console 
     SimpleDateFormat time_formatter = new SimpleDateFormat("HH:mm:ss"); 
     String current_time_str = time_formatter.format(System.currentTimeMillis()); 
     System.out.println("////////////////////////////////////////////////\n" 
       + "#Limit Price: " + order.m_lmtPrice + "///////////////////////////\n" 
       + "#Client number: " + order.m_clientId + "///////////////////////////\n" 
       + "#OrderType: " + order.m_orderType + "///////////////////////////\n" 
       + "#Order Quantity: " + order.m_totalQuantity + "///////////////////////////\n" 
       + "#Account number: " + order.m_account + "///////////////////////////\n" 
       + "#Symbol: " + stock.contract.m_secId + "///////////////////////////\n" 
       + "///////////////////////////////////////" 
     ); 
    } 

    //always impl the error callback so you know what's happening 
    @Override 
    public void error(int id, int errorCode, String errorMsg) { 
     System.out.println(id + " " + errorCode + " " + errorMsg); 
    } 

    @Override 
    public void nextValidId(int orderId) { 
     System.out.println("next order id "+orderId); 
     this.orderId = orderId; 
    } 

    @Override 
    public void orderStatus(int orderId, String status, int filled, int remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, String whyHeld) { 
     //so you know it's been filled 
     System.out.println(EWrapperMsgGenerator.orderStatus(orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld)); 
     //completely filled when remaining == 0, or possible to cancel order from TWS 
     if (remaining == 0 || status.equals("Cancelled")){ 
      //remove from map, should always be there 
      if (workingOrders.remove(orderId) == null) System.out.println("not my order!"); 
     } 

     //if map is empty then exit program as all orders have been filled 
     if (workingOrders.isEmpty()){ 
      System.out.println("all done"); 
      client.eDisconnect();//will stop reader thread 
      //now is when you stop the program, but since all 
      //non-daemon threads have finished, the jvm will close. 
      //System.exit(0); 
     } 
    } 

    //impl rest of interface... 
} 
+0

非常感謝,我會試一試並回復你! – user3628240