Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Orders;
using QuantConnect.Securities;
using QuantConnect.Securities.Option;

namespace QuantConnect.Algorithm.CSharp.Options
{
    public class DebitBullCallSpreadAlgorithm : QCAlgorithm
    {
        const string underlyingTicker = "AAPL";
        public readonly decimal cash = 1000000;

        public readonly int minExpirationDays = 0;
        public readonly int maxExpirationDays = 4;
        public readonly int minStrike = -20;
        public readonly int maxStrike = 20;


        public readonly Symbol underlying = QuantConnect.Symbol.Create(underlyingTicker, SecurityType.Equity, Market.USA);
        public readonly Symbol optionSymbol = QuantConnect.Symbol.Create(underlyingTicker, SecurityType.Option, Market.USA);


        int counter = 0;

        public override void Initialize()
        {
            this.SetStartDate(2013, 1, 1);
            this.SetEndDate(2013, 5, 1);
            this.SetCash(cash);

            this.AddEquity(underlyingTicker);
            this.SetBenchmark(this.underlying);

            var option = this.AddOption(underlyingTicker);
            option.SetFilter(universe => from symbol in universe.Strikes(minStrike, maxStrike).Expiration(TimeSpan.FromDays(this.minExpirationDays), TimeSpan.FromDays(this.maxExpirationDays)) select symbol);

            {
                // log experiment parameters
                string message = "DebitBullCallSpreadAlgorithm: UnderlyingTicker=[" + underlyingTicker + "]";
                message += ", minStrike=[" + minStrike + "], maxStrike=[" + maxStrike + "]";
                message += ", minExpirationDays=[" + minExpirationDays + "], maxExpirationDays=[" + maxExpirationDays + "], cash =[" + cash + "],";
                message += ", weekly and monthly options";
                Debug(message);
            }

            var stockPlot = new Chart("AAPL");
            stockPlot.AddSeries(new Series("AAPL", SeriesType.Line, 0));
            stockPlot.AddSeries(new Series("maxBetPut", SeriesType.Line, 0));
            stockPlot.AddSeries(new Series("maxBetCall", SeriesType.Line, 0));
            stockPlot.AddSeries(new Series("friday", SeriesType.Scatter, 1));
            //            stockPlot.AddSeries(new Series("distributionWidthPut", SeriesType.Scatter, 3));
            //            stockPlot.AddSeries(new Series("distributionWidthCall", SeriesType.Scatter, 4));
            AddChart(stockPlot);
        }

        public override void OnData(Slice slice)
        {
            IEnumerable<OptionContract> contracts = null;
            {
                OptionChain chain;
                if (slice.OptionChains.TryGetValue(this.optionSymbol, out chain))
                {
                    contracts = (from contract in chain select contract);
                }
            }

            this.Plot(contracts);
        }

        public void Plot(IEnumerable<OptionContract> contracts)
        {
            // guard against being called after trading hours
            if (this.Time.TimeOfDay < new TimeSpan(9, 30, 0) || this.Time.TimeOfDay > new TimeSpan(16, 0, 0))
            {
                return;
            }

            if (contracts == null || contracts.Count() == 0)
            {
                return;
            }

            // plot every 10 minutes
            counter++;
            if (counter == 10)
            {
                counter = 0;

                OptionContract maxBetPut = FindContractWithMaxDollarBet(contracts, OptionRight.Put);
                OptionContract maxBetCall = FindContractWithMaxDollarBet(contracts, OptionRight.Call);

                Plot("AAPL", "AAPL", maxBetPut.UnderlyingLastPrice);
                Plot("AAPL", "maxBetPut", maxBetPut.Strike);
                Plot("AAPL", "maxBetCall", maxBetCall.Strike);

                if(this.Time.DayOfWeek == DayOfWeek.Friday)
                {
                    Plot("AAPL", "friday", 1);
                }
            }
        }

        private OptionContract FindContractWithMaxDollarBet(IEnumerable<OptionContract> contracts, OptionRight right)
        {
            OptionContract foundContract = null;
            if (right == OptionRight.Put)
            {
                foundContract = (
                        from contract in contracts
                            .OrderByDescending(contract => (contract.OpenInterest * contract.LastPrice))
                        where contract.Right == right
                        select contract
                    ).FirstOrDefault();
            }
            else
            {
                foundContract = (
                        from contract in contracts
                            .OrderByDescending(contract => (contract.OpenInterest * contract.LastPrice))
                        where contract.Right == right
                        select contract
                    ).FirstOrDefault();
            }

            if (foundContract != null)
            {
                return foundContract;
            }

            throw new Exception("Did not find contract with max dollar bet for=[" + right + "], [" + this.optionSymbol.Value + "]");
        }
    }
}