Overall Statistics |
Total Orders 23 Average Win 33.02% Average Loss -4.36% Compounding Annual Return 15.951% Drawdown 33.300% Expectancy 6.261 Start Equity 100000 End Equity 945589.55 Net Profit 845.590% Sharpe Ratio 0.548 Sortino Ratio 0.544 Probabilistic Sharpe Ratio 2.915% Loss Rate 15% Win Rate 85% Profit-Loss Ratio 7.58 Alpha 0.078 Beta 0.425 Annual Standard Deviation 0.209 Annual Variance 0.044 Information Ratio 0.135 Tracking Error 0.216 Treynor Ratio 0.27 Total Fees $286.12 Estimated Strategy Capacity $0 Lowest Capacity Asset 107.QuantpediaEquity 2S Portfolio Turnover 0.34% |
# https://quantpedia.com/strategies/momentum-effect-in-anomalies-trading-systems/ # # In each year, the trader searches through the universe of financial journals for implementable trading strategies. The investment universe, which consists of existing anomalies, # is then created. The investor then chooses the best performing anomaly for the last two years (based on his backtesting results of all published anomalies) and will trade it in # the following year. # # QC implementation changes: # - Investment universe consists of Quantpedia's equity long-short anomalies. #region imports from AlgorithmImports import * #endregion class MomentumEffectinAnomaliesTradingSystems(QCAlgorithm): def Initialize(self): self.SetStartDate(2010, 1, 1) self.SetCash(100000) # ids with backtest period end year self.backtest_to = {} # daily price data self.perf = {} self.period = 2 * 12 * 21 self.SetWarmUp(self.period, Resolution.Daily) csv_string_file = self.Download('data.quantpedia.com/backtesting_data/equity/quantpedia_strategies/backtest_end_year.csv') lines = csv_string_file.split('\r\n') last_id = None for line in lines[1:]: split = line.split(';') id = str(split[0]) backtest_to = int(split[1]) # add quantpedia strategy data data = self.AddData(QuantpediaEquity, id, Resolution.Daily) data.SetLeverage(10) data.SetFeeModel(CustomFeeModel()) self.backtest_to[id] = backtest_to self.perf[id] = self.ROC(id, self.period, Resolution.Daily) if not last_id: last_id = id self.recent_month = -1 self.Settings.MinimumOrderMarginPortfolioPercentage = 0. def OnData(self, data): if self.IsWarmingUp: return if self.Time.month == self.recent_month: return self.recent_month = self.Time.month if self.Time.month != 1: return _last_update_date:Dict[str, datetime.date] = QuantpediaEquity.get_last_update_date() # calculate performance of those strategies, which were published last year and sooner performance = { x : self.perf[x].Current.Value for x in self.perf if \ self.perf[x].IsReady and \ self.backtest_to[x] < self.Time.year and \ x in data and data[x] and \ _last_update_date[x] > self.Time.date() } # performance sorting if len(performance) != 0: sorted_by_perf = sorted(performance.items(), key = lambda x: x[1], reverse = True) top_performer_id = sorted_by_perf[0][0] if not self.Portfolio[top_performer_id].Invested: self.Liquidate() self.SetHoldings(top_performer_id, 1) else: self.Liquidate() # Quantpedia strategy equity curve data. # NOTE: IMPORTANT: Data order must be ascending (datewise) class QuantpediaEquity(PythonData): def GetSource(self, config, date, isLiveMode): return SubscriptionDataSource( "data.quantpedia.com/backtesting_data/equity/quantpedia_strategies/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv ) _last_update_date:Dict[str, datetime.date] = {} @staticmethod def get_last_update_date() -> Dict[str, datetime.date]: return QuantpediaEquity._last_update_date def Reader(self, config, line, date, isLiveMode): data = QuantpediaEquity() data.Symbol = config.Symbol if not line[0].isdigit(): return None split = line.split(';') data.Time = datetime.strptime(split[0], "%Y-%m-%d") + timedelta(days=1) data['close'] = float(split[1]) data.Value = float(split[1]) # store last update date if config.Symbol.Value not in QuantpediaEquity._last_update_date: QuantpediaEquity._last_update_date[config.Symbol.Value] = datetime(1,1,1).date() if data.Time.date() > QuantpediaEquity._last_update_date[config.Symbol.Value]: QuantpediaEquity._last_update_date[config.Symbol.Value] = data.Time.date() return data # Custom fee model. class CustomFeeModel(FeeModel): def GetOrderFee(self, parameters): fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005 return OrderFee(CashAmount(fee, "USD"))