Overall Statistics
Total Trades
40
Average Win
3.25%
Average Loss
-5.06%
Compounding Annual Return
-99.987%
Drawdown
51.500%
Expectancy
-0.654
Net Profit
-49.632%
Sharpe Ratio
-0.882
Probabilistic Sharpe Ratio
0.006%
Loss Rate
79%
Win Rate
21%
Profit-Loss Ratio
0.64
Alpha
0.925
Beta
2.746
Annual Standard Deviation
1.133
Annual Variance
1.283
Information Ratio
-0.298
Tracking Error
1.002
Treynor Ratio
-0.364
Total Fees
$40.25
# 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.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Portfolio import PortfolioTarget
from QuantConnect.Algorithm.Framework.Risk import RiskManagementModel
from datetime import timedelta

class MaximumExpiryMarginRiskModel(RiskManagementModel):
    '''Provides an implementation of IRiskManagementModel that limits the unrealized profit per holding to the specified percentage'''

    def __init__(self, maximumExpiry = 30):
        '''Initializes a new instance of the MaximumUnrealizedProfitPercentPerSecurity class
        Args:
            maximumExpiry: The maximum number of days allowed till expiration. Defaults 30 days per security'''
        self.maximumExpiry = abs(maximumExpiry)

    def ManageRisk(self, algorithm, targets):
        '''Manages the algorithm's risk at each time step
        Args:
            algorithm: The algorithm instance
            targets: The current portfolio targets to be assessed for risk'''
        targets = []
        for kvp in algorithm.Securities:
            security = kvp.Value

            if not security.Invested:
                continue

            expiry = security.Holdings.Symbol.ID.Date
            if timedelta(days=self.maximumExpiry) >= expiry - algorithm.Time:
                # liquidate
                targets.append(PortfolioTarget(security.Symbol, 0))

        return targets
# 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.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Portfolio import PortfolioTarget
from QuantConnect.Algorithm.Framework.Risk import RiskManagementModel

class StopTakeUnrealizedRiskModel(RiskManagementModel):
    '''Provides an implementation of IRiskManagementModel that limits the unrealized profit per holding to the specified percentage'''

    def __init__(self, takeUnrealized = 0.05, stopUnrealized = 0.05):
        '''Initializes a new instance of the MaximumUnrealizedProfitPercentPerSecurity class
        Args:
            takeUnrealized: The maximum percentage unrealized profit allowed for any single security holding, defaults to 5% gain per security
            stopUnrealized: The maximum percentage unrealized Loss allowed for any single security holding, defaults to 5% drawdown per security'''
        self.takeUnrealized = abs(takeUnrealized)
        self.stopUnrealized = -1 * abs(stopUnrealized)

    def ManageRisk(self, algorithm, targets):
        '''Manages the algorithm's risk at each time step
        Args:
            algorithm: The algorithm instance
            targets: The current portfolio targets to be assessed for risk'''
        targets = []
        for kvp in algorithm.Securities:
            security = kvp.Value

            if not security.Invested:
                continue

            pnl = security.Holdings.UnrealizedProfitPercent 
            if (pnl > self.takeUnrealized) or (pnl < self.stopUnrealized):
                # liquidate
                targets.append(PortfolioTarget(security.Symbol, 0))

        return targets
from StopTakeUnrealizedRiskModel import StopTakeUnrealizedRiskModel
from MaximumExpiryMarginRiskModel import MaximumExpiryMarginRiskModel
from QuantConnect.Securities.Option import OptionPriceModels
from QuantConnect import Resolution
from QuantConnect import OptionRight
from datetime import date, datetime, timedelta
import numpy as np

class TachyonQuantumEngine(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 2, 1)
        self.SetEndDate(2020, 3, 1)
        self.SetCash(10000)
        
        self.alpha = CannaMaxLeverage()
        self.AddAlpha(self.alpha)
        
        self.risk = StopTakeUnrealizedRiskModel(0.20,0.40)
        self.AddRiskManagement(self.risk)
        self.risk2 = MaximumExpiryMarginRiskModel(45)
        self.AddRiskManagement(self.risk2)
        
        tickers = ['SPY','QQQQ'] #di quali ticker prendere le opzioni
        for x in tickers:
            self.option = self.AddOption(x, Resolution.Minute)
            self.option.SetFilter(-1, +1, 180, 900) 
            # set the pricing model for Greeks and volatility
            # find more pricing models https://www.quantconnect.com/lean/documentation/topic27704.html
            self.option.PriceModel = OptionPriceModels.CrankNicolsonFD()
            
        self.UniverseSettings.Resolution = Resolution.Minute
        
        self.SetExecution(ImmediateExecutionModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        self.Settings.FreePortfolioValuePercentage = 0.10
        # set the warm-up period for the pricing model
        self.SetWarmUp(TimeSpan.FromDays(4))
    
        

class CannaMaxLeverage(AlphaModel):
    def __init__(self):
        pass
    
    def Update(self, algorithm, data):
        if algorithm.IsWarmingUp or algorithm.Portfolio.Invested:
            return []
            
        
        #https://www.quantconnect.com/lean/documentation/topic24200.html
        chain = [x.Value for x in data.OptionChains]
        if len(chain):
            weight = 1/len(chain)
        else:
            return []
            
        contracts = [[]] * len(chain)
        for x in range(len(chain)):
            #https://www.quantconnect.com/lean/documentation/topic24233.html
            contracts[x] = [y for y in chain[x] if y.Right==OptionRight.Call and algorithm.Securities[y.Symbol].IsTradable]
            maxExpiry = sorted(contracts[x], key = lambda y: y.Expiry, reverse=True)[0]
            contracts[x] = [y for y in contracts[x] if y.Expiry==maxExpiry.Expiry]
        
        symbols = []
        for x in range(len(contracts)):
            qta = [0] * len(contracts[x])
            capacity = [0] * len(contracts[x])
            i = 0
            for y in contracts[x]:
                qta[i] = round(algorithm.CalculateOrderQuantity(y.Symbol, weight),0)
                capacity[i] = qta[i] * y.Greeks.Delta
                i = i+1
            imax = capacity.index(np.max(capacity))
            symbols.append(contracts[x][imax].Symbol)
        
        insights=[]
        if symbols != []:
            for x in symbols:
                insights.append(Insight.Price(x,timedelta(days=900), InsightDirection.Up))
        return insights
        
    def OnSecuritiesChange(self, algorithm, changes):
        for x in changes.RemovedSecurities:
            algorithm.RemoveSecurity(x.Symbol)
            for symbol in algorithm.Securities.Keys:
                if symbol.SecurityType == SecurityType.Option and symbol.Underlying == x.Symbol:
                    algorithm.RemoveSecurity(symbol)