Day 9 - Adding a Dividend Filter to The Wheel Screener and LEAPS Screener

An overlooked but valuable filter for income-focused investors

Written by Chris on December 9th, 2025

This post is part of the 'The 12 Days of Full Stack Dev' series, an adventure through full stack fintech app development. Join me through the first 12 days of December as we develop a variety of new features, fixes, and components within the Full Stack Craft fintech family. For the full list of days and topics in this series, see the original post: The 12 Days of Full Stack Dev.

Filters within Large Screeners

The Wheel Screener already has a robust mechanism for filtering the daily options data set which we compile from the previous closes' options data. However, one filter that has been requested multiple times by users is the ability to filter stocks based on their dividend yield. This is particularly useful for income-focused investors who want to ensure that the stocks they are considering for options trading also provide a steady income stream through dividends.

Let's get into the code changes for how we added this feature to both The Wheel Screener and LEAPS Screener.

Filter Architecture

Almost every filter that we have available across the dataset is numerical in nature. To keep the UI as informative as possible, at the completion of each dataset, we calculate the minimum and maximum values for each numerical column, and use those to set the bounds of a range slider component. This allows users to quickly see the distribution of values and select their desired range.

We'll have to add the dividend yield to this list of numerical columns that we calculate min/max values for. We have one, dataset_info for The Wheel Screener, and dataset_info_leaps for LEAPS Screener, in short, the two modification scripts are:

ALTER TABLE public.dataset_info
ADD COLUMN dividend_yield_min double precision null,
ADD COLUMN dividend_yield_max double precision null;
ALTER TABLE public.dataset_info_leaps
ADD COLUMN dividend_yield_min double precision null,
ADD COLUMN dividend_yield_max double precision null;

We then have a function that runs at the completion of each dataset which sets these min/max values, so we'll have to modify that as well (this is a paraphrased version of the function):

DECLARE
    min_max_data RECORD;
BEGIN
    -- Min/Max across numeric columns
    SELECT
        --...all other min/max calculations...,
        MIN(dividend_yield) AS dividend_yield_min, MAX(dividend_yield) AS dividend_yield_max
    INTO min_max_data
    FROM options_strategies_leaps;

    INSERT INTO dataset_info_leaps (
        -- ...all other columns...
        dividend_yield_min, dividend_yield_max
    ) VALUES (
        -- ...all other values...
        min_max_data.dividend_yield_min, min_max_data.dividend_yield_max
    );
END;

Client Side Changes

Now, since I'm a React Wizard™️, the filter sliders client side are all derived from a simple config:

import SliderUnitType from '../enums/SliderType'
import IOption from '../interfaces/IOption'

export interface ISliderConfigItem {
  label: string
  property: keyof IOption
  unitType: SliderUnitType
  multiplier: number
}

// almost identical to The Wheel Screener config but we show net credit instead of net debit
export const wheelScreenerSlidersConfig: Array<ISliderConfigItem> = [
  // ..many other sliders here ...
  { label: 'Dividend Yield', property: 'dividendYield', unitType: SliderUnitType.PERCENT, multiplier: 1 }
]

// and of course the LEAPS Screener config
export const leapsScreenerSlidersConfig: Array<ISliderConfigItem> = [
  // ..many other sliders here ...
  { label: 'Dividend Yield', property: 'dividendYield', unitType: SliderUnitType.PERCENT, multiplier: 1 }
]

// and the fancy export - giving away some secret sauce here - we use a constants config combined with matching of a gatsby env variable when determining what site we are building
export sliderConfig = process.env.GATSBY_PRODUCT_NAME === Constants.PRODUCT_NAMES.LEAPS_SCREENER
  ? leapsScreenerSlidersConfig
  : wheelScreenerSlidersConfig

From there, everything more or less "just works"! Thanks for tuning in for Day 9 of The 12 Days of Full Stack Dev! Tomorrow, we'll be adding a full Tradier integration and OAuth flow to VannaCharm for real-time dealer exposure calculations. See you then!

More posts:

footer-frame