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
Probabilistic 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
namespace QuantConnect.Algorithm.CSharp
{
    public partial class CollarAlgorithm : QCAlgorithm
    {
		// **********************   DividendRecord		 **************************************
	    // ***  This structure contains the dividend information necessary to calculate trading
	    // ***	decision.   It is used to build a List<DividendRecord> that can be searched to 
	    // ***	produce the nextExDivDate and dividend amount

	    public struct DividendRecord {
	    	public string ticker;
	    	public DateTime exDate;
	    	public decimal divAmt;
	    	public string frequency;
		}
    
    
    	// **********************   GetTickers()		 **************************************
	    // ***  This function downloads the tickers.csv file from Dropbox and loads it into 
	    // ***	a Dictionary<int, string> for randomly selecting stocks to put on 
	    // ***	this dictionary is used when making a trading decision 
		public void GetTickers()
		{
							// https://www.dropbox.com/s/hkpr3luefv3u141/StockTickers.csv?dl=1		// 2020-09-26
							// https://www.dropbox.com/sh/05qjk3o3y53fp4i/AAA6fEJg8J50xMQWm5nlg7M4a?dl=1 // prior
			var tickerFile = Download("https://www.dropbox.com/s/hkpr3luefv3u141/StockTickers.csv?dl=1");
			if (tickerFile == null)
			{
				return;
			}
			
			string[]  tickerLines = tickerFile.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
			int h = 0;
			foreach (string tickerLine in tickerLines)
			{
				if(h==0)	// discard header row
				{
					h++;
					continue;
				}
				var vals = tickerLine.Split(',');
				tickers.Add(h, vals[0]);   
				h++;
			}
			
			
			// these next 2 lines are for debugging only -- 
			return;
	    
		}
	    
	    // **********************   GetFedFundsRates()		 **************************************
	    // ***  This function downloads the DFF.csv file from Dropbox and loads it into 
	    // ***	a Dictionary<DateTime, interest rate> for each day 
	    // ***	this dictionary is used when making a trading decision to calculate the interest
		public Dictionary<DateTime, decimal> GetFedFundsRates()
		{
			var ffFile = Download("https://www.dropbox.com/s/s25jzi5ng47wv4k/DFF.csv?dl=1");
			if (ffFile == null) return null;
			
			Dictionary<DateTime, decimal> ffDict = new Dictionary<DateTime, decimal>();
			string[]  ffLines = ffFile.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
			int h = 0;
			foreach (string ffLine in ffLines)
			{
				if(h==0)	// discard header row
				{
					h++;
					continue;
				}
				var vals = ffLine.Split(',');
				ffDict.Add(DateTime.Parse(vals[0]), Convert.ToDecimal(vals[1])/100M);   // convert percentage to decimal
				h++;
			}
			
			
			// these next 2 lines are for debugging only -- 
			//DateTime testFind = DateTime.Parse("02/02/2015 16:30:00");
			//var justDate = testFind.Date;
			return ffDict;
		}
	    
	    // **********************   GetDividendDates()		 **************************************
	    // ***  This function downloads the DividendDates.csv file from Dropbox and loads it into 
	    // ***	a List<DividendRecord>.  The List is used to lookup the next ex-dividend date
	    // ***	this list  is used when making a trading decision to calculate the dividend payout
	    public List<DividendRecord> GetDividendDates()
	    {
	    	// 2020-9-25 9:24  https://www.dropbox.com/s/ap8s120gksb858h/DividendData.csv?dl=1
	    	// 2020-09-25 8:11 https://www.dropbox.com/s/ap8s120gksb858h/DividendData.csv?dl=1
	    	//  2020-09-25 8:09 https://www.dropbox.com/sh/05qjk3o3y53fp4i/AAA6fEJg8J50xMQWm5nlg7M4a?dl=1  -- zip file
	    	//var csvFile = Download("https://www.dropbox.com/s/ap8s120gksb858h/DividendData.csv?dl=1");  --- worked then it failed
	    	var csvFile = Download("https://www.dropbox.com/s/ap8s120gksb858h/DividendData.csv?dl=1");
	    	if (csvFile == null) return null;
			
			decimal lastDiv = 0;
	
	    	List<DividendRecord> dividendDates = new List<DividendRecord>();
	    	
	    	// want to use Microsoft.VisualBasic.FileIO csv parser but is not available
	    	// use the system's /cr /lf to parse the file string into lines
	    	string[] csvLines = csvFile.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
	    	int i = 0;
	    	
	    	foreach (string csvLine in csvLines)
	    	{
	    		if (i == 0) 
	    		{
	    			i++;
	    			continue;		//discard the header row
	    		}
	    		DividendRecord divRec = new DividendRecord();
	    		var values = csvLine.Split(',');   // this file is comma delimited
	    		
	    		divRec.ticker = values[0];
	    		
	    		if (values[1] == "") {
	    				divRec.divAmt = 0;
	    		} else {
		    		divRec.divAmt = Convert.ToDecimal(values[1]);
	    		}
	    		
	    		divRec.exDate = DateTime.Parse(values[2]);
	    		divRec.frequency = values[3];
	    		dividendDates.Add(divRec);
	    	}
	    	i++;
	    	return dividendDates;
	    }
    }
    	
}
using QuantConnect.Securities.Option;
using System.Drawing;

namespace QuantConnect.Algorithm.CSharp
{
    public partial class CollarAlgorithm : QCAlgorithm
    {
		// Initialize trade control variables used to intercept automated options exercise.

		public bool badDtParameter;	// get this from the parameters for debugging
		public bool haltProcessing = false;	// use this to trap ERROR
		int logged = 0;						// Switch to toggle log entry writing
		bool doItOnce = true;				// Switch to toggle options exercise interdiction
		bool iteratePortfolio = false;		// Switch to toggle Iterating and Logging portfolio
		
		public int addedSecCount = 0;		// used to figure out how options data is added.
		OptionChain testChain;				// used to figure out when options chains are available after adding them
		OptionContract textContract;		// used to figure out when options greeks are available

		decimal stockDollarValue;			// get the dollar value for the position
		decimal sharesToBuy;				// Get the number shares to achieve the value
		decimal optionsToTrade;				// Get the initial Options to trade (1/10th the sharesToBuy)		
		decimal maxPutOTM = 0.5M;			// Instantiate and set maximum depth of PUT OTM -- percentage
		int MinNmbrDivs = 1;				// Instantiate and set minimum number of dividends acceptable in BestSSQRMatrix
	
		bool doTheTrade = false;			// Used to allow trades the algorithm initiates
		bool useDeltas = false;				// used to turn use of deltas in trade determination on or off
		DateTime oldRollDate;				// used to make sure we don't do an ITM-FORCED ROLL on the same
		DateTime newRollDate;				// date as a DIVIDEND roll.
		public Symbol tradablePut;			// for roll determination
		public Symbol tradableCall;			// for roll determination
		
		public decimal ROCThresh;
		public decimal RORThresh;
		bool goodThresh = false;					// used to determine go/no-go on trade
		public bool switchROC = true;
		
		List<DividendRecord> exDividendDates = new List<DividendRecord>();
		Dictionary<DateTime, decimal> fedFundsRates = new Dictionary<DateTime, decimal>();
		decimal workingDays = 365M;
		decimal thisFFRate = 0M;
		decimal ibkrRateAdj = .006M;		// IBKR adds 60bps to FFR (blended over $3,000,000)
		Dictionary<decimal, decimal> ibkrHairCuts = new Dictionary<decimal, decimal>();

		List<TradePerfRec> tradeRecs = new List<TradePerfRec>();	// used to track P&L of trades
		int tradeRecCount = 0;										// track the trade count

		// initialize class variables for ex-dividend dates, Active
		Dictionary<int, string> tickers = new Dictionary<int, string> ();

		List<OptionContract> ActiveOptions = new List<OptionContract>();
		List<Option> callOptions = new List<Option>();
		
		Symbol thisSymbol;							// Initialize Symbol T as class variable
		Symbol debugSymbol;							// general purpose debugging variable
		OptionChain debugChain;						// special purpose debugging variable
		
		SSQRColumn bestSSQRColumn = new SSQRColumn();
		
		decimal stockDividendAmount = 0M;
		decimal divPlotValue = 0M;
		DateTime fmrNextExDate;
		
		// Instatiate and set plotting information
		Stochastic sto;								//  Stochastic	
        //AccumulationDistribution ad;				// Accumulation / Distribution
        //AccumulationDistributionOscillator adOsc;	// Accumulation / Distribution Oscillator
        AverageDirectionalIndex adx;				// Average Directional Index
        AverageDirectionalMovementIndexRating adxr;	// Average Directional Index Rating
        OnBalanceVolume obv;						// On Balance Volumne indicator
        Variance variance;							// Variance of this stock		
        
