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
19 changes: 19 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"permissions": {
"allow": [
"Bash(find /Users/cotoneum/project/perp-bot/src -type f -name *.py)",
"Bash(find /Users/cotoneum/project/perp-bot/tests -type f -name *.py)",
"Bash(grep -r \"websocket_manager\\\\|WebSocket\\\\|ws://\" /Users/cotoneum/project/perp-bot/src --include=*.py)",
"Bash(/tmp/tree_output.txt:*)",
"Read(//tmp/**)",
"Bash(gh repo:*)",
"Bash(git rm:*)",
"Bash(git rebase:*)"
]
},
"outputStyle": "Explanatory",
"sandbox": {
"enabled": true,
"autoAllowBashIfSandboxed": true
}
}
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Hyperliquid wallet private key (for signed exchange requests in Phase 4)
HL_PRIVATE_KEY=
# Hyperliquid wallet address
HL_WALLET_ADDRESS=
# Discord webhook URL for alerts (optional)
DISCORD_WEBHOOK_URL=
# Telegram Bot API token (optional)
TELEGRAM_BOT_TOKEN=
# Telegram chat ID for alerts (optional)
TELEGRAM_CHAT_ID=
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: CI

on:
push:
branches:
- main
pull_request:

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.12", "3.13"]

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --frozen --group dev

- name: Lint
run: uv run ruff check src tests

- name: Run tests
run: uv run pytest

build:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5

- name: Build distributions
run: uv build

