| Overall Statistics |
|
Total Orders 43 Average Win 0.78% Average Loss -0.70% Compounding Annual Return 5.529% Drawdown 3.800% Expectancy 0.161 Start Equity 100000 End Equity 101810.53 Net Profit 1.811% Sharpe Ratio -0.224 Sortino Ratio -0.166 Probabilistic Sharpe Ratio 39.740% Loss Rate 45% Win Rate 55% Profit-Loss Ratio 1.11 Alpha -0.034 Beta 0.388 Annual Standard Deviation 0.066 Annual Variance 0.004 Information Ratio -0.786 Tracking Error 0.083 Treynor Ratio -0.038 Total Fees $41.00 Estimated Strategy Capacity $1400000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 33.53% Drawdown Recovery 56 |
# region imports
from AlgorithmImports import *
# endregion
class WarmUpCustomIndicatorAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2024, 9, 1)
self.set_end_date(2024, 12, 31)
self.set_cash(100_000)
self.settings.seed_initial_prices = True
self._equity = self.add_equity("SPY", Resolution.DAILY)
self._equity.volatility = CustomVolatility(3*21)
# Warm the custom indicator with daily trade bars.
for bar in self.history[TradeBar](self._equity, self._equity.volatility.warm_up_period, Resolution.DAILY):
self._equity.volatility.update(bar)
self.register_indicator(self._equity, self._equity.volatility)
def on_data(self, data: Slice) -> None:
if not self._equity.volatility.is_ready:
return
# Buy if volatility is increasing.
if not self._equity.invested and self._equity.volatility.value > self._equity.volatility.previous.value:
self.set_holdings(self._equity, 1)
# Exit if volatility is decreasing.
elif self._equity.invested and self._equity.volatility.value < self._equity.volatility.previous.value:
self.liquidate()
class CustomVolatility(PythonIndicator):
def __init__(self, period, trading_days_per_year=252):
super().__init__()
self.warm_up_period = period
self._trading_days_per_year = trading_days_per_year
self.value = 0
self._log_return = LogReturn(1)
self._standard_deviation = IndicatorExtensions.of(StandardDeviation(period), self._log_return)
def update(self, input_: BaseData):
# Annualized log-return volatility.
price = input_.value
if price <= 0:
return
self._log_return.update(input_.end_time, price)
if self.is_ready:
self.value = self._standard_deviation.current.value * math.sqrt(self._trading_days_per_year) * 100.0
return self.is_ready
@property
def is_ready(self) -> bool:
return self._standard_deviation.is_ready