| Overall Statistics |
|
Total Orders 4060 Average Win 0.08% Average Loss -0.09% Compounding Annual Return 0.215% Drawdown 5.900% Expectancy 0.013 Start Equity 100000 End Equity 102113.24 Net Profit 2.113% Sharpe Ratio -1.32 Sortino Ratio -0.833 Probabilistic Sharpe Ratio 0.036% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 0.97 Alpha -0.025 Beta 0.038 Annual Standard Deviation 0.017 Annual Variance 0 Information Ratio -0.673 Tracking Error 0.143 Treynor Ratio -0.575 Total Fees $0.00 Estimated Strategy Capacity $50000000.00 Lowest Capacity Asset SPY R735QTJ8XC9X Portfolio Turnover 38.27% |
# region imports
from AlgorithmImports import *
import random
from statsmodels.tsa.regime_switching.markov_regression import MarkovRegression
# endregion
class FearAndGreedExampleAlgorithm(QCAlgorithm):
def initialize(self) -> None:
self.set_start_date(2015, 7, 12)
self.set_end_date(2025, 4, 1)
self.set_cash(100_000)
# Set the random seed.
random.seed(42)
# Set the flag of whether or not to use the regime filter.
self._filter = True # False
self._probability_of_trade = 0.01 # per minute
# Add the Fear and Greed Index.
self._index = self.add_data(FearGreedIndex, 'FG')
self._index.history = self.history(self._index.symbol, datetime(2014, 7, 1), self.time).loc[self._index.symbol].qcindex
self._index.regime = None
# Add the SPY to trade.
self._equity = self.add_equity('SPY')
self._equity.set_fee_model(ConstantFeeModel(0)) # Remove fees.
# Liquidate positions at market close.
self.schedule.on(self.date_rules.every_day(self._equity.symbol), self.time_rules.before_market_close(self._equity.symbol, 1), self.liquidate)
def on_data(self, data: Slice) -> None:
if self._equity.symbol in data and self._equity.exchange.hours.is_open(self.time + timedelta(minutes=1), False):
# Check if we should trade.
trade = random.random() < self._probability_of_trade
if not trade:
return
if self._filter and self._index.regime == 1: # If filter is on, only trade during the fear regime.
return
self.market_order(self._equity.symbol, 100 if not self.portfolio.invested else -100)
# Wait until the Fear and Greed dataset has new data.
if self._index.symbol not in data:
return
self._index.history.loc[self.time] = self._index.close
# Fit the HMM and detect the current regime.
regimes = pd.Series(
MarkovRegression(self._index.history, k_regimes=2).fit().smoothed_marginal_probabilities.values.argmax(axis=1),
index=self._index.history.index
)
# Sanity check: Ensure that regime 0=fear and 1=greed
self.plot('Regimes Mean', 'Fear', self._index.history[regimes[regimes == 0].index].mean())
self.plot('Regimes Mean', 'Greed', self._index.history[regimes[regimes == 1].index].mean())
# Save the current regime.
self._index.regime = regimes.iloc[-1]
self.plot('Regime', 'Current', self._index.regime)