| 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.Generic;
using System.Linq;
using QuantConnect.Data;
using QuantConnect.Data.Market;
namespace QuantConnect.Algorithm.CSharp.MyStuff.OptionsDataCheck
{
/// <summary>
/// This is a crude (non-foolproof) algorithm to check for bulk missing options data files.
///
/// For the specified options underlying, every day (at 2 hours after open) it checks to see if there is at least 1 ATM call
/// and 1 ATM put for each of the expiry dates it's seen before. If none are found, it logs a debug message.
///
/// It only checks monthly options with 65 or less days to expiration, but could be set to whatever in Initialize().
/// Also, there's a flag to invert the logging, to only log when there IS data available.
/// </summary>
public class ÒptionsDataCheckAlgo : QCAlgorithm
{
private Symbol _optionSymbol;
private bool _checkNextSlice = false;
List<DateTime> _existingExpiries = new List<DateTime>();
private bool _onlyLogWhenThereIsData = false;
/// <summary>
/// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
/// </summary>
public override void Initialize()
{
//SetStartDate(2012, 1, 1);
//SetEndDate(2018, 9, 1);
SetStartDate(2018, 10, 1);
SetEndDate( 2019, 2, 13);
var option = AddOption("AAPL", Resolution.Minute);
option.SetFilter(-1, 1, TimeSpan.FromDays(0), TimeSpan.FromDays(65));
_optionSymbol = option.Symbol;
// Flag to invert the logging.
_onlyLogWhenThereIsData = false; //true;
// Flag to check next data slice every day 2 hours after market open.
Schedule.On(DateRules.EveryDay(_optionSymbol), TimeRules.AfterMarketOpen(_optionSymbol, 120), () => _checkNextSlice = true);
}
/// <summary>
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// </summary>
/// <param name="data">Slice object keyed by symbol containing the stock data</param>
public override void OnData(Slice data)
{
if (!_checkNextSlice)
return;
_checkNextSlice = false;
if (!IsMarketOpen(_optionSymbol))
{
if (!_onlyLogWhenThereIsData)
Debug("On " + Time.ToString("yyyy-MM-dd") + " market closed for " + _optionSymbol.ToString());
return;
}
OptionChain chain;
if (data.OptionChains.TryGetValue(_optionSymbol, out chain))
{
// Remove expired expiries.
var expiredExpiries = _existingExpiries.Where(e => e.Date < Time.Date).ToList();
foreach (var expiry in expiredExpiries)
{
//Debug("Removing old expiry " + expiry.ToString("yyyy-MM-dd"));
_existingExpiries.Remove(expiry);
}
// Add new expiries.
var newExpiries = chain.Where(oc => !_existingExpiries.Contains(oc.Expiry)).Select(oc => oc.Expiry).Distinct();
foreach (var expiry in newExpiries)
{
//Debug("Adding new expiry " + expiry.ToString("yyyy-MM-dd"));
_existingExpiries.Add(expiry);
}
// Check there is at least 1 expiry to check.
if (!_onlyLogWhenThereIsData)
{
if (_existingExpiries.Count == 0)
{
Debug("On " + Time.ToString("yyyy-MM-dd") + " " + chain.Underlying.Symbol.ToString() + " there are no options expiries to check (i.e. missing all options)");
}
}
// Check if there's any calls & puts for each expiry.
foreach (var expiry in _existingExpiries)
{
var calls = chain.Where(oc => oc.Expiry == expiry && oc.Right == OptionRight.Call).Count();
var puts = chain.Where(oc => oc.Expiry == expiry && oc.Right == OptionRight.Put).Count();
// Check for missing data.
if (!_onlyLogWhenThereIsData)
{
if (calls == 0 || puts == 0)
{
Debug("On " + Time.ToString("yyyy-MM-dd") + " " + chain.Underlying.Symbol.ToString() + " options for expiry=" + expiry.ToString("yyyy-MM-dd") + " is missing: " +
(calls == 0 ? "calls " : "") +
(puts == 0 ? "puts " : ""));
}
}
// Check for data.
if (_onlyLogWhenThereIsData)
{
if (calls > 0 || puts > 0)
{
Debug("On " + Time.ToString("yyyy-MM-dd") + " " + chain.Underlying.Symbol.ToString() + " options for expiry=" + expiry.ToString("yyyy-MM-dd") + " exists for: " +
(calls > 0 ? "calls " : "") +
(puts > 0 ? "puts " : ""));
}
}
}
}
else
{
if (!_onlyLogWhenThereIsData)
Debug("On " + Time.ToString("yyyy-MM-dd") + " no options chain for " + _optionSymbol.ToString());
}
}
}
}