01-projects / automated-investing / autoinv

readme

autoinv

Ray Data Co’s Automated Investing toolkit. A small library of reusable utilities for quant research and strategy development, built from the L1-L5 curriculum drills (gemchange roadmap) and Halls-Moore’s Successful Algorithmic Trading.

Design principles

Modules

ModulePurpose
dataPrice pulls (yfinance), returns, lagged features, Fama-French factors (direct from Dartmouth)
statsNormality tests, Student-t MLE, factor regression with Newey-West HAC, permutation test
validationTimeSeriesSplit helper, score_walk_forward, BiasAudit checklist
metricsSharpe, drawdown decomposition, Brier score, one-shot strategy report
portfolioCost-aware Markowitz, efficient frontier, PCA factor decomposition
pricingBlack-Scholes, Greeks, Monte Carlo, put-call parity
engineMinimal event-driven backtester skeleton (DataHandler / Strategy / Portfolio / ExecutionHandler)
polymarketAnonymous read-only client for Polymarket Gamma + CLOB + Data APIs (markets, prices-history, orderbook)
kalshiAnonymous read-only client for Kalshi trading API v2 (markets, events, candlesticks, orderbook). Mirrors the polymarket module structure so the two can be used interchangeably for arbitrage scans.

Quickstart

from autoinv import data, stats, validation, metrics, engine

# 1. Pull prices and returns
prices = data.get_prices("SPY", start="2020-01-01", end="2026-04-01")
returns = data.get_returns("SPY", start="2020-01-01", end="2026-04-01")

# 2. Normality audit
report = stats.normality_report(returns.to_numpy())
print(f"Fat tails? {report.rejected_at_5pct}")

# 3. Test a signal with permutation
signal = (returns.shift(1) > 0).fillna(False).to_numpy()
perm = stats.permutation_test(returns.to_numpy(), signal, n_permutations=10_000)
print(f"Permutation p: {perm.p_one_sided:.4f}")

# 4. Run a strategy through the backtester
# (see scripts/demo_buy_after_up_day_v2.py for a full example)

# 5. Performance report
strategy_returns = ...  # from backtest
r = metrics.strategy_report(strategy_returns)
print(f"Sharpe: {r.sharpe:.3f}, MaxDD: {r.max_drawdown:.2%}")

# 6. Gate with the bias audit
audit = validation.BiasAudit(
    optimisation_bias=False,
    look_ahead_bias=False,
    survivorship_bias=False,
    cognitive_bias=False,
)
assert audit.passed, audit.report()

Tests

.venv/bin/python -m pytest tests/

All 30 tests green as of 2026-04-10.

What’s intentionally NOT here