Overall Statistics
Total Trades
3162
Average Win
0.12%
Average Loss
-0.02%
Compounding Annual Return
14.226%
Drawdown
17.600%
Expectancy
5.714
Net Profit
364.239%
Sharpe Ratio
1.569
Probabilistic Sharpe Ratio
96.006%
Loss Rate
11%
Win Rate
89%
Profit-Loss Ratio
6.52
Alpha
0.094
Beta
0.187
Annual Standard Deviation
0.076
Annual Variance
0.006
Information Ratio
-0.101
Tracking Error
0.144
Treynor Ratio
0.636
Total Fees
$3162.50
Estimated Strategy Capacity
$11000000.00
Lowest Capacity Asset
TLT SGNKIKYGE9NP
# 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.Framework")

from QuantConnect.Algorithm.Framework.Alphas import *
from Portfolio.EqualWeightingPortfolioConstructionModel import *

class AccumulativeInsightPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel):
    '''Provides an implementation of IPortfolioConstructionModel that allocates percent of account
    to each insight, defaulting to 3%.
    For insights of direction InsightDirection.Up, long targets are returned and
    for insights of direction InsightDirection.Down, short targets are returned.
    By default, no rebalancing shall be done.
    Rules:
        1. On active Up insight, increase position size by percent
        2. On active Down insight, decrease position size by percent
        3. On active Flat insight, move by percent towards 0
        4. On expired insight, and no other active insight, emits a 0 target'''

    def __init__(self,  rebalance = None, portfolioBias = PortfolioBias.Long, percent = 0.04):
        '''Initialize a new instance of AccumulativeInsightPortfolioConstructionModel
        Args:
            rebalance: Rebalancing parameter. If it is a timedelta, date rules or Resolution, it will be converted into a function.
                              If None will be ignored.
                              The function returns the next expected rebalance time for a given algorithm UTC DateTime.
                              The function returns null if unknown, in which case the function will be called again in the
                              next loop. Returning current time will trigger rebalance.
            portfolioBias: Specifies the bias of the portfolio (Short, Long/Short, Long)
            percent: percent of portfolio to allocate to each position'''
        super().__init__(rebalance)
        self.portfolioBias = portfolioBias
        self.percent = abs(percent)
        self.sign = lambda x: -1 if x < 0 else (1 if x > 0 else 0)

    def DetermineTargetPercent(self, activeInsights):
        '''Will determine the target percent for each insight
        Args:
            activeInsights: The active insights to generate a target for'''
        percentPerSymbol = {}

        insights = sorted(self.InsightCollection.GetActiveInsights(self.currentUtcTime), key=lambda insight: insight.GeneratedTimeUtc)

        for insight in insights:
            targetPercent = 0
            if insight.Symbol in percentPerSymbol:
                targetPercent = percentPerSymbol[insight.Symbol]
                if insight.Direction == InsightDirection.Flat:
                    # We received a Flat
                    # if adding or subtracting will push past 0, then make it 0
                    if abs(targetPercent) < self.percent:
                        targetPercent = 0
                    else:
                        # otherwise, we flatten by percent
                        targetPercent += (-self.percent if targetPercent > 0 else self.percent)
            targetPercent += self.percent * insight.Direction

            # adjust to respect portfolio bias
            if self.portfolioBias != PortfolioBias.Long and self.sign(targetPercent) != self.portfolioBias:
                targetPercent = 0

            percentPerSymbol[insight.Symbol] = targetPercent

        return dict((insight, percentPerSymbol[insight.Symbol]) for insight in activeInsights)

    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'''
        self.currentUtcTime = algorithm.UtcTime
        return super().CreateTargets(algorithm, insights)
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
import numpy as np
from itertools import groupby

class AlphaFiveUSTreasuries(QCAlgorithm):

    def Initialize(self):

        #1. Required: Five years of backtest history
        self.SetStartDate(2005, 1, 1)
        self.SetStartDate(2010, 1, 1)
    
        #2. Required: Alpha Streams Models:
     #   self.SetBrokerageModel(BrokerageName.AlphaStreams)
    
        #3. Required: Significant AUM Capacity
        self.SetCash(25000)

        #4. Required: Benchmark to SPY
        self.AddEquity("SPY", Resolution.Daily)
        self.SetBenchmark("SPY")
        Benchmark = "QQQ"
        
        #self.SetPortfolioConstruction(AccumulativeInsightPortfolioConstructionModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
       # self.SetExecution(TradeExecution()))
        
        #Market Indicators
        self.spy = "SPY"
        self.iwm = "IWM"
        self.mdy = "MDY"
        self.qqq = "QQQ"
        self.vix = "VIX"
        
        self.assets = ["QQQ","TLT"]
        #self.assets = ['QQQ', 'FDN', 'TLT', 'TLH']
        self.symbols = {}
        
        self.portfolioValue = RollingWindow[Decimal](500)
        self.timeDelta    = int(self.GetParameter("timeDelta"))

        
        self.SetWarmup(500)
        
        # Add Equity ------------------------------------------------ 
        for i in range(len(self.assets)):
            self.symbols[self.assets[i]] = self.AddEquity(self.assets[i],Resolution.Minute).Symbol 
                
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.AfterMarketOpen(Benchmark, 30), self.EveryDayAfterMarketOpen)
        
        
        # Stock Selector
       # self.AddUniverse(self.Coarse, self.Fine)
       # self.activelyTrading = []
       # self.weight = 0
       # self.numberOfSymbolsCoarse = 500
       # self.exposureToSector = 2
        self.lastMonth = -1
    
    def Coarse(self, coarse):
        if self.Time.month == self.lastMonth:
            return Universe.Unchanged
        self.lastMonth = self.Time.month
        
        allCoarse = [x for x in coarse if x.HasFundamentalData and x.Price > 1 and x.Volume > 1]
        finalCoarse = sorted(allCoarse, key = lambda x: x.DollarVolume, reverse = True)
        
        return [x.Symbol for x in finalCoarse][:self.numberOfSymbolsCoarse]
    
    def Fine(self, fine):
        
        filteredSymbols = []
        sortedBySector = [x for x in fine]
        for code, g in groupby(sortedBySector, lambda x: x.AssetClassification.MorningstarSectorCode):
            for x in sorted(g, key = lambda x: x.ValuationRatios.PERatio, reverse = True)[:self.exposureToSector]:
                filteredSymbols.append(x.Symbol)
            
        return filteredSymbols[:2]
        
    def EveryDayAfterMarketOpen(self):
        if not self.Portfolio.Invested:
            insights = []
            for ticker, symbol in self.symbols.items():
                insights.append( Insight.Price(symbol, timedelta(days=(int(self.GetParameter("timeDelta")))), InsightDirection.Up, 0.01, None, None, 1/len(self.symbols)) )
            self.EmitInsights(insights)
        else:
            qb = self 
            #==============================
            # Initialize instance of Random Forest Regressor
            regressor = RandomForestRegressor(n_estimators=100, min_samples_split=5, random_state = 1990)
    
            # Fetch history on our universe
            df = qb.History(qb.Securities.Keys, 500, Resolution.Hour)
            
            # Get train/test data
            returns = df.unstack(level=1).close.transpose().pct_change().dropna()
            X = returns
            y = [x for x in qb.portfolioValue][-X.shape[0]:]
            X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 1990)
            
            # Fit regressor
            regressor.fit(X_train, y_train)
            
            # Get long-only predictions
            weights = regressor.feature_importances_
            symbols = returns.columns[np.where(weights)]
            selected = zip(symbols, weights)
            # ==============================
            
            insights = []
            for symbol, weight in selected:
                insights.append( Insight.Price(symbol, timedelta(days=(int(self.GetParameter("timeDelta")))), InsightDirection.Up, 0.01, None, None, weight) )
            self.EmitInsights(insights)
        
    def OnData(self, data):
        self.portfolioValue.Add(self.Portfolio.TotalPortfolioValue)
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 TrailingStopRiskManagementModel(RiskManagementModel):
    '''Provides an implementation of IRiskManagementModel that limits the maximum possible loss
    measured from the highest unrealized profit'''
    def __init__(self, maximumDrawdownPercent = 0.04):
        '''Initializes a new instance of the TrailingStopRiskManagementModel class
        Args:
            maximumDrawdownPercent: The maximum percentage drawdown allowed for algorithm portfolio compared with the highest unrealized profit, defaults to 5% drawdown'''
        self.maximumDrawdownPercent = -abs(maximumDrawdownPercent)
        self.trailingHighs = dict()
        self.lastDay = -1
        
        self.percentGain = 0.005

    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'''
            
        if algorithm.Time.day == self.lastDay:
            return []
        self.lastDay = algorithm.Time.day
        
        riskAdjustedTargets = list()

        for kvp in algorithm.Securities:
            symbol = kvp.Key
            security = kvp.Value
            percentChange = algorithm.Securities[symbol].Holdings.UnrealizedProfitPercent / 0.01

            # Add newly invested securities
            if symbol not in self.trailingHighs:
                self.trailingHighs[symbol] = security.Close    # Set to average holding cost
                continue
            
            # Remove if not invested
            if not security.Invested and symbol in self.trailingHighs:
                try:
                    self.trailingHighs.pop(symbol, None)
                except:
                    continue
                continue
            
            if percentChange.is_integer() and percentChange > 0:
                self.trailingHighs[symbol] = security.Close
            

            # Check for new highs and update - set to tradebar high
            # if self.trailingHighs[symbol] < security.High:
            #     self.trailingHighs[symbol] = security.High
            #     continue

            # Check for securities past the drawdown limit
            securityHigh = self.trailingHighs[symbol]
            if securityHigh == 0:
                riskAdjustedTargets.append(PortfolioTarget(symbol, 0))
                continue
            
            drawdown = (security.Low / securityHigh) - 1

            if drawdown < self.maximumDrawdownPercent:
                # liquidate
                riskAdjustedTargets.append(PortfolioTarget(symbol, 0))

        return riskAdjustedTargets
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from System import *
from QuantConnect import *
from QuantConnect.Indicators import *
from QuantConnect.Data import *
from QuantConnect.Data.Market import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Portfolio import *
import numpy as np
from datetime import datetime


