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:

#3. Required: Significant AUM Capacity

#4. Required: Benchmark to SPY

#5. Use InsightWeightingPCM since we will compute the weights

# 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.TimeRules.AfterMarketOpen("XLE", 10),

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:

# 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

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:

# The weight is factor normialized by the number of symbols
weight = self.factor / len(self.symbols)
self.factor = 0

# Emit Up Price insight
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!