Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions .claude/skills/chores/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
name: chores
description: "Update README.md, CHANGELOG.md, CLAUDE.md, and VERSION based on recent changes in the current branch."
user_invocable: true
---

You are updating the project's documentation and version files to reflect recent work on the current branch. Follow these steps precisely.

---

## Step 1: Gather recent changes

Run these commands to understand what changed on the current branch since it diverged from `main`:

```bash
git log main..HEAD --oneline
git diff main..HEAD --stat
git diff main..HEAD
```

Read the full diffs carefully. Identify:
- New files and modules added
- Functions/classes added, changed, or removed
- Bug fixes
- Refactors or renames
- Test additions or changes
- Config/CI changes

---

## Step 2: Determine the version bump

Read the current `VERSION` file. Decide the bump based on the changes:
- **Patch** (0.1.2 → 0.1.3): Bug fixes, minor improvements, test additions, doc updates
- **Minor** (0.1.2 → 0.2.0): New features, new modules, new public API functions
- **Major** (0.1.2 → 1.0.0): Breaking changes to existing public API

Ask the user to confirm the version bump before proceeding. Show them what changed and your recommendation.

---

## Step 3: Update VERSION

Write the new version string to `VERSION` (single line, no trailing newline beyond what's standard).

---

## Step 4: Update CHANGELOG.md

Read the current `CHANGELOG.md`. Add a new section under `## [Unreleased]` or replace it with the new version heading. Follow the existing format exactly (Keep a Changelog style):

```markdown
## [X.Y.Z] - YYYY-MM-DD

### Added
- ...

### Changed
- ...

### Removed
- ...
```

Rules:
- Use today's date.
- Only include sections (Added/Changed/Removed/Fixed) that apply.
- Each entry should be a concise, user-facing description — not a commit message.
- Reference module paths where helpful (e.g., "`brokers.alpaca.performance_ops`").
- Move any existing `[Unreleased]` items into the new version section if they are covered by the branch changes. Leave `## [Unreleased]` as an empty heading at the top for future work.

---

## Step 5: Update README.md

Read the current `README.md`. Update only the sections affected by the branch changes:

- **Features list**: Add or update bullet points for new/changed features.
- **Usage Examples**: Add examples for new public functions. Follow the existing code example style (imports, comments, print statements).
- **Library Structure**: Update the tree if files were added or removed.
- **Core Modules**: Add/update function signatures and descriptions for new/changed public API.
- **Test Coverage**: Update the test file list if new test files were added.

Rules:
- Do NOT rewrite unchanged sections.
- Match the existing tone, formatting, and level of detail.
- Keep examples minimal but complete (copy-pasteable).

---

## Step 6: Update CLAUDE.md

Read the current `CLAUDE.md`. Update only what's affected:

- **Commands**: Update if build/test/run commands changed.
- **Architecture**: Update if new modules, key classes, or patterns were added.
- **Key patterns**: Update if new conventions or important design decisions were introduced.
- **CI**: Update if workflow changed.

Rules:
- Keep it concise — CLAUDE.md is for orientation, not exhaustive docs.
- Don't duplicate what's easily discoverable from the code.

---

## Step 7: Present a summary

Show the user a brief summary of all changes made across the four files. Do NOT commit — let the user decide when to commit.
36 changes: 36 additions & 0 deletions .github/workflows/tag-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Tag Release

on:
push:
branches: [ "main" ]

permissions:
contents: write

jobs:
tag:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Read version
id: version
run: echo "version=v$(cat VERSION | tr -d '[:space:]')" >> "$GITHUB_OUTPUT"

- name: Check if tag exists
id: check
run: |
if git rev-parse "${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi

- name: Create and push tag
if: steps.check.outputs.exists == 'false'
run: |
git tag "${{ steps.version.outputs.version }}"
git push origin "${{ steps.version.outputs.version }}"
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,8 @@ cython_debug/

# json settings
*.json

test.py

# Strategy snapshots
strategy_snapshots/
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.2.0] - 2026-04-05

