Created with Highcharts 12.1.2Equity200720082009201020112012201320142015201620172018201920202021202220232024202501M2M-50-25000.20.401205M10M010M20M02040
Overall Statistics
Total Orders
283
Average Win
17.70%
Average Loss
-5.27%
Compounding Annual Return
35.936%
Drawdown
38.000%
Expectancy
1.210
Start Equity
5000
End Equity
1495963.66
Net Profit
29819.273%
Sharpe Ratio
1.117
Sortino Ratio
1.179
Probabilistic Sharpe Ratio
64.694%
Loss Rate
49%
Win Rate
51%
Profit-Loss Ratio
3.36
Alpha
0.201
Beta
0.689
Annual Standard Deviation
0.22
Annual Variance
0.048
Information Ratio
0.915
Tracking Error
0.197
Treynor Ratio
0.357
Total Fees
$2481.75
Estimated Strategy Capacity
$2600000.00
Lowest Capacity Asset
SSO TJNNZWL5I4IT
Portfolio Turnover
1.94%
from AlgorithmImports import *

class LeveragedFTLT(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2006, 6, 1)
        self.set_cash(5000)
        self.set_warmup(timedelta(days=250))

        self.letf = self.add_equity("SSO", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.RAW, extended_market_hours=True).symbol
        self.letf2 = self.add_equity("QLD", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.RAW, extended_market_hours=True).symbol
        self.spy = self.add_equity("SPY", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.RAW, extended_market_hours=True).symbol
        self.hedge = self.add_equity("BIL", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.ADJUSTED, extended_market_hours=True).symbol
        self.hedge2 = self.add_equity("GLD", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.RAW).symbol

        # spy_daily = self.add_equity("QQQ", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).symbol
        self.SetSecurityInitializer(lambda x: x.SetFillModel(ExtendedMarketHoursFillModel(self)))

        spy_daily = self.add_equity("SPY", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).symbol
        self.sma = self.sma(spy_daily, period=200, resolution=Resolution.DAILY)
        self.srsi = self.srsi(spy_daily, 14, 14, 3, 3)
        self.rsi_10 = self.rsi(spy_daily, period=10, resolution=Resolution.DAILY)
        self.rsi_2 = self.rsi(spy_daily, period=2, resolution=Resolution.DAILY)

        self.schedule.on(
            self.date_rules.week_end(self.letf),
            self.time_rules.after_market_close(self.letf, 0),
            self.trade
        )

        self.schedule.on(
            self.date_rules.month_end(self.letf),
            self.time_rules.after_market_close(self.letf, 0),
            self.add_cash
        )

        self.risk_off_price = 0
        self.buyDip1 = False
        self.buyDip2 = False

    def trade(self):
        if not self.sma.is_ready or not self.rsi_10.is_ready or self.time < self.start_date: 
            return 
        
        sma = self.sma.current.value
        rsi_10 = self.rsi_10.current.value
        rsi_2 = self.rsi_2.current.value
        price = self.securities[self.spy].price

        # if not self.portfolio.invested:
        #     self.set_holdings(self.letf, 1)

        history = self.history(self.spy, 2, Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW)
        if price < sma and not self.portfolio[self.hedge].invested: #history["close"][0] > sma and 
            # self.set_holdings([PortfolioTarget(self.hedge, 0.5), PortfolioTarget(self.hedge2, 0.5)], True)
            self.set_holdings([PortfolioTarget(self.hedge, 0.5), PortfolioTarget(self.hedge2, 0.5)], True)
            self.risk_off_price = price
            return
        
        # if price < sma and not self.buyDip1 and self.risk_off_price > 0 and price / self.risk_off_price >= 0.3 and self.portfolio[self.hedge].invested:
        #     self.set_holdings([PortfolioTarget(self.hedge, 0.9), PortfolioTarget(self.letf, 0.1)])
        #     self.buyDip1 = True

        # if price < sma and not self.buyDip2 and self.risk_off_price > 0 and price / self.risk_off_price >= 0.6 and self.portfolio[self.hedge].invested:
        #     # self.set_holdings([PortfolioTarget(self.hedge, 0.8), PortfolioTarget(self.letf, 0.2)])
        #     self.set_holdings(self.hedge, 0.9)
        #     self.buyDip2 = True

        if price > sma and not self.portfolio[self.letf].invested: #history["close"][0] < sma and 
            self.set_holdings([PortfolioTarget(self.letf, 0.5), PortfolioTarget(self.letf2, 0.5)], True)
            self.risk_off_price = 0
            self.buyDip1 = False
            self.buyDip2 = False
            return 
                
        if rsi_10 < 29 and price > sma and self.portfolio[self.letf].invested: 
            self.set_holdings([PortfolioTarget(self.letf, 0.5), PortfolioTarget(self.letf2, 0.5)])
            return 

    def add_cash(self):
        if self.time < self.start_date:
            return
        self.portfolio.cash_book["USD"].add_amount(800.0)
        # if self.portfolio[self.letf].invested:
        #     self.set_holdings(self.letf, 1)
        # if self.portfolio[self.hedge].invested:
        #     self.set_holdings(self.hedge, 1)

    def on_order_event(self, order_event):
        self.log(f"Time: {self.time} | Event: {order_event}")

class ExtendedMarketHoursFillModel(FillModel):

    def __init__(self, algo):
        self.algo = algo

    def Fill(self, parameters):
        security = parameters.Security
        order = parameters.Order
        utcTime = pytz.timezone("America/New_York").localize(self.algo.Time, is_dst=None).astimezone(pytz.utc)
        order_event = OrderEvent(order, utcTime, OrderFee.Zero)
        order_event.FillPrice = security.Price
        order_event.Status = OrderStatus.Filled
        order_event.FillQuantity = order.Quantity
        return Fill(order_event)