Option Strategies

Covered Call


A Covered Call is an options strategy that involves both the underlying stock and an options contract. The trader buys (or already owns) a stock, then sells call options for the same amount of stock. The aim of the Covered Call is to profits from the option premium by selling calls written on the stock you already owned. At any time for US options or at expiration for European options, if the stock moves below the strike price, you can keep the premium and still maintain the stock position. If the price moves above the strike, the options contract will be exercised and you will have to sell the stock at the strike price but you will still keep the premium. The risk of a Covered Call also comes from the long stock position whose price could drop.

The payoff is as follows:


$Payoff=(Price^{T=expiry}_{underlying}-Price^{T=trade\ open}_{underlying}+credit\ received_{call}-Payoff_{call})\times multiplier-commissions$

covered call strategy payoff

The maximum profit is the call strike minus underlying price plus the premium of selling the call after commission when opening the trade, where the underlying price has price the same as or above the strike price of the call at expiration.

If the underlying price drop, the maximum loss is unlimited, but it will always be offset by the premium of selling the call after commission when opening the trade.

If the option is American option, there will be a risk of early assignment on the shorted option. Naked longed call would pose risk of losing all debit paid if its position is not closed with shorted call together and the price dropped below its strike.


Follow these steps to implement the covered call strategy.

  1. Initialize the Algorithm: At the beginning of your algorithm, you need to set the start date, the end date and the cash required for the algorithm. For options algorithm, you need to add the equity and the options written on this equity.
  2. private Symbol _equity;
    private Symbol _symbol;
    public override void Initialize()
        SetStartDate(2016, 1, 1);
        SetEndDate(2016, 3, 1);
        _equity = AddEquity("IBM", Resolution.Minute).Symbol;
        var option = AddOption("IBM", Resolution.Minute);
        _symbol = option.Symbol;
        option.SetFilter(universe => universe.Strikes(-3, 3)
                                                .Expiration(TimeSpan.FromDays(0), TimeSpan.FromDays(30)));
    def Initialize(self) -> None:
        self.SetStartDate(2016, 1, 1)
        self.SetEndDate(2016, 3, 1)
        equity = self.AddEquity("IBM", Resolution.Minute)
        option = self.AddOption("IBM", Resolution.Minute)
        self.symbol = option.Symbol
        # set our strike/expiry filter for this option chain
        option.SetFilter(-3, +3, timedelta(0), timedelta(30))
  3. In the OnData method, select the Option contracts.
  4. public override void OnData(Slice slice)
        if (Portfolio.Invested) return;
        // Get the OptionChain of the symbol
        var chain = slice.OptionChains.get(_symbol, null);
        if (chain == null || chain.Count() == 0) return;
        // get at-the-money strike
        var atmStrike = chain.OrderBy(x => Math.Abs(x.Strike - chain.Underlying.Price)).First().Strike;
        // filter the call options from the contracts which is ATM in the option chain.
        var calls = chain.Where(x => x.Strike == atmStrike && x.Right == OptionRight.Call);
        if (calls.Count() == 0) return;
        // sort the contracts by expiration date
        var contracts = calls.OrderBy(x => x.Expiry);
        // select the farest expiry as far-leg expiry, and the nearest expiry as near-leg expiry
        var contract = contracts.Last();
    def OnData(self, slice: Slice) -> None:
        # avoid extra orders
        if self.Portfolio.Invested: return
        # Get the OptionChain of the self.symbol
        chain = slice.OptionChains.get(self.symbol, None)
        if not chain: return
        # Get ATM strike price
        atm_strike = sorted(chain, key = lambda x: abs(chain.Underlying.Price - x.Strike))[0].Strike
        # filter ATM call options contracts
        calls = [x for x in chain if x.Strike == atm_strike and x.Right == OptionRight.Call] 
        if len(calls) == 0: return
        # sorted the ATM contracts according to their expiration dates
        contracts = sorted(calls, key=lambda x: x.Expiry, reverse=True)
        # Select the furthest expiring contract
        contract = contracts[0]
  5. In the OnData method, sell the selected option and buy the corresponding amount of underlying asset.
  6.     Sell(contract.Symbol, 1);
        Buy(_equity, 100);
    self.Sell(contract.Symbol, 1) # short the call options
        self.Buy("IBM", 100)           # buy 100 (multiplier) the underlying stock


In this algorithm, we've realised the below payout at expiration (2014-1-18).

Price of call$ 3.50
Price of underlying stock when trade open$ 187.07
Strike of call$ 185.00
Price of underlying at expiration$ 190.09
Commission per trade$ 1.00


So, the strategy gains $443.


Backtest using SetFilter

Backtest using OptionChainProvider

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: