Add phase one implementation plan
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.superpowers/
|
||||
.worktrees/
|
||||
.venv/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
277
docs/superpowers/plans/2026-07-08-grid-trading-phase-1.md
Normal file
277
docs/superpowers/plans/2026-07-08-grid-trading-phase-1.md
Normal file
@@ -0,0 +1,277 @@
|
||||
# Grid Trading Phase 1 Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Build the first working PySide6 + SQLite desktop version for A股/ETF grid-trading bookkeeping, including accounts, instruments, manual trades, position calculations, and local persistence.
|
||||
|
||||
**Architecture:** Keep trading math independent from GUI code. The `domain` package owns models and calculations, `storage` owns SQLite schema and repository methods, `services` coordinates validation and summaries, and `ui` renders the PySide6 desktop workflow.
|
||||
|
||||
**Tech Stack:** Python 3.11+, PySide6, SQLite, pytest, Decimal-based money calculations.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
- Create `pyproject.toml`: package metadata, runtime dependencies, pytest config, console entry point.
|
||||
- Create `README.md`: setup and run instructions.
|
||||
- Create `src/grid_trading/__init__.py`: package marker and version.
|
||||
- Create `src/grid_trading/app.py`: application entry point.
|
||||
- Create `src/grid_trading/config.py`: default database path and fee settings.
|
||||
- Create `src/grid_trading/domain/models.py`: dataclasses and enums for accounts, instruments, trades, strategies, summaries.
|
||||
- Create `src/grid_trading/domain/calculations.py`: pure calculation functions for positions, account summary, fees, and T+1 availability.
|
||||
- Create `src/grid_trading/storage/database.py`: SQLite connection and schema initialization.
|
||||
- Create `src/grid_trading/storage/repositories.py`: typed CRUD methods over SQLite.
|
||||
- Create `src/grid_trading/services/trading_service.py`: high-level account, instrument, trade, strategy, and summary service methods.
|
||||
- Create `src/grid_trading/ui/main_window.py`: main PySide6 window and holdings-first layout.
|
||||
- Create `src/grid_trading/ui/dialogs.py`: account, instrument, trade, and strategy dialogs.
|
||||
- Create `src/grid_trading/ui/formatters.py`: UI formatting helpers.
|
||||
- Create `tests/test_calculations.py`: TDD coverage for cost, realized profit, breakeven, and T+1.
|
||||
- Create `tests/test_repositories.py`: SQLite schema and persistence coverage.
|
||||
- Create `tests/test_services.py`: service-level workflow coverage.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Project Scaffold
|
||||
|
||||
**Files:**
|
||||
- Create: `pyproject.toml`
|
||||
- Create: `README.md`
|
||||
- Create: `src/grid_trading/__init__.py`
|
||||
- Create: `src/grid_trading/config.py`
|
||||
- Create: `src/grid_trading/app.py`
|
||||
- Test: `tests/test_imports.py`
|
||||
|
||||
- [ ] **Step 1: Write failing import test**
|
||||
|
||||
```python
|
||||
def test_package_imports():
|
||||
import grid_trading
|
||||
from grid_trading.config import DEFAULT_DB_PATH
|
||||
|
||||
assert grid_trading.__version__
|
||||
assert DEFAULT_DB_PATH.name == "grid_trading.db"
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `pytest tests/test_imports.py -v`
|
||||
Expected: FAIL with `ModuleNotFoundError: No module named 'grid_trading'`.
|
||||
|
||||
- [ ] **Step 3: Add package scaffold**
|
||||
|
||||
Implement a `src` layout, declare PySide6 and pytest dependencies, set `pythonpath = ["src"]`, and add `grid-trading = "grid_trading.app:main"`.
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `pytest tests/test_imports.py -v`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add pyproject.toml README.md src/grid_trading tests/test_imports.py
|
||||
git commit -m "chore: scaffold python desktop app"
|
||||
```
|
||||
|
||||
### Task 2: Pure Trading Calculations
|
||||
|
||||
**Files:**
|
||||
- Create: `src/grid_trading/domain/models.py`
|
||||
- Create: `src/grid_trading/domain/calculations.py`
|
||||
- Test: `tests/test_calculations.py`
|
||||
|
||||
- [ ] **Step 1: Write failing calculation tests**
|
||||
|
||||
Cover these exact scenarios:
|
||||
|
||||
```python
|
||||
def test_buy_sell_grid_profit_and_breakeven():
|
||||
# Buy 100 grid shares at 10 with 1 fee, sell 100 at 11 with 1 fee,
|
||||
# then buy 100 base shares at 9 with 1 fee. Grid profit is 98.
|
||||
# Position cost is 901, position breakeven is 8.03, account breakeven is 9.01.
|
||||
```
|
||||
|
||||
```python
|
||||
def test_t_plus_one_available_quantity_excludes_today_buys():
|
||||
# Buy 200 yesterday and 100 today. As of today, total is 300 and available is 200.
|
||||
```
|
||||
|
||||
```python
|
||||
def test_sell_more_than_group_position_raises():
|
||||
# Buy 100 grid shares, attempt to sell 200 grid shares, expect CalculationError.
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `pytest tests/test_calculations.py -v`
|
||||
Expected: FAIL because `grid_trading.domain` does not exist.
|
||||
|
||||
- [ ] **Step 3: Implement dataclasses and pure functions**
|
||||
|
||||
Define `TradeSide`, `TradeGroup`, `Trade`, `Instrument`, `FeeRules`, `PositionSummary`, `AccountSummary`, `CalculationError`, `estimate_fees`, `calculate_positions`, and `calculate_account_summary`.
|
||||
|
||||
- [ ] **Step 4: Run tests to verify they pass**
|
||||
|
||||
Run: `pytest tests/test_calculations.py -v`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/grid_trading/domain tests/test_calculations.py
|
||||
git commit -m "feat: add grid trading calculations"
|
||||
```
|
||||
|
||||
### Task 3: SQLite Persistence
|
||||
|
||||
**Files:**
|
||||
- Create: `src/grid_trading/storage/database.py`
|
||||
- Create: `src/grid_trading/storage/repositories.py`
|
||||
- Test: `tests/test_repositories.py`
|
||||
|
||||
- [ ] **Step 1: Write failing repository tests**
|
||||
|
||||
Cover:
|
||||
|
||||
```python
|
||||
def test_database_round_trips_account_instrument_and_trade(tmp_path):
|
||||
# Initialize SQLite, create account, default template, instrument, trade.
|
||||
# Reopen the database and assert the same rows are loaded.
|
||||
```
|
||||
|
||||
```python
|
||||
def test_trade_update_and_delete_are_persistent(tmp_path):
|
||||
# Insert a trade, update price/quantity, delete it, assert repository reflects changes.
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `pytest tests/test_repositories.py -v`
|
||||
Expected: FAIL because storage modules do not exist.
|
||||
|
||||
- [ ] **Step 3: Implement schema and repositories**
|
||||
|
||||
Create tables `accounts`, `instruments`, `strategy_templates`, `instrument_strategy_overrides`, `trades`, `cash_ledger`, and `app_settings`. Store Decimal values as text and dates as ISO strings.
|
||||
|
||||
- [ ] **Step 4: Run tests to verify they pass**
|
||||
|
||||
Run: `pytest tests/test_repositories.py -v`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/grid_trading/storage tests/test_repositories.py
|
||||
git commit -m "feat: add sqlite persistence"
|
||||
```
|
||||
|
||||
### Task 4: Trading Service Workflow
|
||||
|
||||
**Files:**
|
||||
- Create: `src/grid_trading/services/trading_service.py`
|
||||
- Test: `tests/test_services.py`
|
||||
|
||||
- [ ] **Step 1: Write failing service tests**
|
||||
|
||||
Cover:
|
||||
|
||||
```python
|
||||
def test_service_creates_default_account_and_computes_summary(tmp_path):
|
||||
# Service starts with no database rows, creates a default account/template,
|
||||
# adds an instrument and trades, then returns a non-empty account summary.
|
||||
```
|
||||
|
||||
```python
|
||||
def test_service_validates_lot_size_and_available_sell_quantity(tmp_path):
|
||||
# Quantity not multiple of 100 is rejected.
|
||||
# Selling more than available prior-day quantity is rejected.
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `pytest tests/test_services.py -v`
|
||||
Expected: FAIL because `TradingService` does not exist.
|
||||
|
||||
- [ ] **Step 3: Implement service methods**
|
||||
|
||||
Implement `ensure_defaults`, `save_account`, `add_instrument`, `save_trade`, `update_trade`, `delete_trade`, `get_position_summaries`, `get_account_summary`, `estimate_trade_fees`, and strategy template helpers.
|
||||
|
||||
- [ ] **Step 4: Run tests to verify they pass**
|
||||
|
||||
Run: `pytest tests/test_services.py -v`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/grid_trading/services tests/test_services.py
|
||||
git commit -m "feat: add trading service workflow"
|
||||
```
|
||||
|
||||
### Task 5: PySide6 GUI
|
||||
|
||||
**Files:**
|
||||
- Create: `src/grid_trading/ui/formatters.py`
|
||||
- Create: `src/grid_trading/ui/dialogs.py`
|
||||
- Create: `src/grid_trading/ui/main_window.py`
|
||||
- Modify: `src/grid_trading/app.py`
|
||||
|
||||
- [ ] **Step 1: Build main window layout**
|
||||
|
||||
Create a `QMainWindow` with left navigation, top account summary cards, toolbar buttons, a holdings `QTableWidget`, and a bottom detail/trade table.
|
||||
|
||||
- [ ] **Step 2: Add dialogs**
|
||||
|
||||
Create dialogs for account settings, instrument editing, trade add/edit, and strategy template editing. Dialogs call `TradingService` and refresh the main table after saves.
|
||||
|
||||
- [ ] **Step 3: Wire validation errors**
|
||||
|
||||
Catch `ValueError` and `CalculationError` from service calls, then show a `QMessageBox.warning` without losing the dialog input.
|
||||
|
||||
- [ ] **Step 4: Run GUI smoke command**
|
||||
|
||||
Run: `python -m grid_trading.app --help`
|
||||
Expected: command prints help without importing errors.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/grid_trading/ui src/grid_trading/app.py
|
||||
git commit -m "feat: add pySide6 holdings gui"
|
||||
```
|
||||
|
||||
### Task 6: Verification And Polish
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
- Modify: `.gitignore`
|
||||
|
||||
- [ ] **Step 1: Run full tests**
|
||||
|
||||
Run: `pytest -v`
|
||||
Expected: all tests pass.
|
||||
|
||||
- [ ] **Step 2: Run import and CLI smoke checks**
|
||||
|
||||
Run: `python -m grid_trading.app --help`
|
||||
Expected: help output is printed.
|
||||
|
||||
- [ ] **Step 3: Update README**
|
||||
|
||||
Document `python -m venv .venv`, dependency install, `pytest`, and `python -m grid_trading.app`.
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add README.md .gitignore
|
||||
git commit -m "docs: add phase one usage guide"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review
|
||||
|
||||
- Spec coverage: first phase requirements are covered by Tasks 1-5: account setup, instruments, strategy template storage, manual trades, holdings table, SQLite persistence, cost/profit/breakeven calculations, T+1 validation, and a GUI shell.
|
||||
- Out of scope items remain excluded: no broker login, no automated orders, no realtime行情, no charts, and no cloud sync.
|
||||
- Placeholder scan: no unresolved placeholders or unspecified implementation steps remain.
|
||||
- Type consistency: model names, service names, and repository names are consistent across tasks.
|
||||
Reference in New Issue
Block a user