Overall Statistics
Total Trades
2
Average Win
0%
Average Loss
0%
Compounding Annual Return
33.667%
Drawdown
0.500%
Expectancy
0
Net Profit
0%
Sharpe Ratio
3.157
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0.011
Beta
0.476
Annual Standard Deviation
0.062
Annual Variance
0.004
Information Ratio
-2.818
Tracking Error
0.068
Treynor Ratio
0.41
Total Fees
$0.50
using System;
using QuantConnect.Orders;
using QuantConnect.Securities.Option;

namespace QuantConnect.Securities
{
    /// <summary>
    /// Represents a simple option margining model. 
    /// </summary>
    /// <remarks>
    /// Options are not traded on margin. Margin requirements exist though for those portfolios with short positions. 
    /// Current implementation covers only single long/naked short option positions.
    /// </remarks>
    public class IBOptionMarginModel : ISecurityMarginModel
    {
        // initial margin
        private decimal _optionMarginRequirement = 1;
        private decimal _nakedPositionMarginRequirement = 0.1m;
        private decimal _nakedPositionMarginRequirementOTM = 0.2m;

        /// <summary>
        /// Initializes a new instance of the <see cref="IBOptionMarginModel"/>
        /// </summary>
        public IBOptionMarginModel()
        {
        }

        /// <summary>
        /// Gets the current leverage of the security
        /// </summary>
        /// <param name="security">The security to get leverage for</param>
        /// <returns>The current leverage in the security</returns>
        public virtual decimal GetLeverage(Security security)
        {
            // Options are not traded on margin
            return 1;
        }

        /// <summary>
        /// Sets the leverage for the applicable securities, i.e, options.
        /// </summary>
        /// <param name="security"></param>
        /// <param name="leverage">The new leverage</param>
        public virtual void SetLeverage(Security security, decimal leverage)
        {
            // Options are leveraged products and different leverage cannot be set by user.
            throw new InvalidOperationException("Options are leveraged products and different leverage cannot be set by user");
        }

        /// <summary>
        /// Gets the total margin required to execute the specified order in units of the account currency including fees
        /// </summary>
        /// <param name="security">The security to compute initial margin for</param>
        /// <param name="order">The order to be executed</param>
        /// <returns>The total margin in terms of the currency quoted in the order</returns>
        public virtual decimal GetInitialMarginRequiredForOrder(Security security, Order order)
        {
            //Get the order value from the non-abstract order classes (MarketOrder, LimitOrder, StopMarketOrder)
            //Market order is approximated from the current security price and set in the MarketOrder Method in QCAlgorithm.
            var orderFees = security.FeeModel.GetOrderFee(security, order);
            var value = order.GetValue(security);
            var orderValue = value * GetInitialMarginRequirement(security, value);

            return orderValue + Math.Sign(orderValue) * orderFees;
        }

        /// <summary>
        /// Gets the margin currently alloted to the specified holding
        /// </summary>
        /// <param name="security">The security to compute maintenance margin for</param>
        /// <returns>The maintenance margin required for the </returns>
        public virtual decimal GetMaintenanceMargin(Security security)
        {
            return security.Holdings.AbsoluteHoldingsCost*GetMaintenanceMarginRequirement(security, security.Holdings.HoldingsCost);
        }

        /// <summary>
        /// Gets the margin cash available for a trade
        /// </summary>
        /// <param name="portfolio">The algorithm's portfolio</param>
        /// <param name="security">The security to be traded</param>
        /// <param name="direction">The direction of the trade</param>
        /// <returns>The margin available for the trade</returns>
        public virtual decimal GetMarginRemaining(SecurityPortfolioManager portfolio, Security security, OrderDirection direction)
        {
            var holdings = security.Holdings;

            if (direction == OrderDirection.Hold)
            {
                return portfolio.MarginRemaining;
            }

            //If the order is in the same direction as holdings, our remaining cash is our cash
            //In the opposite direction, our remaining cash is 2 x current value of assets + our cash
            if (holdings.IsLong)
            {
                switch (direction)
                {
                    case OrderDirection.Buy:
                        return portfolio.MarginRemaining;

                    case OrderDirection.Sell:
                        return 
                            // portion of margin to close the existing position
                            GetMaintenanceMargin(security) +
                            // portion of margin to open the new position
                            security.Holdings.AbsoluteHoldingsValue * GetInitialMarginRequirement(security, security.Holdings.HoldingsValue) +
                            portfolio.MarginRemaining;
                }
            }
            else if (holdings.IsShort)
            {
                switch (direction)
                {
                    case OrderDirection.Buy:
                        return
                            // portion of margin to close the existing position
                            GetMaintenanceMargin(security) +
                            // portion of margin to open the new position
                            security.Holdings.AbsoluteHoldingsValue * GetInitialMarginRequirement(security, security.Holdings.HoldingsValue) +
                            portfolio.MarginRemaining;

                    case OrderDirection.Sell:
                        return portfolio.MarginRemaining;
                }
            }

            //No holdings, return cash
            return portfolio.MarginRemaining;
        }

