Overall Statistics
Total Trades
30
Average Win
0.21%
Average Loss
-0.31%
Compounding Annual Return
-12.871%
Drawdown
1.300%
Expectancy
-0.278
Net Profit
-1.238%
Sharpe Ratio
-4.092
Probabilistic Sharpe Ratio
3.724%
Loss Rate
57%
Win Rate
43%
Profit-Loss Ratio
0.69
Alpha
-0.047
Beta
-0.038
Annual Standard Deviation
0.022
Annual Variance
0
Information Ratio
-2.996
Tracking Error
0.399
Treynor Ratio
2.321
Total Fees
$30.00
Estimated Strategy Capacity
$50000.00
Lowest Capacity Asset
MSFT 31EL5FBC61VMU|MSFT R735QTJ8XC9X
#region imports
from AlgorithmImports import *
#endregion
from datetime import timedelta
from random import random
import random
import pandas as pd
import numpy as np
import scipy
import matplotlib as mpl
import matplotlib.pyplot as plt
import math

class LongStrangleAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 3, 30)
        self.SetEndDate(2020, 5, 1)
        self.SetCash(100000)
        
        option = self.AddOption("MSFT", Resolution.Minute)
        self.symbol = option.Symbol
        # set our strike/expiry filter for this option chain
        option.SetFilter(0, +5, timedelta(0), timedelta(60))
        # use the underlying equity GOOG as the benchmark
        
        self.SetBenchmark("MSFT")
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverseSelection(FineFundamentalUniverseSelectionModel(self.SelectCoarse, self.SelectFine))

        
        self.Averages()
    #Calculate mean of four numbers and add them into self.days
    def Averages(self):
        self.days = []
        for i in range(0, 4):
            x = random.randrange(30) 
            self.days.append(x)
        average2 = [i for i in self.days if i != 0]
        average2 = sum(average2)/len(average2)
        global day
        day = math.ceil(average2)
        self.Log(str(day)) 
        self.Log(str(self.days))

    

    #Add ticker MSFT(for testing) into the universe        
    def SelectCoarse(self, coarse):
        tickers = ["MSFT"]
        return [Symbol.Create(x, SecurityType.Equity, Market.USA) for x in tickers]

    #Define when ticker gets to trade(x days before announcement)
    def SelectFine(self, fine):
        for x in fine:
            self.Debug("Symbol:" + x.SecurityReference.SecuritySymbol +", Filling date:" + x.EarningReports.FileDate.strftime("%m/%d/%Y, %H:%M:%S"))            
        self.Log("the day value is: " + str(day)) 
        return [x for x in fine if self.Time >= x.EarningReports.FileDate - timedelta(days=day) and self.Time < x.EarningReports.FileDate]
        
        
    def OnData(self,slice):
        if self._changes is None: return
        optionchain = slice.OptionChains
        for i in slice.OptionChains:
            if i.Key != self.symbol: continue
            chains = i.Value
            contract_list = [x for x in chains]
            # if there is no contracts in this optionchain, pass the instance
            if (slice.OptionChains.Count == 0) or (len(contract_list) == 0): return   
             # if there is no securities in portfolio, trade the options 
        for security in self._changes.AddedSecurities:
            if self.Portfolio.Invested: return
            self.TradeOptions(optionchain)

        for security in self._changes.RemovedSecurities:
            if security.Invested:
                self.Sell(self.call.Symbol ,1)
                self.Sell(self.put.Symbol ,1)
                self.Debug("sold" + str(self.Time))

        self._changes = None

           
                
    def TradeOptions(self,optionchain):
    
        for i in optionchain:
            if i.Key != self.symbol: continue
            chain = i.Value
            # sorted the optionchain by expiration date and choose the furthest date
            expiry = sorted(chain,key = lambda x: x.Expiry, reverse=True)[0].Expiry
            # filter the call options from the contracts expires on that date
            call = [i for i in chain if i.Expiry == expiry and i.Right == 0]
            # sorted the contracts according to their strike prices 
            call_contracts = sorted(call,key = lambda x: x.Strike)    
            if len(call_contracts) == 0: continue
            # choose the deep OTM call option
            self.call = call_contracts[-1]
            # select the put options which have the same expiration date with the call option 
            # sort the put options by strike price
            put_contracts = sorted([i for i in chain if i.Expiry == expiry and i.Right == 1], key = lambda x: x.Strike)
            # choose the deep OTM put option
            self.put = put_contracts[0]
                    
            self.Buy(self.call.Symbol ,1)
            self.Buy(self.put.Symbol ,1)
            self.Debug("Bought" + str(self.Time))
    
    def OnOrderEvent(self, orderEvent):
        #self.Log(str(orderEvent))
        pass
  

    def OnSecuritiesChanged(self, changes):
        self._changes = changes