Overall Statistics
Total Trades
12
Average Win
0.20%
Average Loss
-0.27%
Compounding Annual Return
-6.139%
Drawdown
3.100%
Expectancy
0.093
Net Profit
-0.810%
Sharpe Ratio
-1.265
Probabilistic Sharpe Ratio
17.242%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
0.75
Alpha
-0.064
Beta
-0.058
Annual Standard Deviation
0.049
Annual Variance
0.002
Information Ratio
-0.193
Tracking Error
0.203
Treynor Ratio
1.084
Total Fees
$6.00
using QuantConnect.Securities.Option;

namespace QuantConnect.Algorithm.CSharp 
{   

    public class BullCallSpreadAlgorithm : QCAlgorithm
    {

	private Equity equity;
	private Option option; 
    private	Symbol optionSymbol;
    	public override void Initialize()
    	{
        	SetStartDate(2018, 1, 1);
        	SetEndDate(2019, 11, 27);
        	SetCash(100000);
        	equity = AddEquity("SPY", Resolution.Minute);
        	option = AddOption("SPY", Resolution.Minute);
        	optionSymbol = option.Symbol;
    		Debug("Init option symbol " + optionSymbol.ToString() + " equity symbol " + equity.Symbol.ToString());
        
            option.SetFilter(u => u.IncludeWeeklys().Strikes(-4, 4)
        	         .Expiration(TimeSpan.FromDays(1) /*TimeSpan.Zero*/, TimeSpan.FromDays(7)));
            option.PriceModel = OptionPriceModels.CrankNicolsonFD();
            // set the warm-up period for the pricing model
            SetWarmup(TimeSpan.FromDays(4));
        	SetBenchmark(equity.Symbol);
        	equity.FeeModel = new ConstantFeeModel(0);
        	option.FeeModel = new ConstantFeeModel(0);
    	}

        public override void OnData(Slice slice) 
        {
        	if(IsWarmingUp) return;
            OptionChain chain;
			if (slice.OptionChains.TryGetValue(optionSymbol, out chain))
			{
				OptionContracts contracts = chain.Contracts;
        		if (contracts == null || contracts.Count == 0) return;
        	
        		// if there is no securities in portfolio, trade the options 
        		if (!Portfolio.Invested) {
            		TradeOptions(chain);
        		}
			}
        }
            
        private void TradeOptions(OptionChain chain)
        {

            	 // sorted the optionchain by expiration date and choose the furthest date
            	 var lastExpiry = chain.OrderByDescending(x => x.Expiry).First().Expiry;
            	 var farthestCallChain = chain.Where(x=> x.Expiry == lastExpiry && x.Right == OptionRight.Call);
            	 var orderedCallChain = farthestCallChain.OrderBy(x => x.Strike);

                 Log(Time + " Chains count " + chain.Contracts.Count + " last Expiry " + lastExpiry.ToShortDateString()
            	       + " count " + farthestCallChain.Count());

            	 // call option contract with lower strike
            	 var call_low = orderedCallChain.First();
            	 // call option contract with higher strike
            	 var call_high = orderedCallChain.Last();

                 Buy(call_low.Symbol, 1);
                 Sell(call_high.Symbol ,1);
        }
        
        public override void OnOrderEvent(OrderEvent orderEvent) 
        {
        	Log(Time + " " + orderEvent);
        }
    }
}