| Overall Statistics |
|
Total Trades 3 Average Win 0% Average Loss -0.68% Compounding Annual Return -6.451% Drawdown 1.300% Expectancy -1 Net Profit -0.541% Sharpe Ratio -1.262 Probabilistic Sharpe Ratio 21.002% Loss Rate 100% Win Rate 0% Profit-Loss Ratio 0 Alpha -0.114 Beta 0.1 Annual Standard Deviation 0.036 Annual Variance 0.001 Information Ratio -5.535 Tracking Error 0.132 Treynor Ratio -0.456 Total Fees $3.00 Estimated Strategy Capacity $30000000.00 Lowest Capacity Asset MSFT R735QTJ8XC9X |
# notes
# I think rolling window is affecting the self.high function? this algo only carrys 2 bars of data so that is probably the reason.
# for charts. the charts lag to it might not be beneficial to actually use this information.
from System.Drawing import Color
class ParticleTachyonCompensator(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2021, 12, 1)
self.SetEndDate(2021, 12, 30)
self.SetCash(100000) # Set Strategy Cash
# add stock with 1min bars
equity = self.AddEquity("MSFT", Resolution.Minute)
self.equity = equity.Symbol
# rolling window for 5min bars (we only want to trade if the 5min bar closes above the breakout)
self.rollingWindow = RollingWindow[TradeBar](2)
# which high do we want to use?
self.high = self.MAX(self.equity, 5 , Resolution.Daily, Field.High)
# create consolidator
self.Consolidate(self.equity, timedelta(minutes=5), self.FiveMinuteBarHandler)
# order tickets
self.entryTicket = None
self.stoplossTicket = None
self.profit1Ticket = None
self.profit2Ticket = None
#captital risk
self.riskCaptial = self.Portfolio.TotalPortfolioValue * 0.05
# charts
#stockPlot = Chart("Trade Plot")
#stockPlot.AddSeries(Series("Buy", SeriesType.Scatter, "$", Color.Green, ScatterMarkerSymbol.Triangle))
#stockPlot.AddSeries(Series("Sell 1", SeriesType.Scatter, "$", Color.Green, ScatterMarkerSymbol.TriangleDown))
#stockPlot.AddSeries(Series("Sell 2", SeriesType.Scatter, "$", Color.Green, ScatterMarkerSymbol.TriangleDown))
#stockPlot.AddSeries(Series("Stop", SeriesType.Scatter, "$", Color.Red, ScatterMarkerSymbol.TriangleDown))
#stockPlot.AddSeries(Series("Price", SeriesType.Line, "$", Color.White))
#self.AddChart(stockPlot)
def OnData(self, data):
# see if the high is ready
if not self.high.IsReady:
return
# see if rolling window (5 min bar) is complete
if not self.rollingWindow.IsReady:
return
# we want to start trading after first bar is complete
if not (self.Time.hour == 9 and self.Time.minute == 36):
return
# chart for current price of the stock
#self.Plot('Trade Plot', 'Price', data.Bars["MSFT"].Close)
# stop/limit parameters (to be optimized)
sp = int(self.GetParameter("stop_percent"))
pp1 = int(self.GetParameter("profit_percent1"))
pp2 = int(self.GetParameter("profit_percent2"))
if self.entryTicket == None:
# next 5min candle closes above the breakout area
if self.rollingWindow[0].Close >= self.high.Current.Value:
# order entry
self.entryTicket = self.MarketOrder("MSFT", 100)
# Enter stop loss order
self.stoplossTicket = self.StopMarketOrder("MSFT", -100, data["MSFT"].Close * (sp / 1000))
# Enter limit order 1
self.profit1Ticket = self.LimitOrder("MSFT", -50, data["MSFT"].Close * (pp1 / 1000))
# Enter limit order 2
self.profit2Ticket = self.LimitOrder("MSFT", -50, data["MSFT"].Close * (pp2 / 1000))
# position sizing
#self.quantity = int(self.riskCaptial / self.stopBuyPrice)
def OnOrderEvent(self, orderevent):
if orderevent.Status != OrderStatus.Filled:
return
# sales entry ticket tells us if we currently have a position.
# references orders below to verfiy
if self.entryTicket != None and self.entryTicket.OrderId == orderevent.OrderId:
self.entryFillPrice = self.entryTicket.Get(AverageFillPrice)
# tells us if the first profit order was triggered
if self.profit1Ticket != None and self.profit1Ticket.OrderId == orderevent.OrderId:
# plots first limit sell price
#self.Plot('Trade Plot', 'Sell 1', orderevent.FillPrice)
# updates stop loss quantity
self.stoplossTicket.UpdateQuantity(-50)
# tells us if the stop order was sent
if self.stoplossTicket != None and self.stoplossTicket.OrderId == orderevent.OrderId:
# plots stop loss fill price
#self.Plot('Trade Plot', 'Stop', orderevent.FillPrice)
# cancels limit profit orders
self.profit1Ticket.Cancel()
self.profit2Ticket.Cancel()
# only one entry ticket, needs to be adjusted for trding multiple stocks
self.entryTicket = None
# tells us if second profit order was triggered
if self.profit2Ticket != None and self.profit2Ticket.OrderId == orderevent.OrderId:
# plots stop loss fill price
#self.Plot('Trade Plot', 'Sell 2', orderevent.FillPrice)
# cancels stop loss order (no more stocks left)
self.stoplossTicket.Cancel()
# only one entry ticket, needs to be adjusted for trding multiple stocks
self.entryTicket = None
# converting 1min to 5min bars
def FiveMinuteBarHandler(self, bar):
self.rollingWindow.Add(bar)