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