Overall Statistics |
Total Trades 2939 Average Win 0.13% Average Loss -0.13% Compounding Annual Return -5.055% Drawdown 9.700% Expectancy -0.027 Net Profit -6.566% Sharpe Ratio -0.789 Loss Rate 52% Win Rate 48% Profit-Loss Ratio 1.01 Alpha 0.03 Beta -4.015 Annual Standard Deviation 0.063 Annual Variance 0.004 Information Ratio -1.105 Tracking Error 0.063 Treynor Ratio 0.012 Total Fees $0.00 |
# 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("System") AddReference("QuantConnect.Common") AddReference("QuantConnect.Algorithm") AddReference("QuantConnect.Algorithm.Framework") from System import * from QuantConnect import * from QuantConnect.Data.UniverseSelection import * from QuantConnect.Orders.Fees import ConstantFeeModel from QuantConnect.Algorithm.Framework.Alphas import * from QuantConnect.Algorithm.Framework.Portfolio import EqualWeightingPortfolioConstructionModel from QuantConnect.Algorithm.Framework.Selection import ManualUniverseSelectionModel # # Equity indices exhibit mean reversion in daily returns. The Internal Bar Strength indicator (IBS), # which relates the closing price of a security to its daily range can be used to identify overbought # and oversold securities. # # This alpha ranks 33 global equity ETFs on its IBS value the previous day and predicts for the following day # that the ETF with the highest IBS value will decrease in price, and the ETF with the lowest IBS value # will increase in price. # # Source: Kakushadze, Zura, and Juan Andrés Serur. “4. Exchange-Traded Funds (ETFs).” 151 Trading Strategies, Palgrave Macmillan, 2018, pp. 90–91. # # This alpha is part of the Benchmark Alpha Series created by QuantConnect which are open sourced so the community and client funds can see an example of an alpha. # class GlobalEquityMeanReversionIBSAlpha(QCAlgorithm): def Initialize(self): self.SetStartDate(2018, 1, 1) self.SetCash(100000) # Set zero transaction fees self.SetSecurityInitializer(lambda security: security.SetFeeModel(ConstantFeeModel(0))) # Global Equity ETF tickers tickers = ["ECH","EEM","EFA","EPHE","EPP","EWA","EWC","EWG", "EWH","EWI","EWJ","EWL","EWM","EWM","EWO","EWP", "EWQ","EWS","EWT","EWU","EWY","EWZ","EZA","FXI", "GXG","IDX","ILF","EWM","QQQ","RSX","SPY","THD"] symbols = [Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers] # Manually curated universe self.UniverseSettings.Resolution = Resolution.Daily self.SetUniverseSelection(ManualUniverseSelectionModel(symbols)) # Use GlobalEquityMeanReversionAlphaModel to establish insights self.SetAlpha(MeanReversionIBSAlphaModel()) # Equally weigh securities in portfolio, based on insights self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) # Set Immediate Execution Model self.SetExecution(ImmediateExecutionModel()) # Set Null Risk Management Model self.SetRiskManagement(NullRiskManagementModel()) class MeanReversionIBSAlphaModel(AlphaModel): '''Uses ranking of Internal Bar Strength (IBS) to create direction prediction for insights''' def __init__(self): # Set the lookback period lookback = 1 # Set the prediction interval for insights self.predictionInterval = Time.Multiply(Extensions.ToTimeSpan(Resolution.Daily), lookback) # Set the number of stocks emitting insights self.numberOfStocks = 2 def Update(self, algorithm, data): insights = [] symbolsIBS = dict() returns = dict() for security in algorithm.ActiveSecurities.Values: if security.HasData: high = security.High low = security.Low hilo = high - low # Do not consider symbol with zero open and avoid division by zero if security.Open * hilo != 0: # Internal bar strength (IBS) symbolsIBS[security.Symbol] = (security.Close - low)/hilo returns[security.Symbol] = security.Close/security.Open-1 # Number of stocks cannot be higher than half of symbolsIBS length number_of_stocks = min(int(len(symbolsIBS)/2), self.numberOfStocks) if number_of_stocks == 0: return [] algorithm.Log(number_of_stocks) # Rank securities with the highest IBS value ordered = sorted(symbolsIBS.items(), key=lambda kv: (round(kv[1], 6), kv[0]), reverse=True) highIBS = dict(ordered[0:number_of_stocks]) # Get highest IBS lowIBS = dict(ordered[-number_of_stocks:]) # Get lowest IBS # Emit "down" insight for the securities with the highest IBS value for key,value in highIBS.items(): insights.append(Insight.Price(key, self.predictionInterval, InsightDirection.Down, abs(returns[key]), None)) # Emit "up" insight for the securities with the lowest IBS value for key,value in lowIBS.items(): insights.append(Insight.Price(key, self.predictionInterval, InsightDirection.Up, abs(returns[key]), None)) return insights