Applying Research
Key Concepts
Introduction
The ultimate goal of research is to produce a strategy that you can backtest and eventually trade live. Once you've developed a hypothesis that you're confident in, you can start working towards exporting your research into backtesting. To export the code, you need to replace QuantBook()
with self
and replace the QuantBook methods with their QCAlgorithm
counterparts.
Workflow
Imagine that you've developed the following hypothesis: stocks that are below 1 standard deviation of their 30-day mean are due to revert and increase in value. The following Research Environment code picks out such stocks from a preselected basket of stocks:
import numpy as np qb = QuantBook() symbols = {} assets = ["SHY", "TLT", "SHV", "TLH", "EDV", "BIL", "SPTL", "TBT", "TMF", "TMV", "TBF", "VGSH", "VGIT", "VGLT", "SCHO", "SCHR", "SPTS", "GOVT"] for i in range(len(assets)): symbols[assets[i]] = qb.add_equity(assets[i],Resolution.MINUTE).symbol # Fetch history on our universe df = qb.history(qb.securities.keys(), 30, Resolution.DAILY) # Make all of them into a single time index. df = df.close.unstack(level=0) # Calculate the truth value of the most recent price being less than 1 std away from the mean classifier = df.le(df.mean().subtract(df.std())).tail(1) # Get indexes of the True values classifier_indexes = np.where(classifier)[1] # Get the Symbols for the True values classifier = classifier.transpose().iloc[classifier_indexes].index.values # Get the std values for the True values (used for magnitude) magnitude = df.std().transpose()[classifier_indexes].values # Zip together to iterate over later selected = zip(classifier, magnitude)
Once you are confident in your hypothesis, you can export this code into the backtesting environment. The algorithm will ultimately go long on the stocks that pass the classifier logic. One way to accommodate this model into a backtest is to create a Scheduled Event that uses the model to pick stocks and place orders.
def initialize(self) -> None: self.set_start_date(2014, 1, 1) self.set_cash(1000000) self.set_benchmark("SPY") self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel()) self.set_execution(ImmediateExecutionModel()) self.assets = ["IEF", "SHY", "TLT", "IEI", "SHV", "TLH", "EDV", "BIL", "SPTL", "TBT", "TMF", "TMV", "TBF", "VGSH", "VGIT", "VGLT", "SCHO", "SCHR", "SPTS", "GOVT"] self.symbols = {} # Add Equity ------------------------------------------------ for i in range(len(self.assets)): self.symbols[self.assets[i]] = self.add_equity(self.assets[i], Resolution.MINUTE).symbol # Set the Scheduled Event method self.schedule.on(self.date_rules.every(DayOfWeek.MONDAY), self.time_rules.after_market_open("IEF", 1), self.every_day_after_market_open)
Now that the Initialize
initialize
method of the algorithm is set, export the model into the Scheduled Event method. You just need to switch qb
with self
and replace QuantBook
methods with their QCAlgorithm
counterparts. In this example, you don't need to switch any methods because the model only uses methods that exist in QCAlgorithm
.
def every_day_after_market_open(self): qb = self # Fetch history on our universe df = qb.history(qb.securities.keys(), 5, Resolution.DAILY) # Make all of them into a single time index. df = df.close.unstack(level=0) # Calculate the truth value of the most recent price being less than 1 std away from the mean classifier = df.le(df.mean().subtract(df.std())).tail(1) # Get indexes of the True values classifier_indexes = np.where(classifier)[1] # Get the Symbols for the True values classifier = classifier.transpose().iloc[classifier_indexes].index.values # Get the std values for the True values (used for magnitude) magnitude = df.std().transpose()[classifier_indexes].values # Zip together to iterate over later selected = zip(classifier, magnitude) # ============================== insights = [] for symbol, magnitude in selected: insights.append(Insight.price(symbol, timedelta(days=5), InsightDirection.UP, magnitude)) self.emit_insights(insights)
With the Research Environment model now in the backtesting environment, you can further analyze its performance with its backtesting metrics. If you are confident in the backtest, you can eventually live trade this strategy.
To view full examples of this Research to Production workflow, see the examples in the menu.
Contribute Tutorials
If you contribute Research to Production tutorials, you'll get the following benefits:
- A QCC reward
- You'll learn the Research to Production methodology to improve your own strategy research and development
- Your contribution will be featured in the community forum
To view the topics the community wants Research to Production tutorials for, see the issues with the WishList tag in the Research GitHub repository. If you find a topic you want to create a tutorial for, make a pull request to the repository with your tutorial and we will review it.
To request new tutorial topics, contact us.