| Overall Statistics |
|
Total Trades 2 Average Win 0.80% Average Loss 0% Compounding Annual Return 0.398% Drawdown 0.700% Expectancy 0 Net Profit 0.797% Sharpe Ratio 0.352 Probabilistic Sharpe Ratio 13.810% Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha 0.005 Beta -0.009 Annual Standard Deviation 0.012 Annual Variance 0 Information Ratio -0.633 Tracking Error 0.131 Treynor Ratio -0.475 Total Fees $2.00 Estimated Strategy Capacity $37000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X |
class RiskModel(RiskManagementModel):
'''Provides an implementation of IRiskManagementModel that limits the unrealized profit per holding to the specified percentage'''
def __init__(self, maximumUnrealizedProfitPercent = 0.01):
'''Initializes a new instance of the MaximumUnrealizedProfitPercentPerSecurity class
Args:
maximumUnrealizedProfitPercent: The maximum percentage unrealized profit allowed for any single security holding, defaults to 5% drawdown per security'''
self.maximumUnrealizedProfitPercent = abs(maximumUnrealizedProfitPercent)
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'''
targets = []
for kvp in algorithm.Securities:
security = kvp.Value
if not security.Invested:
continue
pnl = security.Holdings.UnrealizedProfitPercent
if pnl < -self.maximumUnrealizedProfitPercent:
# liquidate
targets.append(PortfolioTarget(security.Symbol, 0))
return targets
# Your New Python Filefrom RiskModel import RiskModel
from AlphaModel import CrossAlphaModel
from ExecuteModel import ImmediateExecutionPlotModel
class CalmBrownTermite(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2017, 1, 1)
self.SetEndDate(2019,1,1)
self.SetCash(10000)
# self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
self.equity = "SPY"
symbols = [Symbol.Create(self.equity, SecurityType.Equity, Market.USA)]
resolution = Resolution.Daily
self.AddUniverseSelection(ManualUniverseSelectionModel(symbols))
# self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw
self.AddEquity(self.equity)
fastr = int(self.GetParameter("fastr"))
diff = int(self.GetParameter("diff"))
self.AlphaM = CrossAlphaModel(algo = self, fastPeriod = fastr, slowPeriod = fastr+diff)
self.AddAlpha(self.AlphaM)
# self.AddRiskManagement(TrailingStopRiskManagementModel(0.05))
self.SetExecution(ImmediateExecutionPlotModel(self))
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.UniverseSettings.Resolution = resolution
from System.Drawing import Color
stockPlot = Chart('Trade Plot')
stockPlot.AddSeries(Series('Price', SeriesType.Line, '$', Color.Black))
stockPlot.AddSeries(Series('Fast', SeriesType.Line, '$', Color.Green))
stockPlot.AddSeries(Series('Slow', SeriesType.Line, '$', Color.Orange))
stockPlot.AddSeries(Series('Buy', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.Triangle))
stockPlot.AddSeries(Series('Sell', SeriesType.Scatter, '$', Color.Blue, ScatterMarkerSymbol.TriangleDown))
self.AddChart(stockPlot)
def OnEndOfDay(self, symbol):
# if self.lastPrice is None: return
self.Plot("Trade Plot", "Price", self.Securities[self.equity].Close)
self.Log(self.AlphaM)
if self.AlphaM.get()[0][1].IsReady:
self.Plot("Trade Plot", "Fast", self.AlphaM.get()[0][0].Current.Value)
self.Plot("Trade Plot", "Slow", self.AlphaM.get()[0][1].Current.Value)
class ImmediateExecutionPlotModel(ExecutionModel):
'''Provides an implementation of IExecutionModel that immediately submits market orders to achieve the desired portfolio targets'''
def __init__(self,algo):
'''Initializes a new instance of the ImmediateExecutionModel class'''
self.targetsCollection = PortfolioTargetCollection()
self.algo = algo
def Execute(self, algorithm, targets):
'''Immediately submits orders for the specified portfolio targets.
Args:
algorithm: The algorithm instance
targets: The portfolio targets to be ordered'''
# for performance we check count value, OrderByMarginImpact and ClearFulfilled are expensive to call
self.targetsCollection.AddRange(targets)
if self.targetsCollection.Count > 0:
for target in self.targetsCollection.OrderByMarginImpact(algorithm):
# calculate remaining quantity to be ordered
quantity = OrderSizing.GetUnorderedQuantity(algorithm, target)
if quantity != 0:
algorithm.MarketOrder(target.Symbol, quantity)
action = 'Buy' if quantity > 0 else 'Sell'
self.algo.Plot("Trade Plot", action, self.algo.Securities[target.Symbol].Price)
self.targetsCollection.ClearFulfilled(algorithm)
# Your New Python Fileclass CrossAlphaModel(AlphaModel):
'''Alpha model that uses an EMA cross to create insights'''
def __init__(self, algo,
fastPeriod = 12,
slowPeriod = 26,
resolution = Resolution.Daily):
'''Initializes a new instance of the EmaCrossAlphaModel class
Args:
fastPeriod: The fast EMA period
slowPeriod: The slow EMA period'''
self.fastPeriod = fastPeriod
self.slowPeriod = slowPeriod
self.resolution = resolution
self.period = timedelta(days=1)
self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(resolution), fastPeriod)
self.symbolDataBySymbol = {}
self.algo = algo
resolutionString = Extensions.GetEnumString(resolution, Resolution)
self.Name = '{}({},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, resolutionString)
def get(self):
indicts = []
for symbol, symbolData in self.symbolDataBySymbol.items():
indicts.append([symbolData.Fast,symbolData.Slow])
return indicts
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.Fast.IsReady and symbolData.Slow.IsReady:
if symbolData.FastIsOverSlow:
if symbolData.Slow > symbolData.Fast:
# self.algo.Debug("SELL: slow = "+str(symbolData.Slow.Current.Value)+", fast = "+ str(symbolData.Fast.Current.Value))
insights.append(Insight.Price(symbolData.Symbol, self.period, InsightDirection.Down))
elif symbolData.SlowIsOverFast:
if symbolData.Fast > symbolData.Slow:
# self.algo.Debug("BUY: slow = "+str(symbolData.Slow.Current.Value)+", fast = "+ str(symbolData.Fast.Current.Value))
insights.append(Insight.Price(symbolData.Symbol, self.period, InsightDirection.Up))
symbolData.FastIsOverSlow = symbolData.Fast > symbolData.Slow
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'''
for added in changes.AddedSecurities:
symbolData = self.symbolDataBySymbol.get(added.Symbol)
if symbolData is None:
# create fast/slow EMAs
symbolData = SymbolData(added)
symbolData.Fast = algorithm.EMA(added.Symbol, self.fastPeriod, self.resolution)
symbolData.Slow = algorithm.EMA(added.Symbol, self.slowPeriod, self.resolution)
self.symbolDataBySymbol[added.Symbol] = symbolData
else:
# a security that was already initialized was re-added, reset the indicators
symbolData.Fast.Reset()
symbolData.Slow.Reset()
class SymbolData:
'''Contains data specific to a symbol required by this model'''
def __init__(self, security):
self.Security = security
self.Symbol = security.Symbol
self.Fast = None
self.Slow = None
# True if the fast is above the slow, otherwise false.
# This is used to prevent emitting the same signal repeatedly
self.FastIsOverSlow = False
@property
def SlowIsOverFast(self):
return not self.FastIsOverSlow
# Your New Python Fileclass CalmBrownTermite(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2017, 1, 1)
self.SetEndDate(2019,1,1)
self.SetCash(10000)
# self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage)
self.symbol = "SPY"
self.equity = self.AddEquity(self.symbol, Resolution.Minute).Symbol
fastr = 650
slowr = fastr + 650
# fastr = int(self.GetParameter("fastr"))
# slowr = fastr + int(self.GetParameter("diff"))
self.Fast = self.EMA(self.equity,fastr,Resolution.Minute)
self.Slow = self.EMA(self.equity,slowr,Resolution.Minute)
self.lastsign = None
self.lastPrice = None
self.previous = self.Time.min
self.Tolerance = 0.00015
from System.Drawing import Color
stockPlot = Chart('Trade Plot')
stockPlot.AddSeries(Series('Price', SeriesType.Line, '$', Color.Green))
stockPlot.AddSeries(Series('Buy', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.Triangle))
stockPlot.AddSeries(Series('Sell', SeriesType.Scatter, '$', Color.Blue, ScatterMarkerSymbol.TriangleDown))
stockPlot.AddSeries(Series('SMA50', SeriesType.Line, '$', Color.Orange))
stockPlot.AddSeries(Series('SMA200', SeriesType.Line, '$', Color.Yellow))
self.AddChart(stockPlot)
def OnData(self, data):
if not data[self.equity] is None:
self.lastPrice = data[self.equity].Close
if not self.Slow.IsReady :return
# if self.previous is None or self.previous.day==self.Time.day:return
if self.lastsign is None:
self.lastsign = self.Fast.Current.Value > self.Slow.Current.Value
return
holdings = self.Portfolio[self.equity].Quantity
# BUY (CROSSOVER)
if holdings <= 0 and self.Fast.Current.Value > self.Slow.Current.Value and not self.lastsign:
self.Liquidate()
self.SetHoldings(self.equity,1)
self.Plot("Trade Plot", 'Buy', self.Securities[self.equity].Price)
# SELL (CROSSOVER)
elif self.Fast < self.Slow and holdings > 0 and self.lastsign:
self.Liquidate()
self.SetHoldings(self.equity,-1)
self.Plot("Trade Plot", 'Sell', self.Securities[self.equity].Price)
# SELL (STOPLOSS)
if self.Portfolio[self.equity].UnrealizedProfitPercent<= -0.01 :
# print(str(int(self.Portfolio.Cash)))
action = 'Sell' if self.Portfolio[self.equity].IsLong else 'BUY'
self.Plot("Trade Plot", action, self.Securities[self.equity].Price)
self.Liquidate()
# if data.Bars.ContainsKey("SPY"):
# self.Plot("Trade Plot", "Price", data[self.equity].Close)
# self.Plot("Trade Plot", "SMA50" ,self.Fast.Current.Value)
# self.Plot("Trade Plot", "SMA200", self.Slow.Current.Value)
self.previous = self.Time
self.lastsign = self.Fast.Current.Value > self.Slow.Current.Value
def OnEndOfDay(self, symbol):
# if self.lastPrice is None: return
self.Plot("Trade Plot", "Price", self.Securities[self.equity].Price)
self.Plot("Trade Plot", "SMA50" ,self.Fast.Current.Value)
self.Plot("Trade Plot", "SMA200", self.Slow.Current.Value)