Hey everyone,
"The economy, stupid!" -- originally used as a political phrase in the 90s to explain what determined voter behavior, we're using it here to emphasize the power of macroeconomic data in finding alpha. We've written up an example of how you can incorporate Trading Economics data in your algorithms. The Trading Economics data available covers 28 countries and countless macroeconomic fields -- consumer prices, government bonds, inflation, personal spending, etc.
In this algorithm we use the Energy ETF basket and import three Trading Economics datasets: Natural Gas Stocks Change, API Crude Oil Stock Change, and Gasoline Stocks Change. Finally, we add an Insight Weighting Portfolio Construction Model, and Immediate Execution Model, and a Scheduled Event in which we'll perform our analysis and generate Insights.
def Initialize(self):
#1. Required: Five years of backtest history
self.SetStartDate(2014, 1, 1)
#2. Required: Alpha Streams Models:
self.SetBrokerageModel(BrokerageName.AlphaStreams)
#3. Required: Significant AUM Capacity
self.SetCash(1000000)
#4. Required: Benchmark to SPY
self.SetBenchmark("SPY")
#5. Use InsightWeightingPCM since we will compute the weights
self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
# Add TradingEconomicsCalendar for Energy Data
us = TradingEconomics.Calendar.UnitedStates
self.nat = self.AddData(TradingEconomicsCalendar, us.NaturalGasStocksChange).Symbol
self.oli = self.AddData(TradingEconomicsCalendar, us.ApiCrudeOilStockChange).Symbol
self.gas = self.AddData(TradingEconomicsCalendar, us.GasolineStocksChange).Symbol
# Energy Basket
tickers = ["XLE", "IYE", "VDE", "USO", "XES", "XOP",
"UNG", "ICLN", "ERX", "ERY", "SCO", "UCO",
"AMJ", "BNO", "AMLP", "OIH", "DGAZ", "UGAZ", "TAN"]
# Add Equity ----------------------------------------------
self.symbols = [self.AddEquity(x).Symbol for x in tickers]
self.factor = 0
# Emit insights 10 minutes after market open to
# try to ensure all price data is from the current day
self.Schedule.On(self.DateRules.EveryDay("XLE"),
self.TimeRules.AfterMarketOpen("XLE", 10),
self.EveryDayAfterMarketOpen)
In OnData, we iterate over the Trading Economics data and compare the forecasted production values against the actual production values for each of our supplementary data sources. If the actual production was worse than the forecast, then we set the weighting factor to our minimum of 0.1. Otherwise, we use 1 - (actual production / forecasted production). If this is greater than 1, then we cap the factor at 1 so we don't try to assign weights that don't sum to 1. The worst-case floor of 0.1 this provides us with some investment but minimizes our exposure.
def OnData(self, data):
# Discard updates before 10 to avoid EveryDayAfterMarketOpen running with today's data
if self.Time.hour < 10:
return
# Compute the factor based on the Actual vs Forecast values
for kvp in data.Get(TradingEconomicsCalendar):
calendar = kvp.Value
actual = calendar.Actual
# The reference will be the Forecast, but if not available, use the Previous
reference = calendar.Forecast
if reference is None or reference == 0:
reference = calendar.Previous
if reference is None or reference == 0:
reference = actual
# Actual was worse than the reference.
# Bad. Reduce all positions to a minimum
if actual < reference:
self.factor = 0.1
continue
self.factor = max(0.1, min(1, 1 - actual / reference))
In the Scheduled Event EveryDayAfterMarketOpen we create weights for each symbol based on the calculated factor.
def EveryDayAfterMarketOpen(self):
if self.factor == 0:
return
# The weight is factor normialized by the number of symbols
weight = self.factor / len(self.symbols)
self.factor = 0
# Emit Up Price insight
self.EmitInsights([
Insight.Price(x, timedelta(15), InsightDirection.Up, None, None, None, weight)
for x in self.symbols])
This data is certainly a different beast than conventional price data, but it is also immensely informative. Adding macroeconomic data to inform your algorithm could be a huge source of untapped alpha!
Jared Broad
Unfortunately due to lack of interest we we removed Trading Economics data in November-December 2019.
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
Jack Simonson
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!