Overall Statistics
Total Trades
13
Average Win
0.01%
Average Loss
-0.01%
Compounding Annual Return
-0.232%
Drawdown
0.000%
Expectancy
-0.211
Net Profit
-0.018%
Sharpe Ratio
-4.09
Loss Rate
60%
Win Rate
40%
Profit-Loss Ratio
0.97
Alpha
0
Beta
-0.002
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-5.773
Tracking Error
0.156
Treynor Ratio
1.1
Total Fees
$3.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 datetime import timedelta

class IronButterflyAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2017, 4, 1)
        self.SetEndDate(2017, 4, 30)
        self.SetCash(10000000)
        equity = self.AddEquity("GOOG", Resolution.Minute)
        option = self.AddOption("GOOG", Resolution.Minute)
        self.symbol = option.Symbol
        option.SetFilter(-10, 10, timedelta(0), timedelta(30))
        # use the underlying equity GOOG as the benchmark
        self.SetBenchmark(equity.Symbol)
        
    def OnData(self,slice):

        if self.Portfolio["GOOG"].Quantity != 0:
            self.Liquidate()
        if not self.Portfolio.Invested and self.Time.hour != 0 and self.Time.minute != 0: 
            for i in slice.OptionChains:
                if i.Key != self.symbol: continue
                chain = i.Value
                contract_list = [x for x in chain]
                # if there is no optionchain or no contracts in this optionchain, pass the instance
                if (slice.OptionChains.Count == 0) or (len(contract_list) == 0): 
                    return  
                # sorted the optionchain by expiration date and choose the furthest date
                expiry = sorted(chain,key = lambda x: x.Expiry)[-1].Expiry
                # filter the call and put options from the contracts
                call = [i for i in chain if i.Right == 0 and i.Expiry == expiry]
                put = [i for i in chain if i.Right == 1 and  i.Expiry == expiry]
                # sorted the contracts according to their strike prices 
                call_contracts = sorted(call,key = lambda x: x.Strike)    
                put_contracts = sorted(put,key = lambda x: x.Strike)    
                if len(call_contracts) == 0 or len(put_contracts) == 0 : continue
                # Sell 1 ATM Put 
                atm_put = sorted(put_contracts,key = lambda x: abs(chain.Underlying.Price - x.Strike))[0]
                self.Sell(atm_put.Symbol ,1)
                # Sell 1 ATM Call
                atm_call = sorted(call_contracts,key = lambda x: abs(chain.Underlying.Price - x.Strike))[0]
                self.Sell(atm_call.Symbol ,1)
                # Buy 1 OTM Call 
                otm_call = call_contracts[-1]
                self.Buy(otm_call.Symbol ,1)
                # Buy 1 OTM Put 
                otm_put = put_contracts[0]
                self.Buy(otm_put.Symbol ,1)
                
                self.trade_contracts = [atm_put, atm_call, otm_call, otm_put]
    
    def OnOrderEvent(self, orderEvent):
        self.Log(str(orderEvent))