Skip to main content

Ancilla is a Python library for quantitative finance.

Project description

Ancilla

A Polygon.io and FRED-based financial data library for backtesting trading strategies.

Ancilla is a straightforward Python library for querying/visualizing financial data and executing backtests to survey trading strategies. Under the hood, Ancilla uses Polygon.io to fetch historical stock and options data, and FRED, the official data source for the Federal Reserve, to fetch interest rates.

Installation

pip install ancilla

Create a .env file in the root directory with

POLYGON_API_KEY=your_api_key
FRED_API_KEY=your_api_key

Using Ancilla requires paid Polygon.io data subscriptions, which can be obtained here, and a free FRED API key, which can be obtained here.

Usage

# experiments/test_backtest.py
from datetime import datetime
from typing import Dict, Any
import pytz
import os
import dotenv

from ancilla.backtesting.configuration import CommissionConfig, SlippageConfig
from ancilla.backtesting import Backtest, Strategy
from ancilla.providers import PolygonDataProvider

dotenv.load_dotenv()


class HoldSpyStrategy(Strategy):
    """Simple test strategy that buys and holds SPY."""

    def __init__(self, data_provider, position_size: float = 0.2):
        super().__init__(data_provider, name="hold_spy")
        self.position_size = position_size
        self.entry_prices = {}  # Track entry prices for each ticker

    def on_data(self, timestamp: datetime, market_data: Dict[str, Any]) -> None:
        """Buy and hold stocks with basic position sizing."""
        self.logger.debug(f"Processing market data for {timestamp}")
        for ticker, data in market_data.items():
            # Log market data
            self.logger.debug(f"{ticker} price: ${data['close']:.2f}")

            # Skip if we already have a position
            if ticker in self.portfolio.positions:
                continue

            # Calculate position size based on portfolio value
            portfolio_value = self.portfolio.get_total_value()
            position_value = portfolio_value * self.position_size
            shares = int(position_value / data["close"])

            if shares > 0:
                # Open position
                self.logger.info(
                    f"Opening position in {ticker}: {shares} shares @ ${data['close']:.2f}"
                )
                success = self.engine.buy_stock(ticker=ticker, quantity=shares)
                if success:
                    self.entry_prices[ticker] = data["close"]
                    self.logger.info(f"Successfully opened position in {ticker}")
                else:
                    self.logger.warning(f"Failed to open position in {ticker}")


if __name__ == "__main__":
    # Initialize data provider
    api_key = os.getenv("POLYGON_API_KEY")
    if not api_key:
        raise ValueError("POLYGON_API_KEY environment variable not set")

    data_provider = PolygonDataProvider(api_key)

    # Create strategy
    strategy = HoldSpyStrategy(
        data_provider=data_provider, position_size=0.5  # 50% of portfolio per position
    )

    # Set up test parameters
    tickers = ["SPY"]  # Reduced ticker list for testing
    start_date = datetime(2023, 1, 1, tzinfo=pytz.UTC)
    end_date = datetime(2024, 12, 31, tzinfo=pytz.UTC)  # Shorter test period

    # Initialize backtest engine
    simple_backtest = Backtest(
        strategy=strategy,
        initial_capital=100000,
        frequency="1hour",
        start_date=start_date,
        end_date=end_date,
        tickers=tickers,
        commission_config=CommissionConfig(
            min_commission=1.0, per_share=0.005, per_contract=0.65, percentage=0.0001
        ),
        slippage_config=SlippageConfig(
            base_points=1.0, vol_impact=0.1, spread_factor=0.5, market_impact=0.05
        ),
    )

    # Run backtest
    results = simple_backtest.run()

    # Plot results
    results.plot(include_drawdown=True)

Features

  • A Polygon.io data wrapper with retries & automatic caching
  • Basic visualizations for IV surfaces, liquidity, and price data
  • Backtesting for equities and options
    • Batch requests and data caching for speed
    • Configurable strategy frequency (30min, 1hour, etc.)
    • Models slippage, commissions, price impact
    • Fill probability based on volume (or deterministic fills for testing)
    • Adjusts stock prices for splits and dividends, pays dividends
    • Monthly interest using accurate rates
    • Automatic ITM options exercise and assignment
    • Detailed trade history visualizations, performance metrics, logs

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

ancilla-1.1.1.tar.gz (71.6 kB view details)

Uploaded Source

Built Distribution

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

ancilla-1.1.1-py3-none-any.whl (81.2 kB view details)

Uploaded Python 3

File details

Details for the file ancilla-1.1.1.tar.gz.

File metadata

  • Download URL: ancilla-1.1.1.tar.gz
  • Upload date:
  • Size: 71.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.5.1 CPython/3.8.18 Linux/5.15.0-1074-azure

File hashes

Hashes for ancilla-1.1.1.tar.gz
Algorithm Hash digest
SHA256 5e922cd3b181325c36d1e27157b9f0bf1cd65e206bfe41e5cf8dea1695fcdcf4
MD5 fde5edb272d84cc97536cb96643e284d
BLAKE2b-256 6d48c11a9d4a3e513f7fb8a6c6bd251e959846d6a3acc61f9dc8d310e1ce3aa3

See more details on using hashes here.

File details

Details for the file ancilla-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: ancilla-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 81.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.5.1 CPython/3.8.18 Linux/5.15.0-1074-azure

File hashes

Hashes for ancilla-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7b09241b2041332a411366c8384ae93bbd42470ee54fdae0735d27bc4e8e39fe
MD5 903cad75a318ff7f148df98e9b5b3f26
BLAKE2b-256 06e88cce34c77cc249871142e5a2dc1958b7f812f29234cdeaac7e0c8dad68b8

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