Overall Statistics |
Total Trades 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset |
#region imports from AlgorithmImports import * #endregion # Errors To Resolve: # 1. Rolling window is empty (Parameter 'i') in RollingWindow.cs:line 143 - For now I have commented below line in Alpha Model # self.algo.Debug(f"Yesterday's Date:{self.algo.Time} Nasdaq Close:{self.nasdaqYesterdayClose[0]}, Lumber Close: {self.lumberYesterdayClose[0]}") # 2. Backtest Handled Error: Order Error: id: 5848, Insufficient buying power to complete order (Value:-41569), Reason: Id: 5848, Initial Margin: -5942.47, Free Margin: 2711.08. # 3. Backtest Handled Error: You have exceeded maximum number of orders (10000), for unlimited orders upgrade your account. # ToDo # 1. Use the TAG property in Orders to fill Name of Strategy that executed that Order # 2. For AlphaModel confidence in Insight, get 52 Week High & Low for Nasdaq in % terms and then confidence = self.percentageChange/52 Week high or Low depending on Long / Short # 3. When checking condition to generate Long or Short Insight, make sure to get last non zero price for Bid and Ask for Lumber Quotes # 4. # ToCheck/ AskQC # 1. # Trade Logic # ALPHA Model """ Securities :Lumber and Nasdaq Resolution:Tick 1.Calculate NASDAQ %age change using NASDAQ yesterday Close & current* Trade Price. 2.Compare Pre-Market LUMBER ASK/BID vs LUMBER yesterday Close 3.Take Positions Based on Following Logic a. Go Long if both True (1) >1% & (2) LUMBER ASK/BID > LUMBER yesterday Close b. Go Short if both True (1) <1% & (2) LUMBER ASK/BID < LUMBER yesterday Close 4. Number of Contracts (Insight Weights) depends on %age change in Nasdaq (1): a. More than 1% absolute change equates to 1 Contracts b. More than 2% absolute change equates to 2 Contracts & so on *current: This is Pre-Market LUMBER (just before market opens)""" # OrderType:LimitOrder """1. check if the target quantity is positive or negative. 2. if negative 2.1 we are shorting then use the BestAsk 2.2 calculate the sell price by increasing the BestAsk by one percent. 2.3 place the limit order at the calculate price. 3. if Positive 2.1 we are longing (buying) then use the BestAsk 2.2 calculate the buy price by decreasing the BestBid by one percent. 2.3 place the limit order at the calculate price."""
from AlgorithmImports import * import numpy as np class MyExecution(ExecutionModel): def __init__(self,algo): self.algo=algo # create the algo instance self.order_properties = OrderProperties() self.order_properties.TimeInForce = TimeInForce.GoodTilDate(self.algo.Time.replace(hour=4, minute=0, second= 0, microsecond=0)) def Execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None: # update the complete set of portfolio targets with the new targets self.algo.targetsCollection.AddRange(targets) if not self.algo.targetsCollection.IsEmpty: for target in self.algo.targetsCollection.Values: # check order entry conditions if target.Quantity != 0: # Is this neccessary? orderPrice = self.GetOrderPrice(target, algorithm) #initiate Trade class trade=Trade(algorithm) ticket=trade.placeMainOrder(target.Symbol, target.Quantity, orderPrice) self.algo.tradesCollection[str(ticket.OrderId)] = trade # ticket = algorithm.LimitOrder(target.Symbol, target.Quantity, orderPrice,None,self.order_properties) # why not creating a dict like this # self.algi.ticketDict[ticket.OrderId]={"OrderType":"Main","StopLossId":None,"TakeProfitId":None} # self.algo.ticketDict[ticket.OrderId] = ['Main',[ticket],None,0] # ticket.UpdateTag('LumberCopyNasdaq' + '_ID_' + str(ticket.OrderId)) self.algo.targetsCollection.Clear() def GetOrderPrice(self, target, algorithm): orderPrice = None if target.Quantity > 0: # Calculate new orderPrice by reducing BestBid by 1% bid = algorithm.Securities[target.Symbol].BidPrice orderPrice = round(bid - (bid*0.02),1) # Less Competitive # orderPrice = round(bid + (bid*0.01),1) # More Competitive elif target.Quantity < 0: # Calculate new orderPrice by increasing BestAsk by 1% ask = algorithm.Securities[target.Symbol].AskPrice orderPrice = round(ask + (ask*0.02),1) # Less Competitive # orderPrice = round(ask - (ask*0.01),1) # More Competitive return orderPrice class Trade(): def __init__(self,algo): self.mainOrderTicket=None self.stopLossTicket=None self.takeProfitTicket=None self.algo=algo def placeMainOrder(self,symbol,quantity,orderPrice): self.mainOrderTicket=self.algo.LimitOrder(symbol=symbol, quantity=quantity, limitPrice=orderPrice) return self.mainOrderTicket def getMainOrderId(self): self.mainOrderTicket.OrderId def placeStopLossOrder(self,quantity,stopPrice,LimitPrice): self.stopLossTicket=self.algo.StopLimitOrder(symbol=self.mainOrderTicket.Symbol, quantity=quantity, stopPrice=stopPrice, limitPrice=limitPrice,tag=str(self.mainOrderTicket.OrderId)) return self.stopLossTicket def placeTakeProfitOrder(self,quantity,LimitPrice): self.takeProfitTicket=self.algo.LimitOrder( symbol=self.mainOrderTicket.Symbol,quantity=quantity, limitPrice=limitPrice,tag=str(self.mainOrderTicket.OrderId)) return self.takeProfitTicket def cancelStopLoss(self): response=self.stopLossTicket.Cancel() if response.IsSuccess(): self.Debug("StopLossOrder with Order_id {} connected to main order {} Cancelled Successfully".format(self.stopLossTicket.OrderId,self.stopLossTicket.Tag)) return True def cancelTakeProfit(self): response=self.takeProfitTicket.Cancel() if response.IsSuccess(): self.Debug("TakeProfit Order with Order_id {} connected to main order {} Cancelled Successfully".format(self.takeProfitTicket.OrderId,self.takeProfitTicket.Tag)) return True def cancelMainOrder(self): response=self.MainOrderTicket.Cancel() if response.IsSuccess(): self.Debug("MainOrder with Order_id {} Cancelled Successfully".format(self.mainOrderTicket.OrderId)) return True def getMainOrderTicket(self): return self.mainOrderTicket def getStopLossOrderTicket(self): return self.stopLossOrderTicket def getTakeProfitTicket(self): return self.takeProfitTicket
from AlgorithmImports import * class MyExecution(ExecutionModel): def Execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None: for target in targets: security = algorithm.Securities[target.Symbol] quantity = OrderSizing.GetUnorderedQuantity(algorithm, target, security) currentContract = algorithm.Securities[security.Mapped] algorithm.Debug(f"target in ExecutionModel-:-{security} & quantity: {quantity}") if quantity != 0: aboveMinimumPortfolio = BuyingPowerModelExtensions.AboveMinimumOrderMarginPortfolioPercentage(currentContract.BuyingPowerModel, currentContract, quantity, algorithm.Portfolio, algorithm.Settings.MinimumOrderMarginPortfolioPercentage) if aboveMinimumPortfolio: algorithm.MarketOrder(currentContract.Symbol, quantity) algorithm.Debug(f"Worked in ExecutionModel")
from AlgorithmImports import * class MyExecution(ExecutionModel): def Execute(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> None: for target in targets: security = algorithm.Securities[target.Symbol] quantity = OrderSizing.GetUnorderedQuantity(algorithm, target, security) currentContract = algorithm.Securities[security.Mapped] algorithm.Debug(f"target in ExecutionModel-:-{security} & quantity: {quantity}") if quantity != 0: aboveMinimumPortfolio = BuyingPowerModelExtensions.AboveMinimumOrderMarginPortfolioPercentage(currentContract.BuyingPowerModel, currentContract, quantity, algorithm.Portfolio, algorithm.Settings.MinimumOrderMarginPortfolioPercentage) if aboveMinimumPortfolio: algorithm.MarketOrder(currentContract.Symbol, quantity) algorithm.Debug(f"Worked in ExecutionModel") for prop in dir(target): value = getattr(target, prop) algorithm.Debug(f"{prop}:{value}")
from AlgorithmImports import * class NasdaqAlpha(AlphaModel): def __init__(self, algo): # Save an Instance of our Main Algorithm self.algo = algo # variable to hold nasdaq percentage change self.algo.percentageChange=None # Check Entry Condition only 30 seconds prior to Market Open self.entryTimeStart = self.algo.Time.replace(hour=9, minute=59, second=30, microsecond=0) self.entryTimeEnd = self.algo.Time.replace(hour=10, minute=2, second= 10, microsecond=0) # ROLLING WINDOWS TO HOLD YESTERDAY'S CLOSE self.nasdaqYesterdayClose = RollingWindow[float](1) self.lumberYesterdayClose = RollingWindow[float](1) #insight arguments self.insightPeriod = timedelta(hours = 1) self.insightDailyCount = 0 #rolling window to handle latest bid and ask self.latestBidRolling = RollingWindow[float](1) self.latestAskRolling = RollingWindow[float](1) # DICT TO HOLD INSIGHT TIME self.insightsTimeBySymbol = {} # LIST AND COLLECTION FOR INSIGHTS self.insights = [] self.insightCollection = InsightCollection() def OnLumberOpen(self): #Resetting Latest Bid And Ask Rolling Window self.latestAskRolling.Reset() self.latestBidRolling.Reset() # GET LUMBER YESTERDAY'S CLOSE lumber_history = self.algo.History(self.algo.lumberSymbol,7,Resolution.Daily) for bar in lumber_history.itertuples(): self.lumberYesterdayClose.Add(bar.close) # GET NASDAQ'S YESTERDAY CLOSE nasdaq_history = self.algo.History(self.algo.nasdaqSymbol,7,Resolution.Daily) for bar in nasdaq_history.itertuples(): self.nasdaqYesterdayClose.Add(bar.close) self.insightDailyCount = 0 # Reset it to 0 every morning # self.algo.Debug(f"Yesterday's Date:{self.algo.Time} Nasdaq Close:{self.nasdaqYesterdayClose[0]}, Lumber Close: {self.lumberYesterdayClose[0]}") def OnLumberClose(self): # Ideally this code should be inside EndOfDay in our Main class # GeneratedTimeUtc : Gets the utc time this insight was generated # CloseTimeUtc : Gets the insight's prediction end time. This is the time when this insight prediction # is expected to be fulfilled. This time takes into account market hours, weekends, as well as the symbol's data resolution insight_properties = ['Symbol','GeneratedTimeUtc','CloseTimeUtc','Direction','EstimatedValue','Weight','Id','Magnitude','Confidence','Period','Score','IsActive','IsExpired'] for insight in self.insights: for prop in insight_properties: if prop in ['GeneratedTimeUtc','CloseTimeUtc']: value = getattr(insight, prop) - timedelta(hours = 5) # Converting UTC to EST else: value = getattr(insight, prop) # self.algo.Debug(f"{prop}:{value}") def OnSecuritiesChanged(self, algorithm,changes): for security in changes.AddedSecurities: if security.Symbol == self.algo.lumberSymbol: # schedule an event to trigger before lumber market opens to get yesterday close for both nasdaq and lumber algorithm.Schedule.On(algorithm.DateRules.EveryDay(security.Symbol), algorithm.TimeRules.AfterMarketOpen(security.Symbol, -2), self.OnLumberOpen) # algorithm.Schedule.On(algorithm.DateRules.EveryDay(security.Symbol), algorithm.TimeRules.BeforeMarketClose(security.Symbol, 2), self.OnLumberClose) for security in changes.RemovedSecurities: if security.Symbol in self.insightsTimeBySymbol: # REMOVE SECURITY FROM DICT self.insightsTimeBySymbol.pop(security.Symbol) def Update(self, algorithm, data): # CHECK IF MARKET HOURS ARE VALID if algorithm.Time < self.entryTimeStart or algorithm.Time > self.entryTimeEnd: return [] insight = None #CHECK IF YESTERDAY'S LUMBER CLOSE AND NASDAQ CLOSE IS READY if self.lumberYesterdayClose.IsReady and self.nasdaqYesterdayClose.IsReady: for security in data.Keys: # algorithm.Debug(f'{security}') ticks=data.Ticks[security] if security == self.algo.nasdaqSymbol: for tick in ticks: if tick.TickType == TickType.Trade: self.algo.percentageChange=((tick.Price - self.nasdaqYesterdayClose[0])/self.nasdaqYesterdayClose[0])*100 # if int(self.algo.nasdaqROCP.Current.Value) != 0: # algorithm.Debug(f"self.algo.percentageChange:{self.algo.percentageChange}, \ # self.algo.nasdaqROCP:{self.algo.nasdaqROCP.Current.Value}, self.algo.nasdaqDailyChange52High:{self.algo.nasdaqDailyChange52High.Current.Value}, self.algo.nasdaqDailyChange52Low:{self.algo.nasdaqDailyChange52Low.Current.Value} ") if security == self.algo.lumberSymbol: for tick in ticks: if tick.TickType == TickType.Quote: algorithm.Debug(f"bid is {tick.BidPrice} ask is {tick.AskPrice}") # check if tick ask is equal to 0.0 and # there is no ask price in rolling window if int(tick.AskPrice) == 0 and not self.latestAskRolling.IsReady: ask = algorithm.Securities[security].AskPrice algorithm.Debug(f"ask was {tick.AskPrice} so using last ask {ask}") # check if tick ask is equal to 0.0 and # there is ask price in rolling window elif int(tick.AskPrice) == 0 and self.latestAskRolling.IsReady: ask = self.latestAskRolling[0] algorithm.Debug(f"ask was {tick.AskPrice} so using last ask from rolling window {ask}") else: ask = tick.AskPrice self.latestAskRolling.Add(ask) # check if tick bid is equal to 0.0 and # there is no bid price in rolling window if int(tick.BidPrice) == 0 and not self.latestBidRolling.IsReady: bid = algorithm.Securities[security].BidPrice algorithm.Debug(f"bid was {tick.BidPrice} so using last bid {bid}") # check if tick bid is equal to 0.0 and # there is Bid price in rolling window elif int(tick.BidPrice) == 0 and self.latestBidRolling.IsReady: bid = self.latestBidRolling[0] algorithm.Debug(f"bid was {tick.BidPrice} so using last bid from rolling window {bid}") else: bid = tick.BidPrice # adding the bid to rolling window self.latestBidRolling.Add(bid) # algorithm.Debug(f'ask:{tick.AskPrice} bid:{tick.BidPrice} time:{algorithm.Time}') #CHECK IF LUMBER ASK ,TRADE IS GREATER THAN YESTERDAY LUMBER CLOSE AND NASDAQ CHANGE IS MORE THAN 1 if ask > self.lumberYesterdayClose[0] and bid > self.lumberYesterdayClose[0] and self.algo.percentageChange and self.algo.percentageChange > 1 and self.ShouldEmitInsight(algorithm.Time,security): algorithm.Debug(f"Position Up: Date{algorithm.Time} Nasdaq ∆:{self.algo.percentageChange},Lumber Yesterday Close:{self.lumberYesterdayClose[0]}, Lumber Ask:{ask}, Lumber Bid:{bid}") insight = Insight(self.algo._lumberContract.Mapped,self.insightPeriod, InsightType.Price, InsightDirection.Up) algorithm.Debug(f"Up Insight generated at: {algorithm.Time}") self.insights.append(insight) #CHECK IF LUMBER ASK ,TRADE IS LESS THAN YESTERDAY LUMBER CLOSE AND NASDAQ CHANGE IS LESS THAN -1 elif bid < self.lumberYesterdayClose[0] and ask < self.lumberYesterdayClose[0] and self.algo.percentageChange and self.algo.percentageChange < -1 and self.ShouldEmitInsight(algorithm.Time,security): algorithm.Debug(f"Position Down: Date{algorithm.Time} Nasdaq ∆:{self.algo.percentageChange},Lumber Yesterday Close:{self.lumberYesterdayClose[0]}, Lumber Ask:{ask}, Lumber Bid:{bid}") # Insight(symbol, period, type, direction, magnitude=None, confidence=None, sourceModel=None, weight=None) insight = Insight(self.algo._lumberContract.Mapped,self.insightPeriod, InsightType.Price, InsightDirection.Down) algorithm.Debug(f"Down Insight generated at: {algorithm.Time}") self.insights.append(insight) #ELSE NO CONDITION MET else: # algorithm.Debug(f"No Condition Met, Date:{algorithm.Time}") pass if insight is not None: self.insightCollection.Add(insight) return self.insights def ShouldEmitInsight(self, utcTime, symbol): generatedTimeUtc = self.insightsTimeBySymbol.get(symbol) self.insightDailyCount +=1 if generatedTimeUtc is not None: # we previously emitted a insight for this symbol, check it's period to see if we should emit another insight if utcTime - generatedTimeUtc < self.insightPeriod and self.insightDailyCount > 1: return False # we either haven't emitted a insight for this symbol or the previous insight's period has expired, so emit a new insight now for this symbol self.insightsTimeBySymbol[symbol] = utcTime return True
from AlgorithmImports import * class NasdaqAlpha(AlphaModel): def __init__(self, algo): self.percentageChange=None # variable to hold nasdaq percentage change self.algo = algo # Save an Instance of our Main Algorithm self.nasdaqYesterdayClose = RollingWindow[float](1) self.lumberYesterdayClose = RollingWindow[float](1) # Lumber & Nasdaq Symbols self.lumberSymbol = self.algo._lumberContract.Symbol self.nasdaqSymbol = self.algo._nasdaqContract.Symbol self.entryTimeStart = self.algo.Time.replace(hour=10, minute=0, second=0, microsecond=0) self.entryTimeEnd = self.algo.Time.replace(hour=15, minute=45, second=0, microsecond=0) #insight arguments self.insightPeriod = timedelta(minutes=60) # self.insightPeriod = Expiry.EndOfDay(self.algo.Time) - timedelta(seconds=1) self.insightsTimeBySymbol = {} self.insights = [] self.insightCollection = InsightCollection() self.count = 0 def OnLumberOpen(self): # get Lumber yesterday close lumber_history = self.algo.History(self.lumberSymbol,1,Resolution.Daily) for bar in lumber_history.itertuples(): self.lumberYesterdayClose.Add(bar.close) # get nasdaq yesterday close nasdaq_history = self.algo.History(self.nasdaqSymbol,1,Resolution.Daily) for bar in nasdaq_history.itertuples(): self.nasdaqYesterdayClose.Add(bar.close) self.algo.Debug(f"Yesterday's Date:{self.algo.Time} Nasdaq Close:{self.nasdaqYesterdayClose[0]}, Lumber Close: {self.lumberYesterdayClose[0]}") def OnLumberClose(self): # Ideally this code should be inside EndOfDay in our Main class # GeneratedTimeUtc : Gets the utc time this insight was generated # CloseTimeUtc : Gets the insight's prediction end time. This is the time when this insight prediction is expected to be fulfilled. This time takes into account market hours, weekends, as well as the symbol's data resolution insight_properties = ['Symbol','GeneratedTimeUtc','CloseTimeUtc','Direction','EstimatedValue','Weight','Id','Magnitude','Confidence','Period','Score','IsActive','IsExpired'] for insight in self.insights: for prop in insight_properties: if prop in ['GeneratedTimeUtc','CloseTimeUtc']: value = getattr(insight, prop) - timedelta(hours = 5) # Converting UTC to EST else: value = getattr(insight, prop) self.algo.Debug(f"{prop}:{value}") # Check if any Insights are Active self.algo.Debug(f"Active Insights: {self.insightCollection.GetActiveInsights(self.algo.UtcTime)} Time {self.algo.Time}") # Check if any Insights are Expired (Also Remove them) self.algo.Debug(f"Expired Insights: {self.insightCollection.RemoveExpiredInsights(self.algo.UtcTime)} Time {self.algo.Time}") def OnSecuritiesChanged(self, algorithm,changes): for security in changes.AddedSecurities: if security.Symbol == self.lumberSymbol: # schedule an event to trigger before lumber market opens to get yesterday close for both nasdaq and lumber # algorithm.Schedule.On(algorithm.DateRules.EveryDay(security.Symbol), algorithm.TimeRules.AfterMarketOpen(security.Symbol, -2), self.OnLumberOpen) # algorithm.Schedule.On(algorithm.DateRules.EveryDay(security.Symbol), algorithm.TimeRules.BeforeMarketClose(security.Symbol, -2), self.OnLumberClose) pass for security in changes.RemovedSecurities: if security.Symbol in self.insightsTimeBySymbol: # self.insightsTimeBySymbol.pop(security.Symbol) pass def Update(self, algorithm, data): if algorithm.Time < self.entryTimeStart or algorithm.Time > self.entryTimeEnd: return [] insights = [] for security in data.Keys: ticks=data.Ticks[security] for tick in ticks: if tick.TickType == TickType.Quote: if tick.BidPrice != 0 and security == self.lumberSymbol and self.ShouldEmitInsight(algorithm.UtcTime, security): algorithm.Debug(f"Position Up Generated: Date{algorithm.Time}") if (self.count % 2) == 0: # If even insights.append(Insight(security, self.insightPeriod, InsightType.Price, InsightDirection.Up, magnitude = None, confidence = None)) else: insights.append(Insight(security, self.insightPeriod, InsightType.Price, InsightDirection.Down, magnitude = None, confidence = None)) self.count += 1 return insights def ShouldEmitInsight(self, utcTime, symbol): generatedTimeUtc = self.insightsTimeBySymbol.get(symbol) if generatedTimeUtc is not None: # we previously emitted a insight for this symbol, check it's period to see if we should emit another insight if utcTime - generatedTimeUtc < self.insightPeriod: return False # we either haven't emitted a insight for this symbol or the previous insight's period has expired, so emit a new insight now for this symbol self.insightsTimeBySymbol[symbol] = utcTime return True
from AlgorithmImports import * import numpy as np class MyPortfolio(PortfolioConstructionModel): def __init__(self,algo,rebalancingFunc=None,portfolioBias=PortfolioBias.LongShort): # rebalancingFunc=Resolution.Daily self.algo=algo # create the algo instance self.portfolioBias=portfolioBias self.setTargets = False def CreateTargets(self, algorithm, insights): tempCounter = 1 """ This method is used to analyze the insights and determine for which insight we need to create portfolio target i.e based on weight magnitude confidence etc..""" targets = [] # list to hold targets for insight in insights: # check if insight respects the portifolio bias if self.RespectPortfolioBias(insight) : # self.algo.Debug(f"Insight in Portfolio Construction:{insight}") # targets.append(PortfolioTarget(insight.Symbol,insight.Direction*1)) # Fills up self.algo.positionCount self.GetPositionCount() # self.algo.Debug(f"Count of positionCount in CreateTargets of PortfolioModel: {abs(self.algo.positionCount)}") # Append PortfolioTargets List with One Order at a Time rather than 1 element with All Order quantity if not self.setTargets: for _ in range(abs(self.algo.positionCount)): # self.algo.Debug(f"tempCounter in CreateTargets of PortfolioModel: {tempCounter}") targets.append(PortfolioTarget(insight.Symbol,np.sign(self.algo.positionCount)*1)) tempCounter +=1 # self.algo.Debug(f"Count of Insights in CreateTargets of PortfolioModel: {len(insights)} at Time: {self.algo.Time}") self.setTargets = True # if targets and not self.setTargets: # for target in targets: # self.algo.Debug(f"Target in Portfolio Construction-:-{target}") # pass # self.setTargets = True return targets def GetPositionCount(self): if np.sign(self.algo.percentageChange * 1) == -1: self.algo.positionCount = math.ceil(self.algo.percentageChange) * 1 elif np.sign(self.algo.percentageChange * 1) == 1: self.algo.positionCount = math.floor(self.algo.percentageChange) * 1 def RespectPortfolioBias(self, insight): """method is used to check if the long,short or both position are allowed by portifolio""" return self.portfolioBias == PortfolioBias.LongShort or insight.Direction == PortfolioBias.Long or insight.Direction == PortfolioBias.Short def ShouldCreateTargetForInsight(self, insight: Insight) -> bool: """ This method is used to check for which insight we are supposed to generate the portfolio target we can use magnitude, weight and other aspects for this""" return True def DetermineTargetPercent(self, activeInsights): """This method is used to calculate the %age of portifolio or no of stocks we want to set""" pass
from AlgorithmImports import * class MyPortfolio(PortfolioConstructionModel): def __init__(self, algo): # super().__init__() self.algo = algo # Save an Instance of our Main Algorithm def CreateTargets(self, algorithm, insights): targets = [] for insight in insights: self.algo.Debug(f"insight in Portfolio Construction:{insight}") targets.append(PortfolioTarget(insight.Symbol, insight.Direction*1)) if targets: for target in targets: self.algo.Debug(f"target in Portfolio Construction-:-{target}") return targets def DetermineTargetPercent(self, activeInsights): self.algo.Debug(f"Inside DetermineTargetPercent in Portfolio Construction:{insight}") for insight in activeInsights: self.algo.Debug(f"active insight in DetermineTargetPercent:{insight}") # result = {} # # give equal weighting to each security # count = sum(x.Direction != InsightDirection.Flat for x in activeInsights) # self.algo.Debug(f"count in DetermineTargetPercent:{count}") # percent = 0.2 if count == 0 else 1.0 / count # for insight in activeInsights: # self.algo.Debug(f"active insight in DetermineTargetPercent:{insight}") # result[insight] = (InsightDirection.Up) * percent # return result def RespectPortfolioBias(self, insight): return True def ShouldCreateTargetForInsight(self, insight: Insight) -> bool: return True
from AlgorithmImports import * class MyRiskManagementModel(RiskManagementModel): def __init__(self, algo): self.algo = algo # Save an Instance of our Main Algorithm self.count = 0 self.target_modified = [] # Adjust the portfolio targets and return them. If no changes emit nothing. def ManageRisk(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> List[PortfolioTarget]: for target in targets: # self.algo.Debug(f"target in RiskManagamenet-:-{target}") pass return targets
from AlgorithmImports import * class MyRiskManagementModel(RiskManagementModel): def __init__(self, algo): self.algo = algo # Save an Instance of our Main Algorithm self.count = 0 self.target_modified = [] # Adjust the portfolio targets and return them. If no changes emit nothing. def ManageRisk(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> List[PortfolioTarget]: for target in targets: self.algo.Debug(f"target in RiskManagamenet-:-{target}") return targets
from AlgorithmImports import * from NasdaqAlpha import * from PortfolioModel import * from ExecutionModel import * from RiskModel import * from orderEnum import * import numpy as n class NasdaqStrategy(QCAlgorithm): def Initialize(self): # self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin) # self.DefaultOrderProperties = InteractiveBrokersOrderProperties() # # Set a Limit Order to be good until market close self.DefaultOrderProperties.TimeInForce = TimeInForce.Day # Set a Limit Order to be good until noon self.order_properties = OrderProperties() self.order_properties.TimeInForce = TimeInForce.GoodTilDate(self.Time.replace(hour=4, minute=0, second= 0, microsecond=0)) # self.DefaultOrderProperties.OutsideRegularTradingHours = True # Set start and end time for backtest self.SetStartDate(2022, 12, 22) self.SetEndDate(2022,12,23) # self.SetEndDate(datetime.now() - timedelta(2)) self.SetCash(1000000) # Lumber security self._lumberContract=self.AddFuture(Futures.Forestry.RandomLengthLumber, Resolution.Tick,dataMappingMode=DataMappingMode.FirstDayMonth,contractDepthOffset=0, dataNormalizationMode=DataNormalizationMode.Raw,extendedMarketHours=True, fillDataForward = True) # Nasdaq security self._nasdaqContract=self.AddFuture(Futures.Indices.MicroNASDAQ100EMini, Resolution.Tick,dataMappingMode = DataMappingMode.OpenInterest, contractDepthOffset=0, dataNormalizationMode = DataNormalizationMode.Raw, extendedMarketHours=True) # Symbols for securities: self.lumberSymbol = self._lumberContract.Symbol self.nasdaqSymbol = self._nasdaqContract.Symbol # Get 52 Week High and 52 Week Low of Nasdaq self.nasdaqROCP = self.ROCP(self.nasdaqSymbol,1, Resolution.Daily) self.nasdaqDailyChange52High = IndicatorExtensions.MAX(self.nasdaqROCP, 252) self.RegisterIndicator(self.nasdaqSymbol, self.nasdaqDailyChange52High, Resolution.Daily) self.nasdaqDailyChange52Low = IndicatorExtensions.MIN(self.nasdaqROCP, 252) self.RegisterIndicator(self.nasdaqSymbol, self.nasdaqDailyChange52Low, Resolution.Daily) # Warm-Up the algorithm self.SetWarmup(timedelta(253),resolution=Resolution.Minute) # Key is OrderID and each row of dictionary has 3 elements: # First is Type (This can be 'Main','StopLoss', 'TakeProfit') # 2nd is Ticket Refernce itself # 3rd element is None for Main Ticket but for 'StopLoss' & 'TakeProfit', it has the ID of associated Main Ticket # 4th element is Number of Times this Ticket was updated # 5th element is Ticket Tag - not using yet self.ticketDict = {} self.positionCount = 0 # example for buy orders self.TARGET_LIMIT_OFFSET = 10 self.STOPLOSS_STOP_OFFSET = 5 # This will be the actual stop loss - this is called the stop price of the stop loss order self.STOPLOSS_LIMIT_OFFSET = 2 # Maximum allowed below stop loss so its called Limit price of the stop loss self.targetsCollection = PortfolioTargetCollection() # Set security initializer seeder = FuncSecuritySeeder(self.GetLastKnownPrices) self.SetSecurityInitializer(lambda security: seeder.SeedSecurity(security)) # Set portifolio consruction model self.SetPortfolioConstruction(MyPortfolio(self)) # Set risk management model # self.AddRiskManagement(TrailingStopRiskManagementModel(maximumDrawdownPercent=0.05)) # self.AddRiskManagement(MaximumUnrealizedProfitPercentPerSecurity(maximumUnrealizedProfitPercent = 0.05)) self.AddRiskManagement(NullRiskManagementModel()) # Default # Set execution model # self.SetExecution(ImmediateExecutionModel()) self.SetExecution(MyExecution(self)) # Set alpha model self.alpha= NasdaqAlpha(self) self.SetAlpha(self.alpha) # self.tradesCollection={} def OnData(self, slice: Slice) -> None: # orderProperties = InteractiveBrokersOrderProperties() # orderProperties.OutsideRegularTradingHours = True # update_fields = UpdateOrderFields() # update_fields.Tag = "Informative order tag" # self.DefaultOrderProperties.TimeInForce = TimeInForce.GoodTilDate(datetime(year, month, day)) for changed_event in slice.SymbolChangedEvents.Values: self.Log(f"Contract rollover from {changed_event.OldSymbol} to {changed_event.NewSymbol}") # OnEndOfDay notifies when (Time) each security has finished trading for the day def OnEndOfDay(self, symbol: Symbol) -> None: pass # self.Debug(f"Finished Trading on {self.Time} for security {symbol}") # When your algorithm stops executing, LEAN calls the OnEndOfAlgorithm method. def OnEndOfAlgorithm(self) -> None: self.Debug("Printing ticketDict") for key,value in self.ticketDict.items(): self.Debug(f"key:{key}, Value:{value}") self.Debug("Algorithm done") # def OnOrderEvent(self, orderEvent: OrderEvent) -> None: # key = orderEvent.OrderId # order = self.Transactions.GetOrderById(key) # ticket = self.Transactions.GetOrderTicket(key) # Get Order Ticket # self.Debug(f"ticket is :{ticket}") # self.Debug("{} In PreCheck OnOrderEvent: A {} order to {} was {} with quantity:{}, ticketDict {}, OrderType:{}".format( # self.Time, get_order_type_name(order.Type), get_order_direction_name(order.Direction), # get_order_status_name(orderEvent.Status), order.Quantity,self.ticketDict.get(key),get_order_type_name(ticket.OrderType))) # # LimitPrice:{} & StopPrice:{} - , ticket.Get(OrderField.LimitPrice),ticket.Get(OrderField.StopPrice) # # Can Remove either ticket or order above # # This gets a list when we pass the orderID key in the self.ticketDict dictionary # extractedOrder = self.ticketDict.get(key) # Returns None if nothing found # # Sometimes we get random orderevents since it takes a while for orders to be placed # if extractedOrder is not None and int(ticket.Quantity) != 0: # if extractedOrder[0] == 'Main': # self.Debug("{} In OnOrderEvent: A {} MainOrder to {} was {} with quantity:{}, OrderType:{},LimitPrice:{}".format( # self.Time, get_order_type_name(order.Type), get_order_direction_name(order.Direction), # get_order_status_name(orderEvent.Status), order.Quantity, get_order_type_name(ticket.OrderType), # ticket.Get(OrderField.LimitPrice))) # elif extractedOrder[0] == 'StopLoss': # self.Debug("{} In OnOrderEvent: A {} StopLossOrder to {} was {} with quantity:{}, OrderType:{},LimitPrice:{} & StopPrice:{}".format( # self.Time, get_order_type_name(order.Type), get_order_direction_name(order.Direction), # get_order_status_name(orderEvent.Status), order.Quantity,get_order_type_name(ticket.OrderType), # ticket.Get(OrderField.LimitPrice),ticket.Get(OrderField.StopPrice))) # elif extractedOrder[0] == 'TakeProfit': # self.Debug("{} In OnOrderEvent: A {} TakeProfitOrder to {} was {} with quantity:{}, OrderType:{},LimitPrice:{}".format( # self.Time, get_order_type_name(order.Type), get_order_direction_name(order.Direction), # get_order_status_name(orderEvent.Status), order.Quantity,get_order_type_name(ticket.OrderType), # ticket.Get(OrderField.LimitPrice))) # if extractedOrder is not None and ticket.Quantity != 0: # if extractedOrder[0] == 'Main': # self.Debug(f"extractedOrder: {extractedOrder}") # # If Order Filled, place Target & Stop Loss # if orderEvent.Status == OrderStatus.Filled: # self.Debug(f"Order filled for {ticket.Symbol} at {self.Time}") # fill_price = orderEvent.FillPrice # # Place StopLoss # stopLossStopPrice = fill_price - np.sign(order.Quantity * 1) * self.STOPLOSS_STOP_OFFSET # stopLossLimitPrice = stopLossStopPrice - np.sign(order.Quantity * 1) * self.STOPLOSS_LIMIT_OFFSET # ticket_SL = self.StopLimitOrder(orderEvent.Symbol, -extractedOrder[1][0].Quantity, stopLossStopPrice,stopLossLimitPrice,None, self.order_properties) # #Updatinng and creating a new dict of dict for stoploss orders # # self.ticketDict[ticket_SL.OrderId]={'OrderType':"SL","MainOrderId":key} # # self.ticketDict[key]["StopLossId"]=ticket_SL.OrderId # self.ticketDict[ticket_SL.OrderId] = ['StopLoss',[ticket_SL],key,0] # # ticket_SL.UpdateTag('LumberCopyNasdaqSL' + '_ID_' + str(ticket_SL.OrderId)) # # Place TakeProfit # takeProfitPrice = fill_price + np.sign(order.Quantity * 1) * self.TARGET_LIMIT_OFFSET # ticket_TP = self.LimitOrder(orderEvent.Symbol, -extractedOrder[1][0].Quantity, takeProfitPrice,None, self.order_properties) # #Updatinng and creating a new dict of dict for stoploss orders # # self.ticketDict[ticket_TP.OrderId]={'OrderType':"TP","MainOrderID":key} # # self.ticketDict[key]["TakeProfitId"]=ticket_SL.OrderId # self.ticketDict[ticket_TP.OrderId] = ['TakeProfit',[ticket_TP],key,0] # # ticket_TP.UpdateTag('LumberCopyNasdaqTP' + '_ID_' + str(ticket_TP.OrderId)) # # If Order Not Filled Yet but Order Submitted - Then Check BestAsk (if Short) or BestBid (if Long), # # If these are different compared to when we placed the order, cancel that order and replace at new Asks & Bids # elif orderEvent.Status == OrderStatus.Submitted: # LimitPrice = ticket.Get(OrderField.LimitPrice) # LatestAsk = self.Securities[ticket.Symbol].AskPrice # LatestBid = self.Securities[ticket.Symbol].BidPrice # # Update LimitPrice if we are Long and Best Bid has Changed # if get_order_direction_name(order.Direction) == 'Buy': # Its a buy order # if LimitPrice != LatestBid: # self.Debug(f"Updating {get_order_direction_name(order.Direction)} order since LatestAsk {LatestAsk} ≠ LimitPrice {LimitPrice}") # self.ticketDict[key][3] += 1 # Increment Update Count in ticketDict # tag = 'LumberCopyNasdaq' + '_ID_' + str(ticket.OrderId) + str('_Updated#') + str(self.ticketDict[key][3]) # response = self.ticketDict[key][1][0].UpdateLimitPrice(LatestBid*1.05, tag) # # Update LimitPrice if we are Short and Best Ask has Changed # elif get_order_direction_name(order.Direction) == 'Sell': # Its a Sell order # if LimitPrice != LatestAsk: # self.Debug(f"Updating {get_order_direction_name(order.Direction)} order since LatestAsk {LatestAsk} ≠ LimitPrice {LimitPrice}") # self.ticketDict[key][3] += 1 # Increment Update Count in ticketDict # tag = 'LumberCopyNasdaq' + '_ID_' + str(ticket.OrderId) + str('_Updated#') + str(self.ticketDict[key][3]) # response = self.ticketDict[key][1][0].UpdateLimitPrice(LatestAsk*0.95, tag) # else: # self.Debug(f"Not Updating {get_order_direction_name(order.Direction)}: LatestAsk:{LatestAsk}, LatestBid:{LatestBid} ,LimitPrice:{LimitPrice}") # if response.IsSuccess: # self.Debug(f"Order with order_id{ticket.OrderId}is Updated successfully") # elif response.IsError: # self.Debug(f"error Updating order with order_id{ticket.OrderId} Error Code:{response.ErrorCode} \ # Error Message:{response.ErrorMessage}") # # StopLoss Executed, so we Cancel TakeProfit # elif extractedOrder[0] == 'StopLoss' and orderEvent.Status == OrderStatus.Filled: # # Find the ID for TakeProfit but with the same MAIN ticket ID: # TP_key = next(key for key, value in self.ticketDict.items() if value[0] == 'TakeProfit' and value[2] == self.ticketDict[key][2]) # self.ticketDict[TP_key][1].Cancel('Canceled TakeProfit') # # TakeProfit Executed, so we Cancel StopLoss # elif extractedOrder[0] == 'TakeProfit' and orderEvent.Status == OrderStatus.Filled: # # Find the ID for StopLoss but with the same MAIN ticket ID as that for TakeProfit Ticket: # SL_key = next(key for key, value in self.ticketDict.items() if value[0] == 'StopLoss' and value[2] == self.ticketDict[key][2]) # self.ticketDict[SL_key][1].Cancel('Canceled StopLoss') # if orderEvent.Status == OrderStatus.Canceled: # self.Debug(f"Order with orderId:{orderEvent.OrderId} got cancelled") # if orderEvent.Status == OrderStatus.Submitted and ticket.Quantity != 0: # self.Debug(f"Order Submitted of OrderType {get_order_type_name(ticket.OrderType)} at ticket time {ticket.Time} ") # if orderEvent.Status == OrderStatus.UpdateSubmitted and ticket.Quantity != 0: # self.Debug(f"Order UpdateSubmitted for ticketDict {self.ticketDict.get(key)} at ticket time {ticket.Time} ") #new Implementation def OnOrderEvent(self, orderEvent): ticket=self.Transactions.GetOrderTicket(orderEvent.OrderId) # check if order is main if ticket.OrderType == OrderType.Limit and orderEvent.OrderId in self.tradesCollection: # get trade trade=self.tradeCollection[str(orderEvent.OrderId)] if ticket.OrderStatus == OrderStatus.Filled: self.Debug("main Order Placed") # calculate limit and stop price fillPrice=orderEvent.FillPrice stopLossStopPrice = fill_price - np.sign(ticket.Quantity * 1) * self.STOPLOSS_STOP_OFFSET stopLossLimitPrice = stopLossStopPrice - np.sign(ticket.Quantity * 1) * self.STOPLOSS_LIMIT_OFFSET # place stoploss order trade.placeStopLossOrder(-ticket.Quantity,stopLossStopPrice,stopLossLimitPrice) # compute take profit price takeProfitPrice = fill_price + np.sign(ticket.Quantity * 1) * self.TARGET_LIMIT_OFFSET trade.placeTakeProfitOrder(-ticket.Quantity,takeProfitPrice) # check if order is take profit elif ticket.OrderType == OrderType.Limit and order.Tag in self.tradesCollection: if ticket.OrderStatus == OrderStatus.Filled: self.Debug(f"take profit placed with order_id {ticket.OrderId}") elif ticket.OrderType == OrderType.StopLimit: if ticket.OrderStatus == OrderStatus.Filled: self.Debug(f"stop loss placed with order_id={ticket.OrderId}")
from AlgorithmImports import * # https://github.com/QuantConnect/Lean/blob/master/Common/Orders/OrderTypes.cs#L87 def get_order_status_name(index): return { 0: 'New', 1: 'Submitted', 2: 'PartiallyFilled', 3: 'Filled', 4: 'None', 5: 'Canceled', 6: 'None', 7: 'Invalid', 8: 'CancelPending', 9: 'UpdateSubmitted ' }[index] def get_order_direction_name(index): return { 0: 'Buy', 1: 'Sell', 2: 'Hold', }[index] def get_order_type_name(index): return { 0: 'Market', 1: 'Limit', 2: 'StopMarket', 3: 'StopLimit', 4: 'MarketOnOpen', 5: 'MarketOnClose', 6: 'OptionExercise', 7: 'LimitIfTouched' }[index]