- name: Build standalone binary archive
run: ./scripts/build-release-archive.sh perpbot-linux-x86_64.tar.gz

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/*
63 changes: 63 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Release

on:
push:
tags:
- "v*"
workflow_dispatch:

permissions:
contents: write

jobs:
package-release:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5

- name: Build distributions
run: uv build

- name: Publish Python artifacts
uses: softprops/action-gh-release@v2
with:
files: dist/*
generate_release_notes: true

binary-release:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
asset_name: perpbot-linux-x86_64.tar.gz
- os: macos-13
asset_name: perpbot-macos-x86_64.tar.gz
- os: macos-14
asset_name: perpbot-macos-arm64.tar.gz

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Build standalone binary archive
run: ./scripts/build-release-archive.sh ${{ matrix.asset_name }}

- name: Publish binary artifact
uses: softprops/action-gh-release@v2
with:
files: dist/*
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info

# Virtual environments
.venv

# Secrets
.env

# Data
*.db
*.sqlite
data/*.csv

# Tool caches
.ruff_cache/
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project follows Semantic Versioning.

## [Unreleased]

### Added

- One-line installer script that downloads a prebuilt standalone binary from GitHub Releases.
- Release packaging script for OS-specific standalone `perpbot` binaries.

### Changed

- README now treats bare `perpbot` usage as the primary CLI flow instead of `uv run perpbot`.
- Release automation now targets downloadable standalone binaries in addition to Python package artifacts.

## [0.1.0] - 2026-03-19

### Added

- Packaged CLI entry point as `perpbot` with GitHub-installable build artifacts.
- Config loading that works from the current working directory or an explicit `--config` path.
- Public package metadata, README install instructions, and release automation scaffolding.

### Fixed

- Losing-weeks halt now reconciles live positions before halting new entries.
- Live stop-loss now uses actual trade notional instead of recomputed regime size.
- Paper-vs-backtest reporting now excludes live trades.
- Symbol screening now uses the latest candle window.
- Live `OPEN` alerts are only emitted after a successful entry.
- Multi-symbol backtest CSV exports no longer overwrite each other.
81 changes: 81 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# CLAUDE.md

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

## Project Overview

Hyperliquid perpetual futures mean-reversion trading bot. Designed for small capital (~$670, 3x leverage) day-trading on Hyperliquid's on-chain CLOB DEX. The full design specification is in `hyperliquid-mean-reversion-bot-design.md` (Japanese).

## Tech Stack

- **Language**: Python 3.12+
- **Exchange SDK**: `hyperliquid-python-sdk` + `websockets`
- **Data store**: SQLite (initial) -> DuckDB (analysis)
- **Indicators**: Self-implemented with pandas/numpy (no ta-lib dependency — intentional for full logic transparency)
- **Deployment**: GCP Compute Engine (e2-small), systemd service
- **Alerts**: Discord Webhook or Telegram Bot API
- **Logging**: Python `logging` module, JSON-structured

## Architecture (Planned)

Seven modules:

| Module | Responsibility |
|---|---|
| **Data Layer** | REST + WebSocket data ingestion (`WsClient` for real-time mid prices, candles, BBO), SQLite persistence, OHLCV candles (1m/5m/15m/1h), prediction market snapshots |
| **Signal Engine** | Z-Score, Bollinger Bands, RSI, ADX calculations. Entry signal = all 4 indicators agree + ADX regime filter. Prediction market regime modifiers |
| **Prediction Layer** | Polymarket (war risk) + Kalshi (Fed rate) polling, regime classification (NORMAL/HIGH_RISK/DOVISH/HAWKISH/CRISIS), funding side preference |
| **Execution Layer** | `PaperExecutor` (DB-only) + `LiveExecutor` (real orders via Exchange API). Limit-first with taker-fallback, atomic server-side SL attachment, crash recovery via exchange position query |
| **Risk Manager** | Stop-loss (3% per trade), daily loss limit (8%), max 1 position, 30min cooldown after SL, 50% margin usage cap, regime-based position sizing |
| **Backtester** | Fee model (Maker 0.015%/Taker 0.045%), slippage sim, walk-forward analysis for overfitting prevention |
| **Infrastructure** | Structured logging (stdout + file), alert dispatch, health checks |
| **IPC Layer** | Unix socket daemon state server (`DaemonStateServer`), client (`DaemonClient`), thread-safe `DaemonState` container. Socket carries volatile state; SQLite WAL provides concurrent read access for persistent data |
| **TUI Dashboard** | Textual-based terminal UI (`PerpBotApp`). Attaches/detaches freely from daemon. Panels: header, position, signals, risk, trades, log. Key bindings: pause/resume/emergency close |

## Key Trading Logic

- **Entry**: Z-score > ±2.0 AND RSI overbought/oversold AND price outside Bollinger Band AND ADX < 25 (range-bound regime)
- **Exit (profit)**: Z-score returns to ±0.3 (mean reversion complete)
- **Exit (stop)**: Z-score exceeds ±3.0 against position, OR 3% capital loss, OR 24h timeout
- **Order strategy**: Limit orders (Maker) preferred; fallback to market (Taker) if unfilled. Server-side stop orders on Hyperliquid for redundancy.

## Development Phases

1. **Data Pipeline** — OHLCV + funding rate ingestion into SQLite, WebSocket real-time feed
2. **Signal Engine + Backtester** — Indicator modules, backtest engine with realistic cost model, walk-forward overfitting checks
3. **Risk Management + Paper Trading** — Risk modules, paper-trade mode, validate against backtest results
4. **Live Trading** — Signed exchange API, GCP deploy, staged rollout (start with 20% of capital)

## Hyperliquid API Notes

- Gas-free: no gas costs for order placement/modification/cancellation
- Funding rate: settled hourly (1/8 of 8h rate each hour)
- REST info endpoint: `POST /info` with varying `type` field (metaAndAssetCtxs, candleSnapshot, fundingHistory, clearinghouseState)
- Exchange endpoint: `POST /exchange` (signed)
- Known risk: API server overload incidents have caused 30min+ downtime — always pair bot-side SL with server-side stop orders

## Commands

```bash
uv sync # Install dependencies
uv run pytest tests/ -v # Run all tests
uv run pytest tests/test_indicators.py -v # Run a single test file
uv run ruff check src/ tests/ # Lint
perpbot backfill # Backfill historical data from Hyperliquid
perpbot trade # Start trading loop (paper mode by default, set mode: "live" in config.yaml for real orders)
perpbot backfill-predictions # Fetch current prediction market snapshots
perpbot backtest # Run backtest over historical data
perpbot walkforward # Walk-forward overfitting analysis
perpbot sensitivity # Parameter sensitivity sweep
perpbot screen # Screen symbols by Hurst exponent for mean-reversion fit
perpbot review --weeks 1 # Weekly performance report
perpbot compare --days 7 # Compare paper trades vs backtest over same period
perpbot tui # Launch TUI dashboard (attach to running daemon)
perpbot status # One-shot daemon state query (JSON output)
```

## Conventions

- Design doc and code comments may be in Japanese
- All indicator calculations are self-implemented (do not introduce ta-lib or similar libraries)
- Backtest must include: trading fees, slippage, funding costs, and execution delay simulation
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 morfize

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading