Overall Statistics |
Total Trades 112 Average Win 0.50% Average Loss -3.53% Compounding Annual Return 5.904% Drawdown 31.100% Expectancy -0.032 Net Profit 24.241% Sharpe Ratio 0.522 Loss Rate 15% Win Rate 85% Profit-Loss Ratio 0.14 Alpha 0.066 Beta -0.836 Annual Standard Deviation 0.1 Annual Variance 0.01 Information Ratio 0.358 Tracking Error 0.1 Treynor Ratio -0.062 Total Fees $189.04 |
# 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.Algorithm.Framework") AddReference("QuantConnect.Indicators") AddReference("QuantConnect.Common") from QuantConnect import * from QuantConnect.Indicators import * from QuantConnect.Algorithm.Framework.Alphas import * from datetime import timedelta from enum import Enum class PPOAlphaModel(AlphaModel): '''Uses PPO to create insights. Using default settings, slow/fast is 12/26. Above/below -.5 will trigger a new insight.''' rebalance_date = None rebalance_complete = False def __init__(self, fastPeriod = 12, slowPeriod = 26, trigger = 0.0, consolidationPeriod = 7, resolution = Resolution.Daily): self.lookback = (slowPeriod * consolidationPeriod) self.fastPeriod = fastPeriod self.slowPeriod = slowPeriod self.resolution = resolution self.consolidationPeriod = consolidationPeriod self.trigger = trigger self.predictionInterval = Extensions.ToTimeSpan(self.resolution) 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''' #algorithm.Debug("Update Called on PPOAlphaModel") # generate insights when scheduled insights = [] #and algorithm.Time.hour == 8 and algorithm.Time.minute == 59 if self.rebalance_complete or not (algorithm.Time.date() == self.rebalance_date): return insights # only get here to build new insights once on the scheduled trading date self.rebalance_complete = True #algorithm.Debug("Now Generating Insights in PPOAlpha") for symbol, symbolData in self.symbolDataBySymbol.items(): if symbolData.CanEmit: direction = InsightDirection.Flat magnitude = symbolData.Return #algorithm.Debug("got a positive CanEmit with symbol and magnitude: " + str(symbol) + str(magnitude)) if magnitude > self.trigger: direction = InsightDirection.Up if magnitude < self.trigger: direction = InsightDirection.Flat insights.append(Insight.Price(symbol, self.predictionInterval, direction)) algorithm.Log(str(symbol) + ": " + str(magnitude) + ": " + str(direction)) 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''' #algorithm.Debug("starting OnSecuritiesChanged") # clean up data for removed securities for removed in changes.RemovedSecurities: symbolData = self.symbolDataBySymbol.pop(removed.Symbol, None) if symbolData is not None: symbolData.RemoveConsolidators(algorithm) #algorithm.Debug("in OnSecuritiesChanged past removed list") # initialize data for added securities symbols = [ x.Symbol for x in changes.AddedSecurities ] #algorithm.Debug("before history retrieval") history = algorithm.History(symbols, self.lookback, self.resolution) #algorithm.Debug("after history retrieval") if history.empty: return tickers = history.index.levels[0] for ticker in tickers: symbol = SymbolCache.GetSymbol(ticker) if symbol not in self.symbolDataBySymbol: symbolData = SymbolData(symbol, self.fastPeriod, self.slowPeriod, self.consolidationPeriod) self.symbolDataBySymbol[symbol] = symbolData symbolData.RegisterIndicators(algorithm) symbolData.WarmUpIndicators(history.loc[ticker]) class SymbolData: '''Contains data specific to a symbol required by this model''' def __init__(self, symbol, fastPeriod, slowPeriod, consolidationPeriod): self.Symbol = symbol self.Fast = fastPeriod self.Slow = slowPeriod self.PPO = PercentagePriceOscillator(fastPeriod, slowPeriod, MovingAverageType.Exponential) self.Consolidator = TradeBarConsolidator(TimeSpan.FromDays(consolidationPeriod)) #self.Consolidator = None self.Previous = None @property def belowPPOTrigger(self): return (not self.abovePPOTrigger) @property def CanEmit(self): if self.Previous == self.PPO.Samples: return False self.Previous = self.PPO.Samples return self.PPO.IsReady @property def Return(self): return float(self.PPO.Current.Value) #def OnWeeklyData(self, sender, bar): #self.PPO.Update(bar.EndTime, bar.Close) def RegisterIndicators(self, algorithm): #self.Consolidator = algorithm.ResolveConsolidator(self.Symbol, resolution) algorithm.RegisterIndicator(self.Symbol, self.PPO, self.Consolidator) def RemoveConsolidators(self, algorithm): if self.Consolidator is not None: algorithm.SubscriptionManager.RemoveConsolidator(self.Symbol, self.Consolidator) def WarmUpIndicators(self, history): #index = 0 #for tuple in history.itertuples(): for index, tuple in history.iterrows(): #index = index + 1 #if index % consolidationPeriod == 0: #self.PPO.Update(tuple.Index, tuple.close) tradeBar = TradeBar() tradeBar.Close = tuple['close'] tradeBar.Open = tuple['open'] tradeBar.High = tuple['high'] tradeBar.Low = tuple['low'] tradeBar.Volume = tuple['volume'] tradeBar.Time = index self.Consolidator.Update(tradeBar)
from clr import AddReference AddReference("System") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") AddReference("QuantConnect.Common") from System import * from QuantConnect import * from QuantConnect.Orders import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Alphas import * from QuantConnect.Algorithm.Framework.Portfolio import * from QuantConnect.Algorithm.Framework.Selection import * from PPOAlphaModel import PPOAlphaModel #from QuantConnect.Algorithm.Framework.Alphas.ConstantAlphaModel import ConstantAlphaModel from Alphas.RsiAlphaModel import RsiAlphaModel from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel from QuantConnect.Algorithm.Framework.Execution import ImmediateExecutionModel from QuantConnect.Algorithm.Framework.Execution import VolumeWeightedAveragePriceExecutionModel from QuantConnect.Algorithm.Framework.Risk import NullRiskManagementModel from datetime import datetime, timedelta import numpy as np ### <summary> ### Basic template framework algorithm uses framework components to define the algorithm. ### </summary> ### <meta name="tag" content="using data" /> ### <meta name="tag" content="using quantconnect" /> ### <meta name="tag" content="trading and orders" /> class AssetClassRotationFrameworkAlgorithm(QCAlgorithmFramework): '''Basic template framework algorithm uses framework components to define the algorithm.''' alpha = None def Initialize(self): ''' Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' # Set requested data resolution self.UniverseSettings.Resolution = Resolution.Daily self.UniverseSettings.Leverage = 1.0 self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) self.SetStartDate(2014,10,7) #Set Start Date self.SetEndDate(2018,7,18) #Set End Date self.SetCash(100000) #Set Strategy Cash # Find more symbols here: http://quantconnect.com/data # Forex, CFD, Equities Resolutions: Tick, Second, Minute, Hour, Daily. # Futures Resolution: Tick, Second, Minute # Options Resolution: Minute Only. #tickers = ['IWM', 'QQQ','SCHH', 'USO', 'VDE', 'XBI', 'AAXJ', 'DBA', 'DBB', 'DBC', 'DOG', 'EEM', 'EFA', 'EWH', 'EWJ', 'EWZ', 'EZU', 'FXI', 'GDX', 'GLD', 'HYG', 'IEF', 'IEFA', 'LQD', 'SH', 'SLV', 'TAN', 'TIP', 'TLT', 'UUP', 'VAW', 'VEU', 'VNQ', 'XLE', 'XLK', 'XLY', 'XLB', 'XLF', 'XLI', 'XLP', 'XLU', 'XLV'] tickers = ['IWM', 'XLK', 'DOG', 'EEM'] symbols = [ Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers ] # set algorithm framework models self.SetUniverseSelection(ManualUniverseSelectionModel(symbols)) #self.SetAlpha(IchimokuAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(days = 10), 0.025, None)) self.alpha = PPOAlphaModel() self.SetAlpha(self.alpha) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) self.SetExecution(ImmediateExecutionModel()) self.SetRiskManagement(NullRiskManagementModel()) # will initialize a position immediately then on the given schedule self.alpha.rebalance_date = self.Time.date() self.rebalance_trading_day = 7 self.AddEquity('IWM') self.Schedule.On(self.DateRules.MonthStart('IWM'), self.TimeRules.AfterMarketOpen('IWM', 1), Action(self.ScheduleRebalance)) def ScheduleRebalance(self): month_last_day = DateTime(self.Time.year, self.Time.month, DateTime.DaysInMonth(self.Time.year, self.Time.month)) trading_days = self.TradingCalendar.GetDaysByType(TradingDayType.BusinessDay, self.Time, month_last_day) #get the correct trading_day day_count = 0 for x in trading_days: day_count = day_count + 1 if (day_count == self.rebalance_trading_day): self.alpha.rebalance_date = x.Date.date() self.alpha.rebalance_complete = False def OnOrderEvent(self, orderEvent): if orderEvent.Status == OrderStatus.Filled: #self.Debug("Purchased Stock: {0}, {1}".format(orderEvent.Symbol, orderEvent.FillQuantity)) return