Overall Statistics |
Total Trades 91 Average Win 0.41% Average Loss -0.83% Compounding Annual Return -47.600% Drawdown 30.200% Expectancy -0.560 Net Profit -18.133% Sharpe Ratio -1.205 Probabilistic Sharpe Ratio 4.484% Loss Rate 71% Win Rate 29% Profit-Loss Ratio 0.50 Alpha -0.319 Beta 0.272 Annual Standard Deviation 0.28 Annual Variance 0.078 Information Ratio -0.88 Tracking Error 0.308 Treynor Ratio -1.237 Total Fees $290.75 Estimated Strategy Capacity $8700000.00 Lowest Capacity Asset GE R735QTJ8XC9X |
# 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 AlgorithmImports import * ### <summary> ### Framework algorithm that uses the PearsonCorrelationPairsTradingAlphaModel. ### This model extendes BasePairsTradingAlphaModel and uses Pearson correlation ### to rank the pairs trading candidates and use the best candidate to trade. ### ### This modification limits the universe to a specific sector (as per MorningstarSectorCode) ### </summary> class PearsonCorrelationPairsTradingAlphaModelFrameworkAlgorithm(QCAlgorithm): '''Framework algorithm that uses the PearsonCorrelationPairsTradingAlphaModel. This model extendes BasePairsTradingAlphaModel and uses Pearson correlation to rank the pairs trading candidates and use the best candidate to trade.''' def Initialize(self): self.SetStartDate(2022,7,1) self.sector = self.GetParameter("sector") or "FinancialServices" self.riskPercent = self.GetParameter("riskPercent", 0.05) self.topX = int(self.GetParameter("topX", 100)) self.sectors = { "FinancialServices": MorningstarSectorCode.FinancialServices, "RealEstate": MorningstarSectorCode.RealEstate, "Healthcare": MorningstarSectorCode.Healthcare, "Utilities": MorningstarSectorCode.Utilities, "Technology": MorningstarSectorCode.Technology, "BasicMaterials": MorningstarSectorCode.BasicMaterials, "ConsumerCyclical": MorningstarSectorCode.ConsumerCyclical, "ConsumerDefensive": MorningstarSectorCode.ConsumerDefensive, "CommunicationServices": MorningstarSectorCode.CommunicationServices, "Energy": MorningstarSectorCode.Energy, "Industrials": MorningstarSectorCode.Industrials} self.AddUniverseSelection(FineFundamentalUniverseSelectionModel(self.SelectCoarse, self.SelectFine)) self.SetAlpha(PearsonCorrelationPairsTradingAlphaModel(252, Resolution.Daily)) self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) self.SetExecution(ImmediateExecutionModel()) # self.SetRiskManagement(TrailingStopRiskManagementModel(self.riskPercent)) # self.AddRiskManagement(MaximumDrawdownPercentPerSecurity(self.riskPercent)) # self.AddRiskManagement(MaximumDrawdownPercentPortfolio(self.riskPercent)) self.SetRiskManagement(NullRiskManagementModel()) def SelectCoarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]: selected = [c for c in coarse if c.HasFundamentalData] sorted_by_dollar_volume = sorted(selected, key=lambda c: c.DollarVolume, reverse=True) return [c.Symbol for c in sorted_by_dollar_volume[:self.topX]] # Return most liquid assets w/ fundamentals def SelectFine(self, fine): if self.sector != "all": filtered_fine = [x.Symbol for x in fine if x.AssetClassification.MorningstarSectorCode == self.sectors[self.sector]] else: filtered_fine = [x.Symbol for x in fine] if len(filtered_fine) < 2: filtered_fine = [] return filtered_fine # return only assets within one sector (unless sector is 'all', in which case no filter is applied)