        /// <summary>
        /// The percentage of an order's absolute cost that must be held in free cash in order to place the order
        /// </summary>
        public decimal GetInitialMarginRequirement(Security security)
        {
            return GetInitialMarginRequirement(security, security.Holdings.HoldingsValue);
        }

        /// <summary>
        /// The percentage of the holding's absolute cost that must be held in free cash in order to avoid a margin call
        /// </summary>
        public decimal GetMaintenanceMarginRequirement(Security security)
        {
            return GetMaintenanceMarginRequirement(security, security.Holdings.HoldingsValue);
        }

        /// <summary>
        /// The percentage of an order's absolute cost that must be held in free cash in order to place the order
        /// </summary>
        protected decimal GetInitialMarginRequirement(Security security, decimal holding)
        {
            return GetMarginRequirement(security, holding);
        }

        /// <summary>
        /// The percentage of the holding's absolute cost that must be held in free cash in order to avoid a margin call
        /// </summary>
        protected decimal GetMaintenanceMarginRequirement(Security security, decimal holding)
        {
            return GetMarginRequirement(security, holding);
        }

        /// <summary>
        /// Private method takes option security and its holding and returns required margin. Method considers all short positions naked. 
        /// </summary>
        /// <param name="security">Option security</param>
        /// <param name="value">Holding value</param>
        /// <returns></returns>
        private decimal GetMarginRequirement(Security security, decimal value)
        {
            var option = (Option.Option)security;

            if (option.Close == 0m ||
                option.StrikePrice == 0m ||
                option.Underlying == null ||
                option.Underlying.Close == 0m)
            {
                return 0m;
            }

            if (value > 0m)
            {
                return _optionMarginRequirement;
            }
            else
            {
                var absValue = -value;
                var optionProperties = (OptionSymbolProperties)option.SymbolProperties;
                var underlying = option.Underlying;

                // inferring ratios of the option and its underlying to get underlying security value
                var multiplierRatio = underlying.SymbolProperties.ContractMultiplier / optionProperties.ContractMultiplier;
                var quantityRatio = optionProperties.ContractUnitOfTrade;
                var priceRatio = underlying.Close / option.Close;
                var underlyingValueRatio = multiplierRatio * quantityRatio * priceRatio;

                // calculating underlying security value less out-of-the-money amount
                var amountOTM = option.Right == OptionRight.Call ? 
                                Math.Max(0, option.StrikePrice - underlying.Close):
                                Math.Max(0, underlying.Close - option.StrikePrice);
                var priceRatioOTM = amountOTM / option.Close;
                var underlyingValueRatioOTM = multiplierRatio * quantityRatio * priceRatioOTM;

                return _optionMarginRequirement + Math.Max(_nakedPositionMarginRequirement * underlyingValueRatio,
                                                          _nakedPositionMarginRequirementOTM * underlyingValueRatio - underlyingValueRatioOTM);
            }
        }
    }
}                        
namespace Quantconnect
{
	public partial class OptionSellAlgo : QCAlgorithm
	{
		string _symbol = "VXX";
		Symbol _equitySymbol;
		Symbol _optionSymbol;

		private Slice lastSlice = null;
		private bool orderedOnce = false;

		public override void Initialize(){
			SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);
			SetStartDate(2014, 3, 1);
            SetEndDate(2014, 3, 5);
            //Each contract requires approximately 75% of the sale price. Look into creating own margin model
            //At 3/3 Contract of VXX at ~45 required 3550
            SetCash(10000);

