Overall Statistics
Total Orders
359
Average Win
0.65%
Average Loss
-0.32%
Compounding Annual Return
16.270%
Drawdown
13.900%
Expectancy
0.472
Start Equity
100000000
End Equity
124605993.92
Net Profit
24.606%
Sharpe Ratio
0.484
Sortino Ratio
0.569
Probabilistic Sharpe Ratio
40.216%
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
2.04
Alpha
-0.078
Beta
1.126
Annual Standard Deviation
0.137
Annual Variance
0.019
Information Ratio
-0.844
Tracking Error
0.073
Treynor Ratio
0.059
Total Fees
$63330.03
Estimated Strategy Capacity
$6600000.00
Lowest Capacity Asset
VX YK79X28CKDEX
Portfolio Turnover
6.14%
from AlgorithmImports import *

class InverseVolatilityRankAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2023, 3, 1)  # Set Start Date
        self.set_cash(100000000)     # For a large future universe, the fund needed would be large
        
        for contract in ["VX", "ES", "NQ", "YM", "B", "RB", "HO", "NG"]:
            future = self.add_future(contract)
        
        self.schedule.on(self.date_rules.every(DayOfWeek.MONDAY), self.time_rules.at(9, 31), self.rebalance)

    def rebalance(self):
        df = self.history(list(set(x.canonical for x in self.securities.keys())), 22, Resolution.DAILY).close.droplevel([0]).unstack(0).pct_change().dropna()
        inv_vol = 1. / df.std(axis=0, ddof=1)
        inv_vol /= np.sum(inv_vol)
        for contract, weight in inv_vol.items():
            self.set_holdings(self.securities[contract].mapped, weight / 10)

    def on_symbol_changed_events(self, symbols_changed):
        for symbol, changed_event in symbols_changed.items():
            quantity = self.portfolio[changed_event.old_symbol].quantity
            self.liquidate(changed_event.old_symbol)
            if changed_event.new_symbol in self.securities:
                self.market_order(changed_event.new_symbol, quantity // self.securities[symbol].symbol_properties.contract_multiplier)