我正在尝试为 API 创建一个程序,以一次进行多个交易,然后获取股票价格,然后经常重新平衡。我使用了在线教程来获取一些代码,并进行了一些调整。
但是,当我运行代码时,它经常连接,并且如果我重新启动 IB TWS 就会下订单。但是,如果我再次运行代码,它就不起作用,或者显示任何它将连接的指示。谁能帮我弄清楚如何保持连接,以便我可以运行 main.java 文件,并且它将执行多个交易,然后结束连接?我需要在代码或 TWS 设置中更改客户端 ID 号吗?
一共有三个文件:
订单管理.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 设置(如果有帮助的话):
预先感谢您的帮助!
最佳答案
我更改了代码中的一些内容并添加了注释。
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...
}
关于java - 盈透证券 API - 执行多笔交易,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38966654/