## MODIFIED Requirements

### Requirement: CLI validates config values on startup

The CLI SHALL validate that all required config fields are present and have valid values before constructing any modules. Specifically:
- `market.coin` MUST be a non-empty string
- `strategy.start_px` MUST be positive
- `strategy.n_orders` MUST be a positive integer (total grid levels, not per-side)
- `strategy.order_sz` MUST be positive
- `allocation.allocated_token` MUST be positive
- `allocation.allocated_usdc` MUST be positive

Optional tuning parameters SHALL use defaults matching WsState's constructor defaults if omitted.

#### Scenario: Invalid start_px
- **WHEN** config contains `start_px = 0` or a negative value
- **THEN** the process exits with an error message identifying the invalid field

#### Scenario: Missing required field
- **WHEN** a required field (e.g., `market.coin`) is absent from config
- **THEN** the process exits with an error message identifying the missing field

#### Scenario: Optional tuning params omitted
- **WHEN** the `[tuning]` section is omitted or partially filled
- **THEN** defaults are used: `interval_s=3.0`, `dead_zone_bps=5.0`, `price_tolerance_bps=1.0`, `size_tolerance_pct=1.0`, `reconcile_every=20`, `min_notional=0.0`

### Requirement: CLI constructs SDK objects and WsState

The CLI SHALL construct Hyperliquid SDK `Info` and `Exchange` objects using the wallet/private key and the appropriate base URL (testnet or mainnet based on `market.testnet`). It SHALL then construct a `WsState` instance with config params (including `start_px`) and SDK objects, and run it via `asyncio.run(ws_state.run())`.

The `start_px` config value SHALL be passed to `WsState` so it can construct the `PricingGrid` at startup.

#### Scenario: Testnet mode
- **WHEN** config contains `testnet = true`
- **THEN** SDK objects are constructed with the testnet base URL

#### Scenario: Mainnet mode (default)
- **WHEN** config omits `testnet` or sets it to `false`
- **THEN** SDK objects are constructed with the mainnet (default) base URL

#### Scenario: start_px passed to WsState
- **WHEN** config contains `strategy.start_px = 0.020777`
- **THEN** WsState receives `start_px=0.020777` and uses it to construct the PricingGrid
