| Overall Statistics |
|
Total Orders 1034 Average Win 2.65% Average Loss -2.72% Compounding Annual Return 31.618% Drawdown 16.700% Expectancy 0.576 Start Equity 3000 End Equity 571646.23 Net Profit 18954.874% Sharpe Ratio 1.388 Sortino Ratio 1.509 Probabilistic Sharpe Ratio 98.035% Loss Rate 20% Win Rate 80% Profit-Loss Ratio 0.97 Alpha 0.172 Beta 0.436 Annual Standard Deviation 0.144 Annual Variance 0.021 Information Ratio 0.874 Tracking Error 0.155 Treynor Ratio 0.459 Total Fees $1363.73 Estimated Strategy Capacity $13000000.00 Lowest Capacity Asset BRKB R735QTJ8XC9X Portfolio Turnover 1.33% |
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("SPY", Resolution.MINUTE, data_normalization_mode=DataNormalizationMode.RAW, extended_market_hours=True).symbol
self.letf2 = self.add_equity("QQQ", 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
chunk = 0.99 / 3
self.set_holdings([PortfolioTarget(self.hedge, chunk * 2), PortfolioTarget(self.brk, chunk)], True)
return
if price > sma and not self.portfolio[self.letf].invested: #history["close"][0] < sma and
chunk = 0.99 / 3
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)