Overall Statistics
Total Orders
13
Average Win
0.01%
Average Loss
-0.01%
Compounding Annual Return
-0.238%
Drawdown
0.000%
Expectancy
-0.601
Start Equity
10000000
End Equity
9998191
Net Profit
-0.018%
Sharpe Ratio
-36.357
Sortino Ratio
-27.769
Probabilistic Sharpe Ratio
1.146%
Loss Rate
80%
Win Rate
20%
Profit-Loss Ratio
1.00
Alpha
-0.014
Beta
-0.002
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-8.93
Tracking Error
0.146
Treynor Ratio
8.398
Total Fees
$9.00
Estimated Strategy Capacity
$8000.00
Lowest Capacity Asset
GOOCV 30IZW4DA2M6KM|GOOCV VP83T1ZUHROL
Portfolio Turnover
0.06%
#region imports
from AlgorithmImports import *
#endregion
# 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.set_start_date(2017, 4, 1)
        self.set_end_date(2017, 4, 30)
        self.set_cash(10000000)
        equity = self.add_equity("GOOG", Resolution.MINUTE)
        option = self.add_option("GOOG", Resolution.MINUTE)
        self.symbol = option.symbol
        option.set_filter(-10, 10, timedelta(0), timedelta(30))
        # use the underlying equity GOOG as the benchmark
        self.set_benchmark(equity.symbol)
        
    def on_data(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.option_chains:
                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.option_chains.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 on_order_event(self, orderEvent):
        self.log(str(orderEvent))