| 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}");
}
}
}
}