        decimal lastSto;							// store values from night before
        decimal lastAd;
        decimal lastAdOsc;
        decimal lastAdx;
        decimal lastAdxr;
        decimal lastObv;
        decimal lastVariance;
        
		
		public override void Initialize()
        {
    		SetStartDate(2019, 1, 1);  //Set Start Date
		    SetEndDate(2019, 1, 5);
            SetCash(10000000);           //Set Strategy Cash

			SetWarmup(31, Resolution.Daily);
            
            //ABBV	ADM	BA	BBY	BMY	CVS	DOW	GIS	GM	IBM	IRM	KO	LVS	M OHI OXY PM PG	PSX	QCOM SO	T VZ WFC XOM
            //var qBook = new QuantBook();
			// Get RunTime control parameters for Minimum # of Dividends and Maximum OTM Put Depth
			
			badDtParameter = true; // GetParameter("CheckBadDate")  == "true" ? true : false; // get this from parameters      
			stockDollarValue = 10m; // Convert.ToDecimal(GetParameter("StockDollarValue"));
			maxPutOTM = 2; //Convert.ToDecimal(GetParameter("MaxOTMPutDepth"));			// get and set the Maximum OTM Put Depth
			MinNmbrDivs = 1; //Convert.ToInt16(GetParameter("MinNmbrDivs"));			// get and set minimum number of dividends acceptable in BestSSQRMatrix
			useDeltas = true; // GetParameter("UseDeltas")  == "true" ? true : false;	// get this from parameters      
			

			switchROC = true; // GetParameter("ROC") == "true" ? true : false ;	// Switch to decide to trade based upon return on capital or return on risk

            thisSymbol = AddEquity("AAPL", Resolution.Minute).Symbol;
            Securities[thisSymbol].SetDataNormalizationMode(DataNormalizationMode.Raw);  
            Securities[thisSymbol].VolatilityModel = new StandardDeviationOfReturnsVolatilityModel(30);
            
			//SetBenchmark(thisSymbol);
			
			
			sto = STO(thisSymbol, 14, Resolution.Daily);			//  Stochastic 
            adx = ADX(thisSymbol, 7, Resolution.Daily);					// Average Directional Index
            adxr = ADXR(thisSymbol, 7, Resolution.Daily);				// Average Directional Index Rating
            obv = OBV(thisSymbol, Resolution.Daily);					// On Balance Volume
            variance = VAR(thisSymbol, 14, Resolution.Daily);		// Variance of this stock
			
			GetTickers();
			ibkrHairCuts = InitializeHaircuts();
			SetSecurityInitializer(HistoricalSecurityInitializer);  
			
			
        }  // Initialize()


        public override void OnData(Slice data)
        {
			if (!IsMarketOpen(thisSymbol) | !sto.IsReady | !variance.IsReady | !data.Bars.ContainsKey(thisSymbol)) 
				return;
			
			if (useDeltas)
			{

				Plot("Chains", "Vale", data.OptionChains.Count); // 0				

				foreach (var newChain in data.OptionChains)
				{
					var testVol = Securities[newChain.Key.Underlying].VolatilityModel.Volatility;
					Debug("At " + data.Time + ", Symbol,   Bid,  Ask, Last, Open Interest, Volatility, Theoretical Price, Delta, Implied Vol");
						
					foreach (var thisContract in newChain.Value)
					{
						Debug("At " + data.Time + ", " + thisContract.Symbol.Value  + ", " + thisContract.BidPrice + ", " + thisContract.AskPrice + ", "  + thisContract.LastPrice + ", " + 
						thisContract.OpenInterest + ", "+ testVol + ", " + thisContract.TheoreticalPrice + ", " + thisContract.Greeks.Delta + ", " + thisContract.ImpliedVolatility);
					}
				}
				
				if (data.OptionChains.Count > 0) Quit();
				
			}

       		GetBestSSQR(data, thisSymbol, getNextExDate(thisSymbol.Value, data.Time));
        }	// OnData()
        

