{"id":205882,"date":"2024-05-01T15:26:54","date_gmt":"2024-05-01T19:26:54","guid":{"rendered":"https:\/\/ibkrcampus.com\/?p=205882"},"modified":"2025-08-08T12:11:50","modified_gmt":"2025-08-08T16:11:50","slug":"handling-options-chains","status":"publish","type":"post","link":"https:\/\/www.interactivebrokers.com\/campus\/ibkr-quant-news\/handling-options-chains\/","title":{"rendered":"Handling Options Chains"},"content":{"rendered":"\n<p>One of the most ubiquitous questions received for the Interactive Brokers API team is the process for users to receive options chain data through the WebAPI. And while we have received some positive feedback over our existing <a href=\"\/campus\/ibkr-api-page\/cpapi-v1\/#option-chain\">Options Chains Documentation<\/a>, we felt there was room for additional guidance on how a user could implement this system. Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.<\/p>\n\n\n\n<p>As users may be aware already, the Client Portal API requires that users query the \/iserver\/secdef\/search, \/iserver\/secdef\/strikes, and \/iserver\/secdef\/info sequentially, with no means around this process. However, the implementation here will focus on building out our contract libraries pre-emptively before moving into the daily trading. As a result, the expectation for this script would be to run it once in the morning at the start of a month rather than intra-day.<\/p>\n\n\n\n<p>While I am using Python in this scenario, these steps can be translated to most other programming languages given the RESTful request structure. For the Python libraries used in this script, I\u2019ll be referencing the <a href=\"\/campus\/ibkr-api-page\/cpapi-v1\/#endpoints\">external libraries<\/a> documented in our Endpoints section, focusing primarily on \u201crequests\u201d, \u201curllib3\u201d, and \u201ccsv\u201d from the python standard library. Because I\u2019m working in the client portal gateway, I will also be passing verify=False in my requests, though this may be skipped.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import requests\nimport urllib3\nimport csv\n# Ignore insecure error messages\nurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)<\/pre>\n\n\n\n<p>After establishing our imports, I\u2019ll define our secdefSearch method to create our initial search request and handle the returned data. We can set the arguments for symbol and listingExchange, so we can filter the exact contract we\u2019re looking for without having to sort the data using the primary listing exchange.<\/p>\n\n\n\n<p>Moving into our method, I\u2019ll define our \u201curl\u201d variable as f\u201dhttps:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/search?symbol={symbol}\u201d. With a URL set, we can make our request, search_request, set to \u2018requests.get(url=url, verify=False)\u2019. If you print search_request.json() directly, you\u2019ll find an array of several contracts.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def secdefSearch(symbol, listingExchange):\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/search?symbol={symbol}'\n  search_request = requests.get(url=url, verify=False)<\/pre>\n\n\n\n<p>We don\u2019t necessarily care about all of these contracts, so now we can look to filter it using our listingExchange argument from before. To do this, I\u2019ll loop through each <em>contract<\/em> in our json, then if any of the <em>contract<\/em> \u201cdescription\u201d values match our listingExchange, we\u2019ll have found the appropriate contract. Here, I can set our underConid variable to the <em>contract<\/em> \u201cconid\u201d field.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  for contract in search_request.json():\n    if contract[\"description\"] == listingExchange:\n      underConid = contract[\"conid\"]<\/pre>\n\n\n\n<p>While we are still in the <em>contract<\/em> we\u2019re looking for, we can pull out the expiration month\u2019s we\u2019re looking for. I\u2019ll do this by iterating through the <em>secType<\/em> items in the <em>contract<\/em> \u201csections\u201d section. Here, if I find a <em>secType<\/em> \u201csecType\u201d that is an \u201cOPT\u201d, we\u2019ll have our options contract months. I will set our \u201cmonths\u201d variable to the <em>secType<\/em> \u201cmonths\u201d section, and split the value on the semicolons.&nbsp; Now we can return our underConid and months variables.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">      for secType in contract[\"sections\"]:\n        if secType[\"secType\"] == \"OPT\":\n          months = secType[\"months\"].split(';')\n  return underConid,months<\/pre>\n\n\n\n<p>With our first method settled, we can create our name-main idiom and make our initial call to the secdefSearch method from there. At the bottom of the file, we can build out the standard \u2018if __name__ == &#8220;__main__&#8221;:\u2019, then set matching variables <em>underConid<\/em> and <em>months<\/em> equal to the secdefSearch method. I will pass in \u201cAAPL\u201d and \u201cNASDAQ\u201d as my arguments, but you\u2019re welcome to query whichever options contract you\u2019d like.<\/p>\n\n\n\n<p>I will also be creating a new variable in our idiom, <em>month<\/em> which I will set to the 0 value of our returned <em>months<\/em> method. You\u2019re welcome to query whichever contracts you\u2019d like; however, I typically prefer to focus on the front month, so using the first indexed item will always bring up the front month.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">if __name__ == \"__main__\":\n  underConid,months = secdefSearch(\"AAPL\", \"NASDAQ\")\n  month = months[0]<\/pre>\n\n\n\n<p>Before jumping into the strikes endpoint, I\u2019d like to calculate the approximate price of the instrument to find what is in-the-money. To do this, I\u2019ll create a snapshotData method, taking an argument for our <em>underConid<\/em> variable. Similar to our last method, I\u2019ll create a \u2018url\u2019 variable and set it to \u201cf&#8217;https:\/\/localhost:5001\/v1\/api\/iserver\/marketdata\/snapshot?conids={underConid}&amp;fields=31&#8217;\u201d. This is the market data snapshot endpoint that can be used to retrieve the last price {31} for the instrument. I can then create two requests to the same url, using the format of request.get(url=url,verify=False) just like before. We\u2019re sending the request twice due to the mandatory preflight request for the endpoint. I will set my second request to the <em>snapshot<\/em> variable, to pull from it later. To conclude the method, I\u2019ll simply return snapshot.json()[0][\u201c31\u201d] to return the Last price received.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def snapshotData(underConid):\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/marketdata\/snapshot?conids={underConid}&amp;fields=31'\n  requests.get(url=url, verify=False)\n  snapshot = requests.get(url=url, verify=False)\n  return snapshot.json()[0][\"31\"]<\/pre>\n\n\n\n<p>We can move on and define the secdefStrikes method, passing our <em>underConid<\/em> and <em>month<\/em> variables. Within our method, I\u2019ll create the variable, snapshot, and set it to the float of our snapshotData\u2019s response. We\u2019ll be using the value for a calculation later, so we can\u2019t use it as the String value we retrieved it as.&nbsp; I will also create a list named <em>itmStrikes<\/em>, which we\u2019ll leave empty but refer to later. And as usual, I\u2019ll create a <em>url<\/em> variable set to the \/iserver\/secdef\/strikes endpoint. And while I\u2019ll be passing the <em>underConid<\/em> and <em>month<\/em> variables accordingly, I will set the <em>secType<\/em> param to \u201cOPT\u201d, as I have no interest in retrieving Futures Options. However, if you trade Futures Options, or a mix of the two, you could always set the value to a variable all the same. Then, we can set a strike_request variable equal to the request.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def secdefStrikes(underConid,month):\n  snapshot = float(snapshotData(underConid))\n  itmStrikes = []\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/strikes?conid={underConid}&amp;secType=OPT&amp;month={month}'\n  strike_request = requests.get(url=url, verify=False)<\/pre>\n\n\n\n<p>With the request out of the way, we can start working with the response. I\u2019ll begin with a strikes variable set to the \u201cput\u201d key. In most scenarios, the list of Put strikes will match those of the Calls; however, this is not always the case. Users interested in trading both rights or Calls specifically can adjust their code accordingly. Now we can begin to iterate through each <em>strike<\/em> in <em>strikes<\/em>. My condition for contracts in the money will be those within $20 of our contract, and so I will make an \u2018if\u2019 statement to retrieve all strikes within $10 under our snapshot price, and everything $10 over our snapshot price. Developers may alternatively implement a 5% variable rather than a fixed value to approach a similar result. Now we\u2019ll start to append our results to the <em>itmStrikes<\/em> list we had created before, and then return the list once our loop has finished.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">strikes = strike_request.json()[\"put\"]\n  for strike in strikes:\n    if strike>snapshot-10 and strike&lt;snapshot+10:\n      itmStrikes.append(strike)\n  return itmStrikes<\/pre>\n\n\n\n<p>Now we can move back to our Name-Main idiom before writing our last methods. After setting our <em>month<\/em> variable, I will set a new itmStrikes variable equal to a call to our secdefStrikes method with our <em>underConid<\/em> and <em>month<\/em> variables. Next, we can create a dictionary, contractDict. Then, we\u2019ll iterate through each <em>strike<\/em> in itmStrikes. Here, we can set the <em>strike <\/em>as the key of contractDict, and set it equivalent to the response of a new secdefInfo method we\u2019re about to write, taking the <em>underConid, month, <\/em>and <em>strike<\/em> variables we\u2019ve retrieved up to this point.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">itmStrikes = secdefStrikes(underConid,month)\n  contractDict = {}\n  for strike in itmStrikes:\n    contractDict[strike] = secdefInfo(underConid,month,strike)<\/pre>\n\n\n\n<p>At this point, we can write out the secdefInfo method, taking the three arguments mentioned before, <em>underConid, month, <\/em>and <em>strike<\/em>. We\u2019ll create another url variable set to the \/iserver\/secdef\/info endpoint which takes all of our arguments as parameters, and the additional <em>secType<\/em> and <em>right<\/em> parameter, which we\u2019ll preset to \u201cOPT\u201d and \u201cP\u201d respectively. Then we can follow this with setting the info_request variable to our request.get(url=url, verify=False) call once again.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def secdefInfo(conid, month, strike):\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/info?conid={conid}&amp;month={month}&amp;strike={strike}&amp;secType=OPT&amp;right=P'\n  info_request = requests.get(url=url, verify=False)<\/pre>\n\n\n\n<p>Before handling the response, I will first create an empty list, <em>contracts<\/em>. Now, the response to this endpoint will produce several different contracts as there are multiple expiries within the month. Given my scenario trades each weekly contract, I can retrieve each May contract. However, you are welcome to filter by a given MaturityDate, or other field that you feel is relevant. With my scope settled, I can iterate through our info_request.json() response using individual <em>contract<\/em> variables for each. Within the for-loop, we can assign the <em>contract, symbol, strike, <\/em>and <em>maturityDate<\/em> values to a <em>contractDetails<\/em> dictionary definition. I\u2019ll then append this value to our contracts list. Once the loop has finished, I\u2019ll then return the full <em>contracts<\/em> list.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">for contract in info_request.json():\n    contractDetails = {\"conid\": contract[\"conid\"], \n                       \"symbol\": contract[\"symbol\"],\n                       \"strike\": contract[\"strike\"],\n                       \"maturityDate\": contract[\"maturityDate\"]\n                      }\n    contracts.append(contractDetails)\n  return contracts<\/pre>\n\n\n\n<p>With the larger script completed, we could simply print our resulting contractDict, or pass it around our trading session if we chose to run this every morning possible. However, as we mentioned at the start of the article, the intention of this is to elaborate on how to use these requests in the long term. We can look to add our dictionary into a CSV file for future use. I would encourage readers to extrapolate on this idea potentially with a larger internal database structure, or those empowered by Excel may choose to connect with xlwings as we discussed in our <a href=\"\/campus\/ibkr-quant-news\/connecting-python-to-excel\/\">prior lesson<\/a>. We\u2019ll conclude our idiom with a call to a new writeResult method sending our contractDict variable as our argument.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">writeResult(contractDict)<\/pre>\n\n\n\n<p>Within our writeResult method, we can start with our header values, that we had taken from the \/info endpoint: <em>conid, symbol, strike, <\/em>and<em> maturityDate<\/em>. Then, I can write out a filePath to our current directory into a file named \u201c.\/MayContracts.csv\u201d.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def writeResult(contractDict):\n  headers = [\"conid\", \"symbol\", \"strike\", \"maturityDate\"]\n  filePath = \".\/MayContracts.csv\"<\/pre>\n\n\n\n<p>Now we can create some general structures using the csv library. We\u2019ll start with a contract_csv_file variable, set to open(filePath, \u2018w\u2019, newline=\u2019\u2019). This way we can reference a file, defined by our filePath variable that we\u2019ll be writing to. Then, we can set a contract_writer variable exual to the csv.DictWriter object class. We\u2019ll pass in our contract_csv_file as the \u201cf\u201d variable, and set the fieldnames variable equal to our headers. Then, I\u2019d like to write out our headers using the DictWriter.writeheader method.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">contract_csv_file = open(filePath, 'w', newline='')\n  contract_writer = csv.DictWriter(f=contract_csv_file, fieldnames=headers)\n  contract_writer.writeheader()<\/pre>\n\n\n\n<p>With our structure set, let\u2019s iterate through each strikeGroup in our contractDict dictionary. Nesting further down, we can then iterate through each contractDetail inside the contractDict\u2019s strikeGroup. This will allow us to write out the contractDetails with the contract_writer. We can conclude the method by closing out the file once we have finished iterating through our dictionary. I will add a simple print to indicate \u201cJob\u2019s done.\u201d, as none of the other requests handled so far have actually been displayed to the user.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">for strikeGroup in contractDict:\n    for contractDetails in contractDict[strikeGroup]:\n      contract_writer.writerow(contractDetails)\n  contract_csv_file.close()\n  print(\"Job's done.\")<\/pre>\n\n\n\n<p>Thus the file is settled correctly. Assuming everything was saved correctly, we should now see the MayContracts.csv file stored in the same directory as where our python was executed. Opening the file, we\u2019ll find that we now have a column displaying each conid, symbol, strike, and expiration date. Going forward, you could conversely utilize the csv.DictReader() class to pull out these same values as necessary whenever needed, and we can look to use them throughout the month as our trading persists.&nbsp;<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import requests\nimport urllib3\n\nimport csv\n\n# Ignore insecure error messages\nurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n\ndef secdefSearch(symbol, listingExchange):\n\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/search?symbol={symbol}'\n\n  search_request = requests.get(url=url, verify=False)\n  for contract in search_request.json():\n    if contract[\"description\"] == listingExchange:\n      underConid = contract[\"conid\"]\n\n      for secType in contract[\"sections\"]:\n         if secType[\"secType\"] == \"OPT\":\n            months = secType[\"months\"].split(';')\n\n  return underConid,months\n\ndef secdefStrikes(underConid,month):\n\n  snapshot = float(snapshotData(underConid))\n  itmStrikes = []\n\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/strikes?conid={underConid}&amp;secType=OPT&amp;month={month}'\n\n  strike_request = requests.get(url=url, verify=False)\n\n  strikes = strike_request.json()[\"put\"]\n  for strike in strikes:\n    if strike>snapshot-10 and strike&lt;snapshot+10:\n      itmStrikes.append(strike)\n  return itmStrikes\n\ndef secdefInfo(conid, month, strike):\n\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/secdef\/info?conid={conid}&amp;month={month}&amp;strike={strike}&amp;secType=OPT&amp;right=P'\n\n  info_request = requests.get(url=url, verify=False)\n\n  contracts = []\n\n  for contract in info_request.json():\n    contractDetails = {\"conid\": contract[\"conid\"], \n                       \"symbol\": contract[\"symbol\"],\n                       \"strike\": contract[\"strike\"],\n                       \"maturityDate\": contract[\"maturityDate\"]\n                      }\n    contracts.append(contractDetails)\n  return contracts\n\ndef snapshotData(underConid):\n  url = f'https:\/\/localhost:5001\/v1\/api\/iserver\/marketdata\/snapshot?conids={underConid}&amp;fields=31'\n  requests.get(url=url, verify=False)\n  snapshot = requests.get(url=url, verify=False)\n  return snapshot.json()[0][\"31\"]\n\ndef writeResult(contractDict):\n  headers = [\"conid\", \"symbol\", \"strike\", \"maturityDate\"]\n  filePath = \".\/MayContracts.csv\"\n  contract_csv_file = open(filePath, 'w', newline='')\n  contract_writer = csv.DictWriter(f=contract_csv_file, fieldnames=headers)\n  contract_writer.writeheader()\n  for strikeGroup in contractDict:\n    for contractDetails in contractDict[strikeGroup]:\n      contract_writer.writerow(contractDetails)\n  contract_csv_file.close()\n  print(\"Job's done.\")\n\nif __name__ == \"__main__\":\n  # I'm looking for the U.S. Apple Incorporated company listed on NASDAQ\n  underConid,months = secdefSearch(\"AAPL\", \"NASDAQ\")\n  \n  # I only want the front month. \n  # Users could always grab all months, or pull out a specific value, but sending the 0 value always gives me the first available contract.\n  month = months[0]\n\n  # We'll be calling our Strikes endpoint to pull in the money strike prices rather than all strikes.\n  itmStrikes = secdefStrikes(underConid,month)\n\n  # We can then pass those strikes to the \/info endpoint, and retrieve all the contract details we need.\n  contractDict = {}\n  for strike in itmStrikes:\n    contractDict[strike] = secdefInfo(underConid,month,strike)\n\n  writeResult(contractDict)<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.<\/p>\n","protected":false},"author":1173,"featured_media":205915,"comment_status":"open","ping_status":"closed","sticky":true,"template":"","format":"standard","meta":{"_acf_changed":true,"footnotes":""},"categories":[339,340,343,349,338,341,9563,9763],"tags":[851,575,17063,17062],"contributors-categories":[13576],"class_list":{"0":"post-205882","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-data-science","8":"category-api-development","9":"category-programing-languages","10":"category-python-development","11":"category-ibkr-quant-news","12":"category-quant-development","13":"category-options-quant","14":"category-rest-development","15":"tag-algo-trading","16":"tag-ibkr-api","17":"tag-restful-api","18":"tag-webapi","19":"contributors-categories-interactive-brokers"},"pp_statuses_selecting_workflow":false,"pp_workflow_action":"current","pp_status_selection":"publish","acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Handling Options Chains | IBKR Quant<\/title>\n<meta name=\"description\" content=\"Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.interactivebrokers.com\/campus\/wp-json\/wp\/v2\/posts\/205882\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Handling Options Chains\" \/>\n<meta property=\"og:description\" content=\"Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.interactivebrokers.com\/campus\/ibkr-quant-news\/handling-options-chains\/\" \/>\n<meta property=\"og:site_name\" content=\"IBKR Campus US\" \/>\n<meta property=\"article:published_time\" content=\"2024-05-01T19:26:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-08-08T16:11:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"563\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrew Wise\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrew Wise\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\n\t    \"@context\": \"https:\\\/\\\/schema.org\",\n\t    \"@graph\": [\n\t        {\n\t            \"@type\": \"NewsArticle\",\n\t            \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/#article\",\n\t            \"isPartOf\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/\"\n\t            },\n\t            \"author\": {\n\t                \"name\": \"Andrew Wise\",\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#\\\/schema\\\/person\\\/68e347fb855adceb4ccfbfa350f5b783\"\n\t            },\n\t            \"headline\": \"Handling Options Chains\",\n\t            \"datePublished\": \"2024-05-01T19:26:54+00:00\",\n\t            \"dateModified\": \"2025-08-08T16:11:50+00:00\",\n\t            \"mainEntityOfPage\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/\"\n\t            },\n\t            \"wordCount\": 1805,\n\t            \"commentCount\": 5,\n\t            \"publisher\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#organization\"\n\t            },\n\t            \"image\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/#primaryimage\"\n\t            },\n\t            \"thumbnailUrl\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2024\\\/05\\\/api-cubes.jpg\",\n\t            \"keywords\": [\n\t                \"Algo Trading\",\n\t                \"IBKR API\",\n\t                \"RESTful API\",\n\t                \"WebAPI\"\n\t            ],\n\t            \"articleSection\": [\n\t                \"Data Science\",\n\t                \"IBKR API Development\",\n\t                \"Programming Languages\",\n\t                \"Python Development\",\n\t                \"Quant\",\n\t                \"Quant Development\",\n\t                \"Quant Options\",\n\t                \"REST Development\"\n\t            ],\n\t            \"inLanguage\": \"en-US\",\n\t            \"potentialAction\": [\n\t                {\n\t                    \"@type\": \"CommentAction\",\n\t                    \"name\": \"Comment\",\n\t                    \"target\": [\n\t                        \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/#respond\"\n\t                    ]\n\t                }\n\t            ]\n\t        },\n\t        {\n\t            \"@type\": \"WebPage\",\n\t            \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/\",\n\t            \"url\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/\",\n\t            \"name\": \"Handling Options Chains | IBKR Campus US\",\n\t            \"isPartOf\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#website\"\n\t            },\n\t            \"primaryImageOfPage\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/#primaryimage\"\n\t            },\n\t            \"image\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/#primaryimage\"\n\t            },\n\t            \"thumbnailUrl\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2024\\\/05\\\/api-cubes.jpg\",\n\t            \"datePublished\": \"2024-05-01T19:26:54+00:00\",\n\t            \"dateModified\": \"2025-08-08T16:11:50+00:00\",\n\t            \"description\": \"Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.\",\n\t            \"inLanguage\": \"en-US\",\n\t            \"potentialAction\": [\n\t                {\n\t                    \"@type\": \"ReadAction\",\n\t                    \"target\": [\n\t                        \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/\"\n\t                    ]\n\t                }\n\t            ]\n\t        },\n\t        {\n\t            \"@type\": \"ImageObject\",\n\t            \"inLanguage\": \"en-US\",\n\t            \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/ibkr-quant-news\\\/handling-options-chains\\\/#primaryimage\",\n\t            \"url\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2024\\\/05\\\/api-cubes.jpg\",\n\t            \"contentUrl\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2024\\\/05\\\/api-cubes.jpg\",\n\t            \"width\": 1000,\n\t            \"height\": 563,\n\t            \"caption\": \"API\"\n\t        },\n\t        {\n\t            \"@type\": \"WebSite\",\n\t            \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#website\",\n\t            \"url\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/\",\n\t            \"name\": \"IBKR Campus US\",\n\t            \"description\": \"Financial Education from Interactive Brokers\",\n\t            \"publisher\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#organization\"\n\t            },\n\t            \"potentialAction\": [\n\t                {\n\t                    \"@type\": \"SearchAction\",\n\t                    \"target\": {\n\t                        \"@type\": \"EntryPoint\",\n\t                        \"urlTemplate\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/?s={search_term_string}\"\n\t                    },\n\t                    \"query-input\": {\n\t                        \"@type\": \"PropertyValueSpecification\",\n\t                        \"valueRequired\": true,\n\t                        \"valueName\": \"search_term_string\"\n\t                    }\n\t                }\n\t            ],\n\t            \"inLanguage\": \"en-US\"\n\t        },\n\t        {\n\t            \"@type\": \"Organization\",\n\t            \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#organization\",\n\t            \"name\": \"Interactive Brokers\",\n\t            \"alternateName\": \"IBKR\",\n\t            \"url\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/\",\n\t            \"logo\": {\n\t                \"@type\": \"ImageObject\",\n\t                \"inLanguage\": \"en-US\",\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#\\\/schema\\\/logo\\\/image\\\/\",\n\t                \"url\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2024\\\/05\\\/ibkr-campus-logo.jpg\",\n\t                \"contentUrl\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2024\\\/05\\\/ibkr-campus-logo.jpg\",\n\t                \"width\": 669,\n\t                \"height\": 669,\n\t                \"caption\": \"Interactive Brokers\"\n\t            },\n\t            \"image\": {\n\t                \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#\\\/schema\\\/logo\\\/image\\\/\"\n\t            },\n\t            \"publishingPrinciples\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/about-ibkr-campus\\\/\",\n\t            \"ethicsPolicy\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/cyber-security-notice\\\/\"\n\t        },\n\t        {\n\t            \"@type\": \"Person\",\n\t            \"@id\": \"https:\\\/\\\/ibkrcampus.com\\\/campus\\\/#\\\/schema\\\/person\\\/68e347fb855adceb4ccfbfa350f5b783\",\n\t            \"name\": \"Andrew Wise\",\n\t            \"url\": \"https:\\\/\\\/www.interactivebrokers.com\\\/campus\\\/author\\\/andrew-wise\\\/\"\n\t        }\n\t    ]\n\t}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Handling Options Chains | IBKR Quant","description":"Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.interactivebrokers.com\/campus\/wp-json\/wp\/v2\/posts\/205882\/","og_locale":"en_US","og_type":"article","og_title":"Handling Options Chains","og_description":"Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.","og_url":"https:\/\/www.interactivebrokers.com\/campus\/ibkr-quant-news\/handling-options-chains\/","og_site_name":"IBKR Campus US","article_published_time":"2024-05-01T19:26:54+00:00","article_modified_time":"2025-08-08T16:11:50+00:00","og_image":[{"width":1000,"height":563,"url":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg","type":"image\/jpeg"}],"author":"Andrew Wise","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Andrew Wise","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/#article","isPartOf":{"@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/"},"author":{"name":"Andrew Wise","@id":"https:\/\/ibkrcampus.com\/campus\/#\/schema\/person\/68e347fb855adceb4ccfbfa350f5b783"},"headline":"Handling Options Chains","datePublished":"2024-05-01T19:26:54+00:00","dateModified":"2025-08-08T16:11:50+00:00","mainEntityOfPage":{"@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/"},"wordCount":1805,"commentCount":5,"publisher":{"@id":"https:\/\/ibkrcampus.com\/campus\/#organization"},"image":{"@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/#primaryimage"},"thumbnailUrl":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg","keywords":["Algo Trading","IBKR API","RESTful API","WebAPI"],"articleSection":["Data Science","IBKR API Development","Programming Languages","Python Development","Quant","Quant Development","Quant Options","REST Development"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/","url":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/","name":"Handling Options Chains | IBKR Campus US","isPartOf":{"@id":"https:\/\/ibkrcampus.com\/campus\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/#primaryimage"},"image":{"@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/#primaryimage"},"thumbnailUrl":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg","datePublished":"2024-05-01T19:26:54+00:00","dateModified":"2025-08-08T16:11:50+00:00","description":"Throughout this article, I\u2019ll present one method for retrieving an option chain programmatically.","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ibkrcampus.com\/campus\/ibkr-quant-news\/handling-options-chains\/#primaryimage","url":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg","contentUrl":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg","width":1000,"height":563,"caption":"API"},{"@type":"WebSite","@id":"https:\/\/ibkrcampus.com\/campus\/#website","url":"https:\/\/ibkrcampus.com\/campus\/","name":"IBKR Campus US","description":"Financial Education from Interactive Brokers","publisher":{"@id":"https:\/\/ibkrcampus.com\/campus\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ibkrcampus.com\/campus\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ibkrcampus.com\/campus\/#organization","name":"Interactive Brokers","alternateName":"IBKR","url":"https:\/\/ibkrcampus.com\/campus\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ibkrcampus.com\/campus\/#\/schema\/logo\/image\/","url":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/ibkr-campus-logo.jpg","contentUrl":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/ibkr-campus-logo.jpg","width":669,"height":669,"caption":"Interactive Brokers"},"image":{"@id":"https:\/\/ibkrcampus.com\/campus\/#\/schema\/logo\/image\/"},"publishingPrinciples":"https:\/\/www.interactivebrokers.com\/campus\/about-ibkr-campus\/","ethicsPolicy":"https:\/\/www.interactivebrokers.com\/campus\/cyber-security-notice\/"},{"@type":"Person","@id":"https:\/\/ibkrcampus.com\/campus\/#\/schema\/person\/68e347fb855adceb4ccfbfa350f5b783","name":"Andrew Wise","url":"https:\/\/www.interactivebrokers.com\/campus\/author\/andrew-wise\/"}]}},"jetpack_featured_media_url":"https:\/\/www.interactivebrokers.com\/campus\/wp-content\/uploads\/sites\/2\/2024\/05\/api-cubes.jpg","_links":{"self":[{"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/posts\/205882","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/users\/1173"}],"replies":[{"embeddable":true,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/comments?post=205882"}],"version-history":[{"count":0,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/posts\/205882\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/media\/205915"}],"wp:attachment":[{"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/media?parent=205882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/categories?post=205882"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/tags?post=205882"},{"taxonomy":"contributors-categories","embeddable":true,"href":"https:\/\/ibkrcampus.com\/campus\/wp-json\/wp\/v2\/contributors-categories?post=205882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}