Overall Statistics
Total Trades
756
Average Win
0.13%
Average Loss
-0.14%
Compounding Annual Return
-99.802%
Drawdown
33.400%
Expectancy
-0.436
Net Profit
-22.631%
Sharpe Ratio
-16.118
Probabilistic Sharpe Ratio
0%
Loss Rate
71%
Win Rate
29%
Profit-Loss Ratio
0.95
Alpha
-5.17
Beta
0.361
Annual Standard Deviation
0.303
Annual Variance
0.092
Information Ratio
-17.682
Tracking Error
0.321
Treynor Ratio
-13.509
Total Fees
$3170.90
# 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("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Indicators")

from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Alphas import *


class MovingAverageCrossAlphaModel(AlphaModel):
    '''Alpha model that uses an EMA cross to create insights'''

    def __init__(self,
                 fastPeriod = 12,
                 slowPeriod = 26,
                 resolution = Resolution.Daily):
        '''Initializes a new instance of the EmaCrossAlphaModel class
        Args:
            fastPeriod: The fast EMA period
            slowPeriod: The slow EMA period'''
        self.fastPeriod = fastPeriod
        self.slowPeriod = slowPeriod
        self.resolution = resolution
        self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(resolution), fastPeriod)
        self.symbolDataBySymbol = {}

        resolutionString = Extensions.GetEnumString(resolution, Resolution)
        self.Name = '{}({},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, resolutionString)
        

    def Update(self, algorithm, data):
        '''Updates this alpha model with the latest data from the algorithm.
        This is called each time the algorithm receives data for subscribed securities
        Args:
            algorithm: The algorithm instance
            data: The new data available
        Returns:
            The new insights generated'''
        insights = []
     
        for chain in data.FutureChains:
           
            contracts = [contract for contract in chain.Value]
            
            frontContract = contracts[0]
            
            symbol = frontContract.Symbol
            
            if chain.Key not in self.symbolDataBySymbol:
                self.symbolDataBySymbol[chain.Key] = SymbolData(algorithm, symbol, self.fastPeriod, self.slowPeriod, self.resolution)
            else:
                
                if symbol != self.symbolDataBySymbol[chain.Key].frontContractSymbol:
                    self.symbolDataBySymbol[chain.Key].frontContractSymbol = symbol
                    self.symbolDataBySymbol[chain.Key].WarmUp()
            
            symbolData = self.symbolDataBySymbol[chain.Key]
            
            bars = chain.Value.TradeBars
            if symbol in bars.Keys:
                bar = chain.Value.TradeBars[symbol]
                symbolData.Update(bar.Time, bar.Close)
           
                
            if symbolData.IsReady:

                if symbolData.ShortCrossOver:
                    insights.append(Insight(symbolData.frontContractSymbol, self.predictionInterval, InsightType.Price, InsightDirection.Down, -0.0025, 1.00, None, 0.05))
                    
                elif symbolData.LongCrossOver:
                    insights.append(Insight(symbolData.frontContractSymbol, self.predictionInterval, InsightType.Price, InsightDirection.Up, 0.0025, 1.00, None, 0.05))
                

        return insights


class SymbolData:
    '''Contains data specific to a symbol required by this model'''
    def __init__(self, algorithm, symbol, fastPeriod, slowPeriod, resolution):
        self.algorithm = algorithm
        self.frontContractSymbol = symbol
        self.resolution = resolution
        self.fastPeriod = fastPeriod
        self.slowPeriod = slowPeriod
        
        
        self.Fast = ExponentialMovingAverage(self.fastPeriod)
        self.Slow = ExponentialMovingAverage(self.slowPeriod)
        
        self.fastWindow = RollingWindow[IndicatorDataPoint](2)
        self.slowWindow = RollingWindow[IndicatorDataPoint](2)
        
        self.Fast.Updated += self.OnFastEMA
        self.Slow.Updated += self.OnSlowEMA
        
        self.WarmUp()
   
    
    def WarmUp(self):
        history = self.algorithm.History(self.frontContractSymbol, self.slowPeriod, self.resolution)
        if not history.empty:
            history = history.close.unstack(1)
            if not history.empty:
                df = history[self.frontContractSymbol].dropna()
                if not df.empty:
                    for time, close in df.iteritems():
                        self.Update(time[1], close)
 
        
    @property
    def IsReady(self):
        return self.fastWindow.IsReady and self.slowWindow.IsReady
        
        
    def Update(self, time, close):
        self.Fast.Update(time, close)
        self.Slow.Update(time, close)
    
    @property
    def LongCrossOver(self):
        return self.fastWindow[1].Value < self.slowWindow[1].Value \
                and self.fastWindow[0].Value > self.slowWindow[0].Value
    
    @property 
    def ShortCrossOver(self):
        return self.fastWindow[1].Value > self.slowWindow[1].Value \
                and self.fastWindow[0].Value < self.slowWindow[0].Value
        
     
    def OnFastEMA(self, sender, updated):
        if self.Fast.IsReady:
            self.fastWindow.Add(updated)
            
    def OnSlowEMA(self, sender, updated):
        if self.Slow.IsReady:
            self.slowWindow.Add(updated)
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from Portfolio.MeanVarianceOptimizationPortfolioConstructionModel import MeanVarianceOptimizationPortfolioConstructionModel
from Risk.MaximumDrawdownPercentPerSecurity import MaximumDrawdownPercentPerSecurity
from FuturesUniverseSelectionModel import FuturesUniverseSelectionModel
from ATRBasedPositionSizing import ATRBasedPositionSizing
from MovingAverageCrossAlphaModel import MovingAverageCrossAlphaModel