		private void HistoricalSecurityInitializer(Security security)
		{ 
			var bar = GetLastKnownPrice(security);
    		security.SetMarketPrice(bar);
		}

    }  // class
    
} // namespace
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp {
	public partial class CollarAlgorithm : QCAlgorithm
	{
		public class SSQRColumn
		{
			public decimal stockPrice;
			public DateTime exDate;
			public DateTime optExpiry;
			public int daysInPosition;
			public decimal interestCost;
			public Symbol putSymbol;
			public Symbol callSymbol;
			public decimal putPremium;
			public decimal callPremium;
			public decimal putStrike;
			public decimal callStrike;
			public decimal putOpenInterest;
			public decimal callOpenInterest;
			public decimal putDelta;
			public decimal callDelta;
			public decimal putGamma;
			public decimal callGamma;
			public decimal putVega;
			public decimal callVega;
			public decimal putRho;
			public decimal callRho;
			public decimal putTheta;
			public decimal callTheta;
			public decimal putImpliedVol;
			public decimal callImpliedVol;
			public decimal divAmt;
			public int divCount;
			public decimal downsideRisk;
			public decimal upsidePotential;
			public decimal netIncome;
			public decimal netOptions;
			public decimal divDollars;
			public decimal haircut;				// committed capital in a portfolio margin account
			public decimal ROC;					// Return on Capital
			public decimal ROR;					// Return on Risk
			public string description1;
			public string description2;
			//public string description3;

			public override string ToString()
			{
				return this.description1;
			}





		}
		
	}
}
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp {

    //
    //	Make sure to change "BasicTemplateAlgorithm" to your algorithm class name, and that all
    //	files use "public partial class" if you want to split up your algorithm namespace into multiple files.
    //

    public partial class CollarAlgorithm : QCAlgorithm
    {
    	// **********************   assembleSSQRMatrix **************************************
	    // ***  			This sub routine takes in the options expiries and all the symbols
	    // ***				available in the Slice.Data and builds the puts chains and calls symbols lists
	    // ***				The puts and calls symbols lists are used to build the contracts lists
	    // **				The contracts lists are used to build the SSQR Matrix
	    // ***********************************************************************************
    	public List<SSQRColumn> assembleSSQRMatrix(Dictionary<int, DateTime> expiries, IEnumerable <Symbol> allUnderlyingOptionsSymbols, decimal stockPrice, decimal amtDividend, DateTime tradeDate, DateTime thisExDivDate)
    	{
			if (haltProcessing)
			{
				Debug(" @@@@@  Halting assembleSSQR processing");
			}
			
			OptionChain putChain;						// chain object to get contracts
			OptionChain callChain;						// chain object to get contracts
			
			OptionContract putGreeks;						// chain object to collect greeks
			OptionContract callGreeks;						// chain object to collect greeks

			List<SSQRColumn> SSQRMatrix = new List<SSQRColumn>();
			

        	var callSymbolsForThisExpiry = allUnderlyingOptionsSymbols;   
        	var putSymbolsForThisExpiry = allUnderlyingOptionsSymbols;	   
	        // Get the ATM call contract 
    		var atmCall = allUnderlyingOptionsSymbols.Where(s => s.ID.OptionRight == OptionRight.Call)
    											.OrderBy(s => Math.Abs(s.ID.StrikePrice - stockPrice))
    											.FirstOrDefault();
    											
			var atmPut =  allUnderlyingOptionsSymbols.Where(s => s.ID.OptionRight == OptionRight.Put)
    											.OrderBy(s => Math.Abs(s.ID.StrikePrice - stockPrice))
    											.FirstOrDefault();
    		
    		Option atmCallOpt = AddOptionContract(atmCall);
			Option atmPutOpt = AddOptionContract(atmPut);
			
			atmCallOpt.PriceModel = OptionPriceModels.BinomialTian();
			atmPutOpt.PriceModel = OptionPriceModels.BinomialTian();
			
			
			return SSQRMatrix;
			
			if (badDtParameter) debugSymbol = atmPut;				// if debugging, set the debugSymbol to the atmPut for diagnostics
			
			
			// Alex informed me that the openInterest data has to be warmed up
			var callOpenInterest = History<OpenInterest>(atmCall, TimeSpan.FromDays(5)).FirstOrDefault();
			var putOpenInterest = History<OpenInterest>(atmPut, TimeSpan.FromDays(5)).FirstOrDefault();
			
			var totOpenInterest = atmCallOpt.OpenInterest + atmPutOpt.OpenInterest;     											
    		
    		//Debug("0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O");
    		// Debug("0O0O0O0O0O0O0O0O0O0O0O0O		OPEN INTEREST		0O0O0O0O0O0O0O0O0O0O0O0O0O0O0");
    		// Debug(" The total Put + Call Open Interest for " + atmCall.ID.Underlying + " is " + atmCallOpt.OpenInterest + ".");
	   		// Debug("0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O0O");
    		
    		var atmStrike = atmCall.ID.StrikePrice;
    		var lowStrike = (1 - (maxPutOTM / (decimal)100)) * atmStrike;   // ~~ eventually need a mechanism to determine strike steps
    		var highStrike = (decimal)1.1 * atmStrike;  // ~~ and use strike steps to set upper and lower bounds

	        int k = 1;					// initialize iterator for AddOptionContracts below
       		Symbol optSymbol;			// initialize option symbol for building the list of contracts
        	Option tempOption;			// initialize option contract for building list of contracts and obtaining pricing data
    		List<Option> callOptionsList = new List<Option>();
    		List<Option> putOptionsList = new List<Option>();
    		
    		decimal haircut;			// for buliding SSQR -- used when trading decision is based upon return on committed capital
    		int daysInTrade;			// for building SSQR -- calculating interest cost
    		Option thisPutOpt;			// for building SSQR
    		Option thisCallOpt;			// for building SSQR
    		Symbol thisPutSymb;			// for building SSQR
    		Symbol thisCallSymb;		// for building SSQR
    		decimal thisPutPrem;		// for building SSQR
    		decimal thisCallPrem;		// for building SSQR
    		decimal thisPutStrike;		// for building SSQR
    		decimal thisCallStrike;		// for building SSQR
    		DateTime thisExpiry;		// for building SSQR
			//decimal putOpenInterest;
			//decimal callOpenInterest;
			//decimal putDelta;
			//decimal callDelta;
			//decimal putGamma;
			//decimal callGamma;
			//decimal putVega;
			//decimal callVega;
			//decimal putRho;
			//decimal callRho;
			//decimal putTheta;
			//decimal callTheta;
			//decimal putImpliedVol;
			//decimal callImpliedVol;
			int numDividends;			// for building SSQR
    		//decimal amtDividend;		// for building SSQR
    		decimal interestCost;		// for building SSQR
    		decimal amtSpread;			// for building SSQR
    		decimal amtTotCost;			// for building SSQR
    		
    		DateTime whichExpiry = new DateTime();
     	
     		// assemble the symbols lists for each of the next 4 dividends, 
     		for (int dividends = MinNmbrDivs; dividends < 5; dividends++)
        	{	
    			switch (dividends)
    			{
    				case 1:
    					whichExpiry = expiries[1];
    					break;
						
					case 2:
    					whichExpiry = expiries[2];
    					break;
					
					case 3:
    					whichExpiry = expiries[3];
    					break;
					
					case 4:
    					whichExpiry = expiries[4];
    					break;	
    			}
				
				daysInTrade = ((TimeSpan) (whichExpiry - tradeDate)).Days;   // get the # of days from trade date to expiry for carry cost 
				
				///////// NOTE :  CATCH THE EXCEPTION WHERE LOOKUP FAILS
				var justDate = tradeDate.Date;								// separate out the DATEVALUE from the DateTime variable
				thisFFRate = fedFundsRates[justDate];						//	fedFundsRates is a Dictionary where DateTime index are all 12:00:00am
				thisFFRate = thisFFRate;									// fedFundsRates entries are expressed as percentages and were converted upon reading them into dictionary
				interestCost = (thisFFRate + ibkrRateAdj)/workingDays * (decimal) daysInTrade * stockPrice;  
				callSymbolsForThisExpiry = allUnderlyingOptionsSymbols.Where(o => DateTime.Compare(o.ID.Date, whichExpiry) ==  0 && 
         												o.ID.OptionRight == OptionRight.Call &&
         												o.ID.StrikePrice >= lowStrike &&
         												o.ID.StrikePrice < highStrike &&
         												!(daysInTrade <=10 & daysInTrade > 1 & o.ID.StrikePrice > (stockPrice - (0.5M * stockPrice)) | (daysInTrade <= 1 & o.ID.StrikePrice < stockPrice)))
         												.OrderByDescending(o => o.ID.StrikePrice);
			
				if (callSymbolsForThisExpiry != null)
				{
					//Debug("This call chain is for AT&T whose price is " + stockPrice + ", and expiring on " + whichExpiry);
					//IterateChain(callSymbolsForThisExpiry);   // Use this call to debug and examine members
			
        			var enumerator = callSymbolsForThisExpiry.GetEnumerator();	
        			callOptionsList.Clear();
        			
        			while (enumerator.MoveNext()) 
        			{
						optSymbol = enumerator.Current;
						tempOption = AddOptionContract(optSymbol);
						tempOption.PriceModel = OptionPriceModels.BinomialTian();		/// necessary for Greeks?
						callOptionsList.Add(tempOption);
        			}
    			
    				// IterateContracts(callOptionsList);
				}
		
				putSymbolsForThisExpiry = allUnderlyingOptionsSymbols.Where(o => DateTime.Compare(o.ID.Date, whichExpiry) ==  0 && 
         													o.ID.OptionRight == OptionRight.Put &&
         													o.ID.StrikePrice >= lowStrike &&
         													o.ID.StrikePrice <= atmStrike &&
			   												!(daysInTrade <=10 & daysInTrade > 1 & o.ID.StrikePrice > (stockPrice + (0.5M * stockPrice)) | (daysInTrade <= 1 & o.ID.StrikePrice > stockPrice)))
         													.OrderByDescending(o => o.ID.StrikePrice);
				if (putSymbolsForThisExpiry != null)
				{
					//Debug("This put chain is for AT&T whose price is " + stockPrice + ", and expiring on " + whichExpiry);
					//IterateChain(putSymbolsForThisExpiry);   // Use this call to debug and examine members
			
        			var enumerator = putSymbolsForThisExpiry.GetEnumerator();	
        			putOptionsList.Clear();
        			
        			while (enumerator.MoveNext()) 
        			{
						optSymbol = enumerator.Current;
						tempOption = AddOptionContract(optSymbol);
						tempOption.PriceModel = OptionPriceModels.BinomialTian();			/// necessary for Greeks?
						putOptionsList.Add(tempOption);
        			}
    			
					// IterateContracts(putOptionsList);
				}

    			// Now iterate through the puts and sub-iterate through the calls to assemble the SSQRMatrix
    			// for pricing, puts are bought at the offer and calls are sold at the bid prices.
    			// Each price should be the midpoint between the open and close.
 
    			if (putOptionsList != null && callOptionsList != null)
    			{
    				var putEnum = putOptionsList.GetEnumerator();
	    			while (putEnum.MoveNext())
	    			{
	    				thisPutOpt = putEnum.Current;
	    				thisPutPrem = thisPutOpt.AskPrice;
	    				thisPutStrike = thisPutOpt.StrikePrice;
	    				//putChain = History<OptionChain>(thisPutOpt.Symbol, TimeSpan.FromDays(30)).FirstOrDefault();
	    				//putGreeks = putChain.Contracts[thisPutOpt.Symbol];
	    				var callEnum = callOptionsList.GetEnumerator();	// cannot reset this enumerator, have to re-create
	    				while (callEnum.MoveNext())
	    				{
	    					thisCallOpt = callEnum.Current;
	    					thisCallPrem = thisCallOpt.BidPrice;
	    					thisCallStrike = thisCallOpt.StrikePrice;
							//callChain = History<OptionChain>(thisCallOpt.Symbol, TimeSpan.FromDays(30)).FirstOrDefault();
							//callGreeks = callChain.Contracts[thisCallOpt.Symbol];

	    					
	    					if (thisCallStrike >= thisPutStrike)		// only add put/call combinations where call strike is above put strike
	    					{
	    						//SSQRColumn thisSSQRColumn = buildSSQRColumn(thisPutOpt, thisCallOpt, putGreeks, callGreeks, whichExpiry, tradeDate, thisExDivDate, dividends, amtDividend, stockPrice,  daysInTrade, interestCost);
	    						SSQRColumn thisSSQRColumn = buildSSQRColumn(thisPutOpt, thisCallOpt, whichExpiry, tradeDate, thisExDivDate, dividends, amtDividend, stockPrice,  daysInTrade, interestCost);
	    						SSQRMatrix.Add(thisSSQRColumn);
	    						/*
	    						if (thisCallStrike == thisPutStrike)
	    						{
						            Debug(" --------------------------------PUT/CALL EQUIVALENCE WARNING -------------------------------------------------------------");
	    							Debug("the PUT AND CALL CONTRACTS HAVE THE SAME STRIKE  " + thisPutStrike + "/" + thisCallStrike + " and the downside risk is " + thisSSQRColumn.downsideRisk + " with a potential profit of " + thisSSQRColumn.netIncome );
	    							Debug(" The description reads thus:  " + thisSSQRColumn.description);
	    							Debug(" ----------------------------------------------------------------------------------------------------------------------------");
	    						}
	    						*/
	    					}//  if thisCallStrike == thisPutStrike
	    				} // while callEnum
	    			} //while putEnum	
   				} // !null
    			
    			// reset the List<Option> vars for next dividend iteration  (redundant?  -- see above)
    			//putOptionsList.Clear();
    			//callOptionsList.Clear();
    			
        	} // for dividends 1 through 4
    	
    		return SSQRMatrix;
    		
    	} // AssembleSSQRMatrix


    	// **********************   buildSSQRColumn **************************************
	    // ***  			This sub routine takes in the variables for the iterated put and call Options Lists
	    // ***				as well as the dividends count, dividend amount, and stock price
	    // ***				and returns an SSQRColumt to be added to the SSQRMatrix list
	    // ***********************************************************************************

	    public SSQRColumn buildSSQRColumn(Option thisPutOpt, Option thisCallOpt, DateTime whichExpiry, DateTime tradeDate, DateTime exDate, int dividends, decimal amtDividend, decimal stockPrice, int daysInTrade, decimal intCost)
        //public SSQRColumn buildSSQRColumn(Option thisPutOpt, Option thisCallOpt, OptionContract pGrks, OptionContract cGrks, DateTime whichExpiry, DateTime tradeDate, DateTime exDate, int dividends, decimal amtDividend, decimal stockPrice, int daysInTrade, decimal intCost)
	    {
	    	decimal thisSpread = 1M;
	    	
	    	decimal thisPutPrem = thisPutOpt.AskPrice;
	    	decimal thisCallPrem = thisCallOpt.BidPrice;
	    	decimal thisPutStrike = thisPutOpt.StrikePrice;
	    	decimal thisCallStrike = thisCallOpt.StrikePrice;
	    	
	    	SSQRColumn thisColumn = new SSQRColumn();							// get a new SSQRColumn
	    	
	    	
	    	thisColumn.putSymbol = thisPutOpt.Symbol;
	    	thisColumn.callSymbol = thisCallOpt.Symbol;
	    	thisColumn.putPremium = thisPutPrem;
	    	thisColumn.callPremium = thisCallPrem;
	    	thisColumn.putStrike = thisPutStrike;
	    	thisColumn.callStrike = thisCallStrike;
	    	thisColumn.exDate = exDate;
	    	//thisColumn.putDelta = pGrks.Greeks.Delta;
	    	//thisColumn.callDelta = cGrks.Greeks.Delta;
	    	//thisColumn.putGamma = pGrks.Greeks.Gamma;
	    	//thisColumn.callGamma = cGrks.Greeks.Gamma;
	    	//thisColumn.putVega = pGrks.Greeks.Vega;
	    	//thisColumn.callVega = cGrks.Greeks.Vega;
	    	//thisColumn.putRho = pGrks.Greeks.Rho;
	    	//thisColumn.callRho = cGrks.Greeks.Rho;
	    	//thisColumn.putTheta = pGrks.Greeks.Theta;
	    	//thisColumn.callTheta = cGrks.Greeks.Theta;
	    	//thisColumn.putImpliedVol = pGrks.ImpliedVolatility;
	    	//thisColumn.callImpliedVol = cGrks.ImpliedVolatility;
	    	thisColumn.divAmt = amtDividend;
	    	thisColumn.divCount = dividends;
	    	thisColumn.stockPrice = stockPrice;
	    	thisColumn.optExpiry = whichExpiry;
	    	thisColumn.daysInPosition = daysInTrade;
	    	thisColumn.interestCost = intCost;
	    	
	    	thisSpread = thisCallStrike - thisPutStrike;
	    	if (!ibkrHairCuts.ContainsKey( (thisCallStrike - thisPutStrike)) )
	    	{
	    		//Debug("*^*^*^*^*^*^*^*^*^*^**^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*");
	    		//Debug("Make a haircut entry for " + (thisCallStrike - thisPutStrike).ToString());
	    		//Debug("*^*^*^*^*^*^*^*^*^*^**^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*^*");
	    		if (thisSpread < 5M)
				{
					thisColumn.haircut = .5M;
				} else thisColumn.haircut = thisSpread;
	    		
	    	}else
	    	{
	    		thisColumn.haircut = ibkrHairCuts[thisSpread];
	    	}
        	
	    	decimal divDollars = amtDividend * dividends;
	    	thisColumn.divDollars = divDollars;
	    	
	    	decimal stockLossIfCalled = (thisCallStrike>stockPrice) ? 0: thisCallStrike -stockPrice; // loss=0 if cStrike>stkPrice, otherwise negative	***Loss (negative value) if ITM calls are assigned 
	    	
	    	decimal netOptions = -thisPutPrem + thisCallPrem;		/// netOptions equals negative putPrem (expense) plus positive call premium (income)
	    	thisColumn.netOptions = netOptions;

	    	thisColumn.netIncome = divDollars + netOptions + stockLossIfCalled - intCost; 			  // Net Income in SSQR.xls subtracts interest cost but does not allow for appreciation to OTM call strike

	    	thisColumn.ROC = (divDollars + netOptions + stockLossIfCalled - intCost) / thisColumn.haircut;  // store ROC for statistical analysis
	    	
	    	decimal downsideRisk = thisPutStrike - stockPrice + divDollars + netOptions - intCost; 	 // downside risk is defined as the potential loss due to stock price depreciation _
	    	thisColumn.downsideRisk = downsideRisk;													 // subtracts dividends collected and net options premiums and intCost
	    	
	    	decimal upsidePotential = thisCallStrike - stockPrice + divDollars + netOptions - intCost;	// When writing OTM calls, there is a potential 
	    	thisColumn.upsidePotential = upsidePotential;												// upside appreciation from net collar cost to the call strike.
	    	
	    	thisColumn.ROR = upsidePotential/-downsideRisk;												// store ROR 
	    	
	    	
	    	thisColumn.description1 = "Combination in " + thisPutOpt.Symbol.Underlying  + " @ " + stockPrice + " is the " + thisPutStrike + "/" + thisCallStrike + " collar  ";
	    	
	    	thisColumn.description2 = "," + thisPutOpt.Symbol.Underlying + "," + String.Format("{0:0.00}", stockPrice) + "," + exDate.ToString("MM/dd/yy") + "," 
	    		+ dividends + "," + String.Format("{0:0.00}", amtDividend) + "," + String.Format("{0:0.00}",divDollars) + "," + daysInTrade + ", " 
	    		+ String.Format("{0:0.00}", intCost) + ", " + whichExpiry.ToString("MM/dd/yy") + ", " + String.Format("{0:0.00}",thisPutStrike) + ", " 
	    		+ String.Format("{0:0.00}",thisPutPrem) + ", " + String.Format("{0:0.00}",thisCallStrike) + ", " + String.Format("{0:0.00}", thisCallPrem) + ", " 
				+ String.Format("{0:0.00}",thisColumn.putDelta) + ", " + String.Format("{0:0.00}", thisColumn.callDelta) + ", "
	    		+ String.Format("{0:0.00}",netOptions) + ", " + String.Format("{0:0.00}", thisColumn.netIncome) + ", " + String.Format("{0:0.00}", thisColumn.haircut) 
	    		+ ", " + String.Format("{0:0.00}",thisColumn.netIncome/thisColumn.haircut) + "," + String.Format("{0:0.00}", upsidePotential) + "," 
	    		+ String.Format("{0:0.00}", downsideRisk) + "," + String.Format("{0:0.00}",upsidePotential/-downsideRisk);
	    	
	    	return thisColumn;
	    	
	    }
  
    	
	    // **********************   AddCorrespondingPut	  *******************************************
	    // ***  			This code will add the put option which corresponds to the call shorted
	    // ***				for purposes of evaluating it in ex-dividend approachment.
	    // ***				Option must be constructed with correct parameters before it can be added
	    // ******************************************************************************************
        
    	public Option AddCorrespondingPut(Symbol tradableCall)
	    {    		
	        int indexOfC = tradableCall.ToString().LastIndexOf("C");
			char[] charArrayC = tradableCall.ToString().ToCharArray();
			char[] charArrayP = charArrayC;
			charArrayP[indexOfC] = 'P';
			string putString = new string(charArrayP);

			var putSymbol = QuantConnect.Symbol.CreateOption(
	    		tradableCall.Underlying,
				Market.USA,
				OptionStyle.American,
				OptionRight.Put,
				tradableCall.ID.StrikePrice,
				tradableCall.ID.Date);
			
			Option correspondingPut = AddOptionContract(putSymbol);
			return correspondingPut;
	    }
        
        
        // **********************   GetCorrespondingPut	  *******************************************
	    // ***  			This code will get the put option which corresponds to the call shorted
	    // ***				for purposes of evaluating it in ex-dividend approachment -- 
	    // ***				??? return Symbol or string?
	    // ******************************************************************************************
        
    	public string GetCorrespondingPut(Symbol tradableCall)
	    {    		
	        int indexOfC = tradableCall.ToString().LastIndexOf("C");
			char[] charArrayC = tradableCall.ToString().ToCharArray();
			char[] charArrayP = charArrayC;
			charArrayP[indexOfC] = 'P';
			string putString = new string(charArrayP);
			return putString;
	    }
	    
	    
	    // **********************   getNextExDate		**************************************
	    // ***  			Use this to find and return the next ex-dividend date from 
	    // ***				the list exDividendDates given a Slice.DateTime
	    // ***********************************************************************************
        
        public DateTime getNextExDate(string tickStr, DateTime sliceTime)     
		{
		
			DividendRecord nextExDateRec = exDividendDates.Where(d => DateTime.Compare(sliceTime, d.exDate)<0 &&
											 d.ticker == tickStr)
											.OrderBy(d => d.exDate)
											.FirstOrDefault();
			
			DateTime nextExDate = nextExDateRec.exDate;
			stockDividendAmount = nextExDateRec.divAmt;
			
			if (DateTime.Compare(nextExDate, fmrNextExDate) > 0) logged = 0;
			
			//Console.WriteLine("This slice was on " + sliceTime + " and the last NextExDate was " + fmrNextExDate + ".");
			
			if (logged < 1)
			{
				fmrNextExDate = nextExDate;
				//Console.WriteLine("This slice was on " + sliceTime + " and we found the next Ex-Date was " + nextExDate + " ");
				logged++;
			}
				
			
			return nextExDate;
		}	
    	
    	
    	
    	public SSQRColumn fillSSQRColumn ()
	    {
	    	SSQRColumn anotherSSQRColumn = new SSQRColumn();
	    	return anotherSSQRColumn;
	    }
	    
	    // **********************   GetOptionsExpiries **************************************
	    // ***  			Use this to find and return the next 4 options expirations expirations dates
	    // ***				Function will determine if a date is a holiday and subtract 1 day
	    // ***********************************************************************************
	    
	    public Dictionary<int, DateTime> GetOptionExpiries(DateTime nextExDate, DateTime thisMonthExpiry){
	    		// Initialize expiration date variables //
        		DateTime firstExpiry = new DateTime();
        		DateTime secondExpiry = new DateTime();
        		DateTime thirdExpiry = new DateTime();
        		DateTime fourthExpiry = new DateTime();
        		

        		// Initialize the dictionary for return
        		// 1 : first expiry
        		// 2 : second expiry...
        		Dictionary<int, DateTime> expiries = new Dictionary<int, DateTime>();
        		
        		// is the nextExDate before or after the 3rd Friday?  Before ? use this month expiration
        		// After ? use next month's expiration.
        		if (DateTime.Compare(nextExDate, thisMonthExpiry) <= 0)
        		{
        			firstExpiry = FindNextOptionsExpiry(thisMonthExpiry, 0);
        			secondExpiry = FindNextOptionsExpiry(thisMonthExpiry, 3);	
        			thirdExpiry = FindNextOptionsExpiry(thisMonthExpiry, 6);
        			fourthExpiry = FindNextOptionsExpiry(thisMonthExpiry, 9);
        			
        		}else
        		{
        			firstExpiry = FindNextOptionsExpiry(thisMonthExpiry, 1);
        			secondExpiry = FindNextOptionsExpiry(thisMonthExpiry, 4);
        			thirdExpiry = FindNextOptionsExpiry(thisMonthExpiry, 7);
        			fourthExpiry = FindNextOptionsExpiry(thisMonthExpiry, 10);
        		}
        		
        		expiries.Add(1, firstExpiry);
        		expiries.Add(2, secondExpiry);
        		expiries.Add(3, thirdExpiry);
        		expiries.Add(4, fourthExpiry);
        		
        		return expiries;
	    }
	    
	    // **********************   FindNextOptionsExpiry    **************************************
	    // ***  	Use this to find and return the next options expirations date x months ahead
	    // ***		Check the new date to make sure it isn't a holiday and if it is, subtract 1 day
	    // ********************************************************************************************
	
	    public DateTime FindNextOptionsExpiry(DateTime thisExpiry, int addedMonths){
	    	// Given a 3rd friday expiration, it will find the next 3rd friday expiration, addedMonths ahead
	    	// figure out how to handle holidays such as Good Friday, April 19, 2019.
	    	// ****************  should this be amended for non-quarterly dividend frequencies?  ****************
	    	int year = thisExpiry.Year;
	    	int month = thisExpiry.Month;
	    	
	    	month = month + addedMonths;
	    	
	    	// Adjust if bigger than 12
	    	if(month > 12){
	    		month = month % 12; 
	    		year = year + 1;
	    	}

			DateTime findDate = FindDay(year, month, DayOfWeek.Friday, 3);
			
     		// Evaluate if found expirations fall upon holidays and if they do, decrement them 1 day
       		while (USHoliday.Dates.Contains(findDate)) findDate = findDate.AddDays(-1);
   	    	
	    	return findDate;
	    }
	    
	    
		// **********************   FindDay		*******************************************************
	    // ***  	Generalized function to find and return a DateTime for a given year, month, DayOfWeek 
	    // ***		and occurrence in the month.
	    // ***		
	    // ********************************************************************************************
	
	    public DateTime FindDay(int year, int month, DayOfWeek Day, int occurrence)
	    {
	    	// Given a valid month, it will find the datetime for the 3rd friday of the month
	
	        if (occurrence <= 0 || occurrence > 5)
	            throw new Exception("occurrence is invalid");
	
	        DateTime firstDayOfMonth = new DateTime(year, month, 1);
	        //Substract first day of the month with the required day of the week 
	        var daysneeded = (int)Day - (int)firstDayOfMonth.DayOfWeek;
	        //if it is less than zero we need to get the next week day (add 7 days)
	        if (daysneeded < 0) daysneeded = daysneeded + 7;
	        //DayOfWeek is zero index based; multiply by the occurrence to get the day
	        var resultedDay = (daysneeded + 1) + (7 * (occurrence - 1));
	
	        if (resultedDay > (firstDayOfMonth.AddMonths(1) - firstDayOfMonth).Days)
	            throw new Exception(String.Format("No {0} occurrence(s) of {1} in the required month", occurrence, Day.ToString()));
	
	        return new DateTime(year, month, resultedDay);
	    }
	    
		// **********************   IterateChain		*******************************************************
	    // ***  	Generalized function to iterate through and print members of an IEnumerable
	    // ***		This is used for debugging only
	    // ********************************************************************************************
	    public void IterateChain(IEnumerable<Symbol> thisChain)
        {	
        	int k = 1;
       		Symbol optSymbol;
        	var enumerator = thisChain.GetEnumerator();	
        	
        	//Debug("  ||||||||||||||||||||||||||||||||   NEW OPTION SYMBOL CHAIN  |||||||||||||||||||||||||||||||");
        	//Debug("There are " + thisChain.Count() + " options symbols in this list of chains. ");
        	
        	
        	while (enumerator.MoveNext()) 
        	{
				optSymbol = enumerator.Current;
				
				//Debug("Iterated " + k + " times");
				//Debug(optSymbol.Value);
				
				//Debug(optSymbol.Value + " " + optSymbol.ID.StrikePrice + " " + optSymbol.ID.Date + " " + optSymbol.ID.OptionRight);
				k++;
        	}
        	//Debug(" ---------------------------------------------------------------------------------------------");
    
        }
        
        
        // **********************   IterateContracts		*******************************************************
	    // ***  	Generalized function to iterate through and print members of an IEnumerable of Contracts
	    // ***		This is used for debugging only
	    // ********************************************************************************************
	    public void IterateContracts(List<Option> thisOptionsList)
        {	
        	
        	int k = 1;
       		Option thisOption;
        	var enumerator = thisOptionsList.GetEnumerator();	
        	
        	Debug("  ||||||||||||||||||||||||||||||||   NEW OPTION CONTRACTS LIST  |||||||||||||||||||||||||||||||");
        	Debug("There are " + thisOptionsList.Count() + " contracts in this options list.");
        	
        	while (enumerator.MoveNext()) 
        	{
				thisOption = enumerator.Current;
				
				//Debug("Iterated  " + k + " times");
				//Debug("Option Chain: " + thisOption.ToString());
				
				//Debug(thisOption.StrikePrice + " " + thisOption.Expiry + " " + thisOption.Right + " " + thisOption.GetLastData());
				Debug(thisOption.StrikePrice + " " + thisOption.Expiry + " " + thisOption.Right + " BID: " + thisOption.BidPrice + " ASK: " + thisOption.AskPrice);
				k++;
        	}
            //Debug(" ---------------------------------------------------------------------------------------------");

        }
    
    
    	// **********************   Iterate Matrix		*******************************************************
	    // ***  	Generalized function to iterate through and print members of an IEnumerable of Contracts
	    // ***		This is used for debugging only
	    // ********************************************************************************************
	    public void IterateSSQRMatrix(List<SSQRColumn> thisMatrix)
        {	
        	
        	int k = 1;
    		SSQRColumn thisColumn;   		
        	var matrixEnum = thisMatrix.GetEnumerator();	
        	
        	//Debug("  ||||||||||||||||||||||||||||||||   NEW OPTION SSQRMatrix  |||||||||||||||||||||||||||||||");
			//Debug("There are " + thisMatrix.Count() + " columns in this SSQRMatrix.");
        	
        	while (matrixEnum.MoveNext()) 
        	{
				thisColumn = matrixEnum.Current;
				
				//Debug("Iterated  " + k + " times");
				//Debug(thisColumn.description);
				k++;
        	}

            //Debug(" ---------------------------------------------------------------------------------------------");
   
        }   
    
       	// **********************   Iterate Ordered Matrix		***********************************************
	    // ***  	Generalized function to iterate through and print members of an IEnumerable of Contracts
	    // ***		This is used for debugging only  tricky part is passing an IOrderedEnumerable into this 
	    // ****************************************************************************************************
	    public void IterateOrderedSSQRMatrix(IOrderedEnumerable<SSQRColumn> thisOrdMatrix)
	    {	
        	
        	int k = 1;
    		
        	Debug("  ||||||||||||||||||||||||||||||||   NEW TRADABLE SSQRMatrix  |||||||||||||||||||||||||||||||");
			Debug("There are " + thisOrdMatrix.Count() + " columns in this SSQRMatrix.");
        	Debug(",Ticker,Stock Price,Ex-Date,# Dividends,Dividend,Dollars,Days In,Interest,Expiry,PutStrike,PutASK,CallStrike,CallBid, PutDelta, CallDelta, NetOptions,Net Income,Haircut,ROC,Upside,Downside,ROR");

        	foreach (SSQRColumn thisColumn in thisOrdMatrix) 
        	{
				//Debug("Iterated  " + k + " times");
				Debug(thisColumn.description2);
				//Debug("  ");
				k++;
				if (k == 11) break;
        	}

        }
    
    }
    	
}
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp
{
    public partial class CollarAlgorithm : QCAlgorithm
    {
		private bool goodThresh2 = false;
		///////////////////////////////////////////////////////////////////////////////////
		//
		//								KillTheCollar
		//
		////////////////////////////////////////////////////////////////////////////////////

		public void KillTheCollar(TradePerfRec killRec, int killRecIndx, DateTime killDate, string reason)
		{
			if (haltProcessing) 
			{
				Debug("           HALTED IN KILLTHECOLLAR ");
			}
			
			doTheTrade = true;
			var stockTicket = MarketOrder(killRec.uSymbol, -killRec.uQty);	// sell the stock
			if (stockTicket.Status == OrderStatus.Filled)
			{
				killRec.isOpen = false;
				killRec.uEndPrice = stockTicket.AverageFillPrice;
				Plot("Stock Chart", "Sells", stockTicket.AverageFillPrice + 1);
				tradeRecCount = 0;				//  reset trade record count

				//Plot("Stock Chart", "Sells", 40);
			}
			
			doTheTrade = true;
			var closeCallTicket = MarketOrder(killRec.cSymbol, -killRec.cQty);  // buy the calls
			if (closeCallTicket.Status == OrderStatus.Filled)
			{
				killRec.cEndPrice = closeCallTicket.AverageFillPrice;
			}
			
			doTheTrade = true;
			var closePutTicket = MarketOrder(killRec.pSymbol, -killRec.uQty/100); // sell the puts
			if (closePutTicket.Status == OrderStatus.Filled)
			{
				killRec.pEndPrice = closePutTicket.AverageFillPrice;
			}
			
			killRec.reasonForClose = reason;
			killRec.endDate = killDate;			// set the end date of this collar
			
			Debug("-");

			
		}


		///////////////////////////////////////////////////////////////////////////////////
		//
		//								RollTheCollar
		//
		////////////////////////////////////////////////////////////////////////////////////
		public void RollTheCollar(Slice data, Symbol thisSymbol, string reason)
		{
			if (haltProcessing) 
			{
				Debug("                 HALTED ROLL ");
			}

			
			oldRollDate = data.Time.Date;
			decimal stockPrice = data[thisSymbol].Price;
			
			Plot("Stock Chart", "Rolls", stockPrice + 5);
			
			// find the trade performance record for this collar and save its index for updating
			var oldTradeRec = tradeRecs.Where(t => t.isOpen && t.uSymbol.Equals(thisSymbol)).FirstOrDefault();
        	int oldTradeRecIndx = tradeRecs.IndexOf(oldTradeRec);
        	
        	Symbol oldShortCallSymb = oldTradeRec.cSymbol;
        	Symbol oldLongPutSymb = oldTradeRec.pSymbol;
			
			// Cannot execute options spread orders at this time in QuantConnect, so do the collar as 
			// individual legs
			// 1st sell the long put
			doTheTrade = true;
			var closePutTicket = MarketOrder(oldLongPutSymb, -oldTradeRec.pQty);    // sell the existing puts
			if (closePutTicket.Status == OrderStatus.Filled)
			{
				oldTradeRec.pEndPrice = closePutTicket.AverageFillPrice;
			}
			// 2nd, buy back the long call
			doTheTrade = true;
			var closeCallTicket = MarketOrder(oldShortCallSymb, -oldTradeRec.cQty);
			if (closeCallTicket.Status == OrderStatus.Filled)
			{
				oldTradeRec.cEndPrice = closeCallTicket.AverageFillPrice;
			}
			
			//  Keep the stock, but close this trade performance record.
			
			oldTradeRec.uEndPrice = stockPrice;
			oldTradeRec.reasonForClose = reason;
			oldTradeRec.isOpen = false;
			oldTradeRec.endDate = data.Time;
			
			//  Put on a new collar and start a new trade performance record
    		// make a new TradePerfRec
    		
    		tradeRecCount = tradeRecCount + 1;				//  increment trade record count
	        		
    		TradePerfRec thisNewTPRec = new TradePerfRec();    
    		thisNewTPRec.uSymbol = thisSymbol;				// keep the underlying symbol
    		thisNewTPRec.uStartPrice = stockPrice;			// log the current slice stock price
    		thisNewTPRec.uQty = oldTradeRec.uQty;			// maintain the same quantity
			thisNewTPRec.isOpen = true;					// this new trade performance record is open
			thisNewTPRec.isInitializer = false;			// this is a continuation Collar
			thisNewTPRec.tradeRecCount = tradeRecCount;	// count the trades
			thisNewTPRec.startDate = data.Time;		// set the start date
			thisNewTPRec.pStrike = bestSSQRColumn.putStrike;
            thisNewTPRec.cStrike = bestSSQRColumn.callStrike;
			thisNewTPRec.expDate = bestSSQRColumn.optExpiry;	// set the options Expiry
			thisNewTPRec.ROC = bestSSQRColumn.ROC;		
			thisNewTPRec.ROR = bestSSQRColumn.ROR;
            thisNewTPRec.RORThresh = RORThresh;
            thisNewTPRec.ROCThresh = ROCThresh;
            thisNewTPRec.tradeCriteria = switchROC ? "ROC" : "ROR";
    		thisNewTPRec.stockADX  = lastAdx;
    		thisNewTPRec.stockADXR = lastAdxr;
    		thisNewTPRec.stockOBV = lastObv;
    		//thisNewTPRec.stockAD = lastAd;
    		//thisNewTPRec.stockADOSC = lastAdOsc;
    		thisNewTPRec.stockSTO = lastSto;
    		thisNewTPRec.stockVariance = lastVariance;

			//Debug(tradableColumn.ToString());
			var tradablePut = bestSSQRColumn.putSymbol;		// retrieve the put to buy
			var tradableCall = bestSSQRColumn.callSymbol;	// retrieve the call to sell

    		Option logCorrespondingPut = AddCorrespondingPut(tradableCall);   // Add the corresponding put here so system tracks its price for Ex-dividend approachment

			doTheTrade = true;
			var putTicket = MarketOrder(tradablePut, optionsToTrade);
			if (putTicket.Status == OrderStatus.Filled)
			{
				thisNewTPRec.pSymbol = tradablePut;
				thisNewTPRec.pStartPrice = putTicket.AverageFillPrice;
				thisNewTPRec.pQty = putTicket.QuantityFilled;
			}
		
			doTheTrade = true;
			var callTicket = MarketOrder(tradableCall, -optionsToTrade);
			if (callTicket.Status == OrderStatus.Filled)
			{
				thisNewTPRec.cSymbol = tradableCall;
				thisNewTPRec.cStartPrice = callTicket.AverageFillPrice;
				thisNewTPRec.cQty = callTicket.QuantityFilled;
			}
		
			/// roll is done.    save the new trade performance record
			
			//IterateTradeRecord(thisNewTPRec);
			
			tradeRecs.Add(thisNewTPRec);

		}
		
		///////////////////////////////////////////////////////////////////////////////////
		//
		//								GetBestSSQR
		//
		////////////////////////////////////////////////////////////////////////////////////
		
		public SSQRColumn GetBestSSQR(Slice thisSlice, Symbol thisStock, DateTime nextExDivDate)
		{
			// First get the underlying stock price in this Slice
			
			// Alex: we are both changing the same file so it's hard to get it. :D
			// Anyway, I replied to your last email.
    	    
    	    OptionChain ssqrPutChain;		// instantiate an OptionChain var for updating SSQRMatrix with slice data
    	    OptionChain ssqrCallChain;		// 
    	    Symbol ssqrPutSymbol;			// instantiate a Symbol var for updating SSQRMatrix with slice Data
    	    Symbol ssqrCallSymbol;			//
    	    
    	    
	    	if (haltProcessing)
    	    {
		    	Debug("  @@@@@@   BAD DATE IN GetBestSSQR");
	    	}
	    
    	    decimal stockPrice = thisSlice[thisStock].Price;

	        // Second get its options symbols
	        var allUnderlyingOptionsSymbols = OptionChainProvider.GetOptionContractList(thisStock, thisSlice.Time);
			
			if (allUnderlyingOptionsSymbols.Count() == 0)
			{
				SSQRColumn blankSSQR = new SSQRColumn();
				return blankSSQR;
			}
			
			
			int findYear = Time.Year;
			int findMonth = Time.Month;

			// Compute the 3rd Friday of this month [options expiration] ---> do not adjust for potential holiday here
	        DateTime thisMonthExpiry = FindDay(findYear, findMonth, DayOfWeek.Friday, 3);
	        		
	        // Use the 3rd Friday of the current month to seed the function to return the next 4 ex-dividends expiries adjusted for holidays
	        Dictionary<int, DateTime> expiries = GetOptionExpiries(nextExDivDate, thisMonthExpiry);
	        		
	        // now assemble the SSQR matrix using the expiries dictionary and the contracts lists
	        List<SSQRColumn> ssqrMatrix = assembleSSQRMatrix(expiries, allUnderlyingOptionsSymbols, stockPrice, stockDividendAmount, thisSlice.Time, nextExDivDate);
	        
	        return new SSQRColumn();
	        
	        ///////////////////////		GET DELTAS AND OPEN INTEREST FROM thisSlice DATA ////////////////////////
	        
	        foreach (SSQRColumn ssqrC in ssqrMatrix) /// loop through the SSQRMatris to update the deltas and open interest
	        {
	        	ssqrPutSymbol = ssqrC.putSymbol;
	        	ssqrCallSymbol = ssqrC.callSymbol;
	        	if (thisSlice.OptionChains.TryGetValue(ssqrPutSymbol, out ssqrPutChain))
	        	{
					Debug(" HEY THE ssqrPutChain count is " + ssqrPutChain + " AT " + thisSlice.Time);
	        		
	        	} else {
	        		Debug("  HEY NO OPTIONS IN THIS SLICE " + thisSlice.Time);
	        		
	        	}
	        	
	        	
	        	
	        	if (thisSlice.OptionChains.TryGetValue(ssqrCallSymbol, out ssqrCallChain))
	        	{
							        		
	        		
	        	}
	        	
	        	
	        	
	        }
	        
			
			///////////////////////    ATTEMPTS TO ISOLATE ITERATION TO TRADE EVENTS SOLELY  ///////////////////
			//IOrderedEnumable<SSQRColumn> orderedSSQRMatrix = new IOrderedEnumerable<SSQRColumn>();
			//List<SSQRColumn> orderedSSQRMatrix = new List<SSQRColumn>();
			
    		// Get the SSQRColumn with the best reward to risk
	    	SSQRColumn bestTradableColumn = new SSQRColumn();

			if (switchROC )
			{
				bestTradableColumn = ssqrMatrix.Where(p => p.netIncome > 0)
					.OrderByDescending(p => p.netIncome/p.haircut)
	    			.FirstOrDefault();
			} else {
				bestTradableColumn = ssqrMatrix.Where(p => p.netIncome > 0)
					.OrderByDescending(p => p.upsidePotential/-p.downsideRisk)
	    			.FirstOrDefault();
			}
			
			var thisROC = bestTradableColumn.netIncome/bestTradableColumn.haircut;
	        var thisROR = bestTradableColumn.upsidePotential/-bestTradableColumn.downsideRisk;

			if (switchROC )
			{
				goodThresh = (thisROC >= ROCThresh);
    		} else {
				goodThresh = (thisROR >= RORThresh);
			}
			
			if (switchROC)
			{			
				var orderedSSQRMatrix = ssqrMatrix.Where(p => p.netIncome > 0).OrderByDescending(p => p.netIncome/p.haircut);
			    if (goodThresh) IterateOrderedSSQRMatrix(orderedSSQRMatrix);
			    // Debugging Code -- Examine SSQRMatrix in reward/committed-capital descending order
			} else {
				/// *******************    what about where there is no downside risk?   && p.downsideRisk > 0)
				var orderedSSQRMatrix = ssqrMatrix.Where(p => p.netIncome > 0 ).OrderByDescending(p => (p.downsideRisk == 0 ? p.upsidePotential/-.01M : p.upsidePotential/-p.downsideRisk));
				if (goodThresh) IterateOrderedSSQRMatrix(orderedSSQRMatrix);
    			// Debugging Code -- Examine SSQRMatrix in reward/risk descending order
			}
			
			return bestTradableColumn;
	
		}
		
		public void IterateTradeRecord(TradePerfRec tR)
		{
			//Debug("@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%");
			Debug("@%@%@%@%@%@%@%@%@%@%@%		TRADE PERFORMANCE RECORD			@%@%@%@%@%@%@%@%@%@%@%@%");
			Debug("@ OPEN @ uSymbol @ pSymbol @ cSymbol @ uQty @ pQty @ cQty @ uStartPrice @ pStartPrice @ cStartPrice");
			Debug("@ " + tR.isOpen + "@ " + tR.uSymbol + "@ " + tR.pSymbol + "@ " + tR.cSymbol + "@ " + tR.uQty + "@ " + tR.pQty + "@ " + tR.cQty + "@ " + tR.uStartPrice + "@ " + tR.pStartPrice + "@ " + tR.cStartPrice + "@ ");
			Debug("@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%");
		}
    

    }
}
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp {
	public partial class CollarAlgorithm : QCAlgorithm
	{
		public Dictionary<decimal, decimal> InitializeHaircuts()
		{
			Dictionary<decimal, decimal> ibkrHC = new Dictionary<decimal, decimal>(); 
			
			ibkrHC.Add(0M, .75M);
			ibkrHC.Add(0.5M, .75M);
			ibkrHC.Add(1M, .75M);
			ibkrHC.Add(1.5M, .75M);
			ibkrHC.Add(2M, .75M);
			ibkrHC.Add(2.5M, .85M);
			ibkrHC.Add(3M, 1M);
			ibkrHC.Add(3.5M, 1.15M);
			ibkrHC.Add(4M, 1.3M);
			ibkrHC.Add(4.5M, 1.65M);
			ibkrHC.Add(5M, 2M);
			ibkrHC.Add(5.5M, 2.2M);
			ibkrHC.Add(6M, 2.4M);
			ibkrHC.Add(6.5M, 2.6M);
			ibkrHC.Add(7M, 2.8M);
			ibkrHC.Add(7.5M, 3M);
			ibkrHC.Add(8M, 3.5M);
			ibkrHC.Add(8.5M, 3.8M);
			ibkrHC.Add(9M, 4M);
			ibkrHC.Add(9.5M, 4.3M);
			ibkrHC.Add(10M, 4.5M);
			ibkrHC.Add(10.5M, 4.8M);
			ibkrHC.Add(11M, 5M);
			ibkrHC.Add(11.5M, 5.3M);
			ibkrHC.Add(12M, 5.5M);
			ibkrHC.Add(12.5M, 5.7M);
			ibkrHC.Add(13M, 6M);
			ibkrHC.Add(13.5M, 6.2M);
			ibkrHC.Add(14M, 6.6M);
			ibkrHC.Add(14.5M, 6.8M);
			ibkrHC.Add(15M, 7M);
			ibkrHC.Add(15.5M, 7.2M);
			ibkrHC.Add(16M, 7.4M);
			ibkrHC.Add(16.5M, 7.6M);
			ibkrHC.Add(17M, 7.8M);
			ibkrHC.Add(17.5M, 8.1M);
			ibkrHC.Add(18M, 8.2M);
			ibkrHC.Add(18.5M, 8.4M);
			ibkrHC.Add(19M, 8.6M);
			ibkrHC.Add(19.5M, 8.8M);
			ibkrHC.Add(20M, 9M);
			ibkrHC.Add(20.5M, 9.2M);
			ibkrHC.Add(21M, 9.4M);
			ibkrHC.Add(21.5M, 9.6M);
			ibkrHC.Add(22M, 9.8M);
			ibkrHC.Add(22.5M, 10.1M);
			ibkrHC.Add(23M, 10.4M);
			ibkrHC.Add(23.5M, 10.7M);
			ibkrHC.Add(24M, 11M);
			ibkrHC.Add(24.5M, 11.4M);
			ibkrHC.Add(25M, 11.8M);
			ibkrHC.Add(25.5M, 12.3M);
			ibkrHC.Add(26M, 12.8M);
			ibkrHC.Add(26.5M, 13.2M);
			ibkrHC.Add(27M, 13.7M);
			ibkrHC.Add(27.5M, 14.2M);
			ibkrHC.Add(28M, 14.7M);
			ibkrHC.Add(28.5M, 15.2M);
			ibkrHC.Add(29M, 15.6M);
			ibkrHC.Add(29.5M, 16.1M);
			ibkrHC.Add(30M, 16.6M);
			ibkrHC.Add(30.5M, 17M);
			ibkrHC.Add(31M, 17.4M);
			ibkrHC.Add(31.5M, 17.8M);
			ibkrHC.Add(32M, 13.4M);
			ibkrHC.Add(32.5M, 18.2M);
			ibkrHC.Add(33M, 18.6M);
			ibkrHC.Add(33.5M, 19M);
			ibkrHC.Add(34M, 19.4M);
			ibkrHC.Add(34.5M, 19.8M);
			ibkrHC.Add(35M, 20.2M);
			
			return ibkrHC;
			
		}
	}
		
}
using QuantConnect.Securities.Option;
namespace QuantConnect.Algorithm.CSharp {
	public partial class CollarAlgorithm : QCAlgorithm
	{
		public class TradePerfRec
		{
			public Symbol uSymbol;			// Underlying Symbol
			public bool isOpen;				// Is the trade ongoing (open)?
			public bool isInitializer;		// Is this the collar-initializing trade
			public int tradeRecCount;		// counter for trade records -- use in the single-stock use case
			public DateTime startDate;		// starting date for collar
			public DateTime endDate;		// ending date for the collar
			public string reasonForClose;	// reason why collar was killed (ITM options roll, etc.)
			public DateTime expDate;		// expiration date for collar
			public Symbol pSymbol;			// Put Symbol
			public Symbol cSymbol;			// Call Symbol
			public decimal pStrike;			// put strike
			public decimal cStrike;			// call strike
			public decimal pDelta;			// put Delta
			public decimal cDelta;			// all Delta
			public decimal uQty;			// number of underlying shares
			public decimal pQty;			// number of put contracts
			public decimal cQty;			// number of call contracts
			public decimal uStartPrice;		// Underlying Price when trade put on
			public decimal pStartPrice;		// Put Price when trade put on
			public decimal cStartPrice;		// Call Price when trade put on
			public decimal uEndPrice;		// Underlying Price when trade taken off
			public decimal pEndPrice;		// Put Price when trade taken off
			public decimal cEndPrice;		// Call Price when trade taken off
			public int	numDividends;		// # of dividends collected during the trade
			public decimal divIncome;		// $'s collected in Dividend income during the trade
			public decimal betaValue;		// beta value of underlying when trade put on
			public decimal RORThresh;		// Threshold for ROR
			public decimal ROCThresh;		// Threshold for ROC
			public string tradeCriteria;	// ROR or ROC
			public decimal ROR;				// ROR calculation from SSQR Matrix
			public decimal ROC;				// ROC calculation from SSQR Matrix
			public decimal stockADX;		// Average Directional Index Value
			public decimal stockADXR;		// Average Directional Index Rating
			public decimal stockOBV;		// On Balance Volume
			public decimal stockAD;			// Accumulation/Distribution
			public decimal stockADOSC;		// Accumulation/Distribution Oscillator
			public decimal stockSTO;		// Stochastic value
			public decimal stockVariance;	// Variance of underlying stock
		}
		
