Overall Statistics
Total Orders
287
Average Win
1.02%
Average Loss
-1.00%
Compounding Annual Return
15.095%
Drawdown
27.000%
Expectancy
0.344
Start Equity
100000
End Equity
192150.58
Net Profit
92.151%
Sharpe Ratio
0.565
Sortino Ratio
0.69
Probabilistic Sharpe Ratio
20.312%
Loss Rate
33%
Win Rate
67%
Profit-Loss Ratio
1.02
Alpha
0.083
Beta
0.102
Annual Standard Deviation
0.163
Annual Variance
0.026
Information Ratio
0.007
Tracking Error
0.228
Treynor Ratio
0.905
Total Fees
$392.11
Estimated Strategy Capacity
$240000.00
Lowest Capacity Asset
EDZ U8JOSZGR4OKL
Portfolio Turnover
0.66%
from AlgorithmImports import *
from scipy.optimize import minimize

class LeverageEtfRiskParity(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2020, 1, 1)
        self.set_cash(100000)
        self.symbols = [self.add_equity(ticker, data_normalization_mode=DataNormalizationMode.RAW).symbol for ticker in ["TQQQ", "TMF", "EDZ", "UGL"]]
        self.schedule.on(self.date_rules.week_start(), self.time_rules.at(8, 0), self.rebalance)
        self.settings.minimum_order_margin_portfolio_percentage = 0.01

    def rebalance(self):
        ret = self.history(self.symbols, 253, Resolution.DAILY).close.unstack(0).pct_change().dropna()

        x0 = [1/ret.shape[1]] * ret.shape[1]
        constraints = {"type": "eq", "fun": lambda w: np.sum(w) - 1}
        bounds = [(0, 1)] * ret.shape[1]
        opt = minimize(lambda w: 0.5 * (w.T @ ret.cov() @ w) - np.array(x0) @ w, x0=x0, constraints=constraints, bounds=bounds, tol=1e-8, method="SLSQP")

        self.set_holdings([PortfolioTarget(symbol, weight) for symbol, weight in zip(ret.columns, opt.x)])