Skip to main content

Python library for causal time series modeling

Project description

🧠 Causal Time Series (CTS)

Causal Time Series (CTS) is a Python library for modeling, simulating, and intervening in dynamic business systems using Dynamic DAGs and ODE-style causal updates.

It bridges causal inference, forecasting, and simulation, letting you answer “what if” questions such as:

“What if we increase marketing spend, lower price, or improve support response times — how does that affect revenue?”

Example causal time series plot


🚀 Features

  • 🕸️ Dynamic DAGs — define causal dependencies across time.
  • ⚙️ Mechanism-based modeling — learn how each variable evolves.
  • 💡 Interventions (Do operator) — simulate counterfactuals.
  • 🔁 Forecasting & simulation — Euler-style integration through time.
  • 🧮 Derived variables — define deterministic metrics (e.g., revenue = price × paying users).
  • 📊 Pandas-first API — DataFrame in, DataFrame out.
  • 🔍 Scikit-learn style — familiar fit(), forecast(), simulate(), plot() interface.

📦 Installation

pip install causal_time_series

🧩 Example: Business Metrics Simulation

This demo models a subscription-based business with feedback between growth, churn, and monetization.

📊 Variables

Variable Type Description
marketing_spend Lever Daily advertising investment
new_users Flow New users acquired
churned_users Flow Users leaving the platform
active_users Stock Current engaged user base
support_tickets State Customer support volume
price Lever Subscription price
paying_users State Users converting to paid plans
revenue Derived price × paying_users
arpu Derived revenue / active_users

🧭 Quickstart

import pandas as pd
from cts import CausalDAG, CTSModel, Do
from cts.utils import business_dataset

# 1️⃣ Load synthetic data
df = business_dataset()

# 2️⃣ Define the causal DAG (no explicit revenue node)
dag = CausalDAG(
    nodes=['M','P','N','C','S','A','Pay'],
    edges=[
        ('M','M'), ('P','P'),           # persistence for levers
        ('M','N'),                      # marketing -> new users
        ('A','S'), ('S','C'),           # active -> tickets -> churn
        ('N','A'), ('C','A'),           # new adds, churn removes
        ('P','Pay'), ('A','Pay'),       # price & active -> paying users
        ('Pay','Pay'), ('S','S')        # persistence
    ],
    lag=1,
    rename={
        "M":"marketing_spend","P":"price","N":"new_users",
        "C":"churned_users","S":"support_tickets",
        "A":"active_users","Pay":"paying_users"
    }
)

# 3️⃣ Derived variables
derived = {
    "revenue": lambda s: s["price"] * s["paying_users"],
    "arpu": lambda s: s["revenue"] / (s["active_users"] + 1e-6)
}

# 4️⃣ Fit causal model
cts = CTSModel(dag, backend="ridge", derived=derived).fit(df)

cts.constraints = {
    "price": "nonnegative",
    "marketing_spend": "nonnegative",
    "paying_users": "nonnegative",
    "active_users": "nonnegative",
    "churned_users": "nonnegative"
}

# 5️⃣ Forecast baseline
forecast = cts.forecast(h=30)

# 6️⃣ Counterfactual: increase marketing
cf = cts.simulate(
    h=60,
    intervention=Do(shift={"marketing_spend": +50}, from_time=df.index[-1])
)

# 7️⃣ Visualize
cts.plot(df, forecast, cf, cols=["marketing_spend","price","paying_users","churned_users","revenue"])

🧠 Core Concepts

🕸️ Dynamic DAGs

Each edge expresses a temporal causal relationship:

X_{t−1} → Y_t

Variables evolve in time through their causal parents.

⚙️ Differential formulation

CTS learns: [ ΔX_t = f(\text{Parents}_{t−1}) + ε_t ] for each node, using Ridge regression by default (can be extended to Neural ODEs).

🧮 Derived Variables

Derived columns are deterministic functions of other state variables:

derived = {
    "revenue": lambda s: s["price"] * s["paying_users"],
    "arpu": lambda s: s["revenue"] / (s["active_users"] + 1e-6)
}

They are recomputed automatically after each forecast or simulation step.

🧩 Interventions

Simulate causal “what-if” changes:

# Increase marketing spend
Do(shift={'marketing_spend': +100}, from_time='2023-06-01')

# Fix a variable to constant value
Do(set={'price': 8.0}, from_time='2023-07-01')

📁 Repository Structure

cts/
  __init__.py
  dag.py
  core.py
  intervene.py
  models/
    __init__.py
    ridge_delta.py
  utils/
    __init__.py
    datasets.py
examples/
  demo_business.ipynb
main.py
README.md

👩‍💻 License

MIT License © 2025 Nick Gavriil


“Don’t just forecast the future — understand how your actions create it.”

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

causal_time_series-0.0.2.tar.gz (9.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

causal_time_series-0.0.2-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file causal_time_series-0.0.2.tar.gz.

File metadata

  • Download URL: causal_time_series-0.0.2.tar.gz
  • Upload date:
  • Size: 9.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for causal_time_series-0.0.2.tar.gz
Algorithm Hash digest
SHA256 7e5ceb66f5b15240e094e8a73310d428dae9de2ded78e308fe9fff5c18e9216f
MD5 781bb64241bdc29627b9ab93e7b6725f
BLAKE2b-256 d1a0e30fba378e9613bb4434a8fa82b0eeb407a07efe69b521d049988137e77f

See more details on using hashes here.

File details

Details for the file causal_time_series-0.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for causal_time_series-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e15349f40f66ed0485081c7a751a4f0e8d9ff167543594db19517ae7aca43f60
MD5 1cf97521f91e0d46ed8d2388457860ba
BLAKE2b-256 5f64a13cff690ca2d2b88501df814aa764052782af2867f80b28d64858517cb0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page