class VolumeWeightedAveragePriceExecutionModel(ExecutionModel):
    '''Execution model that submits orders while the current market price is more favorable that the current volume weighted average price.'''

    def __init__(self):
        '''Initializes a new instance of the VolumeWeightedAveragePriceExecutionModel class'''
        self.targetsCollection = PortfolioTargetCollection()
        self.symbolData = {}

        # Gets or sets the maximum order quantity as a percentage of the current bar's volume.
        # This defaults to 0.01m = 1%. For example, if the current bar's volume is 100,
        # then the maximum order size would equal 1 share.
        self.MaximumOrderQuantityPercentVolume = 0.02

    def Execute(self, algorithm, targets):
        '''Executes market orders if the standard deviation of price is more
       than the configured number of deviations in the favorable direction.
       Args:
           algorithm: The algorithm instance
           targets: The portfolio targets'''

        # update the complete set of portfolio targets with the new targets
        self.targetsCollection.AddRange(targets)

        # for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
        if self.targetsCollection.Count > 0:
            for target in self.targetsCollection.OrderByMarginImpact(algorithm):
                symbol = target.Symbol

                # calculate remaining quantity to be ordered
                unorderedQuantity = OrderSizing.GetUnorderedQuantity(algorithm, target)

                # fetch our symbol data containing our VWAP indicator
                data = self.symbolData.get(symbol, None)
                if data is None: return

                # check order entry conditions
                if self.PriceIsFavorable(data, unorderedQuantity):
                    # adjust order size to respect maximum order size based on a percentage of current volume
                    orderSize = OrderSizing.GetOrderSizeForPercentVolume(data.Security, self.MaximumOrderQuantityPercentVolume, unorderedQuantity)

                    if orderSize != 0:
                        algorithm.MarketOrder(symbol, orderSize)

            self.targetsCollection.ClearFulfilled(algorithm)


    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 removed in changes.RemovedSecurities:
            # clean up removed security data
            if removed.Symbol in self.symbolData:
                if self.IsSafeToRemove(algorithm, removed.Symbol):
                    data = self.symbolData.pop(removed.Symbol)
                    algorithm.SubscriptionManager.RemoveConsolidator(removed.Symbol, data.Consolidator)

        for added in changes.AddedSecurities:
            if added.Symbol not in self.symbolData:
                self.symbolData[added.Symbol] = SymbolData(algorithm, added)


    def PriceIsFavorable(self, data, unorderedQuantity):
        '''Determines if the current price is more than the configured
       number of standard deviations away from the mean in the favorable direction.'''
        if unorderedQuantity > 0:
            if data.Security.BidPrice < data.VWAP:
                return True
        else:
            if data.Security.AskPrice > data.VWAP:
                return True

        return False

    def IsSafeToRemove(self, algorithm, symbol):
        '''Determines if it's safe to remove the associated symbol data'''
        # confirm the security isn't currently a member of any universe
        return not any([kvp.Value.ContainsMember(symbol) for kvp in algorithm.UniverseManager])

