Overall Statistics
Total Trades
216
Average Win
0.16%
Average Loss
-0.14%
Compounding Annual Return
5.511%
Drawdown
1.400%
Expectancy
0.062
Net Profit
0.915%
Sharpe Ratio
1.051
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
1.16
Alpha
0.258
Beta
-13.549
Annual Standard Deviation
0.041
Annual Variance
0.002
Information Ratio
0.666
Tracking Error
0.041
Treynor Ratio
-0.003
Total Fees
$466.72
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(20)
        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 AlphaModel 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.Minute

        self.SetStartDate(2018, 6, 1)   # Set Start Date
        self.SetEndDate(2018, 8, 1)     # Set End Date
        self.SetCash(100000)            # Set Strategy Cash
        self.AddEquity("SPY")
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 10), self.rebalance)

        count = 5
        self.SetUniverseSelection(UniverseSelectionModel(universeCount = count))
        self.SetAlpha(ConstantAlphaModel())
        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))
        
    def rebalance(self):
        self.Liquidate()        
        
    # def OnEndOfDay(self):
    #     for i in self.Securities.Keys:
    #         self.Liquidate(i)
from clr import AddReference
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")

from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from datetime import timedelta
from QuantConnect.Algorithm.Framework.Alphas import AlphaModel, Insight, InsightType, InsightDirection


class ConstantAlphaModel(AlphaModel):

    def __init__(self):
        self.period = timedelta(hours=6)
        self.securities = []
        self.insightsTimeBySymbol = {}
        self.ShouldEmitInsight = True
        self.Name = 'ConstantAlphaModel'


    def Update(self, algorithm, data):
        insights = []
        if self.ShouldEmitInsight:
            for security in self.securities:
                if security.Symbol.Value != "SPY":
                    insights.append(Insight.Price(security.Symbol, timedelta(hours=6), InsightDirection.Up))
                    self.ShouldEmitInsight = False
        # if self.removedSecurities:
        #     for i in self.removedSecurities:
        #         insights.append(Insight.Price(i.Symbol, timedelta(minutes=10), InsightDirection.Flat))
        return insights


    def OnSecuritiesChanged(self, algorithm, changes):
        self.removedSecurities = []
        for added in changes.AddedSecurities:
            self.securities.append(added)
            self.ShouldEmitInsight = True

        # this will allow the insight to be re-sent when the security re-joins the universe
        for removed in changes.RemovedSecurities:
            self.removedSecurities.append(removed)
            self.ShouldEmitInsight = True
            if removed in self.securities:
                self.securities.remove(removed)
            if removed.Symbol in self.insightsTimeBySymbol:
                self.insightsTimeBySymbol.pop(removed.Symbol)