Overall Statistics |
Total Trades 756 Average Win 0.13% Average Loss -0.14% Compounding Annual Return -99.802% Drawdown 33.400% Expectancy -0.436 Net Profit -22.631% Sharpe Ratio -16.118 Probabilistic Sharpe Ratio 0% Loss Rate 71% Win Rate 29% Profit-Loss Ratio 0.95 Alpha -5.17 Beta 0.361 Annual Standard Deviation 0.303 Annual Variance 0.092 Information Ratio -17.682 Tracking Error 0.321 Treynor Ratio -13.509 Total Fees $3170.90 |
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. # Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from clr import AddReference AddReference("QuantConnect.Common") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") AddReference("QuantConnect.Indicators") from QuantConnect import * from QuantConnect.Indicators import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Alphas import * class MovingAverageCrossAlphaModel(AlphaModel): '''Alpha model that uses an EMA cross to create insights''' def __init__(self, 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.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(resolution), fastPeriod) self.symbolDataBySymbol = {} resolutionString = Extensions.GetEnumString(resolution, Resolution) self.Name = '{}({},{},{})'.format(self.__class__.__name__, fastPeriod, slowPeriod, resolutionString) 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 chain in data.FutureChains: contracts = [contract for contract in chain.Value] frontContract = contracts[0] symbol = frontContract.Symbol if chain.Key not in self.symbolDataBySymbol: self.symbolDataBySymbol[chain.Key] = SymbolData(algorithm, symbol, self.fastPeriod, self.slowPeriod, self.resolution) else: if symbol != self.symbolDataBySymbol[chain.Key].frontContractSymbol: self.symbolDataBySymbol[chain.Key].frontContractSymbol = symbol self.symbolDataBySymbol[chain.Key].WarmUp() symbolData = self.symbolDataBySymbol[chain.Key] bars = chain.Value.TradeBars if symbol in bars.Keys: bar = chain.Value.TradeBars[symbol] symbolData.Update(bar.Time, bar.Close) if symbolData.IsReady: if symbolData.ShortCrossOver: insights.append(Insight(symbolData.frontContractSymbol, self.predictionInterval, InsightType.Price, InsightDirection.Down, -0.0025, 1.00, None, 0.05)) elif symbolData.LongCrossOver: insights.append(Insight(symbolData.frontContractSymbol, self.predictionInterval, InsightType.Price, InsightDirection.Up, 0.0025, 1.00, None, 0.05)) return insights class SymbolData: '''Contains data specific to a symbol required by this model''' def __init__(self, algorithm, symbol, fastPeriod, slowPeriod, resolution): self.algorithm = algorithm self.frontContractSymbol = symbol self.resolution = resolution self.fastPeriod = fastPeriod self.slowPeriod = slowPeriod self.Fast = ExponentialMovingAverage(self.fastPeriod) self.Slow = ExponentialMovingAverage(self.slowPeriod) self.fastWindow = RollingWindow[IndicatorDataPoint](2) self.slowWindow = RollingWindow[IndicatorDataPoint](2) self.Fast.Updated += self.OnFastEMA self.Slow.Updated += self.OnSlowEMA self.WarmUp() def WarmUp(self): history = self.algorithm.History(self.frontContractSymbol, self.slowPeriod, self.resolution) if not history.empty: history = history.close.unstack(1) if not history.empty: df = history[self.frontContractSymbol].dropna() if not df.empty: for time, close in df.iteritems(): self.Update(time[1], close) @property def IsReady(self): return self.fastWindow.IsReady and self.slowWindow.IsReady def Update(self, time, close): self.Fast.Update(time, close) self.Slow.Update(time, close) @property def LongCrossOver(self): return self.fastWindow[1].Value < self.slowWindow[1].Value \ and self.fastWindow[0].Value > self.slowWindow[0].Value @property def ShortCrossOver(self): return self.fastWindow[1].Value > self.slowWindow[1].Value \ and self.fastWindow[0].Value < self.slowWindow[0].Value def OnFastEMA(self, sender, updated): if self.Fast.IsReady: self.fastWindow.Add(updated) def OnSlowEMA(self, sender, updated): if self.Slow.IsReady: self.slowWindow.Add(updated)
from Execution.ImmediateExecutionModel import ImmediateExecutionModel from Portfolio.MeanVarianceOptimizationPortfolioConstructionModel import MeanVarianceOptimizationPortfolioConstructionModel from Risk.MaximumDrawdownPercentPerSecurity import MaximumDrawdownPercentPerSecurity from FuturesUniverseSelectionModel import FuturesUniverseSelectionModel from ATRBasedPositionSizing import ATRBasedPositionSizing from MovingAverageCrossAlphaModel import MovingAverageCrossAlphaModel class MovingAverageCrossTrendFollowing(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 1, 1) # Set Start Date self.SetEndDate(2019, 1, 15) # Set End Date self.SetCash(100000) # Set Strategy Cash self.UniverseSettings.Resolution = Resolution.Minute self.SetUniverseSelection(FuturesUniverseSelectionModel(self.SelectFuturesSymbols)) self.AddAlpha(MovingAverageCrossAlphaModel(50, 200, Resolution.Minute)) self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel()) self.SetExecution(ImmediateExecutionModel()) def SelectFuturesSymbols(self, utcTime): tickers = [Futures.Indices.SP500EMini, Futures.Grains.BlackSeaCornFinanciallySettledPlatts, Futures.Grains.Wheat, Futures.Grains.Corn, Futures.Grains.Soybeans, Futures.Grains.SoybeanMeal, Futures.Grains.SoybeanOil, Futures.Grains.Oats, Futures.Currencies.USD, Futures.Currencies.GBP, Futures.Currencies.CAD, Futures.Currencies.JPY, Futures.Currencies.CHF, Futures.Currencies.EUR, Futures.Softs.Cocoa, Futures.Dairy.CashSettledButter, Futures.Dairy.CashSettledCheese, Futures.Dairy.ClassIIIMilk, Futures.Dairy.DryWhey, Futures.Dairy.ClassIVMilk, Futures.Dairy.NonfatDryMilk] return [ Symbol.Create(ticker, SecurityType.Future, Market.USA) for ticker in tickers]
from Selection.FutureUniverseSelectionModel import FutureUniverseSelectionModel from datetime import date, timedelta class FuturesUniverseSelectionModel(FutureUniverseSelectionModel): def __init__(self, select_future_chain_symbols): super().__init__(timedelta(1), select_future_chain_symbols) def Filter(self, filter): return (filter.FrontMonth())
from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") AddReference("QuantConnect.Common") AddReference("QuantConnect.Indicators") from System import * from QuantConnect import * from QuantConnect.Indicators import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Portfolio import * from Portfolio.MinimumVariancePortfolioOptimizer import MinimumVariancePortfolioOptimizer from datetime import timedelta import numpy as np import pandas as pd ### <summary> ### </summary> class ATRBasedPositionSizing(PortfolioConstructionModel): def __init__(self, riskFactor = 0.2, lookbackPeriod = 100): """Initialize the model Args: lookback(int): Historical return lookback period period(int): The time interval of history price to calculate the weight resolution: The resolution of the history price optimizer(class): Method used to compute the portfolio weights""" self.atrs = {} self.lookbackPeriod = lookbackPeriod self.riskFactor = riskFactor def CreateTargets(self, algorithm, insights): """ Create portfolio targets from the specified insights Args: algorithm: The algorithm instance insights: The insights to create portfolio targets from Returns: An enumerable of portfolio targets to be sent to the execution model """ targets = [] for insight in insights: symbol = insight.Symbol if symbol in self.atrs.keys(): direction = 1 if InsightDirection.Up else -1 price = algorithm.Securities[symbol].Price atr = self.atrs[symbol].Current.Value numberOfContracts = np.floor((direction * (self.riskFactor*algorithm.Portfolio.TotalPortfolioValue)/(atr*price ))) target = PortfolioTarget(insight.Symbol, numberOfContracts) if target is not None: targets.append(target) return targets 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 addedSecurity in changes.AddedSecurities: ticker = addedSecurity.Symbol if ticker not in self.atrs.keys(): self.atrs[ticker] = algorithm.ATR(ticker, self.lookbackPeriod)