Overall Statistics |
Total Orders 24 Average Win 6.24% Average Loss -3.72% Compounding Annual Return 15.983% Drawdown 12.600% Expectancy 0.461 Start Equity 100000 End Equity 134412.37 Net Profit 34.412% Sharpe Ratio 0.642 Sortino Ratio 0.662 Probabilistic Sharpe Ratio 41.094% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 1.68 Alpha 0.08 Beta 0.38 Annual Standard Deviation 0.127 Annual Variance 0.016 Information Ratio 0.473 Tracking Error 0.165 Treynor Ratio 0.214 Total Fees $33.46 Estimated Strategy Capacity $980000000.00 Lowest Capacity Asset QQQ RIWIV7K5Z9LX Portfolio Turnover 2.83% |
# region imports from AlgorithmImports import * # endregion class VirtualAsparagusSheep(QCAlgorithm): def initialize(self): self.set_start_date(2022, 1, 1) self.set_end_date(2024, 1, 1) self.set_cash(100000) self.qqq = self.add_equity("QQQ", Resolution.DAILY).symbol # qqq.set_data_normalization_mode(DataNormalizationMode.RAW) self.entryTicket = None self.stopMarketTicket = None self.entryTime = datetime.min self.stopMarketOrderFillTime = datetime.min self.highestPrice = 0 self.set_benchmark("QQQ") # self.set_brokerage_model(BrokerageName.INTERACTIVE_BROKERS_BROKERAGE, AccountType.CASH) def on_data(self, data: Slice): # wait 30 days after last exit if (self.time - self.stopMarketOrderFillTime).days < 30: return price = self.securities[self.qqq].price # send entry limit order if not already invested or sent the order if not self.portfolio.invested and not self.transactions.get_open_orders(self.qqq): quantity = self.calculate_order_quantity(self.qqq, 0.9) # LIMIT ORDER SENT HERE self.entryTicket = self.limit_order(self.qqq, quantity, price, "Entry order") self.entryTime = self.time # move limit price if limit order not filled after 1 day if (self.time - self.entryTime).days > 1 and self.entryTicket.status != OrderStatus.FILLED: self.entryTime = self.time updateFields = UpdateOrderFields() updateFields.limit_price = price self.entryTicket.update(updateFields) # move up trailing stop price if invested and stop loss ticket exists if self.stopMarketTicket is not None and self.portfolio.invested: if price > self.highestPrice: self.highestPrice = price updateFields = UpdateOrderFields() updateFields.stop_price = price * 0.95 self.stopMarketTicket.update(updateFields) def on_order_event(self, orderEvent): # waiting if orderEvent.status != OrderStatus.FILLED: return # send trailing stop loss order if entry limit order is filled if self.entryTicket is not None and self.entryTicket.order_id == orderEvent.order_id: # STOP LOSS ORDER SENT HERE self.stopMarketTicket = self.stop_market_order(self.qqq, -self.entryTicket.quantity, 0.95 * self.entryTicket.average_fill_price) # save fill time of stop loss order if self.stopMarketTicket is not None and self.stopMarketTicket.order_id == orderEvent.order_id: self.stopMarketOrderFillTime = self.time self.highestPrice = 0