Overall Statistics |
Total Trades 53 Average Win 0.08% Average Loss -0.01% Compounding Annual Return 5.440% Drawdown 16.900% Expectancy 4.095 Net Profit 13.623% Sharpe Ratio 0.502 Probabilistic Sharpe Ratio 19.637% Loss Rate 23% Win Rate 77% Profit-Loss Ratio 5.62 Alpha 0.056 Beta -0.074 Annual Standard Deviation 0.099 Annual Variance 0.01 Information Ratio -0.147 Tracking Error 0.254 Treynor Ratio -0.666 Total Fees $0.00 |
from datetime import timedelta class QuarterlyRebalance(QCAlgorithm): def Initialize(self): # Set Start Date, End Date, and Cash #--------------------------------------------------------------------------------------- self.SetStartDate(2018, 1, 1) self.SetEndDate(2020, 5, 31) self.SetCash(100000) #--------------------------------------------------------------------------------------- # Resolution #--------------------------------------------------------------------------------------- self.resolution = Resolution.Daily #--------------------------------------------------------------------------------------- # Brokerage, Orders, Portfolio Settings #--------------------------------------------------------------------------------------- self.SetBrokerageModel(BrokerageName.Alpaca, AccountType.Margin) # AccountType.Margin required for "non-null" Portfolio and Execution Models self.DefaultOrderProperties.TimeInForce = TimeInForce.GoodTilCanceled # Time in Force for open orders. Default is GoodTilCanceled (GTC) self.Settings.RebalancePortfolioOnInsightChanges = False self.Settings.RebalancePortfolioOnSecurityChanges = False #--------------------------------------------------------------------------------------- # Universe Settings #--------------------------------------------------------------------------------------- self.UniverseSettings.Resolution = self.resolution self.UniverseSettings.SetDataNormalizationMode = DataNormalizationMode.SplitAdjusted self.UniverseSettings.FeeModel = ConstantFeeModel(0.0) self.UniverseSettings.ExtendedMarketHours = False self.UniverseSettings.Leverage = 0 self.weekday = self.Time.isocalendar()[2] #--------------------------------------------------------------------------------------- # Algorithm Framework Configuration #--------------------------------------------------------------------------------------- self.SetUniverseSelection(CustomUniverseSelectionModel("CustomUniverseSelectionModel", lambda time: [ "SPY", "AGG"])) self.SetAlpha(EMAAlphaModel()) self.SetPortfolioConstruction(MyInsightWeightingPortfolioConstructionModel(self.DateRules.MonthEnd())) self.SetExecution(ImmediateExecutionModel()) self.SetRiskManagement(NullRiskManagementModel()) #--------------------------------------------------------------------------------------- class EMAAlphaModel(AlphaModel): def __init__(self): pass def OnSecuritiesChanged(self, algorithm, changes): # Create indicator for each new security for security in changes.AddedSecurities: pass for security in changes.RemovedSecurities: pass def Update(self, algorithm, data): insights = [] for security in algorithm.ActiveSecurities.Values: insights.append(Insight.Price(security.Symbol, timedelta(minutes = 20), InsightDirection.Up, 0.003, None, None, 0.45)) return insights class MyInsightWeightingPortfolioConstructionModel(EqualWeightingPortfolioConstructionModel): '''Provides an implementation of IPortfolioConstructionModel that generates percent targets based on the Insight.Weight. The target percent holdings of each Symbol is given by the Insight.Weight from the last active Insight for that symbol. For insights of direction InsightDirection.Up, long targets are returned and for insights of direction InsightDirection.Down, short targets are returned. If the sum of all the last active Insight per symbol is bigger than 1, it will factor down each target percent holdings proportionally so the sum is 1. It will ignore Insight that have no Insight.Weight value.''' def __init__(self, rebalance = Resolution.Daily, portfolioBias = PortfolioBias.LongShort): '''Initialize a new instance of InsightWeightingPortfolioConstructionModel Args: rebalance: Rebalancing parameter. If it is a timedelta, date rules or Resolution, it will be converted into a function. If None will be ignored. The function returns the next expected rebalance time for a given algorithm UTC DateTime. The function returns null if unknown, in which case the function will be called again in the next loop. Returning current time will trigger rebalance. portfolioBias: Specifies the bias of the portfolio (Short, Long/Short, Long)''' #if algorithm.Time.month == 6: # $$$$$$$$$$CROSSFIELD CAPITAL EDIT$$$$$$$$$$$$$ # algorithm.Debug("YOLO") super().__init__(rebalance, portfolioBias) def ShouldCreateTargetForInsight(self, insight): '''Method that will determine if the portfolio construction model should create a target for this insight Args: insight: The insight to create a target for''' # Ignore insights that don't have Weight value return insight.Weight is not None def DetermineTargetPercent(self, activeInsights): '''Will determine the target percent for each insight Args: activeInsights: The active insights to generate a target for''' result = {} # We will adjust weights proportionally in case the sum is > 1 so it sums to 1. weightSums = sum(self.GetValue(insight) for insight in activeInsights if self.RespectPortfolioBias(insight)) weightFactor = 1.0 if weightSums > 1: weightFactor = 1 / weightSums for insight in activeInsights: result[insight] = (insight.Direction if self.RespectPortfolioBias(insight) else InsightDirection.Flat) * self.GetValue(insight) * weightFactor return result def GetValue(self, insight): '''Method that will determine which member will be used to compute the weights and gets its value Args: insight: The insight to create a target for Returns: The value of the selected insight member''' return insight.Weight