class SymbolData:
    def __init__(self, algorithm, security):
        self.Security = security
        self.Consolidator = algorithm.ResolveConsolidator(security.Symbol, security.Resolution)
        name = algorithm.CreateIndicatorName(security.Symbol, "VWAP", security.Resolution)
        self.vwap = IntradayVwap(name)
        algorithm.RegisterIndicator(security.Symbol, self.vwap, self.Consolidator)

    @property
    def VWAP(self):
       return self.vwap.Value

class IntradayVwap:
    '''Defines the canonical intraday VWAP indicator'''
    def __init__(self, name):
        self.Name = name
        self.Value = 0.0
        self.lastDate = datetime.min
        self.sumOfVolume = 0.0
        self.sumOfPriceTimesVolume = 0.0

    @property
    def IsReady(self):
        return self.sumOfVolume > 0.0

    def Update(self, input):
        '''Computes the new VWAP'''
        success, volume, averagePrice = self.GetVolumeAndAveragePrice(input)
        if not success:
            return self.IsReady

        # reset vwap on daily boundaries
        if self.lastDate != input.EndTime.date():
            self.sumOfVolume = 0.0
            self.sumOfPriceTimesVolume = 0.0
            self.lastDate = input.EndTime.date()

        # running totals for Σ PiVi / Σ Vi
        self.sumOfVolume += volume
        self.sumOfPriceTimesVolume += averagePrice * volume

        if self.sumOfVolume == 0.0:
           # if we have no trade volume then use the current price as VWAP
           self.Value = input.Value
           return self.IsReady

        self.Value = self.sumOfPriceTimesVolume / self.sumOfVolume
        return self.IsReady

    def GetVolumeAndAveragePrice(self, input):
        '''Determines the volume and price to be used for the current input in the VWAP computation'''

        if type(input) is Tick:
            if input.TickType == TickType.Trade:
                return True, float(input.Quantity), float(input.LastPrice)

        if type(input) is TradeBar:
            if not input.IsFillForward:
                averagePrice = float(input.High + input.Low + input.Close) / 3
                return True, float(input.Volume), averagePrice

        return False, 0.0, 0.0