Overall Statistics
Total Orders
1122
Average Win
2.52%
Average Loss
-4.26%
Compounding Annual Return
35.615%
Drawdown
26.100%
Expectancy
0.339
Start Equity
3000
End Equity
1009172.33
Net Profit
33539.078%
Sharpe Ratio
1.222
Sortino Ratio
1.264
Probabilistic Sharpe Ratio
83.587%
Loss Rate
16%
Win Rate
84%
Profit-Loss Ratio
0.59
Alpha
0.193
Beta
0.666
Annual Standard Deviation
0.193
Annual Variance
0.037
Information Ratio
1.007
Tracking Error
0.17
Treynor Ratio
0.354
Total Fees
$2165.18
Estimated Strategy Capacity
$5100000.00
Lowest Capacity Asset
QLD TJNNZWL5I4IT
Portfolio Turnover
1.34%
from AlgorithmImports import *
from datetime import datetime
import math
class LeveragedFTLT(QCAlgorithm):
    def initialize(self):
        self.set_start_date(2006, 1, 1)
        self.set_cash(3000)
        self.set_warmup(timedelta(days=250))
        self.Settings.FreePortfolioValuePercentage = 0.02    # say 1%, for bid-ask spread and slippage

        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.hedge = self.add_equity("SHV", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.ADJUSTED, extended_market_hours=True).symbol
        self.hedge2 = self.add_equity("GLD", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.ADJUSTED).symbol
        self.brk = self.add_equity("BRK.B", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.RAW, extended_market_hours=True).symbol
        # spy_daily = self.add_equity("QQQ", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).symbol
        self.SetSecurityInitializer(lambda x: x.SetFillModel(ExtendedMarketHoursFillModel(self)))

        self.spy = self.add_equity("SPY", Resolution.DAILY, data_normalization_mode=DataNormalizationMode.RAW).symbol
        self.sma = self.sma(self.spy, period=200, resolution=Resolution.DAILY)
        self.rsi_10 = self.rsi(self.spy, period=10, 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, 0),
            self.time_rules.after_market_close(self.letf, 0),
            self.add_cash
        )

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

        self.rsi_below = 0

    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
        price = self.securities[self.spy].price
        letf_price = self.securities[self.letf].price

        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.66), PortfolioTarget(self.brk, 0.33)], True)
            return

        if price > sma and not self.portfolio[self.letf].invested: #history["close"][0] < sma and 
            self.set_holdings([PortfolioTarget(self.letf, 0.33), PortfolioTarget(self.letf2, 0.33), PortfolioTarget(self.brk, 0.33)], True)
            return 

        if price > sma and self.portfolio[self.letf].invested and rsi_10 < 29: 
            self.portfolio.cash_book["USD"].add_amount(500.0)
            self.rsi_below += 1
            self.debug(f"RSI below: {self.rsi_below}")
            self.set_holdings([PortfolioTarget(self.letf, 0.33), PortfolioTarget(self.letf2, 0.33), PortfolioTarget(self.brk, 0.33)])
            return 

    def add_cash(self):
        if self.time < self.start_date:
            return

        self.portfolio.cash_book["USD"].add_amount(350.0)

        if self.portfolio[self.letf].invested:
            self.set_holdings([PortfolioTarget(self.letf, 0.33), PortfolioTarget(self.letf2, 0.33), PortfolioTarget(self.brk, 0.33)])
        if self.portfolio[self.hedge].invested:
            self.set_holdings([PortfolioTarget(self.hedge, 0.66), PortfolioTarget(self.brk, 0.33)])

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)