# 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.