### Added
- Alpaca account helpers: `get_account()` and `get_balances()` (`brokers.alpaca.account`).
- Alpaca activities helper: `get_activities()` (`brokers.alpaca.activities`).
- Strategy snapshot export: `save_strategy_snapshot()` persists positions, orders, activities, balances, and equity performance to JSON (`brokers.alpaca.performance_ops`).
- Strategy report generation: `generate_strategy_report()` and `generate_strategy_report_data()` produce Markdown or JSON reports from snapshot files.
- Snapshot normalization: `normalize_snapshot()` cleans raw snapshot data with data-quality warnings.
- `CLAUDE.md` project guidance file for Claude Code.
- `VERSION` file for tracking releases.
- Tests for account, activities, snapshot export, and report generation (`test_account.py`, `test_activities.py`, `test_performance_ops.py`, `test_reporting.py`).
- GitHub Actions workflow `tag-release.yml` that automatically creates a git tag from `VERSION` when a branch is merged into `main`.

### Changed
- Improved snapshot serialization to handle recursive and self-referential Alpaca SDK objects safely.
- Test setup (`conftest.py`) now gracefully skips when SciPy/PerformanceMetrics cannot be imported.

## [0.1.2] - 2026-01-04
- Added place_trailing_stop_losses_funct

Expand Down
67 changes: 67 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
# Install dependencies
pip install uv
uv pip install --system -r requirements.txt

# Run all tests
pytest tests -v -s

# Run a single test file
pytest tests/test_portfolio_ops.py -v -s

# Run a single test function
pytest tests/test_portfolio_ops.py::test_function_name -v -s

# Lint/format (dev dependencies)
pip install -e ".[dev]"
black algorithmic_trading_utilities/
flake8 algorithmic_trading_utilities/
mypy algorithmic_trading_utilities/
```

## Environment Variables

Required in `.env` (see `.env.example`): `PAPER_KEY`, `PAPER_SECRET` (Alpaca paper trading API credentials). Optional: `web_app_email`, `web_app_email_password`, `recipient_email` for email notifications.

## Architecture

This is a Python library for algorithmic trading, structured into three domains:

- **`brokers/alpaca/`** - Alpaca API integration: account info, order placement (with retry/backoff), position management, portfolio history, strategy performance snapshots. All broker modules depend on `common/config.py` for the `TradingClient` instance.
- **`common/`** - Shared utilities: `PerformanceMetrics` class (Sharpe, Sortino, alpha/beta, drawdown, VaR/CVaR), sentiment analysis (DistilRoBERTa via HuggingFace), email notifications, web scraping, visualization.
- **`data/`** - Market data retrieval from Alpaca (`get_data.py`) and Yahoo Finance (`yfinance_ops.py`).

### Key patterns

**Dual import convention**: All internal imports use a try/except pattern to support both direct execution and package installation:
```python
try:
from common.config import trading_client
except ImportError:
from algorithmic_trading_utilities.common.config import trading_client
```
Follow this pattern when adding new cross-module imports.

**`PerformanceMetrics`** (`common/portfolio_ops.py`) is the central analytics class. It takes portfolio and optional benchmark equity series and provides all risk/return metrics. Tests use a `sample_data` fixture from `conftest.py` that generates deterministic random data (seed 42).

**`performance_ops.py`** (`brokers/alpaca/performance_ops.py`) exports strategy snapshots as JSON and generates Markdown/JSON reports to `strategy_snapshots/`. Key entry points: `save_strategy_snapshot()` for capturing broker state, `generate_strategy_report()` for rendering reports from snapshots. It serializes Alpaca SDK objects by converting `RawData` dicts, enums, and recursive structures to plain types via `_to_serializable()`.

## Generating Strategy Snapshots

`test.py` is a dev entrypoint that creates a strategy snapshot (JSON) and report (Markdown) in `strategy_snapshots/`:

```bash
python test.py <strategy_name> # defaults: 1D timeframe, md report
python test.py sentiment_analysis_v1 --timeframe 1H # custom timeframe
python test.py my_strat --include-benchmark # include benchmark-relative metrics
```

## CI

GitHub Actions runs `pytest tests -v -s` on Python 3.10 against `main` for pushes and PRs. API keys are injected via repository secrets. A separate `tag-release.yml` workflow automatically creates a git tag from `VERSION` on every push to `main` (skips if the tag already exists).
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ A comprehensive Python library for algorithmic trading with Alpaca API and Yahoo
- **Yahoo Finance Integration**: Access to market screeners and S&P 500 benchmark data
- **Visualization Tools**: Time series plotting and portfolio comparison charts
- **Broker Integration**: Seamless integration with Alpaca trading platform
- **Strategy Snapshots**: Export broker state (positions, orders, activities, balances, equity curve) to JSON

## Installation

Expand Down Expand Up @@ -197,6 +198,56 @@ print(f"Found {len(gainers_df)} large-cap gainers today")
print(gainers_df[['symbol', 'shortName', 'regularMarketChangePercent']].head())
```

