Overall Statistics
Total Trades
8
Average Win
32.60%
Average Loss
-21.43%
Compounding Annual Return
-2.394%
Drawdown
39.300%
Expectancy
0.261
Net Profit
-2.587%
Sharpe Ratio
0.162
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
1.52
Alpha
0.076
Beta
0.005
Annual Standard Deviation
0.469
Annual Variance
0.22
Information Ratio
0.186
Tracking Error
0.825
Treynor Ratio
14.891
Total Fees
$72.00
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from datetime import timedelta

### <summary>
### This example demonstrates how to add options for a given underlying equity security.
### It also shows how you can prefilter contracts easily based on strikes and expirations, and how you
### can inspect the option chain to pick a specific option contract to trade.
### </summary>
### <meta name="tag" content="using data" />
### <meta name="tag" content="options" />
### <meta name="tag" content="filter selection" />
class BasicTemplateOptionsAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2017, 1, 1)
        self.SetEndDate(2018, 1, 30)
        self.SetCash(100000)
        

        self.AddEquity("SPXL", Resolution.Minute)
        self.AddEquity("SPXS", Resolution.Minute)

        option = self.AddOption("SPXL")
        self.option_symbol_bull = option.Symbol

        # set our strike/expiry filter for this option chain
        option.SetFilter(-1, +1, timedelta(180), timedelta(720))

        # use the underlying equity as the benchmark
        self.SetBenchmark("SPXL")
        
        option_bear = self.AddOption("SPXS")
        self.option_symbol_bear = option_bear.Symbol

        #self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Monday), self.TimeRules.At(10, 0), self.Rebalance)

        # set our strike/expiry filter for this option chain
        option_bear.SetFilter(-1, +1, timedelta(180), timedelta(720))

    def OnData(self,slice):
        
        price_bull = 12
        price_bear = 13

        weight_bull_init = 0.33333
        weight_bear_init = 0.66667
        weight_bull = (round((weight_bull_init*100000/(price_bull*100)), 0))
        weight_bear = (round((weight_bear_init*100000/(price_bear*100)), 0))

        self.Log(f"Bull: {weight_bull}") #Print out the current number of options bull
        self.Log(f"Bear: {weight_bear}") #Print out the current number of options bear
        
        self.TradeOptions(slice, weight_bull, weight_bear) 
        
    def TradeOptions(self, slice, weight_bull, weight_bear):
        if self.Portfolio.Invested: return

        chain = slice.OptionChains.GetValue(self.option_symbol_bull)
        if chain is None:
            return

        # we sort the contracts to find at the money (ATM) contract with farthest expiration
        contracts_put = sorted(sorted(sorted(chain, \
            key = lambda x: abs(chain.Underlying.Price - x.Strike)), \
            key = lambda x: x.Expiry, reverse=True), \
            key = lambda x: x.Right, reverse=True)
            
        chain2 = slice.OptionChains.GetValue(self.option_symbol_bull)
        if chain2 is None:
            return    

        contracts_call = sorted(sorted(sorted(chain2, \
            key = lambda x: abs(chain2.Underlying.Price - x.Strike)), \
            key = lambda x: x.Expiry, reverse=True), \
            key = lambda x: x.Right, reverse=False)

        chain3 = slice.OptionChains.GetValue(self.option_symbol_bear)
        if chain3 is None:
            return

        # we sort the contracts to find at the money (ATM) contract with farthest expiration
        contracts_bear_put = sorted(sorted(sorted(chain3, \
            key = lambda x: abs(chain3.Underlying.Price - x.Strike)), \
            key = lambda x: x.Expiry, reverse=True), \
            key = lambda x: x.Right, reverse=True)

        chain4 = slice.OptionChains.GetValue(self.option_symbol_bear)
        if chain4 is None:
            return
        
        # we sort the contracts to find at the money (ATM) contract with farthest expiration
        contracts_bear_call = sorted(sorted(sorted(chain4, \
            key = lambda x: abs(chain4.Underlying.Price - x.Strike)), \
            key = lambda x: x.Expiry, reverse=True), \
            key = lambda x: x.Right, reverse=False)

        # if found, trade it
        if len(contracts_put) == 0: return
        symbol_bull_put = contracts_put[0].Symbol
        self.MarketOrder(symbol_bull_put, weight_bull)
        #self.MarketOnCloseOrder(symbol_bull_put, -1)

        if len(contracts_call) == 0: return
        symbol_bull_call = contracts_call[0].Symbol
        self.MarketOrder(symbol_bull_call, -weight_bull)
        #self.MarketOnCloseOrder(symbol_bull_call, 1)

        if len(contracts_bear_put) == 0: return
        symbol_bear_put = contracts_bear_put[0].Symbol
        self.MarketOrder(symbol_bear_put, weight_bear)
        #self.MarketOnCloseOrder(symbol_bear_put, -1)

        if len(contracts_bear_call) == 0: return
        symbol_bear_call = contracts_bear_call[0].Symbol
        self.MarketOrder(symbol_bear_call, -weight_bear)
        #self.MarketOnCloseOrder(symbol_bear_call, 1)

    def OnOrderEvent(self, orderEvent):
        self.Log(str(orderEvent))
        
    # def Rebalance(self):
    #     calendar = self.TradingCalendar.GetDaysByType(TradingDayType.OptionExpiration, self.Time, self.EndDate)
    #     expiries = [i.Date for i in calendar]
    #     if len(expiries) == 0: return
    #     self.lastest_expiry = expiries[0]

    #     if (self.lastest_expiry - self.Time).days <= 5:
    #         self.SetHoldings("OEF", 1)