Corporate Action Adjusted Backtesting logo

Corporate Action Adjusted Backtesting

Community
HimanshuJ16
corporate-action-adjusted-backtesting

Use when a stock split, reverse split or cash dividend puts artificial gaps in a backtest's price history and fabricates signals; builds a CRSP-convention backward-adjusted series for signals while keeping dividend cash accounted separately.

Overview

PublisherHimanshuJ16
RepositoryAlgo-Trading-Skills
Skill namecorporate-action-adjusted-backtesting
Stars
50
Forks
7
Bundled files
5
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 5 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by HimanshuJ16 on GitHub. Read the source before you install it.

Installation

Install the Corporate Action Adjusted Backtesting AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/HimanshuJ16/Algo-Trading-Skills/tree/main/skills/corporate-action-adjusted-backtesting
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/HimanshuJ16/Algo-Trading-Skills.git /tmp/Algo-Trading-Skills
mkdir -p .claude/skills
cp -r /tmp/Algo-Trading-Skills/skills/corporate-action-adjusted-backtesting .claude/skills/corporate-action-adjusted-backtesting
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Corporate Action Adjusted Backtesting in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Corporate Action Adjusted Backtesting on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Corporate Action Adjusted Backtesting is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

When to Use

Use this skill when a backtest reads historical equity or ETF prices over a window that contains a stock split, reverse split, or cash dividend. Raw venue prices contain artificial gaps at every such event — a 4-for-1 split prints as a 75% overnight crash — so technical indicators computed on them (SMA crossovers, RSI, Bollinger bands, any return series) fire false signals. Adjusted prices fix the signal side and break the execution side: they are not the prices anyone traded at, so sizing orders or debiting cash from them corrupts the portfolio's share count and cash balance.

CorporateActionAdjuster resolves that by carrying both series on every bar. Each AdjustedBarData exposes the raw OHLCV as printed by the venue, plus an adjusted OHLCV and the two factors that produced it:

  • caf — the price factor. CAF_t = prod(alpha_E) over every event with ex-date E > t, anchored so the most recent bar has caf == 1.0.
  • volume_caf — the share-count factor, built from split events only.

When NOT to Use

  • You need a total-return series. Multiplying prices by 1 - D/P removes the ex-date price drop; it does not credit the cash. Dividend PnL must be credited separately, from the raw close and the position held on the ex-date. Using this module's adjusted prices as a return series and also crediting dividends double-counts them.
  • You are building a continuous futures series. Rolling contracts stitch on a ratio or difference basis at the roll date, not on a corporate action calendar. See synthetic-continuous-futures-contract-construction.
  • The event is a spin-off, merger, rights issue or return of capital. Only splits, reverse splits and ordinary cash dividends are modelled. A spin-off's factor depends on the when-issued value of the distributed security and must be supplied out of band.
  • You need the corporate action data itself. Ingestion, vendor parity and the declaration/ex/record/pay lifecycle belong to corporate-action-event-calendar-integration.
  • You are reconciling two vendors' already-adjusted series. Vendors differ on dividend treatment and rounding; see vendor-specific-adjustment-methodology-reconciliation.

Prerequisites

  • A corporate action log with, per event: ex-date (not the declaration, record or pay date), type, and value. value is the share multiplier for splits (2.0 for 2-for-1, 1.1 for a 10% stock dividend, 5.0 on a REVERSE_SPLIT for 1-for-5) and the per-share cash amount for dividends.
  • A raw, unadjusted OHLCV series. Feeding an already-adjusted vendor series in and adjusting it again applies every factor twice.
  • The bar preceding each dividend ex-date must be present in the series — that close is the factor's denominator.

Workflow

  1. Load raw bars and events. Both BarData and CorporateActionEvent validate on construction: non-finite or negative fields, non-date dates, unknown event types and non-positive split ratios raise CorporateActionError rather than being coerced. An unrecognised event_type is a hard failure by design — silently skipping it leaves the split gap sitting inside a series labelled "adjusted".
  2. Decide the vantage point. If the series feeds a point-in-time research loop, pass as_of=<simulation date>. Bars after it and events with a later ex-date are both excluded, reproducing the series as it stood that day. Omit as_of only for present-day analysis where the whole event history is legitimately known.
  3. Compute the factors with adjust_bars(bars, as_of=...):
    • Split, ratio R: alpha = 1/R. Reverse split, ratio R: alpha = R.
    • Cash dividend D: alpha = 1 - D / P_close(last bar strictly before ex-date). Not the ex-date close — that couples the factor to the day's market move.
    • Each alpha multiplies every bar with dt < ex_date. Events are keyed by date, not matched to a bar, so an ex-date on a holiday or halt still applies.
  4. Route the two series to the two consumers.
    • Signals, indicators, returns, correlations → adj_open/high/low/close.
    • Order quantity, cash debit/credit, commission, tick rounding, margin → raw_open/high/low/close.
    • ADV and liquidity screens → adj_volume, which is raw_volume / volume_caf and is therefore untouched by cash dividends.
  5. Credit dividend cash separately. On each dividend ex-date, cash += shares_held * D, taken from the event log and the raw position — never inferred from the adjusted price series.
  6. Handle the rejections. A CorporateActionError for a dividend at or above its reference close means either bad vendor data or a special/liquidating distribution that needs an explicitly supplied factor. Do not clamp it — investigate the event.

