Keyboard Shortcuts
Likes
Search
Building an options trading algo using TWS. Need some help!
Ben Alex
Hi It might help if you expand on what you're after. Do you want some guidance on coding Java generally, some help using IB's Java library, or are you seeking someone to write some or all of code for you? Is your long-term goal to maintain the code yourself or did you want someone to continue with that?Java can seem daunting to learn, but it is well worth it if you have a few months available. While there are hundreds of books and tutorials out there, I know lots of professional Java developers who worked their way through (and Oracle to their credit keep it up-to-date with new Java improvements). If you are after trading system design advice or help with the IB Java library, this list will give you a lot of free advice. also includes lots of design, programming and API information if you haven't already seen it. Basically, if you're willing to invest the time and use the many high quality (free) resources out there, you can almost certainly write it yourself. One thing I'm curious on is does your strategy require human involvement or is it entirely algorithmic? What is the typical holding time and what data do you process (eg daily, minute, tick, bid-ask level)? Letting people know that makes a major difference to the sort of program you're trying to build (ie a GUI-driven decision support tool vs a headless black box that performs trades) and is more likely to appeal to someone who has already built that class of application and can quickly adapt their existing experience and/or code. Cheers Ben |
If you are new to programming you have a long road ahead of you. I suggest you get an expert to at least set up a framework for you.
I have such a framework which allows setting up a simple trading environment in less than a day (and yes I do remember the remarks from people in this group that it is "impossible"..... ) However I do not give it away for free. The cost is relatively limited compared to creating it yourself though (expect at least 6 months if you do it yourself - TWS API has a lot of quirks...) Drop me an e-mail at fshsweden@... if you want to discuss this type of solution. //Peter |
This is a recent post to another forum. I am new to the automated trading world and writing code. My goal is to develop an algorithm that trades options credit spreads. I have been manually trading this strategy for about a year, The problem is I still have a full time job and the strategy needs close attention. I would like the ability to have the algo enter trades. It would also need the ability to turn this feature off and be attached to a manually entered trade. The present strategy is to enter trades after the open and close all trades before market close. I have been trading SPY and the overnight gaps are dangerous. The criteria would be: 1. Determine the direction of the underlying. Bullish would enter a put credit. Bearish would enter a call credit spread. 2. Enter trades after an adjustable time. The first hour is too volatile. 3. A short position delta of A. This determines probability of profit. 4. A spread of B points 5. The credit is => the number of days till expiration (15%roi for 15dte) 6. I also look at open interest and find the highest. That is where the smart money is and a great indicator of what is going to happen. Once the credit spread is filled, the algo will monitor the long and short positions. The short position will immediately have a trailing stop order of Ycents placed on it. I have been using .20 cents for the first hour and then adjust to .1-.12 cents for the rest of the day. If price goes in my favor the short will lose value and eventually be stopped out for a profit. If price does not go in my favor the short will get stopped out thus minimizing loss. When this occurs, a tight trailing stop is placed on the long position. If price continues in the right direction the long will get stopped out. If price reverses the long will gain value and either increase profit for the spread or reduce the loss. Finding the right trailing stop values has been a challenge. Getting stopped out and maximizing profit is a fine line. Other ideas for exiting the trades are encouraged! If the trade goes my way and does not get stopped out. the algo will close the trade at a determined percentage of max profit. I currently use Interactive Brokers to trade so the algo should be compatible with IB. I am open to suggestions on where to use it. I see the algo working like this:
There is a lot more to discuss but I think this gives the basic concept. Check out www.daytradingzones.com. This where I learned the strategy. I am not affiliated with them. |
Nick
You forgot to mention things like how to deal with and recover from an outage (either your app or internet connection or IB issue).
toggle quoted message
Show quoted text
Also you have to handle things like when to stay on the sidelines due to economic reports or holidays. If you are new to programming and want to develop this part time I doubt you will finish it in a year. Still, I'm rooting for your success. It's just that there is a huge amount of things you have to learn in order to create an app like this. On 12/14/2015 6:59 AM, todell826@... [TWSAPI] wrote:
This is a recent post to another forum. |
I haven't traded SPY option in awhile, but I noticed with ES options that market makers often pull bids and offers, usually both sides at once, for periods of a fraction of a second to several minutes.? During that time, there is exceedingly poor liquidity, and a stop could get filled at a very bad price.
Note also, if you're a USA taxpayer, ES and SPX options have much better tax treatment. Good luck! [rwk] ---In TWSAPI@..., <todell826@...> wrote : Once the credit spread is filled, the algo will monitor the long and short positions. The short position will immediately have a trailing stop order of Ycents placed on it. I have been using .20 cents for the first hour and then adjust to .1-.12 cents for the rest of the day. If price goes in my favor the short will lose value and eventually be stopped out for a profit. If price does not go in my favor the short will get stopped out thus minimizing loss. When this occurs, a tight trailing stop is placed on the long position. If price continues in the right direction the long will get stopped out. If price reverses the long will gain value and either increase profit for the spread or reduce the loss. Finding the right trailing stop values has been a challenge. Getting stopped out and maximizing profit is a fine line. Other ideas for exiting the trades are encouraged! |
Somewhat related to OP's requirements, i.e., placing orders after certain time in market. ?How do you do it in TWS (not API)? ?I can't seem to find conditional orders in TWS doing that.
I am thinking about a simple execution like this, using swigibpy (Python C++ API wrapper):? if PRICE > High of first 5 min candle: Buy AMT shares of XXX when XXX goes above PRICE else Buy AMT shares of XXX when XXX goes above High of the first 5 min candle # attach stop loss and scaling Stop Loss AMT of XXX at Stop_loss_price Listen to market data for the holdings in the portfolio Sell AMT/2 shares of HOLDINGS when HOLDINGS appreciates 2% Trailing Stop?HOLDINGS |
Hello all, Thanks for all the tips and comments! I am adding them to the specifications. As fshsweden stated, We need a robust framework that can handle and recover from all the problems that can arise. Any trading program needs close attention when running. That being said, is a java api? and TWS the way to go? If so, is building a GUI in NetBeans the best solution? I'm thinking commercial product in the distant future. Little newbie steps for now! |
ce
?
Is? GAT (Good After Time ) order type useful here ?
?
https://www.interactivebrokers.com/en/index.php?f=587
?
-----Original Message----- From: "kein520@... [TWSAPI]" [TWSAPI@...] Date: 12/14/2015 08:17 PM To: TWSAPI@... Subject: [TWS API] Re: Building an options trading algo using TWS. Need some help! ? Somewhat related to OP's requirements, i.e., placing orders after certain time in market. ?How do you do it in TWS (not API)? ?I can't seem to find conditional orders in TWS doing that.
?
I am thinking about a simple execution like this, using swigibpy (Python C++ API wrapper):?
?
if PRICE > High of first 5 min candle:
Buy AMT shares of XXX when XXX goes above PRICE
else
Buy AMT shares of XXX when XXX goes above High of the first 5 min candle
# attach stop loss and scaling
Stop Loss AMT of XXX at Stop_loss_price
?
Listen to market data for the holdings in the portfolio
Sell AMT/2 shares of HOLDINGS when HOLDINGS appreciates 2%
Trailing Stop?HOLDINGS
?
?
?
? |
I have been looking at the IB sample application. From what I can see it has a lot of the functions needed for the option strategies I am working on. One problem it has is when requesting options chain data, the api loses connection due to exceeding the request per second limit of 50. Does anyone have a solution? This is the option chain panel in the latest version. /* Copyright (C) 2013 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 apidemo; import static com.ib.controller.Formats.fmtNz; import static com.ib.controller.Formats.fmtPct; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.Timer; import javax.swing.border.TitledBorder; import javax.swing.table.AbstractTableModel; import apidemo.util.HtmlButton; import apidemo.util.NewTabbedPanel; import apidemo.util.NewTabbedPanel.NewTabPanel; import apidemo.util.TCombo; import apidemo.util.UpperField; import apidemo.util.Util; import apidemo.util.VerticalPanel; import com.ib.client.Contract; import com.ib.client.ContractDetails; import com.ib.client.TickType; import com.ib.client.Types.Right; import com.ib.client.Types.SecType; import com.ib.controller.ApiController.IContractDetailsHandler; import com.ib.controller.ApiController.IOptHandler; import com.ib.controller.ApiController.TopMktDataAdapter; public class OptionChainsPanel extends JPanel { ?private Contract m_underContract = new Contract(); ?private NewTabbedPanel m_tabbedPanel = new NewTabbedPanel(); ?private JTextField m_optExch = new UpperField(); ?private UpperField m_symbol = new UpperField(); ?private TCombo<SecType> m_secType = new TCombo<SecType>( SecType.values() ); ?private UpperField m_exchange = new UpperField(); ?private UpperField m_currency = new UpperField(); ?private JCheckBox m_snapshot = new JCheckBox(); ?OptionChainsPanel() { ??m_symbol.setText( "IBM"); ??m_secType.setSelectedItem( SecType.STK); ??m_exchange.setText( "SMART"); ??m_currency.setText( "USD"); ??m_optExch.setText( "SMART"); ?? ??HtmlButton button = new HtmlButton( "Go") { ???@Override protected void actionPerformed() { ????onAdd(); ???} ??}; ?? ??VerticalPanel topPanel = new VerticalPanel(); ??topPanel.add( "Symbol", m_symbol); ??? ?topPanel.add( "Currency", m_currency); ??? ?topPanel.add( "Underlying sec type", m_secType); ??? ?topPanel.add( "Underlying exchange", m_exchange, Box.createHorizontalStrut(20), button); ??topPanel.add( "Option exchange", m_optExch); ??topPanel.add( "Use snapshot data", m_snapshot); ?? ??setLayout( new BorderLayout() ); ??add( topPanel, BorderLayout.NORTH); ??add( m_tabbedPanel); ?} ?protected void onAdd() { ??m_underContract.symbol( m_symbol.getText().toUpperCase() ); ??m_underContract.secType( m_secType.getSelectedItem() ); ??m_underContract.exchange( m_exchange.getText().toUpperCase() ); ??m_underContract.currency( m_currency.getText().toUpperCase() ); ??ApiDemo.INSTANCE.controller().reqContractDetails( m_underContract, new IContractDetailsHandler() { ???@Override public void contractDetails(ArrayList<ContractDetails> list) { ????onRecUnderDetails( list); ???} ??}); ?} ?protected void onRecUnderDetails(ArrayList<ContractDetails> list) { ??if (list.size() != 1) { ???ApiDemo.INSTANCE.show( "Error: " + list.size() + " underlying contracts returned"); ???return; ??} ?? ??// request option chains ??Contract optContract = new Contract(); ??optContract.symbol( m_underContract.symbol() ); ??optContract.currency( m_underContract.currency() ); ??optContract.exchange( m_optExch.getText() ); ??optContract.secType( SecType.OPT); ?? ??final ChainPanel symbolPanel = new ChainPanel(); ??m_tabbedPanel.addTab( optContract.symbol(), symbolPanel, true, true); ?? ??ApiDemo.INSTANCE.controller().reqContractDetails( optContract, symbolPanel); ?} ? ?private class ChainPanel extends NewTabPanel implements IContractDetailsHandler, ActionListener? { ??ChainModel m_putsModel = new ChainModel(); ??JTable m_putsTable = new JTable( m_putsModel); ??ChainModel m_callsModel = new ChainModel(); ??JTable m_callsTable = new JTable( m_callsModel); ??Timer m_timer = new Timer( 800, this); ???? JLabel m_labUnderPrice = new JLabel(); ???? TopMktDataAdapter m_stockListener = new TopMktDataAdapter() { ??????????? @Override public void tickPrice(TickType tickType, double price, int canAutoExecute) { ??????????????? if (tickType == TickType.LAST) { ??????????????????? m_labUnderPrice.setText( "" + price); ??????????????? } ??????????? } ??????? }; ???? ??ChainPanel() { ???JScrollPane scrollPuts = new JScrollPane( m_putsTable); ???scrollPuts.setBorder( new TitledBorder( "Puts")); ???JScrollPane scrollCalls = new JScrollPane( m_callsTable); ???scrollCalls.setBorder( new TitledBorder( "Calls")); ???VerticalPanel underPanel = new VerticalPanel(); ??????????? underPanel.add( "Underlying price", m_labUnderPrice); ??????????? ???JPanel mainPanel = new JPanel(); ???mainPanel.setLayout( new BoxLayout( mainPanel, BoxLayout.X_AXIS)); ???mainPanel.add( scrollCalls); ??????????? mainPanel.add( scrollPuts); ??? ???setLayout( new BorderLayout() ); ???add( underPanel, BorderLayout.NORTH); ???add( mainPanel); ??? ???m_timer.start(); ??? ???ApiDemo.INSTANCE.controller().reqTopMktData( m_underContract, "", false, m_stockListener); ??} ?? ??/** Called when the tab is first visited. */ ??????? @Override public void activated() { ??????? } ??? ?/** Called when the tab is closed by clicking the X. */ ??????? @Override public void closed() { ??????????? ApiDemo.INSTANCE.controller().cancelTopMktData( m_stockListener); ??????????? m_putsModel.desubscribe(); ??????????? m_callsModel.desubscribe(); ??????????? m_timer.stop(); ??????? } ??@Override public void actionPerformed(ActionEvent e) { ???m_putsModel.fireTableDataChanged(); ???m_callsModel.fireTableDataChanged(); ??} ?? ??@Override public void contractDetails(ArrayList<ContractDetails> list) { ???for (ContractDetails data : list) { ????Contract contract = data.contract(); ???? ????if (contract.right() == Right.Put) { ?????m_putsModel.addRow( contract, m_snapshot.isSelected() ); ????} ????else { ?????m_callsModel.addRow( contract, m_snapshot.isSelected() ); ????} ???} ???m_putsModel.sort(); ???m_callsModel.sort(); ??} ?? ??private class ChainModel extends AbstractTableModel { ???Comparator<ChainRow> c = new Comparator<ChainRow>() { ????@Override public int compare(ChainRow o1, ChainRow o2) { ?????int rc = o1.m_c.lastTradeDateOrContractMonth().compareTo( o2.m_c.lastTradeDateOrContractMonth()); ?????if (rc == 0) { ??????if (o1.m_c.strike() < o2.m_c.strike()) { ???????rc = -1; ??????} ??????if (o1.m_c.strike() > o2.m_c.strike()) { ???????rc = 1; ??????} ?????} ?????return rc; ????} ???}; ??? ???ArrayList<ChainRow> m_list = new ArrayList<ChainRow>(); ??? ??????????? public void desubscribe() { ??????????????? for (ChainRow row : m_list) { ??????????????????? ApiDemo.INSTANCE.controller().cancelOptionMktData( row); ??????????????? } ??????????? } ??? ???@Override public int getRowCount() { ????return m_list.size(); ???} ???public void sort() { ????Collections.sort( m_list, c); ????fireTableDataChanged(); ???} ???public void addRow(Contract contract, boolean snapshot) { ????ChainRow row = new ChainRow( contract); ????m_list.add( row); ???? ????ApiDemo.INSTANCE.controller().reqOptionMktData(contract, "", snapshot, row); ???? ????if (snapshot) { ?????Util.sleep( 11); // try to avoid pacing violation at TWS ????} ???} ???@Override public int getColumnCount() { ????return m_snapshot.isSelected() ? 10 : 9; ???} ??? ???@Override public String getColumnName(int col) { ????switch( col) { ?????case 0: return "Last trade date"; ?????case 1: return "Strike"; ?????case 2: return "Bid"; ?????case 3: return "Ask"; ?????case 4: return "Imp Vol"; ?????case 5: return "Delta"; ?????case 6: return "Gamma"; ?????case 7: return "Vega"; ?????case 8: return "Theta"; ?????default: return null; ????} ???} ???@Override public Object getValueAt(int rowIn, int col) { ????ChainRow row = m_list.get( rowIn); ????switch( col) { ?????case 0: return row.m_c.lastTradeDateOrContractMonth(); ?????case 1: return row.m_c.strike(); ?????case 2: return fmtNz( row.m_bid); ?????case 3: return fmtNz( row.m_ask); ?????case 4: return fmtPct( row.m_impVol); ?????case 5: return fmtNz( row.m_delta); ?????case 6: return fmtNz( row.m_gamma); ?????case 7: return fmtNz( row.m_vega); ?????case 8: return fmtNz( row.m_theta); ?????case 9: return row.m_done ? "*" : null; ?????default: return null; ????} ???} ? ???private class ChainRow extends TopMktDataAdapter implements IOptHandler { ????Contract m_c; ????double m_bid; ????double m_ask; ????double m_impVol; ????double m_delta; ????double m_gamma; ????double m_vega; ????double m_theta; ????boolean m_done; ?? ????public ChainRow(Contract contract) { ?????m_c = contract; ????} ?? ????@Override public void tickPrice(TickType tickType, double price, int canAutoExecute) { ?????switch( tickType) { ??????case BID: ???????m_bid = price; ???????break; ??????case ASK: ???????m_ask = price; ???????break; ????????????????? default: break; ?????} ????} ?? ????@Override public void tickOptionComputation( TickType tickType, double impVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) { ?????if (tickType == TickType.MODEL_OPTION) { ??????m_impVol = impVol; ??????m_delta = delta; ??????m_gamma = gamma; ??????m_vega = vega; ??????m_theta = theta; ?????} ????} ???? ????@Override public void tickSnapshotEnd() { ?????m_done = true; ????} ???} ??} ?} } |
I'm not sure I understand what you're doing.?
It only takes one request to get an entire chain.? The limitation is
on request, not responses.
toggle quoted message
Show quoted text
[rwk] At 07:30 PM 12/18/2015, you wrote: I have been looking at the IB sample application. From what I can see it has a lot of the functions needed for the option strategies I am working on. One problem it has is when requesting options chain data, the api loses connection due to exceeding the request per second limit of 50. Does anyone have a solution? |
Yes, but the request is too big to do all at once. IB has a throttle on how many symbols can be requested in a single request. I assume he is using the Java client IB provides and had the same problem. Disconnects if you request the entire chain even though IB built the client. I had to request one expiration then loop to the next but this is clunky as the expirations are not always Fridays. He could manually enter each expiration date in a structure and iterate through that I suppose.? PA
|
¿ªÔÆÌåÓýare you willing to finish my code
this is what i do in VB ?ListBox1.Items.Add("getting chain") ??????? contractend = 0 ??????? AxTws1.reqContractDetailsEx(1, contract) ??????? While contractend = 0 ??????????? Application.DoEvents() ??????? End While ??????? ListBox1.Items.Add("chain completed") ??????? ListBox1.Items.Add("getting market data for " & fullarray.Count.ToString & " options") ??????? fullarray.Sort() ??????? TextBox1.Text.ToUpper() ??????? rnumber = 0 ??????? tickend = 0 ??????? While rnumber < fullarray.Count ??????????? Application.DoEvents() ??????????? marktime = GetTickCount ??????????? While GetTickCount < marktime + 3 ??????????????? Application.DoEvents() ??????????? End While ??????????? ss = fullarray(rnumber).split(",") ??????????? 'execute the? req market data events ??????????? AxTws1.reqMktData(Convert.ToInt32(ss(3)), TextBox1.Text, "OPT", ss(0), Convert.ToDouble(ss(1)), ss(2), "", "SMART", "", "USD", "", 2)????? '0 =streaming 1=snapshot" ??????????? Application.DoEvents() ??????????? rnumber += 1 ??????? End While ??????? While (tickend < fullarray.Count) ??????????? Application.DoEvents() ??????? End While On 12/18/2015 10:15 PM, Patrick Actor patrick.actor@... [TWSAPI] wrote:
|
On 12/19/15, 4:22 PM, "todell826@... [TWSAPI]"
<TWSAPI@...> wrote: Can the options chain be limited toNo. 1- you only have the choice to specify specific dates (or months, by omitting the two day digits, perhaps years--haven't tried) or not 2- you only have the option to specify a single strike price or not You will have to request more than you need, and filter the result accordingly. In that sense, of course you can do it, and as efficiently as you like. You can't stop the full data from coming in on the socket however. You could specify one expiration at a time, or one month at a time, to limit the throughput, if that actually mattered, which probably it will not. -Kurt |
Hello All
Kurt wrote "You can't stop the
full data from coming in on the socket
Bear with me, I am missing the answer to the getting disconnected problem. If there is a better solution out there than the IB java test client please let me know. This should be the easy stuff. It is really bogging down the fun work.
Here is what we need to make a trade decision. For a group of underlying symbols:
SPYSupport = 208.75 SPYResistance = 210.55 AAPLSupport = 100.00 AAPLResistance = 105.00 SPYPrice = Current price AAPLPrice = Current price And so on_____. //Support and resistance?levels are adjusted daily before market open. ?????? if?SPYPrice < SPYSupport an opportunity for a BullPutSpread exist. SPYBullPutSpread = true ?????? If SPYPrice > SPYResistance an opportunity for a BearCallSpread exist. BearCallSpread = true
dte?= A // These are theta positive strategies. Time decay starts to accelerate at 45days. ShortDeltaBull = .20 // This correlates to an 80% chance of success. Adjust these levels for your risk tolerance. The algo could also adjust these levels based on current 52 week IV percentile. ShortDeltaBear = .80 // Same 80% chance of success. spread = D // The difference in short and long strike prices. Thinking further, each underlying will need its own spread variable (SPYSpread = X, AAPLSpread = Y) The formula for a SPYBullPutSpread short contract is: if SPYBullPutSpread = true Search the options chain for deltas < shortDeltaBull Filter the resulting contracts by variable dte The results are the short side contract candidates.
Again using the SPYBullPutSpread strategy, We take the short contract candidates strike price from above and subtract variable SPYSpread. The result is the long side contract. The two contracts are matched somehow into a combo trade. The credit on this combo is now calculated using the bid (sell the short) price for the short minus the ask (buy the long) on the long (bidPriceShort ¨C askPriceLong). The resulting credit for this combo is now checked for sufficient ROI. Currently I use ROI => DTE. For example, 10 contracts with a $1 spread requires $1000 buying power effect. A $230 credit = 23% ROI. The DTE will need to be 23 days or less. When the smoke clears from all the above, We have a credit spread to trade!!! The next step is to execute the trade. Protections will need to be built into the framework such as: Excluding days the markets?are closed.? FOMC meetings and market moving news days. Earnings. I generally do not enter trades in the first hour on SPY. Weekly SPY trades are not held over night. This list will continue to build. As you can see, I can explain the strategy. Writing code to make it dance is along ways away for me. Any help will definitely be rewarding! I will explain the rest of the strategy when we get the entry portion completed. Terry ? |