Overall Statistics |
Total Trades 97 Average Win 0% Average Loss 0.00% Compounding Annual Return -11.346% Drawdown 0.100% Expectancy -1 Net Profit -0.112% Sharpe Ratio -10.893 Probabilistic Sharpe Ratio 0% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0.005 Annual Variance 0 Information Ratio -10.893 Tracking Error 0.005 Treynor Ratio 0 Total Fees $49.00 |
using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Data; using QuantConnect.Data.Market; using QuantConnect.Orders; using QuantConnect.Securities.Option; namespace QuantConnect.Algorithm.CSharp { public class OptionExpirationCancelTest : QCAlgorithm { private static readonly DateTime Start = new DateTime(2020, 11, 6); private static readonly DateTime End = new DateTime(2020, 11, 9); private static readonly string UnderlyingTicker = "AAPL"; private static readonly Symbol OptionSymbol = QuantConnect.Symbol.Create( UnderlyingTicker, SecurityType.Option, Market.USA ); private static readonly Symbol UnderlyingSymbol = QuantConnect.Symbol.Create( UnderlyingTicker, SecurityType.Equity, Market.USA ); public override void Initialize() { SetStartDate(Start); SetEndDate(End); SetCash(100000); AddEquity(UnderlyingSymbol, Resolution.Daily, Market.USA, false); Option option = AddOption(UnderlyingSymbol, Resolution.Minute, Market.USA, false); //Grab OTM Puts for the current weekly expiration option.SetFilter(u => u .PutsOnly() .Expiration(TimeSpan.Zero, TimeSpan.FromDays(7)) .WeeklysOnly() .Strikes(Int32.MaxValue, -5) ); DefaultOrderProperties.TimeInForce = TimeInForce.Day; //Cancel all orders at end of day Schedule.On(DateRules.EveryDay(UnderlyingSymbol), TimeRules.AfterMarketOpen(UnderlyingSymbol, -1), AtStartOfDayHandler); // 9:29 AM Schedule.On(DateRules.EveryDay(UnderlyingSymbol), TimeRules.Every(TimeSpan.FromMinutes(60)), PeriodicCycleHandler); } private void PeriodicCycleHandler(string arg1, DateTime arg2) { Transactions.CancelOpenOrders(); } public override void OnData(Slice slice) { if (!Portfolio.Invested) { OptionChain chain; if (CurrentSlice.OptionChains.TryGetValue(OptionSymbol, out chain)) { IEnumerable<OptionContract> currentWeeklies = chain .Where(oc => oc.Expiry < CurrentSlice.Time.AddDays(2)); foreach (var optionContract in currentWeeklies) { if(IsMarketOpen(optionContract.Symbol)) MarketOrder(optionContract.Symbol, 1); } } } } private void AtStartOfDayHandler() { // Check if any positions are expired but somehow left over IEnumerable<Option> expiredPos = Portfolio.Where(kvp => kvp.Value.Invested) .Select(kvp => Securities[kvp.Key] as Option) .Where(opt => opt != null) .Where(opt => opt.Expiry.Date < CurrentSlice.Time.Date); if(expiredPos.Any()) { string msg = string.Join(", ", expiredPos.Select(option => $"{option.Symbol}, {Portfolio[option.Symbol].Quantity}, {Securities[option.Symbol].Price}")); Quit($"There are expired holdings on {CurrentSlice.Time.Date.ToShortDateString()} -> {msg}"); } } } }