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