| Overall Statistics |
|
Total Orders 1099 Average Win 2.26% Average Loss -3.74% Compounding Annual Return 33.553% Drawdown 26.200% Expectancy 0.352 Start Equity 3000 End Equity 749002.07 Net Profit 24866.736% Sharpe Ratio 1.195 Sortino Ratio 1.224 Probabilistic Sharpe Ratio 81.716% Loss Rate 16% Win Rate 84% Profit-Loss Ratio 0.60 Alpha 0.178 Beta 0.658 Annual Standard Deviation 0.185 Annual Variance 0.034 Information Ratio 0.962 Tracking Error 0.162 Treynor Ratio 0.336 Total Fees $1813.93 Estimated Strategy Capacity $4800000.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(250.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)