| Overall Statistics |
|
Total Orders 1 Average Win 0% Average Loss 0% Compounding Annual Return 21.644% Drawdown 26.400% Expectancy 0 Start Equity 100000 End Equity 180064.48 Net Profit 80.064% Sharpe Ratio 0.751 Sortino Ratio 0.727 Probabilistic Sharpe Ratio 33.038% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0.056 Beta 0.967 Annual Standard Deviation 0.197 Annual Variance 0.039 Information Ratio 0.725 Tracking Error 0.073 Treynor Ratio 0.153 Total Fees $2.78 Estimated Strategy Capacity $55000000.00 Lowest Capacity Asset QQQ RIWIV7K5Z9LX Portfolio Turnover 0.08% Drawdown Recovery 197 |
# region imports
from AlgorithmImports import *
# endregion
import datetime
class AdaptableSkyBlueBaboon(QCAlgorithm):
def initialize(self):
self.set_start_date(2018, 1, 1)
self.set_end_date(2021, 1, 1)
self.set_cash(100000)
self.qqq = self.add_equity("QQQ", Resolution.HOUR).symbol
self.entryTicket = None
self.stopMarketTicket = None
self.entryTime = self.start_date
self.stopMarketOrderFillTime = self.start_date
self.highestPrice = 0
def on_data(self, data):
# 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 self.portfolio.invested and not self.transactions.get_open_orders(self.qqq):
quantity = self.calculate_order_quantity(self.qqq, 0.9)
self.entryTicket = self.limit_order(self.qqq, quantity, price, "Entry Order")
self.entryTime = self.time
# move limit price if 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 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)
self.debug(updateFields.stop_price)
def on_order_event(self, orderEvent):
if orderEvent.Status != OrderStatus.FILLED:
return
# send stop loss order if entry limit order is filled
if self.entryTicket is not None and self.entryTicket.OrderId == orderEvent.OrderId:
self.stopMarketTicket = self.StopMarketOrder(self.qqq, -self.entryTicket.Quantity, 0.95*self.entryTicket.AverageFillPrice)
# save fill time of stop loss order
if self.stopMarketTicket is not None and self.stopMarketTicket.OrderId == orderEvent.OrderId:
self.stopMarketOrderFillTime = self.time
self.highestPrice = 0