### Account, Activities, and Balances

```python
from algorithmic_trading_utilities.brokers.alpaca.account import get_balances
from algorithmic_trading_utilities.brokers.alpaca.activities import get_activities

balances = get_balances()
print(balances["cash"], balances["buying_power"], balances["equity"])

activities = get_activities(activity_types=["FILL", "DIV"], page_size=50)
print(f"Got {len(activities)} activities")
```

### Strategy Snapshot Export

```python
from pathlib import Path
from algorithmic_trading_utilities.brokers.alpaca.performance_ops import save_strategy_snapshot

snapshot_path = save_strategy_snapshot(
strategy_name="mean_reversion_v1",
output_dir=Path("snapshots"),
timeframe="1D",
date_start="2025-01-01",
date_end="2025-01-31",
)

print(f"Saved snapshot to: {snapshot_path}")
```

### Strategy Report Generation

```python
from algorithmic_trading_utilities.brokers.alpaca.performance_ops import (
generate_strategy_report,
load_strategy_snapshot,
generate_strategy_report_data,
)

# Generate a Markdown report from a saved snapshot
report_path = generate_strategy_report(snapshot_path, format="md")
print(f"Report saved to: {report_path}")

# Or get structured report data for programmatic use
snapshot = load_strategy_snapshot(snapshot_path)
report_data = generate_strategy_report_data(snapshot, include_benchmark=True)
print(f"Strategy: {report_data['strategy']}")
print(f"Open positions: {report_data['executive_summary']['open_positions_count']}")
```

### Quantitative Analysis

```python
Expand Down Expand Up @@ -354,7 +405,10 @@ algorithmic_trading_utilities/
├── brokers/
│ └── alpaca/
│ ├── alpaca_ops.py # Portfolio history operations
│ ├── account.py # Account and balances
│ ├── activities.py # Account activities
│ ├── orders.py # Order management
│ ├── performance_ops.py # Strategy snapshot export
│ └── positions.py # Position management
├── common/
│ ├── portfolio_ops.py # Portfolio analytics
Expand Down Expand Up @@ -419,6 +473,16 @@ algorithmic_trading_utilities/
- `cancel_orders()` - Cancel all orders with retry logic
- `cancel_order_by_symbol(symbol)` - Cancel orders for specific symbol

### Account and Strategy State (`brokers.alpaca.account`, `brokers.alpaca.activities`, `brokers.alpaca.performance_ops`)

- `get_balances()` - Retrieve common account balance fields
- `get_activities(...)` - Retrieve account activities
- `save_strategy_snapshot(strategy_name, ...)` - Export positions/orders/activities/balances/equity performance to JSON
- `generate_strategy_report(snapshot_path, ...)` - Generate Markdown or JSON report from a snapshot
- `generate_strategy_report_data(snapshot, ...)` - Compute structured report aggregates from a snapshot
- `normalize_snapshot(snapshot)` - Normalize raw snapshot data with data-quality warnings
- `load_strategy_snapshot(path)` - Load a saved snapshot JSON file

### Position Management (`brokers.alpaca.positions`)

**Position Retrieval:**
Expand Down Expand Up @@ -584,6 +648,10 @@ pytest tests/ -v -s
- `test_quantitative_tools.py` - Quantitative analysis utilities
- `test_viz_ops.py` - Visualization functions
- `test_email_ops.py` - Email notification system
- `test_account.py` - Alpaca account and balances
- `test_activities.py` - Alpaca account activities
- `test_performance_ops.py` - Strategy snapshot export
- `test_reporting.py` - Strategy report generation and rendering

## Error Handling

Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.2.0
Loading
Loading