Smarter Earnings

Analyze what price tends to do on the day of earnings, and find the best strategy to take advantage and profit from an earnings report.

46 mins
Intermediate
youtube-video-thumbnail
Table of Contents
    Add a header to begin generating the table of contents
    Table of Contents
      Add a header to begin generating the table of contents

      The Smarter Earnings Indicator is designed to help you trade the actual day of earnings, after the earnings report is released. In this guide, I will take you step-by-step through building an earnings indicator from scratch in ThinkOrSwim’s scripting language, thinkScript.

      By the end, you’ll have an indicator that tracks earnings beats and misses, calculates gap fills and gap-and-go scenarios, and visualizes whether price movement exceeded expected values.

      Let’s dive into each section!

      Volatility Box Invite

      We are TOS Indicators.com, home of the Volatility Box.

      The Volatility Box is our secret tool, to help us consistently profit from the market place. We’re a small team, and we spend hours every day, after the market close, doing nothing but studying thousands of data points to keep improving and perfecting the Volatility Box price ranges.

      We have two different Volatility Boxes - a Futures Volatility Box and a Stock Volatility Box.

      Futures Volatility Box - Trade Major Markets With an Edge

      Designed For: Futures, Micro-Futures and Index Market Traders
      Supported Models: Hourly Volatility Box models
      Supported Markets: 10 Major Futures Markets

      The Futures Volatility Box comes with:

      • 5 Volatility Models for each market
      • Support for 10 Futures Markets (/ES, /NQ, /YM, /RTY, /CL, /GC, /SI, /ZB, /HG, /NG)
      • Video Setup Guide
      • Trade Plan
      • Access to all members-only resources, including Squeeze Course

      Learn More About the Futures Volatility Box

      Trade futures and micro futures with a consistent volatility edge

      Stock Volatility Box - Powerful Web Based Volatility Platform

      Designed For: Stock and Options Traders
      Supported Models: Hourly and Daily Volatility Box models
      Supported Markets: 10,000+ Stocks and ETFs (new markets added frequently)

      A Stock Volatility Box membership includes access to: 

      • Live Scanner - A powerful scanner we've built from scratch, to scan 10,000 symbols every 2 seconds for new volatility breaches
      • Dashboard - A quick and easy way to view daily volatility model levels online
      • Short Interest Scanner - Short interest, Squeeze, and EMA data to find short squeezes
      • Squeeze Course - All of our proprietary squeeze tools, including robust backtesters
      • All Members Only Indicators - We don't nickel and dime you. Everything really is included.
      • And much more!

      Learn More About the Stock Volatility Box

      Trade stocks and options with a consistent volatility edge

      Understanding the Smarter Earnings Indicator

      Earnings season brings a wealth of information about companies’ financial health, and traders often look for patterns or anomalies surrounding these announcements. The Smarter Earnings Indicator aims to answer questions like:

      • Did a stock beat or miss its earnings estimates?
      • Did the price gap up or down following earnings, and if so, did it fill?
      • Did the price move beyond its expected range?

      By integrating these elements, you get a robust view of how a stock typically responds during earnings announcements, making it easier to make informed trading decisions.

       

      Setting Up Your ThinkOrSwim Workspace

      Before we start scripting, ensure that you’re in the ThinkOrSwim platform. Navigate to Charts > Studies > Edit Studies and select Create to open the thinkScript editor. This is where we’ll enter our code.

      Step 1: User Inputs

      Let’s begin by setting up the inputs for our indicator. These inputs will allow users to customize which elements they want to see on the chart. For example, they may want to display gap fill labels, gap-and-go labels, or expected move labels based on their specific needs.

        
      input expectedMoveLabels = yes;
      input gapFillLabels = yes;
      input gapNGoLabels = yes;
        
        

      These three inputs enable users to toggle various labels on and off. Setting them to yes by default makes them visible unless the user decides to hide them.

      Step 2: Defining Global Variables

      Global variables form the foundation of our calculations. Here, we identify the earnings day and the timing of earnings (before or after the market). These variables will help us group data and later calculate gaps, fills, and trends.

        
      def earningsDay = HasEarnings();
      def beforeMarketEarnings = HasEarnings(EarningTime.BEFORE_MARKET);
      def afterMarketEarnings = HasEarnings(EarningTime.AFTER_MARKET);
      def groupBME = earningsDay and beforeMarketEarnings;
      def groupAME = earningsDay[1] and afterMarketEarnings[1];
      def earningsGroup = groupBME or groupAME;
      def totalEarnings = TotalSum(earningsDay);
        
        

      In this block, earningsDay is set to detect whether an earnings report is scheduled. We differentiate between earnings reported before the market opens (beforeMarketEarnings) and those reported after it closes (afterMarketEarnings). We then define groups based on these criteria to create an overarching earningsGroup variable.

      Step 3: Calculating Earnings Beats and Misses

      To determine whether earnings beat or missed expectations, we’ll compare estimated and actual earnings:

        
      def EstimatedEarnings = if IsNan(getEstimatedEarnings()) then EstimatedEarnings[1] else getEstimatedEarnings();
      def ActualEarnings = if IsNan(getActualEarnings()) then ActualEarnings[1] else getActualEarnings();
      def earningsBeat = if (earningsGroup) and ActualEarnings > EstimatedEarnings then 1 else 0;
      def earningsMiss = if (earningsGroup) and ActualEarnings < EstimatedEarnings then 1 else 0;
        
        

      Here, we handle missing values with IsNan, which allows us to assign values based on previous data. The resulting earningsBeat and earningsMiss variables allow us to track whether the company met, exceeded, or missed expectations.

      Step 4: Identifying Gap Fills

      Next, we’ll determine whether price gapped up or down after earnings, and if so, whether it filled:

        
      def gapUp = if earningsGroup and open > high[1] then 1 else 0;
      def gapDown = if earningsGroup and open < low[1] then 1 else 0;
      def gapUpFilled = if gapUp and low <= high[1] then 1 else 0;
      def gapDownFilled = if gapDown and high >= low[1] then 1 else 0;
      def gapUpFilledAndEarningsMiss = gapUpFilled and earningsMiss;
      def gapDownFilledAndEarningsBeat = gapDownFilled and earningsBeat;
      def totalGapUpFills = TotalSum(gapUpFilled);
      def totalGapDownFills = TotalSum(gapDownFilled);
      def totalGapFills = totalGapUpFills + totalGapDownFills;
      def gapUpDidNotFill = (gapUp and !gapUpFilled);
      def gapDownDidNotFill = (gapDown and !gapDownFilled);
      def gapDidNotFill = gapUpDidNotFill or gapDownDidNotFill;
        
        

      This code identifies upward and downward gaps and checks whether they filled. The variable gapUpFilled evaluates to 1 if a gap up filled, while gapUpDidNotFill returns 1 if it didn’t. These elements allow you to track trends and movement patterns post-earnings.

      Step 5: Calculating Gap N' Go Scenarios

      Sometimes, after gapping, prices continue in the direction of the gap without filling it. This is often called a “Gap N' Go.” The code below identifies bullish and bearish Gap N' Go scenarios:

        
      def gapNGoBullish = if gapUpDidNotFill then 1 else 0;
      def gapNGoBearish = if gapDownDidNotFill then 1 else 0;
      def totalSumGNG = TotalSum(GapNGoBullish) + TotalSum(GapNGoBearish);
      def totalSumGNGBullish =  TotalSum(GapNGoBullish);
      def totalSumGNGBearish =  TotalSum(GapNGoBearish);
        
        

      These Gap N' Go variables track the total number of instances in which a gap did not fill and instead continued in its original direction. This pattern can indicate momentum-driven price action that traders might leverage.

      Step 6: Calculating Expected Moves

      The expected move calculation considers implied volatility to forecast potential price range movement. This enables traders to measure whether actual price movement exceeded expectations.

        
      def expectedEarningsMove = if earningsgroup then  Sqrt(2) / Sqrt(365)  * (2*imp_volatility()[1]) * close[1] else Sqrt(2) / Sqrt(365)  * (2*imp_volatility()[1]) * close[1];
      def actualEarningsMove = if earningsGroup then AbsValue(close[1]-open) else 0;
      def greaterThanExpected = actualEarningsMove > expectedEarningsMove;
      def totalGreaterThanExpected = TotalSum(greaterThanExpected);
      def totalGreaterThanExpectedPct = totalGreaterThanExpected/totalEarnings * 100;
        
        

      Using the square root of time formula, we estimate the price's potential movement based on implied volatility. We compare the actual move with the expected range, and if the actual movement exceeds the range, we mark it for reference.

      Step 7: Adding Labels and Bubbles

      Finally, we add labels and chart bubbles to display the calculated values on the chart. This provides a visual reference to the data generated by the indicator.

        
      AddLabel(gapFillLabels or gapNGoLabels or expectedMoveLabels, "Total # of Earnings: "+totalEarnings, color.white);
      AddLabel(gapFillLabels, "Total Gap Fills: "+totalGapFills, color.cyan);
      AddLabel(gapNGoLabels, "Total Gap N' Go's: "+totalSumGNG, color.green);
      AddLabel(expectedMoveLabels, "# of Actual Greater Than Expected: "+totalGreaterThanExpected, color.yellow);
      AddLabel(expectedMoveLabels, "% of Actual Greater Than Expected: "+totalGreaterThanExpectedPct, color.yellow);
      AddChartBubble(earningsDay, low, "Earnings", Color.DARK_GREEN, no);
        
        

      Each label and bubble displays a specific piece of information. You can toggle their visibility based on the inputs defined earlier.

      Conclusion

      With the Smarter Earnings Indicator, you gain insights into a stock's behavior around earnings announcements. The indicator helps you track earnings beats/misses, identify gaps and fills, and analyze the price action relative to expected moves. By adapting the inputs and settings, you can customize it for your trading style and strategy, whether you want detailed statistics or high-level information.

      downloads

      Download the Smarter Earnings Indicator for ThinkorSwim.

      The download contains a STUDY.ts file, which you can directly import into your ThinkOrSwim platform.

      Download Indicator

      Download the Smarter Earnings Indicator for ThinkorSwim.

      The download contains a STUDY.ts file, which you can directly import into your ThinkOrSwim platform.

      Have your own idea?

      Let us help you turn your trading strategy into a powerful indicator, scan and backtester.