| Overall Statistics |
|
Total Trades 1163 Average Win 0.11% Average Loss -0.17% Compounding Annual Return 12.317% Drawdown 23.400% Expectancy 0.122 Net Profit 12.351% Sharpe Ratio 0.603 Probabilistic Sharpe Ratio 31.942% Loss Rate 31% Win Rate 69% Profit-Loss Ratio 0.63 Alpha 0.069 Beta 0.43 Annual Standard Deviation 0.204 Annual Variance 0.041 Information Ratio -0.005 Tracking Error 0.233 Treynor Ratio 0.285 Total Fees $1325.44 |
class TheSlippage(AlphaModel):
def __init__(self,
period = 30,
resolution = Resolution.Daily):
self.period = period
self.resolution = resolution
self.insightPeriod = Time.Multiply(Extensions.ToTimeSpan(self.resolution), self.period)
self.symbolDataBySymbol = {}
resolutionString = Extensions.GetEnumString(resolution, Resolution)
self.Name = '{}({},{})'.format(self.__class__.__name__, period, resolutionString)
def OnSecuritiesChanged(self, algorithm, changes):
symbols = [x.Symbol for x in changes.RemovedSecurities]
if len(symbols) > 0:
for subscription in algorithm.SubscriptionManager.Subscriptions:
if subscription.Symbol in symbols:
self.symbolDataBySymbol.pop(subscription.Symbol, None)
subscription.Consolidators.Clear()
addedSymbols = [x.Symbol for x in changes.AddedSecurities if x.Symbol not in self.symbolDataBySymbol]
if len(addedSymbols) == 0: return
history = algorithm.History(addedSymbols, self.period, self.resolution)
# initialize data for added securities
for symbol in addedSymbols:
if not history.empty:
ticker = SymbolCache.GetTicker(symbol)
if ticker not in history.index.levels[0]:
Log.Trace(f'VolAlp.OnSecuritiesChanged: {ticker} not found in history data frame.')
continue
'''
for tuple in history.loc[ticker].itertuples():
macd.Update(tuple.Index, tuple.close)
'''
self.symbolDataBySymbol[symbol] = SymbolData(symbol)
algorithm.Securities[symbol].SetSlippageModel(CustomSlippageModel(self))
class SymbolData:
'''Contains data specific to a symbol required by this model'''
def __init__(self, symbol):
self.Symbol = symbol
class CustomSlippageModel():
def __init__(self, algorithm):
self.algorithm = algorithm
def GetSlippageApproximation(self, asset, order):
# custom slippage math
slippage = asset.Price * d.Decimal(0.0001 * np.log10(2*float(order.AbsoluteQuantity)))
self.algorithm.Log("CustomSlippageModel: " + str(slippage))
return slippageclass TrailingStopRiskManagementModel(RiskManagementModel):
'''Provides an implementation of IRiskManagementModel that limits the maximum possible loss
measured from the highest unrealized profit'''
def __init__(self):
'''Initializes a new instance of the TrailingStopRiskManagementModel class'''
self.liquidated = set()
self.lastmonth=-1
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'''
month= algorithm.Time.month
if month!= self.lastmonth:
self.liquidated.clear()
self.lastmonth= month
#if different month clear all liquidations
riskAdjustedTargets = list()
for kvp in algorithm.Securities:
symbol = kvp.Key
security = kvp.Value
if security.Holdings.UnrealizedProfitPercent > 0.1 or security.Holdings.UnrealizedProfitPercent < -0.1 or security.Symbol in self.liquidated:
riskAdjustedTargets.append(PortfolioTarget(symbol, 0))
if algorithm.Securities[security.Symbol].Invested:
self.liquidated.add(security.Symbol)
return riskAdjustedTargetsfrom CustomUniverse import FundamentalUniverse
from CustomAlpha.Completed import LongHold
from CustomRiskManagement import takeprofit
from CustomerReconciliation import CurrentSlippageModel
from datetime import date, timedelta
class test (QCAlgorithm):
def Initialize(self):
self.SetStartDate(2019,7,25)
self.SetEndDate(2020,7, 25)
self.SetCash(1000000) # Set Strategy Cash
self.SetTimeZone(TimeZones.Chicago)
self.AddUniverseSelection(FundamentalUniverse.universe())
self.UniverseSettings.Resolution = Resolution.Minute
self.UniverseSettings.DataNormalizationMode=DataNormalizationMode.Raw
self.UniverseSettings.FillForward = True #Fill in empty data will next price
self.UniverseSettings.ExtendedMarketHours = False #Takes in account after hours data
self.UniverseSettings.MinimumTimeInUniverse = 1 # each equity has to spend at least 1 hour in universe selection process
self.UniverseSettings.Leverage=1
self.Settings.RebalancePortfolioOnInsightChanges = False;
self.Settings.RebalancePortfolioOnSecurityChanges = False;
self.SetBenchmark("SPY")
self.SetBrokerageModel(BrokerageName.AlphaStreams)
self.AddAlpha(LongHold.BuyHold())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetRiskManagement(takeprofit.TrailingStopRiskManagementModel())
self.SetExecution(ImmediateExecutionModel())
'''Slippage model not used'''from QuantConnect.Algorithm.Framework.Alphas import *
class BuyHold(AlphaModel):
def __init__(self,period = 30, resolution = Resolution.Daily):
self.period = period
self.resolution = resolution
self.decimal = 2
self.insightPeriod = Time.Multiply(Extensions.ToTimeSpan(self.resolution), self.period)
self.symbolDataBySymbol = {}
self.month=-1
resolutionString = Extensions.GetEnumString(resolution, Resolution)
self.Name = '{}({},{})'.format(self.__class__.__name__, period, resolutionString)
def Update(self, algorithm, data):
insights = []
if algorithm.Time.month == self.month:
return []
self.month = algorithm.Time.month
for symbol, SymbolData in self.symbolDataBySymbol.items():
insights.append(Insight.Price(symbol, timedelta(days=26), InsightDirection.Up))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
addedSymbols = [ x.Symbol for x in changes.AddedSecurities if x not in self.symbolDataBySymbol]
for y in changes.RemovedSecurities:
for subscription in algorithm.SubscriptionManager.Subscriptions:
if subscription in changes.RemovedSecurities:
self.symbolDataBySymbol.pop(subscription, None)
subscription.Consolidators.Clear()
if algorithm.Portfolio[y.Symbol].Invested:
algorithm.Liquidate(y.Symbol)
self.symbolDataBySymbol.pop(y.Symbol)
algorithm.RemoveSecurity(y.Symbol)
history = algorithm.History(addedSymbols, self.period, self.resolution)
for symbol in addedSymbols:
self.symbolDataBySymbol[symbol] = SymbolData(symbol)
class SymbolData:
'''Contains data specific to a symbol required by this model'''
def __init__(self, symbol):
self.Symbol = symbolfrom Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel
from QuantConnect.Data.Custom.SEC import *
from Selection.OptionUniverseSelectionModel import OptionUniverseSelectionModel
from datetime import timedelta, datetime
from math import ceil
from itertools import chain
import numpy as np
class universe(FundamentalUniverseSelectionModel):
def __init__(self, filterFineData = True, universeSettings = None, securityInitializer = None):
super().__init__(filterFineData, universeSettings, securityInitializer)
self.NumberOfSymbolsCoarse = 2500
self.NumberOfSymbolsFine = 250
self.NumberOfSymbolsInPortfolio = 10
self.lastmonth = -1
self.dollarVolumeBySymbol = {}
def SelectCoarse(self, algorithm, coarse):
month= algorithm.Time.month
if month == self.lastmonth:
return Universe.Unchanged
self.lastmonth= month
top = sorted([x for x in coarse if x.HasFundamentalData],
key=lambda x: x.DollarVolume, reverse=True)[:self.NumberOfSymbolsCoarse]
self.dollarVolumeBySymbol = { i.Symbol: i.DollarVolume for i in top }
return list(self.dollarVolumeBySymbol.keys())
def SelectFine(self, algorithm, fine):
self.debttoequityMaxAllowance = 1.2
self.priceAllowance = 180
filteredFine = [x for x in fine if x.CompanyReference.CountryId == "USA"
and x.Price > self.priceAllowance
and (x.CompanyReference.PrimaryExchangeID == "NYS" or x.CompanyReference.PrimaryExchangeID == "NAS")
and (algorithm.Time - x.SecurityReference.IPODate).days > 700
#and x.FinancialStatements.CashFlowStatement.ProvisionandWriteOffofAssets.ThreeMonths != 0
and (x.EarningReports.BasicAverageShares.ThreeMonths * x.EarningReports.BasicEPS.TwelveMonths * x.ValuationRatios.PERatio >= 5e10)
#and 0 <= (x.OperationRatios.TotalDebtEquityRatioGrowth.OneYear) <= self.debttoequityMaxAllowance #this value will change in accordance to S&P Momentum
#and x.FinancialStatements.BalanceSheet.AllowanceForDoubtfulAccountsReceivable.ThreeMonths <= 2.0 * x.FinancialStatements.CashFlowStatement.ProvisionandWriteOffofAssets.ThreeMonths
#and (x.FinancialStatements.IncomeStatement.ProvisionForDoubtfulAccounts.TwoMonths <= 1.0*x.FinancialStatements.CashFlowStatement.ProvisionandWriteOffofAssets.ThreeMonths)
]
self.ratingsDict = {}
for ticker in filteredFine:
rating = 0
'''Financial Strength'''
if (ticker.OperationRatios.QuickRatio.ThreeMonths) >= 1.0:
rating += 1
if 2.0 >= (ticker.OperationRatios.CurrentRatio.ThreeMonths) >= 1.2:
rating += 1
if (ticker.OperationRatios.TotalDebtEquityRatioGrowth.OneYear) <= 1.0:
rating += 1
if (ticker.OperationRatios.LongTermDebtEquityRatio.OneYear) < 1.0:
rating += 1
if (ticker.OperationRatios.InterestCoverage.ThreeMonths) >= 3.0:
rating += 1
'''Suitable Growth'''
if (ticker.ValuationRatios.SustainableGrowthRate) >= 0.07:
rating += 1
'''Industry Comparison'''
'''Management and Equity'''
if (ticker.OperationRatios.ROA.ThreeMonths) >= 0.05:
rating += 1
if (ticker.ValuationRatios.FCFRatio) >= 1:
rating += 1
'''Leverage and Liquidity'''
if (ticker.OperationRatios.LongTermDebtTotalCapitalRatio.OneYear) <= 0.4:
rating += 1
'''Fundamental Variables'''
if (ticker.ValuationRatios.PEGRatio) <= 1.0:
rating += 1
if (ticker.OperationRatios.ROE.ThreeMonths) >= 0.15:
rating += 1
'''Apply Rating'''
self.ratingsDict[ticker.Symbol] = rating
count = len(filteredFine)
if count == 0: return []
myDict = dict()
percent = self.NumberOfSymbolsFine / count
value3 = sorted(filteredFine, key = lambda x: self.ratingsDict[x.Symbol], reverse = True)
value4 = value3[:ceil(len(value3) * percent)]
self.stocks = value4[:self.NumberOfSymbolsInPortfolio]
self.newstocks= [x.Symbol for x in self.stocks]
return [x for x in self.newstocks]