		public string ConvertTradePerfRec(List<TradePerfRec> tPR)
		{
			string tPRString = "";
			string jasonString = "";
			
			tPRString = ",^^^,"; 
			tPRString = tPRString + "uSymbol,";
			tPRString = tPRString + "isOpen,";
			tPRString = tPRString + "isInitializer,";
			tPRString = tPRString + "tradeRecCount,";
			tPRString = tPRString + "StartDate,";
			tPRString = tPRString + "EndDate,";
			tPRString = tPRString + "reasonForClose,";
			tPRString = tPRString + "Expiration,";
			tPRString = tPRString + "pSymbol,";
			tPRString = tPRString + "cSymbol,";
			tPRString = tPRString + "pStrike,";
			tPRString = tPRString + "cStrike,";
			tPRString = tPRString + "pDelta,";
			tPRString = tPRString + "cDelta,";
			tPRString = tPRString + "uQty,";
			tPRString = tPRString + "pQty,";
			tPRString = tPRString + "cQty,";
			tPRString = tPRString + "uStartPrice,";
			tPRString = tPRString + "pStartPrice,";
			tPRString = tPRString + "cStartPrice,";
			tPRString = tPRString + "uEndPrice,";
			tPRString = tPRString + "pEndPrice,";
			tPRString = tPRString + "cEndPrice,";
			tPRString = tPRString + "numDividends,";
			tPRString = tPRString + "divIncome,";
			tPRString = tPRString + "betaValue,";
			tPRString = tPRString + "RORThresh,";
			tPRString = tPRString + "ROCThresh,";
			tPRString = tPRString + "tradeCriteria,";
			tPRString = tPRString + "ROR,";
			tPRString = tPRString + "ROC,";
			tPRString = tPRString + "ADXValue,";
			tPRString = tPRString + "ADXRValue,";
			tPRString = tPRString + "OBVValue,";
			tPRString = tPRString + "ADValue,";
			tPRString = tPRString + "ADOSCValue,";
			tPRString = tPRString + "stochValue,";
			tPRString = tPRString + "stockVariance,";
			//tPRString = tPRString + Environment.NewLine;
			
			Debug(tPRString);
			
			var tPREnum = tPR.GetEnumerator();
			
			///////  NOTE:  Have to get the JASON formatted correctly.   Need one long string.  CHECK THIS
			while (tPREnum.MoveNext())
			{
				TradePerfRec thisPerfRec = tPREnum.Current;
				jasonString = "{";
				tPRString = ",^^^";
				foreach (var field in typeof(TradePerfRec).GetFields())	
				{
					//Console.WriteLine("{0} = {1}", field.Name, field.GetValue(thisPerfRec));
					jasonString = jasonString + "\"" + field.Name + "\":\"" + field.GetValue(thisPerfRec) + "\"";
					tPRString = tPRString  + ", " + field.GetValue(thisPerfRec);
				}
				jasonString = jasonString + "}," + Environment.NewLine;
				
				Debug(tPRString);
			}
			
			return jasonString;
		}

	}
}