Overall Statistics
Total Trades
302
Average Win
0.29%
Average Loss
-0.25%
Compounding Annual Return
28.248%
Drawdown
4.600%
Expectancy
0.225
Net Profit
8.746%
Sharpe Ratio
2.239
Loss Rate
43%
Win Rate
57%
Profit-Loss Ratio
1.14
Alpha
0.461
Beta
-10.865
Annual Standard Deviation
0.111
Annual Variance
0.012
Information Ratio
2.062
Tracking Error
0.111
Treynor Ratio
-0.023
Total Fees
$667.58
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect.Data.UniverseSelection import *
from QuantConnect.Indicators import ExponentialMovingAverage
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

import decimal as d

class UniverseSelectionModel(FundamentalUniverseSelectionModel):

    def __init__(self,
                 universeCount = 20,
                 universeSettings = None,
                 securityInitializer = None):

        super().__init__(False, universeSettings, securityInitializer)
        self.universeCount = universeCount
        self.averages = {}

    def SelectCoarse(self, algorithm, coarse):
        # We are going to use a dictionary to refer the object that will keep the moving averages
        for cf in coarse:
            if cf.Symbol not in self.averages:
                self.averages[cf.Symbol] = SymbolData(cf.Symbol)

            # Updates the SymbolData object with price and volume
            avg = self.averages[cf.Symbol]
            avg.update(cf.EndTime, cf.Price, cf.Volume)
        
        # Filter the values of the dict based on criteria
        # In this case, we only want up-trending securities
        filtered_values = list(filter(lambda x: x.is_uptrend, self.averages.values()))
        
        # Sort the values of the dict: we want those with greater DollarVolume
        sorted_values = sorted(filtered_values, key = lambda x: x.volume, reverse = True)
        
        return [ x.symbol for x in sorted_values[:self.universeCount] ]

# class used to improve readability of the coarse selection function
class SymbolData:
    def __init__(self, symbol):
        self.symbol = symbol
        self.priceSMA = SimpleMovingAverage(10)
        self.volSMA = SimpleMovingAverage(50)
        self.priceWin = RollingWindow[float](5)
        self.is_uptrend = False

    def update(self, time, price, volume):
        self.price = price
        self.volume = volume
        self.priceWin.Add(price)
        self.priceSMA.Update(time, price)
        self.volSMA.Update(time, volume)
        if self.priceSMA.IsReady and self.volSMA.IsReady and self.priceWin.IsReady:
            MAprice = self.priceSMA.Current.Value
            MAvol = self.volSMA.Current.Value
            
            # Here we can add the criteria for our universe
            # current price > 10-days moving average price
            # current volume > 10-days moving average volume
            # current price > yesterday's close
            # current price > 10-days maximum price
            
            self.is_uptrend =  price > 20 and price > MAprice and volume > MAvol and price > self.priceWin[1] and price > max(self.priceWin)
from UniverseSelection import UniverseSelectionModel
from Alphas.ConstantAlphaModel import ConstantAlphaModel
from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from Risk.NullRiskManagementModel import NullRiskManagementModel

class BasicTemplateFrameworkAlgorithm(QCAlgorithmFramework):

    def Initialize(self):

        # Set requested data resolution
        self.UniverseSettings.Resolution = Resolution.Daily

        self.SetStartDate(2018, 6, 1)   # Set Start Date
        self.SetEndDate(2018, 10, 1)    # Set End Date
        self.SetCash(100000)            # Set Strategy Cash

        count = 5
        self.SetUniverseSelection(UniverseSelectionModel(universeCount = count))
        self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, TimeSpan.FromMinutes(20), 0.025, None))
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        self.SetExecution(ImmediateExecutionModel())
        self.SetRiskManagement(NullRiskManagementModel())
        
    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status == OrderStatus.Filled:
            self.Debug("Purchased Stock: {0}".format(orderEvent.Symbol))
            
        #for x in sorted_values[:self.universeCount]:
            #self.Log('symbol: ' + str(x.symbol.Value)
            #+ ' close price: ' + str(x.price)
            #+ ' volume: ' + str(x.volume)
            #+ '  mean price: ' + str(x.priceSMA.Current.Value)
            #+ '  mean vol: ' + str(x.volSMA.Current.Value))
        
    def OnEndOfDay(self):
        
        self.Liquidate()
from clr import AddReference
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Indicators")
AddReference("QuantConnect.Common")

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

class HistoricalReturnsAlphaModel(AlphaModel):
    '''Uses Historical returns to create insights.'''

    def __init__(self, *args, **kwargs):
        '''Initializes a new default instance of the HistoricalReturnsAlphaModel class.
        Args:
            lookback(int): Historical return lookback period
            resolution: The resolution of historical data'''
        self.lookback = kwargs['lookback'] if 'lookback' in kwargs else 1
        self.resolution = kwargs['resolution'] if 'resolution' in kwargs else Resolution.Daily
        self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(self.resolution), self.lookback)
        self.symbolDataBySymbol = {}

    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 symbol, symbolData in self.symbolDataBySymbol.items():
            if symbolData.CanEmit:

                direction = InsightDirection.Flat
                magnitude = symbolData.Return
                if magnitude > 0: direction = InsightDirection.Up
                if magnitude < 0: direction = InsightDirection.Down

                insights.append(Insight.Price(symbol, self.predictionInterval, direction, magnitude, None))

        return insights

    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'''

        # clean up data for removed securities
        for removed in changes.RemovedSecurities:
            symbolData = self.symbolDataBySymbol.pop(removed.Symbol, None)
            if symbolData is not None:
                symbolData.RemoveConsolidators(algorithm)

        # initialize data for added securities
        symbols = [ x.Symbol for x in changes.AddedSecurities ]
        history = algorithm.History(symbols, self.lookback, self.resolution)
        if history.empty: return

        tickers = history.index.levels[0]
        for ticker in tickers:
            symbol = SymbolCache.GetSymbol(ticker)

            if symbol not in self.symbolDataBySymbol:
                symbolData = SymbolData(symbol, self.lookback)
                self.symbolDataBySymbol[symbol] = symbolData
                symbolData.RegisterIndicators(algorithm, self.resolution)
                symbolData.WarmUpIndicators(history.loc[ticker])


class SymbolData:
    '''Contains data specific to a symbol required by this model'''
    def __init__(self, symbol, lookback):
        self.Symbol = symbol
        self.ROC = RateOfChange('{}.ROC({})'.format(symbol, lookback), lookback)
        self.Consolidator = None
        self.previous = 0

    def RegisterIndicators(self, algorithm, resolution):
        self.Consolidator = algorithm.ResolveConsolidator(self.Symbol, resolution)
        algorithm.RegisterIndicator(self.Symbol, self.ROC, self.Consolidator)

    def RemoveConsolidators(self, algorithm):
        if self.Consolidator is not None:
            algorithm.SubscriptionManager.RemoveConsolidator(self.Symbol, self.Consolidator)

    def WarmUpIndicators(self, history):
        for tuple in history.itertuples():
            self.ROC.Update(tuple.Index, tuple.close)

    @property
    def Return(self):
        return float(self.ROC.Current.Value)

    @property
    def CanEmit(self):
        if self.previous == self.ROC.Samples:
            return False

        self.previous = self.ROC.Samples
        return self.ROC.IsReady

    def __str__(self, **kwargs):
        return '{}: {:.2%}'.format(self.ROC.Name, (1 + self.Return)**252 - 1)