Overall Statistics |
Total Trades 10 Average Win 0% Average Loss 0% Compounding Annual Return 11.223% Drawdown 0.300% Expectancy 0 Net Profit 0.555% Sharpe Ratio 7.295 Probabilistic Sharpe Ratio 97.248% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.113 Beta 0.262 Annual Standard Deviation 0.017 Annual Variance 0 Information Ratio 2.123 Tracking Error 0.04 Treynor Ratio 0.47 Total Fees $40.50 |
from QuantConnect.Securities.Option import OptionPriceModels from datetime import timedelta import decimal as d #import pandas as pd class PutMarginCalc(QCAlgorithm): def Initialize(self): self.SetStartDate(2017, 1, 6) self.SetEndDate(2017, 1, 24) self.SetCash(1000000) self.Log("PERIOD: JAN 2017") # ---------------------------------------------------------------------- # Algo params # ---------------------------------------------------------------------- self.MIN_EXPIRY = 40 # min num of days to expiration => for uni selection self.MAX_EXPIRY = 55 # max num of days to expiration => for uni selection self.MIN_DELTA = .21 #lower delta = lower risk = less returns self.MAX_DELTA = .40 #higher delta = higher risk = more returns self._no_K = 25 # no of strikes around ATM => for uni selection self.resol = Resolution.Minute # Resolution.Minute #Options only supports minute currently self.tkr = "SPY" self.Lev = d.Decimal(1.0) self.single_trade_portfolio = .2 #max portfolio value to place one single trade self.single_trade_margin = .5 #max margin value to place one single trade # add underlying Equity equity = self.AddEquity(self.tkr, self.resol) equity.SetDataNormalizationMode(DataNormalizationMode.Raw) # IMPORTANT: default self.equity_symbol = equity.Symbol # Add options option = self.AddOption(self.tkr, self.resol) option.SetDataNormalizationMode(DataNormalizationMode.Raw) # IMPORTANT: default self.option_symbol = option.Symbol # filter options option.SetFilter(self.UniverseFunc) # option.SetFilter(-2, +2, timedelta(0), timedelta(30)) #seed greeks option.PriceModel = OptionPriceModels.CrankNicolsonFD() # both European & American, automatically self.SetWarmUp(TimeSpan.FromDays(7)) # timedelta(7) self.call, self.put = None, None def OnData(self, slice): if self.IsWarmingUp: return if not self.HourMinuteIs(10, 1): return ##trade once a day max self._assignedOption = False if not self.Portfolio.Invested or self.Portfolio.GetBuyingPower(self.tkr) > self.Portfolio.TotalPortfolioValue * self.single_trade_portfolio: # select contract #self.Log("get contracts") self.get_contracts(slice) if (not self.put): return #unit_price = self.put.UnderlyingLastPrice * d.Decimal(100.0) #unit_price = self.Securities[self.equity_symbol].Price * d.Decimal(100.0) unit_price = self.put.Strike * d.Decimal(100.0) qty = int((self.Portfolio.GetBuyingPower(self.tkr) * self.single_trade_margin) / unit_price) bp = str(self.Portfolio.GetBuyingPower(self.tkr)) tv = str(self.Portfolio.TotalPortfolioValue) mr = str(self.Portfolio.MarginRemaining) mu = str(self.Portfolio.TotalMarginUsed) cash = str(self.Portfolio.Cash) #settled only u_cash = str(self.Portfolio.UnsettledCash) #settled only #blah = str(self.CalculateOrderQuantity(self.tkr, .2)) #Calculates for buying shares, not contracts self.Debug("Starting BP: " + bp + " Margin Remaining: " + mr + " Margin Used: " + mu) self.Debug("Selling puts: " + str(qty) + "@" + str(self.put.Strike)) if self.put is not None: order = self.MarketOrder(self.put.Symbol, -qty) bp = str(self.Portfolio.GetBuyingPower(self.tkr)) mr = str(self.Portfolio.MarginRemaining) mu = str(self.Portfolio.TotalMarginUsed) self.Debug("Ending BP: " + bp + " Margin Remaining: " + mr + " Margin Used: " + mu) def get_contracts(self, slice): for kvp in slice.OptionChains: if kvp.Key != self.option_symbol: continue optionchain = kvp.Value # option contracts for each 'subscribed' symbol/key puts = [x for x in optionchain if x.Right == 1] contracts_by_T = sorted(puts, key = lambda x: x.Expiry, reverse = True) if not contracts_by_T: return self.expiry = contracts_by_T[0].Expiry.date() # furthest expiry slice_T = [i for i in puts if i.Expiry.date() == self.expiry] sorted_contracts = sorted(slice_T, key = lambda x: x.Strike, reverse = False) self.put = puts[0] if puts else None #self.Log("found contract: " + str(self.put)) def UniverseFunc(self, universe): return universe.IncludeWeeklys()\ .Strikes(-self._no_K, self._no_K)\ .Expiration(timedelta(self.MIN_EXPIRY), timedelta(self.MAX_EXPIRY)) # ---------------------------------------------------------------------- # Other ancillary fncts # ---------------------------------------------------------------------- def OnOrderEvent(self, orderEvent): # self.Log("Order Event -> {}" .format(orderEvent)) pass def TimeIs(self, day, hour, minute): return self.Time.day == day and self.Time.hour == hour and self.Time.minute == minute def HourMinuteIs(self, hour, minute): return self.Time.hour == hour and self.Time.minute == minute