Skip to content

Commit

Permalink
Add test sample code
Browse files Browse the repository at this point in the history
  • Loading branch information
catch-point committed Jan 24, 2023
1 parent df1273c commit d37520f
Show file tree
Hide file tree
Showing 12 changed files with 4,774 additions and 0 deletions.
38 changes: 38 additions & 0 deletions test/samples/dnhedge/DNHedgeOrder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */

package samples.dnhedge;

import com.ib.client.Order;
import com.ib.client.OrderType;
import com.ib.client.Types.Action;
import com.ib.client.Types.VolatilityType;

public class DNHedgeOrder extends Order {
public DNHedgeOrder(int clientId, int id, int size, String account,
String settlingFirm, int underConId, String designatedLocation) {
clientId(clientId);
orderId(id);
permId(id);

account(account);
clearingIntent("AWAY");
settlingFirm(settlingFirm);

orderType(OrderType.VOL);
action(Action.BUY);
totalQuantity(size);

volatility(0.1);
volatilityType(VolatilityType.Daily);
continuousUpdate(1);
deltaNeutralOrderType(OrderType.LMT);

deltaNeutralConId(underConId);
deltaNeutralOpenClose("O");
deltaNeutralShortSale(true);

deltaNeutralDesignatedLocation(designatedLocation);
deltaNeutralShortSaleSlot(deltaNeutralDesignatedLocation().length() == 0 ? 1 : 2);
}
}
233 changes: 233 additions & 0 deletions test/samples/dnhedge/SampleDNHedge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */

package samples.dnhedge;


import com.ib.client.Contract;
import com.ib.client.ContractDetails;
import com.ib.contracts.OptContract;
import com.ib.contracts.StkContract;

import samples.rfq.SimpleWrapper;


public class SampleDNHedge extends SimpleWrapper {
private enum Status { None, SecDef, Order, Done, Error }

private static final int ParentAcked = 1;
private static final int ChildAcked = 2;

private static final int AllAcked = ParentAcked | ChildAcked;

private final Object m_mutex = new Object();
private Status m_status = Status.None;

private int m_clientId;
private int m_orderId;

private String m_account;
private String m_settlingFirm;
private String m_designatedLocation;

private Contract m_contract = null;
private int m_underConId = 0;

private int m_receivedAcks = 0;

public SampleDNHedge(int clientId, int orderId, String account,
String settlingFirm, String designatedLocation) {

m_clientId = clientId;
m_orderId = orderId;

m_account = account;
m_settlingFirm = settlingFirm;
m_designatedLocation = designatedLocation;
}

public void testOrder() throws Exception {
connect(m_clientId);

if (client() != null && client().isConnected()) {
try {
synchronized (m_mutex) {

if (client().serverVersion() < 66) {
error ("Sample will not work with TWS older that 932");
}

while (m_status != Status.Done &&
m_status != Status.Error) {

if (m_status == Status.None) {
obtainContract();
if (m_status != Status.Error &&
m_status != Status.SecDef) {
submitOrder();
}
}
m_mutex.wait();
}
}
}

finally {
disconnect();
}

if (m_status == Status.Done) {

consoleMsg("Done");
}
}
}

private void obtainContract() {
m_contract = new OptContract("IBM", "20121019", 200, "CALL");
m_contract.currency("USD");
m_contract.multiplier("100");

Contract underlying = new StkContract("IBM");
submitSecDef(1, underlying);

m_status = Status.SecDef;
}

private void submitSecDef(int reqId, Contract contract) {
consoleMsg("REQ: secDef " + reqId);

client().reqContractDetails(reqId, contract);
}

private void submitOrder() {
consoleMsg("REQ: order " + m_orderId);

m_status = Status.Order;

client().placeOrder(m_orderId, m_contract,
new DNHedgeOrder(m_clientId, m_orderId, 1, m_account,
m_settlingFirm, m_underConId, m_designatedLocation));
}

private void checkReceivedAllAcks() {
if ((m_receivedAcks & AllAcked) == AllAcked) {
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) {
/*
* Store underConId if needed
*/
if (m_underConId == 0) {
m_underConId = contractDetails.contract().conid();
}

consoleMsg("using " + m_underConId + " for hedging");

/*
* And finally submit RFQ
*/
submitOrder();
}
}
}
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.SecDef) {
error ("Could not find hedge contract id");
}
}
}
catch (Exception e) {
// will update status and notify main thread
error (e.toString());
}
}

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();
}
else if (status.equals("Submitted") ||
status.equals("PreSubmitted")) {

if (orderId == m_orderId) {
m_receivedAcks |= ParentAcked;
}
else if (orderId < 0) {
m_receivedAcks |= ChildAcked;
}

checkReceivedAllAcks();
}
}
}

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 {
if (args.length < 2) {
System.err.println("Account and settlingFirm parameters " +
"are required");
return;
}

int orderId = (int) (System.currentTimeMillis() / 1000);
String account = args[0];
String settlingFirm = args[1];
String designatedLocation = (args.length >= 3) ? args[2] : "";
SampleDNHedge ut = new SampleDNHedge(/* clientId */ 2, orderId,
account, settlingFirm, designatedLocation);
ut.testOrder();
} catch (Exception e) {
e.printStackTrace();
}
}
}
27 changes: 27 additions & 0 deletions test/samples/rfq/RfqOrder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
* and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */

package samples.rfq;

import com.ib.client.Order;
import com.ib.client.OrderType;

public class RfqOrder extends Order {

public RfqOrder(int clientId, int id, int size) {

clientId(clientId);
orderId(id);
permId(id);
totalQuantity(size);
orderType(OrderType.QUOTE);

/*
* Note: this will be overridden by the backend
* because it could not keep such order
* (and it does not make too much sense)
*/
transmit(false);
}
}

Loading

0 comments on commit d37520f

Please sign in to comment.