Created with Highcharts 12.1.2EquityJan 2021Jan…May 2021Sep 2021Jan 2022May 2022Sep 2022Jan 2023May 2023Sep 2023Jan 2024May 2024Sep 2024Jan 2025May 20257.5M10M12.5M-40-20000.10.2-1010500k1,000k01M2M050100
Overall Statistics
Total Orders
6157
Average Win
0.14%
Average Loss
-0.11%
Compounding Annual Return
-1.148%
Drawdown
22.000%
Expectancy
-0.078
Start Equity
10000000
End Equity
9521095.29
Net Profit
-4.789%
Sharpe Ratio
-0.378
Sortino Ratio
-0.433
Probabilistic Sharpe Ratio
0.516%
Loss Rate
58%
Win Rate
42%
Profit-Loss Ratio
1.22
Alpha
-0.035
Beta
-0.034
Annual Standard Deviation
0.097
Annual Variance
0.009
Information Ratio
-0.537
Tracking Error
0.171
Treynor Ratio
1.067
Total Fees
$215945.89
Estimated Strategy Capacity
$15000.00
Lowest Capacity Asset
ALTR R735QTJ8XC9X
Portfolio Turnover
1.83%
# region imports
from AlgorithmImports import *
# endregion

class GeekyAsparagusViper(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2021, 1, 1)
        self.set_end_date(2025, 4, 1)
        self.set_cash(10_000_000)
        # Add a universe of the 100 smallest assets in IWM.
        etf = Symbol.create('IWM', SecurityType.EQUITY, Market.USA)
        date_rule = self.date_rules.week_start(etf, 1)
        self.universe_settings.schedule.on(date_rule)
        self._week = 0
        self._universe = self.add_universe(self.universe.etf(etf, universe_filter_func=self._select_assets))
        # Rebalance the portfolio every 2 weeks.
        self.schedule.on(date_rule, self.time_rules.after_market_open(etf, 1), self._rebalance)

    def _select_assets(self, constituents):
        # Only update the universe every 2 weeks.
        week = self.time.isocalendar()[1]
        if abs(week - self._week) < 2:
            return []
        self._week = week
        # Split assets into long/short groups based on ETF weight.
        sorted_by_weight = [c.symbol for c in sorted(constituents, key=lambda c: c.weight)]
        self._longs = sorted_by_weight[-100:]
        self._shorts = sorted_by_weight[:100]
        return self._longs + self._shorts

    def _rebalance(self):
        if not self._longs:
            return
        self.set_holdings([PortfolioTarget(s, 0.5/len(self._longs)) for s in self._longs] + [PortfolioTarget(s, -0.5/len(self._shorts)) for s in self._shorts], True)
        self._longs = []
        self._shorts = []