Overall Statistics |
Total Trades 27 Average Win 0.04% Average Loss -0.02% Compounding Annual Return -10.497% Drawdown 22.300% Expectancy 0.222 Net Profit -3.686% Sharpe Ratio 0.043 Loss Rate 54% Win Rate 46% Profit-Loss Ratio 1.65 Alpha 0.179 Beta -8.46 Annual Standard Deviation 0.503 Annual Variance 0.253 Information Ratio 0.006 Tracking Error 0.503 Treynor Ratio -0.003 Total Fees $4.25 |
using System.Drawing; using System.Threading; using System.Threading.Tasks; // Short Condor - the same as Short Strangle but with limited loss // sell 1 ATM Call and 1 ATM Put with the same expiration date // and on the same distance from the underlying price // then buy 1 OTM Call and 1 OTM Put to protect ourselves if market goes against us namespace QuantConnect { public partial class ShortCondor : QCAlgorithm { string iSymbol = "MSFT"; DateTime iTime; public override void Initialize() { SetCash(10000); SetStartDate(2018, 1, 1); SetEndDate(DateTime.Now.Date); SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage); AddEquity(iSymbol, Resolution.Minute); } public void OnData(TradeBars data) { if (IsMarketOpen(iSymbol) == false) { return; } if (IsNewBar(TimeSpan.FromHours(1)) == false) { return; } var price = Securities[iSymbol].Price; // If options were exercised and we were assigned to buy shares, sell them immediately if (Portfolio[iSymbol].Invested) { MarketOrder(iSymbol, -100); } if (Portfolio.Invested == false) { var contracts = OptionChainProvider.GetOptionContractList(iSymbol, Time); // Choose all contracts within a month and strike price $1 to $5 from current underlying price var atmCalls = from c in contracts where c.ID.OptionRight == OptionRight.Call where c.ID.StrikePrice - price < 3 && c.ID.StrikePrice - price > 1 where (c.ID.Date - Time).TotalDays < 35 && (c.ID.Date - Time).TotalDays > 0 select c; var atmPuts = from c in contracts where c.ID.OptionRight == OptionRight.Put where price - c.ID.StrikePrice < 3 && price - c.ID.StrikePrice > 1 where (c.ID.Date - Time).TotalDays < 35 && (c.ID.Date - Time).TotalDays > 0 select c; // Choose all contracts within a month and strike price $1 to $5 from current underlying price var otmCalls = from c in contracts where c.ID.OptionRight == OptionRight.Call where c.ID.StrikePrice - price < 7 && c.ID.StrikePrice - price > 5 where (c.ID.Date - Time).TotalDays < 35 && (c.ID.Date - Time).TotalDays > 0 select c; var otmPuts = from c in contracts where c.ID.OptionRight == OptionRight.Put where price - c.ID.StrikePrice < 7 && price - c.ID.StrikePrice > 5 where (c.ID.Date - Time).TotalDays < 35 && (c.ID.Date - Time).TotalDays > 0 select c; // Take ATM options with the MIN expiration date and MAX distance from underlying price var contractAtmCall = atmCalls .OrderBy(o => o.ID.Date) .ThenByDescending(o => o.ID.StrikePrice - price) .FirstOrDefault(); var contractAtmPut = atmPuts .OrderBy(o => o.ID.Date) .ThenByDescending(o => price - o.ID.StrikePrice) .FirstOrDefault(); // Take OTM options with the MIN expiration date and MAX distance from underlying price var contractOtmCall = otmCalls .OrderBy(o => o.ID.Date) .ThenByDescending(o => o.ID.StrikePrice - price) .FirstOrDefault(); var contractOtmPut = otmPuts .OrderBy(o => o.ID.Date) .ThenByDescending(o => price - o.ID.StrikePrice) .FirstOrDefault(); // If we found such options - open trade if (contractAtmCall != null && contractAtmPut != null && contractOtmCall != null && contractOtmPut != null) { AddOptionContract(contractAtmCall, Resolution.Minute); AddOptionContract(contractAtmPut, Resolution.Minute); AddOptionContract(contractOtmCall, Resolution.Minute); AddOptionContract(contractOtmPut, Resolution.Minute); MarketOrder(contractAtmCall, -1); MarketOrder(contractAtmPut, -1); MarketOrder(contractOtmCall, 1); MarketOrder(contractOtmPut, 1); } } } public bool IsNewBar(TimeSpan interval, int points = 1) { var date = Securities[iSymbol].LocalTime; if ((date - iTime).TotalSeconds > interval.TotalSeconds * points) { iTime = new DateTime(date.Ticks - date.Ticks % interval.Ticks, date.Kind); return true; } return false; } } }