Full procedure: see references/workflows.md. Standards reference: see references/standards.md. Printable pre-flight checklist: see assets/checklist.md.

Common Pitfalls

  • Referencing the dividend to the ex-date close. The CRSP convention that Yahoo Finance and MATLAB's adjustedClosingPrices both implement divides by the last close preceding the ex-date. A $2 dividend on a stock that also fell from $100 to $90 that session yields 0.9778 under the wrong reference and 0.98 under the right one — and the error grows without bound as the ex-date close approaches zero.
  • Adjusting volume by the price factor. A cash dividend changes the price basis and leaves the share count alone. Folding it into the volume factor inflates historical share volume by the dividend yield, so every ADV-based liquidity or capacity check reads high on exactly the names that pay dividends. CRSP keeps these as two separate fields; so does this module.
  • Applying an event only when a bar matches its ex-date. Ex-dates land on exchange holidays, on halted sessions, before the start of a truncated series, and on days a vendor's calendar disagrees with yours. Matching event.ex_date == bar.dt drops those events without a word.
  • Look-ahead through the adjusted series. A fully adjusted modern series encodes every future split and dividend into today's price. A signal computed over it at simulated date T has seen events that had not been announced at T. Use as_of.
  • Executing at adjusted prices. Sizing an order off an adjusted price buys the wrong number of shares and debits the wrong cash; the discrepancy compounds silently across the backtest and only surfaces as an unexplained PnL gap against live.
  • Double-adjusting. Most retail data APIs return adjusted closes by default. Confirm which series you fetched before adjusting it again.
  • Pre-applying an announced-but-not-yet-ex event. An event with an ex-date after the last bar has not occurred within the sample; applying it rescales the whole series and breaks the caf == 1.0 anchor on the newest bar. This module ignores such events and logs the reason at DEBUG.

Verification

  • 2-for-1 split: ex-date 2025-01-03, raw close $100 → $50. Assert caf == 0.5 and adj_close == 50.0 on Days 1–2, caf == 1.0 on and after the ex-date, and adj_volume doubled before the ex-date.
  • Dividend reference price: $2.00 dividend ex-date 2025-01-02 with a $100 close on 01-01 and a $90 close on 01-02. Assert caf == 0.98, not 0.9778.
  • Volume/price separation: after that same dividend, assert volume_caf == 1.0 and adj_volume == raw_volume.
  • Point-in-time: with a split on 2025-01-03, adjust_bars(bars, as_of=date(2025,1,1)) must return one bar with caf == 1.0; the same call without as_of must return caf == 0.5 for that bar.
  • Anchor invariant: for any event set, the last bar's caf, volume_caf are 1.0 and adj_close == raw_close.
  • Run python -m unittest discover -s skills/corporate-action-adjusted-backtesting/scripts.

Related Skills

  • corporate-action-event-calendar-integration
  • adjusted-vs-unadjusted-price-series-pitfalls
  • vendor-specific-adjustment-methodology-reconciliation
  • lookahead-bias-elimination
  • point-in-time-fundamentals-data-joins
  • synthetic-continuous-futures-contract-construction

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Corporate Action Adjusted Backtesting AI skill do?

Use when a stock split, reverse split or cash dividend puts artificial gaps in a backtest's price history and fabricates signals; builds a CRSP-convention backward-adjusted series for signals while keeping dividend cash accounted separately.

Why use Corporate Action Adjusted Backtesting on TypingMind?

Because you install it once and use it with any model. Corporate Action Adjusted Backtesting is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Corporate Action Adjusted Backtesting in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/HimanshuJ16/Algo-Trading-Skills/tree/main/skills/corporate-action-adjusted-backtesting. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Corporate Action Adjusted Backtesting?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Corporate Action Adjusted Backtesting?

As many as you like. As long as a model supports skills, you can use Corporate Action Adjusted Backtesting with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Corporate Action Adjusted Backtesting AI skill free?

Yes. It is published on GitHub by HimanshuJ16 under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