From 9a67951458ac97f4d070b8359cca8ffae01accea Mon Sep 17 00:00:00 2001 From: rediar <35616513+rediar@users.noreply.github.com> Date: Sat, 20 Jan 2018 22:11:08 -0500 Subject: [PATCH] Add files via upload --- FetchOptionsChain.java | 195 ++++++++++++++ KillSwitch.java | 76 ++++++ LargePriceFeed.java | 243 +++++++++++++++++ PennyPilot.csv | 1 + SimplePriceFeed.java | 149 +++++++++++ TickerList.csv | 1 + TradeStrategy.java | 73 ++++++ fetchOptionsChain/RequestOptionChain.java | 29 ++ .../RequestOptionChainWrapper.java | 248 ++++++++++++++++++ largePriceFeed/RequestPriceData.java | 73 ++++++ largePriceFeed/RequestPriceWrapper.java | 207 +++++++++++++++ largePriceFeed/WritePriceData.java | 120 +++++++++ simplePriceFeed/RequestPriceData.java | 71 +++++ simplePriceFeed/RequestPriceWrapper.java | 206 +++++++++++++++ simplePriceFeed/WritePriceData.java | 109 ++++++++ tradeStrategy/FetchOrderStatus.java | 124 +++++++++ tradeStrategy/TradeStrategyWrapper.java | 207 +++++++++++++++ 17 files changed, 2132 insertions(+) create mode 100644 FetchOptionsChain.java create mode 100644 KillSwitch.java create mode 100644 LargePriceFeed.java create mode 100644 PennyPilot.csv create mode 100644 SimplePriceFeed.java create mode 100644 TickerList.csv create mode 100644 TradeStrategy.java create mode 100644 fetchOptionsChain/RequestOptionChain.java create mode 100644 fetchOptionsChain/RequestOptionChainWrapper.java create mode 100644 largePriceFeed/RequestPriceData.java create mode 100644 largePriceFeed/RequestPriceWrapper.java create mode 100644 largePriceFeed/WritePriceData.java create mode 100644 simplePriceFeed/RequestPriceData.java create mode 100644 simplePriceFeed/RequestPriceWrapper.java create mode 100644 simplePriceFeed/WritePriceData.java create mode 100644 tradeStrategy/FetchOrderStatus.java create mode 100644 tradeStrategy/TradeStrategyWrapper.java diff --git a/FetchOptionsChain.java b/FetchOptionsChain.java new file mode 100644 index 0000000..861a75f --- /dev/null +++ b/FetchOptionsChain.java @@ -0,0 +1,195 @@ +import fetchOptionsChain.RequestOptionChainWrapper; +import fetchOptionsChain.RequestOptionChain; + +import com.ib.client.Contract; +import com.ib.client.EClientSocket; +import com.ib.client.EWrapper; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collections; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +// Read in TickerList.csv, a list of contracts to generate options chains from +// TickerList.csv fields: Active (T/F) | symbol | secType | exchange | currency +// | expiry | strike | right | multiplier +// Read in PennyPilot.csv, a list of Penny Pilot tickers +// Output option chain to IBAlgoSystem.MasterChainList + +public class FetchOptionsChain { + private EClientSocket socket = null; + public String delimiter = ","; + public String delimiter_under = "_"; + public String csvFile = "TickerList.csv"; + public String PennyPilotFile = "PennyPilot.csv"; + public String[] TickerList; + public int counter_iter = 0; + public double price = -1.0; + public Connection sqlConnection = null; + public PreparedStatement preparedStatement = null; + public ResultSet resultSet = null; + + + public void sqlClose() { + try { + if (resultSet != null) { + resultSet.close(); + } + + if (sqlConnection != null) { + sqlConnection.close(); + } + } catch (Exception e) { + } + } + + + public FetchOptionsChain() { + Map PennyPilotMap = new HashMap<>(); + boolean foundPennyTick; + + // load Penny Pilot Tickers + List PennyPilotTickers = new ArrayList(); + StringBuilder temp_ticker = new StringBuilder(""); + try (BufferedReader br1 = new BufferedReader(new FileReader(PennyPilotFile))) { + String input1; + while ((input1 = br1.readLine()) != null) { + if (!input1.split(delimiter)[0].equals(temp_ticker.toString())) { + temp_ticker = new StringBuilder(input1.split(delimiter)[0]); + PennyPilotTickers.add(temp_ticker.toString()); + } + } + br1.close(); + } catch (IOException e) { + e.printStackTrace(); + } + Collections.sort(PennyPilotTickers); + + + // find number of rows in TickerList + int rows = 0; + try (BufferedReader br2 = new BufferedReader(new FileReader(csvFile))) { + String input2; + while ((input2 = br2.readLine()) != null) { + rows++; + } + br2.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + + // write values of TickerList + TickerList = new String[rows]; + try (BufferedReader br3 = new BufferedReader(new FileReader(csvFile))) { + String input3; + int row_iter = 0; + while ((input3 = br3.readLine()) != null) { + TickerList[row_iter] = input3; + row_iter++; + } + br3.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + + // connect to sql, update counter + try { + Class.forName("com.mysql.jdbc.Driver"); + sqlConnection = DriverManager.getConnection( + "jdbc:mysql://localhost/IBAlgoSystem?user=user&password=pw"); + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.counter SET counter = 0"); + preparedStatement.executeUpdate(); + preparedStatement = sqlConnection.prepareStatement( + "TRUNCATE TABLE IBAlgoSystem.MasterChainList"); + preparedStatement.executeUpdate(); + + + // write PennyPilotMap + for (int i=0; i < TickerList.length; i++) { + foundPennyTick = false; + for (int j=0; j < PennyPilotTickers.size(); j++) { + if (TickerList[i].split(delimiter)[1].equals(PennyPilotTickers.get(j))) { + foundPennyTick = true; + break; + } + } + + if (foundPennyTick) { + PennyPilotMap.put(TickerList[i].split(delimiter)[1], "T"); + } else { + PennyPilotMap.put(TickerList[i].split(delimiter)[1], "F"); + } + } + + + // connect to socket + EWrapper requestOptionChainWrapper = new RequestOptionChainWrapper(sqlConnection); + EClientSocket socket = new EClientSocket(requestOptionChainWrapper); + socket.eConnect (null, 4002, 100); + try { + while (!(socket.isConnected())); + } catch (Exception e) { + } + + // submit a new contract for every request + for (int i = 0; i < rows; i++) { + String line = TickerList[i]; + Contract cont = new Contract(); + cont.m_symbol = line.split(delimiter)[1]; + cont.m_secType = "OPT"; + cont.m_exchange = "SMART"; + cont.m_currency = line.split(delimiter)[4]; + cont.m_multiplier = "100"; + RequestOptionChain data = new RequestOptionChain(cont, socket, sqlConnection); + } + + + // check counter to disconnect socket + preparedStatement = sqlConnection.prepareStatement( + "SELECT counter FROM IBAlgoSystem.counter;"); + resultSet = preparedStatement.executeQuery(); + counter_iter = WriteInt(resultSet, "counter"); + while (counter_iter < rows) { + resultSet = preparedStatement.executeQuery(); + counter_iter = WriteInt(resultSet, "counter"); + } + socket.eDisconnect(); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + sqlClose(); + } + } + + + private int WriteInt(ResultSet resultSet, String column_name) throws SQLException { + int output_counter = 0; + while (resultSet.next()) { + output_counter = resultSet.getInt(column_name); + } + return output_counter; + } + + + public static void main(String args[]) { + try { + FetchOptionsChain runProcess = new FetchOptionsChain(); + } catch (Exception e) { + e.printStackTrace (); + } + } +} \ No newline at end of file diff --git a/KillSwitch.java b/KillSwitch.java new file mode 100644 index 0000000..0287a0b --- /dev/null +++ b/KillSwitch.java @@ -0,0 +1,76 @@ +import tradeStrategy.TradeStrategyWrapper; + +import com.ib.client.EClientSocket; +import com.ib.client.EWrapper; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + + +// kills all active orders + +public class KillSwitch { + public Connection sqlConnection = null; + public PreparedStatement preparedStatement = null; + public ResultSet resultSet = null; + + + public KillSwitch () { + + // connect to SQL + try { + Class.forName("com.mysql.jdbc.Driver"); + sqlConnection = DriverManager.getConnection( + "jdbc:mysql://localhost/IBAlgoSystem?user=user&password=pw"); + + + // connect to socket + EWrapper tradeStrategyWrapper = new TradeStrategyWrapper(sqlConnection); + EClientSocket socket = new EClientSocket(tradeStrategyWrapper); + socket.eConnect("", 4002, 1000); + try { + while (!(socket.isConnected())); + } catch (Exception e) { + } + + + // find outstanding active orders + preparedStatement = sqlConnection.prepareStatement( + "SELECT orderID FROM IBAlgoSystem.orderTracking WHERE " + + "status <> 'Filled' AND status <> 'Cancelled' AND " + + "status <> 'ApiCancelled' AND status <> 'Inactive';"); + resultSet = preparedStatement.executeQuery(); + + // submit cancel request + while (resultSet.next()) { + int orderId = resultSet.getInt("orderID"); + socket.cancelOrder(orderId); + } + + // wait for all orders to cancel + boolean ContinueProcess = false; + preparedStatement = sqlConnection.prepareStatement( + "SELECT COUNT(*) FROM IBAlgoSystem.orderTracking WHERE " + + "status <> 'Filled' AND status <> 'Cancelled' AND " + + "status <> 'ApiCancelled' AND status <> 'Inactive';"); + while (!ContinueProcess) { + resultSet = preparedStatement.executeQuery(); + if (resultSet.getInt("COUNT(*)") == 0) { + ContinueProcess = true; + } + } + + socket.eDisconnect(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public static void main (String args[]) { + KillSwitch runProcess = new KillSwitch(); + } +} \ No newline at end of file diff --git a/LargePriceFeed.java b/LargePriceFeed.java new file mode 100644 index 0000000..d86cab6 --- /dev/null +++ b/LargePriceFeed.java @@ -0,0 +1,243 @@ +import largePriceFeed.RequestPriceData; +import largePriceFeed.RequestPriceWrapper; +import largePriceFeed.WritePriceData; + +import com.ib.client.Contract; +import com.ib.client.EClientSocket; +import com.ib.client.EWrapper; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +// Read in IBAlgoSystem.MasterChainList - a list of options contracts to +// receive live price streams from +// The number of entries may exceed ib's feed limit (FEED_LIMIT) +// This script divides the entries into smaller batches to submit to ib +// Output prices to IBAlgoSystem.price + +public class LargePriceFeed { + private EClientSocket socket = null; + public String delimiter = ","; + public String delimiter_under = "_"; + public String TickerListCSVFile = "TickerList.csv"; + public String[] TickerLines; + public Map FileUpdated = new HashMap(); + public long updateTime, dt_now; + public boolean AllUpdated, running_updated; + public int FEED_LIMIT = 100; + public Connection sqlConnection = null; + public PreparedStatement preparedStatement = null; + public ResultSet resultSet = null; + + + public LargePriceFeed () { + int NUM_FEEDS = 0; + + // find NUM_FEEDS from 100 - rows of TickerList + try (BufferedReader br3 = new BufferedReader(new FileReader(TickerListCSVFile))) { + String input3; + while((input3 = br3.readLine()) != null) { + if (!input3.split(delimiter)[0].equals("active")) { + NUM_FEEDS++; + } + } + br3.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + // make sure NUM_FEEDS is sufficient + if (NUM_FEEDS >= (FEED_LIMIT - 5)) { + System.out.println("Not enough sockets for feed!"); + + } else { + NUM_FEEDS = FEED_LIMIT - 5 - NUM_FEEDS; + + // connect to SQL + try { + Class.forName("com.mysql.jdbc.Driver"); + sqlConnection = DriverManager.getConnection( + "jdbc:mysql://localhost/IBAlgoSystem?user=user&password=pw"); + + // find number of rows in MasterChainList + preparedStatement = sqlConnection.prepareStatement( + "SELECT COUNT(*) FROM IBAlgoSystem.MasterChainList;"); + resultSet = preparedStatement.executeQuery(); + int rows = resultSet.getInt("COUNT(*)"); + + + // write values of MasterChainList to TickerLines, dummy price + // TickerLines format: active, symbol, secType, exchange, + // currency, expiry, strike, right, multiplier, pennyPilot, + // moneyness + TickerLines = new String[rows]; + preparedStatement = sqlConnection.prepareStatement( + "SELECT * FROM IBAlgoSystem.MasterChainList"); + resultSet = preparedStatement.executeQuery(); + + int row_iter = 0; + while (resultSet.next()) { + String symbol = resultSet.getString("symbol"); + String exchange = resultSet.getString("exchange"); + String currency = resultSet.getString("currency"); + String expiry = resultSet.getString("expiry"); + double strike = resultSet.getDouble("strike"); + String right = resultSet.getString("callorput"); + String multiplier = resultSet.getString("multiplier"); + String pennyPilot = resultSet.getString("pennyPilot"); + String moneyness = resultSet.getString("moneyness"); + double bid = -1.0; + double ask = -1.0; + + // delete previous entry + preparedStatement = sqlConnection.prepareStatement( + "DELETE FROM IBAlgoSystem.price WHERE symbol = '" + + symbol + "' and secType = 'OPT' and currency = '" + + currency + "' and expiry = '" + expiry + + "' and strike = " + Double.toString(strike) + + " and callorput = '" + right + "' and multiplier = '" + + multiplier + "';"); + preparedStatement.executeUpdate(); + + // write new entry + preparedStatement = sqlConnection.prepareStatement( + "INSERT INTO IBAlgoSystem.price (entry, symbol, " + + "secType, currency, expiry, strike, callorput, " + + "multiplier, bid, ask, last, close, bugCounter, " + + "updateTime) VALUES (default,'" + symbol + + "', 'OPT', '" + currency + "', '" + expiry + "', " + + Double.toString(strike) + ", '" + right + "', '" + + multiplier + "', 0.0, 0.01, -1.0, -1.0, 0, 0);"); + preparedStatement.executeUpdate(); + } + + + // divide the list of names into batches of NUM_FEEDS + int num_batches = rows/NUM_FEEDS + 1; + + + // connect to socket + EWrapper requestPriceWrapper = new RequestPriceWrapper(); + EClientSocket socket = new EClientSocket(requestPriceWrapper); + + + // update prices by batch + + // connect to socket + socket.eConnect(null, 4002, 101); + try { + while (!(socket.isConnected())); + } catch (Exception e) { + } + + // add while loop to make perpeptual + while (true) { + for (int i=0; i < num_batches; i++) { + + // send price feed requests + for (int j=0; j < NUM_FEEDS; j++) { + if ((i*NUM_FEEDS + j) < rows) { + // submit a new contract for every request + String line = TickerLines[i*NUM_FEEDS + j]; + Contract cont = new Contract(); + cont.m_symbol = line.split(delimiter_under)[1]; + cont.m_secType = line.split(delimiter_under)[2]; + // cont.m_exchange = line.split(delimiter)[3]; + cont.m_exchange = "SMART"; + cont.m_currency = line.split(delimiter_under)[4]; + cont.m_expiry = line.split(delimiter_under)[5]; + cont.m_strike = Double.parseDouble(line.split(delimiter_under)[6]); + cont.m_right = line.split(delimiter_under)[7]; + cont.m_multiplier = line.split(delimiter_under)[8]; + + FileUpdated.put(i*NUM_FEEDS + j, false); + + RequestPriceData data = new RequestPriceData(cont, + true, socket, sqlConnection); + } else { + FileUpdated.put(i*NUM_FEEDS + j, true); + } + } + + + // check price entry is updated to continue + AllUpdated = false; + while (!AllUpdated) { + for (int j=0; j < NUM_FEEDS; j++) { + if (!FileUpdated.get(i*NUM_FEEDS + j)) { + String line = TickerLines[i*NUM_FEEDS + j]; + String symbol = line.split(delimiter_under)[1]; + String exchange = line.split(delimiter_under)[3]; + String currency = line.split(delimiter_under)[4]; + String expiry = line.split(delimiter_under)[5]; + double strike = Double.parseDouble(line.split(delimiter_under)[6]); + String right = line.split(delimiter_under)[7]; + String multiplier = line.split(delimiter_under)[8]; + + preparedStatement = sqlConnection.prepareStatement( + "SELECT updateTime FROM IBAlgoSystem.price WHERE symbol = '" + + symbol + "' and secType = 'OPT' and currency = '" + + currency + "' and expiry = '" + expiry + + "' and strike = " + Double.toString(strike) + + " and callorput = '" + right + + "' and multiplier = '" + multiplier + "';"); + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + updateTime = resultSet.getLong("updateTime"); + } + + // check the last (last updated field) is actually updated, and within 5*NUM_FEEDS secs + if ((fetchPrice.FetchSTKPrice(symbol, "USD", sqlConnection)[2] > -0.01) && + (((new Date()).getTime() - updateTime) < 5*NUM_FEEDS*1000)) { + FileUpdated.put(i*NUM_FEEDS + j, true); + } + } + } + + for (int j=0; j < NUM_FEEDS; j++) { + running_updated = true; + if (!FileUpdated.get(i*NUM_FEEDS + j)) { + running_updated = false; + break; + } + } + if (running_updated) { + AllUpdated = true; + } + } + + // pause for 1 sec between each batch + dt_now = (new Date()).getTime(); + while (((new Date()).getTime() - dt_now) < (1*1000)); + } + + // pause for 1 min between each loop + if (num_batches < 60) { + dt_now = (new Date()).getTime(); + while (((new Date()).getTime() - dt_now) < (60*1000)); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + + public static void main (String args[]) { + try { + LargePriceFeed runProcess = new LargePriceFeed(); + } catch (Exception e) { + e.printStackTrace (); + } + } +} \ No newline at end of file diff --git a/PennyPilot.csv b/PennyPilot.csv new file mode 100644 index 0000000..e715b7f --- /dev/null +++ b/PennyPilot.csv @@ -0,0 +1 @@ +A AAL AAPL ABBV ABT ABX ADBE ADM ADSK AEM AET AFL AGN AGNC AGO AIG AKAM AKS ALL AMAT AMD AMED AMGN AMRN AMZN ANF ANTM APA APC ARNA ARNC ASHR ATVI AUY AXP BA BABA BAC BAX BBBY BBD BBRY BBT BBY BCRX BHI BHP BIDU BK BMY BP BPOP BRCD BRKB BSX BX C CAT CBS CELG CENX CF CHK CI CIEN CIT CL CLF CMA CMCSA CNX COF COP COST COTY CREE CRM CSCO CSX CTIC CVS CVX CX DAL DB DD DDD DE DHI DIA DIS DO DOW DVN DXJ EA EBAY EEM EFA EOG ESRX ETE ETFC EWJ EWT EWW EWY EWZ F FAS FAZ FB FCX FDX FEYE FFIV FH FIS FIT FITB FLEX FSLR FXE FXI FXP GDX GDXJ GE GFI GG GGP GILD GIS GLD GLW GM GME GNW GPRO GPS GRMN GRPN GS HAL HBAN HD HES HIG HL HLF HOG HON HPQ HSBC HSY HYG IBM IBN INTC IP IWM IYR JCI JCP JD JNJ JNPR JPM JWN KBH KCG KEY KGC KMI KO KRE LEN LLY LNC LNG LOW LULU LVS M MA MBI MCD MCO MDLZ MDT MET MGM MMM MNKD MNX MO MON MOS MRK MRO MRVL MS MSFT MSI MT MTG MU MYL NBR NE NEM NFLX NKE NLY NOK NOV NQ NTAP NUE NUGT NVDA ODP OIH ORCL OXY P PBR PEP PFE PG PHM PLUG PM PNC POT PRU PYPL QCOM QID QLD QQQ RAD RCL RF RIG RMBS RSX RTN S SBUX SDS SEED SHLD SINA SIRI SKF SLB SLM SLV SLW SO SPG SPWR SPY SRPT SRS SSO STI STT STX SU SVXY SWN SYMC T TBT TECK TEVA TGT TIF TLT TM TMUS TNA TSLA TSO TWLO TWTR TWX TXN TXT TZA UAA UAL UNG UNH UNP UPS URE USB USO UTX UUP UVXY UYG V VALE VIAV VLO VOD VRSN VRX VVUS VXX VZ WBA WDC WFC WFM WFT WHR WIN WLL WMB WMT WYNN X XBI XHB XL XLB XLE XLF XLI XLK XLNX XLP XLU XLV XLY XME XOM XOP XRT XRX YHOO YRCW YUM ZION ZNGA \ No newline at end of file diff --git a/SimplePriceFeed.java b/SimplePriceFeed.java new file mode 100644 index 0000000..02f3fe6 --- /dev/null +++ b/SimplePriceFeed.java @@ -0,0 +1,149 @@ +import simplePriceFeed.RequestPriceWrapper; +import simplePriceFeed.RequestPriceData; +import simplePriceFeed.WritePriceData; + +import com.ib.client.Contract; +import com.ib.client.EClientSocket; +import com.ib.client.EWrapper; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; + + +// Read in TickerList.csv - a list of contracts to receive live price streams from +// TickerList.csv fields: Active (T/F) | symbol | secType | exchange | currency +// | expiry | strike | right | multiplier +// Output prices to IBAlgoSystem.price + +public class SimplePriceFeed { + public Connection sqlConnection = null; + public PreparedStatement preparedStatement = null; + + + public SimplePriceFeed() throws Exception { + // read in TickerList.csv + String csvFile = "TickerList.csv"; + String delimiter = ","; + + // find number of rows in TickerList + int rows = 0; + try (BufferedReader br1 = new BufferedReader(new FileReader(csvFile))) { + String input1; + while ((input1 = br1.readLine()) != null) { + if (input1.split(delimiter)[0].equals("T")) { + rows++; + } + } + br1.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + + // connect to IBAlgoSystem.price, clear previous data + Class.forName("com.mysql.jdbc.Driver"); + sqlConnection = DriverManager.getConnection( + "jdbc:mysql://localhost/IBAlgoSystem?user=user&password=pw"); + // this line assumes TickerList.csv only contains stocks (secType = STK) + preparedStatement = sqlConnection.prepareStatement( + "DELETE FROM IBAlgoSystem.price WHERE secType = 'STK'"); + preparedStatement.executeUpdate(); + + + // write dummy values of TickerList to IBAlgoSystem.price + String[] TickerLines = new String[rows]; + try (BufferedReader br2 = new BufferedReader(new FileReader(csvFile))) { + String input2; + int row_iter = 0; + while ((input2 = br2.readLine()) != null) { + if (input2.split(delimiter)[0].equals("T")) { + if (input2.split(delimiter)[2].equals("STK")) { + preparedStatement = sqlConnection.prepareStatement( + "INSERT INTO IBAlgoSystem.price (entry, symbol, " + + "secType, currency, bid, ask, last, close, " + + "bugCounter, updateTime) VALUES (default,'" + + input2.split(delimiter)[1] + "','" + + input2.split(delimiter)[2] + "','" + + input2.split(delimiter)[4] + + "', -1.0, -1.0, -1.0, -1.0, 0, 0)"); + } else if (input2.split(delimiter)[2].equals("OPT")) { + preparedStatement = sqlConnection.prepareStatement( + "DELETE FROM IBAlgoSystem.price WHERE symbol = '" + + input2.split(delimiter)[1] + + "' and secType = 'OPT' and currency = '" + + input2.split(delimiter)[4] + "' and expiry = '" + + input2.split(delimiter)[5] + "' and strike = " + + input2.split(delimiter)[6] + " and callorput = '" + + input2.split(delimiter)[7] + + "' and multiplier = '" + + input2.split(delimiter)[8] + "';"); + preparedStatement.executeUpdate(); + + preparedStatement = sqlConnection.prepareStatement( + "INSERT INTO IBAlgoSystem.price (entry, symbol, " + + "secType, currency, expiry, strike, callorput, " + + "multiplier, bid, ask, last, close, bugCounter, " + + "updateTime) VALUES (default,'" + + input2.split(delimiter)[1] + "','" + + input2.split(delimiter)[2] + "','" + + input2.split(delimiter)[4] + "','" + + input2.split(delimiter)[5] + "'," + + input2.split(delimiter)[6] +",'" + + input2.split(delimiter)[7] + "','" + + input2.split(delimiter)[8] + + "', -1.0, -1.0, -1.0, -1.0, 0, 0)"); + } + preparedStatement.executeUpdate(); + + TickerLines[row_iter] = input2; + row_iter++; + } + } + br2.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + // connect to IB socket + EWrapper requestPriceWrapper = new RequestPriceWrapper(); + EClientSocket socket = new EClientSocket(requestPriceWrapper); + socket.eConnect("", 4002, 0); + try { + while (!(socket.isConnected())); + } catch (Exception e) { + } + + // request live data setting + socket.reqMarketDataType(1); + + // submit a new contract for every request + for (int i = 0; i < rows; i++) { + String line = TickerLines[i]; + Contract cont = new Contract(); + cont.m_symbol = line.split(delimiter)[1]; + cont.m_secType = line.split(delimiter)[2]; + cont.m_exchange = line.split(delimiter)[3]; + cont.m_currency = line.split(delimiter)[4]; + if (cont.m_secType.equals("OPT")) { + cont.m_expiry = line.split(delimiter)[5]; + cont.m_strike = Double.parseDouble(line.split(delimiter)[6]); + cont.m_right = line.split(delimiter)[7]; + cont.m_multiplier = line.split(delimiter)[8]; + } + RequestPriceData data = new RequestPriceData(cont, socket, + sqlConnection); + } + } + + public static void main(String[] args) { + try { + SimplePriceFeed runProcess = new SimplePriceFeed(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/TickerList.csv b/TickerList.csv new file mode 100644 index 0000000..55ed095 --- /dev/null +++ b/TickerList.csv @@ -0,0 +1 @@ +active,symbol,secType,exchange,currency,expiry,strike,right,multiplier T,AMZN,STK,ISLAND,USD,,,, T,GOOG,STK,ISLAND,USD,,,, \ No newline at end of file diff --git a/TradeStrategy.java b/TradeStrategy.java new file mode 100644 index 0000000..4d37f4c --- /dev/null +++ b/TradeStrategy.java @@ -0,0 +1,73 @@ +import tradeStrategy.FetchOrderStatus; +import tradeStrategy.TradeStrategyWrapper; + +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.TagValue; +import com.ib.client.CommissionReport; +import com.ib.client.UnderComp; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + + +// template to implement trade strategies + +public class TradeStrategy { + public Connection sqlConnection = null; + public PreparedStatement preparedStatement = null; + public ResultSet resultSet = null; + + + public TradeStrategy () { + + // connect to SQL + try { + Class.forName("com.mysql.jdbc.Driver"); + sqlConnection = DriverManager.getConnection( + "jdbc:mysql://localhost/IBAlgoSystem?user=user&password=pw"); + + + // connect to socket + EWrapper tradeStrategyWrapper = new TradeStrategyWrapper(); + EClientSocket socket = new EClientSocket(tradeStrategyWrapper); + socket.eConnect("", 7496, 1000); + try { + while (!(socket.isConnected())); + } catch (Exception e) { + } + + + // load account summary + socket.reqAccountSummary(7496, "All", "NetLiquidation," + + "TotalCashValue, SettledCash, AccruedCash, BuyingPower," + + "EquityWithLoanValue, PreviousEquityWithLoanValue," + + "GrossPositionValue, ReqTEquity, ReqTMargin, SMA, " + + "InitMarginReq, MaintMarginReq, AvailableFunds," + + "ExcessLiquidity, Cushion, FullInitMarginReq," + + "FullMaintMarginReq, FullAvailableFunds, FullExcessLiquidity," + + "LookAheadNextChange, LookAheadInitMarginReq," + + "LookAheadMaintMarginReq, LookAheadAvailableFunds," + + "LookAheadExcessLiquidity, HighestSeverity, Leverage"); + + + // Here, call core functions to fetch prices, submit orders, manage + // margin limit, etc. + + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public static void main (String args[]) { + TradeStrategy runProcess = new TradeStrategy(); + } +} \ No newline at end of file diff --git a/fetchOptionsChain/RequestOptionChain.java b/fetchOptionsChain/RequestOptionChain.java new file mode 100644 index 0000000..b515d7e --- /dev/null +++ b/fetchOptionsChain/RequestOptionChain.java @@ -0,0 +1,29 @@ +package fetchOptionsChain; + +import com.ib.client.Contract; +import com.ib.client.EClientSocket; +import java.sql.Connection; + + +public class RequestOptionChain { + final Contract cont; + private final EClientSocket socket; + private final Connection sqlConnection; + + private static int nextId = 1; + private final int myId; + + public RequestOptionChain(Contract cont, EClientSocket socket, + Connection sqlConnection) { + this.cont = cont; + this.socket = socket; + this.sqlConnection = sqlConnection; + myId = nextId++; + socket.requestOptionChainWrapper(); + reqOptionData(); + } + + private void reqOptionData() { + socket.reqContractDetails(myId, cont); + } +} \ No newline at end of file diff --git a/fetchOptionsChain/RequestOptionChainWrapper.java b/fetchOptionsChain/RequestOptionChainWrapper.java new file mode 100644 index 0000000..7d0a44c --- /dev/null +++ b/fetchOptionsChain/RequestOptionChainWrapper.java @@ -0,0 +1,248 @@ +package fetchOptionsChain; + +import com.ib.client.CommissionReport; +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.EWrapper; +import com.ib.client.Execution; +import com.ib.client.Order; +import com.ib.client.OrderState; +import com.ib.client.TickType; +import com.ib.client.UnderComp; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.SQLException; + + +public class RequestOptionChainWrapper implements EWrapper{ + private final Connection sqlConnection; + private Statement statement = null; + private PreparedStatement preparedStatement = null; + private ResultSet resultSet = null; + + public int counter_iter; + + public RequestOptionChainWrapper(Connection sqlConnection) { + this.sqlConnection = sqlConnection; + } + + public double outputSQLDouble(ResultSet resultSet, String output_field) throws SQLException { + Double output_value = -1.0; + while (resultSet.next()) { + output_value = resultSet.getDouble(output_field); + } + return output_value; + } + + public int outputSQLInt(ResultSet resultSet, String output_field) throws SQLException { + int output_value = -1; + while (resultSet.next()) { + output_value = resultSet.getInt(output_field); + } + return output_value; + } + + + public void contractDetails(int reqId, ContractDetails contractDetails) { + try { + Contract contract = contractDetails.m_summary; + + // write to MasterChainList + preparedStatement = sqlConnection.prepareStatement("INSERT INTO " + + "IBAlgoSystem.MasterChainList VALUES (default, 'T', '" + + contract.m_symbol + "', '" + contract.m_secType + "', '" + + contract.m_exchange + "', '" + contract.m_currency + "', '" + + contract.m_expiry + "', " + + Double.toString(contract.m_strike) + ", '" + + contract.m_right + "', '" + contract.m_multiplier + + "', 'F', 'OTM');"); + preparedStatement.executeUpdate(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void contractDetailsEnd(int reqId) { + try { + // update counter + statement = sqlConnection.createStatement(); + resultSet = statement.executeQuery( + "SELECT counter FROM misc.counter;"); + counter_iter = outputSQLInt(resultSet, "counter"); + + counter_iter++; + + preparedStatement = sqlConnection.prepareStatement( + "UPDATE misc.counter SET counter = " + + Integer.toString(counter_iter) + ";"); + preparedStatement.executeUpdate(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void tickPrice(int tickerId, int field, double price, + int canAutoExecute) { + } + + public void execDetails(int reqId, Contract contract, Execution execution) { + } + + public void bondContractDetails(int reqId, ContractDetails contractDetails) { + } + + public void fundamentalData(int reqId, String data) { + } + + public void bondContractDetails(ContractDetails contractDetails) { + } + + public void currentTime(long time) { + } + + public void displayGroupList(int requestId, String contraftInfo) { + } + + public void displayGroupUpdated(int requestId, String contractInfo) { + } + + public void verifyCompleted(boolean completed, String contractInfo) { + } + + public void verifyMessageAPI(String message) { + } + + public void execDetailsEnd(int reqId) { + } + + public void historicalData(int reqId, String date, double open, double high, + double low, double close, int volume, int count, double WAP, + boolean hasGaps) { + } + + public void managedAccounts(String accountsList) { + } + + public void commissionReport(CommissionReport cr) { + } + + public void position(String account, Contract contract, int pos, + double avgCost) { + } + + public void positionEnd() { + } + + public void accountSummary(int reqId, String account, String tag, + String value, String currency) { + } + + public void accountSummaryEnd(int reqId) { + } + + public void accountDownloadEnd(String accountName) { + } + + public void openOrder(int orderId, Contract contract, Order order, + OrderState orderState) { + } + + public void openOrderEnd() { + } + + public void orderStatus(int orderId, String status, int filled, + int remaining, double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + } + + public void receiveFA (int faDataType, String xml) { + } + + public void scannerData(int reqId, int rank, ContractDetails contractDetails, + String distance, String benchmark, String projection, String legsStr) { + } + + public void scannerDataEnd(int reqId) { + } + + public void scannerParameters(String xml) { + } + + public void tickEFP(int symbolId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry) { + } + + public void tickGeneric(int symbolId, int tickType, double value) { + } + + public void tickOptionComputation( int tickerId, int field, + double impliedVol, double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + } + + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + } + + public void updateAccountTime(String timeStamp) { + } + + public void updateAccountValue(String key, String value, String currency, + String accountName) { + } + + public void updateMktDepth(int symbolId, int position, int operation, + int side, double price, int size) { + } + + public void updateMktDepthL2(int symbolId, int position, String marketMaker, + int operation, int side, double price, int size) { + } + + public void updateNewsBulletin(int msgId, int msgType, String message, + String origExchange) { + } + + public void updatePortfolio(Contract contract, int position, + double marketPrice, double marketValue, double averageCost, + double unrealizedPNL, double realizedPNL, String accountName) { + } + + public void marketDataType(int reqId, int marketDataType) { + } + + public void tickSnapshotEnd(int tickerId) { + } + + public void connectionClosed() { + } + + public void realtimeBar(int reqId, long time, double open, double high, + double low, double close, long volume, double wap, int count) { + } + + public void tickSize(int orderId, int field, int size) { + } + + public void tickString(int orderId, int tickType, String value) { + } + + public void error(Exception e) { + e.printStackTrace (); + } + + public void error(String str) { + System.err.println (str); + } + + public void error(int id, int errorCode, String errorMsg) { + System.err.println ("error: " + id + "," + errorCode + "," + errorMsg); + } + + public void nextValidId (int orderId) { + } +} \ No newline at end of file diff --git a/largePriceFeed/RequestPriceData.java b/largePriceFeed/RequestPriceData.java new file mode 100644 index 0000000..3b9d414 --- /dev/null +++ b/largePriceFeed/RequestPriceData.java @@ -0,0 +1,73 @@ +package largePriceFeed; + +import com.ib.client.Contract; +import com.ib.client.EClientSocket; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + + +public class RequestPriceData { + final Contract cont; + final boolean snapshot; + private final EClientSocket socket; + private final WritePriceData writePriceData; + private final Connection sqlConnection; + + private static int nextId = 1; + private final int myId; + + List bidPrices = new ArrayList<>(); + List askPrices = new ArrayList<>(); + List lastPrices = new ArrayList<>(); + List closePrices = new ArrayList<>(); + double bidPrice = -1.0; + double askPrice = -1.0; + double lastPrice = -1.0; + double closePrice = -1.0; + + public RequestPriceData(Contract cont, boolean snapshot, + EClientSocket socket, Connection sqlConnection) { + this.cont = cont; + this.snapshot = snapshot; + this.socket = socket; + this.sqlConnection = sqlConnection; + writePriceData = new WritePriceData(this, socket, sqlConnection); + myId = nextId++; + ((RequestPriceWrapper) socket.requestPriceWrapper()).dataMap.put(myId, this); + reqData(); + } + + private void reqData() { + socket.reqMktData(myId, cont, "", snapshot, null); + } + + // record bid price + public void dataRecdBid(double inputPrice) { + bidPrice = inputPrice; + bidPrices.add(inputPrice); + writePriceData.check(); + } + + // record ask price + public void dataRecdAsk(double inputPrice) { + askPrice = inputPrice; + askPrices.add(inputPrice); + writePriceData.check(); + } + + // record last price + public void dataRecdLast(double inputPrice) { + lastPrice = inputPrice; + lastPrices.add(inputPrice); + writePriceData.check(); + } + + // record close price + public void dataRecdClose(double inputPrice) { + closePrice = inputPrice; + closePrices.add(inputPrice); + writePriceData.check(); + } +} \ No newline at end of file diff --git a/largePriceFeed/RequestPriceWrapper.java b/largePriceFeed/RequestPriceWrapper.java new file mode 100644 index 0000000..d00dd9d --- /dev/null +++ b/largePriceFeed/RequestPriceWrapper.java @@ -0,0 +1,207 @@ +package largePriceFeed; + +import com.ib.client.CommissionReport; +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.EWrapper; +import com.ib.client.Execution; +import com.ib.client.Order; +import com.ib.client.OrderState; +import com.ib.client.TickType; +import com.ib.client.UnderComp; + +import java.util.HashMap; +import java.util.Map; + + +public class RequestPriceWrapper implements EWrapper{ + public Map dataMap = new HashMap<>(); + + // reqMktData snapshots are received here + public void tickPrice(int tickerId, int field, double price, + int canAutoExecute) { + + // record bid price + if (field == 1) { + dataMap.get(tickerId).dataRecdBid(price); + + // record ask price + } else if (field == 2) { + dataMap.get(tickerId).dataRecdAsk(price); + + // record last price + } else if (field == 4) { + dataMap.get(tickerId).dataRecdLast(price); + + // record close price + } else if (field == 9) { + dataMap.get(tickerId).dataRecdClose(price); + } + } + + public void execDetails(int reqId, Contract contract, Execution execution) { + } + + public void bondContractDetails(int reqId, ContractDetails contractDetails) { + } + + public void contractDetails(int reqId, ContractDetails contractDetails) { + } + + public void contractDetailsEnd(int reqId) { + } + + public void fundamentalData(int reqId, String data) { + } + + public void bondContractDetails(ContractDetails contractDetails) { + } + + public void contractDetails(ContractDetails contractDetails) { + } + + public void currentTime(long time) { + } + + public void displayGroupList(int requestId, String contraftInfo) { + } + + public void displayGroupUpdated(int requestId, String contractInfo) { + } + + public void verifyCompleted(boolean completed, String contractInfo) { + } + + public void verifyMessageAPI(String message) { + } + + public void execDetailsEnd(int reqId) { + } + + public void historicalData(int reqId, String date, double open, double high, + double low, double close, int volume, int count, double WAP, + boolean hasGaps) { + } + + public void managedAccounts(String accountsList) { + } + + public void commissionReport(CommissionReport cr) { + } + + public void position(String account, Contract contract, int pos, + double avgCost) { + } + + public void positionEnd() { + } + + public void accountSummary(int reqId, String account, String tag, + String value, String currency) { + } + + public void accountSummaryEnd(int reqId) { + } + + public void accountDownloadEnd(String accountName) { + } + + public void openOrder(int orderId, Contract contract, Order order, + OrderState orderState) { + } + + public void openOrderEnd() { + } + + public void orderStatus(int orderId, String status, int filled, + int remaining, double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + } + + public void receiveFA (int faDataType, String xml) { + } + + public void scannerData(int reqId, int rank, ContractDetails contractDetails, + String distance, String benchmark, String projection, String legsStr) { + } + + public void scannerDataEnd(int reqId) { + } + + public void scannerParameters(String xml) { + } + + public void tickEFP(int symbolId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry) { + } + + public void tickGeneric(int symbolId, int tickType, double value) { + } + + public void tickOptionComputation( int tickerId, int field, + double impliedVol, double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + } + + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + } + + public void updateAccountTime(String timeStamp) { + } + + public void updateAccountValue(String key, String value, String currency, + String accountName) { + } + + public void updateMktDepth(int symbolId, int position, int operation, + int side, double price, int size) { + } + + public void updateMktDepthL2(int symbolId, int position, String marketMaker, + int operation, int side, double price, int size) { + } + + public void updateNewsBulletin(int msgId, int msgType, String message, + String origExchange) { + } + + public void updatePortfolio(Contract contract, int position, + double marketPrice, double marketValue, double averageCost, + double unrealizedPNL, double realizedPNL, String accountName) { + } + + public void marketDataType(int reqId, int marketDataType) { + } + + public void tickSnapshotEnd(int tickerId) { + } + + public void connectionClosed() { + } + + public void realtimeBar(int reqId, long time, double open, double high, + double low, double close, long volume, double wap, int count) { + } + + public void tickSize(int orderId, int field, int size) { + } + + public void tickString(int orderId, int tickType, String value) { + } + + public void error(Exception e) { + e.printStackTrace (); + } + + public void error(String str) { + System.err.println (str); + } + + public void error(int id, int errorCode, String errorMsg) { + System.err.println ("error: " + id + "," + errorCode + "," + errorMsg); + } + + public void nextValidId (int orderId) { + } +} \ No newline at end of file diff --git a/largePriceFeed/WritePriceData.java b/largePriceFeed/WritePriceData.java new file mode 100644 index 0000000..d74ba47 --- /dev/null +++ b/largePriceFeed/WritePriceData.java @@ -0,0 +1,120 @@ +package largePriceFeed; + +import com.ib.client.EClientSocket; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.SQLException; +import java.util.Date; + + +public class WritePriceData { + public static final int NULL=0, LOOK=1<<0, LONG=1<<1, SHORT=1<<2, WAIT_FILL=1<<3, WAIT_CANCEL=1<<4; + public int sysState = NULL; + private final RequestPriceData data; + private final EClientSocket socket; + private final Connection sqlConnection; + private Statement statement = null; + private PreparedStatement preparedStatement = null; + private ResultSet resultSet = null; + private double prevLastPrice; + private int bugCounter; + + private static int nextOrderId = 1; + + WritePriceData(RequestPriceData data, EClientSocket socket, + Connection sqlConnection) { + this.data = data; + this.socket = socket; + this.sqlConnection = sqlConnection; + sysState = LOOK; + } + + void check() { + try { + if (data.cont.m_secType.equals("STK")) { + // check that lastPrice isn't a bug + statement = sqlConnection.createStatement(); + resultSet = statement.executeQuery( + "SELECT last FROM IBAlgoSystem.price WHERE symbol='" + + data.cont.m_symbol + "' AND secType='STK';"); + prevLastPrice = outputLastPrice(resultSet); + resultSet = statement.executeQuery( + "SELECT bugCounter FROM IBAlgoSystem.price WHERE symbol='" + + data.cont.m_symbol + "' AND secType='STK';"); + bugCounter = outputBugCounter(resultSet); + + + if ((prevLastPrice > 0.0) && + (Math.abs(data.lastPrice/prevLastPrice - 1) > 0.1) && + (bugCounter < 3)) { + bugCounter++; + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bugCounter=" + + Integer.toString(bugCounter) + ";"); + } else { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bid =" + + Double.toString(data.bidPrice) + ", ask =" + + Double.toString(data.askPrice) + ", last =" + + Double.toString(data.lastPrice) + ", close = " + + Double.toString(data.closePrice) + + ", bugCounter = 0, updateTime = " + + Long.toString((new Date()).getTime()) + + " WHERE symbol = '" + data.cont.m_symbol + + "' AND secType = 'STK' AND currency = '" + + data.cont.m_currency + "';"); + } + + } else if (data.cont.m_secType.equals("OPT")) { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bid =" + + Double.toString(data.bidPrice) + ", ask =" + + Double.toString(data.askPrice) + ", last =" + + Double.toString(data.lastPrice) + ", close = " + + Double.toString(data.closePrice) + + ", updateTime = " + Long.toString((new Date()).getTime()) + + " WHERE symbol = '" + data.cont.m_symbol + + "' AND secType = 'OPT' AND currency = '" + + data.cont.m_currency + "' AND expiry = '" + + data.cont.m_expiry + "' AND strike = " + + Double.toString(data.cont.m_strike) + " AND callorput = '" + + data.cont.m_right + "' AND multiplier = '" + + data.cont.m_multiplier + "';"); + + } else if (data.cont.m_secType.equals("CASH")) { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bid =" + + Double.toString(data.bidPrice) + ", ask =" + + Double.toString(data.askPrice) + ", last =" + + Double.toString(data.lastPrice) + ", close =" + + Double.toString(data.closePrice) + ", updateTime = " + + Long.toString((new Date()).getTime()) + + " WHERE symbol = '" + data.cont.m_symbol + + "' AND secType = 'CASH' AND currency = '" + + data.cont.m_currency + "';"); + } + preparedStatement.executeUpdate(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public double outputLastPrice(ResultSet resultSet) throws SQLException { + Double lastPrice = -1.0; + while (resultSet.next()) { + lastPrice = resultSet.getDouble("last"); + } + return lastPrice; + } + + public int outputBugCounter(ResultSet resultSet) throws SQLException { + int bugCounter = 0; + while (resultSet.next()) { + bugCounter = resultSet.getInt("bugCounter"); + } + return bugCounter; + } +} \ No newline at end of file diff --git a/simplePriceFeed/RequestPriceData.java b/simplePriceFeed/RequestPriceData.java new file mode 100644 index 0000000..9e87f2e --- /dev/null +++ b/simplePriceFeed/RequestPriceData.java @@ -0,0 +1,71 @@ +package simplePriceFeed; + +import com.ib.client.Contract; +import com.ib.client.EClientSocket; + +import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; + + +public class RequestPriceData { + final Contract cont; + private final EClientSocket socket; + private final Connection sqlConnection; + private final WritePriceData writePriceData; + + private static int nextId = 1; + private final int myId; + + List bidPrices = new ArrayList<>(); + List askPrices = new ArrayList<>(); + List lastPrices = new ArrayList<>(); + List closePrices = new ArrayList<>(); + double bidPrice = -1.0; + double askPrice = -1.0; + double lastPrice = -1.0; + double closePrice = -1.0; + + public RequestPriceData(Contract cont, EClientSocket socket, + Connection sqlConnection) { + this.cont = cont; + this.socket = socket; + this.sqlConnection = sqlConnection; + writePriceData = new WritePriceData(this, socket, sqlConnection); + myId = nextId++; + ((RequestPriceWrapper) socket.requestPriceWrapper()).dataMap.put(myId, this); + reqData(); + } + + private void reqData() { + socket.reqMktData(myId, cont, "", false, null); + } + + // record bid price + public void dataRecdBid(double inputPrice) { + bidPrice = inputPrice; + bidPrices.add(inputPrice); + writePriceData.check(); + } + + // record ask price + public void dataRecdAsk(double inputPrice) { + askPrice = inputPrice; + askPrices.add(inputPrice); + writePriceData.check(); + } + + // record last price + public void dataRecdLast(double inputPrice) { + lastPrice = inputPrice; + lastPrices.add(inputPrice); + writePriceData.check(); + } + + // record close price + public void dataRecdClose(double inputPrice) { + closePrice = inputPrice; + closePrices.add(inputPrice); + writePriceData.check(); + } +} \ No newline at end of file diff --git a/simplePriceFeed/RequestPriceWrapper.java b/simplePriceFeed/RequestPriceWrapper.java new file mode 100644 index 0000000..e5720d4 --- /dev/null +++ b/simplePriceFeed/RequestPriceWrapper.java @@ -0,0 +1,206 @@ +package simplePriceFeed; + +import com.ib.client.CommissionReport; +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.EWrapper; +import com.ib.client.Execution; +import com.ib.client.Order; +import com.ib.client.OrderState; +import com.ib.client.TickType; +import com.ib.client.UnderComp; + +import java.util.HashMap; +import java.util.Map; + +public class RequestPriceWrapper implements EWrapper{ + public Map dataMap = new HashMap<>(); + + // reqMktData snapshots are received here + public void tickPrice(int tickerId, int field, double price, + int canAutoExecute) { + + // record bid price + if (field == 1) { + dataMap.get(tickerId).dataRecdBid(price); + + // record ask price + } else if (field == 2) { + dataMap.get(tickerId).dataRecdAsk(price); + + // record last price + } else if (field == 4) { + dataMap.get(tickerId).dataRecdLast(price); + + // record close price + } else if (field == 9) { + dataMap.get(tickerId).dataRecdClose(price); + } + } + + public void execDetails(int reqId, Contract contract, Execution execution) { + } + + public void bondContractDetails(int reqId, ContractDetails contractDetails) { + } + + public void contractDetails(int reqId, ContractDetails contractDetails) { + } + + public void contractDetailsEnd(int reqId) { + } + + public void fundamentalData(int reqId, String data) { + } + + public void bondContractDetails(ContractDetails contractDetails) { + } + + public void contractDetails(ContractDetails contractDetails) { + } + + public void currentTime(long time) { + } + + public void displayGroupList(int requestId, String contraftInfo) { + } + + public void displayGroupUpdated(int requestId, String contractInfo) { + } + + public void verifyCompleted(boolean completed, String contractInfo) { + } + + public void verifyMessageAPI(String message) { + } + + public void execDetailsEnd(int reqId) { + } + + public void historicalData(int reqId, String date, double open, double high, + double low, double close, int volume, int count, double WAP, + boolean hasGaps) { + } + + public void managedAccounts(String accountsList) { + } + + public void commissionReport(CommissionReport cr) { + } + + public void position(String account, Contract contract, int pos, + double avgCost) { + } + + public void positionEnd() { + } + + public void accountSummary(int reqId, String account, String tag, + String value, String currency) { + } + + public void accountSummaryEnd(int reqId) { + } + + public void accountDownloadEnd(String accountName) { + } + + public void openOrder(int orderId, Contract contract, Order order, + OrderState orderState) { + } + + public void openOrderEnd() { + } + + public void orderStatus(int orderId, String status, int filled, + int remaining, double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + } + + public void receiveFA (int faDataType, String xml) { + } + + public void scannerData(int reqId, int rank, ContractDetails contractDetails, + String distance, String benchmark, String projection, String legsStr) { + } + + public void scannerDataEnd(int reqId) { + } + + public void scannerParameters(String xml) { + } + + public void tickEFP(int symbolId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry) { + } + + public void tickGeneric(int symbolId, int tickType, double value) { + } + + public void tickOptionComputation( int tickerId, int field, + double impliedVol, double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + } + + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + } + + public void updateAccountTime(String timeStamp) { + } + + public void updateAccountValue(String key, String value, String currency, + String accountName) { + } + + public void updateMktDepth(int symbolId, int position, int operation, + int side, double price, int size) { + } + + public void updateMktDepthL2(int symbolId, int position, String marketMaker, + int operation, int side, double price, int size) { + } + + public void updateNewsBulletin(int msgId, int msgType, String message, + String origExchange) { + } + + public void updatePortfolio(Contract contract, int position, + double marketPrice, double marketValue, double averageCost, + double unrealizedPNL, double realizedPNL, String accountName) { + } + + public void marketDataType(int reqId, int marketDataType) { + } + + public void tickSnapshotEnd(int tickerId) { + } + + public void connectionClosed() { + } + + public void realtimeBar(int reqId, long time, double open, double high, + double low, double close, long volume, double wap, int count) { + } + + public void tickSize(int orderId, int field, int size) { + } + + public void tickString(int orderId, int tickType, String value) { + } + + public void error(Exception e) { + e.printStackTrace(); + } + + public void error(String str) { + System.err.println(str); + } + + public void error(int id, int errorCode, String errorMsg) { + System.err.println("error: " + id + "," + errorCode + "," + errorMsg); + } + + public void nextValidId (int orderId) { + } +} \ No newline at end of file diff --git a/simplePriceFeed/WritePriceData.java b/simplePriceFeed/WritePriceData.java new file mode 100644 index 0000000..3d601d8 --- /dev/null +++ b/simplePriceFeed/WritePriceData.java @@ -0,0 +1,109 @@ +package simplePriceFeed; + +import com.ib.client.EClientSocket; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.SQLException; +import java.util.Date; + + +public class WritePriceData { + public static final int NULL=0, LOOK=1<<0, LONG=1<<1, SHORT=1<<2, WAIT_FILL=1<<3, WAIT_CANCEL=1<<4; + public int sysState = NULL; + private final RequestPriceData data; + private final EClientSocket socket; + private final Connection sqlConnection; + private Statement statement = null; + private PreparedStatement preparedStatement = null; + private ResultSet resultSet = null; + private double prevLastPrice; + private int bugCounter; + + private static int nextOrderId = 1; + + WritePriceData(RequestPriceData data, EClientSocket socket, + Connection sqlConnection) { + this.data = data; + this.socket = socket; + this.sqlConnection = sqlConnection; + sysState = LOOK; + } + + void check() { + try { + if (data.cont.m_secType.equals("STK")) { + // check that lastPrice isn't a bug + statement = sqlConnection.createStatement(); + resultSet = statement.executeQuery( + "SELECT last FROM IBAlgoSystem.price WHERE symbol='" + + data.cont.m_symbol + "' AND secType='STK';"); + prevLastPrice = outputLastPrice(resultSet); + resultSet = statement.executeQuery( + "SELECT bugCounter FROM IBAlgoSystem.price WHERE symbol='" + + data.cont.m_symbol + "' AND secType='STK';"); + bugCounter = outputBugCounter(resultSet); + + + if ((prevLastPrice > 0.0) && + (Math.abs(data.lastPrice/prevLastPrice - 1) > 0.1) && + (bugCounter < 3)) { + bugCounter++; + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bugCounter=" + + Integer.toString(bugCounter) + ";"); + } else { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bid =" + + Double.toString(data.bidPrice) + ", ask =" + + Double.toString(data.askPrice) + ", last =" + + Double.toString(data.lastPrice) + ", close =" + + Double.toString(data.closePrice) + + ", bugCounter = 0, updateTime = " + + Long.toString((new Date()).getTime()) + + " WHERE symbol = '" + data.cont.m_symbol + + "' AND secType ='STK' AND currency = '" + + data.cont.m_currency + "';"); + } + + } else if (data.cont.m_secType.equals("OPT")) { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.price SET bid =" + + Double.toString(data.bidPrice) + ", ask =" + + Double.toString(data.askPrice) + ", last =" + + Double.toString(data.lastPrice) + ", close =" + + Double.toString(data.closePrice) + ", updateTime =" + + Long.toString((new Date()).getTime()) + + " WHERE symbol = '" + data.cont.m_symbol + + "' AND secType = 'OPT' AND currency = '" + + data.cont.m_currency + "' AND expiry='" + + data.cont.m_expiry + "' AND strike =" + + Double.toString(data.cont.m_strike) + " AND callorput = '" + + data.cont.m_right + "' AND multiplier = '" + + data.cont.m_multiplier + "';"); + } + preparedStatement.executeUpdate(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public double outputLastPrice(ResultSet resultSet) throws SQLException { + Double lastPrice = -1.0; + while (resultSet.next()) { + lastPrice = resultSet.getDouble("last"); + } + return lastPrice; + } + + public int outputBugCounter(ResultSet resultSet) throws SQLException { + int bugCounter = 0; + while (resultSet.next()) { + bugCounter = resultSet.getInt("bugCounter"); + } + return bugCounter; + } +} \ No newline at end of file diff --git a/tradeStrategy/FetchOrderStatus.java b/tradeStrategy/FetchOrderStatus.java new file mode 100644 index 0000000..a7882d3 --- /dev/null +++ b/tradeStrategy/FetchOrderStatus.java @@ -0,0 +1,124 @@ +package tradeStrategy; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + + +public class FetchOrderStatus { + public int num_fields = 4; + + private final Connection sqlConnection; + private PreparedStatement preparedStatement = null; + private ResultSet resultSet = null; + + + public String[] ReadOrderStatus(int orderID, Connection sqlConnection) { + String[] order_stats = new String[num_fields]; + StringBuilder check_order_stats; + + boolean checks_out = false; + while (!(checks_out)) { + try { + preparedStatement = sqlConnection.prepareStatement( + "SELECT status FROM IBAlgoSystem.orderTracking WHERE orderID = " + + Integer.toString(orderId) + ";"); + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + check_order_stats = new StringBuilder(resultSet.getString( + "status")); + } + + if ((check_order_stats.toString().equals("PendingSubmit")) || + (check_order_stats.toString().equals("PendingCancel")) || + (check_order_stats.toString().equals("PreSubmitted")) || + (check_order_stats.toString().equals("ApiCancelled")) || + (check_order_stats.toString().equals("Cancelled")) || + (check_order_stats.toString().equals("Filled")) || + (check_order_stats.toString().equals("Inactive"))) { + + order_stats[0] = check_order_stats.toString(); + + preparedStatement = sqlConnection.prepareStatement( + "SELECT filled FROM IBAlgoSystem.orderTracking WHERE " + + "orderID = " + Integer.toString(orderId) + ";"); + resultSet = preparedStatement.executeQuery(); + order_stats[1] = Integer.toString(outputSQLInt(resultSet, + "filled")); + + preparedStatement = sqlConnection.prepareStatement( + "SELECT remaining FROM IBAlgoSystem.orderTracking WHERE " + + "orderID = " + Integer.toString(orderId) + ";"); + resultSet = preparedStatement.executeQuery(); + order_stats[2] = Integer.toString(outputSQLInt(resultSet, + "remaining")); + + preparedStatement = sqlConnection.prepareStatement( + "SELECT avgFillPrice FROM IBAlgoSystem.orderTracking " + + "WHERE orderID = " + Integer.toString(orderId) + ";"); + resultSet = preparedStatement.executeQuery(); + order_stats[3] = Double.toString(outputSQLDouble(resultSet, + "avgFillPrice")); + + checks_out = true; + } + } catch (Exception e) { + } + } + return order_stats; + } + + + public void WriteOrderStatus(int orderID, String status, int filled, + int remaining, double avgFillPrice, Connection sqlConnection) { + try { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.orderTracking SET orderID = " + + Integer.toString(orderID) + ", status = '" + status + + "', filled = " + Integer.toString(filled) + ", remaining = " + + Integer.toString(remaining) + ", avgFillPrice = " + + Double.toString(avgFillPrice) + " WHERE orderID = " + + Integer.toString(orderID) + ";"); + preparedStatement.executeUpdate(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public boolean OrderRecorded(int orderID, Connection sqlConnection) { + boolean order_recorded = false; + try { + preparedStatement = sqlConnection.prepareStatement( + "SELECT COUNT(*) FROM IBAlgoSystem.orderTracking WHERE orderID = " + + Integer.toString(orderID) + ";"); + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + if (resultSet.getInt("COUNT(*)") > 0) { + order_recorded = true; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return order_recorded; + } + + + public int outputSQLInt(ResultSet resultSet, String field_name) throws SQLException { + int output_value = -1; + while (resultSet.next()) { + output_value = resultSet.getInt(field_name); + } + return output_value; + } + + public double outputSQLDouble(ResultSet resultSet, String field_name) throws SQLException { + double output_value = -1.0; + while (resultSet.next()) { + output_value = resultSet.getInt(field_name); + } + return output_value; + } +} \ No newline at end of file diff --git a/tradeStrategy/TradeStrategyWrapper.java b/tradeStrategy/TradeStrategyWrapper.java new file mode 100644 index 0000000..8388226 --- /dev/null +++ b/tradeStrategy/TradeStrategyWrapper.java @@ -0,0 +1,207 @@ +package tradeStrategy; + +import tradeStrategy.FetchOrderStatus; + +import com.ib.client.CommissionReport; +import com.ib.client.Contract; +import com.ib.client.ContractDetails; +import com.ib.client.EWrapper; +import com.ib.client.Execution; +import com.ib.client.Order; +import com.ib.client.OrderState; +import com.ib.client.TickType; +import com.ib.client.UnderComp; + +import java.sql.Connection; +import java.sql.PreparedStatement; + + +public class TradeStrategyWrapper implements EWrapper{ + private final Connection sqlConnection; + private PreparedStatement preparedStatement = null; + + public FetchOrderStatus fetchOrderStatus = new FetchOrderStatus(); + + public TradeStrategyWrapper(Connection sqlConnection) { + this.sqlConnection = sqlConnection; + } + + public void bondContractDetails(int reqId, ContractDetails contractDetails) { + } + + public void contractDetails(int reqId, ContractDetails contractDetails) { + } + + public void contractDetailsEnd(int reqId) { + } + + public void fundamentalData(int reqId, String data) { + } + + public void bondContractDetails(ContractDetails contractDetails) { + } + + public void contractDetails(ContractDetails contractDetails) { + } + + public void currentTime(long time) { + } + + public void displayGroupList(int requestId, String contraftInfo) { + } + + public void displayGroupUpdated(int requestId, String contractInfo) { + } + + public void verifyCompleted(boolean completed, String contractInfo) { + } + + public void verifyMessageAPI(String message) { + } + + public void execDetails(int orderId, Contract contract, Execution execution) { + } + + public void execDetailsEnd(int reqId) { + } + + public void historicalData(int reqId, String date, double open, double high, + double low, double close, int volume, int count, double WAP, + boolean hasGaps) { + } + + public void managedAccounts(String accountsList) { + } + + public void commissionReport(CommissionReport cr) { + } + + public void position(String account, Contract contract, int pos, + double avgCost) { + } + + public void positionEnd() { + } + + public void accountSummary(int reqId, String account, String tag, + String value, String currency) { + try { + preparedStatement = sqlConnection.prepareStatement( + "UPDATE IBAlgoSystem.margin SET " + tag + " = " + value + ";"); + preparedStatement.executeUpdate(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void accountSummaryEnd(int reqId) { + } + + public void accountDownloadEnd(String accountName) { + } + + public void openOrder(int orderId, Contract contract, Order order, + OrderState orderState) { + } + + public void openOrderEnd() { + } + + public void orderStatus(int orderId, String status, int filled, + int remaining, double avgFillPrice, int permId, int parentId, + double lastFillPrice, int clientId, String whyHeld) { + fetchOrderStatus.WriteOrderStatus(orderId, status, filled, remaining, + avgFillPrice, sqlConnection); + } + + public void receiveFA (int faDataType, String xml) { + } + + public void scannerData(int reqId, int rank, ContractDetails contractDetails, + String distance, String benchmark, String projection, String legsStr) { + } + + public void scannerDataEnd(int reqId) { + } + + public void scannerParameters(String xml) { + } + + public void tickEFP(int symbolId, int tickType, double basisPoints, + String formattedBasisPoints, double impliedFuture, int holdDays, + String futureExpiry, double dividendImpact, double dividendsToExpiry) { + } + + public void tickGeneric(int symbolId, int tickType, double value) { + } + + public void tickOptionComputation( int tickerId, int field, + double impliedVol, double delta, double optPrice, double pvDividend, + double gamma, double vega, double theta, double undPrice) { + } + + public void deltaNeutralValidation(int reqId, UnderComp underComp) { + } + + public void updateAccountTime(String timeStamp) { + } + + public void updateAccountValue(String key, String value, String currency, + String accountName) { + } + + public void updateMktDepth(int symbolId, int position, int operation, + int side, double price, int size) { + } + + public void updateMktDepthL2(int symbolId, int position, String marketMaker, + int operation, int side, double price, int size) { + } + + public void updateNewsBulletin(int msgId, int msgType, String message, + String origExchange) { + } + + public void updatePortfolio(Contract contract, int position, + double marketPrice, double marketValue, double averageCost, + double unrealizedPNL, double realizedPNL, String accountName) { + } + + public void marketDataType(int reqId, int marketDataType) { + } + + public void tickSnapshotEnd(int tickerId) { + } + + public void connectionClosed() { + } + + public void realtimeBar(int reqId, long time, double open, double high, + double low, double close, long volume, double wap, int count) { + } + + public void tickSize(int orderId, int field, int size) { + } + + public void tickString(int orderId, int tickType, String value) { + } + + public void error(Exception e) { + e.printStackTrace (); + } + + public void error(String str) { + System.err.println (str); + } + + public void error(int id, int errorCode, String errorMsg) { + System.err.println ("error: " + id + "," + errorCode + "," + errorMsg); + } + + public void nextValidId (int orderId) { + } + + public void tickPrice(int orderId, int field, double price, + int canAutoExecute) { + } +} \ No newline at end of file