Option Chains

The option chain for a given security can be returned using the function reqContractDetails. If an option contract is incompletely defined (for instance with the strike undefined) and used as an argument to LYNXApi.EClient.reqContractDetails , a list of all matching option contracts will be returned.

The example below shows an "incomplete" option LYNXApi.Contract with no last trading day, strike nor multiplier defined. In most cases using such a contract would result into a contract ambiguity error since there are lots of instruments matching the same description. LYNXApi.EClient.reqContractDetails will instead use it to obtain the whole option chain from the TWS.

** Python **

contract = Contract()
contract.symbol = "FISV"
contract.secType = "OPT"
contract.exchange = "SMART"
contract.currency = "USD"

self.reqContractDetails(210, ContractSamples.OptionForQuery())
self.reqContractDetails(211, ContractSamples.EurGbpFx())
self.reqContractDetails(212, ContractSamples.Bond())
self.reqContractDetails(213, ContractSamples.FuturesOnOptions())
self.reqContractDetails(214, ContractSamples.SimpleFuture())

** Java **

Contract contract = new Contract();

client.reqContractDetails(210, ContractSamples.OptionForQuery());
client.reqContractDetails(211, ContractSamples.EurGbpFx());
client.reqContractDetails(212, ContractSamples.Bond());
client.reqContractDetails(213, ContractSamples.FuturesOnOptions());
client.reqContractDetails(214, ContractSamples.SimpleFuture());

One limitation of this technique is that the return of option chains will be throttled and take a longer time the more ambiguous the contract definition. Starting in version 9.72 of the API, a new function LYNXApi.EClient.reqSecDefOptParams is introduced that does not have the throttling limitation.

  • It is not recommended to use reqContractDetails to receive complete option chains on an underlying, e.g. all combinations of strikes/rights/expiries.
  • For very large option chains returned from reqContractDetails, unchecking the setting in TWS Global Configuration at API -> Settings -> "Expose entire trading schedule to the API" will decrease the amount of data returned per option and help to return the contract list more quickly.

** Python **

self.reqSecDefOptParams(0, "LYNXM", "", "STK", 8314)

def securityDefinitionOptionParameter(self, reqId: int, exchange: str,underlyingConId: int, tradingClass: str, multiplier: str,expirations: SetOfString, strikes: SetOfFloat):

    super().securityDefinitionOptionParameter(reqId, exchange,
                                              multiplier, expirations,

          "ReqId:", reqId, "Exchange:", exchange, "Underlying conId:",
          underlyingConId, "TradingClass:", tradingClass,
          "Multiplier:", multiplier,"Expirations:", expirations,
          "Strikes:", str(strikes))

** Java **

client.reqSecDefOptParams(0, "LYNXM", "", "STK", 8314);

public void securityDefinitionOptionalParameter(int reqId, String exchange,
    int underlyingConId, String tradingClass, String multiplier,
    Set<String> expirations, Set<Double> strikes) {
System.out.println("Security Definition Optional Parameter. Request: "+reqId+", Trading Class: "+tradingClass+", Multiplier: "+multiplier+" \n");

LYNXApi.EClient.reqSecDefOptParams returns a list of expiries and a list of strike prices. In some cases it is possible there are combinations of strike and expiry that would not give a valid option contract.

The API can return the greek values in real time for options, as well as calculate the implied volatility given a hypothetical price or calculate the hypothetical price given an implied volatility.

Exercising options

Options are exercised or lapsed from the API with the function LYNXApi.EClient.exerciseOptions

  • Option exercise will appear with order status side = "BUY" and limit price of 0, but only at the time the request is made
  • Option exercise can be distinguished by price = 0

** Python **

self.exerciseOptions(5003, ContractSamples.OptionWithTradingClass(), 1, 1, self.account, 1)

** Java **

//** Exercising options ***
client.exerciseOptions(5003, ContractSamples.OptionWithTradingClass(), 1, 1, "", 1);

Option Greeks

The option greek values- delta, gamma, theta, vega- are returned by default following a reqMktData() request for the option. See Available Tick Types

Tick types "Bid Option Computation" (#10), "Ask Option Computation" (#11), "Last Option Computation" (#12), and "Model Option Computation" (#13) return all Greeks (delta, gamma, vega, theta), the underlying price and the stock and option reference price when requested.

MODEL_OPTION_COMPUTATION also returns model implied volatility.

[!NOTE] In order to receive live greek values it is necessary to have market data subscriptions for both the option and the underlying contract.

** Python **

# Requesting data for an option contract will return the greek values
self.reqMktData(1013, ContractSamples.OptionWithLocalSymbol(), "", False, False, [])
self.reqMktData(1014, ContractSamples.FuturesOnOptions(), "", False, False, []);

** Java **

//Requesting data for an option contract will return the greek values
client.reqMktData(1002, ContractSamples.OptionWithLocalSymbol(), "", false, false, null);

The Implied Volatility of an underlying based on its current option prices is returned in tick 24. See Available Tick Types

The LYNX 30-day volatility is the at-market volatility estimated for a maturity thirty calendar days forward of the current trading day, and is based on option prices from two consecutive expiration months.

Calculating option prices and historical volatility

The implied volatility for an option given its price and the price of the underlying can be calculated with the function LYNXApi.EClient.calculateImpliedVolatility

** Python **

self.calculateImpliedVolatility(5001, ContractSamples.OptionAtBOX(), 5, 85, [])

** Java **

client.calculateImpliedVolatility(5001, ContractSamples.OptionAtBOX(), 5, 85, null);

Alternatively, given the price of the underlying and an implied volatility it is possible to calculate the option price using the function LYNXApi.EClient.calculateOptionPrice

** Python **

self.calculateOptionPrice(5002, ContractSamples.OptionAtBOX(), 0.22, 85, [])

** Java **

client.calculateOptionPrice(5002, ContractSamples.OptionAtBOX(), 0.22, 85, null);

After the request, the option specific information will be delivered via the LYNXApi.EWrapper.tickOptionComputation method:

** Python **

class TestWrapper(wrapper.EWrapper):

def tickOptionComputation(self, reqId: TickerId, tickType: TickType,impliedVol: float, delta: float, optPrice: float, pvDividend: float,gamma: float, vega: float, theta: float, undPrice: float):

    super().tickOptionComputation(reqId, tickType, impliedVol, delta,
                                  optPrice, pvDividend, gamma, vega,
                                  theta, undPrice)

    print("TickOptionComputation. TickerId:", reqId, "TickType:",
          tickType,"ImpliedVolatility:", impliedVol, "Delta:", delta,
          "OptionPrice:",optPrice, "pvDividend:", pvDividend, "Gamma:
          ", gamma, "Vega:", vega," Theta:", theta,"UnderlyingPrice:",

** Java **

public class EWrapperImpl implements EWrapper {
    public void tickOptionComputation(int tickerId, int field,
            double impliedVol, double delta, double optPrice,
            double pvDividend, double gamma, double vega, double theta,
            double undPrice) {
        System.out.println("TickOptionComputation. TickerId: "+tickerId+", field: "+field+", ImpliedVolatility: "+impliedVol+", Delta: "+delta
                +", OptionPrice: "+optPrice+", pvDividend: "+pvDividend+", Gamma: "+gamma+", Vega: "+vega+", Theta: "+theta+", UnderlyingPrice: "+undPrice);