Previous: Machine Learning

Workshop 8: Options Trading

An option is a contract that gives its owner the right to buy (call option) or sell (put option) a financial asset (the underlying) at a fixed price (the strike price) at or before a fixed date (the expiration date). Options trading has the reputation to be more rewarding, but also more complex than trading currencies or stocks. At least for the script, the latter is not true; Zorro allows easy and straightforward coding of options strategies. Here's an example of a simple options selling system (Workshop8.c):

#include <contract.c>

#define PREMIUM  2.00 // $200 per contract 
#define DAYS     6*7  // 6 weeks to expiration

void run() 
  StartDate = 2012;
  EndDate = 2018;
  BarPeriod = 1440;
  LookBack = 1;

  Multiplier = 100;

// load today's contract chain
  contractUpdate("SPYa",0,CALL|PUT); // artificial options data

  if(!NumOpenShort) { 
// find contracts with 6 weeks expiration and $2 premium
    { // sell a Strangle
      MarginCost = 0.5*(0.15*priceClose() - min(comboStrike(1)-priceClose(),priceClose()-comboStrike(2)));

Unlike Forex data, historical options data is usually not free, but must be purchased from data vendors. For this reason, we've uploaded artificially generated SPY options data (SPYa.t8) on the Zorro download page. You can use it for backtesting this strategy, but if you want to go deeper into algorithmic options trading, better purchase 'real' data. More about generating artificial options data and a general introduction in automated options trading can be found on Financial Hacker.

There are a few differences to a 'normal' trading system. We're using an asset list for the broker IB that contains the underlying stock, SPY, a fund following the S&P500 index. Option contracts usually cover batches of N stocks, often 100, which must be set through Multiplier. The contractUpdate function loads the current options chain - the list of options with all available combinations of expirations and strikes - either from historical data, or from the broker API. If no positions are open, the strategy attempts to sell short a put and a call contract with 6 weeks expiration at a bid price of 2 dollars per stock. The contractFind function scans the options chain for fitting contracts.  

The two contracts that match the desired bid price and expiration are now combined to a combo. Options and option combos can be traded with the usual enter functions, they must only be selected before with contract() or comboLeg() to distinguish the order from a trade with the underlying. The earned price - the premium, in total about 400 dollars minus commission - is booked on the account. That's not yet our profit, since we might be later obliged to sell or buy the underlying SPY stock at the strike price. The broker - or Zorro, respectively - will do that automatically when the underlying price at expiration date is not in our favor, and will deduct the difference of price and strike from our account. Otherwise, the contracts will expire worthlessly and we can keep the premium.

This combination of a put and a call contract is called a Strangle. Because we aimed for small premiums, our contracts start out of the money, meaning that the underlying price is below the call strike and above the put strike. This way we will normally win the premium, or most of it, when the SPY price does not move too far away until expiration. Otherwise, we'll lose. If the price moves a lot, we'll lose a lot.

Mind the MarginCost calculation. It is needed for a realictic backtest, since margin determines the required capital. Brokers use a different margin formula for any options combination, so it should be calculated in the script. Here we assume that the margin of a sold strangle is the premium (which is automatically added) plus 15% of the underlying price minus the minimum of the two strike differences. We multiply that with 0.5 because MarginCost is per stock, but the used margin formula is for the whole strangle. For this formula to work, the historical prices that we're using (priceClose) must be not adjusted for splits and dividends. That's the case for the SPY history from the download page.

The result

We can see that the strategy achieves not spectacular, but relatively constant annual returns in the 20% area. 84% of all trades are won - that's the statistical seller advantage of options trading. The result is based on artificial options data, but real historical data - available from data vendors at some hundred dollars for daily SPY contracts - produces a similar result.

It is not advisable to trade this system unchanged, because it has no mechanism for limiting losses. We can see the dips in the equity curve whenever the S&P500 strongly rises or falls. We could place a stop loss just like for a normal trading system. The contracts are then automatically bought back when the underlying price moves dangerously far. A better solution is buying 'insurance' in the form of two additional contracts with more distant strikes. This long/short combination of 4 contracts reduces the profit a bit, but also restricts losses to a limit that can be determined with the strike prices. A script for displaying the risk and profit curves of arbitrary option combinations can be found on Financial Hacker.

We're now at the end of the strategy coding course. For writing your own systems, it can save you a lot of time when you flip through this manual and make yourself familiar with Zorro's math and statistics functions. Often-used code snippets for your own scripts and strategies can be found on the Tips & tricks page. Writing good code and fixing bugs is described under Troubleshooting. If you worked with a different trade platform before, read the Conversion page about how to convert your old scripts or EAs to C. For serious strategy development, some knowledge of the leading data analysis software R can be of advantage - check out the R lectures.

What have we learned in this workshop?

Further reading: ►contract, combo