class MovingAverageCrossTrendFollowing(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)  # Set Start Date
        self.SetEndDate(2019, 1, 15)  # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        self.UniverseSettings.Resolution = Resolution.Minute
        self.SetUniverseSelection(FuturesUniverseSelectionModel(self.SelectFuturesSymbols))
        
        self.AddAlpha(MovingAverageCrossAlphaModel(50, 200, Resolution.Minute))
        
        self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel())
        self.SetExecution(ImmediateExecutionModel())

    def SelectFuturesSymbols(self, utcTime):
        tickers = [Futures.Indices.SP500EMini,
                  Futures.Grains.BlackSeaCornFinanciallySettledPlatts,
                  Futures.Grains.Wheat,
                  Futures.Grains.Corn,
                  Futures.Grains.Soybeans,
                  Futures.Grains.SoybeanMeal,
                  Futures.Grains.SoybeanOil,
                  Futures.Grains.Oats,
                  Futures.Currencies.USD,
                  Futures.Currencies.GBP,
                  Futures.Currencies.CAD,
                  Futures.Currencies.JPY,
                  Futures.Currencies.CHF,
                  Futures.Currencies.EUR,
                  Futures.Softs.Cocoa,
                  Futures.Dairy.CashSettledButter,
                  Futures.Dairy.CashSettledCheese,
                  Futures.Dairy.ClassIIIMilk,
                  Futures.Dairy.DryWhey,
                  Futures.Dairy.ClassIVMilk,
                  Futures.Dairy.NonfatDryMilk]
        return [ Symbol.Create(ticker, SecurityType.Future, Market.USA) for ticker in tickers]
from Selection.FutureUniverseSelectionModel import FutureUniverseSelectionModel
from datetime import date, timedelta

class FuturesUniverseSelectionModel(FutureUniverseSelectionModel):
    
    def __init__(self, select_future_chain_symbols):
        super().__init__(timedelta(1), select_future_chain_symbols)

    def Filter(self, filter):
        return (filter.FrontMonth())
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Indicators")

from System import *
from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Portfolio import *
from Portfolio.MinimumVariancePortfolioOptimizer import MinimumVariancePortfolioOptimizer
from datetime import timedelta
import numpy as np
import pandas as pd

### <summary>
### </summary>
class ATRBasedPositionSizing(PortfolioConstructionModel):
    def __init__(self,
                 riskFactor = 0.2,
                 lookbackPeriod = 100):
        """Initialize the model
        Args:
            lookback(int): Historical return lookback period
            period(int): The time interval of history price to calculate the weight
            resolution: The resolution of the history price
            optimizer(class): Method used to compute the portfolio weights"""
        self.atrs = {}
        self.lookbackPeriod = lookbackPeriod
        self.riskFactor = riskFactor
            
    def CreateTargets(self, algorithm, insights):
        """
        Create portfolio targets from the specified insights
        Args:
            algorithm: The algorithm instance
            insights: The insights to create portfolio targets from
        Returns:
            An enumerable of portfolio targets to be sent to the execution model
        """
        targets = []
        for insight in insights:
            symbol = insight.Symbol
            if symbol in self.atrs.keys():
                direction = 1 if InsightDirection.Up else -1
                price = algorithm.Securities[symbol].Price
                atr = self.atrs[symbol].Current.Value
                numberOfContracts = np.floor((direction * (self.riskFactor*algorithm.Portfolio.TotalPortfolioValue)/(atr*price )))
                target = PortfolioTarget(insight.Symbol, numberOfContracts)
                if target is not None:
                    targets.append(target)
        return targets

    def OnSecuritiesChanged(self, algorithm, changes):
        '''Event fired each time the we add/remove securities from the data feed
        Args:
            algorithm: The algorithm instance that experienced the change in securities
            changes: The security additions and removals from the algorithm'''
        for addedSecurity in changes.AddedSecurities:
            ticker = addedSecurity.Symbol
            if ticker not in self.atrs.keys():
                self.atrs[ticker] = algorithm.ATR(ticker, self.lookbackPeriod)