            var equity = AddEquity(_symbol, Resolution.Minute);
            _equitySymbol = equity.Symbol;

            Securities[_symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn);

            var option = AddOption(_symbol);
            option.MarginModel = new IBOptionMarginModel();
            _optionSymbol = option.Symbol;

            option.SetFilter(universe =>
            	//Select the data source using a universe that includes weekly options expiring within a month
            	from symbol in universe.Expiration(TimeSpan.FromDays(20), TimeSpan.FromDays(30)).IncludeWeeklys()
            	//Filter the data Only Calls
            	where symbol.ID.OptionRight == OptionRight.Call && 
            	//Between 25 and 30%
            	(symbol.ID.StrikePrice - universe.Underlying.Price) / universe.Underlying.Price <= 0.30m &&
            	(symbol.ID.StrikePrice - universe.Underlying.Price) / universe.Underlying.Price >= 0.25m
            	//Select and return the option symbols
            	select symbol);

            Schedule.On(DateRules.EveryDay(_symbol), TimeRules.At(9, 35), () =>{
            	ConsiderTrade();
            });
		}

		public override void OnData(Slice data){
			if (IsWarmingUp) {return;}
			lastSlice = data;
		}

		public override void OnEndOfDay(){
			if (lastSlice == null) {return;}
			Debug(String.Format("{0} closed at {1}", _symbol, lastSlice.Bars[_symbol].Close.ToString("#.####")));
		}

		private void ConsiderTrade(){
			Debug("Considering trade");
			if (orderedOnce || lastSlice == null || lastSlice.Bars == null 
				|| !lastSlice.Bars.ContainsKey(_symbol)) {return;}
			OrderCallOption(lastSlice);
		}

		public void OrderCallOption(Slice slice){
			Debug("Ordering Call Option");
			OptionChain chain;

			//Output the entire chain to the chain variable
			//Then use the from to filter only the option that we want
			//The current filter is finding the first call strike under market price expiring today
			if (slice.OptionChains.TryGetValue(_optionSymbol, out chain)){
				var contracts = (
					from optionContract in chain.OrderByDescending(x => x.Strike)
					where optionContract.Strike > chain.Underlying.Price
					select optionContract
				).Take(200);

				//Loop through the entire chain and display it
				//Later on enhance this to pick the correct option based off margin and other factors
				OptionContract contract = null;
				foreach (OptionContract _contract in contracts){
					Decimal pctOtm = ((_contract.Strike - _contract.UnderlyingLastPrice) / _contract.UnderlyingLastPrice)*100;
					Debug(String.Format("Chain=>Option Contract. Strike {0}, ULPrice={1}, Bid={2}, Ask={3}, Expiry={4} {5}, {6}%",
						_contract.Strike,
						_contract.UnderlyingLastPrice,
						_contract.BidPrice,
						_contract.AskPrice,
						_contract.Expiry,
						_contract.Expiry.DayOfWeek.ToString(),
						pctOtm.ToString("#.####")
						));
					if (contract == null) { contract = _contract; }
				}

				if ((contract != null) && !orderedOnce){
					//orderedOnce = true;
					int numContracts = -1;
					string message = String.Format("Order Option Contract. Strike {0} x {1}, ULPrice={2}, Bid={3}, Ask={4}, Expiry={5} {6}",numContracts,contract.Strike,contract.UnderlyingLastPrice,contract.BidPrice,contract.AskPrice,contract.Expiry,contract.Expiry.DayOfWeek.ToString());
					Debug(message);
					MarketOrder(contract.Symbol, numContracts);
				}
				else
					Debug("No Option Contract Found");
			}
			else
				Debug("No Option Contract Found [TryGetValue]");
		}

		public override void OnOrderEvent(OrderEvent fill)
		{
			string message = String.Format("Order {0} {1} x {2} at {3} commission={4} OrderId={5}",
        		  fill.Status.ToString(),
        		  fill.FillQuantity,
        		  fill.Symbol,
        		  fill.FillPrice,
        		  fill.OrderFee,
        		  fill.OrderId);
			Debug(message);
		}
	}
}