Overall Statistics |
Total Trades 2 Average Win 0% Average Loss 0% Compounding Annual Return 19.447% Drawdown 1.000% Expectancy 0 Net Profit 0% Sharpe Ratio 3.338 Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.233 Beta 0.655 Annual Standard Deviation 0.029 Annual Variance 0.001 Information Ratio 13.522 Tracking Error 0.022 Treynor Ratio 0.15 Total Fees $0.50 |
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, 8); SetEndDate(2014,3, 12); //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(10490); var equity = AddEquity(_symbol, Resolution.Minute); _equitySymbol = equity.Symbol; Securities[_symbol].SetDataNormalizationMode(DataNormalizationMode.TotalReturn); SetSecurityInitializer(new OptionInitializer()); var option = AddOption(_symbol); _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 5 and 20% (symbol.ID.StrikePrice - universe.Underlying.Price) / universe.Underlying.Price <= 0.20m && (symbol.ID.StrikePrice - universe.Underlying.Price) / universe.Underlying.Price >= 0.05m //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); } } }
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; //Initializes Logging /// <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; Console.WriteLine("multiplierRatio : " + multiplierRatio.ToString("0.00")); var quantityRatio = optionProperties.ContractUnitOfTrade; Console.WriteLine("quantityRatio : " + quantityRatio.ToString("0.00")); Console.WriteLine("underlying.Close: " + underlying.Close.ToString() + " | option.Close: " + option.Close.ToString()); var underlyingValueRatio = multiplierRatio * quantityRatio * underlying.Close; Console.WriteLine("underlyingValueRatio: " + underlyingValueRatio.ToString("0.00")); // 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); Console.WriteLine("option.StrikePrice: " + option.StrikePrice.ToString() + " | underlying.Close: " + underlying.Close.ToString() + " | amountOTM: " + amountOTM.ToString("0.00")); var underlyingValueRatioOTM = multiplierRatio * quantityRatio * amountOTM; Console.WriteLine("underlyingValueRatioOTM: " + underlyingValueRatioOTM.ToString("0.00")); var marginReq = option.Close + Math.Max(_nakedPositionMarginRequirement * underlyingValueRatio, _nakedPositionMarginRequirementOTM * underlyingValueRatio - underlyingValueRatioOTM); Console.WriteLine("GetMarginRequirement: " + marginReq.ToString("0.00")); return marginReq; } } } }
using System; using QuantConnect.Orders; using QuantConnect.Securities.Option; namespace Quantconnect { public class OptionInitializer : ISecurityInitializer { public void Initialize(Security security, bool seedSecurity) { if (security is Option){ security.MarginModel = new IBOptionMarginModel(); } } } }