Overall Statistics
Total Trades
1029
Average Win
0.02%
Average Loss
-0.78%
Compounding Annual Return
0.055%
Drawdown
4.800%
Expectancy
0.009
Net Profit
1.150%
Sharpe Ratio
0.063
Probabilistic Sharpe Ratio
0.000%
Loss Rate
2%
Win Rate
98%
Profit-Loss Ratio
0.03
Alpha
0.001
Beta
-0.003
Annual Standard Deviation
0.008
Annual Variance
0
Information Ratio
-0.401
Tracking Error
0.187
Treynor Ratio
-0.204
Total Fees
$670.00
# Your New Python File


class Probability():
    numerator = 0
    denominator = 0
    
    def value(self):
        if self.denominator > 0:
            return float(self.numerator)/float(self.denominator)
        else:
            return 0
    
    def update(self, success):
        self.denominator += 1
        if success:
            self.numerator += 1
            
    def __str__(self):
     return str(self.numerator) + "/" + str(self.denominator)
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
import pandas as pd

class OptimizedTachyonShield(QCAlgorithm):
    '''
        If SPY is within a certain % of its 52W high, write a call option that is a certain $ above the opening price.
        If the option gets assigned, do a limit order for covering at the assignment price.
        Pre
    '''
    
    # Paramaters
    callOtmAmount = 6
    withinYearlyHighPct = 10
    
    spy = None
    spyOption = None
    spyCoverOrderTicket = None
    yearlyHigh = None
    
    def Initialize(self):
        self.SetStartDate(2000, 1, 1)  # Set Start Date
        self.SetEndDate(2020, 11, 19)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        
        #self.callOtmAmount = int(self.GetParameter("callOtmAmount"))  # TODO deal with missing parameter
        
        self.spy = self.AddEquity("SPY", Resolution.Minute)
        self.spy.SetDataNormalizationMode(DataNormalizationMode.Raw) # Required for working with options
        self.spyOption = self.AddOption("SPY")
        # Include weekly options, only calls, strikes within underlying price + otmAmount, expiring in next 1 days
        self.spyOption.SetFilter( lambda u: u.IncludeWeeklys().CallsOnly().Strikes(self.callOtmAmount, self.callOtmAmount+2).Expiration(0, 1) )

        self.yearlyHigh = self.MAX(self.spy.Symbol, 252, Resolution.Daily)
        history = self.History(self.spy.Symbol, 252, Resolution.Daily)
        for bar in history.itertuples():
            self.yearlyHigh.Update(bar.Index[1], bar.high)
        self.Debug("SPY yearly high warmed up, value = " + str(self.yearlyHigh.Current.Value))

        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday), self.TimeRules.AfterMarketOpen("SPY", 1), self.OpeningBar)
        
        self.SetExecution(ImmediateExecutionModel())

    def OpeningBar(self):
        if not self.IsMarketOpen(self.spy.Symbol):
            self.Debug("Market not open, returning")
            return

        self.LogPortfolio()
        if self.Portfolio[self.spy.Symbol].Invested:
            self.Liquidate("SPY")
            '''
            if self.spyCoverOrderTicket is None:
                self.Debug("Assigned, placing limit order to cover")
                self.spyCoverOrderTicket = self.LimitOrder(self.spy.Symbol, -1 * self.Portfolio["SPY"].Quantity, self.Portfolio["SPY"].AveragePrice)
            return
            '''
        
        high = self.yearlyHigh.Current.Value
        if 100 * (high - self.Securities["SPY"].Close)/high > self.withinYearlyHighPct:
            self.Debug("Too far away from yearly high: " + str(self.Securities["SPY"].Close) + " vs " + str(high))
            return
        
        slice = self.CurrentSlice
        
        optionChain = slice.OptionChains.GetValue(self.spyOption.Symbol)
        if optionChain is None:
            self.Error(str(self.Time) + " No option chain found")
            return

        allContracts = [o for o in optionChain]
        expiringToday = [o for o in optionChain if o.Expiry.date() == self.Time.date()]
        sortedByStrike = sorted(expiringToday, key = lambda o: o.Strike)
        
        if len(sortedByStrike) > 0:
            self.MarketOrder(sortedByStrike[0].Symbol, -5)
        
    def OnOrderEvent(self, orderEvent):
        self.Debug(str(orderEvent))
        if not self.spyCoverOrderTicket is None and orderEvent.OrderId == self.spyCoverOrderTicket.OrderId and self.spyCoverOrderTicket.Status == OrderStatus.Filled:
            self.Debug("covered!")
            self.spyCoverOrderTicket = None
    
    def LogPortfolio(self):
        for symbol in self.Portfolio.Keys:
            holding = self.Portfolio[symbol]
            if holding.Invested:
                self.Debug(str(symbol) + " " + str(holding.Quantity) + " @ " + str(holding.AveragePrice))
    
    def LogContracts(self, optionChain):
        df = pd.DataFrame(
            [[x.Right,float(x.Strike),x.Expiry,float(x.BidPrice),float(x.AskPrice)] for x in optionChain],
            index=[x.Symbol.Value for x in optionChain],
            columns=['type(call 0, put 1)', 'strike', 'expiry', 'ask price', 'bid price']
        )
        
        self.Debug(str(df))